@jackchen_me/open-multi-agent 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +280 -0
  3. package/dist/agent/agent.d.ts +121 -0
  4. package/dist/agent/agent.d.ts.map +1 -0
  5. package/dist/agent/agent.js +294 -0
  6. package/dist/agent/agent.js.map +1 -0
  7. package/dist/agent/pool.d.ts +128 -0
  8. package/dist/agent/pool.d.ts.map +1 -0
  9. package/dist/agent/pool.js +236 -0
  10. package/dist/agent/pool.js.map +1 -0
  11. package/dist/agent/runner.d.ts +120 -0
  12. package/dist/agent/runner.d.ts.map +1 -0
  13. package/dist/agent/runner.js +274 -0
  14. package/dist/agent/runner.js.map +1 -0
  15. package/dist/index.d.ts +73 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +87 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/llm/adapter.d.ts +38 -0
  20. package/dist/llm/adapter.d.ts.map +1 -0
  21. package/dist/llm/adapter.js +46 -0
  22. package/dist/llm/adapter.js.map +1 -0
  23. package/dist/llm/anthropic.d.ts +56 -0
  24. package/dist/llm/anthropic.d.ts.map +1 -0
  25. package/dist/llm/anthropic.js +307 -0
  26. package/dist/llm/anthropic.js.map +1 -0
  27. package/dist/llm/openai.d.ts +62 -0
  28. package/dist/llm/openai.d.ts.map +1 -0
  29. package/dist/llm/openai.js +424 -0
  30. package/dist/llm/openai.js.map +1 -0
  31. package/dist/memory/shared.d.ts +86 -0
  32. package/dist/memory/shared.d.ts.map +1 -0
  33. package/dist/memory/shared.js +155 -0
  34. package/dist/memory/shared.js.map +1 -0
  35. package/dist/memory/store.d.ts +64 -0
  36. package/dist/memory/store.d.ts.map +1 -0
  37. package/dist/memory/store.js +103 -0
  38. package/dist/memory/store.js.map +1 -0
  39. package/dist/orchestrator/orchestrator.d.ts +173 -0
  40. package/dist/orchestrator/orchestrator.d.ts.map +1 -0
  41. package/dist/orchestrator/orchestrator.js +698 -0
  42. package/dist/orchestrator/orchestrator.js.map +1 -0
  43. package/dist/orchestrator/scheduler.d.ts +112 -0
  44. package/dist/orchestrator/scheduler.d.ts.map +1 -0
  45. package/dist/orchestrator/scheduler.js +282 -0
  46. package/dist/orchestrator/scheduler.js.map +1 -0
  47. package/dist/task/queue.d.ts +160 -0
  48. package/dist/task/queue.d.ts.map +1 -0
  49. package/dist/task/queue.js +337 -0
  50. package/dist/task/queue.js.map +1 -0
  51. package/dist/task/task.d.ts +86 -0
  52. package/dist/task/task.d.ts.map +1 -0
  53. package/dist/task/task.js +201 -0
  54. package/dist/task/task.js.map +1 -0
  55. package/dist/team/messaging.d.ts +106 -0
  56. package/dist/team/messaging.d.ts.map +1 -0
  57. package/dist/team/messaging.js +182 -0
  58. package/dist/team/messaging.js.map +1 -0
  59. package/dist/team/team.d.ts +141 -0
  60. package/dist/team/team.d.ts.map +1 -0
  61. package/dist/team/team.js +282 -0
  62. package/dist/team/team.js.map +1 -0
  63. package/dist/tool/built-in/bash.d.ts +12 -0
  64. package/dist/tool/built-in/bash.d.ts.map +1 -0
  65. package/dist/tool/built-in/bash.js +133 -0
  66. package/dist/tool/built-in/bash.js.map +1 -0
  67. package/dist/tool/built-in/file-edit.d.ts +14 -0
  68. package/dist/tool/built-in/file-edit.d.ts.map +1 -0
  69. package/dist/tool/built-in/file-edit.js +130 -0
  70. package/dist/tool/built-in/file-edit.js.map +1 -0
  71. package/dist/tool/built-in/file-read.d.ts +12 -0
  72. package/dist/tool/built-in/file-read.d.ts.map +1 -0
  73. package/dist/tool/built-in/file-read.js +82 -0
  74. package/dist/tool/built-in/file-read.js.map +1 -0
  75. package/dist/tool/built-in/file-write.d.ts +11 -0
  76. package/dist/tool/built-in/file-write.d.ts.map +1 -0
  77. package/dist/tool/built-in/file-write.js +70 -0
  78. package/dist/tool/built-in/file-write.js.map +1 -0
  79. package/dist/tool/built-in/grep.d.ts +15 -0
  80. package/dist/tool/built-in/grep.d.ts.map +1 -0
  81. package/dist/tool/built-in/grep.js +287 -0
  82. package/dist/tool/built-in/grep.js.map +1 -0
  83. package/dist/tool/built-in/index.d.ts +36 -0
  84. package/dist/tool/built-in/index.d.ts.map +1 -0
  85. package/dist/tool/built-in/index.js +45 -0
  86. package/dist/tool/built-in/index.js.map +1 -0
  87. package/dist/tool/executor.d.ts +71 -0
  88. package/dist/tool/executor.d.ts.map +1 -0
  89. package/dist/tool/executor.js +116 -0
  90. package/dist/tool/executor.js.map +1 -0
  91. package/dist/tool/framework.d.ts +143 -0
  92. package/dist/tool/framework.d.ts.map +1 -0
  93. package/dist/tool/framework.js +371 -0
  94. package/dist/tool/framework.js.map +1 -0
  95. package/dist/types.d.ts +285 -0
  96. package/dist/types.d.ts.map +1 -0
  97. package/dist/types.js +8 -0
  98. package/dist/types.js.map +1 -0
  99. package/dist/utils/semaphore.d.ts +47 -0
  100. package/dist/utils/semaphore.d.ts.map +1 -0
  101. package/dist/utils/semaphore.js +85 -0
  102. package/dist/utils/semaphore.js.map +1 -0
  103. package/examples/01-single-agent.ts +131 -0
  104. package/examples/02-team-collaboration.ts +167 -0
  105. package/examples/03-task-pipeline.ts +201 -0
  106. package/examples/04-multi-model-team.ts +261 -0
  107. package/package.json +49 -0
  108. package/src/agent/agent.ts +364 -0
  109. package/src/agent/pool.ts +278 -0
  110. package/src/agent/runner.ts +413 -0
  111. package/src/index.ts +166 -0
  112. package/src/llm/adapter.ts +74 -0
  113. package/src/llm/anthropic.ts +388 -0
  114. package/src/llm/openai.ts +522 -0
  115. package/src/memory/shared.ts +181 -0
  116. package/src/memory/store.ts +124 -0
  117. package/src/orchestrator/orchestrator.ts +851 -0
  118. package/src/orchestrator/scheduler.ts +352 -0
  119. package/src/task/queue.ts +394 -0
  120. package/src/task/task.ts +232 -0
  121. package/src/team/messaging.ts +230 -0
  122. package/src/team/team.ts +334 -0
  123. package/src/tool/built-in/bash.ts +187 -0
  124. package/src/tool/built-in/file-edit.ts +154 -0
  125. package/src/tool/built-in/file-read.ts +105 -0
  126. package/src/tool/built-in/file-write.ts +81 -0
  127. package/src/tool/built-in/grep.ts +362 -0
  128. package/src/tool/built-in/index.ts +50 -0
  129. package/src/tool/executor.ts +178 -0
  130. package/src/tool/framework.ts +557 -0
  131. package/src/types.ts +362 -0
  132. package/src/utils/semaphore.ts +89 -0
  133. package/tsconfig.json +25 -0
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Built-in file-read tool.
3
+ *
4
+ * Reads a file from disk and returns its contents with 1-based line numbers.
5
+ * Supports reading a slice of lines via `offset` and `limit` for large files.
6
+ */
7
+ import { readFile } from 'fs/promises';
8
+ import { z } from 'zod';
9
+ import { defineTool } from '../framework.js';
10
+ // ---------------------------------------------------------------------------
11
+ // Tool definition
12
+ // ---------------------------------------------------------------------------
13
+ export const fileReadTool = defineTool({
14
+ name: 'file_read',
15
+ description: 'Read the contents of a file from disk. ' +
16
+ 'Returns the file contents with line numbers prefixed in the format "N\\t<line>". ' +
17
+ 'Use `offset` and `limit` to read large files in chunks without loading the ' +
18
+ 'entire file into the context window.',
19
+ inputSchema: z.object({
20
+ path: z.string().describe('Absolute path to the file to read.'),
21
+ offset: z
22
+ .number()
23
+ .int()
24
+ .nonnegative()
25
+ .optional()
26
+ .describe('1-based line number to start reading from. ' +
27
+ 'When omitted the file is read from the beginning.'),
28
+ limit: z
29
+ .number()
30
+ .int()
31
+ .positive()
32
+ .optional()
33
+ .describe('Maximum number of lines to return. ' +
34
+ 'When omitted all lines from `offset` to the end of the file are returned.'),
35
+ }),
36
+ execute: async (input) => {
37
+ let raw;
38
+ try {
39
+ const buffer = await readFile(input.path);
40
+ raw = buffer.toString('utf8');
41
+ }
42
+ catch (err) {
43
+ const message = err instanceof Error ? err.message : 'Unknown error reading file.';
44
+ return {
45
+ data: `Could not read file "${input.path}": ${message}`,
46
+ isError: true,
47
+ };
48
+ }
49
+ // Split preserving trailing newlines correctly
50
+ const lines = raw.split('\n');
51
+ // Remove the last empty string produced by a trailing newline
52
+ if (lines.length > 0 && lines[lines.length - 1] === '') {
53
+ lines.pop();
54
+ }
55
+ const totalLines = lines.length;
56
+ // Apply offset (convert from 1-based to 0-based)
57
+ const startIndex = input.offset !== undefined ? Math.max(0, input.offset - 1) : 0;
58
+ if (startIndex >= totalLines && totalLines > 0) {
59
+ return {
60
+ data: `File "${input.path}" has ${totalLines} line${totalLines === 1 ? '' : 's'} ` +
61
+ `but offset ${input.offset} is beyond the end.`,
62
+ isError: true,
63
+ };
64
+ }
65
+ const endIndex = input.limit !== undefined
66
+ ? Math.min(startIndex + input.limit, totalLines)
67
+ : totalLines;
68
+ const slice = lines.slice(startIndex, endIndex);
69
+ // Build line-numbered output (1-based line numbers matching file positions)
70
+ const numbered = slice
71
+ .map((line, i) => `${startIndex + i + 1}\t${line}`)
72
+ .join('\n');
73
+ const meta = endIndex < totalLines
74
+ ? `\n\n(showing lines ${startIndex + 1}–${endIndex} of ${totalLines})`
75
+ : '';
76
+ return {
77
+ data: numbered + meta,
78
+ isError: false,
79
+ };
80
+ },
81
+ });
82
+ //# sourceMappingURL=file-read.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-read.js","sourceRoot":"","sources":["../../../src/tool/built-in/file-read.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Built-in file-write tool.
3
+ *
4
+ * Creates or overwrites a file with the supplied content. Parent directories
5
+ * are created automatically (equivalent to `mkdir -p`).
6
+ */
7
+ export declare const fileWriteTool: import("../framework.js").ToolDefinition<{
8
+ content: string;
9
+ path: string;
10
+ }>;
11
+ //# sourceMappingURL=file-write.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-write.d.ts","sourceRoot":"","sources":["../../../src/tool/built-in/file-write.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAWH,eAAO,MAAM,aAAa;;;EAgExB,CAAA"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Built-in file-write tool.
3
+ *
4
+ * Creates or overwrites a file with the supplied content. Parent directories
5
+ * are created automatically (equivalent to `mkdir -p`).
6
+ */
7
+ import { mkdir, stat, writeFile } from 'fs/promises';
8
+ import { dirname } from 'path';
9
+ import { z } from 'zod';
10
+ import { defineTool } from '../framework.js';
11
+ // ---------------------------------------------------------------------------
12
+ // Tool definition
13
+ // ---------------------------------------------------------------------------
14
+ export const fileWriteTool = defineTool({
15
+ name: 'file_write',
16
+ description: 'Write content to a file, creating it (and any missing parent directories) if it ' +
17
+ 'does not already exist, or overwriting it if it does. ' +
18
+ 'Prefer this tool for creating new files; use file_edit for targeted in-place edits ' +
19
+ 'of existing files.',
20
+ inputSchema: z.object({
21
+ path: z
22
+ .string()
23
+ .describe('Absolute path to the file to write. ' +
24
+ 'The path must be absolute (starting with /).'),
25
+ content: z.string().describe('The full content to write to the file.'),
26
+ }),
27
+ execute: async (input) => {
28
+ // Determine whether the file already exists so we can report create vs update.
29
+ let existed = false;
30
+ try {
31
+ await stat(input.path);
32
+ existed = true;
33
+ }
34
+ catch {
35
+ // File does not exist — will be created.
36
+ }
37
+ // Ensure parent directory hierarchy exists.
38
+ const parentDir = dirname(input.path);
39
+ try {
40
+ await mkdir(parentDir, { recursive: true });
41
+ }
42
+ catch (err) {
43
+ const message = err instanceof Error ? err.message : 'Unknown error creating directories.';
44
+ return {
45
+ data: `Failed to create parent directory "${parentDir}": ${message}`,
46
+ isError: true,
47
+ };
48
+ }
49
+ // Write the file.
50
+ try {
51
+ await writeFile(input.path, input.content, 'utf8');
52
+ }
53
+ catch (err) {
54
+ const message = err instanceof Error ? err.message : 'Unknown error writing file.';
55
+ return {
56
+ data: `Failed to write file "${input.path}": ${message}`,
57
+ isError: true,
58
+ };
59
+ }
60
+ const lineCount = input.content.split('\n').length;
61
+ const byteCount = Buffer.byteLength(input.content, 'utf8');
62
+ const action = existed ? 'Updated' : 'Created';
63
+ return {
64
+ data: `${action} "${input.path}" ` +
65
+ `(${lineCount} line${lineCount === 1 ? '' : 's'}, ${byteCount} bytes).`,
66
+ isError: false,
67
+ };
68
+ },
69
+ });
70
+ //# sourceMappingURL=file-write.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-write.js","sourceRoot":"","sources":["../../../src/tool/built-in/file-write.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAC9B,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAE5C,8EAA8E;AAC9E,kBAAkB;AAClB,8EAA8E;AAE9E,MAAM,CAAC,MAAM,aAAa,GAAG,UAAU,CAAC;IACtC,IAAI,EAAE,YAAY;IAClB,WAAW,EACT,kFAAkF;QAClF,wDAAwD;QACxD,qFAAqF;QACrF,oBAAoB;IAEtB,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;QACpB,IAAI,EAAE,CAAC;aACJ,MAAM,EAAE;aACR,QAAQ,CACP,sCAAsC;YACpC,8CAA8C,CACjD;QACH,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,wCAAwC,CAAC;KACvE,CAAC;IAEF,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;QACvB,+EAA+E;QAC/E,IAAI,OAAO,GAAG,KAAK,CAAA;QACnB,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;YACtB,OAAO,GAAG,IAAI,CAAA;QAChB,CAAC;QAAC,MAAM,CAAC;YACP,yCAAyC;QAC3C,CAAC;QAED,4CAA4C;QAC5C,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;QACrC,IAAI,CAAC;YACH,MAAM,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;QAC7C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,OAAO,GACX,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,qCAAqC,CAAA;YAC5E,OAAO;gBACL,IAAI,EAAE,sCAAsC,SAAS,MAAM,OAAO,EAAE;gBACpE,OAAO,EAAE,IAAI;aACd,CAAA;QACH,CAAC;QAED,kBAAkB;QAClB,IAAI,CAAC;YACH,MAAM,SAAS,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;QACpD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,OAAO,GACX,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,6BAA6B,CAAA;YACpE,OAAO;gBACL,IAAI,EAAE,yBAAyB,KAAK,CAAC,IAAI,MAAM,OAAO,EAAE;gBACxD,OAAO,EAAE,IAAI;aACd,CAAA;QACH,CAAC;QAED,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAA;QAClD,MAAM,SAAS,GAAG,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;QAC1D,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAA;QAE9C,OAAO;YACL,IAAI,EACF,GAAG,MAAM,KAAK,KAAK,CAAC,IAAI,IAAI;gBAC5B,IAAI,SAAS,QAAQ,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,SAAS,UAAU;YACzE,OAAO,EAAE,KAAK;SACf,CAAA;IACH,CAAC;CACF,CAAC,CAAA"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Built-in grep tool.
3
+ *
4
+ * Searches for a regex pattern in files. Prefers the `rg` (ripgrep) binary
5
+ * when available for performance; falls back to a pure Node.js recursive
6
+ * implementation using the standard `fs` module so the tool works in
7
+ * environments without ripgrep installed.
8
+ */
9
+ export declare const grepTool: import("../framework.js").ToolDefinition<{
10
+ pattern: string;
11
+ path?: string | undefined;
12
+ glob?: string | undefined;
13
+ maxResults?: number | undefined;
14
+ }>;
15
+ //# sourceMappingURL=grep.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grep.d.ts","sourceRoot":"","sources":["../../../src/tool/built-in/grep.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AA8BH,eAAO,MAAM,QAAQ;;;;;EAuEnB,CAAA"}
@@ -0,0 +1,287 @@
1
+ /**
2
+ * Built-in grep tool.
3
+ *
4
+ * Searches for a regex pattern in files. Prefers the `rg` (ripgrep) binary
5
+ * when available for performance; falls back to a pure Node.js recursive
6
+ * implementation using the standard `fs` module so the tool works in
7
+ * environments without ripgrep installed.
8
+ */
9
+ import { spawn } from 'child_process';
10
+ import { readdir, readFile, stat } from 'fs/promises';
11
+ // Note: readdir is used with { encoding: 'utf8' } to return string[] directly.
12
+ import { join, relative } from 'path';
13
+ import { z } from 'zod';
14
+ import { defineTool } from '../framework.js';
15
+ // ---------------------------------------------------------------------------
16
+ // Constants
17
+ // ---------------------------------------------------------------------------
18
+ const DEFAULT_MAX_RESULTS = 100;
19
+ // Directories that are almost never useful to search inside
20
+ const SKIP_DIRS = new Set([
21
+ '.git',
22
+ '.svn',
23
+ '.hg',
24
+ 'node_modules',
25
+ '.next',
26
+ 'dist',
27
+ 'build',
28
+ ]);
29
+ // ---------------------------------------------------------------------------
30
+ // Tool definition
31
+ // ---------------------------------------------------------------------------
32
+ export const grepTool = defineTool({
33
+ name: 'grep',
34
+ description: 'Search for a regular-expression pattern in one or more files. ' +
35
+ 'Returns matching lines with their file paths and 1-based line numbers. ' +
36
+ 'Use the `glob` parameter to restrict the search to specific file types ' +
37
+ '(e.g. "*.ts"). ' +
38
+ 'Results are capped by `maxResults` to keep the response manageable.',
39
+ inputSchema: z.object({
40
+ pattern: z
41
+ .string()
42
+ .describe('Regular expression pattern to search for in file contents.'),
43
+ path: z
44
+ .string()
45
+ .optional()
46
+ .describe('Directory or file path to search in. ' +
47
+ 'Defaults to the current working directory.'),
48
+ glob: z
49
+ .string()
50
+ .optional()
51
+ .describe('Glob pattern to filter which files are searched ' +
52
+ '(e.g. "*.ts", "**/*.json"). ' +
53
+ 'Only used when `path` is a directory.'),
54
+ maxResults: z
55
+ .number()
56
+ .int()
57
+ .positive()
58
+ .optional()
59
+ .describe(`Maximum number of matching lines to return. ` +
60
+ `Defaults to ${DEFAULT_MAX_RESULTS}.`),
61
+ }),
62
+ execute: async (input, context) => {
63
+ const searchPath = input.path ?? process.cwd();
64
+ const maxResults = input.maxResults ?? DEFAULT_MAX_RESULTS;
65
+ // Compile the regex once and surface bad patterns immediately.
66
+ let regex;
67
+ try {
68
+ regex = new RegExp(input.pattern);
69
+ }
70
+ catch {
71
+ return {
72
+ data: `Invalid regular expression: "${input.pattern}"`,
73
+ isError: true,
74
+ };
75
+ }
76
+ // Attempt ripgrep first.
77
+ const rgAvailable = await isRipgrepAvailable();
78
+ if (rgAvailable) {
79
+ return runRipgrep(input.pattern, searchPath, {
80
+ glob: input.glob,
81
+ maxResults,
82
+ signal: context.abortSignal,
83
+ });
84
+ }
85
+ // Fallback: pure Node.js recursive search.
86
+ return runNodeSearch(regex, searchPath, {
87
+ glob: input.glob,
88
+ maxResults,
89
+ signal: context.abortSignal,
90
+ });
91
+ },
92
+ });
93
+ async function runRipgrep(pattern, searchPath, options) {
94
+ const args = [
95
+ '--line-number',
96
+ '--no-heading',
97
+ '--color=never',
98
+ `--max-count=${options.maxResults}`,
99
+ ];
100
+ if (options.glob !== undefined) {
101
+ args.push('--glob', options.glob);
102
+ }
103
+ args.push('--', pattern, searchPath);
104
+ return new Promise((resolve) => {
105
+ const chunks = [];
106
+ const errChunks = [];
107
+ const child = spawn('rg', args, { stdio: ['ignore', 'pipe', 'pipe'] });
108
+ child.stdout.on('data', (d) => chunks.push(d));
109
+ child.stderr.on('data', (d) => errChunks.push(d));
110
+ const onAbort = () => { child.kill('SIGKILL'); };
111
+ if (options.signal !== undefined) {
112
+ options.signal.addEventListener('abort', onAbort, { once: true });
113
+ }
114
+ child.on('close', (code) => {
115
+ if (options.signal !== undefined) {
116
+ options.signal.removeEventListener('abort', onAbort);
117
+ }
118
+ const output = Buffer.concat(chunks).toString('utf8').trimEnd();
119
+ // rg exit code 1 = no matches (not an error)
120
+ if (code !== 0 && code !== 1) {
121
+ const errMsg = Buffer.concat(errChunks).toString('utf8').trim();
122
+ resolve({
123
+ data: `ripgrep failed (exit ${code}): ${errMsg}`,
124
+ isError: true,
125
+ });
126
+ return;
127
+ }
128
+ if (output.length === 0) {
129
+ resolve({ data: 'No matches found.', isError: false });
130
+ return;
131
+ }
132
+ const lines = output.split('\n');
133
+ resolve({
134
+ data: lines.join('\n'),
135
+ isError: false,
136
+ });
137
+ });
138
+ child.on('error', () => {
139
+ if (options.signal !== undefined) {
140
+ options.signal.removeEventListener('abort', onAbort);
141
+ }
142
+ // Caller will see an error result — the tool won't retry with Node search
143
+ // since this branch is only reachable after we confirmed rg is available.
144
+ resolve({
145
+ data: 'ripgrep process error — run may be retried with the Node.js fallback.',
146
+ isError: true,
147
+ });
148
+ });
149
+ });
150
+ }
151
+ async function runNodeSearch(regex, searchPath, options) {
152
+ // Collect files
153
+ let files;
154
+ try {
155
+ const info = await stat(searchPath);
156
+ if (info.isFile()) {
157
+ files = [searchPath];
158
+ }
159
+ else {
160
+ files = await collectFiles(searchPath, options.glob, options.signal);
161
+ }
162
+ }
163
+ catch (err) {
164
+ const message = err instanceof Error ? err.message : 'Unknown error';
165
+ return {
166
+ data: `Cannot access path "${searchPath}": ${message}`,
167
+ isError: true,
168
+ };
169
+ }
170
+ const matches = [];
171
+ for (const file of files) {
172
+ if (options.signal?.aborted === true)
173
+ break;
174
+ if (matches.length >= options.maxResults)
175
+ break;
176
+ let fileContent;
177
+ try {
178
+ fileContent = (await readFile(file)).toString('utf8');
179
+ }
180
+ catch {
181
+ // Skip unreadable files (binary, permission denied, etc.)
182
+ continue;
183
+ }
184
+ const lines = fileContent.split('\n');
185
+ for (let i = 0; i < lines.length; i++) {
186
+ if (matches.length >= options.maxResults)
187
+ break;
188
+ // Reset lastIndex for global regexes
189
+ regex.lastIndex = 0;
190
+ if (regex.test(lines[i])) {
191
+ matches.push({
192
+ file: relative(process.cwd(), file) || file,
193
+ lineNumber: i + 1,
194
+ text: lines[i],
195
+ });
196
+ }
197
+ }
198
+ }
199
+ if (matches.length === 0) {
200
+ return { data: 'No matches found.', isError: false };
201
+ }
202
+ const formatted = matches
203
+ .map((m) => `${m.file}:${m.lineNumber}:${m.text}`)
204
+ .join('\n');
205
+ const truncationNote = matches.length >= options.maxResults
206
+ ? `\n\n(results capped at ${options.maxResults}; use maxResults to raise the limit)`
207
+ : '';
208
+ return {
209
+ data: formatted + truncationNote,
210
+ isError: false,
211
+ };
212
+ }
213
+ // ---------------------------------------------------------------------------
214
+ // File collection with glob filtering
215
+ // ---------------------------------------------------------------------------
216
+ /**
217
+ * Recursively walk `dir` and return file paths, honouring `SKIP_DIRS` and an
218
+ * optional glob pattern.
219
+ */
220
+ async function collectFiles(dir, glob, signal) {
221
+ const results = [];
222
+ await walk(dir, glob, results, signal);
223
+ return results;
224
+ }
225
+ async function walk(dir, glob, results, signal) {
226
+ if (signal?.aborted === true)
227
+ return;
228
+ let entryNames;
229
+ try {
230
+ // Read as plain strings so we don't have to deal with Buffer Dirent variants.
231
+ entryNames = await readdir(dir, { encoding: 'utf8' });
232
+ }
233
+ catch {
234
+ return;
235
+ }
236
+ for (const entryName of entryNames) {
237
+ if (signal !== undefined && signal.aborted)
238
+ return;
239
+ const fullPath = join(dir, entryName);
240
+ let entryInfo;
241
+ try {
242
+ entryInfo = await stat(fullPath);
243
+ }
244
+ catch {
245
+ continue;
246
+ }
247
+ if (entryInfo.isDirectory()) {
248
+ if (!SKIP_DIRS.has(entryName)) {
249
+ await walk(fullPath, glob, results, signal);
250
+ }
251
+ }
252
+ else if (entryInfo.isFile()) {
253
+ if (glob === undefined || matchesGlob(entryName, glob)) {
254
+ results.push(fullPath);
255
+ }
256
+ }
257
+ }
258
+ }
259
+ /**
260
+ * Minimal glob match supporting `*.ext` and `**\/<pattern>` forms.
261
+ */
262
+ function matchesGlob(filename, glob) {
263
+ // Strip leading **/ prefix — we already recurse into all directories
264
+ const pattern = glob.startsWith('**/') ? glob.slice(3) : glob;
265
+ // Convert shell glob characters to regex equivalents
266
+ const regexSource = pattern
267
+ .replace(/[.+^${}()|[\]\\]/g, '\\$&') // escape special regex chars first
268
+ .replace(/\*/g, '.*') // * -> .*
269
+ .replace(/\?/g, '.'); // ? -> .
270
+ const re = new RegExp(`^${regexSource}$`, 'i');
271
+ return re.test(filename);
272
+ }
273
+ // ---------------------------------------------------------------------------
274
+ // ripgrep availability check (cached per process)
275
+ // ---------------------------------------------------------------------------
276
+ let rgAvailableCache;
277
+ async function isRipgrepAvailable() {
278
+ if (rgAvailableCache !== undefined)
279
+ return rgAvailableCache;
280
+ rgAvailableCache = await new Promise((resolve) => {
281
+ const child = spawn('rg', ['--version'], { stdio: 'ignore' });
282
+ child.on('close', (code) => resolve(code === 0));
283
+ child.on('error', () => resolve(false));
284
+ });
285
+ return rgAvailableCache;
286
+ }
287
+ //# sourceMappingURL=grep.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grep.js","sourceRoot":"","sources":["../../../src/tool/built-in/grep.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Built-in tool collection.
3
+ *
4
+ * Re-exports every built-in tool and provides a convenience function to
5
+ * register them all with a {@link ToolRegistry} in one call.
6
+ */
7
+ import type { ToolDefinition } from '../../types.js';
8
+ import { ToolRegistry } from '../framework.js';
9
+ import { bashTool } from './bash.js';
10
+ import { fileEditTool } from './file-edit.js';
11
+ import { fileReadTool } from './file-read.js';
12
+ import { fileWriteTool } from './file-write.js';
13
+ import { grepTool } from './grep.js';
14
+ export { bashTool, fileEditTool, fileReadTool, fileWriteTool, grepTool };
15
+ /**
16
+ * The ordered list of all built-in tools. Import this when you need to
17
+ * iterate over them without calling `registerBuiltInTools`.
18
+ *
19
+ * The array is typed as `ToolDefinition<unknown>[]` so it can be passed to
20
+ * APIs that accept any ToolDefinition without requiring a union type.
21
+ */
22
+ export declare const BUILT_IN_TOOLS: ToolDefinition<any>[];
23
+ /**
24
+ * Register all built-in tools with the given registry.
25
+ *
26
+ * @example
27
+ * ```ts
28
+ * import { ToolRegistry } from '../framework.js'
29
+ * import { registerBuiltInTools } from './built-in/index.js'
30
+ *
31
+ * const registry = new ToolRegistry()
32
+ * registerBuiltInTools(registry)
33
+ * ```
34
+ */
35
+ export declare function registerBuiltInTools(registry: ToolRegistry): void;
36
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tool/built-in/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AAEpC,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,CAAA;AAExE;;;;;;GAMG;AAEH,eAAO,MAAM,cAAc,EAAE,cAAc,CAAC,GAAG,CAAC,EAM/C,CAAA;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI,CAIjE"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Built-in tool collection.
3
+ *
4
+ * Re-exports every built-in tool and provides a convenience function to
5
+ * register them all with a {@link ToolRegistry} in one call.
6
+ */
7
+ import { bashTool } from './bash.js';
8
+ import { fileEditTool } from './file-edit.js';
9
+ import { fileReadTool } from './file-read.js';
10
+ import { fileWriteTool } from './file-write.js';
11
+ import { grepTool } from './grep.js';
12
+ export { bashTool, fileEditTool, fileReadTool, fileWriteTool, grepTool };
13
+ /**
14
+ * The ordered list of all built-in tools. Import this when you need to
15
+ * iterate over them without calling `registerBuiltInTools`.
16
+ *
17
+ * The array is typed as `ToolDefinition<unknown>[]` so it can be passed to
18
+ * APIs that accept any ToolDefinition without requiring a union type.
19
+ */
20
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
21
+ export const BUILT_IN_TOOLS = [
22
+ bashTool,
23
+ fileReadTool,
24
+ fileWriteTool,
25
+ fileEditTool,
26
+ grepTool,
27
+ ];
28
+ /**
29
+ * Register all built-in tools with the given registry.
30
+ *
31
+ * @example
32
+ * ```ts
33
+ * import { ToolRegistry } from '../framework.js'
34
+ * import { registerBuiltInTools } from './built-in/index.js'
35
+ *
36
+ * const registry = new ToolRegistry()
37
+ * registerBuiltInTools(registry)
38
+ * ```
39
+ */
40
+ export function registerBuiltInTools(registry) {
41
+ for (const tool of BUILT_IN_TOOLS) {
42
+ registry.register(tool);
43
+ }
44
+ }
45
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tool/built-in/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AAEpC,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,CAAA;AAExE;;;;;;GAMG;AACH,8DAA8D;AAC9D,MAAM,CAAC,MAAM,cAAc,GAA0B;IACnD,QAAQ;IACR,YAAY;IACZ,aAAa;IACb,YAAY;IACZ,QAAQ;CACT,CAAA;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,oBAAoB,CAAC,QAAsB;IACzD,KAAK,MAAM,IAAI,IAAI,cAAc,EAAE,CAAC;QAClC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;IACzB,CAAC;AACH,CAAC"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Parallel tool executor with concurrency control and error isolation.
3
+ *
4
+ * Validates input via Zod schemas, enforces a maximum concurrency limit using
5
+ * a lightweight semaphore, tracks execution duration, and surfaces any
6
+ * execution errors as ToolResult objects rather than thrown exceptions.
7
+ *
8
+ * Types are imported from `../types` to ensure consistency with the rest of
9
+ * the framework.
10
+ */
11
+ import type { ToolResult, ToolUseContext } from '../types.js';
12
+ import { ToolRegistry } from './framework.js';
13
+ export interface ToolExecutorOptions {
14
+ /**
15
+ * Maximum number of tool calls that may run in parallel.
16
+ * Defaults to 4.
17
+ */
18
+ maxConcurrency?: number;
19
+ }
20
+ /** Describes one call in a batch. */
21
+ export interface BatchToolCall {
22
+ /** Caller-assigned ID used as the key in the result map. */
23
+ id: string;
24
+ /** Registered tool name. */
25
+ name: string;
26
+ /** Raw (unparsed) input object from the LLM. */
27
+ input: Record<string, unknown>;
28
+ }
29
+ /**
30
+ * Executes tools from a {@link ToolRegistry}, validating input against each
31
+ * tool's Zod schema and enforcing a concurrency limit for batch execution.
32
+ *
33
+ * All errors — including unknown tool names, Zod validation failures, and
34
+ * execution exceptions — are caught and returned as `ToolResult` objects with
35
+ * `isError: true` so the agent runner can forward them to the LLM.
36
+ */
37
+ export declare class ToolExecutor {
38
+ private readonly registry;
39
+ private readonly semaphore;
40
+ constructor(registry: ToolRegistry, options?: ToolExecutorOptions);
41
+ /**
42
+ * Execute a single tool by name.
43
+ *
44
+ * Errors are caught and returned as a {@link ToolResult} with
45
+ * `isError: true` — this method itself never rejects.
46
+ *
47
+ * @param toolName The registered tool name.
48
+ * @param input Raw input object (before Zod validation).
49
+ * @param context Execution context forwarded to the tool.
50
+ */
51
+ execute(toolName: string, input: Record<string, unknown>, context: ToolUseContext): Promise<ToolResult>;
52
+ /**
53
+ * Execute multiple tool calls in parallel, honouring the concurrency limit.
54
+ *
55
+ * Returns a `Map` from call ID to result. Every call in `calls` is
56
+ * guaranteed to produce an entry — errors are captured as results.
57
+ *
58
+ * @param calls Array of tool calls to execute.
59
+ * @param context Shared execution context for all calls in this batch.
60
+ */
61
+ executeBatch(calls: BatchToolCall[], context: ToolUseContext): Promise<Map<string, ToolResult>>;
62
+ /**
63
+ * Validate input with the tool's Zod schema, then call `execute`.
64
+ * Any synchronous or asynchronous error is caught and turned into an error
65
+ * ToolResult.
66
+ */
67
+ private runTool;
68
+ /** Construct an error ToolResult. */
69
+ private errorResult;
70
+ }
71
+ //# sourceMappingURL=executor.d.ts.map