@k2wanko/gemini-cli-sdk 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +92 -0
- package/dist/agent.d.ts +26 -0
- package/dist/agent.js +171 -0
- package/dist/context.d.ts +41 -0
- package/dist/context.js +66 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/dist/skills.d.ts +8 -0
- package/dist/skills.js +6 -0
- package/dist/tool.d.ts +28 -0
- package/dist/tool.js +78 -0
- package/package.json +57 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 k2wanko
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# @k2wanko/gemini-cli-sdk
|
|
2
|
+
|
|
3
|
+
A lightweight, type-safe SDK for building non-interactive AI agents powered by Google Gemini.
|
|
4
|
+
Built on top of `@google/gemini-cli-core`.
|
|
5
|
+
|
|
6
|
+
## Features
|
|
7
|
+
|
|
8
|
+
- **Skill support** — Load skill directories compatible with Gemini CLI's skill format
|
|
9
|
+
- **Non-interactive by default** — All tool calls are auto-approved, designed for headless agent usage
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install @k2wanko/gemini-cli-sdk
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Quick Start
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
import { GeminiAgent, GeminiEventType } from "@k2wanko/gemini-cli-sdk";
|
|
21
|
+
|
|
22
|
+
const agent = new GeminiAgent({
|
|
23
|
+
instructions: "You are a friendly assistant. Keep responses short.",
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
for await (const event of agent.sendStream("Say hello")) {
|
|
27
|
+
if (event.type === GeminiEventType.Content) {
|
|
28
|
+
process.stdout.write(String(event.value));
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Defining Custom Tools
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
import { GeminiAgent, defineTool, z } from "@k2wanko/gemini-cli-sdk";
|
|
37
|
+
|
|
38
|
+
const fetchUrl = defineTool(
|
|
39
|
+
{
|
|
40
|
+
name: "fetch_url",
|
|
41
|
+
description: "Fetch the content of a URL",
|
|
42
|
+
inputSchema: z.object({
|
|
43
|
+
url: z.string().url(),
|
|
44
|
+
}),
|
|
45
|
+
},
|
|
46
|
+
async (params) => {
|
|
47
|
+
const res = await fetch(params.url);
|
|
48
|
+
return res.text();
|
|
49
|
+
},
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
const agent = new GeminiAgent({
|
|
53
|
+
instructions: "You are a web research assistant.",
|
|
54
|
+
tools: [fetchUrl],
|
|
55
|
+
});
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Using Skills
|
|
59
|
+
|
|
60
|
+
Load skill directories to give the agent additional capabilities:
|
|
61
|
+
|
|
62
|
+
```ts
|
|
63
|
+
import { GeminiAgent, GeminiEventType, skillDir } from "@k2wanko/gemini-cli-sdk";
|
|
64
|
+
|
|
65
|
+
const agent = new GeminiAgent({
|
|
66
|
+
instructions: "You are a browser automation assistant.",
|
|
67
|
+
skills: [
|
|
68
|
+
skillDir(new URL("skills", import.meta.url).pathname),
|
|
69
|
+
],
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
for await (const event of agent.sendStream(
|
|
73
|
+
"Take a screenshot of https://example.com",
|
|
74
|
+
)) {
|
|
75
|
+
if (event.type === GeminiEventType.Content) {
|
|
76
|
+
process.stdout.write(String(event.value));
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
See [`examples/`](./examples/) for runnable samples.
|
|
82
|
+
|
|
83
|
+
## Authentication
|
|
84
|
+
|
|
85
|
+
This SDK uses the same authentication as `@google/gemini-cli-core`. Set up credentials via one of:
|
|
86
|
+
|
|
87
|
+
- **Google Cloud ADC** (default): `gcloud auth application-default login`
|
|
88
|
+
- **API Key**: Set `GEMINI_API_KEY` environment variable
|
|
89
|
+
|
|
90
|
+
## License
|
|
91
|
+
|
|
92
|
+
MIT
|
package/dist/agent.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { GeminiEventType, type ServerGeminiStreamEvent } from "@google/gemini-cli-core";
|
|
2
|
+
import { type SessionContext } from "./context.js";
|
|
3
|
+
import type { SkillRef } from "./skills.js";
|
|
4
|
+
import { type ToolDef } from "./tool.js";
|
|
5
|
+
export { GeminiEventType, type ServerGeminiStreamEvent };
|
|
6
|
+
export interface GeminiAgentOptions {
|
|
7
|
+
instructions: string | ((ctx: SessionContext) => string | Promise<string>);
|
|
8
|
+
tools?: ToolDef<any>[];
|
|
9
|
+
skills?: SkillRef[];
|
|
10
|
+
model?: string;
|
|
11
|
+
cwd?: string;
|
|
12
|
+
debug?: boolean;
|
|
13
|
+
}
|
|
14
|
+
export declare class GeminiAgent {
|
|
15
|
+
private readonly config;
|
|
16
|
+
private readonly tools;
|
|
17
|
+
private readonly skillRefs;
|
|
18
|
+
private readonly instructions;
|
|
19
|
+
private instructionsLoaded;
|
|
20
|
+
constructor(options: GeminiAgentOptions);
|
|
21
|
+
sendStream(prompt: string, signal?: AbortSignal): AsyncGenerator<ServerGeminiStreamEvent>;
|
|
22
|
+
private initialize;
|
|
23
|
+
private resolveInstructions;
|
|
24
|
+
private buildScopedRegistry;
|
|
25
|
+
private extractToolCalls;
|
|
26
|
+
}
|
package/dist/agent.js
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { ActivateSkillTool, AuthType, Config, GeminiEventType, getAuthTypeFromEnv, loadSkillsFromDir, PolicyDecision, PREVIEW_GEMINI_MODEL_AUTO, scheduleAgentTools, } from "@google/gemini-cli-core";
|
|
2
|
+
import { AgentFsImpl, AgentShellImpl } from "./context.js";
|
|
3
|
+
import { SdkTool } from "./tool.js";
|
|
4
|
+
export { GeminiEventType };
|
|
5
|
+
export class GeminiAgent {
|
|
6
|
+
config;
|
|
7
|
+
tools;
|
|
8
|
+
skillRefs;
|
|
9
|
+
instructions;
|
|
10
|
+
instructionsLoaded = false;
|
|
11
|
+
constructor(options) {
|
|
12
|
+
this.instructions = options.instructions;
|
|
13
|
+
this.tools = options.tools ?? [];
|
|
14
|
+
this.skillRefs = options.skills ?? [];
|
|
15
|
+
const cwd = options.cwd ?? process.cwd();
|
|
16
|
+
const initialMemory = typeof this.instructions === "string" ? this.instructions : "";
|
|
17
|
+
const configParams = {
|
|
18
|
+
sessionId: crypto.randomUUID(),
|
|
19
|
+
targetDir: cwd,
|
|
20
|
+
cwd,
|
|
21
|
+
debugMode: options.debug ?? false,
|
|
22
|
+
model: options.model ?? PREVIEW_GEMINI_MODEL_AUTO,
|
|
23
|
+
userMemory: initialMemory,
|
|
24
|
+
enableHooks: false,
|
|
25
|
+
mcpEnabled: false,
|
|
26
|
+
extensionsEnabled: false,
|
|
27
|
+
skillsSupport: true,
|
|
28
|
+
adminSkillsEnabled: true,
|
|
29
|
+
policyEngineConfig: {
|
|
30
|
+
defaultDecision: PolicyDecision.ALLOW,
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
this.config = new Config(configParams);
|
|
34
|
+
}
|
|
35
|
+
async *sendStream(prompt, signal) {
|
|
36
|
+
await this.initialize();
|
|
37
|
+
const client = this.config.getGeminiClient();
|
|
38
|
+
const abortSignal = signal ?? new AbortController().signal;
|
|
39
|
+
const sessionId = this.config.getSessionId();
|
|
40
|
+
const agentFs = new AgentFsImpl(this.config);
|
|
41
|
+
const agentShell = new AgentShellImpl(this.config);
|
|
42
|
+
let request = [
|
|
43
|
+
{ text: prompt },
|
|
44
|
+
];
|
|
45
|
+
if (!this.instructionsLoaded) {
|
|
46
|
+
const ctx = {
|
|
47
|
+
sessionId,
|
|
48
|
+
transcript: client.getHistory(),
|
|
49
|
+
cwd: this.config.getWorkingDir(),
|
|
50
|
+
timestamp: new Date().toISOString(),
|
|
51
|
+
fs: agentFs,
|
|
52
|
+
shell: agentShell,
|
|
53
|
+
agent: this,
|
|
54
|
+
};
|
|
55
|
+
await this.resolveInstructions(ctx, client);
|
|
56
|
+
}
|
|
57
|
+
while (true) {
|
|
58
|
+
const stream = client.sendMessageStream(request, abortSignal, sessionId);
|
|
59
|
+
const events = [];
|
|
60
|
+
for await (const event of stream) {
|
|
61
|
+
yield event;
|
|
62
|
+
events.push(event);
|
|
63
|
+
}
|
|
64
|
+
const toolCalls = this.extractToolCalls(events, sessionId);
|
|
65
|
+
if (toolCalls.length === 0)
|
|
66
|
+
break;
|
|
67
|
+
const transcript = client.getHistory();
|
|
68
|
+
const ctx = {
|
|
69
|
+
sessionId,
|
|
70
|
+
transcript,
|
|
71
|
+
cwd: this.config.getWorkingDir(),
|
|
72
|
+
timestamp: new Date().toISOString(),
|
|
73
|
+
fs: agentFs,
|
|
74
|
+
shell: agentShell,
|
|
75
|
+
agent: this,
|
|
76
|
+
};
|
|
77
|
+
const scopedRegistry = this.buildScopedRegistry(ctx);
|
|
78
|
+
const completedCalls = await scheduleAgentTools(this.config, toolCalls, {
|
|
79
|
+
schedulerId: sessionId,
|
|
80
|
+
toolRegistry: scopedRegistry,
|
|
81
|
+
signal: abortSignal,
|
|
82
|
+
});
|
|
83
|
+
const functionResponses = completedCalls.flatMap((call) => call.response.responseParts);
|
|
84
|
+
request = functionResponses;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
// -------------------------------------------------------------------------
|
|
88
|
+
// Private helpers
|
|
89
|
+
// -------------------------------------------------------------------------
|
|
90
|
+
async initialize() {
|
|
91
|
+
if (this.config.getContentGenerator())
|
|
92
|
+
return;
|
|
93
|
+
const authType = getAuthTypeFromEnv() || AuthType.COMPUTE_ADC;
|
|
94
|
+
await this.config.refreshAuth(authType);
|
|
95
|
+
await this.config.initialize();
|
|
96
|
+
// Load skills from directories
|
|
97
|
+
if (this.skillRefs.length > 0) {
|
|
98
|
+
const skillManager = this.config.getSkillManager();
|
|
99
|
+
const loadPromises = this.skillRefs.map(async (ref) => {
|
|
100
|
+
try {
|
|
101
|
+
if (ref.type === "dir") {
|
|
102
|
+
return await loadSkillsFromDir(ref.path);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
catch (e) {
|
|
106
|
+
console.error(`Failed to load skills from ${ref.path}:`, e);
|
|
107
|
+
}
|
|
108
|
+
return [];
|
|
109
|
+
});
|
|
110
|
+
const loadedSkills = (await Promise.all(loadPromises)).flat();
|
|
111
|
+
if (loadedSkills.length > 0) {
|
|
112
|
+
skillManager.addSkills(loadedSkills);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
// Re-register ActivateSkillTool so its schema reflects all loaded skills
|
|
116
|
+
const skillManager = this.config.getSkillManager();
|
|
117
|
+
if (skillManager.getSkills().length > 0) {
|
|
118
|
+
const registry = this.config.getToolRegistry();
|
|
119
|
+
const toolName = ActivateSkillTool.Name;
|
|
120
|
+
if (registry.getTool(toolName)) {
|
|
121
|
+
registry.unregisterTool(toolName);
|
|
122
|
+
}
|
|
123
|
+
registry.registerTool(new ActivateSkillTool(this.config, this.config.getMessageBus()));
|
|
124
|
+
}
|
|
125
|
+
// Register user-defined tools
|
|
126
|
+
const registry = this.config.getToolRegistry();
|
|
127
|
+
const messageBus = this.config.getMessageBus();
|
|
128
|
+
for (const toolDef of this.tools) {
|
|
129
|
+
const sdkTool = new SdkTool(toolDef, messageBus, this);
|
|
130
|
+
registry.registerTool(sdkTool);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
async resolveInstructions(ctx, client) {
|
|
134
|
+
if (typeof this.instructions !== "function")
|
|
135
|
+
return;
|
|
136
|
+
const resolved = await this.instructions(ctx);
|
|
137
|
+
this.config.setUserMemory(resolved);
|
|
138
|
+
client.updateSystemInstruction();
|
|
139
|
+
this.instructionsLoaded = true;
|
|
140
|
+
}
|
|
141
|
+
buildScopedRegistry(ctx) {
|
|
142
|
+
const originalRegistry = this.config.getToolRegistry();
|
|
143
|
+
const scopedRegistry = Object.create(originalRegistry);
|
|
144
|
+
scopedRegistry.getTool = (name) => {
|
|
145
|
+
const tool = originalRegistry.getTool(name);
|
|
146
|
+
if (tool instanceof SdkTool) {
|
|
147
|
+
return tool.withContext(ctx);
|
|
148
|
+
}
|
|
149
|
+
return tool;
|
|
150
|
+
};
|
|
151
|
+
return scopedRegistry;
|
|
152
|
+
}
|
|
153
|
+
extractToolCalls(events, sessionId) {
|
|
154
|
+
const calls = [];
|
|
155
|
+
for (const event of events) {
|
|
156
|
+
if (event.type === GeminiEventType.ToolCallRequest) {
|
|
157
|
+
const toolCall = event.value;
|
|
158
|
+
const args = typeof toolCall.args === "string"
|
|
159
|
+
? JSON.parse(toolCall.args)
|
|
160
|
+
: toolCall.args;
|
|
161
|
+
calls.push({
|
|
162
|
+
...toolCall,
|
|
163
|
+
args,
|
|
164
|
+
isClientInitiated: false,
|
|
165
|
+
prompt_id: sessionId,
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return calls;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { Content, Config as CoreConfig } from "@google/gemini-cli-core";
|
|
2
|
+
import type { GeminiAgent } from "./agent.js";
|
|
3
|
+
export interface AgentFs {
|
|
4
|
+
readFile(path: string): Promise<string | null>;
|
|
5
|
+
writeFile(path: string, content: string): Promise<void>;
|
|
6
|
+
}
|
|
7
|
+
export interface ShellOptions {
|
|
8
|
+
env?: Record<string, string>;
|
|
9
|
+
timeout?: number;
|
|
10
|
+
cwd?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface ShellResult {
|
|
13
|
+
exitCode: number | null;
|
|
14
|
+
stdout: string;
|
|
15
|
+
stderr: string;
|
|
16
|
+
error?: Error;
|
|
17
|
+
}
|
|
18
|
+
export interface AgentShell {
|
|
19
|
+
exec(cmd: string, options?: ShellOptions): Promise<ShellResult>;
|
|
20
|
+
}
|
|
21
|
+
export interface SessionContext {
|
|
22
|
+
sessionId: string;
|
|
23
|
+
cwd: string;
|
|
24
|
+
transcript: Content[];
|
|
25
|
+
timestamp: string;
|
|
26
|
+
fs: AgentFs;
|
|
27
|
+
shell: AgentShell;
|
|
28
|
+
agent: GeminiAgent;
|
|
29
|
+
}
|
|
30
|
+
export declare class AgentFsImpl implements AgentFs {
|
|
31
|
+
private readonly config;
|
|
32
|
+
constructor(config: CoreConfig);
|
|
33
|
+
readFile(path: string): Promise<string | null>;
|
|
34
|
+
writeFile(path: string, content: string): Promise<void>;
|
|
35
|
+
}
|
|
36
|
+
export declare class AgentShellImpl implements AgentShell {
|
|
37
|
+
private readonly config;
|
|
38
|
+
constructor(config: CoreConfig);
|
|
39
|
+
exec(command: string, options?: ShellOptions): Promise<ShellResult>;
|
|
40
|
+
private canExecute;
|
|
41
|
+
}
|
package/dist/context.js
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import { ShellExecutionService, ShellTool } from "@google/gemini-cli-core";
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
// Internal implementations (exported for use by agent.ts, not part of
|
|
5
|
+
// the intended public API)
|
|
6
|
+
// ---------------------------------------------------------------------------
|
|
7
|
+
export class AgentFsImpl {
|
|
8
|
+
config;
|
|
9
|
+
constructor(config) {
|
|
10
|
+
this.config = config;
|
|
11
|
+
}
|
|
12
|
+
async readFile(path) {
|
|
13
|
+
const error = this.config.validatePathAccess(path, "read");
|
|
14
|
+
if (error)
|
|
15
|
+
return null;
|
|
16
|
+
try {
|
|
17
|
+
return await fs.readFile(path, "utf-8");
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
async writeFile(path, content) {
|
|
24
|
+
const error = this.config.validatePathAccess(path, "write");
|
|
25
|
+
if (error)
|
|
26
|
+
throw new Error(error);
|
|
27
|
+
await fs.writeFile(path, content, "utf-8");
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
export class AgentShellImpl {
|
|
31
|
+
config;
|
|
32
|
+
constructor(config) {
|
|
33
|
+
this.config = config;
|
|
34
|
+
}
|
|
35
|
+
async exec(command, options) {
|
|
36
|
+
const cwd = options?.cwd ?? this.config.getWorkingDir();
|
|
37
|
+
const abortController = new AbortController();
|
|
38
|
+
const allowed = await this.canExecute(command, cwd);
|
|
39
|
+
if (!allowed) {
|
|
40
|
+
return {
|
|
41
|
+
stdout: "",
|
|
42
|
+
stderr: "Command execution requires confirmation but no interactive session is available.",
|
|
43
|
+
exitCode: 1,
|
|
44
|
+
error: new Error("Command blocked by policy"),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
const handle = await ShellExecutionService.execute(command, cwd, () => { }, abortController.signal, false, this.config.getShellExecutionConfig());
|
|
48
|
+
const result = await handle.result;
|
|
49
|
+
return {
|
|
50
|
+
stdout: result.output,
|
|
51
|
+
stderr: "",
|
|
52
|
+
exitCode: result.exitCode,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
async canExecute(command, cwd) {
|
|
56
|
+
const shellTool = new ShellTool(this.config, this.config.getMessageBus());
|
|
57
|
+
try {
|
|
58
|
+
const invocation = shellTool.build({ command, dir_path: cwd });
|
|
59
|
+
const confirmation = await invocation.shouldConfirmExecute(new AbortController().signal);
|
|
60
|
+
return !confirmation;
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
package/dist/skills.d.ts
ADDED
package/dist/skills.js
ADDED
package/dist/tool.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { BaseDeclarativeTool, type MessageBus, type ToolInvocation, type ToolResult } from "@google/gemini-cli-core";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import type { SessionContext } from "./context.js";
|
|
4
|
+
export { z };
|
|
5
|
+
export declare class ToolError extends Error {
|
|
6
|
+
constructor(message: string | Error);
|
|
7
|
+
}
|
|
8
|
+
export type ToolAction<T extends z.ZodTypeAny> = (params: z.infer<T>, context: SessionContext) => Promise<unknown>;
|
|
9
|
+
export interface ToolDef<T extends z.ZodTypeAny> {
|
|
10
|
+
name: string;
|
|
11
|
+
description: string;
|
|
12
|
+
inputSchema: T;
|
|
13
|
+
sendErrorsToModel?: boolean;
|
|
14
|
+
action: ToolAction<T>;
|
|
15
|
+
}
|
|
16
|
+
export declare function defineTool<T extends z.ZodTypeAny>(config: {
|
|
17
|
+
name: string;
|
|
18
|
+
description: string;
|
|
19
|
+
inputSchema: T;
|
|
20
|
+
sendErrorsToModel?: boolean;
|
|
21
|
+
}, action: ToolAction<T>): ToolDef<T>;
|
|
22
|
+
export declare class SdkTool<T extends z.ZodTypeAny> extends BaseDeclarativeTool<z.infer<T>, ToolResult> {
|
|
23
|
+
private readonly def;
|
|
24
|
+
private readonly context?;
|
|
25
|
+
constructor(def: ToolDef<T>, messageBus: MessageBus, _agent?: unknown, context?: SessionContext | undefined);
|
|
26
|
+
withContext(context: SessionContext): SdkTool<T>;
|
|
27
|
+
protected createInvocation(params: z.infer<T>, messageBus: MessageBus, toolName?: string): ToolInvocation<z.infer<T>, ToolResult>;
|
|
28
|
+
}
|
package/dist/tool.js
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { BaseDeclarativeTool, BaseToolInvocation, Kind, } from "@google/gemini-cli-core";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { zodToJsonSchema } from "zod-to-json-schema";
|
|
4
|
+
export { z };
|
|
5
|
+
// ---------------------------------------------------------------------------
|
|
6
|
+
// Public types
|
|
7
|
+
// ---------------------------------------------------------------------------
|
|
8
|
+
export class ToolError extends Error {
|
|
9
|
+
constructor(message) {
|
|
10
|
+
super(message instanceof Error ? message.message : message);
|
|
11
|
+
this.name = "ToolError";
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export function defineTool(config, action) {
|
|
15
|
+
return {
|
|
16
|
+
name: config.name,
|
|
17
|
+
description: config.description,
|
|
18
|
+
inputSchema: config.inputSchema,
|
|
19
|
+
sendErrorsToModel: config.sendErrorsToModel,
|
|
20
|
+
action,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
// Internal: SdkToolInvocation
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
class SdkToolInvocation extends BaseToolInvocation {
|
|
27
|
+
action;
|
|
28
|
+
context;
|
|
29
|
+
sendErrorsToModel;
|
|
30
|
+
constructor(params, messageBus, action, context, toolName, sendErrorsToModel) {
|
|
31
|
+
super(params, messageBus, toolName);
|
|
32
|
+
this.action = action;
|
|
33
|
+
this.context = context;
|
|
34
|
+
this.sendErrorsToModel = sendErrorsToModel;
|
|
35
|
+
}
|
|
36
|
+
getDescription() {
|
|
37
|
+
return `Executing ${this._toolName}...`;
|
|
38
|
+
}
|
|
39
|
+
async execute(_signal, _updateOutput) {
|
|
40
|
+
try {
|
|
41
|
+
const result = await this.action(this.params, this.context);
|
|
42
|
+
const output = this.serialize(result);
|
|
43
|
+
return { llmContent: output, returnDisplay: output };
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
if (this.sendErrorsToModel || error instanceof ToolError) {
|
|
47
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
48
|
+
return {
|
|
49
|
+
llmContent: `Error: ${message}`,
|
|
50
|
+
returnDisplay: `Error: ${message}`,
|
|
51
|
+
error: { message },
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
throw error;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
serialize(value) {
|
|
58
|
+
return typeof value === "string" ? value : JSON.stringify(value, null, 2);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// ---------------------------------------------------------------------------
|
|
62
|
+
// Internal: SdkTool (exported for use by agent.ts)
|
|
63
|
+
// ---------------------------------------------------------------------------
|
|
64
|
+
export class SdkTool extends BaseDeclarativeTool {
|
|
65
|
+
def;
|
|
66
|
+
context;
|
|
67
|
+
constructor(def, messageBus, _agent, context) {
|
|
68
|
+
super(def.name, def.name, def.description, Kind.Other, zodToJsonSchema(def.inputSchema), messageBus);
|
|
69
|
+
this.def = def;
|
|
70
|
+
this.context = context;
|
|
71
|
+
}
|
|
72
|
+
withContext(context) {
|
|
73
|
+
return new SdkTool(this.def, this.messageBus, undefined, context);
|
|
74
|
+
}
|
|
75
|
+
createInvocation(params, messageBus, toolName) {
|
|
76
|
+
return new SdkToolInvocation(params, messageBus, this.def.action, this.context, toolName ?? this.name, this.def.sendErrorsToModel ?? false);
|
|
77
|
+
}
|
|
78
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@k2wanko/gemini-cli-sdk",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "A lightweight SDK for building non-interactive AI agents powered by Google Gemini",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"private": false,
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"author": "k2wanko",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "https://github.com/k2wanko/gemini-cli-sdk.git"
|
|
12
|
+
},
|
|
13
|
+
"homepage": "https://github.com/k2wanko/gemini-cli-sdk",
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/k2wanko/gemini-cli-sdk/issues"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"gemini",
|
|
19
|
+
"ai",
|
|
20
|
+
"agent",
|
|
21
|
+
"sdk",
|
|
22
|
+
"google",
|
|
23
|
+
"gemini-cli"
|
|
24
|
+
],
|
|
25
|
+
"main": "dist/index.js",
|
|
26
|
+
"types": "dist/index.d.ts",
|
|
27
|
+
"exports": {
|
|
28
|
+
".": {
|
|
29
|
+
"types": "./dist/index.d.ts",
|
|
30
|
+
"import": "./dist/index.js"
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"files": [
|
|
34
|
+
"dist"
|
|
35
|
+
],
|
|
36
|
+
"engines": {
|
|
37
|
+
"node": ">=20"
|
|
38
|
+
},
|
|
39
|
+
"scripts": {
|
|
40
|
+
"build": "tsc",
|
|
41
|
+
"lint": "biome check && tsc --noEmit",
|
|
42
|
+
"fix": "biome check --write . && tsc --noEmit",
|
|
43
|
+
"test": "bun test"
|
|
44
|
+
},
|
|
45
|
+
"dependencies": {
|
|
46
|
+
"@google/gemini-cli-core": "0.30.0-nightly.20260218.ce84b3cb5",
|
|
47
|
+
"zod": "^3.23.8",
|
|
48
|
+
"zod-to-json-schema": "^3.23.1"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@biomejs/biome": "latest",
|
|
52
|
+
"@types/bun": "latest"
|
|
53
|
+
},
|
|
54
|
+
"peerDependencies": {
|
|
55
|
+
"typescript": "latest"
|
|
56
|
+
}
|
|
57
|
+
}
|