evoltagent 1.1.2 → 1.1.4

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/dist/index.js CHANGED
@@ -279,9 +279,96 @@ function escapeRegExp(string) {
279
279
  return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
280
280
  }
281
281
 
282
+ // src/utils/deprecated.ts
283
+ function deprecated(options = {}) {
284
+ return function(target, propertyKey, descriptor) {
285
+ const original = descriptor.value;
286
+ descriptor.value = function(...args) {
287
+ const parts = [`${propertyKey} is deprecated`];
288
+ if (options.version) {
289
+ parts.push(`will be removed in ${options.version}`);
290
+ }
291
+ if (options.replacement) {
292
+ parts.push(`use ${options.replacement} instead`);
293
+ }
294
+ console.warn(parts.join(", "));
295
+ return original.apply(this, args);
296
+ };
297
+ return descriptor;
298
+ };
299
+ }
300
+
301
+ // src/utils/readImage.ts
302
+ import * as fs from "fs";
303
+ import * as path from "path";
304
+ var MIME_TYPES = {
305
+ ".jpg": "image/jpeg",
306
+ ".jpeg": "image/jpeg",
307
+ ".png": "image/png",
308
+ ".gif": "image/gif",
309
+ ".webp": "image/webp"
310
+ };
311
+ var SUPPORTED_FORMATS = /* @__PURE__ */ new Set([".jpg", ".jpeg", ".png", ".gif", ".webp"]);
312
+ function getMimeType(pathOrUrl) {
313
+ const cleanPath = pathOrUrl.split("?")[0];
314
+ const ext = path.extname(cleanPath).toLowerCase();
315
+ return MIME_TYPES[ext] || "image/jpeg";
316
+ }
317
+ function isSupportedImageFile(imagePath) {
318
+ const cleanPath = imagePath.split("?")[0];
319
+ const ext = path.extname(cleanPath).toLowerCase();
320
+ return SUPPORTED_FORMATS.has(ext);
321
+ }
322
+ async function fetchUrl(url) {
323
+ const response = await fetch(url, {
324
+ signal: AbortSignal.timeout(3e4)
325
+ });
326
+ if (!response.ok) {
327
+ throw new Error(`Failed to fetch image from ${url}: ${response.statusText}`);
328
+ }
329
+ const arrayBuffer = await response.arrayBuffer();
330
+ return Buffer.from(arrayBuffer);
331
+ }
332
+ function readImage(imagePath) {
333
+ const mimeType = getMimeType(imagePath);
334
+ let content;
335
+ if (imagePath.startsWith("http://") || imagePath.startsWith("https://")) {
336
+ throw new Error("Synchronous URL fetching is not supported. Use areadImage instead.");
337
+ } else {
338
+ if (!fs.existsSync(imagePath)) {
339
+ throw new Error(`Image file not found: ${imagePath}`);
340
+ }
341
+ content = fs.readFileSync(imagePath);
342
+ }
343
+ const b64Content = content.toString("base64");
344
+ const dataUrl = `data:${mimeType};base64,${b64Content}`;
345
+ return {
346
+ type: "image_url",
347
+ image_url: { url: dataUrl }
348
+ };
349
+ }
350
+ async function areadImage(imagePath) {
351
+ const mimeType = getMimeType(imagePath);
352
+ let content;
353
+ if (imagePath.startsWith("http://") || imagePath.startsWith("https://")) {
354
+ content = await fetchUrl(imagePath);
355
+ } else {
356
+ if (!fs.existsSync(imagePath)) {
357
+ throw new Error(`Image file not found: ${imagePath}`);
358
+ }
359
+ content = await fs.promises.readFile(imagePath);
360
+ }
361
+ const b64Content = content.toString("base64");
362
+ const dataUrl = `data:${mimeType};base64,${b64Content}`;
363
+ return {
364
+ type: "image_url",
365
+ image_url: { url: dataUrl }
366
+ };
367
+ }
368
+
282
369
  // src/utils/logger.ts
283
370
  import * as winston from "winston";
284
- import * as fs from "fs";
371
+ import * as fs2 from "fs";
285
372
  import * as dotenv from "dotenv";
286
373
  dotenv.config();
287
374
  var getDisableLog = () => {
@@ -474,7 +561,7 @@ var streamLogger = {
474
561
  if (!getDisableLog()) {
475
562
  process.stdout.write(message);
476
563
  if (process.env.LOG_OUTPUT) {
477
- fs.appendFileSync(process.env.LOG_OUTPUT, message);
564
+ fs2.appendFileSync(process.env.LOG_OUTPUT, message);
478
565
  }
479
566
  }
480
567
  },
@@ -485,7 +572,7 @@ var streamLogger = {
485
572
  if (!getDisableLog()) {
486
573
  process.stderr.write(message);
487
574
  if (process.env.LOG_OUTPUT) {
488
- fs.appendFileSync(process.env.LOG_OUTPUT, message);
575
+ fs2.appendFileSync(process.env.LOG_OUTPUT, message);
489
576
  }
490
577
  }
491
578
  },
@@ -496,7 +583,7 @@ var streamLogger = {
496
583
  if (!getDisableLog()) {
497
584
  process.stdout.write(message + "\n");
498
585
  if (process.env.LOG_OUTPUT) {
499
- fs.appendFileSync(process.env.LOG_OUTPUT, message + "\n");
586
+ fs2.appendFileSync(process.env.LOG_OUTPUT, message + "\n");
500
587
  }
501
588
  }
502
589
  },
@@ -504,7 +591,7 @@ var streamLogger = {
504
591
  if (!getDisableLog()) {
505
592
  process.stdout.write(message);
506
593
  if (process.env.LOG_OUTPUT) {
507
- fs.appendFileSync(process.env.LOG_OUTPUT, message);
594
+ fs2.appendFileSync(process.env.LOG_OUTPUT, message);
508
595
  }
509
596
  }
510
597
  }
@@ -671,18 +758,18 @@ function createMcpConnection(config2) {
671
758
  }
672
759
 
673
760
  // src/configs/configLoader.ts
674
- import * as fs2 from "fs";
675
- import * as path from "path";
761
+ import * as fs3 from "fs";
762
+ import * as path2 from "path";
676
763
  import * as yaml from "yaml";
677
764
  function getConfigPath() {
678
- return path.join(process.env.HOME || "~", ".evolt", "config.yaml");
765
+ return path2.join(process.env.HOME || "~", ".evolt", "config.yaml");
679
766
  }
680
767
  function loadModelConfig(modelName) {
681
768
  const configPath = process.env.EVOLT_CONFIG_PATH || getConfigPath();
682
769
  let configData = {};
683
770
  try {
684
- if (fs2.existsSync(configPath)) {
685
- const fileContent = fs2.readFileSync(configPath, "utf8");
771
+ if (fs3.existsSync(configPath)) {
772
+ const fileContent = fs3.readFileSync(configPath, "utf8");
686
773
  configData = yaml.parse(fileContent);
687
774
  } else {
688
775
  logger.warn(`Config file not found at ${configPath}, using defaults`);
@@ -808,62 +895,62 @@ var LOG_LEVELS = {
808
895
  };
809
896
 
810
897
  // src/configs/paths.ts
811
- import * as path2 from "path";
812
- import * as fs3 from "fs";
898
+ import * as path3 from "path";
899
+ import * as fs4 from "fs";
813
900
  function getWorkspaceDir() {
814
- return process.env.EVOLT_WORKSPACE || path2.join(process.cwd(), "workspace");
901
+ return process.env.EVOLT_WORKSPACE || path3.join(process.cwd(), "workspace");
815
902
  }
816
903
  function getConfigDir() {
817
- return process.env.EVOLT_CONFIG_DIR || path2.join(process.cwd(), "config");
904
+ return process.env.EVOLT_CONFIG_DIR || path3.join(process.cwd(), "config");
818
905
  }
819
906
  function getLogsDir() {
820
- return process.env.EVOLT_LOGS_DIR || path2.join(getWorkspaceDir(), "logs");
907
+ return process.env.EVOLT_LOGS_DIR || path3.join(getWorkspaceDir(), "logs");
821
908
  }
822
909
  function getCacheDir() {
823
- return process.env.EVOLT_CACHE_DIR || path2.join(getWorkspaceDir(), "cache");
910
+ return process.env.EVOLT_CACHE_DIR || path3.join(getWorkspaceDir(), "cache");
824
911
  }
825
912
  function getSkillsDir() {
826
- return process.env.EVOLT_SKILLS_DIR || path2.join(getWorkspaceDir(), "skills");
913
+ return process.env.EVOLT_SKILLS_DIR || path3.join(getWorkspaceDir(), "skills");
827
914
  }
828
915
  function ensureDir(dirPath) {
829
- if (!fs3.existsSync(dirPath)) {
830
- fs3.mkdirSync(dirPath, { recursive: true });
916
+ if (!fs4.existsSync(dirPath)) {
917
+ fs4.mkdirSync(dirPath, { recursive: true });
831
918
  }
832
919
  }
833
920
  function getWorkspacePath(relativePath) {
834
921
  const workspaceDir = getWorkspaceDir();
835
922
  ensureDir(workspaceDir);
836
- return path2.join(workspaceDir, relativePath);
923
+ return path3.join(workspaceDir, relativePath);
837
924
  }
838
925
  function getConfigPath2(relativePath) {
839
926
  const configDir = getConfigDir();
840
927
  ensureDir(configDir);
841
- return path2.join(configDir, relativePath);
928
+ return path3.join(configDir, relativePath);
842
929
  }
843
930
  function isInWorkspace(filePath) {
844
931
  const workspaceDir = getWorkspaceDir();
845
- const absolutePath = path2.resolve(filePath);
846
- return absolutePath.startsWith(path2.resolve(workspaceDir));
932
+ const absolutePath = path3.resolve(filePath);
933
+ return absolutePath.startsWith(path3.resolve(workspaceDir));
847
934
  }
848
935
  function normalizePath(filePath) {
849
- return path2.normalize(filePath).replace(/\\/g, "/");
936
+ return path3.normalize(filePath).replace(/\\/g, "/");
850
937
  }
851
938
  function getFileExtension(filePath) {
852
- return path2.extname(filePath).toLowerCase();
939
+ return path3.extname(filePath).toLowerCase();
853
940
  }
854
941
  function fileExists(filePath) {
855
942
  try {
856
- return fs3.existsSync(filePath);
943
+ return fs4.existsSync(filePath);
857
944
  } catch {
858
945
  return false;
859
946
  }
860
947
  }
861
948
  function getTempFilePath(prefix = "evolt") {
862
- const tempDir = path2.join(getCacheDir(), "temp");
949
+ const tempDir = path3.join(getCacheDir(), "temp");
863
950
  ensureDir(tempDir);
864
951
  const timestamp = Date.now();
865
952
  const random = Math.random().toString(36).substring(2, 8);
866
- return path2.join(tempDir, `${prefix}_${timestamp}_${random}.tmp`);
953
+ return path3.join(tempDir, `${prefix}_${timestamp}_${random}.tmp`);
867
954
  }
868
955
  var WORKSPACE_DIR = getWorkspaceDir();
869
956
  var SKILLS_DIR = getSkillsDir();
@@ -1388,8 +1475,8 @@ var CommandLineTool = class {
1388
1475
  try {
1389
1476
  const workDir = cwd || process.cwd();
1390
1477
  try {
1391
- const fs9 = await import("fs");
1392
- if (!fs9.existsSync(workDir)) {
1478
+ const fs14 = await import("fs");
1479
+ if (!fs14.existsSync(workDir)) {
1393
1480
  return `Working directory does not exist: ${workDir}`;
1394
1481
  }
1395
1482
  } catch (error) {
@@ -1409,9 +1496,9 @@ var CommandLineTool = class {
1409
1496
  const processId = manager.registerBackgroundProcess(childProcess, command, workDir);
1410
1497
  logger.debug(`Register background process: Command: ${command}
1411
1498
  Process ID: ${processId}`);
1412
- return new Promise((resolve2) => {
1499
+ return new Promise((resolve5) => {
1413
1500
  const timeout = setTimeout(async () => {
1414
- resolve2(
1501
+ resolve5(
1415
1502
  `COMMAND: ${command}
1416
1503
  PROCESS ID: ${processId}
1417
1504
  STATUS: The process may still be executing (waited 5 seconds, not completed)
@@ -1440,11 +1527,11 @@ ${stdoutText}`);
1440
1527
  ${stderrText}`);
1441
1528
  }
1442
1529
  resultParts.push(`EXIT CODE: ${code}`);
1443
- resolve2(resultParts.join("\n\n"));
1530
+ resolve5(resultParts.join("\n\n"));
1444
1531
  });
1445
1532
  childProcess.on("error", (error) => {
1446
1533
  clearTimeout(timeout);
1447
- resolve2(`COMMAND: ${command}
1534
+ resolve5(`COMMAND: ${command}
1448
1535
  ERROR: ${error.message}`);
1449
1536
  });
1450
1537
  });
@@ -1543,22 +1630,22 @@ CommandLineTool = __decorateClass([
1543
1630
  ], CommandLineTool);
1544
1631
 
1545
1632
  // src/tools/fileTool.ts
1546
- import * as fs4 from "fs/promises";
1633
+ import * as fs5 from "fs/promises";
1547
1634
  import * as pathModule from "path";
1548
1635
  var FileEditor = class {
1549
- async read(path5, lineRange = "all") {
1636
+ async read(path10, lineRange = "all") {
1550
1637
  try {
1551
- await fs4.access(path5);
1638
+ await fs5.access(path10);
1552
1639
  } catch {
1553
- throw new ToolExecutionError(`File does not exist: ${path5}`);
1640
+ throw new ToolExecutionError(`File does not exist: ${path10}`);
1554
1641
  }
1555
1642
  try {
1556
1643
  let content;
1557
1644
  try {
1558
- content = await fs4.readFile(path5, "utf-8");
1645
+ content = await fs5.readFile(path10, "utf-8");
1559
1646
  } catch (error) {
1560
1647
  if (error.code === "ENCODING_NOT_SUPPORTED" || error.message.includes("encoding")) {
1561
- const buffer = await fs4.readFile(path5);
1648
+ const buffer = await fs5.readFile(path10);
1562
1649
  content = buffer.toString("latin1");
1563
1650
  } else {
1564
1651
  throw error;
@@ -1577,11 +1664,11 @@ var FileEditor = class {
1577
1664
  throw new ToolExecutionError(`Line range is invalid: ${lineRange}`);
1578
1665
  }
1579
1666
  const selectedLines = lines.slice(start, end);
1580
- return `Lines ${start + 1} to ${end} of file ${path5}:
1667
+ return `Lines ${start + 1} to ${end} of file ${path10}:
1581
1668
  ` + selectedLines.join("\n");
1582
1669
  } catch (error) {
1583
1670
  throw new ToolExecutionError(
1584
- `Invalid line range format when reading file ${path5}: ${lineRange}, error: ${error.message}`
1671
+ `Invalid line range format when reading file ${path10}: ${lineRange}, error: ${error.message}`
1585
1672
  );
1586
1673
  }
1587
1674
  } else {
@@ -1593,11 +1680,11 @@ var FileEditor = class {
1593
1680
  if (lineNum >= lines.length) {
1594
1681
  throw new ToolExecutionError(`Line number ${lineNum + 1} exceeds file length ${lines.length}`);
1595
1682
  }
1596
- return `Line ${lineNum + 1} of file ${path5}:
1683
+ return `Line ${lineNum + 1} of file ${path10}:
1597
1684
  ` + lines[lineNum];
1598
1685
  } catch (error) {
1599
1686
  throw new ToolExecutionError(
1600
- `Invalid line number format when reading file ${path5}: ${lineRange}, error: ${error.message}`
1687
+ `Invalid line number format when reading file ${path10}: ${lineRange}, error: ${error.message}`
1601
1688
  );
1602
1689
  }
1603
1690
  }
@@ -1605,30 +1692,30 @@ var FileEditor = class {
1605
1692
  if (error instanceof ToolExecutionError) {
1606
1693
  throw error;
1607
1694
  }
1608
- throw new ToolExecutionError(`Error reading file ${path5}: ${error.message}`);
1695
+ throw new ToolExecutionError(`Error reading file ${path10}: ${error.message}`);
1609
1696
  }
1610
1697
  }
1611
- async write(path5, content) {
1698
+ async write(path10, content) {
1612
1699
  try {
1613
- const dirPath = pathModule.dirname(path5);
1700
+ const dirPath = pathModule.dirname(path10);
1614
1701
  if (dirPath) {
1615
- await fs4.mkdir(dirPath, { recursive: true });
1702
+ await fs5.mkdir(dirPath, { recursive: true });
1616
1703
  }
1617
- await fs4.writeFile(path5, content, "utf-8");
1704
+ await fs5.writeFile(path10, content, "utf-8");
1618
1705
  const bytesWritten = Buffer.from(content, "utf-8").length;
1619
- return `Successfully wrote content to file ${path5}, wrote ${bytesWritten} bytes`;
1706
+ return `Successfully wrote content to file ${path10}, wrote ${bytesWritten} bytes`;
1620
1707
  } catch (error) {
1621
1708
  if (error.code === "EACCES") {
1622
- throw new ToolExecutionError(`No write permission: ${path5}`);
1709
+ throw new ToolExecutionError(`No write permission: ${path10}`);
1623
1710
  }
1624
- throw new ToolExecutionError(`Error writing to file ${path5}: ${error.message}`);
1711
+ throw new ToolExecutionError(`Error writing to file ${path10}: ${error.message}`);
1625
1712
  }
1626
1713
  }
1627
- async find(path5, pattern) {
1714
+ async find(path10, pattern) {
1628
1715
  try {
1629
- await fs4.access(path5);
1716
+ await fs5.access(path10);
1630
1717
  } catch {
1631
- throw new ToolExecutionError(`File does not exist: ${path5}`);
1718
+ throw new ToolExecutionError(`File does not exist: ${path10}`);
1632
1719
  }
1633
1720
  let compiledPattern;
1634
1721
  try {
@@ -1640,10 +1727,10 @@ var FileEditor = class {
1640
1727
  try {
1641
1728
  let content;
1642
1729
  try {
1643
- content = await fs4.readFile(path5, "utf-8");
1730
+ content = await fs5.readFile(path10, "utf-8");
1644
1731
  } catch (error) {
1645
1732
  if (error.code === "ENCODING_NOT_SUPPORTED" || error.message.includes("encoding")) {
1646
- const buffer = await fs4.readFile(path5);
1733
+ const buffer = await fs5.readFile(path10);
1647
1734
  content = buffer.toString("latin1");
1648
1735
  } else {
1649
1736
  throw error;
@@ -1665,23 +1752,23 @@ var FileEditor = class {
1665
1752
  }
1666
1753
  }
1667
1754
  } catch (error) {
1668
- throw new ToolExecutionError(`Error reading file ${path5}: ${error.message}`);
1755
+ throw new ToolExecutionError(`Error reading file ${path10}: ${error.message}`);
1669
1756
  }
1670
1757
  if (matches.length === 0) {
1671
- return `No content matching pattern '${pattern}' found in file ${path5}`;
1758
+ return `No content matching pattern '${pattern}' found in file ${path10}`;
1672
1759
  }
1673
- const resultLines = [`Found ${matches.length} matches in file ${path5}:`];
1760
+ const resultLines = [`Found ${matches.length} matches in file ${path10}:`];
1674
1761
  for (const match of matches) {
1675
1762
  resultLines.push(`Line ${match.lineNumber}: ${match.match} (position ${match.startPos}-${match.endPos})`);
1676
1763
  resultLines.push(` Full line content: ${match.lineContent}`);
1677
1764
  }
1678
1765
  return resultLines.join("\n");
1679
1766
  }
1680
- async findAndReplace(path5, pattern, replacement) {
1767
+ async findAndReplace(path10, pattern, replacement) {
1681
1768
  try {
1682
- await fs4.access(path5);
1769
+ await fs5.access(path10);
1683
1770
  } catch {
1684
- throw new ToolExecutionError(`File does not exist: ${path5}`);
1771
+ throw new ToolExecutionError(`File does not exist: ${path10}`);
1685
1772
  }
1686
1773
  let compiledPattern;
1687
1774
  try {
@@ -1692,17 +1779,17 @@ var FileEditor = class {
1692
1779
  let content;
1693
1780
  try {
1694
1781
  try {
1695
- content = await fs4.readFile(path5, "utf-8");
1782
+ content = await fs5.readFile(path10, "utf-8");
1696
1783
  } catch (error) {
1697
1784
  if (error.code === "ENCODING_NOT_SUPPORTED" || error.message.includes("encoding")) {
1698
- const buffer = await fs4.readFile(path5);
1785
+ const buffer = await fs5.readFile(path10);
1699
1786
  content = buffer.toString("latin1");
1700
1787
  } else {
1701
1788
  throw error;
1702
1789
  }
1703
1790
  }
1704
1791
  } catch (error) {
1705
- throw new ToolExecutionError(`Error reading file ${path5}: ${error.message}`);
1792
+ throw new ToolExecutionError(`Error reading file ${path10}: ${error.message}`);
1706
1793
  }
1707
1794
  const newContent = content.replace(compiledPattern, replacement);
1708
1795
  const replacementCount = (content.match(compiledPattern) || []).length;
@@ -1712,30 +1799,30 @@ var FileEditor = class {
1712
1799
  const newLines = newContent.split("\n");
1713
1800
  modifiedLines = originalLines.filter((line, index) => line !== newLines[index]).length;
1714
1801
  try {
1715
- await fs4.writeFile(path5, newContent, "utf-8");
1802
+ await fs5.writeFile(path10, newContent, "utf-8");
1716
1803
  } catch (error) {
1717
1804
  if (error.code === "EACCES") {
1718
- throw new ToolExecutionError(`No write permission: ${path5}`);
1805
+ throw new ToolExecutionError(`No write permission: ${path10}`);
1719
1806
  }
1720
- throw new ToolExecutionError(`Error writing to file ${path5}: ${error.message}`);
1807
+ throw new ToolExecutionError(`Error writing to file ${path10}: ${error.message}`);
1721
1808
  }
1722
1809
  }
1723
- return `In file ${path5}, found and replaced pattern '${pattern}' with '${replacement}', successfully replaced ${replacementCount} occurrences, modified ${modifiedLines} lines`;
1810
+ return `In file ${path10}, found and replaced pattern '${pattern}' with '${replacement}', successfully replaced ${replacementCount} occurrences, modified ${modifiedLines} lines`;
1724
1811
  }
1725
- async insert(path5, content, line) {
1812
+ async insert(path10, content, line) {
1726
1813
  try {
1727
- await fs4.access(path5);
1814
+ await fs5.access(path10);
1728
1815
  } catch {
1729
- throw new ToolExecutionError(`File does not exist: ${path5}`);
1816
+ throw new ToolExecutionError(`File does not exist: ${path10}`);
1730
1817
  }
1731
1818
  let lines;
1732
1819
  try {
1733
1820
  let fileContent;
1734
1821
  try {
1735
- fileContent = await fs4.readFile(path5, "utf-8");
1822
+ fileContent = await fs5.readFile(path10, "utf-8");
1736
1823
  } catch (error) {
1737
1824
  if (error.code === "ENCODING_NOT_SUPPORTED" || error.message.includes("encoding")) {
1738
- const buffer = await fs4.readFile(path5);
1825
+ const buffer = await fs5.readFile(path10);
1739
1826
  fileContent = buffer.toString("latin1");
1740
1827
  } else {
1741
1828
  throw error;
@@ -1743,27 +1830,27 @@ var FileEditor = class {
1743
1830
  }
1744
1831
  lines = fileContent.split("\n");
1745
1832
  } catch (error) {
1746
- throw new ToolExecutionError(`Error reading file ${path5}: ${error.message}`);
1833
+ throw new ToolExecutionError(`Error reading file ${path10}: ${error.message}`);
1747
1834
  }
1748
1835
  let actionDesc;
1749
1836
  if (line === void 0) {
1750
1837
  lines.push(content);
1751
- actionDesc = `Appended content to end of file ${path5}`;
1838
+ actionDesc = `Appended content to end of file ${path10}`;
1752
1839
  } else {
1753
1840
  if (!(0 < line && line <= lines.length + 1)) {
1754
- throw new ToolExecutionError(`Line number ${line} exceeds file ${path5} bounds (1 to ${lines.length + 1})`);
1841
+ throw new ToolExecutionError(`Line number ${line} exceeds file ${path10} bounds (1 to ${lines.length + 1})`);
1755
1842
  }
1756
1843
  lines.splice(line - 1, 0, content);
1757
- actionDesc = `Inserted content at line ${line} of file ${path5}`;
1844
+ actionDesc = `Inserted content at line ${line} of file ${path10}`;
1758
1845
  }
1759
1846
  try {
1760
- await fs4.writeFile(path5, lines.join("\n"), "utf-8");
1847
+ await fs5.writeFile(path10, lines.join("\n"), "utf-8");
1761
1848
  return actionDesc;
1762
1849
  } catch (error) {
1763
1850
  if (error.code === "EACCES") {
1764
- throw new ToolExecutionError(`No write permission: ${path5}`);
1851
+ throw new ToolExecutionError(`No write permission: ${path10}`);
1765
1852
  }
1766
- throw new ToolExecutionError(`Error writing to file ${path5}: ${error.message}`);
1853
+ throw new ToolExecutionError(`Error writing to file ${path10}: ${error.message}`);
1767
1854
  }
1768
1855
  }
1769
1856
  };
@@ -2031,8 +2118,8 @@ ReflectTool = __decorateClass([
2031
2118
  ], ReflectTool);
2032
2119
 
2033
2120
  // src/tools/skills.ts
2034
- import * as fs5 from "fs";
2035
- import * as path3 from "path";
2121
+ import * as fs6 from "fs";
2122
+ import * as path4 from "path";
2036
2123
  var SkillsTool = class {
2037
2124
  /**
2038
2125
  * Skills directory
@@ -2051,8 +2138,8 @@ var SkillsTool = class {
2051
2138
  * str: The content of the skill description file
2052
2139
  */
2053
2140
  async readSkillDescription(name) {
2054
- const skillsPath = path3.join(this.skillsDir, name, "SKILL.md");
2055
- if (!fs5.existsSync(skillsPath)) {
2141
+ const skillsPath = path4.join(this.skillsDir, name, "SKILL.md");
2142
+ if (!fs6.existsSync(skillsPath)) {
2056
2143
  throw new ToolExecutionError(`Skill description file not found: ${skillsPath}`);
2057
2144
  }
2058
2145
  const fileEditor = new FileEditor();
@@ -2065,14 +2152,14 @@ var SkillsTool = class {
2065
2152
  * List the skills in the skills root directory
2066
2153
  */
2067
2154
  async listSkills() {
2068
- if (!fs5.existsSync(this.skillsDir)) {
2155
+ if (!fs6.existsSync(this.skillsDir)) {
2069
2156
  throw new ToolExecutionError(`Skills path not found: ${this.skillsDir}`);
2070
2157
  }
2071
2158
  const skillsDict = {};
2072
- const items = fs5.readdirSync(this.skillsDir);
2159
+ const items = fs6.readdirSync(this.skillsDir);
2073
2160
  for (const skillName of items) {
2074
- const skillPath = path3.join(this.skillsDir, skillName, "SKILL.md");
2075
- if (!fs5.existsSync(skillPath)) {
2161
+ const skillPath = path4.join(this.skillsDir, skillName, "SKILL.md");
2162
+ if (!fs6.existsSync(skillPath)) {
2076
2163
  continue;
2077
2164
  }
2078
2165
  const fileEditor = new FileEditor();
@@ -2104,8 +2191,8 @@ SkillsTool = __decorateClass([
2104
2191
 
2105
2192
  // src/tools/gitTool.ts
2106
2193
  import { exec } from "child_process";
2107
- import * as fs6 from "fs";
2108
- import * as path4 from "path";
2194
+ import * as fs7 from "fs";
2195
+ import * as path5 from "path";
2109
2196
  function quote(str) {
2110
2197
  if (/^[a-zA-Z0-9_\-.\/]+$/.test(str)) {
2111
2198
  return str;
@@ -2657,12 +2744,12 @@ var GitTool = class {
2657
2744
  */
2658
2745
  async _executeGitCommand(command, cwd, timeout = 3e4, config2) {
2659
2746
  const workDir = cwd || process.cwd();
2660
- if (!fs6.existsSync(workDir)) {
2747
+ if (!fs7.existsSync(workDir)) {
2661
2748
  throw new ToolExecutionError(`\u5DE5\u4F5C\u76EE\u5F55\u4E0D\u5B58\u5728: ${workDir}`);
2662
2749
  }
2663
- const gitDir = path4.join(workDir, ".git");
2750
+ const gitDir = path5.join(workDir, ".git");
2664
2751
  const isInitOrClone = command.includes("clone") || command.includes("init");
2665
- if (!fs6.existsSync(gitDir) && !isInitOrClone) {
2752
+ if (!fs7.existsSync(gitDir) && !isInitOrClone) {
2666
2753
  throw new ToolExecutionError(`\u5F53\u524D\u76EE\u5F55\u4E0D\u662F git \u4ED3\u5E93: ${workDir}`);
2667
2754
  }
2668
2755
  let gitCmd = "git";
@@ -2672,7 +2759,7 @@ var GitTool = class {
2672
2759
  }
2673
2760
  }
2674
2761
  gitCmd += ` ${command}`;
2675
- return new Promise((resolve2, reject) => {
2762
+ return new Promise((resolve5, reject) => {
2676
2763
  exec(gitCmd, { cwd: workDir, timeout, encoding: "utf-8" }, (error, stdout, stderr) => {
2677
2764
  const stdoutText = stdout ? stdout.trim() : "";
2678
2765
  const stderrText = stderr ? stderr.trim() : "";
@@ -2685,7 +2772,7 @@ var GitTool = class {
2685
2772
  reject(new ToolExecutionError(`Git \u547D\u4EE4\u6267\u884C\u5931\u8D25: ${errorMsg}`));
2686
2773
  return;
2687
2774
  }
2688
- resolve2(stdoutText || "\u547D\u4EE4\u6267\u884C\u6210\u529F\uFF0C\u65E0\u8F93\u51FA");
2775
+ resolve5(stdoutText || "\u547D\u4EE4\u6267\u884C\u6210\u529F\uFF0C\u65E0\u8F93\u51FA");
2689
2776
  });
2690
2777
  });
2691
2778
  }
@@ -2863,96 +2950,779 @@ GitTool = __decorateClass([
2863
2950
  tools(gitToolConfig)
2864
2951
  ], GitTool);
2865
2952
 
2866
- // src/model.ts
2867
- import OpenAI from "openai";
2868
- import Anthropic from "@anthropic-ai/sdk";
2869
- import { GoogleGenerativeAI } from "@google/generative-ai";
2870
- var Model = class {
2871
- modelName;
2872
- config;
2873
- openaiClient;
2874
- anthropicClient;
2875
- geminiClient;
2876
- constructor(model) {
2877
- if (typeof model === "string" || model === void 0) {
2878
- this.modelName = model || "deepseek";
2879
- this.config = loadModelConfig(this.modelName);
2880
- } else {
2881
- this.config = model;
2882
- this.modelName = model.model || "deepseek";
2953
+ // src/schemas/message.ts
2954
+ import * as fs8 from "fs";
2955
+ var _Message = class _Message {
2956
+ role;
2957
+ content;
2958
+ images;
2959
+ // OpenAI vision API format image content
2960
+ imagesContent;
2961
+ // Message tag for wrapping content
2962
+ tag;
2963
+ // Function calling / OpenAI tool call message information
2964
+ isFunctionCall;
2965
+ toolCallId;
2966
+ toolName;
2967
+ // Legacy type field (kept for compatibility)
2968
+ type;
2969
+ constructor(role, content, images, type) {
2970
+ this.role = role;
2971
+ this.content = content;
2972
+ this.images = images;
2973
+ this.type = type;
2974
+ this.imagesContent = [];
2975
+ this.tag = "";
2976
+ this.isFunctionCall = false;
2977
+ this.toolCallId = "";
2978
+ this.toolName = "";
2979
+ }
2980
+ /**
2981
+ * Create message from user input
2982
+ */
2983
+ static fromUserMsg(content, images) {
2984
+ return new _Message("user", content, images);
2985
+ }
2986
+ /**
2987
+ * Create message from assistant response
2988
+ */
2989
+ static fromAssistantMsg(content) {
2990
+ return new _Message("assistant", content);
2991
+ }
2992
+ /**
2993
+ * Create system message
2994
+ */
2995
+ static fromSystemMsg(content) {
2996
+ return new _Message("system", content);
2997
+ }
2998
+ /**
2999
+ * Check if message is truthy based on content
3000
+ */
3001
+ isTruthy() {
3002
+ if (typeof this.content === "string") {
3003
+ return Boolean(this.content.trim());
2883
3004
  }
2884
- this._initializeClient();
3005
+ return false;
2885
3006
  }
2886
3007
  /**
2887
- * Initialize the appropriate SDK client based on provider
3008
+ * Format the content with pre/post content and optional tag wrapping
2888
3009
  */
2889
- _initializeClient() {
2890
- const provider = this.config.provider.toLowerCase();
2891
- switch (provider) {
2892
- case "openai":
2893
- this.openaiClient = new OpenAI({
2894
- apiKey: this.config.apiKey || process.env.OPENAI_API_KEY,
2895
- baseURL: this.config.baseUrl,
2896
- timeout: 6e4
2897
- });
2898
- break;
2899
- case "deepseek":
2900
- this.openaiClient = new OpenAI({
2901
- apiKey: this.config.apiKey || process.env.DEEPSEEK_API_KEY,
2902
- baseURL: this.config.baseUrl || "https://api.deepseek.com",
2903
- timeout: 6e4
2904
- });
2905
- break;
2906
- case "anthropic":
2907
- if (this.config.baseUrl.endsWith("/v1") || this.config.baseUrl.endsWith("v1/")) {
2908
- this.config.baseUrl = this.config.baseUrl.slice(0, -3);
3010
+ _formatForContent(preContent = "", postContent = "") {
3011
+ if (this.tag) {
3012
+ return `${preContent}<${this.tag}>
3013
+ ${this.content}
3014
+ </${this.tag}>${postContent}`.trim();
3015
+ }
3016
+ return `${preContent}${this.content}${postContent}`.trim();
3017
+ }
3018
+ /**
3019
+ * Ensure text content is not empty to avoid API errors
3020
+ */
3021
+ static _ensureNonEmptyText(text) {
3022
+ return text.trim() ? text : " ";
3023
+ }
3024
+ /**
3025
+ * Format message for OpenAI API
3026
+ *
3027
+ * This is the recommended method replacing toChatMessage.
3028
+ *
3029
+ * @param preContent - Content to prepend
3030
+ * @param postContent - Content to append
3031
+ * @returns Formatted message object for API
3032
+ */
3033
+ formatForApi(preContent = "", postContent = "") {
3034
+ const role = ["user", "assistant", "system", "tool"].includes(this.role) ? this.role : "user";
3035
+ const functionCallingMeta = { tool_call_id: this.toolCallId, name: this.toolName };
3036
+ if (!this.imagesContent || this.imagesContent.length === 0) {
3037
+ const msg2 = {
3038
+ role,
3039
+ content: this._formatForContent(preContent, postContent)
3040
+ };
3041
+ return this.isFunctionCall ? { ...msg2, ...functionCallingMeta } : msg2;
3042
+ }
3043
+ let formattedText = this._formatForContent(preContent, postContent);
3044
+ formattedText = _Message._ensureNonEmptyText(formattedText);
3045
+ const content = [{ type: "text", text: formattedText }];
3046
+ content.push(...this.imagesContent);
3047
+ const msg = { role, content };
3048
+ return this.isFunctionCall ? { ...msg, ...functionCallingMeta } : msg;
3049
+ }
3050
+ /**
3051
+ * Convert to plain object for API calls
3052
+ */
3053
+ toObject() {
3054
+ const obj = {
3055
+ role: this.role,
3056
+ content: this.content
3057
+ };
3058
+ if (this.images) {
3059
+ obj.images = this.images;
3060
+ }
3061
+ if (this.type) {
3062
+ obj.type = this.type;
3063
+ }
3064
+ if (this.tag) {
3065
+ obj.tag = this.tag;
3066
+ }
3067
+ if (this.imagesContent && this.imagesContent.length > 0) {
3068
+ obj.images_content = this.imagesContent;
3069
+ }
3070
+ if (this.isFunctionCall) {
3071
+ obj.is_function_call = this.isFunctionCall;
3072
+ obj.tool_call_id = this.toolCallId;
3073
+ obj.tool_name = this.toolName;
3074
+ }
3075
+ return obj;
3076
+ }
3077
+ /**
3078
+ * Convert to dictionary representation
3079
+ */
3080
+ toDict() {
3081
+ return {
3082
+ role: this.role,
3083
+ content: this.content,
3084
+ tag: this.tag || "",
3085
+ images_content: this.imagesContent || [],
3086
+ is_function_call: this.isFunctionCall || false,
3087
+ tool_call_id: this.toolCallId || "",
3088
+ tool_name: this.toolName || ""
3089
+ };
3090
+ }
3091
+ /**
3092
+ * Check if message contains images
3093
+ */
3094
+ hasImages() {
3095
+ return !!this.images && (Array.isArray(this.images) ? this.images.length > 0 : true) || !!this.imagesContent && this.imagesContent.length > 0;
3096
+ }
3097
+ /**
3098
+ * Get message content length
3099
+ */
3100
+ getContentLength() {
3101
+ return this.content.length;
3102
+ }
3103
+ /**
3104
+ * Convert to string representation
3105
+ */
3106
+ toString() {
3107
+ const parts = [];
3108
+ parts.push(`role=${this.role}`);
3109
+ if (this.content) {
3110
+ const truncatedContent = this.content.length > 100 ? this.content.slice(0, 100) + "..." : this.content;
3111
+ parts.push(`content=${truncatedContent}`);
3112
+ }
3113
+ if (this.tag) {
3114
+ parts.push(`tag=${this.tag}`);
3115
+ }
3116
+ if (this.imagesContent && this.imagesContent.length > 0) {
3117
+ const imagePaths = [];
3118
+ for (const img of this.imagesContent) {
3119
+ if (img && img.image_url && img.image_url.url) {
3120
+ const url = img.image_url.url;
3121
+ if (!url.startsWith("data:")) {
3122
+ imagePaths.push(url);
3123
+ }
2909
3124
  }
2910
- this.anthropicClient = new Anthropic({
2911
- apiKey: this.config.apiKey || process.env.ANTHROPIC_API_KEY,
2912
- baseURL: this.config.baseUrl,
2913
- timeout: 6e4
3125
+ }
3126
+ if (imagePaths.length > 0) {
3127
+ parts.push(`images_paths=[${imagePaths.join(", ")}]`);
3128
+ }
3129
+ }
3130
+ return `Message(${parts.join(", ")})`;
3131
+ }
3132
+ /**
3133
+ * Merge two messages into one
3134
+ *
3135
+ * @param other - Message to merge with
3136
+ * @returns New merged Message
3137
+ */
3138
+ merge(other) {
3139
+ if (this.role !== other.role) {
3140
+ throw new Error("Messages must have the same role to merge");
3141
+ }
3142
+ if (this.isFunctionCall !== other.isFunctionCall) {
3143
+ throw new Error("Messages must have the same isFunctionCall to merge");
3144
+ }
3145
+ if (this.toolCallId !== other.toolCallId) {
3146
+ throw new Error("Messages must have the same toolCallId to merge");
3147
+ }
3148
+ if (this.toolName !== other.toolName) {
3149
+ throw new Error("Messages must have the same toolName to merge");
3150
+ }
3151
+ let selfContent = this.content;
3152
+ let otherContent = other.content;
3153
+ let resultTag = this.tag;
3154
+ if (this.tag !== other.tag) {
3155
+ selfContent = this.tag ? `<${this.tag}>
3156
+ ${this.content}
3157
+ </${this.tag}>` : this.content;
3158
+ otherContent = other.tag ? `<${other.tag}>
3159
+ ${other.content}
3160
+ </${other.tag}>` : other.content;
3161
+ resultTag = "";
3162
+ }
3163
+ const merged = new _Message(this.role, `${selfContent}
3164
+ ${otherContent}`);
3165
+ merged.tag = resultTag;
3166
+ merged.imagesContent = [...this.imagesContent || [], ...other.imagesContent || []];
3167
+ merged.isFunctionCall = this.isFunctionCall;
3168
+ merged.toolCallId = this.toolCallId;
3169
+ merged.toolName = this.toolName;
3170
+ return merged;
3171
+ }
3172
+ async toChatMessage() {
3173
+ const role = this.role;
3174
+ if (!this.hasImages()) {
3175
+ return { role, content: this.content };
3176
+ }
3177
+ const content = [{ type: "text", text: this.content }];
3178
+ if (this.images) {
3179
+ const imageArray = Array.isArray(this.images) ? this.images : [this.images];
3180
+ for (const img of imageArray) {
3181
+ let base64Data;
3182
+ if (img.startsWith("http://") || img.startsWith("https://")) {
3183
+ base64Data = await this.encodeHttpImage(img);
3184
+ } else if (fs8.existsSync(img)) {
3185
+ base64Data = await this.encodeLocalFile(img);
3186
+ } else {
3187
+ base64Data = img;
3188
+ }
3189
+ const mimeType = this.getMimeType(img);
3190
+ content.push({
3191
+ type: "image_url",
3192
+ image_url: { url: `data:${mimeType};base64,${base64Data}` }
2914
3193
  });
2915
- break;
2916
- case "gemini":
2917
- const apiKey = this.config.apiKey || process.env.GEMINI_API_KEY || "";
2918
- this.geminiClient = new GoogleGenerativeAI(apiKey);
2919
- break;
2920
- default:
2921
- throw new ModelError(`Unsupported provider: ${provider}`);
3194
+ }
3195
+ }
3196
+ if (this.imagesContent && this.imagesContent.length > 0) {
3197
+ content.push(...this.imagesContent);
2922
3198
  }
3199
+ return { role, content };
2923
3200
  }
2924
3201
  /**
2925
- * Asynchronous chat completion
3202
+ * Get MIME type from file path or URL
2926
3203
  */
2927
- async achat(messages, tools2, stream = true) {
2928
- const provider = this.config.provider.toLowerCase();
2929
- const useStream = stream !== void 0 ? stream : !!this.config.stream;
3204
+ getMimeType(path10) {
3205
+ const ext = path10.toLowerCase().split(".").pop();
3206
+ const mimeTypes = {
3207
+ png: "image/png",
3208
+ jpg: "image/jpeg",
3209
+ jpeg: "image/jpeg",
3210
+ gif: "image/gif",
3211
+ webp: "image/webp",
3212
+ bmp: "image/bmp"
3213
+ };
3214
+ return mimeTypes[ext || ""] || "image/jpeg";
3215
+ }
3216
+ /**
3217
+ * Encode local file to base64
3218
+ */
3219
+ async encodeLocalFile(filePath) {
3220
+ const fileBuffer = await fs8.promises.readFile(filePath);
3221
+ return fileBuffer.toString("base64");
3222
+ }
3223
+ /**
3224
+ * Fetch and encode HTTP image to base64
3225
+ */
3226
+ async encodeHttpImage(url) {
3227
+ const response = await fetch(url);
3228
+ if (!response.ok) {
3229
+ throw new Error(`Failed to fetch image from ${url}: ${response.statusText}`);
3230
+ }
3231
+ const buffer = await response.arrayBuffer();
3232
+ return Buffer.from(buffer).toString("base64");
3233
+ }
3234
+ };
3235
+ __decorateClass([
3236
+ deprecated({ version: "0.2.2", replacement: "formatForApi" })
3237
+ ], _Message.prototype, "toChatMessage", 1);
3238
+ var Message = _Message;
3239
+
3240
+ // src/tools/imageTool.ts
3241
+ var ImageTool = class {
3242
+ /**
3243
+ * Read and analyze an image (JPEG, JPG, PNG, GIF, WebP) from image path or URL.
3244
+ *
3245
+ * Note: SVG format is not supported by the AI model.
3246
+ *
3247
+ * @param imagePath - Image path or URL
3248
+ * @param instruction - Instruction for analyzing the image
3249
+ * @returns Message containing image content in base64 format
3250
+ */
3251
+ async readImage(imagePath, instruction = "") {
2930
3252
  try {
2931
- switch (provider) {
2932
- case "openai":
2933
- case "deepseek":
2934
- return await this._callOpenAICompatible(messages, tools2, useStream);
2935
- case "anthropic":
2936
- return await this._callAnthropic(messages, tools2, useStream);
2937
- case "gemini":
2938
- return await this._callGemini(messages, tools2, useStream);
2939
- default:
2940
- throw new ModelError(`Unsupported provider: ${provider}`);
3253
+ if (!isSupportedImageFile(imagePath)) {
3254
+ logger.warn(`Unsupported image format: ${imagePath}. Only JPEG, PNG, GIF, and WebP are supported.`);
3255
+ const errorMsg = new Message(
3256
+ "user",
3257
+ `Error: Unsupported image format '${imagePath}'. Only JPEG, PNG, GIF, and WebP are supported by the AI model.`
3258
+ );
3259
+ return errorMsg;
3260
+ }
3261
+ const imageContent = await areadImage(imagePath);
3262
+ let content;
3263
+ if (instruction) {
3264
+ content = `Please analyze the image from ${imagePath} according to the following instruction:
3265
+
3266
+ ${instruction}
3267
+
3268
+ Please provide a detailed analysis of the image content based on this instruction.`;
3269
+ } else {
3270
+ content = `Please analyze and describe the image from ${imagePath} in detail. Include information about:
3271
+ - What is shown in the image
3272
+ - Key elements, objects, or features
3273
+ - Colors, composition, and visual characteristics
3274
+ - Any text or symbols present
3275
+ - Overall context and meaning`;
2941
3276
  }
3277
+ const msg = new Message("user", content);
3278
+ msg.imagesContent = [imageContent];
3279
+ msg.tag = "image_content";
3280
+ return msg;
2942
3281
  } catch (error) {
2943
- logger.error(`Model call failed: ${error}`);
2944
- throw error;
3282
+ return new Message("user", `Error reading image ${imagePath}: ${error}`);
2945
3283
  }
2946
3284
  }
2947
3285
  /**
2948
- * Call OpenAI-compatible API (OpenAI, DeepSeek, etc.)
3286
+ * Read images (JPEG, JPG, PNG, GIF, WebP) from image paths or URLs.
3287
+ *
3288
+ * Note: SVG format is not supported by the AI model and will be automatically filtered out.
3289
+ *
3290
+ * @param imagePaths - List of image paths or URLs
3291
+ * @param instruction - Instruction for reading the images
3292
+ * @returns Message containing multiple image contents in base64 format
2949
3293
  */
2950
- async _callOpenAICompatible(messages, tools2, stream = false) {
2951
- if (!this.openaiClient) {
2952
- throw new ModelError("OpenAI client not initialized");
2953
- }
3294
+ async readImages(imagePaths, instruction = "") {
2954
3295
  try {
2955
- const params = {
3296
+ const supportedPaths = imagePaths.filter((path10) => isSupportedImageFile(path10));
3297
+ const unsupportedPaths = imagePaths.filter((path10) => !isSupportedImageFile(path10));
3298
+ if (unsupportedPaths.length > 0) {
3299
+ logger.warn(
3300
+ `Skipping unsupported image formats (only JPEG/PNG/GIF/WebP are supported): ${unsupportedPaths.join(", ")}`
3301
+ );
3302
+ }
3303
+ if (supportedPaths.length === 0) {
3304
+ return new Message(
3305
+ "user",
3306
+ `No supported image formats found in the provided list. Only JPEG, PNG, GIF, and WebP are supported. Unsupported files: ${unsupportedPaths.join(", ")}`
3307
+ );
3308
+ }
3309
+ const imageContents = await Promise.all(
3310
+ supportedPaths.map((imagePath) => areadImage(imagePath))
3311
+ );
3312
+ const contentParts = [`Successfully loaded ${supportedPaths.length} image(s): ${supportedPaths.join(", ")}`];
3313
+ if (unsupportedPaths.length > 0) {
3314
+ contentParts.push(`Skipped ${unsupportedPaths.length} unsupported file(s): ${unsupportedPaths.join(", ")}`);
3315
+ }
3316
+ const msg = new Message("user", contentParts.join("\n"));
3317
+ msg.imagesContent = imageContents;
3318
+ return msg;
3319
+ } catch (error) {
3320
+ return new Message("user", `Error reading images ${imagePaths.join(", ")}: ${error}`);
3321
+ }
3322
+ }
3323
+ };
3324
+ ImageTool = __decorateClass([
3325
+ tools({
3326
+ readImage: {
3327
+ description: "Read and analyze an image (JPEG, JPG, PNG, GIF, WebP) from image path or URL. Note: SVG format is not supported by the AI model.",
3328
+ params: [
3329
+ { name: "imagePath", type: "string", description: "Image path or URL" },
3330
+ { name: "instruction", type: "string", description: "Instruction for analyzing the image", optional: true }
3331
+ ],
3332
+ returns: { type: "Message", description: "Message containing image content in base64 format" }
3333
+ },
3334
+ readImages: {
3335
+ description: "Read images (JPEG, JPG, PNG, GIF, WebP) from image paths or URLs. Note: SVG format is not supported by the AI model and will be automatically filtered out.",
3336
+ params: [
3337
+ { name: "imagePaths", type: "array", description: "List of image paths or URLs" },
3338
+ { name: "instruction", type: "string", description: "Instruction for reading the images", optional: true }
3339
+ ],
3340
+ returns: { type: "Message", description: "Message containing multiple image contents in base64 format" }
3341
+ }
3342
+ })
3343
+ ], ImageTool);
3344
+
3345
+ // src/tools/patchTool.ts
3346
+ import * as fs9 from "fs";
3347
+ import * as path6 from "path";
3348
+ import { spawn as spawn2 } from "child_process";
3349
+ var PatchTool = class {
3350
+ /**
3351
+ * Write patch content to file
3352
+ *
3353
+ * @param patchPath - Path to the patch file
3354
+ * @param patchContent - Content of the patch in unified diff format
3355
+ * @returns Success message
3356
+ */
3357
+ async writePatchFile(patchPath, patchContent) {
3358
+ let warningMsg = "";
3359
+ if (!patchPath.endsWith(".patch")) {
3360
+ patchPath = `${patchPath}.patch`;
3361
+ warningMsg = `Warning: Patch path does not end with '.patch', automatically appended '.patch' to ${patchPath}`;
3362
+ }
3363
+ const dirPath = path6.dirname(patchPath);
3364
+ if (dirPath) {
3365
+ await fs9.promises.mkdir(dirPath, { recursive: true });
3366
+ }
3367
+ patchContent = patchContent.trim();
3368
+ if (patchContent.startsWith("```")) {
3369
+ const newlineIndex = patchContent.indexOf("\n");
3370
+ patchContent = newlineIndex !== -1 ? patchContent.slice(newlineIndex + 1) : patchContent.slice(3);
3371
+ }
3372
+ if (patchContent.endsWith("```")) {
3373
+ patchContent = patchContent.slice(0, -3).trimEnd();
3374
+ }
3375
+ patchContent = patchContent.trim();
3376
+ if (patchContent && patchContent.split("\n")[0].startsWith("diff --git")) {
3377
+ patchContent = this._convertGitDiffToUnifiedDiff(patchContent);
3378
+ }
3379
+ this._validatePatchFormat(patchContent);
3380
+ if (fs9.existsSync(patchPath)) {
3381
+ const baseName = path6.basename(patchPath, ".patch");
3382
+ const oldPatchPath = path6.join(path6.dirname(patchPath), `${baseName}1.patch`);
3383
+ await fs9.promises.rename(patchPath, oldPatchPath);
3384
+ }
3385
+ await fs9.promises.writeFile(patchPath, patchContent, "utf-8");
3386
+ const bytesWritten = Buffer.from(patchContent, "utf-8").length;
3387
+ const resultMsg = `Successfully wrote patch to ${patchPath}, wrote ${bytesWritten} bytes`;
3388
+ return warningMsg ? `${resultMsg}
3389
+ ${warningMsg}` : resultMsg;
3390
+ }
3391
+ /**
3392
+ * Apply a patch to a file
3393
+ *
3394
+ * @param patchPath - Path to the patch file
3395
+ * @param patchContent - Optional patch content to write before applying
3396
+ * @returns Success message
3397
+ */
3398
+ async applyPatch(patchPath, patchContent) {
3399
+ let warningMsg = "";
3400
+ if (!patchPath.endsWith(".patch")) {
3401
+ patchPath = `${patchPath}.patch`;
3402
+ warningMsg = `Warning: Patch path does not end with '.patch', automatically appended '.patch' to ${patchPath}`;
3403
+ }
3404
+ const patchFileAbs = path6.resolve(patchPath);
3405
+ if (patchContent === void 0) {
3406
+ if (!fs9.existsSync(patchFileAbs)) {
3407
+ throw new Error(`Patch file does not exist: ${patchPath}`);
3408
+ }
3409
+ patchContent = await fs9.promises.readFile(patchFileAbs, "utf-8");
3410
+ }
3411
+ const workDir = this._determineWorkDir(patchFileAbs, patchContent);
3412
+ let writeMsg;
3413
+ if (patchContent !== void 0) {
3414
+ writeMsg = await this.writePatchFile(patchPath, patchContent);
3415
+ }
3416
+ const applyMsg = await this._applyPatch(patchFileAbs, workDir);
3417
+ if (writeMsg) {
3418
+ return `${writeMsg}. ${applyMsg}.`;
3419
+ }
3420
+ return `Successfully applied existing patch file ${patchPath}. ${applyMsg}.
3421
+ ${warningMsg}`;
3422
+ }
3423
+ /**
3424
+ * Validate patch format
3425
+ */
3426
+ _validatePatchFormat(patchContent) {
3427
+ if (!patchContent.trim()) {
3428
+ throw new Error("Patch content is empty.");
3429
+ }
3430
+ const lines = patchContent.split("\n");
3431
+ const hasMinusLine = lines.slice(0, 50).some((line) => line.startsWith("--- "));
3432
+ const hasPlusLine = lines.slice(0, 50).some((line) => line.startsWith("+++ "));
3433
+ const hasHunkHeader = lines.slice(0, 100).some((line) => /^@@ -\d+,\d+ \+\d+,\d+ @@/.test(line));
3434
+ if (!(hasMinusLine && hasPlusLine)) {
3435
+ throw new Error(
3436
+ "Patch does not appear to be in standard unified diff format. Expected lines starting with '--- ' and '+++ '."
3437
+ );
3438
+ }
3439
+ if (!hasHunkHeader) {
3440
+ throw new Error(
3441
+ "Patch does not contain valid hunk headers (lines starting with '@@'). Example: '@@ -1,2 +1,2 @@'"
3442
+ );
3443
+ }
3444
+ }
3445
+ /**
3446
+ * Convert git diff format to unified diff format
3447
+ */
3448
+ _convertGitDiffToUnifiedDiff(patchContent) {
3449
+ const lines = patchContent.split("\n");
3450
+ const convertedLines = [];
3451
+ const skipPrefixes = [
3452
+ "diff --git",
3453
+ "index ",
3454
+ "new file mode",
3455
+ "old file mode",
3456
+ "deleted file mode",
3457
+ "rename from",
3458
+ "rename to",
3459
+ "similarity index",
3460
+ "copy from",
3461
+ "copy to"
3462
+ ];
3463
+ for (const line of lines) {
3464
+ if (skipPrefixes.some((prefix) => line.startsWith(prefix))) {
3465
+ continue;
3466
+ }
3467
+ if (line.startsWith("--- a/")) {
3468
+ const filePath = line.slice(6).split(" ")[0];
3469
+ convertedLines.push(`--- ${filePath}`);
3470
+ } else if (line.startsWith("+++ b/")) {
3471
+ const filePath = line.slice(6).split(" ")[0];
3472
+ convertedLines.push(`+++ ${filePath}`);
3473
+ } else {
3474
+ convertedLines.push(line);
3475
+ }
3476
+ }
3477
+ return convertedLines.join("\n");
3478
+ }
3479
+ /**
3480
+ * Extract target file path from patch content
3481
+ */
3482
+ _extractTargetFile(patchContent) {
3483
+ for (const line of patchContent.split("\n")) {
3484
+ if (line.startsWith("+++ b/")) {
3485
+ return line.slice(6).split(" ")[0];
3486
+ } else if (line.startsWith("+++ ") && !line.startsWith("+++ /dev/null")) {
3487
+ return line.slice(4).split(" ")[0];
3488
+ }
3489
+ }
3490
+ return null;
3491
+ }
3492
+ /**
3493
+ * Determine working directory for applying patch
3494
+ */
3495
+ _determineWorkDir(patchFileAbs, patchContent) {
3496
+ const patchDir = path6.dirname(patchFileAbs) || process.cwd();
3497
+ const defaultWorkDir = path6.resolve(patchDir);
3498
+ const targetFile = this._extractTargetFile(patchContent);
3499
+ if (!targetFile || targetFile === "/dev/null") {
3500
+ return defaultWorkDir;
3501
+ }
3502
+ const searchDirs = [process.cwd(), patchDir];
3503
+ for (const searchDir of searchDirs) {
3504
+ const candidate = path6.join(searchDir, targetFile);
3505
+ if (fs9.existsSync(candidate)) {
3506
+ return path6.dirname(candidate);
3507
+ }
3508
+ }
3509
+ return defaultWorkDir;
3510
+ }
3511
+ /**
3512
+ * Apply patch using patch command or manual fallback
3513
+ */
3514
+ async _applyPatch(patchFileAbs, workDir) {
3515
+ try {
3516
+ const result = await this._executePatchCommand(patchFileAbs, workDir);
3517
+ if (result.exitCode === 0) {
3518
+ return `Successfully applied patch using patch command${result.stdout ? ": " + result.stdout : ""}`;
3519
+ }
3520
+ } catch (error) {
3521
+ logger.debug(`Patch command failed: ${error}`);
3522
+ }
3523
+ const manualResult = await this._applyPatchManually(patchFileAbs, workDir);
3524
+ if (manualResult) {
3525
+ return manualResult;
3526
+ }
3527
+ throw new Error(
3528
+ `Failed to apply patch ${patchFileAbs}. Working directory: ${workDir}. Both patch command and manual application failed. Please check: 1) patch format is correct, 2) target file exists, 3) line numbers match the file content.`
3529
+ );
3530
+ }
3531
+ /**
3532
+ * Execute patch command
3533
+ */
3534
+ _executePatchCommand(patchFileAbs, workDir) {
3535
+ return new Promise((resolve5, reject) => {
3536
+ const patchProcess = spawn2("patch", ["--batch", "-p1", "-i", patchFileAbs], {
3537
+ cwd: workDir
3538
+ });
3539
+ let stdout = "";
3540
+ let stderr = "";
3541
+ patchProcess.stdout.on("data", (data) => {
3542
+ stdout += data.toString();
3543
+ });
3544
+ patchProcess.stderr.on("data", (data) => {
3545
+ stderr += data.toString();
3546
+ });
3547
+ patchProcess.on("close", (code) => {
3548
+ resolve5({
3549
+ exitCode: code || 0,
3550
+ stdout: stdout.trim(),
3551
+ stderr: stderr.trim()
3552
+ });
3553
+ });
3554
+ patchProcess.on("error", (error) => {
3555
+ reject(error);
3556
+ });
3557
+ });
3558
+ }
3559
+ /**
3560
+ * Manually apply patch by parsing unified diff format
3561
+ */
3562
+ async _applyPatchManually(patchFileAbs, workDir) {
3563
+ try {
3564
+ const patchContent = await fs9.promises.readFile(patchFileAbs, "utf-8");
3565
+ const targetFile = this._extractTargetFile(patchContent);
3566
+ if (!targetFile || targetFile === "/dev/null") {
3567
+ return null;
3568
+ }
3569
+ const targetPath = path6.join(workDir, targetFile);
3570
+ const targetDir = path6.dirname(targetPath);
3571
+ if (!fs9.existsSync(targetDir)) {
3572
+ await fs9.promises.mkdir(targetDir, { recursive: true });
3573
+ }
3574
+ let fileLines = [];
3575
+ if (fs9.existsSync(targetPath)) {
3576
+ const content = await fs9.promises.readFile(targetPath, "utf-8");
3577
+ fileLines = content.split("\n");
3578
+ }
3579
+ const resultLines = [...fileLines];
3580
+ const lines = patchContent.split("\n");
3581
+ let inHunk = false;
3582
+ let oldLineNum = 0;
3583
+ let newLineNum = 0;
3584
+ const skipPrefixes = ["diff --git", "new file mode", "index ", "---", "+++"];
3585
+ for (const line of lines) {
3586
+ const hunkMatch = line.match(/^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/);
3587
+ if (hunkMatch) {
3588
+ inHunk = true;
3589
+ oldLineNum = parseInt(hunkMatch[1], 10) - 1;
3590
+ newLineNum = parseInt(hunkMatch[3], 10) - 1;
3591
+ continue;
3592
+ }
3593
+ if (skipPrefixes.some((prefix) => line.startsWith(prefix))) {
3594
+ continue;
3595
+ }
3596
+ if (!inHunk) {
3597
+ continue;
3598
+ }
3599
+ if (line.startsWith(" ")) {
3600
+ if (oldLineNum < resultLines.length) {
3601
+ oldLineNum++;
3602
+ }
3603
+ newLineNum++;
3604
+ } else if (line.startsWith("-")) {
3605
+ if (oldLineNum < resultLines.length) {
3606
+ resultLines.splice(oldLineNum, 1);
3607
+ }
3608
+ } else if (line.startsWith("+")) {
3609
+ resultLines.splice(newLineNum, 0, line.slice(1));
3610
+ newLineNum++;
3611
+ }
3612
+ }
3613
+ await fs9.promises.writeFile(targetPath, resultLines.join("\n"), "utf-8");
3614
+ return "Successfully applied patch manually by parsing and applying changes";
3615
+ } catch (error) {
3616
+ logger.debug(`Manual patch application failed: ${error}`);
3617
+ return null;
3618
+ }
3619
+ }
3620
+ };
3621
+ PatchTool = __decorateClass([
3622
+ tools({
3623
+ writePatchFile: {
3624
+ description: "Write patch content to file. IMPORTANT: Always read the target file first before generating a patch. Use correct line numbers based on actual file content. Never use @@ -0,0 format unless file is truly empty.",
3625
+ params: [
3626
+ { name: "patchPath", type: "string", description: "Path to the patch file. Will automatically append .patch suffix if not present." },
3627
+ { name: "patchContent", type: "string", description: "Content of the patch in unified diff format. Must start with --- a/file_path and include +++ b/file_path lines." }
3628
+ ],
3629
+ returns: { type: "string", description: "Success message with bytes written" }
3630
+ },
3631
+ applyPatch: {
3632
+ description: "Apply a patch to a file. The patch should be generated using writePatchFile first. IMPORTANT: Ensure patch line numbers match the actual file content to avoid duplicate content.",
3633
+ params: [
3634
+ { name: "patchPath", type: "string", description: "Path to the patch file. Will automatically append .patch suffix if not present." },
3635
+ { name: "patchContent", type: "string", description: "Optional patch content to write before applying", optional: true }
3636
+ ],
3637
+ returns: { type: "string", description: "Success message describing the applied patch" }
3638
+ }
3639
+ })
3640
+ ], PatchTool);
3641
+
3642
+ // src/core/agent.ts
3643
+ import { v4 as uuidv4 } from "uuid";
3644
+ import * as path7 from "path";
3645
+ import * as fs10 from "fs";
3646
+
3647
+ // src/core/model.ts
3648
+ import OpenAI from "openai";
3649
+ import { GoogleGenerativeAI } from "@google/generative-ai";
3650
+ var Model = class {
3651
+ modelName;
3652
+ config;
3653
+ openaiClient;
3654
+ anthropicClient;
3655
+ geminiClient;
3656
+ constructor(model) {
3657
+ if (typeof model === "string" || model === void 0) {
3658
+ this.modelName = model || "deepseek";
3659
+ this.config = loadModelConfig(this.modelName);
3660
+ } else {
3661
+ this.config = model;
3662
+ this.modelName = model.model || "deepseek";
3663
+ }
3664
+ this._initializeClient();
3665
+ }
3666
+ /**
3667
+ * Initialize the appropriate SDK client based on provider
3668
+ */
3669
+ _initializeClient() {
3670
+ const provider = this.config.provider.toLowerCase();
3671
+ switch (provider) {
3672
+ case "openai":
3673
+ case "anthropic":
3674
+ this.openaiClient = new OpenAI({
3675
+ apiKey: this.config.apiKey || process.env.OPENAI_API_KEY,
3676
+ baseURL: this.config.baseUrl,
3677
+ timeout: 6e4
3678
+ });
3679
+ break;
3680
+ case "deepseek":
3681
+ this.openaiClient = new OpenAI({
3682
+ apiKey: this.config.apiKey || process.env.DEEPSEEK_API_KEY,
3683
+ baseURL: this.config.baseUrl || "https://api.deepseek.com",
3684
+ timeout: 6e4
3685
+ });
3686
+ break;
3687
+ case "gemini":
3688
+ const apiKey = this.config.apiKey || process.env.GEMINI_API_KEY || "";
3689
+ this.geminiClient = new GoogleGenerativeAI(apiKey);
3690
+ break;
3691
+ default:
3692
+ throw new ModelError(`Unsupported provider: ${provider}`);
3693
+ }
3694
+ }
3695
+ /**
3696
+ * Asynchronous chat completion
3697
+ */
3698
+ async achat(messages, tools2, stream = true) {
3699
+ const provider = this.config.provider.toLowerCase();
3700
+ const useStream = stream !== void 0 ? stream : !!this.config.stream;
3701
+ try {
3702
+ switch (provider) {
3703
+ case "openai":
3704
+ case "deepseek":
3705
+ case "anthropic":
3706
+ return await this._callOpenAICompatible(messages, tools2, useStream);
3707
+ case "gemini":
3708
+ return await this._callGemini(messages, tools2, useStream);
3709
+ default:
3710
+ throw new ModelError(`Unsupported provider: ${provider}`);
3711
+ }
3712
+ } catch (error) {
3713
+ logger.error(`Model call failed: ${error}`);
3714
+ throw error;
3715
+ }
3716
+ }
3717
+ /**
3718
+ * Call OpenAI-compatible API (OpenAI, DeepSeek, etc.)
3719
+ */
3720
+ async _callOpenAICompatible(messages, tools2, stream = false) {
3721
+ if (!this.openaiClient) {
3722
+ throw new ModelError("OpenAI client not initialized");
3723
+ }
3724
+ try {
3725
+ const params = {
2956
3726
  model: this.config.model || "gpt-3.5-turbo",
2957
3727
  messages,
2958
3728
  temperature: this.config.temperature || 0.7,
@@ -3346,197 +4116,66 @@ Arguments: `);
3346
4116
  }
3347
4117
  };
3348
4118
 
3349
- // src/schemas/message.ts
3350
- import * as fs7 from "fs";
3351
- var Message = class _Message {
3352
- role;
3353
- content;
3354
- images;
3355
- type;
3356
- constructor(role, content, images, type) {
3357
- this.role = role;
3358
- this.content = content;
3359
- this.images = images;
3360
- this.type = type;
4119
+ // src/runtime/memory/messageHistory.ts
4120
+ var MessageHistory = class {
4121
+ messages = [];
4122
+ systemPrompt;
4123
+ model;
4124
+ contextWindowTokens;
4125
+ currentTokens = 0;
4126
+ constructor(model, system, contextWindowTokens) {
4127
+ this.model = model;
4128
+ this.systemPrompt = system;
4129
+ this.contextWindowTokens = contextWindowTokens;
4130
+ if (system) {
4131
+ const systemMessage = new Message("system", system);
4132
+ this.messages.push(systemMessage);
4133
+ this.currentTokens += this.estimateTokens(system);
4134
+ }
3361
4135
  }
3362
- /**
3363
- * Create message from user input
3364
- */
3365
- static fromUserMsg(content, images) {
3366
- return new _Message("user", content, images);
4136
+ addMessage(arg1, arg2) {
4137
+ let message;
4138
+ if (arg1 instanceof Message) {
4139
+ message = arg1;
4140
+ } else if (typeof arg1 === "string") {
4141
+ message = new Message(arg1, arg2);
4142
+ } else if (typeof arg1 === "object" && arg1 !== null) {
4143
+ this.messages.push(arg1);
4144
+ const contentStr = arg1.content || JSON.stringify(arg1);
4145
+ this.currentTokens += this.estimateTokens(contentStr);
4146
+ return;
4147
+ } else {
4148
+ throw new Error(`Invalid message format: ${arg1}`);
4149
+ }
4150
+ this.messages.push(message);
4151
+ this.currentTokens += this.estimateTokens(message.content);
3367
4152
  }
3368
4153
  /**
3369
- * Create message from assistant response
4154
+ * Get all messages
3370
4155
  */
3371
- static fromAssistantMsg(content) {
3372
- return new _Message("assistant", content);
4156
+ getMessages() {
4157
+ return [...this.messages];
3373
4158
  }
3374
4159
  /**
3375
- * Create system message
4160
+ * Get messages formatted for API calls
4161
+ * Async version to handle base64 image encoding
3376
4162
  */
3377
- static fromSystemMsg(content) {
3378
- return new _Message("system", content);
3379
- }
3380
- /**
3381
- * Convert to plain object for API calls
3382
- */
3383
- toObject() {
3384
- const obj = {
3385
- role: this.role,
3386
- content: this.content
3387
- };
3388
- if (this.images) {
3389
- obj.images = this.images;
3390
- }
3391
- if (this.type) {
3392
- obj.type = this.type;
3393
- }
3394
- return obj;
3395
- }
3396
- /**
3397
- * Check if message contains images
3398
- */
3399
- hasImages() {
3400
- return !!this.images && (Array.isArray(this.images) ? this.images.length > 0 : true);
3401
- }
3402
- /**
3403
- * Get message content length
3404
- */
3405
- getContentLength() {
3406
- return this.content.length;
3407
- }
3408
- /**
3409
- * Convert to string representation
3410
- */
3411
- toString() {
3412
- return `${this.role}: ${this.content}`;
3413
- }
3414
- /**
3415
- * Convert to OpenAI Vision API format with base64-encoded images
3416
- * This method handles:
3417
- * - HTTP/HTTPS URLs: Downloads and converts to base64
3418
- * - Local file paths: Reads file and converts to base64
3419
- * - Already base64 strings: Passes through
3420
- */
3421
- async toChatMessage() {
3422
- const role = this.role;
3423
- if (!this.hasImages()) {
3424
- return { role, content: this.content };
3425
- }
3426
- const content = [{ type: "text", text: this.content }];
3427
- const imageArray = Array.isArray(this.images) ? this.images : [this.images];
3428
- for (const img of imageArray) {
3429
- let base64Data;
3430
- if (img.startsWith("http://") || img.startsWith("https://")) {
3431
- base64Data = await this.encodeHttpImage(img);
3432
- } else if (fs7.existsSync(img)) {
3433
- base64Data = await this.encodeLocalFile(img);
3434
- } else {
3435
- base64Data = img;
3436
- }
3437
- const mimeType = this.getMimeType(img);
3438
- content.push({
3439
- type: "image_url",
3440
- image_url: { url: `data:${mimeType};base64,${base64Data}` }
3441
- });
3442
- }
3443
- return { role, content };
3444
- }
3445
- /**
3446
- * Get MIME type from file path or URL
3447
- */
3448
- getMimeType(path5) {
3449
- const ext = path5.toLowerCase().split(".").pop();
3450
- const mimeTypes = {
3451
- png: "image/png",
3452
- jpg: "image/jpeg",
3453
- jpeg: "image/jpeg",
3454
- gif: "image/gif",
3455
- webp: "image/webp",
3456
- bmp: "image/bmp"
3457
- };
3458
- return mimeTypes[ext || ""] || "image/jpeg";
3459
- }
3460
- /**
3461
- * Encode local file to base64
3462
- */
3463
- async encodeLocalFile(filePath) {
3464
- const fileBuffer = await fs7.promises.readFile(filePath);
3465
- return fileBuffer.toString("base64");
3466
- }
3467
- /**
3468
- * Fetch and encode HTTP image to base64
3469
- */
3470
- async encodeHttpImage(url) {
3471
- const response = await fetch(url);
3472
- if (!response.ok) {
3473
- throw new Error(`Failed to fetch image from ${url}: ${response.statusText}`);
3474
- }
3475
- const buffer = await response.arrayBuffer();
3476
- return Buffer.from(buffer).toString("base64");
3477
- }
3478
- };
3479
-
3480
- // src/memory/messageHistory.ts
3481
- var MessageHistory = class {
3482
- messages = [];
3483
- systemPrompt;
3484
- model;
3485
- contextWindowTokens;
3486
- currentTokens = 0;
3487
- constructor(model, system, contextWindowTokens) {
3488
- this.model = model;
3489
- this.systemPrompt = system;
3490
- this.contextWindowTokens = contextWindowTokens;
3491
- if (system) {
3492
- const systemMessage = new Message("system", system);
3493
- this.messages.push(systemMessage);
3494
- this.currentTokens += this.estimateTokens(system);
3495
- }
3496
- }
3497
- addMessage(arg1, arg2) {
3498
- let message;
3499
- if (arg1 instanceof Message) {
3500
- message = arg1;
3501
- } else if (typeof arg1 === "string") {
3502
- message = new Message(arg1, arg2);
3503
- } else if (typeof arg1 === "object" && arg1 !== null) {
3504
- this.messages.push(arg1);
3505
- const contentStr = arg1.content || JSON.stringify(arg1);
3506
- this.currentTokens += this.estimateTokens(contentStr);
3507
- return;
3508
- } else {
3509
- throw new Error(`Invalid message format: ${arg1}`);
3510
- }
3511
- this.messages.push(message);
3512
- this.currentTokens += this.estimateTokens(message.content);
3513
- }
3514
- /**
3515
- * Get all messages
3516
- */
3517
- getMessages() {
3518
- return [...this.messages];
3519
- }
3520
- /**
3521
- * Get messages formatted for API calls
3522
- * Async version to handle base64 image encoding
3523
- */
3524
- async formatForApi() {
3525
- const results = [];
3526
- for (const msg of this.messages) {
3527
- if (msg instanceof Message) {
3528
- if (msg.hasImages()) {
3529
- results.push(await msg.toChatMessage());
3530
- } else {
3531
- results.push(msg.toObject());
3532
- }
3533
- } else if (typeof msg.toObject === "function") {
3534
- results.push(msg.toObject());
3535
- } else {
3536
- results.push(msg);
3537
- }
3538
- }
3539
- return results;
4163
+ async formatForApi() {
4164
+ const results = [];
4165
+ for (const msg of this.messages) {
4166
+ if (msg instanceof Message) {
4167
+ if (msg.hasImages()) {
4168
+ results.push(await msg.toChatMessage());
4169
+ } else {
4170
+ results.push(msg.toObject());
4171
+ }
4172
+ } else if (typeof msg.toObject === "function") {
4173
+ results.push(msg.toObject());
4174
+ } else {
4175
+ results.push(msg);
4176
+ }
4177
+ }
4178
+ return results;
3540
4179
  }
3541
4180
  /**
3542
4181
  * Update system prompt
@@ -3796,7 +4435,7 @@ var ToolcallManager = class {
3796
4435
  return;
3797
4436
  }
3798
4437
  while (this.semaphore.available <= 0) {
3799
- await new Promise((resolve2) => setTimeout(resolve2, 100));
4438
+ await new Promise((resolve5) => setTimeout(resolve5, 100));
3800
4439
  }
3801
4440
  this.semaphore.available--;
3802
4441
  try {
@@ -3886,7 +4525,7 @@ background process observation: ${backgroundResult.content}`;
3886
4525
  async observe(waitAll = false, timeout = null) {
3887
4526
  await this.execute();
3888
4527
  if (this.tasks.size > 0 && !waitAll) {
3889
- await new Promise((resolve2) => setTimeout(resolve2, 1e3));
4528
+ await new Promise((resolve5) => setTimeout(resolve5, 1e3));
3890
4529
  }
3891
4530
  if (waitAll && this.tasks.size > 0) {
3892
4531
  if (timeout) {
@@ -3960,7 +4599,7 @@ background process observation: ${backgroundResult.content}`;
3960
4599
  */
3961
4600
  async monitorProcess(processId, process2) {
3962
4601
  try {
3963
- await new Promise((resolve2, reject) => {
4602
+ await new Promise((resolve5, reject) => {
3964
4603
  process2.on("exit", (code) => {
3965
4604
  if (this.backgroundProcesses.has(processId)) {
3966
4605
  const command = this.backgroundProcesses.get(processId).command;
@@ -3970,7 +4609,7 @@ background process observation: ${backgroundResult.content}`;
3970
4609
  if (this.monitorTasks.has(processId)) {
3971
4610
  this.monitorTasks.delete(processId);
3972
4611
  }
3973
- resolve2();
4612
+ resolve5();
3974
4613
  });
3975
4614
  process2.on("error", (error) => {
3976
4615
  reject(error);
@@ -4022,17 +4661,17 @@ PID: ${info.pid}`;
4022
4661
  logger.info(`\u7EC8\u6B62\u540E\u53F0\u8FDB\u7A0B: ${command} (PID: ${process2.pid})`);
4023
4662
  }
4024
4663
  try {
4025
- await new Promise((resolve2) => {
4664
+ await new Promise((resolve5) => {
4026
4665
  const timeoutId = setTimeout(() => {
4027
4666
  if (!force) {
4028
4667
  process2.kill("SIGKILL");
4029
4668
  logger.warn(`\u540E\u53F0\u8FDB\u7A0B\u672A\u54CD\u5E94\u7EC8\u6B62\u4FE1\u53F7\uFF0C\u5DF2\u5F3A\u5236\u6740\u6B7B: ${command}`);
4030
4669
  }
4031
- resolve2();
4670
+ resolve5();
4032
4671
  }, 5e3);
4033
4672
  process2.on("exit", () => {
4034
4673
  clearTimeout(timeoutId);
4035
- resolve2();
4674
+ resolve5();
4036
4675
  });
4037
4676
  });
4038
4677
  } catch (error) {
@@ -4116,69 +4755,48 @@ PID: ${info.pid}`;
4116
4755
  };
4117
4756
 
4118
4757
  // src/prompts/tools.ts
4119
- var OUTPUT_FORMAT_PROMPT = `<System Tools OutputFormat>
4120
-
4121
- We have three types of tasks: Generative Tasks, Analytical Tasks, and Operational Tasks.
4122
- You should choose the appropriate task type based on the task description.
4123
-
4124
- #### Generative Tasks Output Format
4125
- <Generative Tasks Purpose>Create Something New</Generative Tasks Purpose>
4126
-
4127
- <Generative Tasks Definition>
4128
- These tasks focus on creating new artifacts from scratch, such as text, code, designs, or configurations.
4129
- The model synthesizes information and produces original outputs.
4130
- </Generative Tasks Definition>
4131
-
4132
- <Generative Tasks Output Format>
4133
- Output a sequence of tool calls in the format below. Replace <ToolName.method_name> and <args_name> with actual tool and parameter names.
4134
-
4135
- You may interleave tool calls with reasoning or explanations as needed:
4136
-
4137
- [Your reasoning or explanation here...]
4138
- <ToolName.method_name><args_name1>args_value1</args_name1><args_name2>args_value2</args_name2>...</ToolName.method_name>
4139
-
4140
- [Additional thoughts or context...]
4141
- <ToolName2.method_name2><args_name1>args_value1</args_name1><args_name2>args_value2</args_name2>...</ToolName2.method_name2>
4142
- ...
4143
- </Generative Tasks Output Format>
4758
+ var REFLECT_OUTPUT_FORMAT_PROMPT = `**Reflection Prompt: Output Format Error**
4759
+ Your output does not follow the required XML format:
4760
+ <OutputFormat>
4761
+ <ToolName.method_name><arg1_name>value1</arg1_name><arg2_name>value2</arg2_name></ToolName.method_name>
4762
+ </OutputFormat>
4144
4763
 
4764
+ Your erroneous output:
4765
+ {output_text}
4145
4766
 
4146
- ### Analytical Tasks Output Format
4147
- <Analytical Tasks Purpose>Understand, Diagnose & Evaluate Existing Information</Analytical Tasks Purpose>
4767
+ Please analyze the format discrepancies and re-output, ensuring:
4148
4768
 
4149
- <Analytical Tasks Definition>
4150
- Analytical tasks focus on understanding, decomposing, diagnosing, and evaluating existing information.
4151
- They include requirement analysis, code and system comprehension, quality evaluation, debugging and root-cause analysis, and data or behavioral analysis.
4152
- Such tasks produce structured insights and decisions that guide subsequent generative or operational steps.
4153
- </Analytical Tasks Definition>
4769
+ - Use the correct XML tag structure
4770
+ - All tags are properly closed
4771
+ - Parameter values are placed within the corresponding tags
4154
4772
 
4155
- <Analytical Tasks Output Format>
4156
- You should fellow the format below, replace the <ToolName.method_name> and <args_name> with the actual name.
4157
-
4158
- Thoughts: ...
4159
- ToolCall: <ToolName.method_name><args_name1>args_value1</args_name1><args_name2>args_value2</args_name2>...</ToolName.method_name>
4160
- // stop ToolCall here, and wait for the Observation of the ToolCall.
4773
+ Re-output:
4774
+ `;
4775
+ var OUTPUT_FORMAT_PROMPT = `<OutputFormat>
4161
4776
 
4162
- </Analytical Tasks Output Format>
4777
+ You should use one tool or multiple tools (depends on your task), follow the format below, replace the <ToolName.method_name> and <args_name> with the actual tool name.
4163
4778
 
4164
- ### Operational Tasks Output Format
4779
+ Thought: ...
4780
+ Action: <ToolName1.method_name1><args_name1>args_value1</args_name1><args_name2>args_value2</args_name2>...</ToolName1.method_name1>
4165
4781
 
4166
- <Operational Tasks Purpose>Act & Operate Tools</Operational Tasks Purpose>
4782
+ **YOUR OUTPUT MUST INCLUDE THE ACTUAL <args_name> AND <args_value>!!!**
4783
+ **If the task is completed, simply return the completion information like <TaskCompletion>your_completion_information</TaskCompletion>, No any tool call should be included.**
4784
+ </OutputFormat>
4785
+ `;
4786
+ var TOOLS_PROMPT = `
4787
+ ## Tools And Tool Calls Format
4167
4788
 
4168
- <Operational Tasks Definition>
4169
- These tasks involve performing concrete actions through tools, systems, or commands.
4170
- The focus is on executing operations rather than generating or analyzing content.
4171
- </Operational Tasks Definition>
4789
+ Tools are represented by a predefined XML-like syntax structure. This structure encapsulates parameter lists within tags such as \`<ToolName.method_name>\`.
4790
+ By identifying and matching keywords inside these tags, the system automatically parses the target tool name and its corresponding input parameter values to execute subsequent tool calls.
4172
4791
 
4173
- <Operational Tasks Output Format>
4174
- You should follow the format below, replace the <ToolName.method_name> and <args_name> with the actual name.
4792
+ ### Available Tools
4793
+ {available_tools}
4175
4794
 
4176
- <ToolName.method_name><args_name1>args_value1</args_name1><args_name2>args_value2</args_name2>...</ToolName.method_name>
4177
- </Operational Tasks Output Format>
4795
+ ### Description of Available Tools
4796
+ {desc_of_tools}
4178
4797
 
4179
- **YOUR OUTPUT MUST INCLUDE THE ACTUAL <args_name> AND <args_value>!!!**
4180
- **If the task is completed, simply return the completion information like <TaskCompletion>your_completion_information</TaskCompletion>, No any tool call should be included.**
4181
- </System Tools OutputFormat>
4798
+ ### Output Format
4799
+ {output_format}
4182
4800
  `;
4183
4801
  var SYSTEM_TOOLS_PROMPT = `
4184
4802
  ## System Tools And System Tools Call Format
@@ -4196,7 +4814,7 @@ By identifying and matching keywords inside these tags, the system automatically
4196
4814
  {outputFormat}
4197
4815
  `;
4198
4816
 
4199
- // src/agent.ts
4817
+ // src/core/agent.ts
4200
4818
  var Agent = class {
4201
4819
  name;
4202
4820
  profile;
@@ -4212,6 +4830,14 @@ var Agent = class {
4212
4830
  toolcallManagerPoolSize;
4213
4831
  postProcessor;
4214
4832
  useFunctionCalling;
4833
+ // New properties from Python 0.2.2
4834
+ agentId;
4835
+ workspaceDir;
4836
+ executor;
4837
+ autoShutdownExecutor;
4838
+ parallelExecution;
4839
+ observeTimeout;
4840
+ skills;
4215
4841
  constructor(config2) {
4216
4842
  const {
4217
4843
  name,
@@ -4221,18 +4847,38 @@ var Agent = class {
4221
4847
  subAgents = [],
4222
4848
  mcpServerNames = [],
4223
4849
  modelConfig,
4850
+ udfModelName,
4224
4851
  verbose = false,
4225
4852
  useFunctionCalling = false,
4226
4853
  postProcessor = null,
4227
- toolcallManagerPoolSize = 5
4854
+ toolcallManagerPoolSize = 5,
4855
+ // New parameters from Python 0.2.2
4856
+ agentId,
4857
+ workspaceDir = "",
4858
+ executor = null,
4859
+ autoShutdownExecutor = false,
4860
+ parallelExecution = false,
4861
+ observeTimeout = 60,
4862
+ skills = []
4228
4863
  } = config2;
4229
4864
  this.name = name;
4230
4865
  this.profile = profile;
4231
4866
  this.verbose = verbose;
4232
- this.modelConfig = modelConfig || "deepseek";
4867
+ this.modelConfig = udfModelName || modelConfig || "deepseek";
4233
4868
  this.subAgents = subAgents || [];
4234
4869
  this.postProcessor = postProcessor;
4235
4870
  this.useFunctionCalling = useFunctionCalling;
4871
+ this.agentId = agentId || uuidv4();
4872
+ this.workspaceDir = workspaceDir ? path7.resolve(workspaceDir) : "";
4873
+ this.executor = executor;
4874
+ this.autoShutdownExecutor = autoShutdownExecutor;
4875
+ this.parallelExecution = parallelExecution;
4876
+ this.observeTimeout = observeTimeout;
4877
+ this.skills = skills;
4878
+ if (this.workspaceDir && !fs10.existsSync(this.workspaceDir)) {
4879
+ fs10.mkdirSync(this.workspaceDir, { recursive: true });
4880
+ logger.debug(`Created workspace directory for agent ${this.name}: ${this.workspaceDir}`);
4881
+ }
4236
4882
  const agentToolNames = registerAgentAsTool(this.subAgents, Boolean(this.verbose));
4237
4883
  this.tools = [...tools2, ...agentToolNames];
4238
4884
  this.mcpServerNames = mcpServerNames;
@@ -4501,6 +5147,14 @@ var Agent = class {
4501
5147
  throw error;
4502
5148
  } finally {
4503
5149
  await stack.close();
5150
+ if (this.autoShutdownExecutor && this.executor) {
5151
+ try {
5152
+ await this.executor.shutdown({ wait: true });
5153
+ logger.debug(`Executor shutdown completed for agent ${this.name}`);
5154
+ } catch (error) {
5155
+ logger.warn(`Error during executor shutdown: ${error}`);
5156
+ }
5157
+ }
4504
5158
  }
4505
5159
  }
4506
5160
  /**
@@ -4554,21 +5208,192 @@ var Agent = class {
4554
5208
  getSubAgents() {
4555
5209
  return [...this.subAgents];
4556
5210
  }
5211
+ /**
5212
+ * Get agent ID
5213
+ */
5214
+ getAgentId() {
5215
+ return this.agentId;
5216
+ }
5217
+ /**
5218
+ * Get workspace directory
5219
+ */
5220
+ getWorkspaceDir() {
5221
+ return this.workspaceDir;
5222
+ }
5223
+ /**
5224
+ * Get parallel execution setting
5225
+ */
5226
+ getParallelExecution() {
5227
+ return this.parallelExecution;
5228
+ }
5229
+ /**
5230
+ * Get observe timeout setting
5231
+ */
5232
+ getObserveTimeout() {
5233
+ return this.observeTimeout;
5234
+ }
5235
+ /**
5236
+ * Get skills
5237
+ */
5238
+ getSkills() {
5239
+ return [...this.skills];
5240
+ }
5241
+ /**
5242
+ * Get executor
5243
+ */
5244
+ getExecutor() {
5245
+ return this.executor;
5246
+ }
5247
+ /**
5248
+ * Set executor
5249
+ */
5250
+ setExecutor(executor) {
5251
+ this.executor = executor;
5252
+ }
5253
+ /**
5254
+ * Get chat history message
5255
+ */
5256
+ get chatHistoryMessage() {
5257
+ return this.history;
5258
+ }
5259
+ };
5260
+
5261
+ // src/schemas/feedback.ts
5262
+ var Feedback = class _Feedback {
5263
+ /**
5264
+ * Whether the test/evaluation passed
5265
+ */
5266
+ isPassing;
5267
+ /**
5268
+ * Detailed feedback message
5269
+ */
5270
+ feedback;
5271
+ constructor(isPassing = false, feedback) {
5272
+ this.isPassing = isPassing;
5273
+ this.feedback = feedback || new Message("user", "No feedback provided. Please check feedback settings.");
5274
+ this._validate();
5275
+ }
5276
+ /**
5277
+ * Validate the feedback
5278
+ */
5279
+ _validate() {
5280
+ if (!this.feedback.content) {
5281
+ throw new Error("Feedback content cannot be empty");
5282
+ }
5283
+ if (this.feedback.tag !== void 0) {
5284
+ if (!this.feedback.tag) {
5285
+ this.feedback.tag = "feedback";
5286
+ } else if (!this.feedback.tag.toLowerCase().includes("feedback")) {
5287
+ this.feedback.tag = `feedback_${this.feedback.tag}`;
5288
+ }
5289
+ }
5290
+ }
5291
+ /**
5292
+ * Convert feedback to a Message, optionally with pre/post content
5293
+ *
5294
+ * @param preContent - Content to prepend to the feedback
5295
+ * @param postContent - Content to append to the feedback
5296
+ * @returns Combined Message
5297
+ */
5298
+ toMessage(preContent = "", postContent = "") {
5299
+ const feedbackMsg = new Message(
5300
+ this.feedback.role,
5301
+ this.feedback.content,
5302
+ this.feedback.images,
5303
+ this.feedback.type
5304
+ );
5305
+ if (this.feedback.tag !== void 0) {
5306
+ feedbackMsg.tag = this.feedback.tag;
5307
+ }
5308
+ let result = feedbackMsg;
5309
+ if (preContent) {
5310
+ const preMsg = new Message("user", preContent);
5311
+ result = this._mergeMessages(preMsg, result);
5312
+ }
5313
+ if (postContent) {
5314
+ const postMsg = new Message("user", postContent);
5315
+ result = this._mergeMessages(result, postMsg);
5316
+ }
5317
+ return result;
5318
+ }
5319
+ /**
5320
+ * Merge two messages into one
5321
+ */
5322
+ _mergeMessages(first, second) {
5323
+ const merged = new Message(
5324
+ first.role,
5325
+ `${first.content}
5326
+ ${second.content}`,
5327
+ first.images || second.images,
5328
+ first.type || second.type
5329
+ );
5330
+ if (second.tag !== void 0) {
5331
+ merged.tag = second.tag;
5332
+ }
5333
+ return merged;
5334
+ }
5335
+ /**
5336
+ * Format feedback for API calls
5337
+ *
5338
+ * @param preContent - Content to prepend
5339
+ * @param postContent - Content to append
5340
+ * @returns Formatted object for API
5341
+ */
5342
+ formatForApi(preContent = "", postContent = "") {
5343
+ const message = this.toMessage(preContent, postContent);
5344
+ return message.toObject();
5345
+ }
5346
+ /**
5347
+ * Create a passing feedback
5348
+ */
5349
+ static pass(content) {
5350
+ return new _Feedback(true, new Message("user", content));
5351
+ }
5352
+ /**
5353
+ * Create a failing feedback
5354
+ */
5355
+ static fail(content) {
5356
+ return new _Feedback(false, new Message("user", content));
5357
+ }
4557
5358
  };
4558
5359
 
4559
- // src/environment/base.ts
4560
- var BaseEnvironment = class {
5360
+ // src/runtime/orchestrator/base.ts
5361
+ var InstructionType = /* @__PURE__ */ ((InstructionType2) => {
5362
+ InstructionType2["VALID"] = "valid";
5363
+ InstructionType2["QUIT"] = "quit";
5364
+ InstructionType2["SEND_TO_ALL"] = "sendToAll";
5365
+ InstructionType2["NO_AGENT_NAME"] = "noAgentName";
5366
+ InstructionType2["NO_AVAILABLE_AGENT_NAME"] = "noAvailableAgentName";
5367
+ return InstructionType2;
5368
+ })(InstructionType || {});
5369
+ var BaseOrchestrator = class {
4561
5370
  /**
4562
- * List of agents in the environment
5371
+ * List of agents in the orchestrator
4563
5372
  */
4564
5373
  agents = [];
4565
5374
  /**
4566
5375
  * Assign skills to agent with their names
4567
5376
  */
4568
5377
  agentSkills = {};
4569
- constructor(agents = [], agentSkills = {}) {
5378
+ /**
5379
+ * Whether to always wait for human input
5380
+ */
5381
+ alwaysWaitHumanInput = false;
5382
+ /**
5383
+ * Maximum number of rounds for agent execution
5384
+ */
5385
+ maxRounds = 100;
5386
+ constructor(options = {}) {
5387
+ const {
5388
+ agents = [],
5389
+ agentSkills = {},
5390
+ alwaysWaitHumanInput = false,
5391
+ maxRounds = 100
5392
+ } = options;
4570
5393
  this.agents = agents;
4571
5394
  this.agentSkills = agentSkills;
5395
+ this.alwaysWaitHumanInput = alwaysWaitHumanInput;
5396
+ this.maxRounds = maxRounds;
4572
5397
  this.setAgentSkills();
4573
5398
  }
4574
5399
  /**
@@ -4638,12 +5463,21 @@ var BaseEnvironment = class {
4638
5463
  }
4639
5464
  return ["noAvailableAgentName" /* NO_AVAILABLE_AGENT_NAME */, instruction];
4640
5465
  }
5466
+ /**
5467
+ * Shutdown all agent executors
5468
+ */
5469
+ async shutdownAllExecutors(options) {
5470
+ const wait = options?.wait ?? true;
5471
+ for (const agent of this.agents) {
5472
+ }
5473
+ logger.debug("All agent executors shutdown");
5474
+ }
4641
5475
  /**
4642
5476
  * Run with a single goal until completion (non-interactive mode)
4643
5477
  */
4644
5478
  async runGoal(goal) {
4645
5479
  if (this.agents.length === 0) {
4646
- logger.error("No agents in the environment.");
5480
+ logger.error("No agents in the orchestrator.");
4647
5481
  return;
4648
5482
  }
4649
5483
  const [instructionType, processedInstruction] = this.postProcessInstruction(
@@ -4674,36 +5508,40 @@ var BaseEnvironment = class {
4674
5508
  }
4675
5509
  }
4676
5510
  /**
4677
- * Run the environment (interactive mode)
5511
+ * Run the orchestrator (interactive mode)
4678
5512
  */
4679
- async run() {
5513
+ async run(instruction) {
5514
+ if (instruction) {
5515
+ await this.runGoal(instruction);
5516
+ return;
5517
+ }
4680
5518
  const readline = await import("readline");
4681
5519
  const rl = readline.createInterface({
4682
5520
  input: process.stdin,
4683
5521
  output: process.stdout
4684
5522
  });
4685
5523
  const question = (prompt) => {
4686
- return new Promise((resolve2) => {
4687
- rl.question(prompt, resolve2);
5524
+ return new Promise((resolve5) => {
5525
+ rl.question(prompt, resolve5);
4688
5526
  });
4689
5527
  };
4690
5528
  try {
4691
5529
  while (true) {
4692
5530
  try {
4693
- let instruction;
5531
+ let userInstruction;
4694
5532
  if (this.agents.length === 0) {
4695
- logger.error("No agents in the environment.");
5533
+ logger.error("No agents in the orchestrator.");
4696
5534
  break;
4697
5535
  } else if (this.agents.length === 1) {
4698
- instruction = await question("Enter your instruction (or '/q' to quit): ");
5536
+ userInstruction = await question("Enter your instruction (or '/q' to quit): ");
4699
5537
  } else {
4700
5538
  const agentNames = this.agents.map((agent) => agent.name).join(", ");
4701
- instruction = await question(
5539
+ userInstruction = await question(
4702
5540
  `Enter your instruction with '@agent_name' (or '/q' to quit), available agents: ${agentNames}: `
4703
5541
  );
4704
5542
  }
4705
5543
  const [instructionType, processedInstruction] = this.postProcessInstruction(
4706
- instruction,
5544
+ userInstruction,
4707
5545
  this.agents.map((agent) => agent.name)
4708
5546
  );
4709
5547
  if (instructionType === "quit" /* QUIT */) {
@@ -4729,16 +5567,18 @@ var BaseEnvironment = class {
4729
5567
  }
4730
5568
  }
4731
5569
  };
5570
+ var BaseEnvironment = BaseOrchestrator;
4732
5571
 
4733
- // src/environment/coding.ts
4734
- import * as fs8 from "fs";
4735
- var CodingEnvironment = class extends BaseEnvironment {
5572
+ // src/runtime/orchestrator/coding.ts
5573
+ import * as fs11 from "fs";
5574
+ var CodingOrchestrator = class extends BaseOrchestrator {
4736
5575
  /**
4737
5576
  * Workspace directory
4738
5577
  */
4739
5578
  workspaceDir = "";
4740
- constructor(agents = [], agentSkills = {}, workspaceDir = "") {
4741
- super(agents, agentSkills);
5579
+ constructor(options = {}) {
5580
+ const { workspaceDir = "", ...baseOptions } = options;
5581
+ super(baseOptions);
4742
5582
  this.workspaceDir = workspaceDir;
4743
5583
  this.setWorkspaceDir();
4744
5584
  }
@@ -4749,8 +5589,8 @@ var CodingEnvironment = class extends BaseEnvironment {
4749
5589
  if (!this.workspaceDir) {
4750
5590
  this.workspaceDir = WORKSPACE_DIR;
4751
5591
  }
4752
- if (!fs8.existsSync(this.workspaceDir)) {
4753
- fs8.mkdirSync(this.workspaceDir, { recursive: true });
5592
+ if (!fs11.existsSync(this.workspaceDir)) {
5593
+ fs11.mkdirSync(this.workspaceDir, { recursive: true });
4754
5594
  } else {
4755
5595
  logger.debug(`Workspace directory already exists: ${this.workspaceDir}`);
4756
5596
  }
@@ -4769,32 +5609,1206 @@ Your workspace directory is: <workspace>${this.workspaceDir}</workspace>
4769
5609
  }
4770
5610
  }
4771
5611
  };
5612
+ var CodingEnvironment = CodingOrchestrator;
5613
+
5614
+ // src/runtime/orchestrator/reflexion.ts
5615
+ var CRITIC_SYSTEM_PROMPT = `You are a critic agent specialized in {taskType} tasks.
5616
+
5617
+ Your role is to:
5618
+ 1. Analyze the implementation provided
5619
+ 2. Identify issues and areas for improvement
5620
+ 3. Provide constructive feedback in the form of {feedbackType}
5621
+ 4. Suggest specific improvements
5622
+
5623
+ Be thorough but constructive in your feedback.`;
5624
+ var ACTOR_SYSTEM_PROMPT = `You are an actor agent specialized in {taskType} tasks.
5625
+
5626
+ Your role is to:
5627
+ 1. Review the feedback and self-reflection
5628
+ 2. Improve the implementation based on the suggestions
5629
+ 3. Produce a better version of the code/output
5630
+
5631
+ Focus on addressing all issues mentioned in the feedback.`;
5632
+ var ReflexionOrchestrator = class {
5633
+ task;
5634
+ taskType;
5635
+ feedbackType;
5636
+ environment;
5637
+ criticAgentConfig;
5638
+ actorAgentConfig;
5639
+ maxIterations;
5640
+ constructor(options) {
5641
+ this.task = options.task;
5642
+ this.taskType = options.taskType;
5643
+ this.feedbackType = options.feedbackType;
5644
+ this.environment = options.environment;
5645
+ this.maxIterations = options.maxIterations ?? 3;
5646
+ this.criticAgentConfig = {
5647
+ name: "CriticAgent",
5648
+ profile: "You are an AI assistant.",
5649
+ tools: ["CommandLineTool.execute", "FileEditor.write", "FileEditor.read"],
5650
+ udfModelName: "deepseek",
5651
+ workspaceDir: "",
5652
+ fewShot: "",
5653
+ verbose: false,
5654
+ saveSelfReflection: false,
5655
+ postContent: "",
5656
+ ...options.criticAgentConfig
5657
+ };
5658
+ this.actorAgentConfig = {
5659
+ name: "ActorAgent",
5660
+ profile: "You are an AI engineer.",
5661
+ tools: ["CommandLineTool.execute", "FileEditor.write", "ThinkTool.execute"],
5662
+ udfModelName: "deepseek",
5663
+ workspaceDir: "",
5664
+ fewShot: "",
5665
+ verbose: false,
5666
+ ...options.actorAgentConfig
5667
+ };
5668
+ }
5669
+ /**
5670
+ * Create system prompt for critic agent
5671
+ */
5672
+ createCriticSystemPrompt() {
5673
+ return CRITIC_SYSTEM_PROMPT.replace("{taskType}", this.taskType).replace("{feedbackType}", this.feedbackType);
5674
+ }
5675
+ /**
5676
+ * Create system prompt for actor agent
5677
+ */
5678
+ createActorSystemPrompt() {
5679
+ return ACTOR_SYSTEM_PROMPT.replace("{taskType}", this.taskType).replace("{feedbackType}", this.feedbackType);
5680
+ }
5681
+ /**
5682
+ * Build history message for critic agent
5683
+ */
5684
+ buildCriticHistoryMessage(impl, feedback) {
5685
+ const preContent = this.criticAgentConfig.workspaceDir ? `Your workspace directory is: ${this.criticAgentConfig.workspaceDir}
5686
+
5687
+ ` : "";
5688
+ const postContent = (this.criticAgentConfig.postContent || "") + "\nDo not change the impl file, just use tools to find the correct way and give the self-reflection.";
5689
+ return [feedback.toMessage(preContent, postContent)];
5690
+ }
5691
+ /**
5692
+ * Build history message for actor agent
5693
+ */
5694
+ buildActorHistoryMessage(feedback, selfReflection, improvedImplPath) {
5695
+ const messages = [];
5696
+ if (this.actorAgentConfig.fewShot) {
5697
+ messages.push(new Message("user", this.actorAgentConfig.fewShot));
5698
+ }
5699
+ messages.push(feedback);
5700
+ messages.push(new Message(
5701
+ "assistant",
5702
+ `<self_reflection>
5703
+ ${selfReflection}
5704
+ </self_reflection>`
5705
+ ));
5706
+ messages.push(new Message(
5707
+ "user",
5708
+ `Use ThinkTool to recap the feedback and self-reflection, think how to improve the previous impl, and use FileEditor tools to write your improved implementation, and saved it to the file \`${improvedImplPath}\`.`
5709
+ ));
5710
+ return messages;
5711
+ }
5712
+ /**
5713
+ * Run the reflexion loop
5714
+ */
5715
+ async run() {
5716
+ const actor = new Agent({
5717
+ name: this.actorAgentConfig.name || "ActorAgent",
5718
+ profile: this.actorAgentConfig.profile || "You are an AI engineer.",
5719
+ system: this.createActorSystemPrompt(),
5720
+ tools: this.actorAgentConfig.tools,
5721
+ modelConfig: this.actorAgentConfig.udfModelName,
5722
+ verbose: this.actorAgentConfig.verbose
5723
+ });
5724
+ const critic = new Agent({
5725
+ name: this.criticAgentConfig.name || "CriticAgent",
5726
+ profile: this.criticAgentConfig.profile || "You are an AI assistant.",
5727
+ system: this.createCriticSystemPrompt(),
5728
+ tools: this.criticAgentConfig.tools,
5729
+ modelConfig: this.criticAgentConfig.udfModelName,
5730
+ verbose: this.criticAgentConfig.verbose
5731
+ });
5732
+ let currentRound = 0;
5733
+ let feedback = await this.environment.step(this.environment.initStepKwargs);
5734
+ let finalOutput = "";
5735
+ while (!feedback.isPassing && currentRound < this.maxIterations) {
5736
+ logger.debug(`Feedback: ${feedback.feedback.content}`);
5737
+ const criticHistoryMsgs = this.buildCriticHistoryMessage(
5738
+ this.environment.improvedImpl,
5739
+ feedback
5740
+ );
5741
+ let selfReflection = await critic.run(
5742
+ criticHistoryMsgs[0].content
5743
+ );
5744
+ if (selfReflection.includes("<TaskCompletion>")) {
5745
+ selfReflection = selfReflection.replace(/<TaskCompletion>/g, "<self-reflection>").replace(/<\/TaskCompletion>/g, "</self-reflection>").trim();
5746
+ }
5747
+ logger.info(`Critic agent self-reflection: ${selfReflection}`);
5748
+ const actorHistoryMsgs = this.buildActorHistoryMessage(
5749
+ criticHistoryMsgs[criticHistoryMsgs.length - 1],
5750
+ selfReflection,
5751
+ this.environment.improvedImpl
5752
+ );
5753
+ let improvedImplSummary = await actor.run(
5754
+ actorHistoryMsgs[actorHistoryMsgs.length - 1].content
5755
+ );
5756
+ if (improvedImplSummary.includes("<TaskCompletion>")) {
5757
+ improvedImplSummary = improvedImplSummary.replace(/<TaskCompletion>/g, "<improved-impl-summary>").replace(/<\/TaskCompletion>/g, "</improved-impl-summary>").trim();
5758
+ }
5759
+ logger.info(`Actor agent improved impl summary: ${improvedImplSummary}`);
5760
+ finalOutput = improvedImplSummary;
5761
+ feedback = await this.environment.step(this.environment.improvedStepKwargs);
5762
+ currentRound++;
5763
+ }
5764
+ logger.info(`Reflection task completed in ${currentRound} rounds`);
5765
+ try {
5766
+ await this.environment.shutdown();
5767
+ logger.info("Environment shutdown completed");
5768
+ } catch (error) {
5769
+ logger.warn(`Error during environment shutdown: ${error}`);
5770
+ }
5771
+ return {
5772
+ success: feedback.isPassing,
5773
+ iterations: currentRound,
5774
+ finalOutput
5775
+ };
5776
+ }
5777
+ };
5778
+
5779
+ // src/runtime/environment/base.ts
5780
+ import * as fs12 from "fs";
5781
+ import * as path8 from "path";
5782
+ var Environment = class {
5783
+ /**
5784
+ * Arguments for the step method (initial implementation)
5785
+ */
5786
+ initStepKwargs = {};
5787
+ /**
5788
+ * Arguments for the step method (improved implementation)
5789
+ */
5790
+ improvedStepKwargs = {};
5791
+ /**
5792
+ * Path to the initial implementation file
5793
+ */
5794
+ initImpl;
5795
+ /**
5796
+ * Path to the improved implementation file
5797
+ */
5798
+ improvedImpl;
5799
+ constructor(options) {
5800
+ this.initImpl = path8.resolve(options.initImpl);
5801
+ this.improvedImpl = path8.resolve(options.improvedImpl);
5802
+ this.initStepKwargs = options.initStepKwargs || {};
5803
+ this.improvedStepKwargs = options.improvedStepKwargs || {};
5804
+ this._initImprovedImpl();
5805
+ }
5806
+ /**
5807
+ * Initialize the improved implementation by copying from init
5808
+ */
5809
+ _initImprovedImpl() {
5810
+ if (fs12.existsSync(this.initImpl)) {
5811
+ if (fs12.existsSync(this.improvedImpl)) {
5812
+ const stats = fs12.statSync(this.improvedImpl);
5813
+ if (stats.isDirectory()) {
5814
+ fs12.rmSync(this.improvedImpl, { recursive: true });
5815
+ } else {
5816
+ fs12.unlinkSync(this.improvedImpl);
5817
+ }
5818
+ }
5819
+ fs12.copyFileSync(this.initImpl, this.improvedImpl);
5820
+ }
5821
+ }
5822
+ /**
5823
+ * Check if the improved implementation exists
5824
+ */
5825
+ hasImprovedImpl() {
5826
+ return fs12.existsSync(this.improvedImpl);
5827
+ }
5828
+ /**
5829
+ * Shutdown the environment
5830
+ *
5831
+ * Called when the evaluation is complete or interrupted.
5832
+ * Override to clean up resources.
5833
+ */
5834
+ async shutdown() {
5835
+ }
5836
+ /**
5837
+ * Evaluate the environment on a benchmark
5838
+ *
5839
+ * TODO: Add benchmark support for self-evolving
5840
+ *
5841
+ * @returns Whether the benchmark passed
5842
+ */
5843
+ async bench() {
5844
+ throw new Error("bench() is not implemented");
5845
+ }
5846
+ };
5847
+
5848
+ // src/runtime/executors/base.ts
5849
+ function createGeneratedToolcall(options) {
5850
+ const toolCallId = options.toolCallId || `call_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
5851
+ return {
5852
+ toolName: options.toolName,
5853
+ toolArguments: options.toolArguments,
5854
+ toolCallId,
5855
+ source: options.source || "chat",
5856
+ isSuccess: true,
5857
+ rawContentFromLlm: options.rawContentFromLlm,
5858
+ idempotencyKey: `${options.toolName}-${JSON.stringify(options.toolArguments)}-${toolCallId}`
5859
+ };
5860
+ }
5861
+ function createExecutedToolcall(metadata, isSuccess, result) {
5862
+ return {
5863
+ metadata,
5864
+ isSuccess,
5865
+ result
5866
+ };
5867
+ }
5868
+
5869
+ // src/runtime/executors/utils.ts
5870
+ async function _executeSingleTool(generatedToolcall, toolStore) {
5871
+ const toolStores = Array.isArray(toolStore) ? toolStore : [toolStore];
5872
+ if (!generatedToolcall.isSuccess) {
5873
+ return createExecutedToolcall(
5874
+ generatedToolcall,
5875
+ false,
5876
+ `Tool extraction failed: ${generatedToolcall.failedReason || "Unknown"}`
5877
+ );
5878
+ }
5879
+ if (generatedToolcall.toolName.toLowerCase() === "taskcompletion") {
5880
+ return createExecutedToolcall(
5881
+ generatedToolcall,
5882
+ true,
5883
+ "The task has been completed."
5884
+ );
5885
+ }
5886
+ try {
5887
+ for (const ts of toolStores) {
5888
+ if (ts.hasTool && ts.hasTool(generatedToolcall.toolName)) {
5889
+ const toolDef = ts.getTool(generatedToolcall.toolName);
5890
+ if (!toolDef) {
5891
+ continue;
5892
+ }
5893
+ const toolExecute = toolDef.execute;
5894
+ if (!toolExecute) {
5895
+ return createExecutedToolcall(
5896
+ generatedToolcall,
5897
+ false,
5898
+ `Tool '${generatedToolcall.toolName}' has no execute function`
5899
+ );
5900
+ }
5901
+ const result = await toolExecute(generatedToolcall.toolArguments);
5902
+ const resultValue = result instanceof Message ? result : String(result);
5903
+ return createExecutedToolcall(
5904
+ generatedToolcall,
5905
+ true,
5906
+ resultValue
5907
+ );
5908
+ }
5909
+ }
5910
+ return createExecutedToolcall(
5911
+ generatedToolcall,
5912
+ false,
5913
+ `Tool '${generatedToolcall.toolName}' not found in tool_store. Please check the tool name.`
5914
+ );
5915
+ } catch (error) {
5916
+ const errorMsg = `Error executing tool: ${error instanceof Error ? error.message : String(error)}`;
5917
+ logger.error(errorMsg);
5918
+ return createExecutedToolcall(
5919
+ generatedToolcall,
5920
+ false,
5921
+ errorMsg
5922
+ );
5923
+ }
5924
+ }
5925
+ async function executeToolsSequential(toolcalls, toolStore) {
5926
+ const results = [];
5927
+ for (const toolcall of toolcalls) {
5928
+ const result = await _executeSingleTool(toolcall, toolStore);
5929
+ results.push(result);
5930
+ }
5931
+ return results;
5932
+ }
5933
+ async function executeToolsParallel(toolcalls, toolStore, maxConcurrency = 5) {
5934
+ const results = [];
5935
+ const pending = [];
5936
+ let runningCount = 0;
5937
+ for (const toolcall of toolcalls) {
5938
+ while (runningCount >= maxConcurrency) {
5939
+ await Promise.race(pending);
5940
+ }
5941
+ runningCount++;
5942
+ const promise = (async () => {
5943
+ try {
5944
+ const result = await _executeSingleTool(toolcall, toolStore);
5945
+ results.push(result);
5946
+ } finally {
5947
+ runningCount--;
5948
+ }
5949
+ })();
5950
+ pending.push(promise);
5951
+ }
5952
+ await Promise.all(pending);
5953
+ return results;
5954
+ }
5955
+
5956
+ // src/runtime/executors/localExecutor.ts
5957
+ import { v4 as uuidv42 } from "uuid";
5958
+ var _currentExecutor = null;
5959
+ function getCurrentExecutor() {
5960
+ return _currentExecutor;
5961
+ }
5962
+ function setCurrentExecutor(executor) {
5963
+ _currentExecutor = executor;
5964
+ }
5965
+ var LocalToolExecutor = class {
5966
+ poolSize;
5967
+ toolStores;
5968
+ // Concurrency control
5969
+ semaphore;
5970
+ // Task management
5971
+ pendingTasks = [];
5972
+ runningTasks = /* @__PURE__ */ new Set();
5973
+ finishedResults = [];
5974
+ successTasks = /* @__PURE__ */ new Map();
5975
+ failedTasks = /* @__PURE__ */ new Map();
5976
+ // Statistics
5977
+ totalSubmitted = 0;
5978
+ totalFinished = 0;
5979
+ totalFailed = 0;
5980
+ // Lifecycle state
5981
+ started = false;
5982
+ isShutdown = false;
5983
+ // Background process management
5984
+ backgroundProcesses = /* @__PURE__ */ new Map();
5985
+ constructor(poolSize = 5, toolStores = []) {
5986
+ this.poolSize = poolSize;
5987
+ this.toolStores = toolStores;
5988
+ this.semaphore = { available: poolSize };
5989
+ }
5990
+ // ---- Lifecycle Methods ----
5991
+ async start() {
5992
+ if (this.started) {
5993
+ logger.warn("Executor already started");
5994
+ return;
5995
+ }
5996
+ this.semaphore = { available: this.poolSize };
5997
+ this.started = true;
5998
+ this.isShutdown = false;
5999
+ logger.info(`LocalToolExecutor started with max concurrency: ${this.poolSize}`);
6000
+ }
6001
+ async shutdown(options) {
6002
+ const wait = options?.wait ?? true;
6003
+ if (this.isShutdown) {
6004
+ logger.warn("Executor already shutdown");
6005
+ return;
6006
+ }
6007
+ this.isShutdown = true;
6008
+ if (wait && this.runningTasks.size > 0) {
6009
+ logger.info(`Waiting for ${this.runningTasks.size} running tasks to complete...`);
6010
+ await Promise.allSettled(Array.from(this.runningTasks));
6011
+ logger.info("All tasks completed");
6012
+ }
6013
+ if (this.backgroundProcesses.size > 0) {
6014
+ logger.info("Cleaning up background processes...");
6015
+ await this.cleanupBackgroundProcesses();
6016
+ }
6017
+ this.started = false;
6018
+ logger.info("LocalToolExecutor shutdown");
6019
+ }
6020
+ // ---- Execution Methods ----
6021
+ async submit(toolcall) {
6022
+ if (!this.started) {
6023
+ throw new Error("Executor not started. Call start() first.");
6024
+ }
6025
+ if (this.isShutdown) {
6026
+ throw new Error("Executor already shutdown");
6027
+ }
6028
+ this.totalSubmitted++;
6029
+ const task = this._executeToolcall(toolcall);
6030
+ this.runningTasks.add(task);
6031
+ task.finally(() => {
6032
+ this.runningTasks.delete(task);
6033
+ });
6034
+ logger.debug(`Submitted tool call: ${toolcall.toolName}`);
6035
+ }
6036
+ async submitMany(toolcalls, options) {
6037
+ if (!this.started) {
6038
+ throw new Error("Executor not started. Call start() first.");
6039
+ }
6040
+ const toolcallList = Array.from(toolcalls);
6041
+ if (toolcallList.length === 0) {
6042
+ return;
6043
+ }
6044
+ const parallel = options?.parallel ?? true;
6045
+ if (parallel) {
6046
+ for (const toolcall of toolcallList) {
6047
+ await this.submit(toolcall);
6048
+ }
6049
+ logger.debug(`Submitted ${toolcallList.length} tool calls in parallel`);
6050
+ } else {
6051
+ logger.debug(`Starting sequential execution of ${toolcallList.length} tool calls`);
6052
+ for (const toolcall of toolcallList) {
6053
+ await this.submit(toolcall);
6054
+ while (this.runningTasks.size > 0) {
6055
+ await new Promise((resolve5) => setTimeout(resolve5, 100));
6056
+ }
6057
+ }
6058
+ logger.debug("Sequential execution completed");
6059
+ }
6060
+ }
6061
+ // ---- Observation Methods ----
6062
+ async observe(options) {
6063
+ const wait = options?.wait ?? false;
6064
+ const timeout = options?.timeout;
6065
+ const maxItems = options?.maxItems;
6066
+ if (wait && this.finishedResults.length === 0 && this.runningTasks.size > 0) {
6067
+ const startTime = Date.now();
6068
+ while (this.finishedResults.length === 0 && this.runningTasks.size > 0) {
6069
+ if (timeout !== void 0) {
6070
+ const elapsed = (Date.now() - startTime) / 1e3;
6071
+ if (elapsed >= timeout) {
6072
+ logger.warn(`Observe timeout (${timeout}s), no results yet`);
6073
+ break;
6074
+ }
6075
+ }
6076
+ await new Promise((resolve5) => setTimeout(resolve5, 100));
6077
+ }
6078
+ }
6079
+ const results = [];
6080
+ let count = 0;
6081
+ while (this.finishedResults.length > 0 && (maxItems === void 0 || count < maxItems)) {
6082
+ results.push(this.finishedResults.shift());
6083
+ count++;
6084
+ }
6085
+ if (results.length > 0) {
6086
+ logger.debug(`Returning ${results.length} execution results`);
6087
+ }
6088
+ return results;
6089
+ }
6090
+ async waitAll() {
6091
+ if (this.runningTasks.size > 0) {
6092
+ logger.debug(`Waiting for ${this.runningTasks.size} tasks to complete...`);
6093
+ await Promise.allSettled(Array.from(this.runningTasks));
6094
+ logger.info("All tasks completed");
6095
+ }
6096
+ }
6097
+ // ---- Status Methods ----
6098
+ status() {
6099
+ return {
6100
+ pending: this.pendingTasks.length,
6101
+ running: this.runningTasks.size,
6102
+ finished: this.successTasks.size,
6103
+ failed: this.failedTasks.size,
6104
+ totalSubmitted: this.totalSubmitted,
6105
+ isRunning: this.started && !this.isShutdown
6106
+ };
6107
+ }
6108
+ clear() {
6109
+ const cleared = this.finishedResults.length;
6110
+ this.finishedResults = [];
6111
+ this.successTasks.clear();
6112
+ this.failedTasks.clear();
6113
+ if (cleared > 0) {
6114
+ logger.debug(`Cleared ${cleared} execution results`);
6115
+ }
6116
+ }
6117
+ // ---- Private Methods ----
6118
+ async _executeToolcall(toolcall) {
6119
+ if (this.successTasks.has(toolcall.idempotencyKey) || this.failedTasks.has(toolcall.idempotencyKey)) {
6120
+ logger.debug(`Tool call already executed: ${toolcall.toolName}, using cached result`);
6121
+ const result = this.successTasks.get(toolcall.idempotencyKey) || this.failedTasks.get(toolcall.idempotencyKey);
6122
+ if (result) {
6123
+ this.finishedResults.push(result);
6124
+ }
6125
+ return;
6126
+ }
6127
+ if (!toolcall.isSuccess) {
6128
+ logger.warn(`Tool call extraction failed: ${toolcall.toolName}, reason: ${toolcall.failedReason || "Unknown"}`);
6129
+ const result = createExecutedToolcall(
6130
+ toolcall,
6131
+ false,
6132
+ `Tool extraction failed: ${toolcall.failedReason || "Unknown"}`
6133
+ );
6134
+ this.finishedResults.push(result);
6135
+ this.totalFailed++;
6136
+ this.failedTasks.set(toolcall.idempotencyKey, result);
6137
+ return;
6138
+ }
6139
+ while (this.semaphore.available <= 0) {
6140
+ await new Promise((resolve5) => setTimeout(resolve5, 100));
6141
+ }
6142
+ this.semaphore.available--;
6143
+ try {
6144
+ const previousExecutor = _currentExecutor;
6145
+ _currentExecutor = this;
6146
+ try {
6147
+ logger.debug(`Starting execution: ${toolcall.toolName}(${JSON.stringify(toolcall.toolArguments)})`);
6148
+ const executedToolcall = await _executeSingleTool(toolcall, this.toolStores);
6149
+ if (executedToolcall.isSuccess) {
6150
+ logger.debug(`Execution successful: ${executedToolcall.metadata.toolName}`);
6151
+ this.totalFinished++;
6152
+ this.successTasks.set(toolcall.idempotencyKey, executedToolcall);
6153
+ } else {
6154
+ logger.warn(
6155
+ `Execution failed: ${executedToolcall.metadata.toolName}, status: ${executedToolcall.isSuccess}, reason: ${executedToolcall.result}`
6156
+ );
6157
+ this.totalFailed++;
6158
+ this.failedTasks.set(toolcall.idempotencyKey, executedToolcall);
6159
+ }
6160
+ this.finishedResults.push(executedToolcall);
6161
+ } finally {
6162
+ _currentExecutor = previousExecutor;
6163
+ }
6164
+ } catch (error) {
6165
+ logger.error(`Exception executing tool ${toolcall.toolName}: ${error}`);
6166
+ const result = createExecutedToolcall(
6167
+ toolcall,
6168
+ false,
6169
+ `Execution exception: ${error instanceof Error ? error.message : String(error)}`
6170
+ );
6171
+ this.finishedResults.push(result);
6172
+ this.failedTasks.set(toolcall.idempotencyKey, result);
6173
+ this.totalFailed++;
6174
+ } finally {
6175
+ this.semaphore.available++;
6176
+ }
6177
+ }
6178
+ // ---- Background Process Management ----
6179
+ registerBackgroundProcess(process2, command, cwd) {
6180
+ const processId = uuidv42().slice(0, 8);
6181
+ this.backgroundProcesses.set(processId, {
6182
+ process: process2,
6183
+ command,
6184
+ cwd,
6185
+ pid: process2.pid || 0,
6186
+ status: "running"
6187
+ });
6188
+ logger.debug(`Registered background process: ${processId}, PID: ${process2.pid}, Command: ${command}`);
6189
+ return processId;
6190
+ }
6191
+ listBackgroundProcesses() {
6192
+ if (this.backgroundProcesses.size === 0) {
6193
+ return "No running background processes";
6194
+ }
6195
+ const lines = [`Total ${this.backgroundProcesses.size} background processes:
6196
+ `];
6197
+ for (const [processId, info] of this.backgroundProcesses) {
6198
+ const status = info.process.exitCode !== null ? "completed" : "running";
6199
+ lines.push(
6200
+ `- Process ID: ${processId}
6201
+ PID: ${info.pid}
6202
+ Command: ${info.command}
6203
+ Working Dir: ${info.cwd}
6204
+ Status: ${status}`
6205
+ );
6206
+ if (info.process.exitCode !== null) {
6207
+ lines.push(` Exit Code: ${info.process.exitCode}`);
6208
+ }
6209
+ }
6210
+ return lines.join("\n");
6211
+ }
6212
+ async stopBackgroundProcess(processId, force = false) {
6213
+ if (!this.backgroundProcesses.has(processId)) {
6214
+ return `Process ${processId} not found`;
6215
+ }
6216
+ const info = this.backgroundProcesses.get(processId);
6217
+ const process2 = info.process;
6218
+ if (process2.exitCode !== null) {
6219
+ return `Process ${processId} already terminated (exit code: ${process2.exitCode})`;
6220
+ }
6221
+ try {
6222
+ if (force) {
6223
+ process2.kill("SIGKILL");
6224
+ logger.info(`Force killed process ${process2.pid} (Process ID: ${processId})`);
6225
+ } else {
6226
+ process2.kill("SIGTERM");
6227
+ logger.info(`Sent SIGTERM to process ${process2.pid} (Process ID: ${processId})`);
6228
+ }
6229
+ await new Promise((resolve5) => {
6230
+ const timeout = setTimeout(() => {
6231
+ if (process2.exitCode === null && !force) {
6232
+ process2.kill("SIGKILL");
6233
+ logger.warn(`Process ${process2.pid} did not respond to SIGTERM, force killed`);
6234
+ }
6235
+ resolve5();
6236
+ }, 5e3);
6237
+ process2.on("exit", () => {
6238
+ clearTimeout(timeout);
6239
+ resolve5();
6240
+ });
6241
+ });
6242
+ info.status = "stopped";
6243
+ return `Process ${processId} stopped`;
6244
+ } catch (error) {
6245
+ logger.error(`Error stopping process ${processId}: ${error}`);
6246
+ return `Failed to stop process ${processId}: ${error}`;
6247
+ }
6248
+ }
6249
+ async cleanupBackgroundProcesses() {
6250
+ if (this.backgroundProcesses.size === 0) {
6251
+ return "No background processes to clean up";
6252
+ }
6253
+ const total = this.backgroundProcesses.size;
6254
+ let cleaned = 0;
6255
+ const errors = [];
6256
+ for (const processId of Array.from(this.backgroundProcesses.keys())) {
6257
+ const info = this.backgroundProcesses.get(processId);
6258
+ const process2 = info.process;
6259
+ if (process2.exitCode === null) {
6260
+ try {
6261
+ process2.kill("SIGTERM");
6262
+ await new Promise((resolve5) => {
6263
+ const timeout = setTimeout(() => {
6264
+ if (process2.exitCode === null) {
6265
+ process2.kill("SIGKILL");
6266
+ }
6267
+ resolve5();
6268
+ }, 3e3);
6269
+ process2.on("exit", () => {
6270
+ clearTimeout(timeout);
6271
+ resolve5();
6272
+ });
6273
+ });
6274
+ } catch (error) {
6275
+ errors.push(`Process ${processId}: ${error}`);
6276
+ continue;
6277
+ }
6278
+ }
6279
+ this.backgroundProcesses.delete(processId);
6280
+ cleaned++;
6281
+ }
6282
+ if (errors.length > 0) {
6283
+ return `Cleaned ${cleaned}/${total} processes. Errors:
6284
+ ${errors.join("\n")}`;
6285
+ }
6286
+ return `Successfully cleaned ${cleaned} background processes`;
6287
+ }
6288
+ };
6289
+
6290
+ // src/runtime/state/store.ts
6291
+ function createStateRecord(sessionId, agentName, type, data) {
6292
+ return {
6293
+ sessionId,
6294
+ agentName,
6295
+ timestamp: Date.now() / 1e3,
6296
+ type,
6297
+ data
6298
+ };
6299
+ }
6300
+
6301
+ // src/runtime/state/jsonlStore.ts
6302
+ import * as fs13 from "fs";
6303
+ import * as path9 from "path";
6304
+ import * as os from "os";
6305
+ var JsonlAgentStateStore = class {
6306
+ storageDir;
6307
+ maxSessions;
6308
+ sessionFileMap = /* @__PURE__ */ new Map();
6309
+ /**
6310
+ * Create a new JSONL state store
6311
+ *
6312
+ * @param storageDir - Directory to store JSONL files. Defaults to ~/.evolt/state/
6313
+ * @param maxSessions - Maximum number of session files to keep. Older sessions are automatically cleaned up.
6314
+ */
6315
+ constructor(storageDir, maxSessions = 3) {
6316
+ this.storageDir = storageDir || path9.join(os.homedir(), ".evolt", "state");
6317
+ this.maxSessions = maxSessions;
6318
+ if (!fs13.existsSync(this.storageDir)) {
6319
+ fs13.mkdirSync(this.storageDir, { recursive: true });
6320
+ }
6321
+ this._loadSessionMap();
6322
+ }
6323
+ /**
6324
+ * Load existing session_id to file mappings from disk
6325
+ */
6326
+ _loadSessionMap() {
6327
+ try {
6328
+ const files = fs13.readdirSync(this.storageDir);
6329
+ for (const file of files) {
6330
+ if (file.endsWith(".jsonl")) {
6331
+ const sessionId = path9.basename(file, ".jsonl");
6332
+ this.sessionFileMap.set(sessionId, path9.join(this.storageDir, file));
6333
+ }
6334
+ }
6335
+ } catch (error) {
6336
+ logger.warn(`Failed to load session map: ${error}`);
6337
+ }
6338
+ }
6339
+ /**
6340
+ * Get existing file path for session or create a new one
6341
+ */
6342
+ _getOrCreateFilePath(sessionId) {
6343
+ if (this.sessionFileMap.has(sessionId)) {
6344
+ return this.sessionFileMap.get(sessionId);
6345
+ }
6346
+ const filePath = path9.join(this.storageDir, `${sessionId}.jsonl`);
6347
+ this.sessionFileMap.set(sessionId, filePath);
6348
+ logger.debug(`Created new session file: ${filePath} for session=${sessionId}`);
6349
+ this._cleanupOldSessions();
6350
+ return filePath;
6351
+ }
6352
+ /**
6353
+ * Cleanup old session files to maintain max_sessions limit
6354
+ */
6355
+ _cleanupOldSessions() {
6356
+ try {
6357
+ const files = fs13.readdirSync(this.storageDir).filter((f) => f.endsWith(".jsonl")).map((f) => path9.join(this.storageDir, f));
6358
+ const filesWithTs = [];
6359
+ for (const filePath of files) {
6360
+ const timestamp = this._getLatestTimestamp(filePath);
6361
+ filesWithTs.push({ path: filePath, timestamp });
6362
+ }
6363
+ filesWithTs.sort((a, b) => b.timestamp - a.timestamp);
6364
+ let deleted = 0;
6365
+ for (let i = this.maxSessions; i < filesWithTs.length; i++) {
6366
+ const filePath = filesWithTs[i].path;
6367
+ try {
6368
+ const sessionId = path9.basename(filePath, ".jsonl");
6369
+ this.sessionFileMap.delete(sessionId);
6370
+ fs13.unlinkSync(filePath);
6371
+ deleted++;
6372
+ logger.debug(`Deleted old session file: ${filePath}`);
6373
+ } catch (error) {
6374
+ logger.warn(`Failed to delete ${filePath}: ${error}`);
6375
+ }
6376
+ }
6377
+ if (deleted > 0) {
6378
+ logger.info(`Cleaned up ${deleted} old session files`);
6379
+ }
6380
+ return deleted;
6381
+ } catch (error) {
6382
+ logger.error(`Failed to cleanup old sessions: ${error}`);
6383
+ return 0;
6384
+ }
6385
+ }
6386
+ /**
6387
+ * Get the latest record timestamp from a session file
6388
+ */
6389
+ _getLatestTimestamp(filePath) {
6390
+ try {
6391
+ if (!fs13.existsSync(filePath)) {
6392
+ return 0;
6393
+ }
6394
+ const content = fs13.readFileSync(filePath, "utf-8");
6395
+ const lines = content.trim().split("\n").filter((l) => l.trim());
6396
+ if (lines.length === 0) {
6397
+ return 0;
6398
+ }
6399
+ const lastLine = lines[lines.length - 1];
6400
+ try {
6401
+ const record = JSON.parse(lastLine);
6402
+ return record.timestamp || 0;
6403
+ } catch {
6404
+ return 0;
6405
+ }
6406
+ } catch (error) {
6407
+ return 0;
6408
+ }
6409
+ }
6410
+ async append(sessionId, agentName, record) {
6411
+ const filePath = this._getOrCreateFilePath(sessionId);
6412
+ const fullRecord = {
6413
+ sessionId,
6414
+ agentName,
6415
+ ...record
6416
+ };
6417
+ const line = JSON.stringify(fullRecord) + "\n";
6418
+ await fs13.promises.appendFile(filePath, line, "utf-8");
6419
+ logger.debug(`Appended record to session ${sessionId}: type=${record.type}`);
6420
+ }
6421
+ async getAll(sessionId, agentName) {
6422
+ const filePath = this.sessionFileMap.get(sessionId);
6423
+ if (!filePath || !fs13.existsSync(filePath)) {
6424
+ return [];
6425
+ }
6426
+ try {
6427
+ const content = await fs13.promises.readFile(filePath, "utf-8");
6428
+ const lines = content.trim().split("\n").filter((l) => l.trim());
6429
+ const records = [];
6430
+ for (const line of lines) {
6431
+ try {
6432
+ const record = JSON.parse(line);
6433
+ if (record.agentName === agentName) {
6434
+ records.push(record);
6435
+ }
6436
+ } catch {
6437
+ logger.warn(`Failed to parse record line: ${line}`);
6438
+ }
6439
+ }
6440
+ records.sort((a, b) => a.timestamp - b.timestamp);
6441
+ return records;
6442
+ } catch (error) {
6443
+ logger.error(`Failed to read session file: ${error}`);
6444
+ return [];
6445
+ }
6446
+ }
6447
+ async clear(sessionId, agentName) {
6448
+ const filePath = this.sessionFileMap.get(sessionId);
6449
+ if (!filePath || !fs13.existsSync(filePath)) {
6450
+ return;
6451
+ }
6452
+ try {
6453
+ const content = await fs13.promises.readFile(filePath, "utf-8");
6454
+ const lines = content.trim().split("\n").filter((l) => l.trim());
6455
+ const remainingLines = [];
6456
+ for (const line of lines) {
6457
+ try {
6458
+ const record = JSON.parse(line);
6459
+ if (record.agentName !== agentName) {
6460
+ remainingLines.push(line);
6461
+ }
6462
+ } catch {
6463
+ remainingLines.push(line);
6464
+ }
6465
+ }
6466
+ await fs13.promises.writeFile(filePath, remainingLines.join("\n") + "\n", "utf-8");
6467
+ logger.debug(`Cleared records for agent ${agentName} in session ${sessionId}`);
6468
+ } catch (error) {
6469
+ logger.error(`Failed to clear records: ${error}`);
6470
+ }
6471
+ }
6472
+ exportJson(sessionId, agentName, filename) {
6473
+ const filePath = this.sessionFileMap.get(sessionId);
6474
+ if (!filePath || !fs13.existsSync(filePath)) {
6475
+ fs13.writeFileSync(filename, "[]", "utf-8");
6476
+ return;
6477
+ }
6478
+ const content = fs13.readFileSync(filePath, "utf-8");
6479
+ const lines = content.trim().split("\n").filter((l) => l.trim());
6480
+ const records = [];
6481
+ for (const line of lines) {
6482
+ try {
6483
+ const record = JSON.parse(line);
6484
+ if (record.agentName === agentName) {
6485
+ records.push(record);
6486
+ }
6487
+ } catch {
6488
+ }
6489
+ }
6490
+ fs13.writeFileSync(filename, JSON.stringify(records, null, 2), "utf-8");
6491
+ logger.info(`Exported ${records.length} records to ${filename}`);
6492
+ }
6493
+ importJson(filename) {
6494
+ if (!fs13.existsSync(filename)) {
6495
+ logger.warn(`Import file not found: ${filename}`);
6496
+ return;
6497
+ }
6498
+ const content = fs13.readFileSync(filename, "utf-8");
6499
+ const records = JSON.parse(content);
6500
+ const bySession = /* @__PURE__ */ new Map();
6501
+ for (const record of records) {
6502
+ if (!bySession.has(record.sessionId)) {
6503
+ bySession.set(record.sessionId, []);
6504
+ }
6505
+ bySession.get(record.sessionId).push(record);
6506
+ }
6507
+ for (const [sessionId, sessionRecords] of bySession) {
6508
+ const filePath = this._getOrCreateFilePath(sessionId);
6509
+ const lines = sessionRecords.map((r) => JSON.stringify(r));
6510
+ fs13.appendFileSync(filePath, lines.join("\n") + "\n", "utf-8");
6511
+ }
6512
+ logger.info(`Imported ${records.length} records from ${filename}`);
6513
+ }
6514
+ async deleteLastN(sessionId, agentName, n) {
6515
+ const filePath = this.sessionFileMap.get(sessionId);
6516
+ if (!filePath || !fs13.existsSync(filePath)) {
6517
+ return 0;
6518
+ }
6519
+ try {
6520
+ const content = await fs13.promises.readFile(filePath, "utf-8");
6521
+ const lines = content.trim().split("\n").filter((l) => l.trim());
6522
+ const agentRecordIndices = [];
6523
+ const parsedRecords = [];
6524
+ for (let i = 0; i < lines.length; i++) {
6525
+ const line = lines[i];
6526
+ try {
6527
+ const record = JSON.parse(line);
6528
+ parsedRecords.push({ line, record });
6529
+ if (record.agentName === agentName) {
6530
+ agentRecordIndices.push(i);
6531
+ }
6532
+ } catch {
6533
+ parsedRecords.push({ line, record: null });
6534
+ }
6535
+ }
6536
+ const indicesToDelete = new Set(agentRecordIndices.slice(-n));
6537
+ const deleted = indicesToDelete.size;
6538
+ const remainingLines = parsedRecords.filter((_, i) => !indicesToDelete.has(i)).map((r) => r.line);
6539
+ await fs13.promises.writeFile(filePath, remainingLines.join("\n") + "\n", "utf-8");
6540
+ logger.debug(`Deleted ${deleted} records for agent ${agentName} in session ${sessionId}`);
6541
+ return deleted;
6542
+ } catch (error) {
6543
+ logger.error(`Failed to delete records: ${error}`);
6544
+ return 0;
6545
+ }
6546
+ }
6547
+ async sessionExists(sessionId) {
6548
+ const filePath = this.sessionFileMap.get(sessionId);
6549
+ return filePath !== void 0 && fs13.existsSync(filePath);
6550
+ }
6551
+ listSessions() {
6552
+ const sessions = [];
6553
+ for (const [sessionId, filePath] of this.sessionFileMap) {
6554
+ if (!fs13.existsSync(filePath)) {
6555
+ continue;
6556
+ }
6557
+ try {
6558
+ const content = fs13.readFileSync(filePath, "utf-8");
6559
+ const lines = content.trim().split("\n").filter((l) => l.trim());
6560
+ if (lines.length === 0) {
6561
+ continue;
6562
+ }
6563
+ let firstInstruction;
6564
+ const agents = /* @__PURE__ */ new Set();
6565
+ let timestamp = 0;
6566
+ for (const line of lines) {
6567
+ try {
6568
+ const record = JSON.parse(line);
6569
+ agents.add(record.agentName);
6570
+ if (timestamp === 0) {
6571
+ timestamp = record.timestamp;
6572
+ }
6573
+ if (!firstInstruction && record.type === "instruction") {
6574
+ firstInstruction = record.data.content?.slice(0, 100);
6575
+ }
6576
+ } catch {
6577
+ }
6578
+ }
6579
+ sessions.push({
6580
+ sessionId,
6581
+ timestamp,
6582
+ firstInstruction,
6583
+ agents: Array.from(agents)
6584
+ });
6585
+ } catch (error) {
6586
+ logger.warn(`Failed to read session file ${filePath}: ${error}`);
6587
+ }
6588
+ }
6589
+ sessions.sort((a, b) => b.timestamp - a.timestamp);
6590
+ return sessions;
6591
+ }
6592
+ async getAgentsInSession(sessionId) {
6593
+ const filePath = this.sessionFileMap.get(sessionId);
6594
+ if (!filePath || !fs13.existsSync(filePath)) {
6595
+ return [];
6596
+ }
6597
+ try {
6598
+ const content = await fs13.promises.readFile(filePath, "utf-8");
6599
+ const lines = content.trim().split("\n").filter((l) => l.trim());
6600
+ const agents = /* @__PURE__ */ new Set();
6601
+ for (const line of lines) {
6602
+ try {
6603
+ const record = JSON.parse(line);
6604
+ agents.add(record.agentName);
6605
+ } catch {
6606
+ }
6607
+ }
6608
+ return Array.from(agents);
6609
+ } catch (error) {
6610
+ logger.error(`Failed to read session file: ${error}`);
6611
+ return [];
6612
+ }
6613
+ }
6614
+ };
6615
+
6616
+ // src/runtime/state/context.ts
6617
+ import { v4 as uuidv43 } from "uuid";
6618
+ var _sessionId = null;
6619
+ var _sessionIdExplicit = false;
6620
+ var _skipExecutorRestore = false;
6621
+ function useSessionId(sessionId, options) {
6622
+ if (_sessionId !== null) {
6623
+ throw new Error(
6624
+ `Session ID already set to '${_sessionId}'. Cannot change to '${sessionId}'. Call resetSessionId() first.`
6625
+ );
6626
+ }
6627
+ _sessionId = sessionId;
6628
+ _sessionIdExplicit = true;
6629
+ _skipExecutorRestore = options?.skipExecutorRestore ?? false;
6630
+ }
6631
+ function getOrCreateSessionId() {
6632
+ if (_sessionId === null) {
6633
+ _sessionId = uuidv43();
6634
+ _sessionIdExplicit = false;
6635
+ }
6636
+ return _sessionId;
6637
+ }
6638
+ function getSessionId() {
6639
+ return _sessionId;
6640
+ }
6641
+ function isNewSession() {
6642
+ return !_sessionIdExplicit;
6643
+ }
6644
+ function resetSessionId() {
6645
+ _sessionId = null;
6646
+ _sessionIdExplicit = false;
6647
+ _skipExecutorRestore = false;
6648
+ }
6649
+ function shouldSkipExecutorRestore() {
6650
+ return _skipExecutorRestore;
6651
+ }
6652
+ var _globalStore = null;
6653
+ function enableStateStore(store, options) {
6654
+ if (store !== void 0) {
6655
+ _globalStore = store;
6656
+ } else if (options?.backend === "jsonl" || !options?.backend) {
6657
+ _globalStore = new JsonlAgentStateStore(options?.storageDir);
6658
+ } else {
6659
+ _globalStore = null;
6660
+ }
6661
+ return _globalStore;
6662
+ }
6663
+ function getGlobalStore() {
6664
+ return _globalStore;
6665
+ }
6666
+ function isPersistenceEnabled() {
6667
+ return _globalStore !== null;
6668
+ }
6669
+ var _agentName = null;
6670
+ function setAgentName(agentName) {
6671
+ _agentName = agentName;
6672
+ }
6673
+ function getAgentName() {
6674
+ return _agentName;
6675
+ }
6676
+ function resetAgentName() {
6677
+ _agentName = null;
6678
+ }
6679
+
6680
+ // src/runtime/state/decorator.ts
6681
+ function persistentState(recordType) {
6682
+ return function(target, propertyKey, descriptor) {
6683
+ const originalMethod = descriptor.value;
6684
+ descriptor.value = async function(...args) {
6685
+ const result = await originalMethod.apply(this, args);
6686
+ const sessionId = getOrCreateSessionId();
6687
+ const agentName = getAgentName();
6688
+ const store = getGlobalStore();
6689
+ if (store !== null && agentName) {
6690
+ let currentType = recordType;
6691
+ const data = _serializeForPersistence(recordType, args, result);
6692
+ try {
6693
+ await store.append(sessionId, agentName, {
6694
+ type: currentType,
6695
+ data,
6696
+ timestamp: Date.now() / 1e3
6697
+ });
6698
+ logger.debug(`Persisted ${currentType} record for session=${sessionId}, agent=${agentName}`);
6699
+ } catch (error) {
6700
+ logger.error(`Failed to persist state: ${error}`);
6701
+ }
6702
+ }
6703
+ return result;
6704
+ };
6705
+ return descriptor;
6706
+ };
6707
+ }
6708
+ function _serializeForPersistence(recordType, args, result) {
6709
+ if (recordType === "message") {
6710
+ const message = args[0];
6711
+ if (message !== void 0) {
6712
+ if (typeof message.toDict === "function") {
6713
+ return { message: message.toDict() };
6714
+ } else if (typeof message.toObject === "function") {
6715
+ return { message: message.toObject() };
6716
+ } else if (typeof message === "object") {
6717
+ return { message };
6718
+ }
6719
+ }
6720
+ return { args: String(args) };
6721
+ } else if (recordType === "tool_call") {
6722
+ const toolcalls = [];
6723
+ const toolcallsArg = args[0];
6724
+ if (toolcallsArg !== void 0 && Symbol.iterator in Object(toolcallsArg)) {
6725
+ for (const tc of toolcallsArg) {
6726
+ if (typeof tc.toDict === "function") {
6727
+ toolcalls.push(tc.toDict());
6728
+ } else if (typeof tc === "object") {
6729
+ toolcalls.push(tc);
6730
+ }
6731
+ }
6732
+ }
6733
+ return { toolcalls };
6734
+ }
6735
+ return {};
6736
+ }
6737
+ function agentAutoRestore(target, propertyKey, descriptor) {
6738
+ const originalMethod = descriptor.value;
6739
+ descriptor.value = async function(instruction, images) {
6740
+ const inst = instruction || "";
6741
+ const sessionId = getOrCreateSessionId();
6742
+ const agentName = this.name;
6743
+ setAgentName(agentName);
6744
+ try {
6745
+ const result = await originalMethod.call(this, inst, images);
6746
+ const store = getGlobalStore();
6747
+ if (store !== null && typeof result === "string") {
6748
+ try {
6749
+ await store.append(sessionId, agentName, {
6750
+ type: "completion",
6751
+ data: { response: result },
6752
+ timestamp: Date.now() / 1e3
6753
+ });
6754
+ logger.debug(`Recorded completion for session=${sessionId}, agent=${agentName}`);
6755
+ } catch (error) {
6756
+ logger.error(`Failed to record completion: ${error}`);
6757
+ }
6758
+ }
6759
+ return result;
6760
+ } catch (error) {
6761
+ logger.error(`Agent ${agentName} run error: ${error}`);
6762
+ throw error;
6763
+ } finally {
6764
+ resetAgentName();
6765
+ if (this.autoShutdownExecutor && this.executor) {
6766
+ await this.executor.shutdown({ wait: true });
6767
+ }
6768
+ }
6769
+ };
6770
+ return descriptor;
6771
+ }
4772
6772
  export {
4773
6773
  Agent,
4774
6774
  ApiTool,
4775
6775
  BaseEnvironment,
6776
+ BaseOrchestrator,
4776
6777
  CodingEnvironment,
6778
+ CodingOrchestrator,
4777
6779
  CommandLineTool,
4778
6780
  DEFAULT_CONFIG,
4779
6781
  DEFAULT_SETTINGS,
4780
6782
  ENV_VARS,
4781
6783
  ERROR_MESSAGES,
6784
+ Environment,
4782
6785
  EvoltError,
4783
6786
  ExtendStateMachineTool,
6787
+ Feedback,
4784
6788
  FileEditor,
4785
6789
  FunctionCallingStore,
4786
6790
  GitTool,
6791
+ ImageTool,
6792
+ InstructionType,
6793
+ JsonlAgentStateStore,
4787
6794
  LOG_LEVELS,
6795
+ LocalToolExecutor,
4788
6796
  MESSAGE_ROLES,
4789
6797
  Message,
4790
6798
  MessageHistory,
4791
6799
  Model,
4792
6800
  ModelError,
6801
+ OUTPUT_FORMAT_PROMPT,
6802
+ PatchTool,
6803
+ REFLECT_OUTPUT_FORMAT_PROMPT,
4793
6804
  ReflectTool,
6805
+ ReflexionOrchestrator,
4794
6806
  Reply2HumanTool,
4795
6807
  SKILLS_DIR,
6808
+ SYSTEM_TOOLS_PROMPT,
4796
6809
  SkillsTool,
4797
6810
  SystemToolStore,
6811
+ TOOLS_PROMPT,
4798
6812
  TOOL_CALL_TYPES,
4799
6813
  TOOL_CONSTANTS,
4800
6814
  ThinkTool,
@@ -4804,13 +6818,28 @@ export {
4804
6818
  UserToolStore,
4805
6819
  WORKSPACE_DIR,
4806
6820
  WriteUIDesignDocument,
6821
+ _executeSingleTool,
6822
+ agentAutoRestore,
6823
+ areadImage,
6824
+ createExecutedToolcall,
6825
+ createGeneratedToolcall,
6826
+ createStateRecord,
6827
+ deprecated,
6828
+ enableStateStore,
4807
6829
  ensureDir,
6830
+ executeToolsParallel,
6831
+ executeToolsSequential,
4808
6832
  fileExists,
6833
+ getAgentName,
4809
6834
  getCacheDir,
4810
6835
  getConfigDir,
4811
6836
  getConfigPath2 as getConfigPath,
6837
+ getCurrentExecutor,
4812
6838
  getFileExtension,
6839
+ getGlobalStore,
4813
6840
  getLogsDir,
6841
+ getOrCreateSessionId,
6842
+ getSessionId,
4814
6843
  getSettings,
4815
6844
  getSkillsDir,
4816
6845
  getTempFilePath,
@@ -4818,12 +6847,23 @@ export {
4818
6847
  getWorkspacePath,
4819
6848
  initializeSettings,
4820
6849
  isInWorkspace,
6850
+ isNewSession,
6851
+ isPersistenceEnabled,
6852
+ isSupportedImageFile,
4821
6853
  loadModelConfig,
4822
6854
  logger_default as logger,
4823
6855
  normalizePath,
6856
+ persistentState,
6857
+ readImage,
4824
6858
  registerAgentAsTool,
6859
+ resetAgentName,
6860
+ resetSessionId,
6861
+ setAgentName,
6862
+ setCurrentExecutor,
4825
6863
  settings,
6864
+ shouldSkipExecutorRestore,
4826
6865
  tools,
4827
- updateSettings
6866
+ updateSettings,
6867
+ useSessionId
4828
6868
  };
4829
6869
  //# sourceMappingURL=index.js.map