@kenkaiiii/ggcoder 4.2.43 → 4.2.45

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 (116) hide show
  1. package/dist/cli.js +21 -1
  2. package/dist/cli.js.map +1 -1
  3. package/dist/core/compaction/compactor.d.ts +1 -0
  4. package/dist/core/compaction/compactor.d.ts.map +1 -1
  5. package/dist/core/compaction/compactor.js +8 -1
  6. package/dist/core/compaction/compactor.js.map +1 -1
  7. package/dist/system-prompt.d.ts +1 -1
  8. package/dist/system-prompt.d.ts.map +1 -1
  9. package/dist/system-prompt.js +39 -2
  10. package/dist/system-prompt.js.map +1 -1
  11. package/dist/tools/bash.d.ts +3 -1
  12. package/dist/tools/bash.d.ts.map +1 -1
  13. package/dist/tools/bash.js +4 -1
  14. package/dist/tools/bash.js.map +1 -1
  15. package/dist/tools/edit-diff.test.d.ts +2 -0
  16. package/dist/tools/edit-diff.test.d.ts.map +1 -0
  17. package/dist/tools/edit-diff.test.js +67 -0
  18. package/dist/tools/edit-diff.test.js.map +1 -0
  19. package/dist/tools/edit.d.ts +3 -1
  20. package/dist/tools/edit.d.ts.map +1 -1
  21. package/dist/tools/edit.js +4 -1
  22. package/dist/tools/edit.js.map +1 -1
  23. package/dist/tools/edit.test.d.ts +2 -0
  24. package/dist/tools/edit.test.d.ts.map +1 -0
  25. package/dist/tools/edit.test.js +93 -0
  26. package/dist/tools/edit.test.js.map +1 -0
  27. package/dist/tools/enter-plan.d.ts +8 -0
  28. package/dist/tools/enter-plan.d.ts.map +1 -0
  29. package/dist/tools/enter-plan.js +28 -0
  30. package/dist/tools/enter-plan.js.map +1 -0
  31. package/dist/tools/exit-plan.d.ts +8 -0
  32. package/dist/tools/exit-plan.d.ts.map +1 -0
  33. package/dist/tools/exit-plan.js +35 -0
  34. package/dist/tools/exit-plan.js.map +1 -0
  35. package/dist/tools/index.d.ts +10 -0
  36. package/dist/tools/index.d.ts.map +1 -1
  37. package/dist/tools/index.js +15 -4
  38. package/dist/tools/index.js.map +1 -1
  39. package/dist/tools/path-utils.test.d.ts +2 -0
  40. package/dist/tools/path-utils.test.d.ts.map +1 -0
  41. package/dist/tools/path-utils.test.js +49 -0
  42. package/dist/tools/path-utils.test.js.map +1 -0
  43. package/dist/tools/plan-mode.test.d.ts +2 -0
  44. package/dist/tools/plan-mode.test.d.ts.map +1 -0
  45. package/dist/tools/plan-mode.test.js +214 -0
  46. package/dist/tools/plan-mode.test.js.map +1 -0
  47. package/dist/tools/read.test.d.ts +2 -0
  48. package/dist/tools/read.test.d.ts.map +1 -0
  49. package/dist/tools/read.test.js +81 -0
  50. package/dist/tools/read.test.js.map +1 -0
  51. package/dist/tools/subagent.d.ts +3 -1
  52. package/dist/tools/subagent.d.ts.map +1 -1
  53. package/dist/tools/subagent.js +4 -1
  54. package/dist/tools/subagent.js.map +1 -1
  55. package/dist/tools/truncate-utils.test.d.ts +2 -0
  56. package/dist/tools/truncate-utils.test.d.ts.map +1 -0
  57. package/dist/tools/truncate-utils.test.js +93 -0
  58. package/dist/tools/truncate-utils.test.js.map +1 -0
  59. package/dist/tools/write.d.ts +3 -1
  60. package/dist/tools/write.d.ts.map +1 -1
  61. package/dist/tools/write.js +13 -1
  62. package/dist/tools/write.js.map +1 -1
  63. package/dist/tools/write.test.js +65 -52
  64. package/dist/tools/write.test.js.map +1 -1
  65. package/dist/ui/App.d.ts +11 -0
  66. package/dist/ui/App.d.ts.map +1 -1
  67. package/dist/ui/App.js +146 -4
  68. package/dist/ui/App.js.map +1 -1
  69. package/dist/ui/components/ActivityIndicator.d.ts +2 -1
  70. package/dist/ui/components/ActivityIndicator.d.ts.map +1 -1
  71. package/dist/ui/components/ActivityIndicator.js +25 -4
  72. package/dist/ui/components/ActivityIndicator.js.map +1 -1
  73. package/dist/ui/components/Banner.d.ts.map +1 -1
  74. package/dist/ui/components/Banner.js +1 -1
  75. package/dist/ui/components/Banner.js.map +1 -1
  76. package/dist/ui/components/Footer.d.ts +2 -1
  77. package/dist/ui/components/Footer.d.ts.map +1 -1
  78. package/dist/ui/components/Footer.js +9 -5
  79. package/dist/ui/components/Footer.js.map +1 -1
  80. package/dist/ui/components/InputArea.d.ts +2 -1
  81. package/dist/ui/components/InputArea.d.ts.map +1 -1
  82. package/dist/ui/components/InputArea.js +13 -8
  83. package/dist/ui/components/InputArea.js.map +1 -1
  84. package/dist/ui/components/PlanApproval.d.ts +8 -0
  85. package/dist/ui/components/PlanApproval.d.ts.map +1 -0
  86. package/dist/ui/components/PlanApproval.js +44 -0
  87. package/dist/ui/components/PlanApproval.js.map +1 -0
  88. package/dist/ui/components/PlanBanner.d.ts +6 -0
  89. package/dist/ui/components/PlanBanner.d.ts.map +1 -0
  90. package/dist/ui/components/PlanBanner.js +14 -0
  91. package/dist/ui/components/PlanBanner.js.map +1 -0
  92. package/dist/ui/components/PlanOverlay.d.ts +11 -0
  93. package/dist/ui/components/PlanOverlay.d.ts.map +1 -0
  94. package/dist/ui/components/PlanOverlay.js +263 -0
  95. package/dist/ui/components/PlanOverlay.js.map +1 -0
  96. package/dist/ui/components/SkillsOverlay.js +1 -1
  97. package/dist/ui/components/SkillsOverlay.js.map +1 -1
  98. package/dist/ui/components/StreamingArea.d.ts +2 -1
  99. package/dist/ui/components/StreamingArea.d.ts.map +1 -1
  100. package/dist/ui/components/StreamingArea.js +2 -2
  101. package/dist/ui/components/StreamingArea.js.map +1 -1
  102. package/dist/ui/components/TaskOverlay.js +1 -1
  103. package/dist/ui/components/TaskOverlay.js.map +1 -1
  104. package/dist/ui/hooks/useTerminalSize.d.ts +7 -7
  105. package/dist/ui/hooks/useTerminalSize.d.ts.map +1 -1
  106. package/dist/ui/hooks/useTerminalSize.js +14 -10
  107. package/dist/ui/hooks/useTerminalSize.js.map +1 -1
  108. package/dist/ui/render.d.ts +11 -0
  109. package/dist/ui/render.d.ts.map +1 -1
  110. package/dist/ui/render.js +4 -0
  111. package/dist/ui/render.js.map +1 -1
  112. package/dist/ui/theme/dark.json +3 -1
  113. package/dist/ui/theme/light.json +3 -1
  114. package/dist/ui/theme/theme.d.ts +2 -0
  115. package/dist/ui/theme/theme.d.ts.map +1 -1
  116. package/package.json +3 -3
@@ -0,0 +1,93 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from "vitest";
2
+ import fs from "node:fs/promises";
3
+ import path from "node:path";
4
+ import os from "node:os";
5
+ import { createEditTool } from "./edit.js";
6
+ describe("createEditTool", () => {
7
+ let tmpDir;
8
+ beforeEach(async () => {
9
+ tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "edit-test-"));
10
+ });
11
+ afterEach(async () => {
12
+ await fs.rm(tmpDir, { recursive: true, force: true });
13
+ });
14
+ it("replaces exact text and returns a diff", async () => {
15
+ const filePath = path.join(tmpDir, "hello.txt");
16
+ await fs.writeFile(filePath, "hello world\n");
17
+ const tool = createEditTool(tmpDir);
18
+ const result = await tool.execute({ file_path: "hello.txt", old_text: "hello", new_text: "goodbye" }, { signal: new AbortController().signal, toolCallId: "test-1" });
19
+ expect(typeof result).toBe("string");
20
+ expect(result).toContain("-hello world");
21
+ expect(result).toContain("+goodbye world");
22
+ const written = await fs.readFile(filePath, "utf-8");
23
+ expect(written).toBe("goodbye world\n");
24
+ });
25
+ it("returns error string in plan mode", async () => {
26
+ const filePath = path.join(tmpDir, "plan.txt");
27
+ await fs.writeFile(filePath, "original\n");
28
+ const planModeRef = { current: true };
29
+ const tool = createEditTool(tmpDir, undefined, undefined, planModeRef);
30
+ const result = await tool.execute({ file_path: "plan.txt", old_text: "original", new_text: "modified" }, { signal: new AbortController().signal, toolCallId: "test-2" });
31
+ expect(result).toContain("Error: edit is restricted in plan mode");
32
+ // File should remain unchanged
33
+ const content = await fs.readFile(filePath, "utf-8");
34
+ expect(content).toBe("original\n");
35
+ });
36
+ it("throws when file hasn't been read with readFiles tracking", async () => {
37
+ const filePath = path.join(tmpDir, "unread.txt");
38
+ await fs.writeFile(filePath, "content\n");
39
+ const readFiles = new Set();
40
+ const tool = createEditTool(tmpDir, readFiles);
41
+ await expect(tool.execute({ file_path: "unread.txt", old_text: "content", new_text: "new" }, { signal: new AbortController().signal, toolCallId: "test-3" })).rejects.toThrow("File must be read first");
42
+ });
43
+ it("allows edit when file is in readFiles set", async () => {
44
+ const filePath = path.join(tmpDir, "tracked.txt");
45
+ await fs.writeFile(filePath, "alpha beta\n");
46
+ const readFiles = new Set();
47
+ readFiles.add(path.resolve(tmpDir, "tracked.txt"));
48
+ const tool = createEditTool(tmpDir, readFiles);
49
+ const result = await tool.execute({ file_path: "tracked.txt", old_text: "alpha", new_text: "gamma" }, { signal: new AbortController().signal, toolCallId: "test-4" });
50
+ expect(result).toContain("-alpha beta");
51
+ expect(result).toContain("+gamma beta");
52
+ const written = await fs.readFile(filePath, "utf-8");
53
+ expect(written).toBe("gamma beta\n");
54
+ });
55
+ it("throws when old_text is not found", async () => {
56
+ const filePath = path.join(tmpDir, "missing.txt");
57
+ await fs.writeFile(filePath, "some content here\n");
58
+ const tool = createEditTool(tmpDir);
59
+ await expect(tool.execute({ file_path: "missing.txt", old_text: "nonexistent text", new_text: "replacement" }, { signal: new AbortController().signal, toolCallId: "test-5" })).rejects.toThrow("old_text not found");
60
+ });
61
+ it("throws when old_text matches multiple times", async () => {
62
+ const filePath = path.join(tmpDir, "dupes.txt");
63
+ await fs.writeFile(filePath, "foo bar foo baz foo\n");
64
+ const tool = createEditTool(tmpDir);
65
+ await expect(tool.execute({ file_path: "dupes.txt", old_text: "foo", new_text: "qux" }, { signal: new AbortController().signal, toolCallId: "test-6" })).rejects.toThrow(/found 3 times/);
66
+ });
67
+ it("handles fuzzy matching with trailing whitespace and smart quotes", async () => {
68
+ const filePath = path.join(tmpDir, "fuzzy.txt");
69
+ // File has trailing whitespace and straight quotes
70
+ await fs.writeFile(filePath, "const msg = 'hello'; \nend\n");
71
+ const tool = createEditTool(tmpDir);
72
+ // Search with no trailing whitespace and smart quotes
73
+ const result = await tool.execute({
74
+ file_path: "fuzzy.txt",
75
+ old_text: "const msg = \u2018hello\u2019;",
76
+ new_text: "const msg = 'goodbye';",
77
+ }, { signal: new AbortController().signal, toolCallId: "test-7" });
78
+ expect(typeof result).toBe("string");
79
+ expect(result).toContain("+const msg = 'goodbye';");
80
+ const written = await fs.readFile(filePath, "utf-8");
81
+ expect(written).toContain("goodbye");
82
+ });
83
+ it("preserves CRLF line endings", async () => {
84
+ const filePath = path.join(tmpDir, "crlf.txt");
85
+ await fs.writeFile(filePath, "line one\r\nline two\r\nline three\r\n");
86
+ const tool = createEditTool(tmpDir);
87
+ const result = await tool.execute({ file_path: "crlf.txt", old_text: "line two", new_text: "line TWO" }, { signal: new AbortController().signal, toolCallId: "test-8" });
88
+ expect(result).toContain("+line TWO");
89
+ const written = await fs.readFile(filePath, "utf-8");
90
+ expect(written).toBe("line one\r\nline TWO\r\nline three\r\n");
91
+ });
92
+ });
93
+ //# sourceMappingURL=edit.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"edit.test.js","sourceRoot":"","sources":["../../src/tools/edit.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import { z } from "zod";
2
+ import type { AgentTool } from "@kenkaiiii/gg-agent";
3
+ declare const EnterPlanParams: z.ZodObject<{
4
+ reason: z.ZodOptional<z.ZodString>;
5
+ }, z.core.$strip>;
6
+ export declare function createEnterPlanTool(onEnterPlan: (reason?: string) => void): AgentTool<typeof EnterPlanParams>;
7
+ export {};
8
+ //# sourceMappingURL=enter-plan.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enter-plan.d.ts","sourceRoot":"","sources":["../../src/tools/enter-plan.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAErD,QAAA,MAAM,eAAe;;iBAKnB,CAAC;AAEH,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,GACrC,SAAS,CAAC,OAAO,eAAe,CAAC,CAsBnC"}
@@ -0,0 +1,28 @@
1
+ import { z } from "zod";
2
+ const EnterPlanParams = z.object({
3
+ reason: z
4
+ .string()
5
+ .optional()
6
+ .describe("Why you are entering plan mode (e.g. complex multi-file task)"),
7
+ });
8
+ export function createEnterPlanTool(onEnterPlan) {
9
+ return {
10
+ name: "enter_plan",
11
+ description: "Enter plan mode for safe, read-only exploration before making changes. " +
12
+ "Use this when facing complex, multi-file tasks that benefit from research and planning " +
13
+ "before implementation. In plan mode, destructive tools (bash, edit, write, subagent) are " +
14
+ "restricted — only read-only tools and writing to .gg/plans/ are allowed.",
15
+ parameters: EnterPlanParams,
16
+ async execute({ reason }) {
17
+ onEnterPlan(reason);
18
+ return ("Plan mode activated. You are now in read-only research mode.\n\n" +
19
+ "Allowed actions:\n" +
20
+ "- Use read, grep, find, ls to explore the codebase\n" +
21
+ "- Use web_fetch for documentation and references\n" +
22
+ "- Write your plan to .gg/plans/<name>.md\n\n" +
23
+ "Restricted: bash, edit, write (except .gg/plans/), subagent\n\n" +
24
+ "When your plan is ready, call exit_plan with the plan file path.");
25
+ },
26
+ };
27
+ }
28
+ //# sourceMappingURL=enter-plan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enter-plan.js","sourceRoot":"","sources":["../../src/tools/enter-plan.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,CAAC;IAC/B,MAAM,EAAE,CAAC;SACN,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CAAC,+DAA+D,CAAC;CAC7E,CAAC,CAAC;AAEH,MAAM,UAAU,mBAAmB,CACjC,WAAsC;IAEtC,OAAO;QACL,IAAI,EAAE,YAAY;QAClB,WAAW,EACT,yEAAyE;YACzE,yFAAyF;YACzF,2FAA2F;YAC3F,0EAA0E;QAC5E,UAAU,EAAE,eAAe;QAC3B,KAAK,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE;YACtB,WAAW,CAAC,MAAM,CAAC,CAAC;YACpB,OAAO,CACL,kEAAkE;gBAClE,oBAAoB;gBACpB,sDAAsD;gBACtD,oDAAoD;gBACpD,8CAA8C;gBAC9C,iEAAiE;gBACjE,kEAAkE,CACnE,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { z } from "zod";
2
+ import type { AgentTool } from "@kenkaiiii/gg-agent";
3
+ declare const ExitPlanParams: z.ZodObject<{
4
+ plan_path: z.ZodString;
5
+ }, z.core.$strip>;
6
+ export declare function createExitPlanTool(cwd: string, onExitPlan: (planPath: string) => Promise<string>): AgentTool<typeof ExitPlanParams>;
7
+ export {};
8
+ //# sourceMappingURL=exit-plan.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exit-plan.d.ts","sourceRoot":"","sources":["../../src/tools/exit-plan.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAGrD,QAAA,MAAM,cAAc;;iBAElB,CAAC;AAEH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,MAAM,EACX,UAAU,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,GAChD,SAAS,CAAC,OAAO,cAAc,CAAC,CA6BlC"}
@@ -0,0 +1,35 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { z } from "zod";
4
+ import { resolvePath } from "./path-utils.js";
5
+ const ExitPlanParams = z.object({
6
+ plan_path: z.string().describe("Path to the plan markdown file (must be under .gg/plans/)"),
7
+ });
8
+ export function createExitPlanTool(cwd, onExitPlan) {
9
+ return {
10
+ name: "exit_plan",
11
+ description: "Submit your plan for user review and exit plan mode. " +
12
+ "The plan file must be under .gg/plans/. The user will approve, reject with feedback, or cancel.",
13
+ parameters: ExitPlanParams,
14
+ async execute({ plan_path }) {
15
+ const resolved = resolvePath(cwd, plan_path);
16
+ const plansDir = path.join(cwd, ".gg", "plans");
17
+ if (!resolved.startsWith(plansDir)) {
18
+ return "Error: plan_path must be under .gg/plans/. Got: " + plan_path;
19
+ }
20
+ // Validate the plan file exists and has content
21
+ try {
22
+ const content = await fs.readFile(resolved, "utf-8");
23
+ if (!content.trim()) {
24
+ return "Error: Plan file is empty. Write your plan before calling exit_plan.";
25
+ }
26
+ }
27
+ catch {
28
+ return "Error: Could not read plan file at " + plan_path + ". Make sure the file exists.";
29
+ }
30
+ const result = await onExitPlan(resolved);
31
+ return result;
32
+ },
33
+ };
34
+ }
35
+ //# sourceMappingURL=exit-plan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exit-plan.js","sourceRoot":"","sources":["../../src/tools/exit-plan.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE9C,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,2DAA2D,CAAC;CAC5F,CAAC,CAAC;AAEH,MAAM,UAAU,kBAAkB,CAChC,GAAW,EACX,UAAiD;IAEjD,OAAO;QACL,IAAI,EAAE,WAAW;QACjB,WAAW,EACT,uDAAuD;YACvD,iGAAiG;QACnG,UAAU,EAAE,cAAc;QAC1B,KAAK,CAAC,OAAO,CAAC,EAAE,SAAS,EAAE;YACzB,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;YAC7C,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;YAEhD,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACnC,OAAO,kDAAkD,GAAG,SAAS,CAAC;YACxE,CAAC;YAED,gDAAgD;YAChD,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;gBACrD,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;oBACpB,OAAO,sEAAsE,CAAC;gBAChF,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,qCAAqC,GAAG,SAAS,GAAG,8BAA8B,CAAC;YAC5F,CAAC;YAED,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,QAAQ,CAAC,CAAC;YAC1C,OAAO,MAAM,CAAC;QAChB,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -10,6 +10,14 @@ export interface CreateToolsOptions {
10
10
  model?: string;
11
11
  /** Custom I/O operations for remote execution (SSH, Docker, etc.). Defaults to local filesystem. */
12
12
  operations?: ToolOperations;
13
+ /** Ref for checking plan mode state inside tool execute functions. */
14
+ planModeRef?: {
15
+ current: boolean;
16
+ };
17
+ /** Callback when the LLM enters plan mode. */
18
+ onEnterPlan?: (reason?: string) => void;
19
+ /** Callback when the LLM exits plan mode. Returns approval result string. */
20
+ onExitPlan?: (planPath: string) => Promise<string>;
13
21
  }
14
22
  export interface CreateToolsResult {
15
23
  tools: AgentTool[];
@@ -28,6 +36,8 @@ export { createTaskOutputTool } from "./task-output.js";
28
36
  export { createTaskStopTool } from "./task-stop.js";
29
37
  export { createTasksTool } from "./tasks.js";
30
38
  export { createSkillTool } from "./skill.js";
39
+ export { createEnterPlanTool } from "./enter-plan.js";
40
+ export { createExitPlanTool } from "./exit-plan.js";
31
41
  export { ProcessManager } from "../core/process-manager.js";
32
42
  export { localOperations, type ToolOperations } from "./operations.js";
33
43
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAc5D,OAAO,EAAmB,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACvE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAE/C,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,EAAE,eAAe,EAAE,CAAC;IAC3B,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oGAAoG;IACpG,UAAU,CAAC,EAAE,cAAc,CAAC;CAC7B;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,cAAc,EAAE,cAAc,CAAC;CAChC;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,kBAAkB,GAAG,iBAAiB,CA4BrF;AAED,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAgB5D,OAAO,EAAmB,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACvE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAE/C,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,EAAE,eAAe,EAAE,CAAC;IAC3B,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oGAAoG;IACpG,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B,sEAAsE;IACtE,WAAW,CAAC,EAAE;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IACnC,8CAA8C;IAC9C,WAAW,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,6EAA6E;IAC7E,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CACpD;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,cAAc,EAAE,cAAc,CAAC;CAChC;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,kBAAkB,GAAG,iBAAiB,CAqCrF;AAED,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAC"}
@@ -12,16 +12,19 @@ import { createTaskOutputTool } from "./task-output.js";
12
12
  import { createTaskStopTool } from "./task-stop.js";
13
13
  import { createTasksTool } from "./tasks.js";
14
14
  import { createSkillTool } from "./skill.js";
15
+ import { createEnterPlanTool } from "./enter-plan.js";
16
+ import { createExitPlanTool } from "./exit-plan.js";
15
17
  import { localOperations } from "./operations.js";
16
18
  export function createTools(cwd, opts) {
17
19
  const readFiles = new Set();
18
20
  const processManager = new ProcessManager();
19
21
  const ops = opts?.operations ?? localOperations;
22
+ const planModeRef = opts?.planModeRef;
20
23
  const tools = [
21
24
  createReadTool(cwd, readFiles, ops),
22
- createWriteTool(cwd, readFiles, ops),
23
- createEditTool(cwd, readFiles, ops),
24
- createBashTool(cwd, processManager, ops),
25
+ createWriteTool(cwd, readFiles, ops, planModeRef),
26
+ createEditTool(cwd, readFiles, ops, planModeRef),
27
+ createBashTool(cwd, processManager, ops, planModeRef),
25
28
  createFindTool(cwd),
26
29
  createGrepTool(cwd, ops),
27
30
  createLsTool(cwd, ops),
@@ -31,11 +34,17 @@ export function createTools(cwd, opts) {
31
34
  createTasksTool(cwd),
32
35
  ];
33
36
  if (opts?.agents && opts.agents.length > 0 && opts.provider && opts.model) {
34
- tools.push(createSubAgentTool(cwd, opts.agents, opts.provider, opts.model));
37
+ tools.push(createSubAgentTool(cwd, opts.agents, opts.provider, opts.model, planModeRef));
35
38
  }
36
39
  if (opts?.skills && opts.skills.length > 0) {
37
40
  tools.push(createSkillTool(opts.skills));
38
41
  }
42
+ if (opts?.onEnterPlan) {
43
+ tools.push(createEnterPlanTool(opts.onEnterPlan));
44
+ }
45
+ if (opts?.onExitPlan) {
46
+ tools.push(createExitPlanTool(cwd, opts.onExitPlan));
47
+ }
39
48
  return { tools, processManager };
40
49
  }
41
50
  export { createReadTool } from "./read.js";
@@ -50,6 +59,8 @@ export { createTaskOutputTool } from "./task-output.js";
50
59
  export { createTaskStopTool } from "./task-stop.js";
51
60
  export { createTasksTool } from "./tasks.js";
52
61
  export { createSkillTool } from "./skill.js";
62
+ export { createEnterPlanTool } from "./enter-plan.js";
63
+ export { createExitPlanTool } from "./exit-plan.js";
53
64
  export { ProcessManager } from "../core/process-manager.js";
54
65
  export { localOperations } from "./operations.js";
55
66
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAuB,MAAM,iBAAiB,CAAC;AAkBvE,MAAM,UAAU,WAAW,CAAC,GAAW,EAAE,IAAyB;IAChE,MAAM,SAAS,GAAG,IAAI,GAAG,EAAU,CAAC;IACpC,MAAM,cAAc,GAAG,IAAI,cAAc,EAAE,CAAC;IAC5C,MAAM,GAAG,GAAG,IAAI,EAAE,UAAU,IAAI,eAAe,CAAC;IAEhD,MAAM,KAAK,GAAgB;QACzB,cAAc,CAAC,GAAG,EAAE,SAAS,EAAE,GAAG,CAAC;QACnC,eAAe,CAAC,GAAG,EAAE,SAAS,EAAE,GAAG,CAAC;QACpC,cAAc,CAAC,GAAG,EAAE,SAAS,EAAE,GAAG,CAAC;QACnC,cAAc,CAAC,GAAG,EAAE,cAAc,EAAE,GAAG,CAAC;QACxC,cAAc,CAAC,GAAG,CAAC;QACnB,cAAc,CAAC,GAAG,EAAE,GAAG,CAAC;QACxB,YAAY,CAAC,GAAG,EAAE,GAAG,CAAC;QACtB,kBAAkB,EAAE;QACpB,oBAAoB,CAAC,cAAc,CAAC;QACpC,kBAAkB,CAAC,cAAc,CAAC;QAClC,eAAe,CAAC,GAAG,CAAC;KACrB,CAAC;IAEF,IAAI,IAAI,EAAE,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QAC1E,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IAC9E,CAAC;IAED,IAAI,IAAI,EAAE,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3C,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;IAC3C,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC;AACnC,CAAC;AAED,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAuB,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=path-utils.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-utils.test.d.ts","sourceRoot":"","sources":["../../src/tools/path-utils.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,49 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from "vitest";
2
+ import fs from "node:fs/promises";
3
+ import path from "node:path";
4
+ import os from "node:os";
5
+ import { resolvePath, rejectSymlink } from "./path-utils.js";
6
+ describe("resolvePath", () => {
7
+ it("resolves relative path from cwd", () => {
8
+ const result = resolvePath("/home/user/project", "src/index.ts");
9
+ expect(result).toBe(path.resolve("/home/user/project", "src/index.ts"));
10
+ });
11
+ it("returns absolute path as-is", () => {
12
+ const result = resolvePath("/home/user/project", "/etc/hosts");
13
+ expect(result).toBe("/etc/hosts");
14
+ });
15
+ it("expands ~ to home directory", () => {
16
+ const result = resolvePath("/anywhere", "~");
17
+ expect(result).toBe(os.homedir());
18
+ });
19
+ it("expands ~/path to homedir/path", () => {
20
+ const result = resolvePath("/anywhere", "~/documents/file.txt");
21
+ expect(result).toBe(path.join(os.homedir(), "documents/file.txt"));
22
+ });
23
+ });
24
+ describe("rejectSymlink", () => {
25
+ let tmpDir;
26
+ beforeEach(async () => {
27
+ tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "path-utils-test-"));
28
+ });
29
+ afterEach(async () => {
30
+ await fs.rm(tmpDir, { recursive: true, force: true });
31
+ });
32
+ it("does not throw for a regular file", async () => {
33
+ const filePath = path.join(tmpDir, "regular.txt");
34
+ await fs.writeFile(filePath, "hello");
35
+ await expect(rejectSymlink(filePath)).resolves.toBeUndefined();
36
+ });
37
+ it("throws for a symlink", async () => {
38
+ const target = path.join(tmpDir, "target.txt");
39
+ const link = path.join(tmpDir, "link.txt");
40
+ await fs.writeFile(target, "hello");
41
+ await fs.symlink(target, link);
42
+ await expect(rejectSymlink(link)).rejects.toThrow("Refusing to follow symlink");
43
+ });
44
+ it("does not throw for a non-existent file (ENOENT swallowed)", async () => {
45
+ const missing = path.join(tmpDir, "does-not-exist.txt");
46
+ await expect(rejectSymlink(missing)).resolves.toBeUndefined();
47
+ });
48
+ });
49
+ //# sourceMappingURL=path-utils.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-utils.test.js","sourceRoot":"","sources":["../../src/tools/path-utils.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=plan-mode.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan-mode.test.d.ts","sourceRoot":"","sources":["../../src/tools/plan-mode.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,214 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from "vitest";
2
+ import fs from "node:fs/promises";
3
+ import path from "node:path";
4
+ import os from "node:os";
5
+ import { createEnterPlanTool } from "./enter-plan.js";
6
+ import { createExitPlanTool } from "./exit-plan.js";
7
+ import { createWriteTool } from "./write.js";
8
+ import { createEditTool } from "./edit.js";
9
+ import { createBashTool } from "./bash.js";
10
+ import { ProcessManager } from "../core/process-manager.js";
11
+ import { buildSystemPrompt } from "../system-prompt.js";
12
+ function resultToString(result) {
13
+ return typeof result === "string" ? result : result.content;
14
+ }
15
+ const mockContext = {
16
+ signal: new AbortController().signal,
17
+ toolCallId: "test-1",
18
+ };
19
+ // ── enter_plan tool ──────────────────────────────────────
20
+ describe("createEnterPlanTool", () => {
21
+ it("calls onEnterPlan callback and returns instructions", async () => {
22
+ let calledWith;
23
+ const tool = createEnterPlanTool((reason) => {
24
+ calledWith = reason;
25
+ });
26
+ const result = resultToString(await tool.execute({ reason: "complex task" }, mockContext));
27
+ expect(calledWith).toBe("complex task");
28
+ expect(result).toContain("Plan mode activated");
29
+ expect(result).toContain(".gg/plans/");
30
+ expect(result).toContain("exit_plan");
31
+ });
32
+ it("works without a reason", async () => {
33
+ let called = false;
34
+ const tool = createEnterPlanTool(() => {
35
+ called = true;
36
+ });
37
+ await tool.execute({}, mockContext);
38
+ expect(called).toBe(true);
39
+ });
40
+ });
41
+ // ── exit_plan tool ───────────────────────────────────────
42
+ describe("createExitPlanTool", () => {
43
+ let tmpDir;
44
+ beforeEach(async () => {
45
+ tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "exit-plan-test-"));
46
+ await fs.mkdir(path.join(tmpDir, ".gg", "plans"), { recursive: true });
47
+ });
48
+ afterEach(async () => {
49
+ await fs.rm(tmpDir, { recursive: true, force: true });
50
+ });
51
+ it("rejects paths outside .gg/plans/", async () => {
52
+ const tool = createExitPlanTool(tmpDir, async () => "ok");
53
+ const result = resultToString(await tool.execute({ plan_path: "src/hack.ts" }, mockContext));
54
+ expect(result).toContain("Error");
55
+ expect(result).toContain(".gg/plans/");
56
+ });
57
+ it("rejects empty plan files", async () => {
58
+ const planPath = path.join(tmpDir, ".gg", "plans", "empty.md");
59
+ await fs.writeFile(planPath, " \n \n");
60
+ const tool = createExitPlanTool(tmpDir, async () => "should not reach");
61
+ const result = resultToString(await tool.execute({ plan_path: ".gg/plans/empty.md" }, mockContext));
62
+ expect(result).toContain("Error");
63
+ expect(result).toContain("empty");
64
+ });
65
+ it("rejects non-existent plan files", async () => {
66
+ const tool = createExitPlanTool(tmpDir, async () => "should not reach");
67
+ const result = resultToString(await tool.execute({ plan_path: ".gg/plans/ghost.md" }, mockContext));
68
+ expect(result).toContain("Error");
69
+ expect(result).toContain("Could not read");
70
+ });
71
+ it("calls onExitPlan for valid plans and returns the result", async () => {
72
+ const planPath = path.join(tmpDir, ".gg", "plans", "my-plan.md");
73
+ await fs.writeFile(planPath, "# Plan\n\n1. Step one\n2. Step two\n");
74
+ let receivedPath = "";
75
+ const tool = createExitPlanTool(tmpDir, async (p) => {
76
+ receivedPath = p;
77
+ return "Plan submitted.";
78
+ });
79
+ const result = resultToString(await tool.execute({ plan_path: ".gg/plans/my-plan.md" }, mockContext));
80
+ expect(receivedPath).toBe(planPath);
81
+ expect(result).toBe("Plan submitted.");
82
+ });
83
+ });
84
+ // ── Tool restrictions in plan mode ───────────────────────
85
+ describe("plan mode tool restrictions", () => {
86
+ let tmpDir;
87
+ const planModeRef = { current: false };
88
+ beforeEach(async () => {
89
+ tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "plan-restrict-test-"));
90
+ planModeRef.current = false;
91
+ });
92
+ afterEach(async () => {
93
+ await fs.rm(tmpDir, { recursive: true, force: true });
94
+ });
95
+ describe("bash", () => {
96
+ it("allows execution when plan mode is off", async () => {
97
+ const pm = new ProcessManager();
98
+ const tool = createBashTool(tmpDir, pm, undefined, planModeRef);
99
+ const result = resultToString(await tool.execute({ command: "echo hello" }, mockContext));
100
+ expect(result).toContain("Exit code: 0");
101
+ expect(result).toContain("hello");
102
+ pm.shutdownAll();
103
+ });
104
+ it("blocks execution when plan mode is on", async () => {
105
+ planModeRef.current = true;
106
+ const pm = new ProcessManager();
107
+ const tool = createBashTool(tmpDir, pm, undefined, planModeRef);
108
+ const result = resultToString(await tool.execute({ command: "echo hello" }, mockContext));
109
+ expect(result).toContain("Error");
110
+ expect(result).toContain("restricted in plan mode");
111
+ pm.shutdownAll();
112
+ });
113
+ });
114
+ describe("edit", () => {
115
+ it("blocks execution when plan mode is on", async () => {
116
+ planModeRef.current = true;
117
+ const readFiles = new Set();
118
+ const tool = createEditTool(tmpDir, readFiles, undefined, planModeRef);
119
+ const result = resultToString(await tool.execute({ file_path: "test.ts", old_text: "foo", new_text: "bar" }, mockContext));
120
+ expect(result).toContain("Error");
121
+ expect(result).toContain("restricted in plan mode");
122
+ });
123
+ });
124
+ describe("write", () => {
125
+ it("blocks writing to non-plan paths when plan mode is on", async () => {
126
+ planModeRef.current = true;
127
+ const tool = createWriteTool(tmpDir, undefined, undefined, planModeRef);
128
+ const result = resultToString(await tool.execute({ file_path: "src/hack.ts", content: "malicious" }, mockContext));
129
+ expect(result).toContain("Error");
130
+ expect(result).toContain("restricted in plan mode");
131
+ expect(result).toContain(".gg/plans/");
132
+ });
133
+ it("allows writing to .gg/plans/ when plan mode is on", async () => {
134
+ planModeRef.current = true;
135
+ const tool = createWriteTool(tmpDir, undefined, undefined, planModeRef);
136
+ const result = resultToString(await tool.execute({ file_path: ".gg/plans/my-plan.md", content: "# Plan\n\nDo stuff." }, mockContext));
137
+ expect(result).toContain("Wrote");
138
+ expect(result).toContain("bytes");
139
+ // Verify file was actually created
140
+ const written = await fs.readFile(path.join(tmpDir, ".gg", "plans", "my-plan.md"), "utf-8");
141
+ expect(written).toBe("# Plan\n\nDo stuff.");
142
+ });
143
+ it("creates .gg/plans/ directory if it doesn't exist", async () => {
144
+ planModeRef.current = true;
145
+ const tool = createWriteTool(tmpDir, undefined, undefined, planModeRef);
146
+ await tool.execute({ file_path: ".gg/plans/auto-created.md", content: "# Plan" }, mockContext);
147
+ const stat = await fs.stat(path.join(tmpDir, ".gg", "plans"));
148
+ expect(stat.isDirectory()).toBe(true);
149
+ });
150
+ it("allows writing anywhere when plan mode is off", async () => {
151
+ planModeRef.current = false;
152
+ const tool = createWriteTool(tmpDir, undefined, undefined, planModeRef);
153
+ const result = resultToString(await tool.execute({ file_path: "src/normal.ts", content: "export const x = 1;" }, mockContext));
154
+ expect(result).toContain("Wrote");
155
+ });
156
+ });
157
+ });
158
+ // ── System prompt generation ─────────────────────────────
159
+ describe("buildSystemPrompt with plan mode", () => {
160
+ let tmpDir;
161
+ beforeEach(async () => {
162
+ tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "prompt-test-"));
163
+ });
164
+ afterEach(async () => {
165
+ await fs.rm(tmpDir, { recursive: true, force: true });
166
+ });
167
+ it("includes plan mode section when planMode is true", async () => {
168
+ const prompt = await buildSystemPrompt(tmpDir, [], true);
169
+ expect(prompt).toContain("Plan Mode (ACTIVE)");
170
+ expect(prompt).toContain("read-only");
171
+ expect(prompt).toContain("exit_plan");
172
+ expect(prompt).toContain(".gg/plans/");
173
+ });
174
+ it("does not include plan mode section when planMode is false", async () => {
175
+ const prompt = await buildSystemPrompt(tmpDir, [], false);
176
+ expect(prompt).not.toContain("Plan Mode (ACTIVE)");
177
+ });
178
+ it("includes enter_plan and exit_plan tool descriptions", async () => {
179
+ const prompt = await buildSystemPrompt(tmpDir, [], false);
180
+ expect(prompt).toContain("enter_plan");
181
+ expect(prompt).toContain("exit_plan");
182
+ });
183
+ it("includes approved plan when approvedPlanPath is set", async () => {
184
+ const plansDir = path.join(tmpDir, ".gg", "plans");
185
+ await fs.mkdir(plansDir, { recursive: true });
186
+ const planPath = path.join(plansDir, "approved.md");
187
+ await fs.writeFile(planPath, "# My Plan\n\n1. Do this\n2. Do that\n");
188
+ const prompt = await buildSystemPrompt(tmpDir, [], false, planPath);
189
+ expect(prompt).toContain("Approved Plan");
190
+ expect(prompt).toContain("approved.md");
191
+ expect(prompt).toContain("# My Plan");
192
+ expect(prompt).toContain("Do this");
193
+ expect(prompt).toContain("Follow the plan");
194
+ });
195
+ it("does not include approved plan section when no path is set", async () => {
196
+ const prompt = await buildSystemPrompt(tmpDir, [], false);
197
+ expect(prompt).not.toContain("Approved Plan");
198
+ expect(prompt).not.toContain("<approved_plan>");
199
+ });
200
+ it("does not include approved plan when in plan mode (even if path is set)", async () => {
201
+ const planPath = path.join(tmpDir, "fake-plan.md");
202
+ const prompt = await buildSystemPrompt(tmpDir, [], true, planPath);
203
+ // Plan mode section should be present, but not the approved plan
204
+ expect(prompt).toContain("Plan Mode (ACTIVE)");
205
+ expect(prompt).not.toContain("Approved Plan");
206
+ });
207
+ it("gracefully handles missing approved plan file", async () => {
208
+ const prompt = await buildSystemPrompt(tmpDir, [], false, "/nonexistent/plan.md");
209
+ // Should not crash, and should not include the section
210
+ expect(prompt).not.toContain("Approved Plan");
211
+ expect(prompt).not.toContain("<approved_plan>");
212
+ });
213
+ });
214
+ //# sourceMappingURL=plan-mode.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan-mode.test.js","sourceRoot":"","sources":["../../src/tools/plan-mode.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=read.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read.test.d.ts","sourceRoot":"","sources":["../../src/tools/read.test.ts"],"names":[],"mappings":""}