mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-05-13 05:12:55 -07:00
refactor(sdk): introduce session-based architecture (#19180)
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
This commit is contained in:
@@ -38,6 +38,7 @@ export default tseslint.config(
|
|||||||
'dist/**',
|
'dist/**',
|
||||||
'evals/**',
|
'evals/**',
|
||||||
'packages/test-utils/**',
|
'packages/test-utils/**',
|
||||||
|
'.gemini/skills/**',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
eslint.configs.recommended,
|
eslint.configs.recommended,
|
||||||
|
|||||||
@@ -180,6 +180,86 @@ describe('Storage – additional helpers', () => {
|
|||||||
expect(storageWithSession.getProjectTempPlansDir()).toBe(expected);
|
expect(storageWithSession.getProjectTempPlansDir()).toBe(expected);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('Session and JSON Loading', () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
await storage.initialize();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('listProjectChatFiles returns sorted sessions from chats directory', async () => {
|
||||||
|
const readdirSpy = vi
|
||||||
|
.spyOn(fs.promises, 'readdir')
|
||||||
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
|
.mockResolvedValue([
|
||||||
|
'session-1.json',
|
||||||
|
'session-2.json',
|
||||||
|
'not-a-session.txt',
|
||||||
|
] as any);
|
||||||
|
|
||||||
|
const statSpy = vi
|
||||||
|
.spyOn(fs.promises, 'stat')
|
||||||
|
.mockImplementation(async (p: any) => {
|
||||||
|
if (p.toString().endsWith('session-1.json')) {
|
||||||
|
return {
|
||||||
|
mtime: new Date('2026-02-01'),
|
||||||
|
mtimeMs: 1000,
|
||||||
|
} as any;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
mtime: new Date('2026-02-02'),
|
||||||
|
mtimeMs: 2000,
|
||||||
|
} as any;
|
||||||
|
});
|
||||||
|
/* eslint-enable @typescript-eslint/no-explicit-any */
|
||||||
|
|
||||||
|
const sessions = await storage.listProjectChatFiles();
|
||||||
|
|
||||||
|
expect(readdirSpy).toHaveBeenCalledWith(expect.stringContaining('chats'));
|
||||||
|
expect(sessions).toHaveLength(2);
|
||||||
|
// Sorted by mtime desc
|
||||||
|
expect(sessions[0].filePath).toBe(path.join('chats', 'session-2.json'));
|
||||||
|
expect(sessions[1].filePath).toBe(path.join('chats', 'session-1.json'));
|
||||||
|
expect(sessions[0].lastUpdated).toBe(
|
||||||
|
new Date('2026-02-02').toISOString(),
|
||||||
|
);
|
||||||
|
|
||||||
|
readdirSpy.mockRestore();
|
||||||
|
statSpy.mockRestore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('loadProjectTempFile loads and parses JSON from relative path', async () => {
|
||||||
|
const readFileSpy = vi
|
||||||
|
.spyOn(fs.promises, 'readFile')
|
||||||
|
.mockResolvedValue(JSON.stringify({ hello: 'world' }));
|
||||||
|
|
||||||
|
const result = await storage.loadProjectTempFile<{ hello: string }>(
|
||||||
|
'some/file.json',
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(readFileSpy).toHaveBeenCalledWith(
|
||||||
|
expect.stringContaining(path.join(PROJECT_SLUG, 'some/file.json')),
|
||||||
|
'utf8',
|
||||||
|
);
|
||||||
|
expect(result).toEqual({ hello: 'world' });
|
||||||
|
|
||||||
|
readFileSpy.mockRestore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('loadProjectTempFile returns null if file does not exist', async () => {
|
||||||
|
const error = new Error('File not found');
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
(error as any).code = 'ENOENT';
|
||||||
|
const readFileSpy = vi
|
||||||
|
.spyOn(fs.promises, 'readFile')
|
||||||
|
.mockRejectedValue(error);
|
||||||
|
|
||||||
|
const result = await storage.loadProjectTempFile('missing.json');
|
||||||
|
|
||||||
|
expect(result).toBeNull();
|
||||||
|
|
||||||
|
readFileSpy.mockRestore();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('getPlansDir', () => {
|
describe('getPlansDir', () => {
|
||||||
interface TestCase {
|
interface TestCase {
|
||||||
name: string;
|
name: string;
|
||||||
|
|||||||
@@ -295,6 +295,63 @@ export class Storage {
|
|||||||
return path.join(this.getProjectTempDir(), 'tasks');
|
return path.join(this.getProjectTempDir(), 'tasks');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async listProjectChatFiles(): Promise<
|
||||||
|
Array<{ filePath: string; lastUpdated: string }>
|
||||||
|
> {
|
||||||
|
const chatsDir = path.join(this.getProjectTempDir(), 'chats');
|
||||||
|
try {
|
||||||
|
const files = await fs.promises.readdir(chatsDir);
|
||||||
|
const jsonFiles = files.filter((f) => f.endsWith('.json'));
|
||||||
|
|
||||||
|
const sessions = await Promise.all(
|
||||||
|
jsonFiles.map(async (file) => {
|
||||||
|
const absolutePath = path.join(chatsDir, file);
|
||||||
|
const stats = await fs.promises.stat(absolutePath);
|
||||||
|
return {
|
||||||
|
filePath: path.join('chats', file),
|
||||||
|
lastUpdated: stats.mtime.toISOString(),
|
||||||
|
mtimeMs: stats.mtimeMs,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
return sessions
|
||||||
|
.sort((a, b) => b.mtimeMs - a.mtimeMs)
|
||||||
|
.map(({ filePath, lastUpdated }) => ({ filePath, lastUpdated }));
|
||||||
|
} catch (e) {
|
||||||
|
// If directory doesn't exist, return empty
|
||||||
|
if (
|
||||||
|
e instanceof Error &&
|
||||||
|
'code' in e &&
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||||
|
(e as NodeJS.ErrnoException).code === 'ENOENT'
|
||||||
|
) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async loadProjectTempFile<T>(filePath: string): Promise<T | null> {
|
||||||
|
const absolutePath = path.join(this.getProjectTempDir(), filePath);
|
||||||
|
try {
|
||||||
|
const content = await fs.promises.readFile(absolutePath, 'utf8');
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||||
|
return JSON.parse(content) as T;
|
||||||
|
} catch (e) {
|
||||||
|
// If file doesn't exist, return null
|
||||||
|
if (
|
||||||
|
e instanceof Error &&
|
||||||
|
'code' in e &&
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||||
|
(e as NodeJS.ErrnoException).code === 'ENOENT'
|
||||||
|
) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
getExtensionsDir(): string {
|
getExtensionsDir(): string {
|
||||||
return path.join(this.getGeminiDir(), 'extensions');
|
return path.join(this.getGeminiDir(), 'extensions');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -180,7 +180,7 @@ export { OAuthUtils } from './mcp/oauth-utils.js';
|
|||||||
|
|
||||||
// Export telemetry functions
|
// Export telemetry functions
|
||||||
export * from './telemetry/index.js';
|
export * from './telemetry/index.js';
|
||||||
export { sessionId } from './utils/session.js';
|
export { sessionId, createSessionId } from './utils/session.js';
|
||||||
export * from './utils/compatibility.js';
|
export * from './utils/compatibility.js';
|
||||||
export * from './utils/browser.js';
|
export * from './utils/browser.js';
|
||||||
export { Storage } from './config/storage.js';
|
export { Storage } from './config/storage.js';
|
||||||
|
|||||||
@@ -7,3 +7,7 @@
|
|||||||
import { randomUUID } from 'node:crypto';
|
import { randomUUID } from 'node:crypto';
|
||||||
|
|
||||||
export const sessionId = randomUUID();
|
export const sessionId = randomUUID();
|
||||||
|
|
||||||
|
export function createSessionId(): string {
|
||||||
|
return randomUUID();
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,7 +8,8 @@
|
|||||||
|
|
||||||
## `Simple Example`
|
## `Simple Example`
|
||||||
|
|
||||||
> **Status:** Implemented. `GeminiCliAgent` supports `cwd` and `sendStream`.
|
> **Status:** Implemented. `GeminiCliAgent` supports `session()` and
|
||||||
|
> `resumeSession()`.
|
||||||
|
|
||||||
Equivalent to `gemini -p "what does this project do?"`. Loads all workspace and
|
Equivalent to `gemini -p "what does this project do?"`. Loads all workspace and
|
||||||
user settings.
|
user settings.
|
||||||
@@ -20,10 +21,14 @@ const simpleAgent = new GeminiCliAgent({
|
|||||||
cwd: '/path/to/some/dir',
|
cwd: '/path/to/some/dir',
|
||||||
});
|
});
|
||||||
|
|
||||||
for await (const chunk of simpleAgent.sendStream(
|
// Create a new empty session
|
||||||
'what does this project do?',
|
const session = simpleAgent.session();
|
||||||
)) {
|
|
||||||
console.log(chunk); // equivalent to JSON streaming chunks (probably?) for now
|
// Resume a specific session by ID
|
||||||
|
// const session = await simpleAgent.resumeSession('some-session-id');
|
||||||
|
|
||||||
|
for await (const chunk of session.sendStream('what does this project do?')) {
|
||||||
|
console.log(chunk); // equivalent to JSON streaming chunks
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -268,8 +273,9 @@ export interface SessionContext {
|
|||||||
// helpers to access files and run shell commands while adhering to policies/validation
|
// helpers to access files and run shell commands while adhering to policies/validation
|
||||||
fs: AgentFilesystem;
|
fs: AgentFilesystem;
|
||||||
shell: AgentShell;
|
shell: AgentShell;
|
||||||
// the agent itself is passed as context
|
// the agent and session are passed as context
|
||||||
agent: GeminiCliAgent;
|
agent: GeminiCliAgent;
|
||||||
|
session: GeminiCliSession;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AgentFilesystem {
|
export interface AgentFilesystem {
|
||||||
|
|||||||
@@ -30,8 +30,12 @@ describe('GeminiCliAgent Integration', () => {
|
|||||||
fakeResponses: RECORD_MODE ? undefined : goldenFile,
|
fakeResponses: RECORD_MODE ? undefined : goldenFile,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const session = agent.session();
|
||||||
|
expect(session.id).toMatch(
|
||||||
|
/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,
|
||||||
|
);
|
||||||
const events = [];
|
const events = [];
|
||||||
const stream = agent.sendStream('Say hello.');
|
const stream = session.sendStream('Say hello.');
|
||||||
|
|
||||||
for await (const event of stream) {
|
for await (const event of stream) {
|
||||||
events.push(event);
|
events.push(event);
|
||||||
@@ -60,9 +64,11 @@ describe('GeminiCliAgent Integration', () => {
|
|||||||
fakeResponses: RECORD_MODE ? undefined : goldenFile,
|
fakeResponses: RECORD_MODE ? undefined : goldenFile,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const session = agent.session();
|
||||||
|
|
||||||
// First turn
|
// First turn
|
||||||
const stream1 = agent.sendStream('What is the secret number?');
|
|
||||||
const events1 = [];
|
const events1 = [];
|
||||||
|
const stream1 = session.sendStream('What is the secret number?');
|
||||||
for await (const event of stream1) {
|
for await (const event of stream1) {
|
||||||
events1.push(event);
|
events1.push(event);
|
||||||
}
|
}
|
||||||
@@ -72,11 +78,10 @@ describe('GeminiCliAgent Integration', () => {
|
|||||||
.join('');
|
.join('');
|
||||||
|
|
||||||
expect(responseText1).toContain('1');
|
expect(responseText1).toContain('1');
|
||||||
expect(callCount).toBe(1);
|
|
||||||
|
|
||||||
// Second turn
|
// Second turn
|
||||||
const stream2 = agent.sendStream('What is the secret number now?');
|
|
||||||
const events2 = [];
|
const events2 = [];
|
||||||
|
const stream2 = session.sendStream('What is the secret number now?');
|
||||||
for await (const event of stream2) {
|
for await (const event of stream2) {
|
||||||
events2.push(event);
|
events2.push(event);
|
||||||
}
|
}
|
||||||
@@ -85,57 +90,60 @@ describe('GeminiCliAgent Integration', () => {
|
|||||||
.map((e) => (typeof e.value === 'string' ? e.value : ''))
|
.map((e) => (typeof e.value === 'string' ? e.value : ''))
|
||||||
.join('');
|
.join('');
|
||||||
|
|
||||||
// Should still be 1 because instructions are only loaded once per session
|
expect(responseText2).toContain('2');
|
||||||
expect(responseText2).toContain('1');
|
|
||||||
expect(callCount).toBe(1);
|
|
||||||
}, 30000);
|
}, 30000);
|
||||||
|
|
||||||
it('handles async dynamic instructions', async () => {
|
it('resumes a session', async () => {
|
||||||
const goldenFile = getGoldenPath('agent-async-instructions');
|
const goldenFile = getGoldenPath('agent-resume-session');
|
||||||
|
|
||||||
let callCount = 0;
|
// Create initial session
|
||||||
const agent = new GeminiCliAgent({
|
const agent = new GeminiCliAgent({
|
||||||
instructions: async (_ctx) => {
|
instructions: 'You are a memory test. Remember the word "BANANA".',
|
||||||
await new Promise((resolve) => setTimeout(resolve, 10)); // Simulate async work
|
|
||||||
callCount++;
|
|
||||||
return `You are a helpful assistant. The secret number is ${callCount}. Always mention the secret number when asked.`;
|
|
||||||
},
|
|
||||||
model: 'gemini-2.0-flash',
|
model: 'gemini-2.0-flash',
|
||||||
recordResponses: RECORD_MODE ? goldenFile : undefined,
|
recordResponses: RECORD_MODE ? goldenFile : undefined,
|
||||||
fakeResponses: RECORD_MODE ? undefined : goldenFile,
|
fakeResponses: RECORD_MODE ? undefined : goldenFile,
|
||||||
});
|
});
|
||||||
|
|
||||||
// First turn
|
const session1 = agent.session({ sessionId: 'resume-test-fixed-id' });
|
||||||
const stream1 = agent.sendStream('What is the secret number?');
|
const sessionId = session1.id;
|
||||||
const events1 = [];
|
const stream1 = session1.sendStream('What is the word?');
|
||||||
for await (const event of stream1) {
|
for await (const _ of stream1) {
|
||||||
events1.push(event);
|
// consume stream
|
||||||
}
|
}
|
||||||
const responseText1 = events1
|
|
||||||
.filter((e) => e.type === 'content')
|
|
||||||
.map((e) => (typeof e.value === 'string' ? e.value : ''))
|
|
||||||
.join('');
|
|
||||||
|
|
||||||
expect(responseText1).toContain('1');
|
// Resume session
|
||||||
expect(callCount).toBe(1);
|
// Allow some time for async writes if any
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, 500));
|
||||||
|
|
||||||
|
const session2 = await agent.resumeSession(sessionId);
|
||||||
|
expect(session2.id).toBe(sessionId);
|
||||||
|
|
||||||
// Second turn
|
|
||||||
const stream2 = agent.sendStream('What is the secret number now?');
|
|
||||||
const events2 = [];
|
const events2 = [];
|
||||||
|
const stream2 = session2.sendStream('What is the word again?');
|
||||||
for await (const event of stream2) {
|
for await (const event of stream2) {
|
||||||
events2.push(event);
|
events2.push(event);
|
||||||
}
|
}
|
||||||
const responseText2 = events2
|
|
||||||
|
const responseText = events2
|
||||||
.filter((e) => e.type === 'content')
|
.filter((e) => e.type === 'content')
|
||||||
.map((e) => (typeof e.value === 'string' ? e.value : ''))
|
.map((e) => (typeof e.value === 'string' ? e.value : ''))
|
||||||
.join('');
|
.join('');
|
||||||
|
|
||||||
// Should still be 1 because instructions are only loaded once per session
|
expect(responseText).toContain('BANANA');
|
||||||
expect(responseText2).toContain('1');
|
|
||||||
expect(callCount).toBe(1);
|
|
||||||
}, 30000);
|
}, 30000);
|
||||||
|
|
||||||
it('throws when dynamic instructions fail', async () => {
|
it('throws on invalid instructions', () => {
|
||||||
|
// Missing instructions should be fine
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
expect(() => new GeminiCliAgent({} as any).session()).not.toThrow();
|
||||||
|
|
||||||
|
expect(() =>
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
new GeminiCliAgent({ instructions: 123 as any }).session(),
|
||||||
|
).toThrow('Instructions must be a string or a function.');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('propagates errors from dynamic instructions', async () => {
|
||||||
const agent = new GeminiCliAgent({
|
const agent = new GeminiCliAgent({
|
||||||
instructions: () => {
|
instructions: () => {
|
||||||
throw new Error('Dynamic instruction failure');
|
throw new Error('Dynamic instruction failure');
|
||||||
@@ -143,7 +151,8 @@ describe('GeminiCliAgent Integration', () => {
|
|||||||
model: 'gemini-2.0-flash',
|
model: 'gemini-2.0-flash',
|
||||||
});
|
});
|
||||||
|
|
||||||
const stream = agent.sendStream('Say hello.');
|
const session = agent.session();
|
||||||
|
const stream = session.sendStream('Say hello.');
|
||||||
|
|
||||||
await expect(async () => {
|
await expect(async () => {
|
||||||
for await (const _event of stream) {
|
for await (const _event of stream) {
|
||||||
|
|||||||
+56
-220
@@ -4,245 +4,81 @@
|
|||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import * as path from 'node:path';
|
||||||
import {
|
import {
|
||||||
Config,
|
Storage,
|
||||||
type ConfigParameters,
|
createSessionId,
|
||||||
AuthType,
|
type ResumedSessionData,
|
||||||
PREVIEW_GEMINI_MODEL_AUTO,
|
type ConversationRecord,
|
||||||
GeminiEventType,
|
|
||||||
type ToolCallRequestInfo,
|
|
||||||
type ServerGeminiStreamEvent,
|
|
||||||
type GeminiClient,
|
|
||||||
type Content,
|
|
||||||
scheduleAgentTools,
|
|
||||||
getAuthTypeFromEnv,
|
|
||||||
type ToolRegistry,
|
|
||||||
loadSkillsFromDir,
|
|
||||||
ActivateSkillTool,
|
|
||||||
} from '@google/gemini-cli-core';
|
} from '@google/gemini-cli-core';
|
||||||
|
|
||||||
import { type Tool, SdkTool } from './tool.js';
|
import { GeminiCliSession } from './session.js';
|
||||||
import { SdkAgentFilesystem } from './fs.js';
|
import type { GeminiCliAgentOptions } from './types.js';
|
||||||
import { SdkAgentShell } from './shell.js';
|
|
||||||
import type { SessionContext } from './types.js';
|
|
||||||
import type { SkillReference } from './skills.js';
|
|
||||||
|
|
||||||
export type SystemInstructions =
|
|
||||||
| string
|
|
||||||
| ((context: SessionContext) => string | Promise<string>);
|
|
||||||
|
|
||||||
export interface GeminiCliAgentOptions {
|
|
||||||
instructions: SystemInstructions;
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
tools?: Array<Tool<any>>;
|
|
||||||
skills?: SkillReference[];
|
|
||||||
model?: string;
|
|
||||||
cwd?: string;
|
|
||||||
debug?: boolean;
|
|
||||||
recordResponses?: string;
|
|
||||||
fakeResponses?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class GeminiCliAgent {
|
export class GeminiCliAgent {
|
||||||
private readonly config: Config;
|
private options: GeminiCliAgentOptions;
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
private readonly tools: Array<Tool<any>>;
|
|
||||||
private readonly skillRefs: SkillReference[];
|
|
||||||
private readonly instructions: SystemInstructions;
|
|
||||||
private instructionsLoaded = false;
|
|
||||||
|
|
||||||
constructor(options: GeminiCliAgentOptions) {
|
constructor(options: GeminiCliAgentOptions) {
|
||||||
this.instructions = options.instructions;
|
this.options = options;
|
||||||
const cwd = options.cwd || process.cwd();
|
|
||||||
this.tools = options.tools || [];
|
|
||||||
this.skillRefs = options.skills || [];
|
|
||||||
|
|
||||||
const initialMemory =
|
|
||||||
typeof this.instructions === 'string' ? this.instructions : '';
|
|
||||||
|
|
||||||
const configParams: ConfigParameters = {
|
|
||||||
sessionId: `sdk-${Date.now()}`,
|
|
||||||
targetDir: cwd,
|
|
||||||
cwd,
|
|
||||||
debugMode: options.debug ?? false,
|
|
||||||
model: options.model || PREVIEW_GEMINI_MODEL_AUTO,
|
|
||||||
userMemory: initialMemory,
|
|
||||||
// Minimal config
|
|
||||||
enableHooks: false,
|
|
||||||
mcpEnabled: false,
|
|
||||||
extensionsEnabled: false,
|
|
||||||
recordResponses: options.recordResponses,
|
|
||||||
fakeResponses: options.fakeResponses,
|
|
||||||
skillsSupport: true,
|
|
||||||
adminSkillsEnabled: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
this.config = new Config(configParams);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async *sendStream(
|
session(options?: { sessionId?: string }): GeminiCliSession {
|
||||||
prompt: string,
|
const sessionId = options?.sessionId || createSessionId();
|
||||||
signal?: AbortSignal,
|
return new GeminiCliSession(this.options, sessionId, this);
|
||||||
): AsyncGenerator<ServerGeminiStreamEvent> {
|
}
|
||||||
// Lazy initialization of auth and client
|
|
||||||
if (!this.config.getContentGenerator()) {
|
|
||||||
const authType = getAuthTypeFromEnv() || AuthType.COMPUTE_ADC;
|
|
||||||
|
|
||||||
await this.config.refreshAuth(authType);
|
async resumeSession(sessionId: string): Promise<GeminiCliSession> {
|
||||||
await this.config.initialize();
|
const cwd = this.options.cwd || process.cwd();
|
||||||
|
const storage = new Storage(cwd);
|
||||||
|
await storage.initialize();
|
||||||
|
|
||||||
// Load additional skills from options
|
let conversation: ConversationRecord | undefined;
|
||||||
if (this.skillRefs.length > 0) {
|
let filePath: string | undefined;
|
||||||
const skillManager = this.config.getSkillManager();
|
|
||||||
|
|
||||||
const loadPromises = this.skillRefs.map(async (ref) => {
|
const sessions = await storage.listProjectChatFiles();
|
||||||
try {
|
|
||||||
if (ref.type === 'dir') {
|
|
||||||
return await loadSkillsFromDir(ref.path);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
// eslint-disable-next-line no-console
|
|
||||||
console.error(`Failed to load skills from ${ref.path}:`, e);
|
|
||||||
}
|
|
||||||
return [];
|
|
||||||
});
|
|
||||||
|
|
||||||
const loadedSkills = (await Promise.all(loadPromises)).flat();
|
if (sessions.length === 0) {
|
||||||
|
throw new Error(
|
||||||
if (loadedSkills.length > 0) {
|
`No sessions found in ${path.join(storage.getProjectTempDir(), 'chats')}`,
|
||||||
skillManager.addSkills(loadedSkills);
|
);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Re-register ActivateSkillTool if we have skills (either built-in/workspace or manually loaded)
|
|
||||||
// This is required because ActivateSkillTool captures the set of available skills at construction time.
|
|
||||||
const skillManager = this.config.getSkillManager();
|
|
||||||
if (skillManager.getSkills().length > 0) {
|
|
||||||
const registry = this.config.getToolRegistry();
|
|
||||||
const toolName = ActivateSkillTool.Name;
|
|
||||||
// Config.initialize already registers it, but we might have added more skills.
|
|
||||||
// Re-registering updates the schema with new skills.
|
|
||||||
if (registry.getTool(toolName)) {
|
|
||||||
registry.unregisterTool(toolName);
|
|
||||||
}
|
|
||||||
registry.registerTool(
|
|
||||||
new ActivateSkillTool(this.config, this.config.getMessageBus()),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Register tools now that registry exists
|
|
||||||
const registry = this.config.getToolRegistry();
|
|
||||||
const messageBus = this.config.getMessageBus();
|
|
||||||
|
|
||||||
for (const toolDef of this.tools) {
|
|
||||||
const sdkTool = new SdkTool(toolDef, messageBus, this);
|
|
||||||
registry.registerTool(sdkTool);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const client = this.config.getGeminiClient();
|
const truncatedId = sessionId.slice(0, 8);
|
||||||
const abortSignal = signal ?? new AbortController().signal;
|
// Optimization: filenames include first 8 chars of sessionId.
|
||||||
const sessionId = this.config.getSessionId();
|
// Filter sessions that might match.
|
||||||
|
const candidates = sessions.filter((s) => s.filePath.includes(truncatedId));
|
||||||
|
|
||||||
const fs = new SdkAgentFilesystem(this.config);
|
// If optimization fails (e.g. old files), check all?
|
||||||
const shell = new SdkAgentShell(this.config);
|
// Assuming filenames always follow convention if created by this tool.
|
||||||
|
// But we can fallback to checking all if needed, but let's stick to candidates first.
|
||||||
|
// If candidates is empty, maybe fallback to all.
|
||||||
|
const filesToCheck = candidates.length > 0 ? candidates : sessions;
|
||||||
|
|
||||||
let request: Parameters<GeminiClient['sendMessageStream']>[0] = [
|
for (const sessionFile of filesToCheck) {
|
||||||
{ text: prompt },
|
const loaded = await storage.loadProjectTempFile<ConversationRecord>(
|
||||||
];
|
sessionFile.filePath,
|
||||||
|
);
|
||||||
if (!this.instructionsLoaded && typeof this.instructions === 'function') {
|
if (loaded && loaded.sessionId === sessionId) {
|
||||||
const context: SessionContext = {
|
conversation = loaded;
|
||||||
sessionId,
|
filePath = path.join(storage.getProjectTempDir(), sessionFile.filePath);
|
||||||
transcript: client.getHistory(),
|
|
||||||
cwd: this.config.getWorkingDir(),
|
|
||||||
timestamp: new Date().toISOString(),
|
|
||||||
fs,
|
|
||||||
shell,
|
|
||||||
agent: this,
|
|
||||||
};
|
|
||||||
try {
|
|
||||||
const newInstructions = await this.instructions(context);
|
|
||||||
this.config.setUserMemory(newInstructions);
|
|
||||||
client.updateSystemInstruction();
|
|
||||||
this.instructionsLoaded = true;
|
|
||||||
} catch (e) {
|
|
||||||
const error =
|
|
||||||
e instanceof Error
|
|
||||||
? e
|
|
||||||
: new Error(`Error resolving dynamic instructions: ${String(e)}`);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
// sendMessageStream returns AsyncGenerator<ServerGeminiStreamEvent, Turn>
|
|
||||||
const stream = client.sendMessageStream(request, abortSignal, sessionId);
|
|
||||||
|
|
||||||
const toolCallsToSchedule: ToolCallRequestInfo[] = [];
|
|
||||||
|
|
||||||
for await (const event of stream) {
|
|
||||||
yield event;
|
|
||||||
if (event.type === GeminiEventType.ToolCallRequest) {
|
|
||||||
const toolCall = event.value;
|
|
||||||
let args = toolCall.args;
|
|
||||||
if (typeof args === 'string') {
|
|
||||||
args = JSON.parse(args);
|
|
||||||
}
|
|
||||||
toolCallsToSchedule.push({
|
|
||||||
...toolCall,
|
|
||||||
args,
|
|
||||||
isClientInitiated: false,
|
|
||||||
prompt_id: sessionId,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (toolCallsToSchedule.length === 0) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare SessionContext
|
|
||||||
const transcript: Content[] = client.getHistory();
|
|
||||||
const context: SessionContext = {
|
|
||||||
sessionId,
|
|
||||||
transcript,
|
|
||||||
cwd: this.config.getWorkingDir(),
|
|
||||||
timestamp: new Date().toISOString(),
|
|
||||||
fs,
|
|
||||||
shell,
|
|
||||||
agent: this,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Create a scoped registry for this turn to bind context safely
|
|
||||||
const originalRegistry = this.config.getToolRegistry();
|
|
||||||
const scopedRegistry: ToolRegistry = Object.create(originalRegistry);
|
|
||||||
scopedRegistry.getTool = (name: string) => {
|
|
||||||
const tool = originalRegistry.getTool(name);
|
|
||||||
if (tool instanceof SdkTool) {
|
|
||||||
return tool.bindContext(context);
|
|
||||||
}
|
|
||||||
return tool;
|
|
||||||
};
|
|
||||||
|
|
||||||
const completedCalls = await scheduleAgentTools(
|
|
||||||
this.config,
|
|
||||||
toolCallsToSchedule,
|
|
||||||
{
|
|
||||||
schedulerId: sessionId,
|
|
||||||
toolRegistry: scopedRegistry,
|
|
||||||
signal: abortSignal,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
const functionResponses = completedCalls.flatMap(
|
|
||||||
(call) => call.response.responseParts,
|
|
||||||
);
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
|
||||||
request = functionResponses as unknown as Parameters<
|
|
||||||
GeminiClient['sendMessageStream']
|
|
||||||
>[0];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!conversation || !filePath) {
|
||||||
|
throw new Error(`Session with ID ${sessionId} not found`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const resumedData: ResumedSessionData = {
|
||||||
|
conversation,
|
||||||
|
filePath,
|
||||||
|
};
|
||||||
|
|
||||||
|
return new GeminiCliSession(
|
||||||
|
this.options,
|
||||||
|
conversation.sessionId,
|
||||||
|
this,
|
||||||
|
resumedData,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
export * from './agent.js';
|
export * from './agent.js';
|
||||||
|
export * from './session.js';
|
||||||
export * from './tool.js';
|
export * from './tool.js';
|
||||||
export * from './skills.js';
|
export * from './skills.js';
|
||||||
export * from './types.js';
|
export * from './types.js';
|
||||||
|
|||||||
@@ -0,0 +1,270 @@
|
|||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright 2026 Google LLC
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {
|
||||||
|
Config,
|
||||||
|
type ConfigParameters,
|
||||||
|
AuthType,
|
||||||
|
PREVIEW_GEMINI_MODEL_AUTO,
|
||||||
|
GeminiEventType,
|
||||||
|
type ToolCallRequestInfo,
|
||||||
|
type ServerGeminiStreamEvent,
|
||||||
|
type GeminiClient,
|
||||||
|
type Content,
|
||||||
|
scheduleAgentTools,
|
||||||
|
getAuthTypeFromEnv,
|
||||||
|
type ToolRegistry,
|
||||||
|
loadSkillsFromDir,
|
||||||
|
ActivateSkillTool,
|
||||||
|
type ResumedSessionData,
|
||||||
|
PolicyDecision,
|
||||||
|
} from '@google/gemini-cli-core';
|
||||||
|
|
||||||
|
import { type Tool, SdkTool } from './tool.js';
|
||||||
|
import { SdkAgentFilesystem } from './fs.js';
|
||||||
|
import { SdkAgentShell } from './shell.js';
|
||||||
|
import type {
|
||||||
|
SessionContext,
|
||||||
|
GeminiCliAgentOptions,
|
||||||
|
SystemInstructions,
|
||||||
|
} from './types.js';
|
||||||
|
import type { SkillReference } from './skills.js';
|
||||||
|
import type { GeminiCliAgent } from './agent.js';
|
||||||
|
|
||||||
|
export class GeminiCliSession {
|
||||||
|
private readonly config: Config;
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
private readonly tools: Array<Tool<any>>;
|
||||||
|
private readonly skillRefs: SkillReference[];
|
||||||
|
private readonly instructions: SystemInstructions | undefined;
|
||||||
|
private client: GeminiClient | undefined;
|
||||||
|
private initialized = false;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
options: GeminiCliAgentOptions,
|
||||||
|
private readonly sessionId: string,
|
||||||
|
private readonly agent: GeminiCliAgent,
|
||||||
|
private readonly resumedData?: ResumedSessionData,
|
||||||
|
) {
|
||||||
|
this.instructions = options.instructions;
|
||||||
|
const cwd = options.cwd || process.cwd();
|
||||||
|
this.tools = options.tools || [];
|
||||||
|
this.skillRefs = options.skills || [];
|
||||||
|
|
||||||
|
let initialMemory = '';
|
||||||
|
if (typeof this.instructions === 'string') {
|
||||||
|
initialMemory = this.instructions;
|
||||||
|
} else if (this.instructions && typeof this.instructions !== 'function') {
|
||||||
|
throw new Error('Instructions must be a string or a function.');
|
||||||
|
}
|
||||||
|
|
||||||
|
const configParams: ConfigParameters = {
|
||||||
|
sessionId: this.sessionId,
|
||||||
|
targetDir: cwd,
|
||||||
|
cwd,
|
||||||
|
debugMode: options.debug ?? false,
|
||||||
|
model: options.model || PREVIEW_GEMINI_MODEL_AUTO,
|
||||||
|
userMemory: initialMemory,
|
||||||
|
// Minimal config
|
||||||
|
enableHooks: false,
|
||||||
|
mcpEnabled: false,
|
||||||
|
extensionsEnabled: false,
|
||||||
|
recordResponses: options.recordResponses,
|
||||||
|
fakeResponses: options.fakeResponses,
|
||||||
|
skillsSupport: true,
|
||||||
|
adminSkillsEnabled: true,
|
||||||
|
policyEngineConfig: {
|
||||||
|
// TODO: Revisit this default when we have a mechanism for wiring up approvals
|
||||||
|
defaultDecision: PolicyDecision.ALLOW,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
this.config = new Config(configParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
get id(): string {
|
||||||
|
return this.sessionId;
|
||||||
|
}
|
||||||
|
|
||||||
|
async initialize(): Promise<void> {
|
||||||
|
if (this.initialized) return;
|
||||||
|
|
||||||
|
const authType = getAuthTypeFromEnv() || AuthType.COMPUTE_ADC;
|
||||||
|
|
||||||
|
await this.config.refreshAuth(authType);
|
||||||
|
await this.config.initialize();
|
||||||
|
|
||||||
|
// Load additional skills from options
|
||||||
|
if (this.skillRefs.length > 0) {
|
||||||
|
const skillManager = this.config.getSkillManager();
|
||||||
|
|
||||||
|
const loadPromises = this.skillRefs.map(async (ref) => {
|
||||||
|
try {
|
||||||
|
if (ref.type === 'dir') {
|
||||||
|
return await loadSkillsFromDir(ref.path);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
// TODO: refactor this to use a proper logger interface
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.error(`Failed to load skills from ${ref.path}:`, e);
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
});
|
||||||
|
|
||||||
|
const loadedSkills = (await Promise.all(loadPromises)).flat();
|
||||||
|
|
||||||
|
if (loadedSkills.length > 0) {
|
||||||
|
skillManager.addSkills(loadedSkills);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Re-register ActivateSkillTool if we have skills
|
||||||
|
const skillManager = this.config.getSkillManager();
|
||||||
|
if (skillManager.getSkills().length > 0) {
|
||||||
|
const registry = this.config.getToolRegistry();
|
||||||
|
const toolName = ActivateSkillTool.Name;
|
||||||
|
if (registry.getTool(toolName)) {
|
||||||
|
registry.unregisterTool(toolName);
|
||||||
|
}
|
||||||
|
registry.registerTool(
|
||||||
|
new ActivateSkillTool(this.config, this.config.getMessageBus()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register tools
|
||||||
|
const registry = this.config.getToolRegistry();
|
||||||
|
const messageBus = this.config.getMessageBus();
|
||||||
|
|
||||||
|
for (const toolDef of this.tools) {
|
||||||
|
const sdkTool = new SdkTool(toolDef, messageBus, this.agent, undefined);
|
||||||
|
registry.registerTool(sdkTool);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.client = this.config.getGeminiClient();
|
||||||
|
|
||||||
|
if (this.resumedData) {
|
||||||
|
const history: Content[] = this.resumedData.conversation.messages.map(
|
||||||
|
(m) => {
|
||||||
|
const role = m.type === 'gemini' ? 'model' : 'user';
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
let parts: any[] = [];
|
||||||
|
if (Array.isArray(m.content)) {
|
||||||
|
parts = m.content;
|
||||||
|
} else if (m.content) {
|
||||||
|
parts = [{ text: String(m.content) }];
|
||||||
|
}
|
||||||
|
return { role, parts };
|
||||||
|
},
|
||||||
|
);
|
||||||
|
await this.client.resumeChat(history, this.resumedData);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
async *sendStream(
|
||||||
|
prompt: string,
|
||||||
|
signal?: AbortSignal,
|
||||||
|
): AsyncGenerator<ServerGeminiStreamEvent> {
|
||||||
|
if (!this.initialized || !this.client) {
|
||||||
|
await this.initialize();
|
||||||
|
}
|
||||||
|
const client = this.client!;
|
||||||
|
const abortSignal = signal ?? new AbortController().signal;
|
||||||
|
const sessionId = this.config.getSessionId();
|
||||||
|
|
||||||
|
const fs = new SdkAgentFilesystem(this.config);
|
||||||
|
const shell = new SdkAgentShell(this.config);
|
||||||
|
|
||||||
|
let request: Parameters<GeminiClient['sendMessageStream']>[0] = [
|
||||||
|
{ text: prompt },
|
||||||
|
];
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
if (typeof this.instructions === 'function') {
|
||||||
|
const context: SessionContext = {
|
||||||
|
sessionId,
|
||||||
|
transcript: client.getHistory(),
|
||||||
|
cwd: this.config.getWorkingDir(),
|
||||||
|
timestamp: new Date().toISOString(),
|
||||||
|
fs,
|
||||||
|
shell,
|
||||||
|
agent: this.agent,
|
||||||
|
session: this,
|
||||||
|
};
|
||||||
|
const newInstructions = await this.instructions(context);
|
||||||
|
this.config.setUserMemory(newInstructions);
|
||||||
|
client.updateSystemInstruction();
|
||||||
|
}
|
||||||
|
|
||||||
|
const stream = client.sendMessageStream(request, abortSignal, sessionId);
|
||||||
|
|
||||||
|
const toolCallsToSchedule: ToolCallRequestInfo[] = [];
|
||||||
|
|
||||||
|
for await (const event of stream) {
|
||||||
|
yield event;
|
||||||
|
if (event.type === GeminiEventType.ToolCallRequest) {
|
||||||
|
const toolCall = event.value;
|
||||||
|
let args = toolCall.args;
|
||||||
|
if (typeof args === 'string') {
|
||||||
|
args = JSON.parse(args);
|
||||||
|
}
|
||||||
|
toolCallsToSchedule.push({
|
||||||
|
...toolCall,
|
||||||
|
args,
|
||||||
|
isClientInitiated: false,
|
||||||
|
prompt_id: sessionId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toolCallsToSchedule.length === 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const transcript: Content[] = client.getHistory();
|
||||||
|
const context: SessionContext = {
|
||||||
|
sessionId,
|
||||||
|
transcript,
|
||||||
|
cwd: this.config.getWorkingDir(),
|
||||||
|
timestamp: new Date().toISOString(),
|
||||||
|
fs,
|
||||||
|
shell,
|
||||||
|
agent: this.agent,
|
||||||
|
session: this,
|
||||||
|
};
|
||||||
|
|
||||||
|
const originalRegistry = this.config.getToolRegistry();
|
||||||
|
const scopedRegistry: ToolRegistry = Object.create(originalRegistry);
|
||||||
|
scopedRegistry.getTool = (name: string) => {
|
||||||
|
const tool = originalRegistry.getTool(name);
|
||||||
|
if (tool instanceof SdkTool) {
|
||||||
|
return tool.bindContext(context);
|
||||||
|
}
|
||||||
|
return tool;
|
||||||
|
};
|
||||||
|
|
||||||
|
const completedCalls = await scheduleAgentTools(
|
||||||
|
this.config,
|
||||||
|
toolCallsToSchedule,
|
||||||
|
{
|
||||||
|
schedulerId: sessionId,
|
||||||
|
toolRegistry: scopedRegistry,
|
||||||
|
signal: abortSignal,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const functionResponses = completedCalls.flatMap(
|
||||||
|
(call) => call.response.responseParts,
|
||||||
|
);
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||||
|
request = functionResponses as unknown as Parameters<
|
||||||
|
GeminiClient['sendMessageStream']
|
||||||
|
>[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -39,8 +39,9 @@ describe('GeminiCliAgent Skills Integration', () => {
|
|||||||
|
|
||||||
// 1. Ask to activate the skill
|
// 1. Ask to activate the skill
|
||||||
const events = [];
|
const events = [];
|
||||||
|
const session = agent.session();
|
||||||
// The prompt explicitly asks to activate the skill by name
|
// The prompt explicitly asks to activate the skill by name
|
||||||
const stream = agent.sendStream(
|
const stream = session.sendStream(
|
||||||
'Activate the pirate-skill and then tell me a joke.',
|
'Activate the pirate-skill and then tell me a joke.',
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -72,7 +73,8 @@ describe('GeminiCliAgent Skills Integration', () => {
|
|||||||
|
|
||||||
// 1. Ask to activate the skill
|
// 1. Ask to activate the skill
|
||||||
const events = [];
|
const events = [];
|
||||||
const stream = agent.sendStream(
|
const session = agent.session();
|
||||||
|
const stream = session.sendStream(
|
||||||
'Activate the pirate-skill and confirm it is active.',
|
'Activate the pirate-skill and confirm it is active.',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,8 @@ describe('GeminiCliAgent Tool Integration', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const events = [];
|
const events = [];
|
||||||
const stream = agent.sendStream('What is 5 + 3?');
|
const session = agent.session();
|
||||||
|
const stream = session.sendStream('What is 5 + 3?');
|
||||||
|
|
||||||
for await (const event of stream) {
|
for await (const event of stream) {
|
||||||
events.push(event);
|
events.push(event);
|
||||||
@@ -85,9 +86,10 @@ describe('GeminiCliAgent Tool Integration', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const events = [];
|
const events = [];
|
||||||
|
const session = agent.session();
|
||||||
// Force the model to trigger the error first, then hopefully recover or at least acknowledge it.
|
// Force the model to trigger the error first, then hopefully recover or at least acknowledge it.
|
||||||
// The prompt is crafted to make the model try 'fail' first.
|
// The prompt is crafted to make the model try 'fail' first.
|
||||||
const stream = agent.sendStream(
|
const stream = session.sendStream(
|
||||||
'Call the tool with "fail". If it fails, tell me the error message.',
|
'Call the tool with "fail". If it fails, tell me the error message.',
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -128,7 +130,8 @@ describe('GeminiCliAgent Tool Integration', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const events = [];
|
const events = [];
|
||||||
const stream = agent.sendStream(
|
const session = agent.session();
|
||||||
|
const stream = session.sendStream(
|
||||||
'Check the system status and report any errors.',
|
'Check the system status and report any errors.',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,26 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import type { Content } from '@google/gemini-cli-core';
|
import type { Content } from '@google/gemini-cli-core';
|
||||||
|
import type { Tool } from './tool.js';
|
||||||
|
import type { SkillReference } from './skills.js';
|
||||||
import type { GeminiCliAgent } from './agent.js';
|
import type { GeminiCliAgent } from './agent.js';
|
||||||
|
import type { GeminiCliSession } from './session.js';
|
||||||
|
|
||||||
|
export type SystemInstructions =
|
||||||
|
| string
|
||||||
|
| ((context: SessionContext) => string | Promise<string>);
|
||||||
|
|
||||||
|
export interface GeminiCliAgentOptions {
|
||||||
|
instructions: SystemInstructions;
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
tools?: Array<Tool<any>>;
|
||||||
|
skills?: SkillReference[];
|
||||||
|
model?: string;
|
||||||
|
cwd?: string;
|
||||||
|
debug?: boolean;
|
||||||
|
recordResponses?: string;
|
||||||
|
fakeResponses?: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface AgentFilesystem {
|
export interface AgentFilesystem {
|
||||||
readFile(path: string): Promise<string | null>;
|
readFile(path: string): Promise<string | null>;
|
||||||
@@ -38,4 +57,5 @@ export interface SessionContext {
|
|||||||
fs: AgentFilesystem;
|
fs: AgentFilesystem;
|
||||||
shell: AgentShell;
|
shell: AgentShell;
|
||||||
agent: GeminiCliAgent;
|
agent: GeminiCliAgent;
|
||||||
|
session: GeminiCliSession;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,24 @@
|
|||||||
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"The secret number is"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":9831,"totalTokenCount":9831,"promptTokensDetails":[{"modality":"TEXT","tokenCount":9831}]}},{"candidates":[{"content":{"parts":[{"text":" 1.\n"}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7098,"candidatesTokenCount":8,"totalTokenCount":7106,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7098}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":8}]}}]}
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"The secret number is"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":9831,"totalTokenCount":9831,"promptTokensDetails":[{"modality":"TEXT","tokenCount":9831}]}},{"candidates":[{"content":{"parts":[{"text":" 1.\n"}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7098,"candidatesTokenCount":8,"totalTokenCount":7106,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7098}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":8}]}}]}
|
||||||
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"The secret number is"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":9848,"totalTokenCount":9848,"promptTokensDetails":[{"modality":"TEXT","tokenCount":9848}]}},{"candidates":[{"content":{"parts":[{"text":" 1.\n"}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7113,"candidatesTokenCount":8,"totalTokenCount":7121,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7113}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":8}]}}]}
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"The secret number is"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":9848,"totalTokenCount":9848,"promptTokensDetails":[{"modality":"TEXT","tokenCount":9848}]}},{"candidates":[{"content":{"parts":[{"text":" 2.\n"}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7113,"candidatesTokenCount":8,"totalTokenCount":7121,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7113}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":8}]}}]}
|
||||||
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"The secret number is"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":9853,"totalTokenCount":9853,"promptTokensDetails":[{"modality":"TEXT","tokenCount":9853}]}},{"candidates":[{"content":{"parts":[{"text":" 1.\n"}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7120,"candidatesTokenCount":8,"totalTokenCount":7128,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7120}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":8}]}}]}
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"The secret number is"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":9853,"totalTokenCount":9853,"promptTokensDetails":[{"modality":"TEXT","tokenCount":9853}]}},{"candidates":[{"content":{"parts":[{"text":" 1.\n"}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7120,"candidatesTokenCount":8,"totalTokenCount":7128,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7120}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":8}]}}]}
|
||||||
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"The secret number is"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":9870,"totalTokenCount":9870,"promptTokensDetails":[{"modality":"TEXT","tokenCount":9870}]}},{"candidates":[{"content":{"parts":[{"text":" 1.\n"}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7135,"candidatesTokenCount":8,"totalTokenCount":7143,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7135}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":8}]}}]}
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"The secret number is"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":9870,"totalTokenCount":9870,"promptTokensDetails":[{"modality":"TEXT","tokenCount":9870}]}},{"candidates":[{"content":{"parts":[{"text":" 2.\n"}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7135,"candidatesTokenCount":8,"totalTokenCount":7143,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7135}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":8}]}}]}
|
||||||
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"The secret number is"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":10028,"totalTokenCount":10028,"promptTokensDetails":[{"modality":"TEXT","tokenCount":10028}]}},{"candidates":[{"content":{"parts":[{"text":" 1."}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7193,"candidatesTokenCount":7,"totalTokenCount":7200,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7193}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":7}]}}]}
|
||||||
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"The secret number is"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":10044,"totalTokenCount":10044,"promptTokensDetails":[{"modality":"TEXT","tokenCount":10044}]}},{"candidates":[{"content":{"parts":[{"text":" 2."}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7207,"candidatesTokenCount":7,"totalTokenCount":7214,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7207}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":7}]}}]}
|
||||||
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"The secret number is"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":10039,"totalTokenCount":10039,"promptTokensDetails":[{"modality":"TEXT","tokenCount":10039}]}},{"candidates":[{"content":{"parts":[{"text":" 1."}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7204,"candidatesTokenCount":7,"totalTokenCount":7211,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7204}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":7}]}}]}
|
||||||
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"The secret number is"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":10055,"totalTokenCount":10055,"promptTokensDetails":[{"modality":"TEXT","tokenCount":10055}]}},{"candidates":[{"content":{"parts":[{"text":" 2."}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7218,"candidatesTokenCount":7,"totalTokenCount":7225,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7218}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":7}]}}]}
|
||||||
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"The"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":10039,"totalTokenCount":10039,"promptTokensDetails":[{"modality":"TEXT","tokenCount":10039}]}},{"candidates":[{"content":{"parts":[{"text":" secret number is 1."}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7204,"candidatesTokenCount":7,"totalTokenCount":7211,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7204}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":7}]}}]}
|
||||||
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"The secret number is"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":10055,"totalTokenCount":10055,"promptTokensDetails":[{"modality":"TEXT","tokenCount":10055}]}},{"candidates":[{"content":{"parts":[{"text":" 2."}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7218,"candidatesTokenCount":7,"totalTokenCount":7225,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7218}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":7}]}}]}
|
||||||
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"The"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":10039,"totalTokenCount":10039,"promptTokensDetails":[{"modality":"TEXT","tokenCount":10039}]}},{"candidates":[{"content":{"parts":[{"text":" secret number is 1."}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7204,"candidatesTokenCount":7,"totalTokenCount":7211,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7204}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":7}]}}]}
|
||||||
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"The secret number is"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":10055,"totalTokenCount":10055,"promptTokensDetails":[{"modality":"TEXT","tokenCount":10055}]}},{"candidates":[{"content":{"parts":[{"text":" 2.\n"}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7218,"candidatesTokenCount":8,"totalTokenCount":7226,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7218}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":8}]}}]}
|
||||||
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"The"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":10039,"totalTokenCount":10039,"promptTokensDetails":[{"modality":"TEXT","tokenCount":10039}]}},{"candidates":[{"content":{"parts":[{"text":" secret number is 1."}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7204,"candidatesTokenCount":7,"totalTokenCount":7211,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7204}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":7}]}}]}
|
||||||
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"The secret number is"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":10055,"totalTokenCount":10055,"promptTokensDetails":[{"modality":"TEXT","tokenCount":10055}]}},{"candidates":[{"content":{"parts":[{"text":" 2."}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7218,"candidatesTokenCount":7,"totalTokenCount":7225,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7218}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":7}]}}]}
|
||||||
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"The secret number is"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":10039,"totalTokenCount":10039,"promptTokensDetails":[{"modality":"TEXT","tokenCount":10039}]}},{"candidates":[{"content":{"parts":[{"text":" 1."}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7204,"candidatesTokenCount":7,"totalTokenCount":7211,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7204}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":7}]}}]}
|
||||||
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"The secret number is"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":10055,"totalTokenCount":10055,"promptTokensDetails":[{"modality":"TEXT","tokenCount":10055}]}},{"candidates":[{"content":{"parts":[{"text":" 2."}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7218,"candidatesTokenCount":7,"totalTokenCount":7225,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7218}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":7}]}}]}
|
||||||
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"The"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":10039,"totalTokenCount":10039,"promptTokensDetails":[{"modality":"TEXT","tokenCount":10039}]}},{"candidates":[{"content":{"parts":[{"text":" secret number is 1."}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7204,"candidatesTokenCount":7,"totalTokenCount":7211,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7204}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":7}]}}]}
|
||||||
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"The secret number is"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":10055,"totalTokenCount":10055,"promptTokensDetails":[{"modality":"TEXT","tokenCount":10055}]}},{"candidates":[{"content":{"parts":[{"text":" 2."}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7218,"candidatesTokenCount":7,"totalTokenCount":7225,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7218}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":7}]}}]}
|
||||||
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"The secret number is"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":10123,"totalTokenCount":10123,"promptTokensDetails":[{"modality":"TEXT","tokenCount":10123}]}},{"candidates":[{"content":{"parts":[{"text":" 1.\n"}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7188,"candidatesTokenCount":8,"totalTokenCount":7196,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7188}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":8}]}}]}
|
||||||
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"The secret number is"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":10140,"totalTokenCount":10140,"promptTokensDetails":[{"modality":"TEXT","tokenCount":10140}]}},{"candidates":[{"content":{"parts":[{"text":" 2.\n"}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7203,"candidatesTokenCount":8,"totalTokenCount":7211,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7203}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":8}]}}]}
|
||||||
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"The secret number is"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":10123,"totalTokenCount":10123,"promptTokensDetails":[{"modality":"TEXT","tokenCount":10123}]}},{"candidates":[{"content":{"parts":[{"text":" 1.\n"}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7188,"candidatesTokenCount":8,"totalTokenCount":7196,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7188}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":8}]}}]}
|
||||||
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"The secret number is"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":10140,"totalTokenCount":10140,"promptTokensDetails":[{"modality":"TEXT","tokenCount":10140}]}},{"candidates":[{"content":{"parts":[{"text":" 2.\n"}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7203,"candidatesTokenCount":8,"totalTokenCount":7211,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7203}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":8}]}}]}
|
||||||
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"The secret number is"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":10112,"totalTokenCount":10112,"promptTokensDetails":[{"modality":"TEXT","tokenCount":10112}]}},{"candidates":[{"content":{"parts":[{"text":" 1."}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7177,"candidatesTokenCount":7,"totalTokenCount":7184,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7177}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":7}]}}]}
|
||||||
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"The secret number is"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":10128,"totalTokenCount":10128,"promptTokensDetails":[{"modality":"TEXT","tokenCount":10128}]}},{"candidates":[{"content":{"parts":[{"text":" 2."}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7191,"candidatesTokenCount":7,"totalTokenCount":7198,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7191}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":7}]}}]}
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"BAN"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":10103,"totalTokenCount":10103,"promptTokensDetails":[{"modality":"TEXT","tokenCount":10103}]}},{"candidates":[{"content":{"parts":[{"text":"ANA\n"}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7168,"candidatesTokenCount":3,"totalTokenCount":7171,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7168}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":3}]}}]}
|
||||||
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"BANANA\n"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":10124,"totalTokenCount":10124,"promptTokensDetails":[{"modality":"TEXT","tokenCount":10124}]}},{"candidates":[{"content":{"parts":[{"text":""}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7187,"candidatesTokenCount":3,"totalTokenCount":7190,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7187}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":3}]}}]}
|
||||||
@@ -1 +1,4 @@
|
|||||||
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"Ah"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":9828,"totalTokenCount":9828,"promptTokensDetails":[{"modality":"TEXT","tokenCount":9828}]}},{"candidates":[{"content":{"parts":[{"text":"oy, matey! Ready to chart a course through the code?"}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7095,"candidatesTokenCount":15,"totalTokenCount":7110,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7095}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":15}]}}]}
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"Ah"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":9828,"totalTokenCount":9828,"promptTokensDetails":[{"modality":"TEXT","tokenCount":9828}]}},{"candidates":[{"content":{"parts":[{"text":"oy, matey! Ready to chart a course through the code?"}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7095,"candidatesTokenCount":15,"totalTokenCount":7110,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7095}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":15}]}}]}
|
||||||
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"Ah"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":10109,"totalTokenCount":10109,"promptTokensDetails":[{"modality":"TEXT","tokenCount":10109}]}},{"candidates":[{"content":{"parts":[{"text":"oy, matey! Ready to plunder the codebase, are ye?\n"}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7174,"candidatesTokenCount":16,"totalTokenCount":7190,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7174}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":16}]}}]}
|
||||||
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"Ah"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":10109,"totalTokenCount":10109,"promptTokensDetails":[{"modality":"TEXT","tokenCount":10109}]}},{"candidates":[{"content":{"parts":[{"text":"oy, matey! Ready to shiver some timbers and get to work?\n"}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7174,"candidatesTokenCount":18,"totalTokenCount":7192,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7174}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":18}]}}]}
|
||||||
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"Ah"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":10098,"totalTokenCount":10098,"promptTokensDetails":[{"modality":"TEXT","tokenCount":10098}]}},{"candidates":[{"content":{"parts":[{"text":"oy, matey! Ready to chart a course through these here files, are we?\n"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":10098,"totalTokenCount":10098,"promptTokensDetails":[{"modality":"TEXT","tokenCount":10098}]}},{"candidates":[{"content":{"parts":[{"text":""}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7163,"candidatesTokenCount":20,"totalTokenCount":7183,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7163}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":20}]}}]}
|
||||||
|
|||||||
@@ -1,2 +1,8 @@
|
|||||||
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"functionCall":{"name":"activate_skill","args":{"name":"pirate-skill"}}}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7160,"candidatesTokenCount":8,"totalTokenCount":7168,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7160}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":8}]}}]}
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"functionCall":{"name":"activate_skill","args":{"name":"pirate-skill"}}}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7160,"candidatesTokenCount":8,"totalTokenCount":7168,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7160}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":8}]}}]}
|
||||||
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"Arrr, why"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":10048,"totalTokenCount":10048,"promptTokensDetails":[{"modality":"TEXT","tokenCount":10048}]}},{"candidates":[{"content":{"parts":[{"text":" don't pirates play poker? Because they always have a hidden ace up their sleeves"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":10048,"totalTokenCount":10048,"promptTokensDetails":[{"modality":"TEXT","tokenCount":10048}]}},{"candidates":[{"content":{"parts":[{"text":"!\\n"}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7284,"candidatesTokenCount":23,"totalTokenCount":7307,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7284}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":23}]}}]}
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"Arrr, why"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":10048,"totalTokenCount":10048,"promptTokensDetails":[{"modality":"TEXT","tokenCount":10048}]}},{"candidates":[{"content":{"parts":[{"text":" don't pirates play poker? Because they always have a hidden ace up their sleeves"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":10048,"totalTokenCount":10048,"promptTokensDetails":[{"modality":"TEXT","tokenCount":10048}]}},{"candidates":[{"content":{"parts":[{"text":"!\\n"}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7284,"candidatesTokenCount":23,"totalTokenCount":7307,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7284}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":23}]}}]}
|
||||||
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"functionCall":{"name":"activate_skill","args":{"name":"pirate-skill"}}}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7185,"candidatesTokenCount":8,"totalTokenCount":7193,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7185}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":8}]}}]}
|
||||||
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"I am"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":10179,"totalTokenCount":10179,"promptTokensDetails":[{"modality":"TEXT","tokenCount":10179}]}},{"candidates":[{"content":{"parts":[{"text":" sorry, I cannot activate the skill at this time because it requires user confirmation."}],"role":"model"}}],"usageMetadata":{"promptTokenCount":10179,"totalTokenCount":10179,"promptTokensDetails":[{"modality":"TEXT","tokenCount":10179}]}},{"candidates":[{"content":{"parts":[{"text":" Would you like me to proceed with telling you a joke without activating the skill?"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":10179,"totalTokenCount":10179,"promptTokensDetails":[{"modality":"TEXT","tokenCount":10179}]}},{"candidates":[{"content":{"parts":[{"text":"\n"}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7218,"candidatesTokenCount":35,"totalTokenCount":7253,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7218}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":35}]}}]}
|
||||||
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"functionCall":{"name":"activate_skill","args":{"name":"pirate-skill"}}}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7185,"candidatesTokenCount":8,"totalTokenCount":7193,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7185}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":8}]}}]}
|
||||||
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"Arrr, why"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":10275,"totalTokenCount":10275,"promptTokensDetails":[{"modality":"TEXT","tokenCount":10275}]}},{"candidates":[{"content":{"parts":[{"text":" don't pirates play cards? Because someone's always standin' on the"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":10275,"totalTokenCount":10275,"promptTokensDetails":[{"modality":"TEXT","tokenCount":10275}]}},{"candidates":[{"content":{"parts":[{"text":" deck!\n"}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7309,"candidatesTokenCount":24,"totalTokenCount":7333,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7309}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":24}]}}]}
|
||||||
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"functionCall":{"name":"activate_skill","args":{"name":"pirate-skill"}}}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7174,"candidatesTokenCount":8,"totalTokenCount":7182,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7174}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":8}]}}]}
|
||||||
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"Ar"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":10264,"totalTokenCount":10264,"promptTokensDetails":[{"modality":"TEXT","tokenCount":10264}]}},{"candidates":[{"content":{"parts":[{"text":"rr, why don't pirates play cards? Because someone always be standin' on the"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":10264,"totalTokenCount":10264,"promptTokensDetails":[{"modality":"TEXT","tokenCount":10264}]}},{"candidates":[{"content":{"parts":[{"text":" deck!\n"}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7298,"candidatesTokenCount":23,"totalTokenCount":7321,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7298}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":23}]}}]}
|
||||||
|
|||||||
@@ -1,2 +1,8 @@
|
|||||||
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"functionCall":{"name":"activate_skill","args":{"name":"pirate-skill"}}}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7170,"candidatesTokenCount":8,"totalTokenCount":7178,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7170}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":8}]}}]}
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"functionCall":{"name":"activate_skill","args":{"name":"pirate-skill"}}}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7170,"candidatesTokenCount":8,"totalTokenCount":7178,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7170}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":8}]}}]}
|
||||||
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"Ar"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":10058,"totalTokenCount":10058,"promptTokensDetails":[{"modality":"TEXT","tokenCount":10058}]}},{"candidates":[{"content":{"parts":[{"text":"rr, the pirate skill be active, matey!"}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7294,"candidatesTokenCount":12,"totalTokenCount":7306,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7294}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":12}]}}]}
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"Ar"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":10058,"totalTokenCount":10058,"promptTokensDetails":[{"modality":"TEXT","tokenCount":10058}]}},{"candidates":[{"content":{"parts":[{"text":"rr, the pirate skill be active, matey!"}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7294,"candidatesTokenCount":12,"totalTokenCount":7306,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7294}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":12}]}}]}
|
||||||
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"functionCall":{"name":"activate_skill","args":{"name":"pirate-skill"}}}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7184,"candidatesTokenCount":8,"totalTokenCount":7192,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7184}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":8}]}}]}
|
||||||
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"I"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":10178,"totalTokenCount":10178,"promptTokensDetails":[{"modality":"TEXT","tokenCount":10178}]}},{"candidates":[{"content":{"parts":[{"text":" am unable to activate the skill without user confirmation. I will await further instructions.\n"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":10178,"totalTokenCount":10178,"promptTokensDetails":[{"modality":"TEXT","tokenCount":10178}]}},{"candidates":[{"content":{"parts":[{"text":""}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7217,"candidatesTokenCount":18,"totalTokenCount":7235,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7217}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":18}]}}]}
|
||||||
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"functionCall":{"name":"activate_skill","args":{"name":"pirate-skill"}}}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7184,"candidatesTokenCount":8,"totalTokenCount":7192,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7184}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":8}]}}]}
|
||||||
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"Ar"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":10274,"totalTokenCount":10274,"promptTokensDetails":[{"modality":"TEXT","tokenCount":10274}]}},{"candidates":[{"content":{"parts":[{"text":"rr, the pirate-skill be active, aye!\n"}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7308,"candidatesTokenCount":13,"totalTokenCount":7321,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7308}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":13}]}}]}
|
||||||
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"functionCall":{"name":"activate_skill","args":{"name":"pirate-skill"}}}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7173,"candidatesTokenCount":8,"totalTokenCount":7181,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7173}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":8}]}}]}
|
||||||
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"Ar"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":10263,"totalTokenCount":10263,"promptTokensDetails":[{"modality":"TEXT","tokenCount":10263}]}},{"candidates":[{"content":{"parts":[{"text":"rr, pirate skill activated, aye!"}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7297,"candidatesTokenCount":9,"totalTokenCount":7306,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7297}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":9}]}}]}
|
||||||
|
|||||||
@@ -1,2 +1,8 @@
|
|||||||
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"functionCall":{"name":"checkSystemStatus","args":{}}}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7070,"candidatesTokenCount":3,"totalTokenCount":7073,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7070}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":3}]}}]}
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"functionCall":{"name":"checkSystemStatus","args":{}}}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7070,"candidatesTokenCount":3,"totalTokenCount":7073,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7070}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":3}]}}]}
|
||||||
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"The system status check"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":9850,"totalTokenCount":9850,"promptTokensDetails":[{"modality":"TEXT","tokenCount":9850}]}},{"candidates":[{"content":{"parts":[{"text":" returned an error. It says `Error: Standard error caught`."}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7082,"candidatesTokenCount":17,"totalTokenCount":7099,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7082}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":17}]}}]}
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"The system status check"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":9850,"totalTokenCount":9850,"promptTokensDetails":[{"modality":"TEXT","tokenCount":9850}]}},{"candidates":[{"content":{"parts":[{"text":" returned an error. It says `Error: Standard error caught`."}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7082,"candidatesTokenCount":17,"totalTokenCount":7099,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7082}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":17}]}}]}
|
||||||
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"functionCall":{"name":"checkSystemStatus","args":{}}}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7184,"candidatesTokenCount":3,"totalTokenCount":7187,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7184}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":3}]}}]}
|
||||||
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"I am unable to"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":10183,"totalTokenCount":10183,"promptTokensDetails":[{"modality":"TEXT","tokenCount":10183}]}},{"candidates":[{"content":{"parts":[{"text":" check the system status because it requires user confirmation in interactive mode. Is there anything else I"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":10183,"totalTokenCount":10183,"promptTokensDetails":[{"modality":"TEXT","tokenCount":10183}]}},{"candidates":[{"content":{"parts":[{"text":" can help with?"}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7213,"candidatesTokenCount":26,"totalTokenCount":7239,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7213}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":26}]}}]}
|
||||||
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"functionCall":{"name":"checkSystemStatus","args":{}}}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7184,"candidatesTokenCount":3,"totalTokenCount":7187,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7184}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":3}]}}]}
|
||||||
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"The system status check"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":10164,"totalTokenCount":10164,"promptTokensDetails":[{"modality":"TEXT","tokenCount":10164}]}},{"candidates":[{"content":{"parts":[{"text":" reported an error: \"Standard error caught\".\n"}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7194,"candidatesTokenCount":14,"totalTokenCount":7208,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7194}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":14}]}}]}
|
||||||
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"functionCall":{"name":"checkSystemStatus","args":{}}}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7184,"candidatesTokenCount":3,"totalTokenCount":7187,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7184}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":3}]}}]}
|
||||||
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"There"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":10164,"totalTokenCount":10164,"promptTokensDetails":[{"modality":"TEXT","tokenCount":10164}]}},{"candidates":[{"content":{"parts":[{"text":" is an error reported in the system status.\n"}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7194,"candidatesTokenCount":11,"totalTokenCount":7205,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7194}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":11}]}}]}
|
||||||
|
|||||||
@@ -1,2 +1,8 @@
|
|||||||
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"functionCall":{"name":"failVisible","args":{"input":"fail"}}}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7073,"candidatesTokenCount":4,"totalTokenCount":7077,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7073}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":4}]}}]}
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"functionCall":{"name":"failVisible","args":{"input":"fail"}}}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7073,"candidatesTokenCount":4,"totalTokenCount":7077,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7073}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":4}]}}]}
|
||||||
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"The"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":9867,"totalTokenCount":9867,"promptTokensDetails":[{"modality":"TEXT","tokenCount":9867}]}},{"candidates":[{"content":{"parts":[{"text":" tool failed visibly with the error message: \"Error: Tool failed visibly\"."}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7085,"candidatesTokenCount":16,"totalTokenCount":7101,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7085}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":16}]}}]}
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"The"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":9867,"totalTokenCount":9867,"promptTokensDetails":[{"modality":"TEXT","tokenCount":9867}]}},{"candidates":[{"content":{"parts":[{"text":" tool failed visibly with the error message: \"Error: Tool failed visibly\"."}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7085,"candidatesTokenCount":16,"totalTokenCount":7101,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7085}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":16}]}}]}
|
||||||
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"functionCall":{"name":"failVisible","args":{"input":"fail"}}}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7198,"candidatesTokenCount":4,"totalTokenCount":7202,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7198}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":4}]}}]}
|
||||||
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"The"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":10210,"totalTokenCount":10210,"promptTokensDetails":[{"modality":"TEXT","tokenCount":10210}]}},{"candidates":[{"content":{"parts":[{"text":" tool execution for \"failVisible\" requires user confirmation, which is not supported in non-"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":10210,"totalTokenCount":10210,"promptTokensDetails":[{"modality":"TEXT","tokenCount":10210}]}},{"candidates":[{"content":{"parts":[{"text":"interactive mode."}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7226,"candidatesTokenCount":22,"totalTokenCount":7248,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7226}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":22}]}}]}
|
||||||
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"functionCall":{"name":"failVisible","args":{"input":"fail"}}}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7198,"candidatesTokenCount":4,"totalTokenCount":7202,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7198}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":4}]}}]}
|
||||||
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"The"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":10192,"totalTokenCount":10192,"promptTokensDetails":[{"modality":"TEXT","tokenCount":10192}]}},{"candidates":[{"content":{"parts":[{"text":" tool failed visibly. The error message is \"Tool failed visibly\"."}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7208,"candidatesTokenCount":14,"totalTokenCount":7222,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7208}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":14}]}}]}
|
||||||
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"functionCall":{"name":"failVisible","args":{"input":"fail"}}}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7187,"candidatesTokenCount":4,"totalTokenCount":7191,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7187}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":4}]}}]}
|
||||||
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"The tool failed with"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":10181,"totalTokenCount":10181,"promptTokensDetails":[{"modality":"TEXT","tokenCount":10181}]}},{"candidates":[{"content":{"parts":[{"text":" the error message \"Tool failed visibly\"."}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7197,"candidatesTokenCount":12,"totalTokenCount":7209,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7197}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":12}]}}]}
|
||||||
|
|||||||
@@ -1,2 +1,8 @@
|
|||||||
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"functionCall":{"name":"add","args":{"a":5,"b":3}}}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7045,"candidatesTokenCount":5,"totalTokenCount":7050,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7045}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":5}]}}]}
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"functionCall":{"name":"add","args":{"a":5,"b":3}}}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7045,"candidatesTokenCount":5,"totalTokenCount":7050,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7045}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":5}]}}]}
|
||||||
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"8"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":9849,"totalTokenCount":9849,"promptTokensDetails":[{"modality":"TEXT","tokenCount":9849}]}},{"candidates":[{"content":{"parts":[{"text":""}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7053,"candidatesTokenCount":1,"totalTokenCount":7054,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7053}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":1}]}}]}
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"8"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":9849,"totalTokenCount":9849,"promptTokensDetails":[{"modality":"TEXT","tokenCount":9849}]}},{"candidates":[{"content":{"parts":[{"text":""}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7053,"candidatesTokenCount":1,"totalTokenCount":7054,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7053}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":1}]}}]}
|
||||||
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"functionCall":{"name":"add","args":{"b":3,"a":5}}}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7179,"candidatesTokenCount":5,"totalTokenCount":7184,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7179}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":5}]}}]}
|
||||||
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"I"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":10204,"totalTokenCount":10204,"promptTokensDetails":[{"modality":"TEXT","tokenCount":10204}]}},{"candidates":[{"content":{"parts":[{"text":" am unable to execute the add tool in non-interactive mode.\n"}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7206,"candidatesTokenCount":15,"totalTokenCount":7221,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7206}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":15}]}}]}
|
||||||
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"functionCall":{"name":"add","args":{"a":5,"b":3}}}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7179,"candidatesTokenCount":5,"totalTokenCount":7184,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7179}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":5}]}}]}
|
||||||
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"8"}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7187,"candidatesTokenCount":1,"totalTokenCount":7188,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7187}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":1}]}}]}
|
||||||
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"functionCall":{"name":"add","args":{"a":5,"b":3}}}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7168,"candidatesTokenCount":5,"totalTokenCount":7173,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7168}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":5}]}}]}
|
||||||
|
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"8"}],"role":"model"}}],"usageMetadata":{"promptTokenCount":10174,"totalTokenCount":10174,"promptTokensDetails":[{"modality":"TEXT","tokenCount":10174}]}},{"candidates":[{"content":{"parts":[{"text":"\n"}],"role":"model"},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":7176,"candidatesTokenCount":2,"totalTokenCount":7178,"promptTokensDetails":[{"modality":"TEXT","tokenCount":7176}],"candidatesTokensDetails":[{"modality":"TEXT","tokenCount":2}]}}]}
|
||||||
|
|||||||
Reference in New Issue
Block a user