@scanton/phase2s 0.13.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 (103) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +137 -0
  3. package/dist/bin/phase2s.d.ts +3 -0
  4. package/dist/bin/phase2s.d.ts.map +1 -0
  5. package/dist/bin/phase2s.js +7 -0
  6. package/dist/bin/phase2s.js.map +1 -0
  7. package/dist/src/cli/index.d.ts +2 -0
  8. package/dist/src/cli/index.d.ts.map +1 -0
  9. package/dist/src/cli/index.js +499 -0
  10. package/dist/src/cli/index.js.map +1 -0
  11. package/dist/src/core/agent.d.ts +63 -0
  12. package/dist/src/core/agent.d.ts.map +1 -0
  13. package/dist/src/core/agent.js +178 -0
  14. package/dist/src/core/agent.js.map +1 -0
  15. package/dist/src/core/config.d.ts +52 -0
  16. package/dist/src/core/config.d.ts.map +1 -0
  17. package/dist/src/core/config.js +103 -0
  18. package/dist/src/core/config.js.map +1 -0
  19. package/dist/src/core/conversation.d.ts +44 -0
  20. package/dist/src/core/conversation.d.ts.map +1 -0
  21. package/dist/src/core/conversation.js +128 -0
  22. package/dist/src/core/conversation.js.map +1 -0
  23. package/dist/src/core/memory.d.ts +24 -0
  24. package/dist/src/core/memory.d.ts.map +1 -0
  25. package/dist/src/core/memory.js +65 -0
  26. package/dist/src/core/memory.js.map +1 -0
  27. package/dist/src/mcp/server.d.ts +73 -0
  28. package/dist/src/mcp/server.d.ts.map +1 -0
  29. package/dist/src/mcp/server.js +215 -0
  30. package/dist/src/mcp/server.js.map +1 -0
  31. package/dist/src/providers/codex.d.ts +28 -0
  32. package/dist/src/providers/codex.d.ts.map +1 -0
  33. package/dist/src/providers/codex.js +162 -0
  34. package/dist/src/providers/codex.js.map +1 -0
  35. package/dist/src/providers/index.d.ts +6 -0
  36. package/dist/src/providers/index.d.ts.map +1 -0
  37. package/dist/src/providers/index.js +13 -0
  38. package/dist/src/providers/index.js.map +1 -0
  39. package/dist/src/providers/openai.d.ts +36 -0
  40. package/dist/src/providers/openai.d.ts.map +1 -0
  41. package/dist/src/providers/openai.js +117 -0
  42. package/dist/src/providers/openai.js.map +1 -0
  43. package/dist/src/providers/types.d.ts +34 -0
  44. package/dist/src/providers/types.d.ts.map +1 -0
  45. package/dist/src/providers/types.js +2 -0
  46. package/dist/src/providers/types.js.map +1 -0
  47. package/dist/src/skills/index.d.ts +3 -0
  48. package/dist/src/skills/index.d.ts.map +1 -0
  49. package/dist/src/skills/index.js +2 -0
  50. package/dist/src/skills/index.js.map +1 -0
  51. package/dist/src/skills/loader.d.ts +23 -0
  52. package/dist/src/skills/loader.d.ts.map +1 -0
  53. package/dist/src/skills/loader.js +136 -0
  54. package/dist/src/skills/loader.js.map +1 -0
  55. package/dist/src/skills/types.d.ts +14 -0
  56. package/dist/src/skills/types.d.ts.map +1 -0
  57. package/dist/src/skills/types.js +2 -0
  58. package/dist/src/skills/types.js.map +1 -0
  59. package/dist/src/tools/file-read.d.ts +3 -0
  60. package/dist/src/tools/file-read.d.ts.map +1 -0
  61. package/dist/src/tools/file-read.js +50 -0
  62. package/dist/src/tools/file-read.js.map +1 -0
  63. package/dist/src/tools/file-write.d.ts +3 -0
  64. package/dist/src/tools/file-write.d.ts.map +1 -0
  65. package/dist/src/tools/file-write.js +90 -0
  66. package/dist/src/tools/file-write.js.map +1 -0
  67. package/dist/src/tools/glob-tool.d.ts +3 -0
  68. package/dist/src/tools/glob-tool.d.ts.map +1 -0
  69. package/dist/src/tools/glob-tool.js +38 -0
  70. package/dist/src/tools/glob-tool.js.map +1 -0
  71. package/dist/src/tools/grep-tool.d.ts +3 -0
  72. package/dist/src/tools/grep-tool.d.ts.map +1 -0
  73. package/dist/src/tools/grep-tool.js +59 -0
  74. package/dist/src/tools/grep-tool.js.map +1 -0
  75. package/dist/src/tools/index.d.ts +5 -0
  76. package/dist/src/tools/index.d.ts.map +1 -0
  77. package/dist/src/tools/index.js +17 -0
  78. package/dist/src/tools/index.js.map +1 -0
  79. package/dist/src/tools/registry.d.ts +13 -0
  80. package/dist/src/tools/registry.d.ts.map +1 -0
  81. package/dist/src/tools/registry.js +50 -0
  82. package/dist/src/tools/registry.js.map +1 -0
  83. package/dist/src/tools/sandbox.d.ts +29 -0
  84. package/dist/src/tools/sandbox.d.ts.map +1 -0
  85. package/dist/src/tools/sandbox.js +84 -0
  86. package/dist/src/tools/sandbox.js.map +1 -0
  87. package/dist/src/tools/shell.d.ts +10 -0
  88. package/dist/src/tools/shell.d.ts.map +1 -0
  89. package/dist/src/tools/shell.js +108 -0
  90. package/dist/src/tools/shell.js.map +1 -0
  91. package/dist/src/tools/types.d.ts +25 -0
  92. package/dist/src/tools/types.d.ts.map +1 -0
  93. package/dist/src/tools/types.js +54 -0
  94. package/dist/src/tools/types.js.map +1 -0
  95. package/dist/src/utils/logger.d.ts +10 -0
  96. package/dist/src/utils/logger.d.ts.map +1 -0
  97. package/dist/src/utils/logger.js +25 -0
  98. package/dist/src/utils/logger.js.map +1 -0
  99. package/dist/src/utils/prompt.d.ts +3 -0
  100. package/dist/src/utils/prompt.d.ts.map +1 -0
  101. package/dist/src/utils/prompt.js +26 -0
  102. package/dist/src/utils/prompt.js.map +1 -0
  103. package/package.json +55 -0
@@ -0,0 +1,38 @@
1
+ import { z } from "zod";
2
+ import { glob } from "glob";
3
+ import { resolve, sep } from "node:path";
4
+ const params = z.object({
5
+ pattern: z.string().describe("Glob pattern to match files (e.g. '**/*.ts')"),
6
+ cwd: z.string().optional().describe("Base directory to search from"),
7
+ ignore: z.array(z.string()).optional().describe("Patterns to ignore"),
8
+ });
9
+ export const globTool = {
10
+ name: "glob",
11
+ description: "Find files matching a glob pattern. Returns matching file paths.",
12
+ parameters: params,
13
+ async execute(raw) {
14
+ const args = params.parse(raw);
15
+ // Sandbox: validate the cwd parameter stays inside the project
16
+ const projectRoot = process.cwd();
17
+ const cwdPath = args.cwd ? resolve(args.cwd) : projectRoot;
18
+ if (!cwdPath.startsWith(projectRoot + sep) && cwdPath !== projectRoot) {
19
+ return { success: false, output: "", error: `cwd outside project directory: ${args.cwd}` };
20
+ }
21
+ try {
22
+ const files = await glob(args.pattern, {
23
+ cwd: cwdPath,
24
+ ignore: args.ignore ?? ["node_modules/**", ".git/**"],
25
+ nodir: true,
26
+ });
27
+ if (files.length === 0) {
28
+ return { success: true, output: "No files matched the pattern." };
29
+ }
30
+ return { success: true, output: files.join("\n") };
31
+ }
32
+ catch (err) {
33
+ const msg = err instanceof Error ? err.message : String(err);
34
+ return { success: false, output: "", error: msg };
35
+ }
36
+ },
37
+ };
38
+ //# sourceMappingURL=glob-tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"glob-tool.js","sourceRoot":"","sources":["../../../src/tools/glob-tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAGzC,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC;IACtB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,8CAA8C,CAAC;IAC5E,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,+BAA+B,CAAC;IACpE,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,oBAAoB,CAAC;CACtE,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,QAAQ,GAAmB;IACtC,IAAI,EAAE,MAAM;IACZ,WAAW,EAAE,kEAAkE;IAC/E,UAAU,EAAE,MAAM;IAClB,KAAK,CAAC,OAAO,CAAC,GAAY;QACxB,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAE/B,+DAA+D;QAC/D,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;QAClC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC;QAC3D,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,WAAW,GAAG,GAAG,CAAC,IAAI,OAAO,KAAK,WAAW,EAAE,CAAC;YACtE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,kCAAkC,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;QAC7F,CAAC;QAED,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE;gBACrC,GAAG,EAAE,OAAO;gBACZ,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,CAAC,iBAAiB,EAAE,SAAS,CAAC;gBACrD,KAAK,EAAE,IAAI;aACZ,CAAC,CAAC;YAEH,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACvB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,+BAA+B,EAAE,CAAC;YACpE,CAAC;YAED,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACrD,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC7D,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;QACpD,CAAC;IACH,CAAC;CACF,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { ToolDefinition } from "./types.js";
2
+ export declare const grepTool: ToolDefinition;
3
+ //# sourceMappingURL=grep-tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grep-tool.d.ts","sourceRoot":"","sources":["../../../src/tools/grep-tool.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAc,MAAM,YAAY,CAAC;AAY7D,eAAO,MAAM,QAAQ,EAAE,cAqDtB,CAAC"}
@@ -0,0 +1,59 @@
1
+ import { z } from "zod";
2
+ import { execFile } from "node:child_process";
3
+ import { promisify } from "node:util";
4
+ import { resolve, sep } from "node:path";
5
+ const execFileAsync = promisify(execFile);
6
+ const params = z.object({
7
+ pattern: z.string().describe("Regex pattern to search for"),
8
+ path: z.string().optional().describe("File or directory to search (default: current directory)"),
9
+ filePattern: z.string().optional().describe("Only search files matching this glob (e.g. '*.ts')"),
10
+ caseSensitive: z.boolean().optional().describe("Case sensitive search (default: true)"),
11
+ maxResults: z.number().optional().describe("Maximum number of results (default: 50)"),
12
+ });
13
+ export const grepTool = {
14
+ name: "grep",
15
+ description: "Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.",
16
+ parameters: params,
17
+ async execute(raw) {
18
+ const args = params.parse(raw);
19
+ const grepArgs = ["-rn", "--color=never"];
20
+ if (!args.caseSensitive && args.caseSensitive !== undefined) {
21
+ grepArgs.push("-i");
22
+ }
23
+ if (args.filePattern) {
24
+ grepArgs.push("--include", args.filePattern);
25
+ }
26
+ // Always exclude common noise
27
+ grepArgs.push("--exclude-dir=node_modules", "--exclude-dir=.git", "--exclude-dir=dist");
28
+ grepArgs.push(args.pattern);
29
+ // Sandbox: resolve and validate the search path
30
+ const projectRoot = process.cwd();
31
+ const searchPath = args.path ? resolve(args.path) : projectRoot;
32
+ if (!searchPath.startsWith(projectRoot + sep) && searchPath !== projectRoot) {
33
+ return { success: false, output: "", error: `Path outside project directory: ${args.path}` };
34
+ }
35
+ grepArgs.push(searchPath);
36
+ try {
37
+ const { stdout } = await execFileAsync("grep", grepArgs, {
38
+ maxBuffer: 1024 * 1024 * 5,
39
+ timeout: 15_000,
40
+ });
41
+ const lines = stdout.trim().split("\n");
42
+ const maxResults = args.maxResults ?? 50;
43
+ const truncated = lines.slice(0, maxResults);
44
+ let output = truncated.join("\n");
45
+ if (lines.length > maxResults) {
46
+ output += `\n\n... (${lines.length - maxResults} more results truncated)`;
47
+ }
48
+ return { success: true, output };
49
+ }
50
+ catch (err) {
51
+ if (err && typeof err === "object" && "code" in err && err.code === 1) {
52
+ return { success: true, output: "No matches found." };
53
+ }
54
+ const msg = err instanceof Error ? err.message : String(err);
55
+ return { success: false, output: "", error: msg };
56
+ }
57
+ },
58
+ };
59
+ //# sourceMappingURL=grep-tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grep-tool.js","sourceRoot":"","sources":["../../../src/tools/grep-tool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import { ToolRegistry } from "./registry.js";
2
+ export declare function createDefaultRegistry(allowDestructive?: boolean): ToolRegistry;
3
+ export { ToolRegistry } from "./registry.js";
4
+ export type { ToolDefinition, ToolResult, OpenAIFunctionDef } from "./types.js";
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAO7C,wBAAgB,qBAAqB,CAAC,gBAAgB,UAAQ,GAAG,YAAY,CAQ5E;AAED,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,17 @@
1
+ import { ToolRegistry } from "./registry.js";
2
+ import { fileReadTool } from "./file-read.js";
3
+ import { fileWriteTool } from "./file-write.js";
4
+ import { createShellTool } from "./shell.js";
5
+ import { globTool } from "./glob-tool.js";
6
+ import { grepTool } from "./grep-tool.js";
7
+ export function createDefaultRegistry(allowDestructive = false) {
8
+ const registry = new ToolRegistry();
9
+ registry.register(fileReadTool);
10
+ registry.register(fileWriteTool);
11
+ registry.register(createShellTool(allowDestructive));
12
+ registry.register(globTool);
13
+ registry.register(grepTool);
14
+ return registry;
15
+ }
16
+ export { ToolRegistry } from "./registry.js";
17
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE1C,MAAM,UAAU,qBAAqB,CAAC,gBAAgB,GAAG,KAAK;IAC5D,MAAM,QAAQ,GAAG,IAAI,YAAY,EAAE,CAAC;IACpC,QAAQ,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;IAChC,QAAQ,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;IACjC,QAAQ,CAAC,QAAQ,CAAC,eAAe,CAAC,gBAAgB,CAAC,CAAC,CAAC;IACrD,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAC5B,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAC5B,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,13 @@
1
+ import { ToolDefinition, ToolResult, type OpenAIFunctionDef } from "./types.js";
2
+ export declare class ToolRegistry {
3
+ private tools;
4
+ register(tool: ToolDefinition): void;
5
+ get(name: string): ToolDefinition | undefined;
6
+ list(): ToolDefinition[];
7
+ names(): string[];
8
+ /** Get all tools as OpenAI function definitions */
9
+ toOpenAI(): OpenAIFunctionDef[];
10
+ /** Execute a tool by name with parsed arguments */
11
+ execute(name: string, args: unknown): Promise<ToolResult>;
12
+ }
13
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/tools/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,UAAU,EAAgB,KAAK,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE9F,qBAAa,YAAY;IACvB,OAAO,CAAC,KAAK,CAAqC;IAElD,QAAQ,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI;IAIpC,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS;IAI7C,IAAI,IAAI,cAAc,EAAE;IAIxB,KAAK,IAAI,MAAM,EAAE;IAIjB,mDAAmD;IACnD,QAAQ,IAAI,iBAAiB,EAAE;IAI/B,mDAAmD;IAC7C,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC;CA6BhE"}
@@ -0,0 +1,50 @@
1
+ import { toolToOpenAI } from "./types.js";
2
+ export class ToolRegistry {
3
+ tools = new Map();
4
+ register(tool) {
5
+ this.tools.set(tool.name, tool);
6
+ }
7
+ get(name) {
8
+ return this.tools.get(name);
9
+ }
10
+ list() {
11
+ return Array.from(this.tools.values());
12
+ }
13
+ names() {
14
+ return Array.from(this.tools.keys());
15
+ }
16
+ /** Get all tools as OpenAI function definitions */
17
+ toOpenAI() {
18
+ return this.list().map(toolToOpenAI);
19
+ }
20
+ /** Execute a tool by name with parsed arguments */
21
+ async execute(name, args) {
22
+ const tool = this.tools.get(name);
23
+ if (!tool) {
24
+ return {
25
+ success: false,
26
+ output: "",
27
+ error: `Unknown tool: ${name}`,
28
+ };
29
+ }
30
+ const parsed = tool.parameters.safeParse(args);
31
+ if (!parsed.success) {
32
+ return {
33
+ success: false,
34
+ output: "",
35
+ error: `Invalid arguments for ${name}: ${parsed.error.message}`,
36
+ };
37
+ }
38
+ try {
39
+ return await tool.execute(parsed.data);
40
+ }
41
+ catch (err) {
42
+ return {
43
+ success: false,
44
+ output: "",
45
+ error: `Tool ${name} failed: ${err instanceof Error ? err.message : String(err)}`,
46
+ };
47
+ }
48
+ }
49
+ }
50
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/tools/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8B,YAAY,EAA0B,MAAM,YAAY,CAAC;AAE9F,MAAM,OAAO,YAAY;IACf,KAAK,GAAG,IAAI,GAAG,EAA0B,CAAC;IAElD,QAAQ,CAAC,IAAoB;QAC3B,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAClC,CAAC;IAED,GAAG,CAAC,IAAY;QACd,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC9B,CAAC;IAED,IAAI;QACF,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;IACzC,CAAC;IAED,KAAK;QACH,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;IACvC,CAAC;IAED,mDAAmD;IACnD,QAAQ;QACN,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IACvC,CAAC;IAED,mDAAmD;IACnD,KAAK,CAAC,OAAO,CAAC,IAAY,EAAE,IAAa;QACvC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAClC,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,MAAM,EAAE,EAAE;gBACV,KAAK,EAAE,iBAAiB,IAAI,EAAE;aAC/B,CAAC;QACJ,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAC/C,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,MAAM,EAAE,EAAE;gBACV,KAAK,EAAE,yBAAyB,IAAI,KAAK,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE;aAChE,CAAC;QACJ,CAAC;QAED,IAAI,CAAC;YACH,OAAO,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACzC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,MAAM,EAAE,EAAE;gBACV,KAAK,EAAE,QAAQ,IAAI,YAAY,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;aAClF,CAAC;QACJ,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Shared sandbox enforcement helper.
3
+ *
4
+ * Resolves `filePath` to its real (symlink-expanded) absolute path and
5
+ * verifies it lives inside `cwd` (also resolved via realpath).
6
+ *
7
+ * Why realpath() instead of resolve()?
8
+ * `path.resolve()` does lexical normalization only — it cannot follow symlinks.
9
+ * A symlink at `<project>/link -> /etc` would pass a `resolve()`-based check
10
+ * because the resolved path starts with the project root. `realpath()` follows
11
+ * the chain and returns `/etc`, which correctly fails the sandbox check.
12
+ *
13
+ * Edge cases:
14
+ * - File does not exist: realpath() throws ENOENT. We catch it and fall back
15
+ * to lexical resolve() for the sandbox check. The caller (file_write with
16
+ * createDirs) must ensure parent dirs exist before calling assertInSandbox
17
+ * when it needs the realpath guarantee for a new file.
18
+ * - Dangling symlink (points to non-existent target): realpath() throws. We
19
+ * catch it and return a sandbox error WITHOUT leaking the absolute path in
20
+ * the error message (the raw realpath error would expose it).
21
+ * - `cwd` itself: we realpath() it once per call, which is cheap and correct.
22
+ *
23
+ * @param filePath The user-supplied (potentially relative) file path.
24
+ * @param cwd The project root to sandbox against. Defaults to process.cwd().
25
+ * @returns The resolved absolute path (realpath or lexical fallback).
26
+ * @throws Error with a safe message if the path escapes the sandbox.
27
+ */
28
+ export declare function assertInSandbox(filePath: string, cwd?: string): Promise<string>;
29
+ //# sourceMappingURL=sandbox.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandbox.d.ts","sourceRoot":"","sources":["../../../src/tools/sandbox.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAChB,GAAG,GAAE,MAAsB,GAC1B,OAAO,CAAC,MAAM,CAAC,CAoDjB"}
@@ -0,0 +1,84 @@
1
+ import { realpath } from "node:fs/promises";
2
+ import { resolve, sep, dirname, basename } from "node:path";
3
+ /**
4
+ * Shared sandbox enforcement helper.
5
+ *
6
+ * Resolves `filePath` to its real (symlink-expanded) absolute path and
7
+ * verifies it lives inside `cwd` (also resolved via realpath).
8
+ *
9
+ * Why realpath() instead of resolve()?
10
+ * `path.resolve()` does lexical normalization only — it cannot follow symlinks.
11
+ * A symlink at `<project>/link -> /etc` would pass a `resolve()`-based check
12
+ * because the resolved path starts with the project root. `realpath()` follows
13
+ * the chain and returns `/etc`, which correctly fails the sandbox check.
14
+ *
15
+ * Edge cases:
16
+ * - File does not exist: realpath() throws ENOENT. We catch it and fall back
17
+ * to lexical resolve() for the sandbox check. The caller (file_write with
18
+ * createDirs) must ensure parent dirs exist before calling assertInSandbox
19
+ * when it needs the realpath guarantee for a new file.
20
+ * - Dangling symlink (points to non-existent target): realpath() throws. We
21
+ * catch it and return a sandbox error WITHOUT leaking the absolute path in
22
+ * the error message (the raw realpath error would expose it).
23
+ * - `cwd` itself: we realpath() it once per call, which is cheap and correct.
24
+ *
25
+ * @param filePath The user-supplied (potentially relative) file path.
26
+ * @param cwd The project root to sandbox against. Defaults to process.cwd().
27
+ * @returns The resolved absolute path (realpath or lexical fallback).
28
+ * @throws Error with a safe message if the path escapes the sandbox.
29
+ */
30
+ export async function assertInSandbox(filePath, cwd = process.cwd()) {
31
+ // Resolve cwd via realpath to handle the case where cwd itself is a symlink.
32
+ let realCwd;
33
+ try {
34
+ realCwd = await realpath(cwd);
35
+ }
36
+ catch {
37
+ // cwd doesn't exist or isn't accessible — use lexical fallback
38
+ realCwd = resolve(cwd);
39
+ }
40
+ // Attempt to resolve the file path via realpath (follows symlinks).
41
+ let resolvedPath;
42
+ let usedRealpath = true;
43
+ try {
44
+ resolvedPath = await realpath(resolve(cwd, filePath));
45
+ }
46
+ catch (err) {
47
+ // File doesn't exist yet (ENOENT) OR is a dangling symlink.
48
+ // For ENOENT we fall back to lexical resolve (safe — new files can't escape
49
+ // the sandbox via lexical path alone).
50
+ // For other errors (dangling symlinks, permission issues) we conservatively
51
+ // block rather than risk leaking data or paths.
52
+ const code = err.code;
53
+ if (code === "ENOENT") {
54
+ // File doesn't exist yet. Try realpath() on the parent directory to catch
55
+ // the case where the parent is a symlink pointing outside cwd.
56
+ // e.g. <project>/exfil -> /etc, then write to exfil/newfile.txt must be blocked.
57
+ const absFilePath = resolve(cwd, filePath);
58
+ const parentDir = dirname(absFilePath);
59
+ try {
60
+ const realParent = await realpath(parentDir);
61
+ // Parent exists and was realpath'd — compose the final path from the real parent.
62
+ resolvedPath = realParent + sep + basename(absFilePath);
63
+ // usedRealpath remains true — we have a realpath-based parent.
64
+ }
65
+ catch {
66
+ // Parent also doesn't exist (multi-level new path) — lexical fallback.
67
+ // This is safe because lexical normalization prevents `../` escapes.
68
+ resolvedPath = absFilePath;
69
+ usedRealpath = false;
70
+ }
71
+ }
72
+ else {
73
+ // Dangling symlink or other error — block without leaking the path.
74
+ throw new Error(`Path outside project directory: ${filePath}`);
75
+ }
76
+ }
77
+ // Sandbox check: resolved path must be inside cwd.
78
+ const sandboxRoot = usedRealpath ? realCwd : resolve(cwd);
79
+ if (!resolvedPath.startsWith(sandboxRoot + sep) && resolvedPath !== sandboxRoot) {
80
+ throw new Error(`Path outside project directory: ${filePath}`);
81
+ }
82
+ return resolvedPath;
83
+ }
84
+ //# sourceMappingURL=sandbox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandbox.js","sourceRoot":"","sources":["../../../src/tools/sandbox.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAE5D;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,QAAgB,EAChB,MAAc,OAAO,CAAC,GAAG,EAAE;IAE3B,6EAA6E;IAC7E,IAAI,OAAe,CAAC;IACpB,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,+DAA+D;QAC/D,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IACzB,CAAC;IAED,oEAAoE;IACpE,IAAI,YAAoB,CAAC;IACzB,IAAI,YAAY,GAAG,IAAI,CAAC;IACxB,IAAI,CAAC;QACH,YAAY,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC;IACxD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,4DAA4D;QAC5D,4EAA4E;QAC5E,uCAAuC;QACvC,4EAA4E;QAC5E,gDAAgD;QAChD,MAAM,IAAI,GAAI,GAA6B,CAAC,IAAI,CAAC;QACjD,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;YACtB,0EAA0E;YAC1E,+DAA+D;YAC/D,iFAAiF;YACjF,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;YAC3C,MAAM,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;YACvC,IAAI,CAAC;gBACH,MAAM,UAAU,GAAG,MAAM,QAAQ,CAAC,SAAS,CAAC,CAAC;gBAC7C,kFAAkF;gBAClF,YAAY,GAAG,UAAU,GAAG,GAAG,GAAG,QAAQ,CAAC,WAAW,CAAC,CAAC;gBACxD,+DAA+D;YACjE,CAAC;YAAC,MAAM,CAAC;gBACP,uEAAuE;gBACvE,qEAAqE;gBACrE,YAAY,GAAG,WAAW,CAAC;gBAC3B,YAAY,GAAG,KAAK,CAAC;YACvB,CAAC;QACH,CAAC;aAAM,CAAC;YACN,oEAAoE;YACpE,MAAM,IAAI,KAAK,CAAC,mCAAmC,QAAQ,EAAE,CAAC,CAAC;QACjE,CAAC;IACH,CAAC;IAED,mDAAmD;IACnD,MAAM,WAAW,GAAG,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC1D,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,WAAW,GAAG,GAAG,CAAC,IAAI,YAAY,KAAK,WAAW,EAAE,CAAC;QAChF,MAAM,IAAI,KAAK,CAAC,mCAAmC,QAAQ,EAAE,CAAC,CAAC;IACjE,CAAC;IAED,OAAO,YAAY,CAAC;AACtB,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { ToolDefinition } from "./types.js";
2
+ /**
3
+ * Create a shell tool with configurable destructive command behavior.
4
+ *
5
+ * When allowDestructive is false (default), commands matching DESTRUCTIVE_PATTERNS
6
+ * are blocked and return success: false. When true, they are allowed with a warning.
7
+ */
8
+ export declare function createShellTool(allowDestructive?: boolean): ToolDefinition;
9
+ export declare const shellTool: ToolDefinition;
10
+ //# sourceMappingURL=shell.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell.d.ts","sourceRoot":"","sources":["../../../src/tools/shell.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAc,MAAM,YAAY,CAAC;AA0B7D;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,gBAAgB,UAAQ,GAAG,cAAc,CAuExE;AAID,eAAO,MAAM,SAAS,gBAAyB,CAAC"}
@@ -0,0 +1,108 @@
1
+ import { z } from "zod";
2
+ import { execFile } from "node:child_process";
3
+ import { promisify } from "node:util";
4
+ import { resolve, sep } from "node:path";
5
+ const execFileAsync = promisify(execFile);
6
+ /** Patterns that suggest a destructive or exfiltration-risk command. */
7
+ const DESTRUCTIVE_PATTERNS = [
8
+ /rm\s+-[a-zA-Z]*r[a-zA-Z]*f/i, // rm -rf variants (case-insensitive: -RF, -rF, etc.)
9
+ /rm\s+-[a-zA-Z]*f[a-zA-Z]*r/i, // rm -fr variants (case-insensitive)
10
+ /\bcurl\b.*\|\s*(ba)?sh/, // curl | sh / curl | bash
11
+ /\bwget\b.*\|\s*(ba)?sh/, // wget | sh
12
+ /git\s+push\s+.*--force/, // git push --force
13
+ /git\s+push\s+-f\b/, // git push -f
14
+ /:\s*>\s*\S+/, // : > file (truncate via colon)
15
+ /\bdd\b.*of=/, // dd to any output file (device or otherwise)
16
+ /\bchmod\s+0?777\b/, // world-writable permission (octal 777 or 0777)
17
+ /\bsudo\b/, // sudo escalation
18
+ /\bmkfs\b/, // filesystem format (always destructive)
19
+ /:\s*\(\s*\)\s*\{.*\|.*&/, // fork bomb :(){ :|:& };:
20
+ ];
21
+ const params = z.object({
22
+ command: z.string().describe("Shell command to execute"),
23
+ timeout: z.number().min(1_000).max(300_000).optional().describe("Timeout in milliseconds (default: 30000, max: 300000)"),
24
+ cwd: z.string().optional().describe("Working directory for the command (defaults to project directory)"),
25
+ });
26
+ /**
27
+ * Create a shell tool with configurable destructive command behavior.
28
+ *
29
+ * When allowDestructive is false (default), commands matching DESTRUCTIVE_PATTERNS
30
+ * are blocked and return success: false. When true, they are allowed with a warning.
31
+ */
32
+ export function createShellTool(allowDestructive = false) {
33
+ return {
34
+ name: "shell",
35
+ description: "Execute a shell command and return its output. Use for running builds, tests, git commands, etc.",
36
+ parameters: params,
37
+ async execute(raw) {
38
+ const args = params.parse(raw);
39
+ const timeout = args.timeout ?? 30_000;
40
+ // Check for destructive patterns
41
+ for (const pattern of DESTRUCTIVE_PATTERNS) {
42
+ if (pattern.test(args.command)) {
43
+ if (!allowDestructive) {
44
+ return {
45
+ success: false,
46
+ output: "",
47
+ error: "Blocked: destructive command detected. Set allowDestructive: true in .phase2s.yaml to enable.",
48
+ };
49
+ }
50
+ process.stdout.write(` [shell] ⚠ Destructive command (allowDestructive: true): ${args.command}\n`);
51
+ break;
52
+ }
53
+ }
54
+ // Sandbox: reject cwd values that escape the project directory
55
+ const projectRoot = process.cwd();
56
+ let cwdPath = projectRoot;
57
+ if (args.cwd) {
58
+ const resolvedCwd = resolve(args.cwd);
59
+ if (!resolvedCwd.startsWith(projectRoot + sep) && resolvedCwd !== projectRoot) {
60
+ return {
61
+ success: false,
62
+ output: "",
63
+ error: `cwd outside project directory: ${args.cwd}`,
64
+ };
65
+ }
66
+ cwdPath = resolvedCwd;
67
+ }
68
+ try {
69
+ const { stdout, stderr } = await execFileAsync("/bin/sh", ["-c", args.command], {
70
+ timeout,
71
+ maxBuffer: 1024 * 1024 * 10, // 10MB
72
+ cwd: cwdPath,
73
+ });
74
+ // Return stdout and stderr separately so the LLM gets accurate signal
75
+ const parts = [];
76
+ if (stdout)
77
+ parts.push(stdout);
78
+ if (stderr)
79
+ parts.push(`[stderr]\n${stderr}`);
80
+ return { success: true, output: parts.join("\n") || "(no output)" };
81
+ }
82
+ catch (err) {
83
+ if (err && typeof err === "object" && "stdout" in err) {
84
+ const execErr = err;
85
+ const parts = [];
86
+ if (execErr.stdout)
87
+ parts.push(execErr.stdout);
88
+ if (execErr.stderr)
89
+ parts.push(`[stderr]\n${execErr.stderr}`);
90
+ const errorMsg = execErr.killed
91
+ ? `Command timed out after ${timeout}ms`
92
+ : `Command exited with code ${execErr.code}`;
93
+ return {
94
+ success: false,
95
+ output: parts.join("\n"),
96
+ error: errorMsg,
97
+ };
98
+ }
99
+ const msg = err instanceof Error ? err.message : String(err);
100
+ return { success: false, output: "", error: msg };
101
+ }
102
+ },
103
+ };
104
+ }
105
+ // Backward-compat export — blocks destructive commands (safe default).
106
+ // All existing non-destructive shell tests use this directly and are unaffected.
107
+ export const shellTool = createShellTool(false);
108
+ //# sourceMappingURL=shell.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell.js","sourceRoot":"","sources":["../../../src/tools/shell.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import { z } from "zod";
2
+ export interface ToolResult {
3
+ success: boolean;
4
+ output: string;
5
+ error?: string;
6
+ }
7
+ export interface ToolDefinition {
8
+ name: string;
9
+ description: string;
10
+ parameters: z.ZodType;
11
+ execute(params: unknown): Promise<ToolResult>;
12
+ }
13
+ /** OpenAI-compatible function definition for tool calling */
14
+ export interface OpenAIFunctionDef {
15
+ type: "function";
16
+ function: {
17
+ name: string;
18
+ description: string;
19
+ parameters: Record<string, unknown>;
20
+ };
21
+ }
22
+ /** Convert a zod schema to a JSON Schema-like object for OpenAI */
23
+ export declare function zodToJsonSchema(schema: z.ZodType): Record<string, unknown>;
24
+ export declare function toolToOpenAI(tool: ToolDefinition): OpenAIFunctionDef;
25
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/tools/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,CAAC,CAAC,OAAO,CAAC;IACtB,OAAO,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;CAC/C;AAED,6DAA6D;AAC7D,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;QACpB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACrC,CAAC;CACH;AAED,mEAAmE;AACnE,wBAAgB,eAAe,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAoB1E;AAyBD,wBAAgB,YAAY,CAAC,IAAI,EAAE,cAAc,GAAG,iBAAiB,CASpE"}
@@ -0,0 +1,54 @@
1
+ import { z } from "zod";
2
+ /** Convert a zod schema to a JSON Schema-like object for OpenAI */
3
+ export function zodToJsonSchema(schema) {
4
+ if (schema instanceof z.ZodObject) {
5
+ const shape = schema.shape;
6
+ const properties = {};
7
+ const required = [];
8
+ for (const [key, value] of Object.entries(shape)) {
9
+ properties[key] = zodFieldToJson(value);
10
+ if (!(value instanceof z.ZodOptional)) {
11
+ required.push(key);
12
+ }
13
+ }
14
+ return {
15
+ type: "object",
16
+ properties,
17
+ required: required.length > 0 ? required : undefined,
18
+ };
19
+ }
20
+ return { type: "object" };
21
+ }
22
+ function zodFieldToJson(field) {
23
+ if (field instanceof z.ZodString) {
24
+ return { type: "string", description: field.description };
25
+ }
26
+ if (field instanceof z.ZodNumber) {
27
+ return { type: "number", description: field.description };
28
+ }
29
+ if (field instanceof z.ZodBoolean) {
30
+ return { type: "boolean", description: field.description };
31
+ }
32
+ if (field instanceof z.ZodOptional) {
33
+ return zodFieldToJson(field.unwrap());
34
+ }
35
+ if (field instanceof z.ZodArray) {
36
+ return {
37
+ type: "array",
38
+ items: zodFieldToJson(field.element),
39
+ description: field.description,
40
+ };
41
+ }
42
+ return { type: "string" };
43
+ }
44
+ export function toolToOpenAI(tool) {
45
+ return {
46
+ type: "function",
47
+ function: {
48
+ name: tool.name,
49
+ description: tool.description,
50
+ parameters: zodToJsonSchema(tool.parameters),
51
+ },
52
+ };
53
+ }
54
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/tools/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAyBxB,mEAAmE;AACnE,MAAM,UAAU,eAAe,CAAC,MAAiB;IAC/C,IAAI,MAAM,YAAY,CAAC,CAAC,SAAS,EAAE,CAAC;QAClC,MAAM,KAAK,GAAG,MAAM,CAAC,KAAkC,CAAC;QACxD,MAAM,UAAU,GAA4B,EAAE,CAAC;QAC/C,MAAM,QAAQ,GAAa,EAAE,CAAC;QAE9B,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACjD,UAAU,CAAC,GAAG,CAAC,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;YACxC,IAAI,CAAC,CAAC,KAAK,YAAY,CAAC,CAAC,WAAW,CAAC,EAAE,CAAC;gBACtC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACrB,CAAC;QACH,CAAC;QAED,OAAO;YACL,IAAI,EAAE,QAAQ;YACd,UAAU;YACV,QAAQ,EAAE,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS;SACrD,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;AAC5B,CAAC;AAED,SAAS,cAAc,CAAC,KAAgB;IACtC,IAAI,KAAK,YAAY,CAAC,CAAC,SAAS,EAAE,CAAC;QACjC,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE,CAAC;IAC5D,CAAC;IACD,IAAI,KAAK,YAAY,CAAC,CAAC,SAAS,EAAE,CAAC;QACjC,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE,CAAC;IAC5D,CAAC;IACD,IAAI,KAAK,YAAY,CAAC,CAAC,UAAU,EAAE,CAAC;QAClC,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE,CAAC;IAC7D,CAAC;IACD,IAAI,KAAK,YAAY,CAAC,CAAC,WAAW,EAAE,CAAC;QACnC,OAAO,cAAc,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;IACxC,CAAC;IACD,IAAI,KAAK,YAAY,CAAC,CAAC,QAAQ,EAAE,CAAC;QAChC,OAAO;YACL,IAAI,EAAE,OAAO;YACb,KAAK,EAAE,cAAc,CAAC,KAAK,CAAC,OAAO,CAAC;YACpC,WAAW,EAAE,KAAK,CAAC,WAAW;SAC/B,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAoB;IAC/C,OAAO;QACL,IAAI,EAAE,UAAU;QAChB,QAAQ,EAAE;YACR,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,UAAU,EAAE,eAAe,CAAC,IAAI,CAAC,UAAU,CAAC;SAC7C;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,10 @@
1
+ export declare const log: {
2
+ info(msg: string): void;
3
+ success(msg: string): void;
4
+ warn(msg: string): void;
5
+ error(msg: string): void;
6
+ tool(name: string, msg: string): void;
7
+ assistant(msg: string): void;
8
+ dim(msg: string): void;
9
+ };
10
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../../src/utils/logger.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,GAAG;cACJ,MAAM,GAAG,IAAI;iBAGV,MAAM,GAAG,IAAI;cAGhB,MAAM,GAAG,IAAI;eAGZ,MAAM,GAAG,IAAI;eAGb,MAAM,OAAO,MAAM,GAAG,IAAI;mBAGtB,MAAM,GAAG,IAAI;aAGnB,MAAM,GAAG,IAAI;CAGvB,CAAC"}
@@ -0,0 +1,25 @@
1
+ import chalk from "chalk";
2
+ export const log = {
3
+ info(msg) {
4
+ console.log(chalk.blue("i"), msg);
5
+ },
6
+ success(msg) {
7
+ console.log(chalk.green("✓"), msg);
8
+ },
9
+ warn(msg) {
10
+ console.log(chalk.yellow("⚠"), msg);
11
+ },
12
+ error(msg) {
13
+ console.error(chalk.red("✗"), msg);
14
+ },
15
+ tool(name, msg) {
16
+ console.log(chalk.dim(` [${name}]`), chalk.dim(msg));
17
+ },
18
+ assistant(msg) {
19
+ console.log(msg);
20
+ },
21
+ dim(msg) {
22
+ console.log(chalk.dim(msg));
23
+ },
24
+ };
25
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../../src/utils/logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,CAAC,MAAM,GAAG,GAAG;IACjB,IAAI,CAAC,GAAW;QACd,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;IACpC,CAAC;IACD,OAAO,CAAC,GAAW;QACjB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;IACrC,CAAC;IACD,IAAI,CAAC,GAAW;QACd,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;IACtC,CAAC;IACD,KAAK,CAAC,GAAW;QACf,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;IACrC,CAAC;IACD,IAAI,CAAC,IAAY,EAAE,GAAW;QAC5B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;IACxD,CAAC;IACD,SAAS,CAAC,GAAW;QACnB,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC;IACD,GAAG,CAAC,GAAW;QACb,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9B,CAAC;CACF,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { ToolDefinition } from "../tools/types.js";
2
+ export declare function buildSystemPrompt(tools: ToolDefinition[], customPrompt?: string, learnings?: string): string;
3
+ //# sourceMappingURL=prompt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../../../src/utils/prompt.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAExD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,cAAc,EAAE,EAAE,YAAY,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CA8B5G"}