From 78877942eccb1e19ce531715c5fbb9570217341b Mon Sep 17 00:00:00 2001 From: ANDI FAUZAN HEDIANTORO <144610468+fauzan171@users.noreply.github.com> Date: Tue, 5 May 2026 02:32:47 +0700 Subject: [PATCH] docs(sdk): add JSDoc to all exported interfaces and types (#26277) --- packages/sdk/src/agent.ts | 38 ++++++++ packages/sdk/src/fs.ts | 7 ++ packages/sdk/src/session.ts | 40 ++++++++ packages/sdk/src/shell.ts | 12 +++ packages/sdk/src/skills.ts | 6 ++ packages/sdk/src/tool.ts | 80 ++++++++++++++++ packages/sdk/src/types.ts | 183 ++++++++++++++++++++++++++++-------- 7 files changed, 328 insertions(+), 38 deletions(-) diff --git a/packages/sdk/src/agent.ts b/packages/sdk/src/agent.ts index dba25ca444..d92ffd19f6 100644 --- a/packages/sdk/src/agent.ts +++ b/packages/sdk/src/agent.ts @@ -16,6 +16,27 @@ import { import { GeminiCliSession } from './session.js'; import type { GeminiCliAgentOptions } from './types.js'; +/** + * The main entry point for the Gemini CLI SDK. + * + * An agent encapsulates configuration (instructions, tools, skills, model) + * and can create new sessions or resume existing ones. + * + * @example + * ```typescript + * const agent = new GeminiCliAgent({ + * instructions: 'You are a helpful coding assistant.', + * tools: [myTool], + * }); + * + * const session = agent.session(); + * await session.initialize(); + * + * for await (const event of session.sendStream('Hello!')) { + * console.log(event); + * } + * ``` + */ export class GeminiCliAgent { private options: GeminiCliAgentOptions; @@ -23,11 +44,28 @@ export class GeminiCliAgent { this.options = options; } + /** + * Create a new conversation session. + * + * @param options - Optional session configuration. Pass `{ sessionId }` to + * use a specific session ID; otherwise a new one is generated. + * @returns A new {@link GeminiCliSession} instance. + */ session(options?: { sessionId?: string }): GeminiCliSession { const sessionId = options?.sessionId || createSessionId(); return new GeminiCliSession(this.options, sessionId, this); } + /** + * Resume a previously created session by its ID. + * + * Looks up the session's conversation history from storage and replays it + * so the agent can continue the conversation. + * + * @param sessionId - The ID of the session to resume. + * @returns A {@link GeminiCliSession} with the prior conversation loaded. + * @throws {Error} If no sessions exist or the specified ID is not found. + */ async resumeSession(sessionId: string): Promise { const cwd = this.options.cwd || process.cwd(); const storage = new Storage(cwd); diff --git a/packages/sdk/src/fs.ts b/packages/sdk/src/fs.ts index afdb92acff..f12d56780b 100644 --- a/packages/sdk/src/fs.ts +++ b/packages/sdk/src/fs.ts @@ -8,6 +8,13 @@ import type { Config as CoreConfig } from '@google/gemini-cli-core'; import type { AgentFilesystem } from './types.js'; import fs from 'node:fs/promises'; +/** + * SDK implementation of {@link AgentFilesystem} that enforces path-based + * access policies from the core Config. + * + * Read operations return `null` when access is denied; write operations + * throw an error. + */ export class SdkAgentFilesystem implements AgentFilesystem { constructor(private readonly config: CoreConfig) {} diff --git a/packages/sdk/src/session.ts b/packages/sdk/src/session.ts index 001d528817..8c94a9b5c8 100644 --- a/packages/sdk/src/session.ts +++ b/packages/sdk/src/session.ts @@ -35,6 +35,15 @@ import type { import type { SkillReference } from './skills.js'; import type { GeminiCliAgent } from './agent.js'; +/** + * Represents an interactive conversation session with a Gemini CLI agent. + * + * A session manages the conversation lifecycle: initialization, sending messages + * via streaming, handling tool calls, and maintaining conversation history. + * + * Create a session via {@link GeminiCliAgent.session} or resume one with + * {@link GeminiCliAgent.resumeSession}. + */ export class GeminiCliSession { private readonly config: Config; // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -86,10 +95,20 @@ export class GeminiCliSession { this.config = new Config(configParams); } + /** + * The unique identifier for this session. + */ get id(): string { return this.sessionId; } + /** + * Initialize the session by setting up authentication, loading skills, + * and registering tools. Must be called before {@link sendStream}. + * + * This method is idempotent — calling it multiple times has no effect + * after the first successful initialization. + */ async initialize(): Promise { if (this.initialized) return; @@ -168,6 +187,27 @@ export class GeminiCliSession { this.initialized = true; } + /** + * Send a prompt to the model and yield streaming events as they arrive. + * + * Handles the full agentic loop: sends the user prompt, streams model + * responses, executes any tool calls the model requests, and continues + * the loop until the model produces a final response with no tool calls. + * + * @param prompt - The user message to send. + * @param signal - Optional {@link AbortSignal} to cancel the stream. + * @yields {@link ServerGeminiStreamEvent} events as they are received from + * the model. + * + * @example + * ```typescript + * for await (const event of session.sendStream('Explain this code')) { + * if (event.type === GeminiEventType.ModelResponse) { + * process.stdout.write(event.value); + * } + * } + * ``` + */ async *sendStream( prompt: string, signal?: AbortSignal, diff --git a/packages/sdk/src/shell.ts b/packages/sdk/src/shell.ts index 770accfea7..827941edd8 100644 --- a/packages/sdk/src/shell.ts +++ b/packages/sdk/src/shell.ts @@ -16,6 +16,18 @@ import type { AgentShellOptions, } from './types.js'; +/** + * SDK implementation of {@link AgentShell} that executes commands via the + * core ShellExecutionService, subject to the agent's security policies. + * + * Commands that require interactive confirmation will be rejected since + * no interactive session is available in headless SDK mode. + * + * @remarks In this implementation, stderr is combined into stdout by the + * underlying ShellExecutionService. As a result, the stderr field of the + * returned {@link AgentShellResult} will be empty, and both output and + * stdout will contain the combined output. + */ export class SdkAgentShell implements AgentShell { constructor(private readonly config: CoreConfig) {} diff --git a/packages/sdk/src/skills.ts b/packages/sdk/src/skills.ts index 37d58214d1..d1a7e23a8c 100644 --- a/packages/sdk/src/skills.ts +++ b/packages/sdk/src/skills.ts @@ -4,6 +4,12 @@ * SPDX-License-Identifier: Apache-2.0 */ +/** + * A reference to a skill directory that can be loaded by the agent. + * + * Skills extend the agent's capabilities by providing additional prompts, + * tools, and behaviors defined in a directory structure. + */ export type SkillReference = { type: 'dir'; path: string }; /** diff --git a/packages/sdk/src/tool.ts b/packages/sdk/src/tool.ts index 33bd602795..4b7a319357 100644 --- a/packages/sdk/src/tool.ts +++ b/packages/sdk/src/tool.ts @@ -19,6 +19,11 @@ import type { SessionContext } from './types.js'; export { z }; +/** + * An error that, when thrown from a tool's action, will be visible to the + * Gemini model in the conversation. Useful for providing feedback to the + * model about why a tool failed so it can retry or adjust its approach. + */ export class ModelVisibleError extends Error { constructor(message: string | Error) { super(message instanceof Error ? message.message : message); @@ -26,14 +31,56 @@ export class ModelVisibleError extends Error { } } +/** + * The declarative definition of a tool, including its name, description, + * Zod input schema, and optional error-handling behavior. + * + * @typeParam T - The Zod schema type that validates the tool's input parameters. + */ export interface ToolDefinition { + /** + * A unique name for the tool, used by the model to invoke it. + */ name: string; + + /** + * A human-readable description of what the tool does. + * This is sent to the model to help it decide when to use the tool. + */ description: string; + + /** + * A Zod schema that validates and type-checks the tool's input parameters. + */ inputSchema: T; + + /** + * When `true`, any errors thrown by the tool's action will be sent back + * to the model as part of the conversation. Defaults to `false`. + */ sendErrorsToModel?: boolean; } +/** + * A complete tool definition that combines a {@link ToolDefinition} with + * an executable action function. + * + * The action receives validated parameters (inferred from the Zod schema) + * and an optional {@link SessionContext}, and returns an arbitrary result + * that will be serialized and sent back to the model. + * + * @typeParam T - The Zod schema type that validates the tool's input parameters. + */ export interface Tool extends ToolDefinition { + /** + * The function executed when the model invokes this tool. + * + * @param params - The validated input parameters, typed from the Zod schema. + * @param context - Optional session context providing access to filesystem, + * shell, and other session state. + * @returns A promise resolving to the tool's output, which will be + * serialized (to JSON if not already a string) and sent to the model. + */ action: (params: z.infer, context?: SessionContext) => Promise; } @@ -88,6 +135,14 @@ class SdkToolInvocation extends BaseToolInvocation< } } +/** + * A wrapper that integrates an SDK {@link Tool} into the core tool registry. + * + * Handles parameter validation, execution, error handling (including + * {@link ModelVisibleError}), and context binding for tool invocations. + * + * @typeParam T - The Zod schema type that validates the tool's input parameters. + */ export class SdkTool extends BaseDeclarativeTool< z.infer, ToolResult @@ -144,6 +199,31 @@ export class SdkTool extends BaseDeclarativeTool< } } +/** + * Helper function to create a {@link Tool} by combining a definition and an action. + * + * @typeParam T - The Zod schema type for the tool's input parameters. + * @param definition - The tool's name, description, and input schema. + * @param action - The async function to execute when the tool is invoked. + * @returns A complete {@link Tool} object ready to be passed to + * {@link GeminiCliAgentOptions.tools}. + * + * @example + * ```typescript + * import { z, tool } from '@google/gemini-cli-sdk'; + * + * const myTool = tool( + * { + * name: 'get_weather', + * description: 'Get the current weather for a location', + * inputSchema: z.object({ city: z.string() }), + * }, + * async (params) => { + * return `Weather in ${params.city}: Sunny, 25°C`; + * }, + * ); + * ``` + */ export function tool( definition: ToolDefinition, action: (params: z.infer, context?: SessionContext) => Promise, diff --git a/packages/sdk/src/types.ts b/packages/sdk/src/types.ts index 6896d4bd3e..bad8f4dedc 100644 --- a/packages/sdk/src/types.ts +++ b/packages/sdk/src/types.ts @@ -11,8 +11,11 @@ import type { GeminiCliAgent } from './agent.js'; import type { GeminiCliSession } from './session.js'; /** - * Instructions that guide the agent's behavior and personality. - * Can be a static string or a dynamic function that receives the current session context. + * System instructions for a Gemini CLI agent. + * + * Can be either a static string or a function that receives the current + * session context and returns a string (or a promise of one), allowing + * dynamic instructions that change based on conversation state. * * @issue-16272/packages/core/coverage/lcov-report/src/utils/security.ts.html WARNING: If using a dynamic function, ensure that any data from the * session context is sanitized (e.g., removing newlines, ']', and escaping '<', '>') @@ -23,55 +26,108 @@ export type SystemInstructions = | ((context: SessionContext) => string | Promise); /** - * Configuration options for creating a GeminiCliAgent. + * Configuration options for creating a {@link GeminiCliAgent}. */ export interface GeminiCliAgentOptions { /** - * The system instructions defining the agent's behavior. + * System instructions that define the agent's behavior. + * Can be a static string or a dynamic function that receives session context. + * * @issue-16272/packages/core/coverage/lcov-report/src/utils/security.ts.html WARNING: If using a dynamic function, sanitize all input from the * SessionContext (e.g., removing newlines, ']', and escaping '<', '>') to prevent prompt injection. */ instructions: SystemInstructions; - /** Optional list of tools the agent can use. */ + + /** + * Custom tools to register with the agent. + * Each tool is defined using a Zod schema for input validation. + */ // eslint-disable-next-line @typescript-eslint/no-explicit-any tools?: Array>; - /** Optional list of skills the agent possesses. */ + + /** + * Skill directories to load into the agent's skill set. + */ skills?: SkillReference[]; - /** The model name to use (e.g., 'gemini-1.5-pro'). */ + + /** + * The Gemini model to use for this agent. + * Defaults to the auto-selected model if not specified. + */ model?: string; - /** The current working directory for the agent. */ + + /** + * The working directory for the agent. + * Defaults to `process.cwd()` if not specified. + */ cwd?: string; - /** Whether to enable debug logging. */ + + /** + * Whether to enable debug mode for verbose logging. + * Defaults to `false`. + */ debug?: boolean; - /** Optional path to record agent responses for testing. */ + + /** + * File path to record agent responses to for debugging/replay. + */ recordResponses?: string; - /** Optional path to load fake responses for testing. */ + + /** + * File path to load fake/resimulated responses from for testing. + */ fakeResponses?: string; } /** - * Interface for basic filesystem operations that the agent can perform. + * A virtual filesystem interface available to agents during tool execution. + * + * Provides sandboxed read/write access to files, subject to the agent's + * configured path access policies. * * Note: Implementations must internally validate and sanitize file paths to * prevent path traversal attacks (e.g., checking for '..' or null bytes) * using robust functions like resolveToRealPath. */ export interface AgentFilesystem { - /** Reads the content of a file at the given path. */ + /** + * Read the contents of a file. + * + * @param path - Absolute or relative path to the file. + * @returns The file contents as a UTF-8 string, or `null` if the file + * does not exist or access is denied. + */ readFile(path: string): Promise; - /** Writes content to a file at the given path. */ + + /** + * Write content to a file. + * + * @param path - Absolute or relative path to the file. + * @param content - The content to write. + * @throws {Error} If write access is denied by the agent's policy. + */ writeFile(path: string, content: string): Promise; } /** - * Options for executing shell commands. + * Options for configuring shell command execution via {@link AgentShell.exec}. */ export interface AgentShellOptions { - /** Environment variables for the shell process. */ + /** + * Environment variables to set for the command execution. + * These are merged with the default environment. + */ env?: Record; - /** Timeout for the command in seconds. */ + + /** + * Maximum time in seconds to wait for the command to complete. + */ timeoutSeconds?: number; - /** The working directory where the command should be executed. */ + + /** + * Working directory in which to execute the command. + * Defaults to the agent's configured working directory. + */ cwd?: string; } @@ -79,56 +135,107 @@ export interface AgentShellOptions { * The result of a shell command execution. */ export interface AgentShellResult { - /** The exit code of the process, or null if it was terminated. */ + /** + * The exit code of the process, or `null` if the process was killed + * or did not exit normally. + */ exitCode: number | null; - /** The combined output of stdout and stderr. */ + + /** + * The combined stdout and stderr output of the command. + */ output: string; - /** The content written to stdout. */ + + /** + * The standard output stream content. + */ stdout: string; - /** The content written to stderr. */ + + /** + * The standard error stream content. + */ stderr: string; - /** Any error that occurred during execution. */ + + /** + * An error object if the command failed to execute or was rejected + * by policy. + */ error?: Error; } /** - * Interface for executing shell commands within the agent's environment. + * A shell interface for executing commands within an agent's sandboxed environment. + * + * Commands are subject to the agent's security policies and may be rejected + * if they require interactive confirmation. */ export interface AgentShell { /** - * Executes a shell command and returns the result. + * Execute a shell command. + * * @issue-16272/packages/core/coverage/lcov-report/src/utils/security.ts.html WARNING: Ensure the command string is properly sanitized and does * not contain unvalidated user or LLM input to prevent command injection. + * + * @param cmd - The command string to execute. + * @param options - Optional execution configuration. + * @returns A promise resolving to the command result. */ exec(cmd: string, options?: AgentShellOptions): Promise; } /** - * Contextual information provided to tools and dynamic instructions during a session. + * Contextual information about the current session, passed to tools and + * dynamic system instruction functions. + * + * Provides access to session metadata, conversation history, filesystem, + * shell, and the parent agent/session instances. */ export interface SessionContext { - /** Unique identifier for the current session. */ - sessionId: string; - /** The full transcript of the conversation so far. */ - transcript: readonly Content[]; - /** The current working directory of the session. */ - cwd: string; - /** The ISO timestamp of when the context was generated. */ - timestamp: string; /** - * Access to the filesystem for the agent. + * Unique identifier for the current session. + */ + sessionId: string; + + /** + * Read-only transcript of the conversation so far, including user + * messages and model responses. + */ + transcript: readonly Content[]; + + /** + * The current working directory of the session. + */ + cwd: string; + + /** + * ISO 8601 timestamp of when this context was created. + */ + timestamp: string; + + /** + * Virtual filesystem for reading and writing files within the agent's + * sandbox. + * * @issue-16272/packages/core/coverage/lcov-report/src/utils/security.ts.html WARNING: This provides full access to the agent's filesystem. * Ensure tools using this are trusted and validate their inputs. */ fs: AgentFilesystem; + /** - * Access to the shell for the agent. + * Shell interface for executing commands within the agent's sandbox. + * * @issue-16272/packages/core/coverage/lcov-report/src/utils/security.ts.html WARNING: This provides full access to the agent's shell. * Any tool receiving this context can execute arbitrary commands. */ shell: AgentShell; - /** Reference to the current GeminiCliAgent instance. */ + + /** + * The parent agent that owns this session. + */ agent: GeminiCliAgent; - /** Reference to the current GeminiCliSession instance. */ + + /** + * The current session instance. + */ session: GeminiCliSession; }