jazz-ai 0.2.2 → 0.4.3

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 (151) hide show
  1. package/README.md +8 -6
  2. package/dist/cli/commands/chat-agent.d.ts +3 -1
  3. package/dist/cli/commands/chat-agent.d.ts.map +1 -1
  4. package/dist/cli/commands/chat-agent.js +180 -102
  5. package/dist/cli/commands/chat-agent.js.map +1 -1
  6. package/dist/cli/commands/edit-agent.d.ts +2 -2
  7. package/dist/cli/commands/edit-agent.d.ts.map +1 -1
  8. package/dist/cli/commands/edit-agent.js +20 -10
  9. package/dist/cli/commands/edit-agent.js.map +1 -1
  10. package/dist/cli/commands/task-agent.d.ts +1 -1
  11. package/dist/cli/commands/task-agent.d.ts.map +1 -1
  12. package/dist/cli/commands/task-agent.js +6 -6
  13. package/dist/cli/commands/task-agent.js.map +1 -1
  14. package/dist/constants/agent.d.ts +2 -0
  15. package/dist/constants/agent.d.ts.map +1 -0
  16. package/dist/constants/agent.js +5 -0
  17. package/dist/constants/agent.js.map +1 -0
  18. package/dist/core/agent/agent-prompt.d.ts +0 -1
  19. package/dist/core/agent/agent-prompt.d.ts.map +1 -1
  20. package/dist/core/agent/agent-prompt.js +7 -15
  21. package/dist/core/agent/agent-prompt.js.map +1 -1
  22. package/dist/core/agent/agent-runner.d.ts +15 -0
  23. package/dist/core/agent/agent-runner.d.ts.map +1 -1
  24. package/dist/core/agent/agent-runner.js +570 -270
  25. package/dist/core/agent/agent-runner.js.map +1 -1
  26. package/dist/core/agent/agent-service.d.ts +20 -5
  27. package/dist/core/agent/agent-service.d.ts.map +1 -1
  28. package/dist/core/agent/agent-service.js +54 -6
  29. package/dist/core/agent/agent-service.js.map +1 -1
  30. package/dist/core/agent/gmail-agent.js +7 -7
  31. package/dist/core/agent/gmail-agent.js.map +1 -1
  32. package/dist/core/agent/prompts/coder/v1.d.ts +2 -0
  33. package/dist/core/agent/prompts/coder/v1.d.ts.map +1 -0
  34. package/dist/core/agent/prompts/coder/v1.js +370 -0
  35. package/dist/core/agent/prompts/coder/v1.js.map +1 -0
  36. package/dist/core/agent/prompts/default/v2.d.ts +1 -1
  37. package/dist/core/agent/prompts/default/v2.d.ts.map +1 -1
  38. package/dist/core/agent/prompts/default/v2.js +1 -2
  39. package/dist/core/agent/prompts/default/v2.js.map +1 -1
  40. package/dist/core/agent/prompts/gmail/v1.d.ts +1 -1
  41. package/dist/core/agent/prompts/gmail/v1.d.ts.map +1 -1
  42. package/dist/core/agent/prompts/gmail/v1.js +5 -5
  43. package/dist/core/agent/prompts/gmail/v2.d.ts +1 -1
  44. package/dist/core/agent/prompts/gmail/v2.d.ts.map +1 -1
  45. package/dist/core/agent/prompts/gmail/v2.js +7 -7
  46. package/dist/core/agent/tools/base-tool.d.ts +3 -4
  47. package/dist/core/agent/tools/base-tool.d.ts.map +1 -1
  48. package/dist/core/agent/tools/base-tool.js +11 -51
  49. package/dist/core/agent/tools/base-tool.js.map +1 -1
  50. package/dist/core/agent/tools/context-utils.d.ts +6 -0
  51. package/dist/core/agent/tools/context-utils.d.ts.map +1 -0
  52. package/dist/core/agent/tools/context-utils.js +9 -0
  53. package/dist/core/agent/tools/context-utils.js.map +1 -0
  54. package/dist/core/agent/tools/env-utils.d.ts +7 -0
  55. package/dist/core/agent/tools/env-utils.d.ts.map +1 -0
  56. package/dist/core/agent/tools/env-utils.js +39 -0
  57. package/dist/core/agent/tools/env-utils.js.map +1 -0
  58. package/dist/core/agent/tools/fs-tools.d.ts.map +1 -1
  59. package/dist/core/agent/tools/fs-tools.js +48 -53
  60. package/dist/core/agent/tools/fs-tools.js.map +1 -1
  61. package/dist/core/agent/tools/git-tools.d.ts +5 -0
  62. package/dist/core/agent/tools/git-tools.d.ts.map +1 -1
  63. package/dist/core/agent/tools/git-tools.js +716 -154
  64. package/dist/core/agent/tools/git-tools.js.map +1 -1
  65. package/dist/core/agent/tools/gmail-tools.js +35 -35
  66. package/dist/core/agent/tools/gmail-tools.js.map +1 -1
  67. package/dist/core/agent/tools/http-tools.js +2 -2
  68. package/dist/core/agent/tools/http-tools.js.map +1 -1
  69. package/dist/core/agent/tools/register-tools.d.ts +18 -1
  70. package/dist/core/agent/tools/register-tools.d.ts.map +1 -1
  71. package/dist/core/agent/tools/register-tools.js +52 -6
  72. package/dist/core/agent/tools/register-tools.js.map +1 -1
  73. package/dist/core/agent/tools/shell-tools.d.ts.map +1 -1
  74. package/dist/core/agent/tools/shell-tools.js +10 -20
  75. package/dist/core/agent/tools/shell-tools.js.map +1 -1
  76. package/dist/core/agent/tools/tool-registry.d.ts +11 -7
  77. package/dist/core/agent/tools/tool-registry.d.ts.map +1 -1
  78. package/dist/core/agent/tools/tool-registry.js +45 -19
  79. package/dist/core/agent/tools/tool-registry.js.map +1 -1
  80. package/dist/core/agent/tools/web-search-tools.js +1 -1
  81. package/dist/core/agent/tools/web-search-tools.js.map +1 -1
  82. package/dist/core/agent/tracking/agent-run-tracker.d.ts +2 -0
  83. package/dist/core/agent/tracking/agent-run-tracker.d.ts.map +1 -1
  84. package/dist/core/agent/tracking/agent-run-tracker.js +40 -2
  85. package/dist/core/agent/tracking/agent-run-tracker.js.map +1 -1
  86. package/dist/core/types/index.d.ts +82 -15
  87. package/dist/core/types/index.d.ts.map +1 -1
  88. package/dist/core/types/index.js.map +1 -1
  89. package/dist/core/utils/markdown-renderer.d.ts +25 -0
  90. package/dist/core/utils/markdown-renderer.d.ts.map +1 -1
  91. package/dist/core/utils/markdown-renderer.js +100 -1
  92. package/dist/core/utils/markdown-renderer.js.map +1 -1
  93. package/dist/core/utils/output-renderer.d.ts +81 -0
  94. package/dist/core/utils/output-renderer.d.ts.map +1 -0
  95. package/dist/core/utils/output-renderer.js +291 -0
  96. package/dist/core/utils/output-renderer.js.map +1 -0
  97. package/dist/core/utils/output-theme.d.ts +64 -0
  98. package/dist/core/utils/output-theme.d.ts.map +1 -0
  99. package/dist/core/utils/output-theme.js +154 -0
  100. package/dist/core/utils/output-theme.js.map +1 -0
  101. package/dist/core/utils/output-writer.d.ts +79 -0
  102. package/dist/core/utils/output-writer.d.ts.map +1 -0
  103. package/dist/core/utils/output-writer.js +133 -0
  104. package/dist/core/utils/output-writer.js.map +1 -0
  105. package/dist/core/utils/runtime-detection.d.ts +28 -0
  106. package/dist/core/utils/runtime-detection.d.ts.map +1 -0
  107. package/dist/core/utils/runtime-detection.js +62 -0
  108. package/dist/core/utils/runtime-detection.js.map +1 -0
  109. package/dist/core/utils/string.d.ts +8 -0
  110. package/dist/core/utils/string.d.ts.map +1 -0
  111. package/dist/core/utils/string.js +19 -0
  112. package/dist/core/utils/string.js.map +1 -0
  113. package/dist/core/utils/thinking-renderer.d.ts +56 -0
  114. package/dist/core/utils/thinking-renderer.d.ts.map +1 -0
  115. package/dist/core/utils/thinking-renderer.js +174 -0
  116. package/dist/core/utils/thinking-renderer.js.map +1 -0
  117. package/dist/core/utils/tool-formatter.d.ts +21 -0
  118. package/dist/core/utils/tool-formatter.d.ts.map +1 -0
  119. package/dist/core/utils/tool-formatter.js +343 -0
  120. package/dist/core/utils/tool-formatter.js.map +1 -0
  121. package/dist/main.js +11 -4
  122. package/dist/main.js.map +1 -1
  123. package/dist/services/config.d.ts.map +1 -1
  124. package/dist/services/config.js +20 -20
  125. package/dist/services/config.js.map +1 -1
  126. package/dist/services/llm/ai-sdk-service.d.ts.map +1 -1
  127. package/dist/services/llm/ai-sdk-service.js +128 -37
  128. package/dist/services/llm/ai-sdk-service.js.map +1 -1
  129. package/dist/services/llm/stream-detector.d.ts +44 -0
  130. package/dist/services/llm/stream-detector.d.ts.map +1 -0
  131. package/dist/services/llm/stream-detector.js +81 -0
  132. package/dist/services/llm/stream-detector.js.map +1 -0
  133. package/dist/services/llm/stream-processor.d.ts +93 -0
  134. package/dist/services/llm/stream-processor.d.ts.map +1 -0
  135. package/dist/services/llm/stream-processor.js +330 -0
  136. package/dist/services/llm/stream-processor.js.map +1 -0
  137. package/dist/services/llm/streaming-types.d.ts +131 -0
  138. package/dist/services/llm/streaming-types.d.ts.map +1 -0
  139. package/dist/services/llm/streaming-types.js +12 -0
  140. package/dist/services/llm/streaming-types.js.map +1 -0
  141. package/dist/services/llm/types.d.ts +8 -0
  142. package/dist/services/llm/types.d.ts.map +1 -1
  143. package/dist/services/llm/types.js.map +1 -1
  144. package/dist/services/logger.d.ts +4 -4
  145. package/dist/services/logger.d.ts.map +1 -1
  146. package/dist/services/logger.js +23 -45
  147. package/dist/services/logger.js.map +1 -1
  148. package/dist/services/shell.d.ts.map +1 -1
  149. package/dist/services/shell.js +52 -18
  150. package/dist/services/shell.js.map +1 -1
  151. package/package.json +1 -1
@@ -1,19 +1,107 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  Object.defineProperty(exports, "__esModule", { value: true });
3
36
  exports.createGitStatusTool = createGitStatusTool;
4
37
  exports.createGitLogTool = createGitLogTool;
5
38
  exports.createGitDiffTool = createGitDiffTool;
6
39
  exports.createGitBranchTool = createGitBranchTool;
7
40
  exports.createGitAddTool = createGitAddTool;
41
+ exports.createExecuteGitAddTool = createExecuteGitAddTool;
8
42
  exports.createGitCommitTool = createGitCommitTool;
43
+ exports.createExecuteGitCommitTool = createExecuteGitCommitTool;
9
44
  exports.createGitPushTool = createGitPushTool;
10
45
  exports.createGitPullTool = createGitPullTool;
11
46
  exports.createGitCheckoutTool = createGitCheckoutTool;
47
+ exports.createExecuteGitPushTool = createExecuteGitPushTool;
48
+ exports.createExecuteGitPullTool = createExecuteGitPullTool;
49
+ exports.createExecuteGitCheckoutTool = createExecuteGitCheckoutTool;
12
50
  const effect_1 = require("effect");
13
51
  const zod_1 = require("zod");
14
52
  const shell_1 = require("../../../services/shell");
15
53
  const base_tool_1 = require("./base-tool");
16
- // Safe Git operations (no approval needed)
54
+ const context_utils_1 = require("./context-utils");
55
+ const env_utils_1 = require("./env-utils");
56
+ const DEFAULT_GIT_TIMEOUT = 15000;
57
+ function runGitCommand(options) {
58
+ return effect_1.Effect.gen(function* () {
59
+ const { spawn } = yield* effect_1.Effect.promise(() => Promise.resolve().then(() => __importStar(require("child_process"))));
60
+ return yield* effect_1.Effect.async((resume) => {
61
+ const sanitizedEnv = (0, env_utils_1.createSanitizedEnv)();
62
+ const gitArgs = ["--no-pager", ...options.args];
63
+ const child = spawn("git", gitArgs, {
64
+ cwd: options.workingDirectory,
65
+ stdio: ["ignore", "pipe", "pipe"],
66
+ env: sanitizedEnv,
67
+ detached: false,
68
+ });
69
+ let stdout = "";
70
+ let stderr = "";
71
+ const timeoutMs = options.timeoutMs ?? DEFAULT_GIT_TIMEOUT;
72
+ const timeoutId = setTimeout(() => {
73
+ child.kill("SIGTERM");
74
+ resume(effect_1.Effect.fail(new Error(`Git command timed out after ${timeoutMs}ms`)));
75
+ }, timeoutMs);
76
+ child.stdout.on("data", (data) => {
77
+ stdout += data.toString();
78
+ });
79
+ child.stderr.on("data", (data) => {
80
+ stderr += data.toString();
81
+ });
82
+ child.on("error", (error) => {
83
+ clearTimeout(timeoutId);
84
+ resume(effect_1.Effect.fail(error));
85
+ });
86
+ child.on("close", (code) => {
87
+ clearTimeout(timeoutId);
88
+ resume(effect_1.Effect.succeed({
89
+ stdout: stdout.trimEnd(),
90
+ stderr: stderr.trimEnd(),
91
+ exitCode: code ?? 0,
92
+ }));
93
+ });
94
+ });
95
+ });
96
+ }
97
+ function resolveWorkingDirectory(shell, context, path) {
98
+ const key = (0, context_utils_1.buildKeyFromContext)(context);
99
+ if (path && path.trim().length > 0) {
100
+ return shell.resolvePath(key, path);
101
+ }
102
+ return shell.getCwd(key);
103
+ }
104
+ // Safe Git operations (no approval needed) \\
17
105
  function createGitStatusTool() {
18
106
  const parameters = zod_1.z
19
107
  .object({
@@ -24,8 +112,8 @@ function createGitStatusTool() {
24
112
  })
25
113
  .strict();
26
114
  return (0, base_tool_1.defineTool)({
27
- name: "gitStatus",
28
- description: "Show the working tree status of a Git repository",
115
+ name: "git_status",
116
+ description: "Display the current status of a Git repository's working tree. Shows modified files, untracked files, staged changes, and current branch information. Use this to understand what changes exist before committing or to check repository state.",
29
117
  tags: ["git", "status"],
30
118
  parameters,
31
119
  validate: (args) => {
@@ -37,29 +125,53 @@ function createGitStatusTool() {
37
125
  handler: (args, context) => effect_1.Effect.gen(function* () {
38
126
  const shell = yield* shell_1.FileSystemContextServiceTag;
39
127
  const typedArgs = args;
40
- const workingDir = typedArgs.path
41
- ? yield* shell.resolvePath({
42
- agentId: context.agentId,
43
- ...(context.conversationId && { conversationId: context.conversationId }),
44
- }, typedArgs.path)
45
- : yield* shell.getCwd({
46
- agentId: context.agentId,
47
- ...(context.conversationId && { conversationId: context.conversationId }),
48
- });
49
- // For now, return a simple status message
128
+ // Catch errors from path resolution and return them as ToolExecutionResult
129
+ const workingDirResult = yield* resolveWorkingDirectory(shell, context, typedArgs.path).pipe(effect_1.Effect.catchAll((error) => effect_1.Effect.succeed({
130
+ success: false,
131
+ result: null,
132
+ error: error instanceof Error ? error.message : String(error),
133
+ })));
134
+ // If path resolution failed, return the error
135
+ if (typeof workingDirResult === "object" &&
136
+ "success" in workingDirResult &&
137
+ !workingDirResult.success) {
138
+ return workingDirResult;
139
+ }
140
+ const workingDir = workingDirResult;
141
+ const commandResult = yield* runGitCommand({
142
+ args: ["status", "--short", "--branch"],
143
+ workingDirectory: workingDir,
144
+ });
145
+ if (commandResult.exitCode !== 0) {
146
+ return {
147
+ success: false,
148
+ result: null,
149
+ error: commandResult.stderr ||
150
+ `git status failed with exit code ${commandResult.exitCode}`,
151
+ };
152
+ }
153
+ const lines = commandResult.stdout.split("\n").filter((line) => line.trim().length > 0);
154
+ const branchLine = lines.find((line) => line.startsWith("##")) ?? "";
155
+ const changes = lines.filter((line) => !line.startsWith("##"));
156
+ const hasChanges = changes.length > 0;
50
157
  return {
51
158
  success: true,
52
159
  result: {
53
160
  workingDirectory: workingDir,
54
- status: "Git status would be executed here",
55
- hasChanges: false,
161
+ branch: branchLine.replace(/^##\s*/, "") || "unknown",
162
+ hasChanges,
163
+ summary: hasChanges ? changes : ["Working tree clean"],
164
+ rawStatus: commandResult.stdout,
56
165
  },
57
166
  };
58
167
  }),
59
168
  createSummary: (result) => {
60
169
  if (result.success && typeof result.result === "object" && result.result !== null) {
61
170
  const gitResult = result.result;
62
- return gitResult.hasChanges ? "Repository has changes" : "Repository is clean (no changes)";
171
+ const suffix = gitResult.branch ? ` on ${gitResult.branch}` : "";
172
+ return gitResult.hasChanges
173
+ ? `Repository has changes${suffix}`
174
+ : `Repository is clean${suffix}`;
63
175
  }
64
176
  return result.success ? "Git status retrieved" : "Git status failed";
65
177
  },
@@ -83,8 +195,8 @@ function createGitLogTool() {
83
195
  })
84
196
  .strict();
85
197
  return (0, base_tool_1.defineTool)({
86
- name: "gitLog",
87
- description: "Show commit history of a Git repository",
198
+ name: "git_log",
199
+ description: "Display commit history of a Git repository. Shows commit hashes, authors, dates, and messages. Supports limiting results and one-line format for quick overview. Use to review recent changes, find specific commits, or understand repository evolution.",
88
200
  tags: ["git", "history"],
89
201
  parameters,
90
202
  validate: (args) => {
@@ -96,22 +208,59 @@ function createGitLogTool() {
96
208
  handler: (args, context) => effect_1.Effect.gen(function* () {
97
209
  const shell = yield* shell_1.FileSystemContextServiceTag;
98
210
  const typedArgs = args;
99
- const workingDir = typedArgs.path
100
- ? yield* shell.resolvePath({
101
- agentId: context.agentId,
102
- ...(context.conversationId && { conversationId: context.conversationId }),
103
- }, typedArgs.path)
104
- : yield* shell.getCwd({
105
- agentId: context.agentId,
106
- ...(context.conversationId && { conversationId: context.conversationId }),
107
- });
108
- // For now, return a simple log message
211
+ // Catch errors from path resolution and return them as ToolExecutionResult
212
+ const workingDirResult = yield* resolveWorkingDirectory(shell, context, typedArgs.path).pipe(effect_1.Effect.catchAll((error) => effect_1.Effect.succeed({
213
+ success: false,
214
+ result: null,
215
+ error: error instanceof Error ? error.message : String(error),
216
+ })));
217
+ // If path resolution failed, return the error
218
+ if (typeof workingDirResult === "object" &&
219
+ "success" in workingDirResult &&
220
+ !workingDirResult.success) {
221
+ return workingDirResult;
222
+ }
223
+ const workingDir = workingDirResult;
224
+ const limit = typedArgs.limit ?? 10;
225
+ const prettyFormat = "%H%x1f%h%x1f%an%x1f%ar%x1f%s%x1e";
226
+ const commandResult = yield* runGitCommand({
227
+ args: [
228
+ "log",
229
+ `--max-count=${limit}`,
230
+ `--pretty=format:${prettyFormat}`,
231
+ "--date=relative",
232
+ ],
233
+ workingDirectory: workingDir,
234
+ });
235
+ if (commandResult.exitCode !== 0) {
236
+ return {
237
+ success: false,
238
+ result: null,
239
+ error: commandResult.stderr || `git log failed with exit code ${commandResult.exitCode}`,
240
+ };
241
+ }
242
+ const commits = commandResult.stdout
243
+ .split("\x1e")
244
+ .filter((entry) => entry.trim().length > 0)
245
+ .map((entry) => {
246
+ const [hash, shortHash, author, relativeDate, subject] = entry
247
+ .split("\x1f")
248
+ .map((value) => value.trim());
249
+ return {
250
+ hash,
251
+ shortHash,
252
+ author,
253
+ relativeDate,
254
+ subject,
255
+ oneline: typedArgs.oneline ? `${shortHash} ${subject}` : undefined,
256
+ };
257
+ });
109
258
  return {
110
259
  success: true,
111
260
  result: {
112
261
  workingDirectory: workingDir,
113
- commits: "Git log would be executed here",
114
- commitCount: 0,
262
+ commitCount: commits.length,
263
+ commits,
115
264
  },
116
265
  };
117
266
  }),
@@ -137,8 +286,8 @@ function createGitDiffTool() {
137
286
  })
138
287
  .strict();
139
288
  return (0, base_tool_1.defineTool)({
140
- name: "gitDiff",
141
- description: "Show changes between commits, commit and working tree, etc.",
289
+ name: "git_diff",
290
+ description: "Display differences between commits, branches, or working tree. Shows what has changed in files (additions, deletions, modifications). Use to review changes before committing, compare branches, or see what differs from a specific commit. Supports staged changes and branch comparisons.",
142
291
  tags: ["git", "diff"],
143
292
  parameters,
144
293
  validate: (args) => {
@@ -150,24 +299,51 @@ function createGitDiffTool() {
150
299
  handler: (args, context) => effect_1.Effect.gen(function* () {
151
300
  const shell = yield* shell_1.FileSystemContextServiceTag;
152
301
  const typedArgs = args;
153
- const workingDir = typedArgs.path
154
- ? yield* shell.resolvePath({
155
- agentId: context.agentId,
156
- ...(context.conversationId && { conversationId: context.conversationId }),
157
- }, typedArgs.path)
158
- : yield* shell.getCwd({
159
- agentId: context.agentId,
160
- ...(context.conversationId && { conversationId: context.conversationId }),
161
- });
162
- // For now, return a simple diff message
302
+ // Catch errors from path resolution and return them as ToolExecutionResult
303
+ const workingDirResult = yield* resolveWorkingDirectory(shell, context, typedArgs.path).pipe(effect_1.Effect.catchAll((error) => effect_1.Effect.succeed({
304
+ success: false,
305
+ result: null,
306
+ error: error instanceof Error ? error.message : String(error),
307
+ })));
308
+ // If path resolution failed, return the error
309
+ if (typeof workingDirResult === "object" &&
310
+ "success" in workingDirResult &&
311
+ !workingDirResult.success) {
312
+ return workingDirResult;
313
+ }
314
+ const workingDir = workingDirResult;
315
+ const diffArgs = ["diff", "--no-color"];
316
+ if (typedArgs.staged) {
317
+ diffArgs.push("--staged");
318
+ }
319
+ if (typedArgs.branch) {
320
+ diffArgs.push(typedArgs.branch);
321
+ }
322
+ else if (typedArgs.commit) {
323
+ diffArgs.push(typedArgs.commit);
324
+ }
325
+ const commandResult = yield* runGitCommand({
326
+ args: diffArgs,
327
+ workingDirectory: workingDir,
328
+ timeoutMs: 20000,
329
+ });
330
+ if (commandResult.exitCode !== 0) {
331
+ return {
332
+ success: false,
333
+ result: null,
334
+ error: commandResult.stderr || `git diff failed with exit code ${commandResult.exitCode}`,
335
+ };
336
+ }
337
+ const trimmedDiff = commandResult.stdout.trimEnd();
338
+ const hasChanges = trimmedDiff.length > 0;
163
339
  return {
164
340
  success: true,
165
341
  result: {
166
342
  workingDirectory: workingDir,
167
- diff: "Git diff would be executed here",
168
- hasChanges: false,
343
+ diff: trimmedDiff || "No differences",
344
+ hasChanges,
169
345
  options: {
170
- staged: typedArgs.staged || false,
346
+ staged: typedArgs.staged ?? false,
171
347
  branch: typedArgs.branch,
172
348
  commit: typedArgs.commit,
173
349
  },
@@ -196,8 +372,8 @@ function createGitBranchTool() {
196
372
  })
197
373
  .strict();
198
374
  return (0, base_tool_1.defineTool)({
199
- name: "gitBranch",
200
- description: "List, create, or delete branches",
375
+ name: "git_branch",
376
+ description: "List Git branches (local, remote, or both). Shows all available branches and identifies the current branch. Use to see what branches exist, check which branch you're on, or discover remote branches. Note: This tool only lists branches; use git_checkout to switch branches.",
201
377
  tags: ["git", "branch"],
202
378
  parameters,
203
379
  validate: (args) => {
@@ -209,26 +385,56 @@ function createGitBranchTool() {
209
385
  handler: (args, context) => effect_1.Effect.gen(function* () {
210
386
  const shell = yield* shell_1.FileSystemContextServiceTag;
211
387
  const typedArgs = args;
212
- const workingDir = typedArgs.path
213
- ? yield* shell.resolvePath({
214
- agentId: context.agentId,
215
- ...(context.conversationId && { conversationId: context.conversationId }),
216
- }, typedArgs.path)
217
- : yield* shell.getCwd({
218
- agentId: context.agentId,
219
- ...(context.conversationId && { conversationId: context.conversationId }),
220
- });
221
- // For now, return a simple branch message
388
+ // Catch errors from path resolution and return them as ToolExecutionResult
389
+ const workingDirResult = yield* resolveWorkingDirectory(shell, context, typedArgs.path).pipe(effect_1.Effect.catchAll((error) => effect_1.Effect.succeed({
390
+ success: false,
391
+ result: null,
392
+ error: error instanceof Error ? error.message : String(error),
393
+ })));
394
+ // If path resolution failed, return the error
395
+ if (typeof workingDirResult === "object" &&
396
+ "success" in workingDirResult &&
397
+ !workingDirResult.success) {
398
+ return workingDirResult;
399
+ }
400
+ const workingDir = workingDirResult;
401
+ const branchArgs = ["branch", "--list"];
402
+ if (typedArgs.remote) {
403
+ branchArgs.push("--remotes");
404
+ }
405
+ else if (typedArgs.all) {
406
+ branchArgs.push("--all");
407
+ }
408
+ const commandResult = yield* runGitCommand({
409
+ args: branchArgs,
410
+ workingDirectory: workingDir,
411
+ });
412
+ if (commandResult.exitCode !== 0) {
413
+ return {
414
+ success: false,
415
+ result: null,
416
+ error: commandResult.stderr || `git branch failed with exit code ${commandResult.exitCode}`,
417
+ };
418
+ }
419
+ const lines = commandResult.stdout.split("\n").filter((line) => line.trim().length > 0);
420
+ let currentBranch;
421
+ const branches = lines.map((line) => {
422
+ const trimmed = line.replace(/^\*\s*/, "").trim();
423
+ if (line.trim().startsWith("*")) {
424
+ currentBranch = trimmed;
425
+ }
426
+ return trimmed;
427
+ });
222
428
  return {
223
429
  success: true,
224
430
  result: {
225
431
  workingDirectory: workingDir,
226
- branches: ["main", "develop", "feature/new-feature"],
227
- currentBranch: "main",
432
+ branches,
433
+ currentBranch,
228
434
  options: {
229
435
  list: typedArgs.list !== false,
230
- all: typedArgs.all || false,
231
- remote: typedArgs.remote || false,
436
+ all: typedArgs.all ?? false,
437
+ remote: typedArgs.remote ?? false,
232
438
  },
233
439
  },
234
440
  };
@@ -255,8 +461,8 @@ function createGitAddTool() {
255
461
  })
256
462
  .strict();
257
463
  return (0, base_tool_1.defineTool)({
258
- name: "gitAdd",
259
- description: "Add file contents to the staging area (requires user approval)",
464
+ name: "git_add",
465
+ description: "Stage files for commit by adding them to Git's index. Prepares changes to be included in the next commit. Can stage specific files or all changes. Requires user approval before execution.",
260
466
  tags: ["git", "index"],
261
467
  parameters,
262
468
  validate: (args) => {
@@ -279,28 +485,95 @@ function createGitAddTool() {
279
485
  ...(context.conversationId && { conversationId: context.conversationId }),
280
486
  });
281
487
  const filesToAdd = typedArgs.all ? "all files" : typedArgs.files.join(", ");
282
- return `Add ${filesToAdd} to Git staging area in ${workingDir}?`;
488
+ return `Add ${filesToAdd} to Git staging area in ${workingDir}?\n\nIMPORTANT: After getting user confirmation, you MUST call the execute_git_add tool with these exact arguments: {"path": ${typedArgs.path ? `"${typedArgs.path}"` : "undefined"}, "files": ${JSON.stringify(typedArgs.files)}, "all": ${typedArgs.all === true}}`;
283
489
  }),
490
+ errorMessage: "Approval required: Git add requires user confirmation.",
491
+ execute: {
492
+ toolName: "execute_git_add",
493
+ buildArgs: (args) => {
494
+ const typedArgs = args;
495
+ return {
496
+ path: typedArgs.path,
497
+ files: typedArgs.files,
498
+ all: typedArgs.all,
499
+ };
500
+ },
501
+ },
502
+ },
503
+ handler: (_args, _context) => effect_1.Effect.succeed({
504
+ success: false,
505
+ result: null,
506
+ error: "Approval required",
507
+ }),
508
+ createSummary: (result) => {
509
+ if (result.success && typeof result.result === "object" && result.result !== null) {
510
+ const gitResult = result.result;
511
+ return `Added ${Array.isArray(gitResult.addedFiles) ? gitResult.addedFiles.join(", ") : gitResult.addedFiles} to staging area`;
512
+ }
513
+ return result.success ? "Files added to Git" : "Git add failed";
514
+ },
515
+ });
516
+ }
517
+ function createExecuteGitAddTool() {
518
+ const parameters = zod_1.z
519
+ .object({
520
+ path: zod_1.z
521
+ .string()
522
+ .optional()
523
+ .describe("Path to the Git repository (defaults to current working directory)"),
524
+ files: zod_1.z.array(zod_1.z.string()).min(1).describe("Files to add to the staging area"),
525
+ all: zod_1.z.boolean().optional().describe("Add all changes in the working directory"),
526
+ })
527
+ .strict();
528
+ return (0, base_tool_1.defineTool)({
529
+ name: "execute_git_add",
530
+ description: "Internal tool that performs the actual git add operation after user has approved the git_add request. Stages files for commit by adding them to Git's index.",
531
+ hidden: true,
532
+ parameters,
533
+ validate: (args) => {
534
+ const result = parameters.safeParse(args);
535
+ return result.success
536
+ ? { valid: true, value: result.data }
537
+ : { valid: false, errors: result.error.issues.map((i) => i.message) };
284
538
  },
285
539
  handler: (args, context) => effect_1.Effect.gen(function* () {
286
540
  const shell = yield* shell_1.FileSystemContextServiceTag;
287
541
  const typedArgs = args;
288
- const workingDir = typedArgs.path
289
- ? yield* shell.resolvePath({
290
- agentId: context.agentId,
291
- ...(context.conversationId && { conversationId: context.conversationId }),
292
- }, typedArgs.path)
293
- : yield* shell.getCwd({
294
- agentId: context.agentId,
295
- ...(context.conversationId && { conversationId: context.conversationId }),
296
- });
297
- // For now, return a simple add message
542
+ const workingDirResult = yield* resolveWorkingDirectory(shell, context, typedArgs.path).pipe(effect_1.Effect.catchAll((error) => effect_1.Effect.succeed({
543
+ success: false,
544
+ result: null,
545
+ error: error instanceof Error ? error.message : String(error),
546
+ })));
547
+ if (typeof workingDirResult === "object" &&
548
+ "success" in workingDirResult &&
549
+ !workingDirResult.success) {
550
+ return workingDirResult;
551
+ }
552
+ const workingDir = workingDirResult;
553
+ const addArgs = ["add"];
554
+ if (typedArgs.all) {
555
+ addArgs.push("--all");
556
+ }
557
+ else {
558
+ addArgs.push(...typedArgs.files);
559
+ }
560
+ const commandResult = yield* runGitCommand({
561
+ args: addArgs,
562
+ workingDirectory: workingDir,
563
+ });
564
+ if (commandResult.exitCode !== 0) {
565
+ return {
566
+ success: false,
567
+ result: null,
568
+ error: commandResult.stderr || `git add failed with exit code ${commandResult.exitCode}`,
569
+ };
570
+ }
298
571
  return {
299
572
  success: true,
300
573
  result: {
301
574
  workingDirectory: workingDir,
302
575
  addedFiles: typedArgs.all ? "all files" : typedArgs.files,
303
- message: "Files would be added to staging area",
576
+ message: "Files added to staging area",
304
577
  },
305
578
  };
306
579
  }),
@@ -325,8 +598,8 @@ function createGitCommitTool() {
325
598
  })
326
599
  .strict();
327
600
  return (0, base_tool_1.defineTool)({
328
- name: "gitCommit",
329
- description: "Record changes to the repository (requires user approval)",
601
+ name: "git_commit",
602
+ description: "Create a commit to permanently record staged changes in the repository history. Requires a commit message describing the changes. Can commit all staged changes or all working directory changes. Requires user approval before execution.",
330
603
  tags: ["git", "commit"],
331
604
  parameters,
332
605
  validate: (args) => {
@@ -348,28 +621,98 @@ function createGitCommitTool() {
348
621
  agentId: context.agentId,
349
622
  ...(context.conversationId && { conversationId: context.conversationId }),
350
623
  });
351
- return `Commit changes in ${workingDir} with message: "${typedArgs.message}"?`;
624
+ return `Commit changes in ${workingDir} with message: "${typedArgs.message}"?\n\nIMPORTANT: After getting user confirmation, you MUST call the execute_git_commit tool with these exact arguments: {"path": ${typedArgs.path ? `"${typedArgs.path}"` : "undefined"}, "message": ${JSON.stringify(typedArgs.message)}, "all": ${typedArgs.all === true}}`;
352
625
  }),
626
+ errorMessage: "Approval required: Git commit requires user confirmation.",
627
+ execute: {
628
+ toolName: "execute_git_commit",
629
+ buildArgs: (args) => {
630
+ const typedArgs = args;
631
+ return {
632
+ path: typedArgs.path,
633
+ message: typedArgs.message,
634
+ all: typedArgs.all,
635
+ };
636
+ },
637
+ },
638
+ },
639
+ handler: (_args, _context) => effect_1.Effect.succeed({
640
+ success: false,
641
+ result: null,
642
+ error: "Approval required",
643
+ }),
644
+ createSummary: (result) => {
645
+ if (result.success && typeof result.result === "object" && result.result !== null) {
646
+ const gitResult = result.result;
647
+ return `Committed: "${gitResult.message}" (${gitResult.commitHash})`;
648
+ }
649
+ return result.success ? "Git commit created" : "Git commit failed";
650
+ },
651
+ });
652
+ }
653
+ function createExecuteGitCommitTool() {
654
+ const parameters = zod_1.z
655
+ .object({
656
+ path: zod_1.z
657
+ .string()
658
+ .optional()
659
+ .describe("Path to the Git repository (defaults to current working directory)"),
660
+ message: zod_1.z.string().min(1).describe("Commit message"),
661
+ all: zod_1.z.boolean().optional().describe("Commit all changes in the working directory"),
662
+ })
663
+ .strict();
664
+ return (0, base_tool_1.defineTool)({
665
+ name: "execute_git_commit",
666
+ description: "Internal tool that performs the actual git commit operation after user has approved the git_commit request. Creates a commit with the specified message.",
667
+ hidden: true,
668
+ parameters,
669
+ validate: (args) => {
670
+ const result = parameters.safeParse(args);
671
+ return result.success
672
+ ? { valid: true, value: result.data }
673
+ : { valid: false, errors: result.error.issues.map((i) => i.message) };
353
674
  },
354
675
  handler: (args, context) => effect_1.Effect.gen(function* () {
355
676
  const shell = yield* shell_1.FileSystemContextServiceTag;
356
677
  const typedArgs = args;
357
- const workingDir = typedArgs.path
358
- ? yield* shell.resolvePath({
359
- agentId: context.agentId,
360
- ...(context.conversationId && { conversationId: context.conversationId }),
361
- }, typedArgs.path)
362
- : yield* shell.getCwd({
363
- agentId: context.agentId,
364
- ...(context.conversationId && { conversationId: context.conversationId }),
365
- });
366
- // For now, return a simple commit message
678
+ const workingDirResult = yield* resolveWorkingDirectory(shell, context, typedArgs.path).pipe(effect_1.Effect.catchAll((error) => effect_1.Effect.succeed({
679
+ success: false,
680
+ result: null,
681
+ error: error instanceof Error ? error.message : String(error),
682
+ })));
683
+ if (typeof workingDirResult === "object" &&
684
+ "success" in workingDirResult &&
685
+ !workingDirResult.success) {
686
+ return workingDirResult;
687
+ }
688
+ const workingDir = workingDirResult;
689
+ const commitArgs = ["commit", "-m", typedArgs.message];
690
+ if (typedArgs.all) {
691
+ commitArgs.push("--all");
692
+ }
693
+ const commandResult = yield* runGitCommand({
694
+ args: commitArgs,
695
+ workingDirectory: workingDir,
696
+ });
697
+ if (commandResult.exitCode !== 0) {
698
+ return {
699
+ success: false,
700
+ result: null,
701
+ error: commandResult.stderr || `git commit failed with exit code ${commandResult.exitCode}`,
702
+ };
703
+ }
704
+ // Get the commit hash from the last commit
705
+ const hashResult = yield* runGitCommand({
706
+ args: ["rev-parse", "HEAD"],
707
+ workingDirectory: workingDir,
708
+ });
709
+ const commitHash = hashResult.exitCode === 0 ? hashResult.stdout.trim() : "unknown";
367
710
  return {
368
711
  success: true,
369
712
  result: {
370
713
  workingDirectory: workingDir,
371
714
  message: typedArgs.message,
372
- commitHash: "abc123",
715
+ commitHash,
373
716
  },
374
717
  };
375
718
  }),
@@ -395,8 +738,8 @@ function createGitPushTool() {
395
738
  })
396
739
  .strict();
397
740
  return (0, base_tool_1.defineTool)({
398
- name: "gitPush",
399
- description: "Update remote refs along with associated objects (requires user approval)",
741
+ name: "git_push",
742
+ description: "Upload local commits to a remote repository. Pushes the current branch (or specified branch) to the remote (default: origin). Supports force push to overwrite remote history (use with caution). Requires user approval before execution.",
400
743
  tags: ["git", "push"],
401
744
  parameters,
402
745
  validate: (args) => {
@@ -421,32 +764,26 @@ function createGitPushTool() {
421
764
  const remote = typedArgs.remote || "origin";
422
765
  const branch = typedArgs.branch || "current branch";
423
766
  const force = typedArgs.force ? " (force push)" : "";
424
- return `Push${force} to ${remote}/${branch} in ${workingDir}?`;
767
+ return `Push${force} to ${remote}/${branch} in ${workingDir}?\n\nIMPORTANT: After getting user confirmation, you MUST call the execute_git_push tool with these exact arguments: {"path": ${typedArgs.path ? `"${typedArgs.path}"` : "undefined"}, "remote": ${typedArgs.remote ? `"${typedArgs.remote}"` : "undefined"}, "branch": ${typedArgs.branch ? `"${typedArgs.branch}"` : "undefined"}, "force": ${typedArgs.force === true}}`;
425
768
  }),
426
- },
427
- handler: (args, context) => effect_1.Effect.gen(function* () {
428
- const shell = yield* shell_1.FileSystemContextServiceTag;
429
- const typedArgs = args;
430
- const workingDir = typedArgs.path
431
- ? yield* shell.resolvePath({
432
- agentId: context.agentId,
433
- ...(context.conversationId && { conversationId: context.conversationId }),
434
- }, typedArgs.path)
435
- : yield* shell.getCwd({
436
- agentId: context.agentId,
437
- ...(context.conversationId && { conversationId: context.conversationId }),
438
- });
439
- // For now, return a simple push message
440
- return {
441
- success: true,
442
- result: {
443
- workingDirectory: workingDir,
444
- remote: typedArgs.remote || "origin",
445
- branch: typedArgs.branch || "current",
446
- force: typedArgs.force || false,
447
- message: "Changes would be pushed successfully",
769
+ errorMessage: "Approval required: Git push requires user confirmation.",
770
+ execute: {
771
+ toolName: "execute_git_push",
772
+ buildArgs: (args) => {
773
+ const typedArgs = args;
774
+ return {
775
+ path: typedArgs.path,
776
+ remote: typedArgs.remote,
777
+ branch: typedArgs.branch,
778
+ force: typedArgs.force,
779
+ };
448
780
  },
449
- };
781
+ },
782
+ },
783
+ handler: (_args, _context) => effect_1.Effect.succeed({
784
+ success: false,
785
+ result: null,
786
+ error: "Approval required",
450
787
  }),
451
788
  createSummary: (result) => {
452
789
  if (result.success && typeof result.result === "object" && result.result !== null) {
@@ -470,8 +807,8 @@ function createGitPullTool() {
470
807
  })
471
808
  .strict();
472
809
  return (0, base_tool_1.defineTool)({
473
- name: "gitPull",
474
- description: "Fetch from and integrate with another repository or a local branch (requires user approval)",
810
+ name: "git_pull",
811
+ description: "Download and merge changes from a remote repository into the current branch. Combines git fetch and git merge. Supports rebase mode to maintain linear history. Use to update your local branch with remote changes. Requires user approval before execution.",
475
812
  tags: ["git", "pull"],
476
813
  parameters,
477
814
  validate: (args) => {
@@ -496,32 +833,26 @@ function createGitPullTool() {
496
833
  const remote = typedArgs.remote || "origin";
497
834
  const branch = typedArgs.branch || "current branch";
498
835
  const rebase = typedArgs.rebase ? " (with rebase)" : "";
499
- return `Pull${rebase} from ${remote}/${branch} in ${workingDir}?`;
836
+ return `Pull${rebase} from ${remote}/${branch} in ${workingDir}?\n\nIMPORTANT: After getting user confirmation, you MUST call the execute_git_pull tool with these exact arguments: {"path": ${typedArgs.path ? `"${typedArgs.path}"` : "undefined"}, "remote": ${typedArgs.remote ? `"${typedArgs.remote}"` : "undefined"}, "branch": ${typedArgs.branch ? `"${typedArgs.branch}"` : "undefined"}, "rebase": ${typedArgs.rebase === true}}`;
500
837
  }),
501
- },
502
- handler: (args, context) => effect_1.Effect.gen(function* () {
503
- const shell = yield* shell_1.FileSystemContextServiceTag;
504
- const typedArgs = args;
505
- const workingDir = typedArgs.path
506
- ? yield* shell.resolvePath({
507
- agentId: context.agentId,
508
- ...(context.conversationId && { conversationId: context.conversationId }),
509
- }, typedArgs.path)
510
- : yield* shell.getCwd({
511
- agentId: context.agentId,
512
- ...(context.conversationId && { conversationId: context.conversationId }),
513
- });
514
- // For now, return a simple pull message
515
- return {
516
- success: true,
517
- result: {
518
- workingDirectory: workingDir,
519
- remote: typedArgs.remote || "origin",
520
- branch: typedArgs.branch || "current",
521
- rebase: typedArgs.rebase || false,
522
- message: "Changes would be pulled successfully",
838
+ errorMessage: "Approval required: Git pull requires user confirmation.",
839
+ execute: {
840
+ toolName: "execute_git_pull",
841
+ buildArgs: (args) => {
842
+ const typedArgs = args;
843
+ return {
844
+ path: typedArgs.path,
845
+ remote: typedArgs.remote,
846
+ branch: typedArgs.branch,
847
+ rebase: typedArgs.rebase,
848
+ };
523
849
  },
524
- };
850
+ },
851
+ },
852
+ handler: (_args, _context) => effect_1.Effect.succeed({
853
+ success: false,
854
+ result: null,
855
+ error: "Approval required",
525
856
  }),
526
857
  createSummary: (result) => {
527
858
  if (result.success && typeof result.result === "object" && result.result !== null) {
@@ -545,8 +876,8 @@ function createGitCheckoutTool() {
545
876
  })
546
877
  .strict();
547
878
  return (0, base_tool_1.defineTool)({
548
- name: "gitCheckout",
549
- description: "Switch branches or restore working tree files (requires user approval)",
879
+ name: "git_checkout",
880
+ description: "Switch to a different branch or create a new branch. Changes the working directory to match the specified branch. Can create new branches or force checkout (discarding local changes). Use to navigate between branches or start work on a new feature branch. Requires user approval before execution.",
550
881
  tags: ["git", "checkout"],
551
882
  parameters,
552
883
  validate: (args) => {
@@ -570,22 +901,253 @@ function createGitCheckoutTool() {
570
901
  });
571
902
  const create = typedArgs.create ? " (create new branch)" : "";
572
903
  const force = typedArgs.force ? " (force - discards changes)" : "";
573
- return `Checkout branch "${typedArgs.branch}"${create}${force} in ${workingDir}?`;
904
+ return `Checkout branch "${typedArgs.branch}"${create}${force} in ${workingDir}?\n\nIMPORTANT: After getting user confirmation, you MUST call the execute_git_checkout tool with these exact arguments: {"path": ${typedArgs.path ? `"${typedArgs.path}"` : "undefined"}, "branch": "${typedArgs.branch}", "create": ${typedArgs.create === true}, "force": ${typedArgs.force === true}}`;
574
905
  }),
906
+ errorMessage: "Approval required: Git checkout requires user confirmation.",
907
+ execute: {
908
+ toolName: "execute_git_checkout",
909
+ buildArgs: (args) => {
910
+ const typedArgs = args;
911
+ return {
912
+ path: typedArgs.path,
913
+ branch: typedArgs.branch,
914
+ create: typedArgs.create,
915
+ force: typedArgs.force,
916
+ };
917
+ },
918
+ },
919
+ },
920
+ handler: (_args, _context) => effect_1.Effect.succeed({
921
+ success: false,
922
+ result: null,
923
+ error: "Approval required",
924
+ }),
925
+ createSummary: (result) => {
926
+ if (result.success && typeof result.result === "object" && result.result !== null) {
927
+ const gitResult = result.result;
928
+ return `Switched to ${gitResult.branch}${gitResult.created ? " (newly created)" : ""}`;
929
+ }
930
+ return result.success ? "Git checkout successful" : "Git checkout failed";
931
+ },
932
+ });
933
+ }
934
+ function createExecuteGitPushTool() {
935
+ const parameters = zod_1.z
936
+ .object({
937
+ path: zod_1.z
938
+ .string()
939
+ .optional()
940
+ .describe("Path to the Git repository (defaults to current working directory)"),
941
+ remote: zod_1.z.string().optional().describe("Remote repository name (defaults to 'origin')"),
942
+ branch: zod_1.z.string().optional().describe("Branch to push (defaults to current branch)"),
943
+ force: zod_1.z.boolean().optional().describe("Force push (overwrites remote history)"),
944
+ })
945
+ .strict();
946
+ return (0, base_tool_1.defineTool)({
947
+ name: "execute_git_push",
948
+ description: "Internal tool that performs the actual git push operation after user has approved the git_push request. Uploads local commits to the remote repository.",
949
+ hidden: true,
950
+ parameters,
951
+ validate: (args) => {
952
+ const result = parameters.safeParse(args);
953
+ return result.success
954
+ ? { valid: true, value: result.data }
955
+ : { valid: false, errors: result.error.issues.map((i) => i.message) };
956
+ },
957
+ handler: (args, context) => effect_1.Effect.gen(function* () {
958
+ const shell = yield* shell_1.FileSystemContextServiceTag;
959
+ const typedArgs = args;
960
+ const workingDirResult = yield* resolveWorkingDirectory(shell, context, typedArgs.path).pipe(effect_1.Effect.catchAll((error) => effect_1.Effect.succeed({
961
+ success: false,
962
+ result: null,
963
+ error: error instanceof Error ? error.message : String(error),
964
+ })));
965
+ if (typeof workingDirResult === "object" &&
966
+ "success" in workingDirResult &&
967
+ !workingDirResult.success) {
968
+ return workingDirResult;
969
+ }
970
+ const workingDir = workingDirResult;
971
+ const remote = typedArgs.remote || "origin";
972
+ const branch = typedArgs.branch || "";
973
+ const pushArgs = ["push"];
974
+ if (typedArgs.force) {
975
+ pushArgs.push("--force");
976
+ }
977
+ if (branch) {
978
+ pushArgs.push(remote, branch);
979
+ }
980
+ else {
981
+ pushArgs.push(remote);
982
+ }
983
+ const commandResult = yield* runGitCommand({
984
+ args: pushArgs,
985
+ workingDirectory: workingDir,
986
+ });
987
+ if (commandResult.exitCode !== 0) {
988
+ return {
989
+ success: false,
990
+ result: null,
991
+ error: commandResult.stderr || `git push failed with exit code ${commandResult.exitCode}`,
992
+ };
993
+ }
994
+ return {
995
+ success: true,
996
+ result: {
997
+ workingDirectory: workingDir,
998
+ remote,
999
+ branch: branch || "current",
1000
+ force: typedArgs.force || false,
1001
+ message: "Changes pushed successfully",
1002
+ },
1003
+ };
1004
+ }),
1005
+ createSummary: (result) => {
1006
+ if (result.success && typeof result.result === "object" && result.result !== null) {
1007
+ const gitResult = result.result;
1008
+ return `Pushed to ${gitResult.remote}/${gitResult.branch}${gitResult.force ? " (force)" : ""}`;
1009
+ }
1010
+ return result.success ? "Git push successful" : "Git push failed";
1011
+ },
1012
+ });
1013
+ }
1014
+ function createExecuteGitPullTool() {
1015
+ const parameters = zod_1.z
1016
+ .object({
1017
+ path: zod_1.z
1018
+ .string()
1019
+ .optional()
1020
+ .describe("Path to the Git repository (defaults to current working directory)"),
1021
+ remote: zod_1.z.string().optional().describe("Remote repository name (defaults to 'origin')"),
1022
+ branch: zod_1.z.string().optional().describe("Branch to pull (defaults to current branch)"),
1023
+ rebase: zod_1.z.boolean().optional().describe("Use rebase instead of merge"),
1024
+ })
1025
+ .strict();
1026
+ return (0, base_tool_1.defineTool)({
1027
+ name: "execute_git_pull",
1028
+ description: "Internal tool that performs the actual git pull operation after user has approved the git_pull request. Downloads and merges changes from the remote repository.",
1029
+ hidden: true,
1030
+ parameters,
1031
+ validate: (args) => {
1032
+ const result = parameters.safeParse(args);
1033
+ return result.success
1034
+ ? { valid: true, value: result.data }
1035
+ : { valid: false, errors: result.error.issues.map((i) => i.message) };
575
1036
  },
576
1037
  handler: (args, context) => effect_1.Effect.gen(function* () {
577
1038
  const shell = yield* shell_1.FileSystemContextServiceTag;
578
1039
  const typedArgs = args;
579
- const workingDir = typedArgs.path
580
- ? yield* shell.resolvePath({
581
- agentId: context.agentId,
582
- ...(context.conversationId && { conversationId: context.conversationId }),
583
- }, typedArgs.path)
584
- : yield* shell.getCwd({
585
- agentId: context.agentId,
586
- ...(context.conversationId && { conversationId: context.conversationId }),
587
- });
588
- // For now, return a simple checkout message
1040
+ const workingDirResult = yield* resolveWorkingDirectory(shell, context, typedArgs.path).pipe(effect_1.Effect.catchAll((error) => effect_1.Effect.succeed({
1041
+ success: false,
1042
+ result: null,
1043
+ error: error instanceof Error ? error.message : String(error),
1044
+ })));
1045
+ if (typeof workingDirResult === "object" &&
1046
+ "success" in workingDirResult &&
1047
+ !workingDirResult.success) {
1048
+ return workingDirResult;
1049
+ }
1050
+ const workingDir = workingDirResult;
1051
+ const remote = typedArgs.remote || "origin";
1052
+ const branch = typedArgs.branch || "";
1053
+ const pullArgs = ["pull"];
1054
+ if (typedArgs.rebase) {
1055
+ pullArgs.push("--rebase");
1056
+ }
1057
+ if (branch) {
1058
+ pullArgs.push(remote, branch);
1059
+ }
1060
+ else {
1061
+ pullArgs.push(remote);
1062
+ }
1063
+ const commandResult = yield* runGitCommand({
1064
+ args: pullArgs,
1065
+ workingDirectory: workingDir,
1066
+ });
1067
+ if (commandResult.exitCode !== 0) {
1068
+ return {
1069
+ success: false,
1070
+ result: null,
1071
+ error: commandResult.stderr || `git pull failed with exit code ${commandResult.exitCode}`,
1072
+ };
1073
+ }
1074
+ return {
1075
+ success: true,
1076
+ result: {
1077
+ workingDirectory: workingDir,
1078
+ remote,
1079
+ branch: branch || "current",
1080
+ rebase: typedArgs.rebase || false,
1081
+ message: "Changes pulled successfully",
1082
+ },
1083
+ };
1084
+ }),
1085
+ createSummary: (result) => {
1086
+ if (result.success && typeof result.result === "object" && result.result !== null) {
1087
+ const gitResult = result.result;
1088
+ return `Pulled from ${gitResult.remote}/${gitResult.branch}${gitResult.rebase ? " (rebase)" : ""}`;
1089
+ }
1090
+ return result.success ? "Git pull successful" : "Git pull failed";
1091
+ },
1092
+ });
1093
+ }
1094
+ function createExecuteGitCheckoutTool() {
1095
+ const parameters = zod_1.z
1096
+ .object({
1097
+ path: zod_1.z
1098
+ .string()
1099
+ .optional()
1100
+ .describe("Path to the Git repository (defaults to current working directory)"),
1101
+ branch: zod_1.z.string().min(1).describe("Branch name to checkout"),
1102
+ create: zod_1.z.boolean().optional().describe("Create the branch if it doesn't exist"),
1103
+ force: zod_1.z.boolean().optional().describe("Force checkout (discards local changes)"),
1104
+ })
1105
+ .strict();
1106
+ return (0, base_tool_1.defineTool)({
1107
+ name: "execute_git_checkout",
1108
+ description: "Internal tool that performs the actual git checkout operation after user has approved the git_checkout request. Switches to the specified branch or creates a new branch.",
1109
+ hidden: true,
1110
+ parameters,
1111
+ validate: (args) => {
1112
+ const result = parameters.safeParse(args);
1113
+ return result.success
1114
+ ? { valid: true, value: result.data }
1115
+ : { valid: false, errors: result.error.issues.map((i) => i.message) };
1116
+ },
1117
+ handler: (args, context) => effect_1.Effect.gen(function* () {
1118
+ const shell = yield* shell_1.FileSystemContextServiceTag;
1119
+ const typedArgs = args;
1120
+ const workingDirResult = yield* resolveWorkingDirectory(shell, context, typedArgs.path).pipe(effect_1.Effect.catchAll((error) => effect_1.Effect.succeed({
1121
+ success: false,
1122
+ result: null,
1123
+ error: error instanceof Error ? error.message : String(error),
1124
+ })));
1125
+ if (typeof workingDirResult === "object" &&
1126
+ "success" in workingDirResult &&
1127
+ !workingDirResult.success) {
1128
+ return workingDirResult;
1129
+ }
1130
+ const workingDir = workingDirResult;
1131
+ const checkoutArgs = ["checkout"];
1132
+ if (typedArgs.create) {
1133
+ checkoutArgs.push("-b");
1134
+ }
1135
+ if (typedArgs.force) {
1136
+ checkoutArgs.push("--force");
1137
+ }
1138
+ checkoutArgs.push(typedArgs.branch);
1139
+ const commandResult = yield* runGitCommand({
1140
+ args: checkoutArgs,
1141
+ workingDirectory: workingDir,
1142
+ });
1143
+ if (commandResult.exitCode !== 0) {
1144
+ return {
1145
+ success: false,
1146
+ result: null,
1147
+ error: commandResult.stderr ||
1148
+ `git checkout failed with exit code ${commandResult.exitCode}`,
1149
+ };
1150
+ }
589
1151
  return {
590
1152
  success: true,
591
1153
  result: {