ak-gemini 2.1.5 → 2.3.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/base.js +52 -13
- package/code-agent.js +190 -40
- package/image-generator.js +186 -0
- package/index.cjs +368 -54
- package/index.js +3 -1
- package/package.json +3 -2
- package/types.d.ts +78 -3
package/index.cjs
CHANGED
|
@@ -35,6 +35,7 @@ __export(index_exports, {
|
|
|
35
35
|
Embedding: () => Embedding,
|
|
36
36
|
HarmBlockThreshold: () => import_genai2.HarmBlockThreshold,
|
|
37
37
|
HarmCategory: () => import_genai2.HarmCategory,
|
|
38
|
+
ImageGenerator: () => ImageGenerator,
|
|
38
39
|
Message: () => message_default,
|
|
39
40
|
RagAgent: () => rag_agent_default,
|
|
40
41
|
ThinkingLevel: () => import_genai2.ThinkingLevel,
|
|
@@ -322,29 +323,46 @@ var DEFAULT_THINKING_CONFIG = {
|
|
|
322
323
|
};
|
|
323
324
|
var DEFAULT_MAX_OUTPUT_TOKENS = 5e4;
|
|
324
325
|
var THINKING_SUPPORTED_MODELS = [
|
|
325
|
-
/^gemini-3
|
|
326
|
-
/^gemini-3
|
|
326
|
+
/^gemini-3(\.\d+)?-pro(-preview)?$/,
|
|
327
|
+
/^gemini-3(\.\d+)?-flash(-preview)?$/,
|
|
328
|
+
/^gemini-3(\.\d+)?-flash-lite(-preview)?$/,
|
|
327
329
|
/^gemini-2\.5-pro/,
|
|
328
330
|
/^gemini-2\.5-flash(-preview)?$/,
|
|
329
331
|
/^gemini-2\.5-flash-lite(-preview)?$/,
|
|
330
332
|
/^gemini-2\.0-flash$/
|
|
331
333
|
];
|
|
332
334
|
var MODEL_PRICING = {
|
|
333
|
-
|
|
334
|
-
"gemini-
|
|
335
|
-
"gemini-
|
|
336
|
-
|
|
337
|
-
"gemini-3-pro-preview": { input: 2, output: 12 },
|
|
335
|
+
// Gemini 3.x stable
|
|
336
|
+
"gemini-3.5-flash": { input: 1.5, output: 9 },
|
|
337
|
+
"gemini-3.1-flash-lite": { input: 0.25, output: 1.5 },
|
|
338
|
+
// Gemini 3.x preview
|
|
339
|
+
"gemini-3.1-pro-preview": { input: 2, output: 12 },
|
|
340
|
+
// ≤200k tier
|
|
341
|
+
"gemini-3-flash-preview": { input: 0.5, output: 3 },
|
|
342
|
+
"gemini-3.1-flash-lite-preview": { input: 0.25, output: 1.5 },
|
|
343
|
+
"gemini-3.1-flash-image-preview": { input: 0.5, output: 3 },
|
|
344
|
+
// text-only; image-output is $60/M
|
|
345
|
+
"gemini-3-pro-image-preview": { input: 2, output: 12 },
|
|
346
|
+
// text-only; image-output is $120/M
|
|
347
|
+
// Gemini 2.5 stable
|
|
348
|
+
"gemini-2.5-flash": { input: 0.3, output: 2.5 },
|
|
349
|
+
"gemini-2.5-flash-lite": { input: 0.1, output: 0.4 },
|
|
350
|
+
"gemini-2.5-pro": { input: 1.25, output: 10 },
|
|
351
|
+
// ≤200k tier
|
|
352
|
+
"gemini-2.5-flash-image": { input: 0.3, output: 0 },
|
|
353
|
+
// image-output is ~$0.039/image (1290 tokens)
|
|
354
|
+
// Deprecated but kept for back-compat (shut down June 2026)
|
|
338
355
|
"gemini-2.0-flash": { input: 0.1, output: 0.4 },
|
|
339
356
|
"gemini-2.0-flash-lite": { input: 0.02, output: 0.1 },
|
|
340
|
-
|
|
357
|
+
// Embeddings
|
|
358
|
+
"gemini-embedding-001": { input: 0.15, output: 0 }
|
|
341
359
|
};
|
|
342
360
|
var BaseGemini = class {
|
|
343
361
|
/**
|
|
344
362
|
* @param {BaseGeminiOptions} [options={}]
|
|
345
363
|
*/
|
|
346
364
|
constructor(options = {}) {
|
|
347
|
-
this.modelName = options.modelName || "gemini-
|
|
365
|
+
this.modelName = options.modelName || "gemini-3-flash-preview";
|
|
348
366
|
if (options.systemPrompt !== void 0) {
|
|
349
367
|
this.systemPrompt = options.systemPrompt;
|
|
350
368
|
} else {
|
|
@@ -369,6 +387,8 @@ var BaseGemini = class {
|
|
|
369
387
|
this.enableGrounding = options.enableGrounding || false;
|
|
370
388
|
this.groundingConfig = options.groundingConfig || {};
|
|
371
389
|
this.cachedContent = options.cachedContent || null;
|
|
390
|
+
this.serviceTier = options.serviceTier || null;
|
|
391
|
+
this.includeServerSideToolInvocations = options.includeServerSideToolInvocations ?? false;
|
|
372
392
|
this.chatConfig = {
|
|
373
393
|
temperature: 0.7,
|
|
374
394
|
topP: 0.95,
|
|
@@ -376,6 +396,8 @@ var BaseGemini = class {
|
|
|
376
396
|
safetySettings: DEFAULT_SAFETY_SETTINGS,
|
|
377
397
|
...options.chatConfig
|
|
378
398
|
};
|
|
399
|
+
if (this.serviceTier) this.chatConfig["serviceTier"] = this.serviceTier;
|
|
400
|
+
if (this.includeServerSideToolInvocations) this.chatConfig["includeServerSideToolInvocations"] = true;
|
|
379
401
|
if (this.systemPrompt) {
|
|
380
402
|
this.chatConfig.systemInstruction = this.systemPrompt;
|
|
381
403
|
} else if (this.systemPrompt === null && options.systemPrompt === void 0) {
|
|
@@ -573,6 +595,7 @@ ${contextText}
|
|
|
573
595
|
* @protected
|
|
574
596
|
*/
|
|
575
597
|
_captureMetadata(response) {
|
|
598
|
+
const modelStatus = response?.modelStatus || null;
|
|
576
599
|
this.lastResponseMetadata = {
|
|
577
600
|
modelVersion: response.modelVersion || null,
|
|
578
601
|
requestedModel: this.modelName,
|
|
@@ -580,8 +603,13 @@ ${contextText}
|
|
|
580
603
|
responseTokens: response.usageMetadata?.candidatesTokenCount || 0,
|
|
581
604
|
totalTokens: response.usageMetadata?.totalTokenCount || 0,
|
|
582
605
|
timestamp: Date.now(),
|
|
583
|
-
groundingMetadata: response.candidates?.[0]?.groundingMetadata || null
|
|
606
|
+
groundingMetadata: response.candidates?.[0]?.groundingMetadata || null,
|
|
607
|
+
modelStatus
|
|
584
608
|
};
|
|
609
|
+
if (modelStatus === "DEPRECATED" && !this._deprecationWarned) {
|
|
610
|
+
logger_default.warn(`Model "${this.modelName}" is marked DEPRECATED by Google. Plan migration.`);
|
|
611
|
+
this._deprecationWarned = true;
|
|
612
|
+
}
|
|
585
613
|
}
|
|
586
614
|
/**
|
|
587
615
|
* Returns structured usage data from the last API call for billing verification.
|
|
@@ -601,7 +629,8 @@ ${contextText}
|
|
|
601
629
|
modelVersion: meta.modelVersion,
|
|
602
630
|
requestedModel: meta.requestedModel,
|
|
603
631
|
timestamp: meta.timestamp,
|
|
604
|
-
groundingMetadata: meta.groundingMetadata || null
|
|
632
|
+
groundingMetadata: meta.groundingMetadata || null,
|
|
633
|
+
modelStatus: meta.modelStatus || null
|
|
605
634
|
};
|
|
606
635
|
}
|
|
607
636
|
// ── Token Estimation ─────────────────────────────────────────────────────
|
|
@@ -1626,7 +1655,55 @@ var import_node_path = require("node:path");
|
|
|
1626
1655
|
var import_node_crypto = require("node:crypto");
|
|
1627
1656
|
var MAX_OUTPUT_CHARS = 5e4;
|
|
1628
1657
|
var MAX_FILE_TREE_LINES = 500;
|
|
1629
|
-
var IGNORE_DIRS = /* @__PURE__ */ new Set(["node_modules", ".git", "dist", "coverage", ".next", "build", "__pycache__"]);
|
|
1658
|
+
var IGNORE_DIRS = /* @__PURE__ */ new Set(["node_modules", ".git", "dist", "coverage", ".next", "build", "__pycache__", ".venv"]);
|
|
1659
|
+
var LANG_CONFIG = {
|
|
1660
|
+
javascript: {
|
|
1661
|
+
toolDescExecute: "Execute a given piece of JavaScript code in a Node.js child process. Use this when you already have code to run \u2014 e.g., running code from a previous write_code call, re-running a snippet, or executing code the user provided. Use console.log() for output.",
|
|
1662
|
+
toolDescWriteAndRun: "Write a fresh solution from scratch and execute it in one step. Use this when you need to figure out the code AND run it \u2014 the autonomous, end-to-end tool for solving problems with code.",
|
|
1663
|
+
codeParamDesc: "JavaScript code to execute. Use console.log() for output. Use import syntax (ES modules).",
|
|
1664
|
+
codeRules: `- Your code runs in a Node.js child process with access to all built-in modules
|
|
1665
|
+
- IMPORTANT: Your code runs as an ES module (.mjs). Use import syntax, NOT require():
|
|
1666
|
+
- import fs from 'fs';
|
|
1667
|
+
- import path from 'path';
|
|
1668
|
+
- import { execSync } from 'child_process';
|
|
1669
|
+
- Use console.log() to produce output \u2014 that's how results are returned to you
|
|
1670
|
+
- Write efficient scripts that do multiple things per execution when possible
|
|
1671
|
+
- For parallel async operations, use Promise.all()
|
|
1672
|
+
- Handle errors in your scripts with try/catch so you get useful error messages
|
|
1673
|
+
- Top-level await is supported`,
|
|
1674
|
+
commentsEnabled: `- Add a JSDoc @fileoverview comment at the top of each script explaining what it does
|
|
1675
|
+
- Add brief JSDoc @param comments for any functions you define`,
|
|
1676
|
+
commentsDisabled: `- Do NOT write any comments in your code \u2014 save tokens. The code should be self-explanatory.`,
|
|
1677
|
+
packageLabel: "Available Packages",
|
|
1678
|
+
packageIntro: "These npm packages are installed and can be imported",
|
|
1679
|
+
bashExamples: "ls, grep, curl, git, npm, cat",
|
|
1680
|
+
codeBlockLang: "javascript",
|
|
1681
|
+
execToolSummary: "Run a given piece of JavaScript code. Use when you already have code to run \u2014 e.g., from a previous write_code call, re-running a snippet, or executing user-provided code.",
|
|
1682
|
+
writeRunToolSummary: "Write a fresh solution from scratch and execute it in one step. The autonomous, end-to-end tool for solving problems with code."
|
|
1683
|
+
},
|
|
1684
|
+
python: {
|
|
1685
|
+
toolDescExecute: "Execute a given piece of Python code in a child process. Use this when you already have code to run \u2014 e.g., running code from a previous write_code call, re-running a snippet, or executing code the user provided. Use print() for output.",
|
|
1686
|
+
toolDescWriteAndRun: "Write a fresh Python solution from scratch and execute it in one step. Use this when you need to figure out the code AND run it \u2014 the autonomous, end-to-end tool for solving problems with code.",
|
|
1687
|
+
codeParamDesc: "Python code to execute. Use print() for output.",
|
|
1688
|
+
codeRules: `- Your code runs in a Python 3 child process
|
|
1689
|
+
- Use print() to produce output \u2014 that's how results are returned to you
|
|
1690
|
+
- Use standard Python imports (import os, import json, from pathlib import Path, etc.)
|
|
1691
|
+
- Write efficient scripts; prefer list comprehensions and built-in functions
|
|
1692
|
+
- For async operations, use asyncio
|
|
1693
|
+
- Handle errors with try/except so you get useful error messages
|
|
1694
|
+
- A virtual environment is active \u2014 you can install packages using run_bash with: pip install <package>
|
|
1695
|
+
- Installed packages persist across executions in this session`,
|
|
1696
|
+
commentsEnabled: `- Add a module-level docstring at the top of each script explaining what it does
|
|
1697
|
+
- Add brief docstrings for any functions you define`,
|
|
1698
|
+
commentsDisabled: `- Do NOT write any comments in your code \u2014 save tokens. The code should be self-explanatory.`,
|
|
1699
|
+
packageLabel: "Available Packages",
|
|
1700
|
+
packageIntro: "These Python packages are available for import",
|
|
1701
|
+
bashExamples: "ls, grep, curl, git, pip, cat",
|
|
1702
|
+
codeBlockLang: "python",
|
|
1703
|
+
execToolSummary: "Run a given piece of Python code. Use when you already have code to run \u2014 e.g., from a previous write_code call, re-running a snippet, or executing user-provided code.",
|
|
1704
|
+
writeRunToolSummary: "Write a fresh Python solution from scratch and execute it in one step. The autonomous, end-to-end tool for solving problems with code."
|
|
1705
|
+
}
|
|
1706
|
+
};
|
|
1630
1707
|
var EXECUTING_TOOLS = /* @__PURE__ */ new Set(["execute_code", "write_and_run_code", "run_bash"]);
|
|
1631
1708
|
var CodeAgent = class extends base_default {
|
|
1632
1709
|
/**
|
|
@@ -1638,6 +1715,8 @@ var CodeAgent = class extends base_default {
|
|
|
1638
1715
|
}
|
|
1639
1716
|
super(options);
|
|
1640
1717
|
this.workingDirectory = options.workingDirectory || process.cwd();
|
|
1718
|
+
this.language = options.language || "javascript";
|
|
1719
|
+
this.pythonPath = options.pythonPath || null;
|
|
1641
1720
|
this.maxRounds = options.maxRounds || 10;
|
|
1642
1721
|
this.timeout = options.timeout || 3e4;
|
|
1643
1722
|
this.onBeforeExecution = options.onBeforeExecution || null;
|
|
@@ -1649,6 +1728,9 @@ var CodeAgent = class extends base_default {
|
|
|
1649
1728
|
this.maxRetries = options.maxRetries ?? 3;
|
|
1650
1729
|
this.skills = options.skills || [];
|
|
1651
1730
|
this.envOverview = options.envOverview || "";
|
|
1731
|
+
this._pythonBinary = null;
|
|
1732
|
+
this._venvPath = null;
|
|
1733
|
+
this._venvEnv = null;
|
|
1652
1734
|
this.customTools = (options.tools || []).map((t) => ({
|
|
1653
1735
|
name: t.name,
|
|
1654
1736
|
description: t.description,
|
|
@@ -1677,6 +1759,7 @@ var CodeAgent = class extends base_default {
|
|
|
1677
1759
|
* @returns {{ functionDeclarations: Array<Object> }}
|
|
1678
1760
|
*/
|
|
1679
1761
|
_buildToolDefinitions() {
|
|
1762
|
+
const lang = LANG_CONFIG[this.language] || LANG_CONFIG.javascript;
|
|
1680
1763
|
const declarations = [
|
|
1681
1764
|
{
|
|
1682
1765
|
name: "write_code",
|
|
@@ -1693,11 +1776,11 @@ var CodeAgent = class extends base_default {
|
|
|
1693
1776
|
},
|
|
1694
1777
|
{
|
|
1695
1778
|
name: "execute_code",
|
|
1696
|
-
description:
|
|
1779
|
+
description: lang.toolDescExecute,
|
|
1697
1780
|
parametersJsonSchema: {
|
|
1698
1781
|
type: "object",
|
|
1699
1782
|
properties: {
|
|
1700
|
-
code: { type: "string", description:
|
|
1783
|
+
code: { type: "string", description: lang.codeParamDesc },
|
|
1701
1784
|
purpose: { type: "string", description: 'A short 2-4 word slug describing what this script does (e.g., "read-config", "parse-logs").' }
|
|
1702
1785
|
},
|
|
1703
1786
|
required: ["code"]
|
|
@@ -1705,11 +1788,11 @@ var CodeAgent = class extends base_default {
|
|
|
1705
1788
|
},
|
|
1706
1789
|
{
|
|
1707
1790
|
name: "write_and_run_code",
|
|
1708
|
-
description:
|
|
1791
|
+
description: lang.toolDescWriteAndRun,
|
|
1709
1792
|
parametersJsonSchema: {
|
|
1710
1793
|
type: "object",
|
|
1711
1794
|
properties: {
|
|
1712
|
-
code: { type: "string", description:
|
|
1795
|
+
code: { type: "string", description: lang.codeParamDesc },
|
|
1713
1796
|
purpose: { type: "string", description: 'A short 2-4 word slug describing what this script does (e.g., "fetch-api-data", "generate-report").' }
|
|
1714
1797
|
},
|
|
1715
1798
|
required: ["code"]
|
|
@@ -1731,7 +1814,7 @@ var CodeAgent = class extends base_default {
|
|
|
1731
1814
|
},
|
|
1732
1815
|
{
|
|
1733
1816
|
name: "run_bash",
|
|
1734
|
-
description:
|
|
1817
|
+
description: `Execute a shell command in the working directory. Use this for file operations, git commands, installing packages, or any shell task (e.g., ${lang.bashExamples}). Prefer this over execute_code for simple shell operations.`,
|
|
1735
1818
|
parametersJsonSchema: {
|
|
1736
1819
|
type: "object",
|
|
1737
1820
|
properties: {
|
|
@@ -1770,6 +1853,10 @@ var CodeAgent = class extends base_default {
|
|
|
1770
1853
|
if (this.skills.length > 0 && (this._skillRegistry.size === 0 || force)) {
|
|
1771
1854
|
await this._loadSkills();
|
|
1772
1855
|
}
|
|
1856
|
+
if (this.language === "python" && (!this._pythonBinary || force)) {
|
|
1857
|
+
await this._resolvePython();
|
|
1858
|
+
await this._setupVenv();
|
|
1859
|
+
}
|
|
1773
1860
|
this.chatConfig.tools = [this._buildToolDefinitions()];
|
|
1774
1861
|
if (!this._contextGathered || force) {
|
|
1775
1862
|
await this._gatherCodebaseContext();
|
|
@@ -1797,6 +1884,70 @@ var CodeAgent = class extends base_default {
|
|
|
1797
1884
|
}
|
|
1798
1885
|
}
|
|
1799
1886
|
}
|
|
1887
|
+
// ── Python Resolution ───────────────────────────────────────────────────
|
|
1888
|
+
/**
|
|
1889
|
+
* Resolve the Python 3 binary path.
|
|
1890
|
+
* @private
|
|
1891
|
+
*/
|
|
1892
|
+
async _resolvePython() {
|
|
1893
|
+
const tryBinary = (bin) => new Promise((resolve2) => {
|
|
1894
|
+
(0, import_node_child_process.execFile)(bin, ["--version"], { timeout: 5e3 }, (err, stdout, stderr) => {
|
|
1895
|
+
if (err) return resolve2(null);
|
|
1896
|
+
const output = (stdout || "") + (stderr || "");
|
|
1897
|
+
if (output.includes("Python 3.")) return resolve2(bin);
|
|
1898
|
+
resolve2(null);
|
|
1899
|
+
});
|
|
1900
|
+
});
|
|
1901
|
+
if (this.pythonPath) {
|
|
1902
|
+
const result = await tryBinary(this.pythonPath);
|
|
1903
|
+
if (result) {
|
|
1904
|
+
this._pythonBinary = result;
|
|
1905
|
+
return;
|
|
1906
|
+
}
|
|
1907
|
+
throw new Error(`CodeAgent: pythonPath "${this.pythonPath}" is not a valid Python 3 binary.`);
|
|
1908
|
+
}
|
|
1909
|
+
const python3 = await tryBinary("python3");
|
|
1910
|
+
if (python3) {
|
|
1911
|
+
this._pythonBinary = python3;
|
|
1912
|
+
return;
|
|
1913
|
+
}
|
|
1914
|
+
const python = await tryBinary("python");
|
|
1915
|
+
if (python) {
|
|
1916
|
+
this._pythonBinary = python;
|
|
1917
|
+
return;
|
|
1918
|
+
}
|
|
1919
|
+
throw new Error('CodeAgent: language is "python" but python3 was not found on PATH. Install Python 3 or provide the pythonPath option.');
|
|
1920
|
+
}
|
|
1921
|
+
/**
|
|
1922
|
+
* Create a virtual environment for Python execution.
|
|
1923
|
+
* @private
|
|
1924
|
+
*/
|
|
1925
|
+
async _setupVenv() {
|
|
1926
|
+
await (0, import_promises2.mkdir)(this.writeDir, { recursive: true });
|
|
1927
|
+
this._venvPath = (0, import_node_path.join)(this.writeDir, ".venv");
|
|
1928
|
+
const isWin = process.platform === "win32";
|
|
1929
|
+
const venvBin = isWin ? (0, import_node_path.join)(this._venvPath, "Scripts") : (0, import_node_path.join)(this._venvPath, "bin");
|
|
1930
|
+
const venvPython = (0, import_node_path.join)(venvBin, isWin ? "python.exe" : "python");
|
|
1931
|
+
try {
|
|
1932
|
+
await (0, import_promises2.readFile)(venvPython);
|
|
1933
|
+
} catch {
|
|
1934
|
+
logger_default.debug(`Creating Python venv at ${this._venvPath}`);
|
|
1935
|
+
await new Promise((resolve2, reject) => {
|
|
1936
|
+
(0, import_node_child_process.execFile)(this._pythonBinary, ["-m", "venv", this._venvPath], {
|
|
1937
|
+
timeout: 3e4
|
|
1938
|
+
}, (err) => {
|
|
1939
|
+
if (err) return reject(new Error(`CodeAgent: failed to create venv: ${err.message}`));
|
|
1940
|
+
resolve2();
|
|
1941
|
+
});
|
|
1942
|
+
});
|
|
1943
|
+
}
|
|
1944
|
+
const env = Object.assign({}, process.env);
|
|
1945
|
+
env.VIRTUAL_ENV = this._venvPath;
|
|
1946
|
+
env.PATH = venvBin + (isWin ? ";" : ":") + (process.env.PATH || "");
|
|
1947
|
+
this._venvEnv = env;
|
|
1948
|
+
this._pythonBinary = venvPython;
|
|
1949
|
+
logger_default.debug(`Python venv ready at ${this._venvPath}`);
|
|
1950
|
+
}
|
|
1800
1951
|
// ── Context Gathering ────────────────────────────────────────────────────
|
|
1801
1952
|
/**
|
|
1802
1953
|
* @private
|
|
@@ -1815,15 +1966,35 @@ var CodeAgent = class extends base_default {
|
|
|
1815
1966
|
fileTree = `${truncated}
|
|
1816
1967
|
... (${lines.length - MAX_FILE_TREE_LINES} more files)`;
|
|
1817
1968
|
}
|
|
1818
|
-
let
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1969
|
+
let packages = [];
|
|
1970
|
+
if (this.language === "python") {
|
|
1971
|
+
try {
|
|
1972
|
+
const reqPath = (0, import_node_path.join)(this.workingDirectory, "requirements.txt");
|
|
1973
|
+
const content = await (0, import_promises2.readFile)(reqPath, "utf-8");
|
|
1974
|
+
packages = content.split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("#") && !l.startsWith("-")).map((l) => l.split(/[>=<!\[;\s]/)[0]);
|
|
1975
|
+
} catch {
|
|
1976
|
+
}
|
|
1977
|
+
if (packages.length === 0) {
|
|
1978
|
+
try {
|
|
1979
|
+
const ppPath = (0, import_node_path.join)(this.workingDirectory, "pyproject.toml");
|
|
1980
|
+
const content = await (0, import_promises2.readFile)(ppPath, "utf-8");
|
|
1981
|
+
const depMatch = content.match(/dependencies\s*=\s*\[([\s\S]*?)\]/);
|
|
1982
|
+
if (depMatch) {
|
|
1983
|
+
packages = (depMatch[1].match(/"([^"]+)"/g) || []).map((s) => s.replace(/"/g, "").split(/[>=<!\[;\s]/)[0]);
|
|
1984
|
+
}
|
|
1985
|
+
} catch {
|
|
1986
|
+
}
|
|
1987
|
+
}
|
|
1988
|
+
} else {
|
|
1989
|
+
try {
|
|
1990
|
+
const pkgPath = (0, import_node_path.join)(this.workingDirectory, "package.json");
|
|
1991
|
+
const pkg = JSON.parse(await (0, import_promises2.readFile)(pkgPath, "utf-8"));
|
|
1992
|
+
packages = [
|
|
1993
|
+
...Object.keys(pkg.dependencies || {}),
|
|
1994
|
+
...Object.keys(pkg.devDependencies || {})
|
|
1995
|
+
];
|
|
1996
|
+
} catch {
|
|
1997
|
+
}
|
|
1827
1998
|
}
|
|
1828
1999
|
const importantFileContents = [];
|
|
1829
2000
|
if (this.importantFiles.length > 0) {
|
|
@@ -1843,7 +2014,7 @@ var CodeAgent = class extends base_default {
|
|
|
1843
2014
|
}
|
|
1844
2015
|
}
|
|
1845
2016
|
}
|
|
1846
|
-
this._codebaseContext = { fileTree, npmPackages, importantFileContents };
|
|
2017
|
+
this._codebaseContext = { fileTree, npmPackages: packages, packages, importantFileContents };
|
|
1847
2018
|
this._contextGathered = true;
|
|
1848
2019
|
}
|
|
1849
2020
|
/**
|
|
@@ -1901,7 +2072,8 @@ var CodeAgent = class extends base_default {
|
|
|
1901
2072
|
* @private
|
|
1902
2073
|
*/
|
|
1903
2074
|
_buildSystemPrompt() {
|
|
1904
|
-
const { fileTree,
|
|
2075
|
+
const { fileTree, packages, importantFileContents } = this._codebaseContext || { fileTree: "", packages: [], importantFileContents: [] };
|
|
2076
|
+
const lang = LANG_CONFIG[this.language] || LANG_CONFIG.javascript;
|
|
1905
2077
|
let prompt = `You are a coding agent working in ${this.workingDirectory}.
|
|
1906
2078
|
|
|
1907
2079
|
## Available Tools
|
|
@@ -1910,16 +2082,16 @@ var CodeAgent = class extends base_default {
|
|
|
1910
2082
|
Output code without executing it. Use when showing, proposing, or presenting code to the user.
|
|
1911
2083
|
|
|
1912
2084
|
### execute_code
|
|
1913
|
-
|
|
2085
|
+
${lang.execToolSummary}
|
|
1914
2086
|
|
|
1915
2087
|
### write_and_run_code
|
|
1916
|
-
|
|
2088
|
+
${lang.writeRunToolSummary}
|
|
1917
2089
|
|
|
1918
2090
|
### fix_code
|
|
1919
2091
|
Fix broken code by providing original and fixed versions. Set execute=true to verify the fix works.
|
|
1920
2092
|
|
|
1921
2093
|
### run_bash
|
|
1922
|
-
Run shell commands directly (e.g.,
|
|
2094
|
+
Run shell commands directly (e.g., ${lang.bashExamples}). Prefer this over execute_code for simple shell operations.`;
|
|
1923
2095
|
if (this._skillRegistry.size > 0) {
|
|
1924
2096
|
prompt += `
|
|
1925
2097
|
|
|
@@ -1931,24 +2103,14 @@ Load a skill by name to get detailed instructions and templates. Available skill
|
|
|
1931
2103
|
## Code Execution Rules
|
|
1932
2104
|
These rules apply when using execute_code, write_and_run_code, or fix_code (with execute=true):
|
|
1933
2105
|
- Always provide a short descriptive \`purpose\` parameter (2-4 word slug like "read-config")
|
|
1934
|
-
|
|
1935
|
-
- IMPORTANT: Your code runs as an ES module (.mjs). Use import syntax, NOT require():
|
|
1936
|
-
- import fs from 'fs';
|
|
1937
|
-
- import path from 'path';
|
|
1938
|
-
- import { execSync } from 'child_process';
|
|
1939
|
-
- Use console.log() to produce output \u2014 that's how results are returned to you
|
|
1940
|
-
- Write efficient scripts that do multiple things per execution when possible
|
|
1941
|
-
- For parallel async operations, use Promise.all()
|
|
1942
|
-
- Handle errors in your scripts with try/catch so you get useful error messages
|
|
1943
|
-
- Top-level await is supported
|
|
2106
|
+
${lang.codeRules}
|
|
1944
2107
|
- The working directory is: ${this.workingDirectory}`;
|
|
1945
2108
|
if (this.comments) {
|
|
1946
2109
|
prompt += `
|
|
1947
|
-
|
|
1948
|
-
- Add brief JSDoc @param comments for any functions you define`;
|
|
2110
|
+
${lang.commentsEnabled}`;
|
|
1949
2111
|
} else {
|
|
1950
2112
|
prompt += `
|
|
1951
|
-
|
|
2113
|
+
${lang.commentsDisabled}`;
|
|
1952
2114
|
}
|
|
1953
2115
|
if (fileTree) {
|
|
1954
2116
|
prompt += `
|
|
@@ -1958,11 +2120,11 @@ These rules apply when using execute_code, write_and_run_code, or fix_code (with
|
|
|
1958
2120
|
${fileTree}
|
|
1959
2121
|
\`\`\``;
|
|
1960
2122
|
}
|
|
1961
|
-
if (
|
|
2123
|
+
if (packages && packages.length > 0) {
|
|
1962
2124
|
prompt += `
|
|
1963
2125
|
|
|
1964
|
-
##
|
|
1965
|
-
|
|
2126
|
+
## ${lang.packageLabel}
|
|
2127
|
+
${lang.packageIntro}: ${packages.join(", ")}`;
|
|
1966
2128
|
}
|
|
1967
2129
|
if (importantFileContents && importantFileContents.length > 0) {
|
|
1968
2130
|
prompt += `
|
|
@@ -1972,7 +2134,7 @@ These npm packages are installed and can be imported: ${npmPackages.join(", ")}`
|
|
|
1972
2134
|
prompt += `
|
|
1973
2135
|
|
|
1974
2136
|
### ${filePath}
|
|
1975
|
-
|
|
2137
|
+
\`\`\`${lang.codeBlockLang}
|
|
1976
2138
|
${content}
|
|
1977
2139
|
\`\`\``;
|
|
1978
2140
|
}
|
|
@@ -2018,14 +2180,17 @@ ${this.envOverview}`;
|
|
|
2018
2180
|
}
|
|
2019
2181
|
await (0, import_promises2.mkdir)(this.writeDir, { recursive: true });
|
|
2020
2182
|
const slug = this._slugify(purpose);
|
|
2021
|
-
const
|
|
2183
|
+
const ext = this.language === "python" ? ".py" : ".mjs";
|
|
2184
|
+
const tempFile = (0, import_node_path.join)(this.writeDir, `agent-${slug}-${Date.now()}${ext}`);
|
|
2022
2185
|
try {
|
|
2023
2186
|
await (0, import_promises2.writeFile)(tempFile, code, "utf-8");
|
|
2187
|
+
const binary = this.language === "python" ? this._pythonBinary : "node";
|
|
2188
|
+
const execEnv = this.language === "python" && this._venvEnv ? this._venvEnv : process.env;
|
|
2024
2189
|
const result = await new Promise((resolve2) => {
|
|
2025
|
-
const child = (0, import_node_child_process.execFile)(
|
|
2190
|
+
const child = (0, import_node_child_process.execFile)(binary, [tempFile], {
|
|
2026
2191
|
cwd: this.workingDirectory,
|
|
2027
2192
|
timeout: this.timeout,
|
|
2028
|
-
env:
|
|
2193
|
+
env: execEnv,
|
|
2029
2194
|
maxBuffer: 10 * 1024 * 1024
|
|
2030
2195
|
}, (err, stdout, stderr) => {
|
|
2031
2196
|
this._activeProcess = null;
|
|
@@ -2096,11 +2261,12 @@ ${this.envOverview}`;
|
|
|
2096
2261
|
logger_default.warn(`onBeforeExecution callback error: ${e.message}`);
|
|
2097
2262
|
}
|
|
2098
2263
|
}
|
|
2264
|
+
const execEnv = this.language === "python" && this._venvEnv ? this._venvEnv : process.env;
|
|
2099
2265
|
const result = await new Promise((resolve2) => {
|
|
2100
2266
|
const child = (0, import_node_child_process.execFile)("bash", ["-c", command], {
|
|
2101
2267
|
cwd: this.workingDirectory,
|
|
2102
2268
|
timeout: this.timeout,
|
|
2103
|
-
env:
|
|
2269
|
+
env: execEnv,
|
|
2104
2270
|
maxBuffer: 10 * 1024 * 1024
|
|
2105
2271
|
}, (err, stdout, stderr) => {
|
|
2106
2272
|
this._activeProcess = null;
|
|
@@ -2480,8 +2646,9 @@ ${this.envOverview}`;
|
|
|
2480
2646
|
* @returns {Array<{fileName: string, purpose: string|null, script: string, filePath: string|null, tool: string}>}
|
|
2481
2647
|
*/
|
|
2482
2648
|
dump() {
|
|
2649
|
+
const ext = this.language === "python" ? ".py" : ".mjs";
|
|
2483
2650
|
return this._allExecutions.map((exec, i) => ({
|
|
2484
|
-
fileName: exec.purpose ? `agent-${exec.purpose}
|
|
2651
|
+
fileName: exec.purpose ? `agent-${exec.purpose}${ext}` : `script-${i + 1}${ext}`,
|
|
2485
2652
|
purpose: exec.purpose || null,
|
|
2486
2653
|
script: exec.code,
|
|
2487
2654
|
filePath: exec.filePath || null,
|
|
@@ -2897,9 +3064,155 @@ var Embedding = class extends base_default {
|
|
|
2897
3064
|
}
|
|
2898
3065
|
};
|
|
2899
3066
|
|
|
3067
|
+
// image-generator.js
|
|
3068
|
+
var import_node_fs = require("node:fs");
|
|
3069
|
+
var DEFAULT_IMAGE_MODEL = "gemini-3.1-flash-image-preview";
|
|
3070
|
+
var ImageGenerator = class extends base_default {
|
|
3071
|
+
/**
|
|
3072
|
+
* @param {import('./types.d.ts').ImageGeneratorOptions} [options={}]
|
|
3073
|
+
*/
|
|
3074
|
+
constructor(options = {}) {
|
|
3075
|
+
if (options.modelName === void 0) {
|
|
3076
|
+
options = { ...options, modelName: DEFAULT_IMAGE_MODEL };
|
|
3077
|
+
}
|
|
3078
|
+
if (options.systemPrompt === void 0) {
|
|
3079
|
+
options = { ...options, systemPrompt: null };
|
|
3080
|
+
}
|
|
3081
|
+
super(options);
|
|
3082
|
+
this.aspectRatio = options.aspectRatio || null;
|
|
3083
|
+
this.imageSize = options.imageSize || null;
|
|
3084
|
+
this.personGeneration = options.personGeneration || null;
|
|
3085
|
+
this.includeText = options.includeText ?? false;
|
|
3086
|
+
logger_default.debug(`ImageGenerator created with model: ${this.modelName}`);
|
|
3087
|
+
}
|
|
3088
|
+
/**
|
|
3089
|
+
* Validate API connection only; no chat session (stateless).
|
|
3090
|
+
* @param {boolean} [force=false]
|
|
3091
|
+
*/
|
|
3092
|
+
async init(force = false) {
|
|
3093
|
+
if (this._initialized && !force) return;
|
|
3094
|
+
logger_default.debug(`Initializing ${this.constructor.name} with model: ${this.modelName}...`);
|
|
3095
|
+
try {
|
|
3096
|
+
await this.genAIClient.models.list();
|
|
3097
|
+
logger_default.debug(`${this.constructor.name}: API connection successful.`);
|
|
3098
|
+
} catch (e) {
|
|
3099
|
+
throw new Error(`${this.constructor.name} initialization failed: ${e.message}`);
|
|
3100
|
+
}
|
|
3101
|
+
this._initialized = true;
|
|
3102
|
+
}
|
|
3103
|
+
/**
|
|
3104
|
+
* Build a FRESH config — Gemini image models reject safetySettings/temp/topK/topP/thinkingConfig.
|
|
3105
|
+
* Do NOT spread this.chatConfig.
|
|
3106
|
+
* @private
|
|
3107
|
+
*/
|
|
3108
|
+
_buildConfig(overrides = {}) {
|
|
3109
|
+
const includeText = overrides.includeText ?? this.includeText;
|
|
3110
|
+
const config = { responseModalities: includeText ? ["IMAGE", "TEXT"] : ["IMAGE"] };
|
|
3111
|
+
const imageConfig = {};
|
|
3112
|
+
const aspectRatio = overrides.aspectRatio || this.aspectRatio;
|
|
3113
|
+
const imageSize = overrides.imageSize || this.imageSize;
|
|
3114
|
+
const personGeneration = overrides.personGeneration || this.personGeneration;
|
|
3115
|
+
if (aspectRatio) imageConfig.aspectRatio = aspectRatio;
|
|
3116
|
+
if (imageSize) imageConfig.imageSize = imageSize;
|
|
3117
|
+
if (personGeneration) imageConfig.personGeneration = personGeneration;
|
|
3118
|
+
if (Object.keys(imageConfig).length > 0) config.imageConfig = imageConfig;
|
|
3119
|
+
return config;
|
|
3120
|
+
}
|
|
3121
|
+
/**
|
|
3122
|
+
* Generate one or more images from a text prompt.
|
|
3123
|
+
* Optionally accepts `inputImages` for image editing / multi-image composition.
|
|
3124
|
+
*
|
|
3125
|
+
* @param {string} prompt
|
|
3126
|
+
* @param {import('./types.d.ts').ImageGenerateOptions} [opts={}]
|
|
3127
|
+
* @returns {Promise<import('./types.d.ts').ImageGenerationResult>}
|
|
3128
|
+
*/
|
|
3129
|
+
async generate(prompt, opts = {}) {
|
|
3130
|
+
if (!this._initialized) await this.init();
|
|
3131
|
+
const parts = [{ text: prompt }];
|
|
3132
|
+
if (Array.isArray(opts.inputImages)) {
|
|
3133
|
+
for (const img of opts.inputImages) {
|
|
3134
|
+
parts.push({ inlineData: { data: img.data, mimeType: img.mimeType } });
|
|
3135
|
+
}
|
|
3136
|
+
}
|
|
3137
|
+
const result = await this._withRetry(() => this.genAIClient.models.generateContent({
|
|
3138
|
+
model: this.modelName,
|
|
3139
|
+
contents: [{ role: "user", parts }],
|
|
3140
|
+
config: this._buildConfig(opts)
|
|
3141
|
+
}));
|
|
3142
|
+
this._captureMetadata(result);
|
|
3143
|
+
this._cumulativeUsage = {
|
|
3144
|
+
promptTokens: this.lastResponseMetadata.promptTokens,
|
|
3145
|
+
responseTokens: this.lastResponseMetadata.responseTokens,
|
|
3146
|
+
totalTokens: this.lastResponseMetadata.totalTokens,
|
|
3147
|
+
attempts: 1
|
|
3148
|
+
};
|
|
3149
|
+
const images = [];
|
|
3150
|
+
let text = "";
|
|
3151
|
+
const responseParts = result.candidates?.[0]?.content?.parts || [];
|
|
3152
|
+
for (const part of responseParts) {
|
|
3153
|
+
if (part.inlineData?.data) {
|
|
3154
|
+
images.push({
|
|
3155
|
+
data: part.inlineData.data,
|
|
3156
|
+
mimeType: part.inlineData.mimeType || "image/png"
|
|
3157
|
+
});
|
|
3158
|
+
} else if (part.text) {
|
|
3159
|
+
text += part.text;
|
|
3160
|
+
}
|
|
3161
|
+
}
|
|
3162
|
+
if (images.length === 0) {
|
|
3163
|
+
logger_default.warn("ImageGenerator: no images returned. Check prompt or safety filters.");
|
|
3164
|
+
}
|
|
3165
|
+
return { images, text: text || null, usage: this.getLastUsage() };
|
|
3166
|
+
}
|
|
3167
|
+
/**
|
|
3168
|
+
* Convenience: write one or all images to disk.
|
|
3169
|
+
* If multiple images, suffixes with `_N` before extension.
|
|
3170
|
+
* @param {import('./types.d.ts').ImageGenerationResult} result
|
|
3171
|
+
* @param {string} filePath
|
|
3172
|
+
* @returns {string[]} Written file paths
|
|
3173
|
+
*/
|
|
3174
|
+
save(result, filePath) {
|
|
3175
|
+
if (!result?.images?.length) {
|
|
3176
|
+
logger_default.warn("ImageGenerator.save(): no images to save.");
|
|
3177
|
+
return [];
|
|
3178
|
+
}
|
|
3179
|
+
const paths = [];
|
|
3180
|
+
const dot = filePath.lastIndexOf(".");
|
|
3181
|
+
const base = dot >= 0 ? filePath.slice(0, dot) : filePath;
|
|
3182
|
+
const ext = dot >= 0 ? filePath.slice(dot) : ".png";
|
|
3183
|
+
result.images.forEach((img, i) => {
|
|
3184
|
+
const out = result.images.length === 1 ? filePath : `${base}_${i}${ext}`;
|
|
3185
|
+
(0, import_node_fs.writeFileSync)(out, Buffer.from(img.data, "base64"));
|
|
3186
|
+
paths.push(out);
|
|
3187
|
+
});
|
|
3188
|
+
return paths;
|
|
3189
|
+
}
|
|
3190
|
+
// ── No-ops (image gen is stateless) ──
|
|
3191
|
+
/** @returns {any[]} Always returns empty array */
|
|
3192
|
+
getHistory() {
|
|
3193
|
+
return [];
|
|
3194
|
+
}
|
|
3195
|
+
/** No-op for ImageGenerator */
|
|
3196
|
+
async clearHistory() {
|
|
3197
|
+
}
|
|
3198
|
+
/** No-op for ImageGenerator */
|
|
3199
|
+
async seed() {
|
|
3200
|
+
logger_default.warn("ImageGenerator.seed() is a no-op \u2014 image generation does not support few-shot.");
|
|
3201
|
+
return [];
|
|
3202
|
+
}
|
|
3203
|
+
/**
|
|
3204
|
+
* @param {any} _nextPayload
|
|
3205
|
+
* @throws {Error} ImageGenerator does not support token estimation
|
|
3206
|
+
* @returns {Promise<{ inputTokens: number }>}
|
|
3207
|
+
*/
|
|
3208
|
+
async estimate(_nextPayload) {
|
|
3209
|
+
throw new Error("ImageGenerator does not support token estimation. Use generate() directly.");
|
|
3210
|
+
}
|
|
3211
|
+
};
|
|
3212
|
+
|
|
2900
3213
|
// index.js
|
|
2901
3214
|
var import_genai2 = require("@google/genai");
|
|
2902
|
-
var index_default = { Transformer: transformer_default, Chat: chat_default, Message: message_default, ToolAgent: tool_agent_default, CodeAgent: code_agent_default, RagAgent: rag_agent_default, Embedding };
|
|
3215
|
+
var index_default = { Transformer: transformer_default, Chat: chat_default, Message: message_default, ToolAgent: tool_agent_default, CodeAgent: code_agent_default, RagAgent: rag_agent_default, Embedding, ImageGenerator };
|
|
2903
3216
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2904
3217
|
0 && (module.exports = {
|
|
2905
3218
|
BaseGemini,
|
|
@@ -2908,6 +3221,7 @@ var index_default = { Transformer: transformer_default, Chat: chat_default, Mess
|
|
|
2908
3221
|
Embedding,
|
|
2909
3222
|
HarmBlockThreshold,
|
|
2910
3223
|
HarmCategory,
|
|
3224
|
+
ImageGenerator,
|
|
2911
3225
|
Message,
|
|
2912
3226
|
RagAgent,
|
|
2913
3227
|
ThinkingLevel,
|
package/index.js
CHANGED
|
@@ -27,6 +27,7 @@ export { default as ToolAgent } from './tool-agent.js';
|
|
|
27
27
|
export { default as CodeAgent } from './code-agent.js';
|
|
28
28
|
export { default as RagAgent } from './rag-agent.js';
|
|
29
29
|
export { default as Embedding } from './embedding.js';
|
|
30
|
+
export { default as ImageGenerator } from './image-generator.js';
|
|
30
31
|
export { default as BaseGemini } from './base.js';
|
|
31
32
|
export { default as log } from './logger.js';
|
|
32
33
|
export { ThinkingLevel, HarmCategory, HarmBlockThreshold } from '@google/genai';
|
|
@@ -41,5 +42,6 @@ import ToolAgent from './tool-agent.js';
|
|
|
41
42
|
import CodeAgent from './code-agent.js';
|
|
42
43
|
import RagAgent from './rag-agent.js';
|
|
43
44
|
import Embedding from './embedding.js';
|
|
45
|
+
import ImageGenerator from './image-generator.js';
|
|
44
46
|
|
|
45
|
-
export default { Transformer, Chat, Message, ToolAgent, CodeAgent, RagAgent, Embedding };
|
|
47
|
+
export default { Transformer, Chat, Message, ToolAgent, CodeAgent, RagAgent, Embedding, ImageGenerator };
|