ak-gemini 2.1.3 → 2.1.5
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/code-agent.js +44 -3
- package/index.cjs +36 -2
- package/package.json +1 -1
- package/types.d.ts +23 -2
package/code-agent.js
CHANGED
|
@@ -8,7 +8,7 @@ import BaseGemini from './base.js';
|
|
|
8
8
|
import log from './logger.js';
|
|
9
9
|
import { execFile } from 'node:child_process';
|
|
10
10
|
import { writeFile, unlink, readdir, readFile, mkdir } from 'node:fs/promises';
|
|
11
|
-
import { join, sep, basename } from 'node:path';
|
|
11
|
+
import { join, sep, basename, isAbsolute } from 'node:path';
|
|
12
12
|
import { randomUUID } from 'node:crypto';
|
|
13
13
|
|
|
14
14
|
/**
|
|
@@ -49,6 +49,17 @@ class CodeAgent extends BaseGemini {
|
|
|
49
49
|
this.skills = options.skills || [];
|
|
50
50
|
this.envOverview = options.envOverview || '';
|
|
51
51
|
|
|
52
|
+
// ── Custom tools ──
|
|
53
|
+
this.customTools = (options.tools || []).map(t => ({
|
|
54
|
+
name: t.name,
|
|
55
|
+
description: t.description,
|
|
56
|
+
parametersJsonSchema: t.parametersJsonSchema || t.parameters || t.input_schema || t.inputSchema
|
|
57
|
+
}));
|
|
58
|
+
this.toolExecutor = options.toolExecutor || null;
|
|
59
|
+
if (this.customTools.length > 0 && !this.toolExecutor) {
|
|
60
|
+
throw new Error('CodeAgent: tools provided without a toolExecutor.');
|
|
61
|
+
}
|
|
62
|
+
|
|
52
63
|
// ── Internal state ──
|
|
53
64
|
this._codebaseContext = null;
|
|
54
65
|
this._contextGathered = false;
|
|
@@ -156,6 +167,11 @@ class CodeAgent extends BaseGemini {
|
|
|
156
167
|
});
|
|
157
168
|
}
|
|
158
169
|
|
|
170
|
+
// Append custom tools
|
|
171
|
+
for (const t of this.customTools) {
|
|
172
|
+
declarations.push({ name: t.name, description: t.description, parametersJsonSchema: t.parametersJsonSchema });
|
|
173
|
+
}
|
|
174
|
+
|
|
159
175
|
return { functionDeclarations: declarations };
|
|
160
176
|
}
|
|
161
177
|
|
|
@@ -252,7 +268,7 @@ class CodeAgent extends BaseGemini {
|
|
|
252
268
|
continue;
|
|
253
269
|
}
|
|
254
270
|
try {
|
|
255
|
-
const fullPath = join(this.workingDirectory, resolved);
|
|
271
|
+
const fullPath = isAbsolute(resolved) ? resolved : join(this.workingDirectory, resolved);
|
|
256
272
|
const content = await readFile(fullPath, 'utf-8');
|
|
257
273
|
importantFileContents.push({ path: resolved, content });
|
|
258
274
|
} catch (e) {
|
|
@@ -269,6 +285,8 @@ class CodeAgent extends BaseGemini {
|
|
|
269
285
|
* @private
|
|
270
286
|
*/
|
|
271
287
|
_resolveImportantFile(filename, fileTreeLines) {
|
|
288
|
+
if (isAbsolute(filename)) return filename;
|
|
289
|
+
|
|
272
290
|
const exact = fileTreeLines.find(line => line === filename);
|
|
273
291
|
if (exact) return exact;
|
|
274
292
|
|
|
@@ -651,12 +669,30 @@ These rules apply when using execute_code, write_and_run_code, or fix_code (with
|
|
|
651
669
|
data: { tool: 'use_skill', skillName: skill.name, content: skill.content, found: true }
|
|
652
670
|
};
|
|
653
671
|
}
|
|
654
|
-
default:
|
|
672
|
+
default: {
|
|
673
|
+
if (this.toolExecutor) {
|
|
674
|
+
try {
|
|
675
|
+
const result = await this.toolExecutor(name, input);
|
|
676
|
+
const resultStr = typeof result === 'string' ? result : JSON.stringify(result);
|
|
677
|
+
return {
|
|
678
|
+
output: resultStr,
|
|
679
|
+
type: 'tool',
|
|
680
|
+
data: { tool: name, args: input, result }
|
|
681
|
+
};
|
|
682
|
+
} catch (err) {
|
|
683
|
+
return {
|
|
684
|
+
output: `Tool "${name}" failed: ${err.message}`,
|
|
685
|
+
type: 'tool',
|
|
686
|
+
data: { tool: name, args: input, error: err.message }
|
|
687
|
+
};
|
|
688
|
+
}
|
|
689
|
+
}
|
|
655
690
|
return {
|
|
656
691
|
output: `Unknown tool: ${name}`,
|
|
657
692
|
type: 'unknown',
|
|
658
693
|
data: { tool: name }
|
|
659
694
|
};
|
|
695
|
+
}
|
|
660
696
|
}
|
|
661
697
|
}
|
|
662
698
|
|
|
@@ -859,6 +895,11 @@ These rules apply when using execute_code, write_and_run_code, or fix_code (with
|
|
|
859
895
|
yield { type: 'skill', skillName: data.skillName, content: data.content, found: data.found };
|
|
860
896
|
}
|
|
861
897
|
|
|
898
|
+
// Emit custom tool event
|
|
899
|
+
if (type === 'tool') {
|
|
900
|
+
yield { type: 'tool', toolName, args: data.args, result: data.result, error: data.error };
|
|
901
|
+
}
|
|
902
|
+
|
|
862
903
|
// Track consecutive failures
|
|
863
904
|
const isExecutingTool = EXECUTING_TOOLS.has(toolName) || (toolName === 'fix_code' && toolInput.execute);
|
|
864
905
|
if (isExecutingTool) {
|
package/index.cjs
CHANGED
|
@@ -1649,6 +1649,15 @@ var CodeAgent = class extends base_default {
|
|
|
1649
1649
|
this.maxRetries = options.maxRetries ?? 3;
|
|
1650
1650
|
this.skills = options.skills || [];
|
|
1651
1651
|
this.envOverview = options.envOverview || "";
|
|
1652
|
+
this.customTools = (options.tools || []).map((t) => ({
|
|
1653
|
+
name: t.name,
|
|
1654
|
+
description: t.description,
|
|
1655
|
+
parametersJsonSchema: t.parametersJsonSchema || t.parameters || t.input_schema || t.inputSchema
|
|
1656
|
+
}));
|
|
1657
|
+
this.toolExecutor = options.toolExecutor || null;
|
|
1658
|
+
if (this.customTools.length > 0 && !this.toolExecutor) {
|
|
1659
|
+
throw new Error("CodeAgent: tools provided without a toolExecutor.");
|
|
1660
|
+
}
|
|
1652
1661
|
this._codebaseContext = null;
|
|
1653
1662
|
this._contextGathered = false;
|
|
1654
1663
|
this._stopped = false;
|
|
@@ -1746,6 +1755,9 @@ var CodeAgent = class extends base_default {
|
|
|
1746
1755
|
}
|
|
1747
1756
|
});
|
|
1748
1757
|
}
|
|
1758
|
+
for (const t of this.customTools) {
|
|
1759
|
+
declarations.push({ name: t.name, description: t.description, parametersJsonSchema: t.parametersJsonSchema });
|
|
1760
|
+
}
|
|
1749
1761
|
return { functionDeclarations: declarations };
|
|
1750
1762
|
}
|
|
1751
1763
|
// ── Init ─────────────────────────────────────────────────────────────────
|
|
@@ -1823,7 +1835,7 @@ var CodeAgent = class extends base_default {
|
|
|
1823
1835
|
continue;
|
|
1824
1836
|
}
|
|
1825
1837
|
try {
|
|
1826
|
-
const fullPath = (0, import_node_path.join)(this.workingDirectory, resolved);
|
|
1838
|
+
const fullPath = (0, import_node_path.isAbsolute)(resolved) ? resolved : (0, import_node_path.join)(this.workingDirectory, resolved);
|
|
1827
1839
|
const content = await (0, import_promises2.readFile)(fullPath, "utf-8");
|
|
1828
1840
|
importantFileContents.push({ path: resolved, content });
|
|
1829
1841
|
} catch (e) {
|
|
@@ -1838,6 +1850,7 @@ var CodeAgent = class extends base_default {
|
|
|
1838
1850
|
* @private
|
|
1839
1851
|
*/
|
|
1840
1852
|
_resolveImportantFile(filename, fileTreeLines) {
|
|
1853
|
+
if ((0, import_node_path.isAbsolute)(filename)) return filename;
|
|
1841
1854
|
const exact = fileTreeLines.find((line) => line === filename);
|
|
1842
1855
|
if (exact) return exact;
|
|
1843
1856
|
const partial = fileTreeLines.find(
|
|
@@ -2234,12 +2247,30 @@ ${this.envOverview}`;
|
|
|
2234
2247
|
data: { tool: "use_skill", skillName: skill.name, content: skill.content, found: true }
|
|
2235
2248
|
};
|
|
2236
2249
|
}
|
|
2237
|
-
default:
|
|
2250
|
+
default: {
|
|
2251
|
+
if (this.toolExecutor) {
|
|
2252
|
+
try {
|
|
2253
|
+
const result = await this.toolExecutor(name, input);
|
|
2254
|
+
const resultStr = typeof result === "string" ? result : JSON.stringify(result);
|
|
2255
|
+
return {
|
|
2256
|
+
output: resultStr,
|
|
2257
|
+
type: "tool",
|
|
2258
|
+
data: { tool: name, args: input, result }
|
|
2259
|
+
};
|
|
2260
|
+
} catch (err) {
|
|
2261
|
+
return {
|
|
2262
|
+
output: `Tool "${name}" failed: ${err.message}`,
|
|
2263
|
+
type: "tool",
|
|
2264
|
+
data: { tool: name, args: input, error: err.message }
|
|
2265
|
+
};
|
|
2266
|
+
}
|
|
2267
|
+
}
|
|
2238
2268
|
return {
|
|
2239
2269
|
output: `Unknown tool: ${name}`,
|
|
2240
2270
|
type: "unknown",
|
|
2241
2271
|
data: { tool: name }
|
|
2242
2272
|
};
|
|
2273
|
+
}
|
|
2243
2274
|
}
|
|
2244
2275
|
}
|
|
2245
2276
|
// ── Non-Streaming Chat ───────────────────────────────────────────────────
|
|
@@ -2396,6 +2427,9 @@ ${this.envOverview}`;
|
|
|
2396
2427
|
if (toolName === "use_skill") {
|
|
2397
2428
|
yield { type: "skill", skillName: data.skillName, content: data.content, found: data.found };
|
|
2398
2429
|
}
|
|
2430
|
+
if (type === "tool") {
|
|
2431
|
+
yield { type: "tool", toolName, args: data.args, result: data.result, error: data.error };
|
|
2432
|
+
}
|
|
2399
2433
|
const isExecutingTool = EXECUTING_TOOLS.has(toolName) || toolName === "fix_code" && toolInput.execute;
|
|
2400
2434
|
if (isExecutingTool) {
|
|
2401
2435
|
if (data.exitCode !== 0 && !data.denied) {
|
package/package.json
CHANGED
package/types.d.ts
CHANGED
|
@@ -324,6 +324,17 @@ export interface CodeAgentOptions extends BaseGeminiOptions {
|
|
|
324
324
|
skills?: string[];
|
|
325
325
|
/** Plain text environment overview appended to the system prompt — describe the project, stack, conventions, etc. */
|
|
326
326
|
envOverview?: string;
|
|
327
|
+
/** Custom tool declarations to add alongside built-in CodeAgent tools. Accepts Gemini, Claude, or OpenAI tool formats (auto-mapped). */
|
|
328
|
+
tools?: Array<{
|
|
329
|
+
name: string;
|
|
330
|
+
description: string;
|
|
331
|
+
parametersJsonSchema?: any;
|
|
332
|
+
parameters?: any;
|
|
333
|
+
input_schema?: any;
|
|
334
|
+
inputSchema?: any;
|
|
335
|
+
}>;
|
|
336
|
+
/** Function to execute custom tool calls: (toolName, args) => result */
|
|
337
|
+
toolExecutor?: (toolName: string, args: Record<string, any>) => Promise<any>;
|
|
327
338
|
}
|
|
328
339
|
|
|
329
340
|
export interface CodeExecution {
|
|
@@ -340,7 +351,7 @@ export interface CodeExecution {
|
|
|
340
351
|
}
|
|
341
352
|
|
|
342
353
|
export interface ToolCallResult {
|
|
343
|
-
tool: 'write_code' | 'execute_code' | 'write_and_run_code' | 'fix_code' | 'run_bash' | 'use_skill';
|
|
354
|
+
tool: 'write_code' | 'execute_code' | 'write_and_run_code' | 'fix_code' | 'run_bash' | 'use_skill' | string;
|
|
344
355
|
code?: string;
|
|
345
356
|
purpose?: string;
|
|
346
357
|
language?: string;
|
|
@@ -370,7 +381,7 @@ export interface CodeAgentResponse {
|
|
|
370
381
|
}
|
|
371
382
|
|
|
372
383
|
export interface CodeAgentStreamEvent {
|
|
373
|
-
type: 'text' | 'code' | 'output' | 'write' | 'fix' | 'bash' | 'skill' | 'done';
|
|
384
|
+
type: 'text' | 'code' | 'output' | 'write' | 'fix' | 'bash' | 'skill' | 'tool' | 'done';
|
|
374
385
|
text?: string;
|
|
375
386
|
code?: string;
|
|
376
387
|
stdout?: string;
|
|
@@ -390,6 +401,14 @@ export interface CodeAgentStreamEvent {
|
|
|
390
401
|
skillName?: string;
|
|
391
402
|
content?: string;
|
|
392
403
|
found?: boolean;
|
|
404
|
+
/** custom tool: tool name */
|
|
405
|
+
toolName?: string;
|
|
406
|
+
/** custom tool: arguments passed */
|
|
407
|
+
args?: Record<string, any>;
|
|
408
|
+
/** custom tool: result returned */
|
|
409
|
+
result?: any;
|
|
410
|
+
/** custom tool: error message (if failed) */
|
|
411
|
+
error?: string;
|
|
393
412
|
}
|
|
394
413
|
|
|
395
414
|
// ── Per-Message Options ──────────────────────────────────────────────────────
|
|
@@ -625,6 +644,8 @@ export declare class CodeAgent extends BaseGemini {
|
|
|
625
644
|
maxRetries: number;
|
|
626
645
|
skills: string[];
|
|
627
646
|
envOverview: string;
|
|
647
|
+
customTools: Array<{ name: string; description: string; parametersJsonSchema: any }>;
|
|
648
|
+
toolExecutor: ((toolName: string, args: Record<string, any>) => Promise<any>) | null;
|
|
628
649
|
|
|
629
650
|
init(force?: boolean): Promise<void>;
|
|
630
651
|
chat(message: string, opts?: { labels?: Record<string, string> }): Promise<CodeAgentResponse>;
|