@morphllm/morphsdk 0.2.6

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 (168) hide show
  1. package/README.md +39 -0
  2. package/dist/chunk-4UVEBIDK.js +358 -0
  3. package/dist/chunk-4UVEBIDK.js.map +1 -0
  4. package/dist/chunk-4V46N27D.js +169 -0
  5. package/dist/chunk-4V46N27D.js.map +1 -0
  6. package/dist/chunk-4VWJFZVS.js +89 -0
  7. package/dist/chunk-4VWJFZVS.js.map +1 -0
  8. package/dist/chunk-5COKN3XD.js +91 -0
  9. package/dist/chunk-5COKN3XD.js.map +1 -0
  10. package/dist/chunk-5VQEQSJQ.js +394 -0
  11. package/dist/chunk-5VQEQSJQ.js.map +1 -0
  12. package/dist/chunk-63WE2C5R.js +43 -0
  13. package/dist/chunk-63WE2C5R.js.map +1 -0
  14. package/dist/chunk-74ZHKB54.js +9 -0
  15. package/dist/chunk-74ZHKB54.js.map +1 -0
  16. package/dist/chunk-7PZJQFCY.js +39 -0
  17. package/dist/chunk-7PZJQFCY.js.map +1 -0
  18. package/dist/chunk-BILUTNBC.js +83 -0
  19. package/dist/chunk-BILUTNBC.js.map +1 -0
  20. package/dist/chunk-G4DJ6VSM.js +78 -0
  21. package/dist/chunk-G4DJ6VSM.js.map +1 -0
  22. package/dist/chunk-HGIFACNP.js +59 -0
  23. package/dist/chunk-HGIFACNP.js.map +1 -0
  24. package/dist/chunk-OI5YYE36.js +189 -0
  25. package/dist/chunk-OI5YYE36.js.map +1 -0
  26. package/dist/chunk-PZ5AY32C.js +10 -0
  27. package/dist/chunk-PZ5AY32C.js.map +1 -0
  28. package/dist/chunk-VJK4PH5V.js +105 -0
  29. package/dist/chunk-VJK4PH5V.js.map +1 -0
  30. package/dist/chunk-WXBUVKYL.js +128 -0
  31. package/dist/chunk-WXBUVKYL.js.map +1 -0
  32. package/dist/chunk-X2K57BH6.js +1 -0
  33. package/dist/chunk-X2K57BH6.js.map +1 -0
  34. package/dist/chunk-YQMPVJ2L.js +32 -0
  35. package/dist/chunk-YQMPVJ2L.js.map +1 -0
  36. package/dist/chunk-YWS2GRQC.js +97 -0
  37. package/dist/chunk-YWS2GRQC.js.map +1 -0
  38. package/dist/chunk-ZQEWQ7LJ.js +97 -0
  39. package/dist/chunk-ZQEWQ7LJ.js.map +1 -0
  40. package/dist/client.cjs +1358 -0
  41. package/dist/client.cjs.map +1 -0
  42. package/dist/client.js +15 -0
  43. package/dist/client.js.map +1 -0
  44. package/dist/git/client.cjs +428 -0
  45. package/dist/git/client.cjs.map +1 -0
  46. package/dist/git/client.js +8 -0
  47. package/dist/git/client.js.map +1 -0
  48. package/dist/git/config.cjs +41 -0
  49. package/dist/git/config.cjs.map +1 -0
  50. package/dist/git/config.js +17 -0
  51. package/dist/git/config.js.map +1 -0
  52. package/dist/git/index.cjs +438 -0
  53. package/dist/git/index.cjs.map +1 -0
  54. package/dist/git/index.js +14 -0
  55. package/dist/git/index.js.map +1 -0
  56. package/dist/git/types.cjs +19 -0
  57. package/dist/git/types.cjs.map +1 -0
  58. package/dist/git/types.js +1 -0
  59. package/dist/git/types.js.map +1 -0
  60. package/dist/index.cjs +1372 -0
  61. package/dist/index.cjs.map +1 -0
  62. package/dist/index.js +34 -0
  63. package/dist/index.js.map +1 -0
  64. package/dist/tools/browser/anthropic.cjs +281 -0
  65. package/dist/tools/browser/anthropic.cjs.map +1 -0
  66. package/dist/tools/browser/anthropic.js +72 -0
  67. package/dist/tools/browser/anthropic.js.map +1 -0
  68. package/dist/tools/browser/core.cjs +459 -0
  69. package/dist/tools/browser/core.cjs.map +1 -0
  70. package/dist/tools/browser/core.js +21 -0
  71. package/dist/tools/browser/core.js.map +1 -0
  72. package/dist/tools/browser/index.cjs +497 -0
  73. package/dist/tools/browser/index.cjs.map +1 -0
  74. package/dist/tools/browser/index.js +27 -0
  75. package/dist/tools/browser/index.js.map +1 -0
  76. package/dist/tools/browser/openai.cjs +297 -0
  77. package/dist/tools/browser/openai.cjs.map +1 -0
  78. package/dist/tools/browser/openai.js +85 -0
  79. package/dist/tools/browser/openai.js.map +1 -0
  80. package/dist/tools/browser/prompts.cjs +64 -0
  81. package/dist/tools/browser/prompts.cjs.map +1 -0
  82. package/dist/tools/browser/prompts.js +10 -0
  83. package/dist/tools/browser/prompts.js.map +1 -0
  84. package/dist/tools/browser/types.cjs +19 -0
  85. package/dist/tools/browser/types.cjs.map +1 -0
  86. package/dist/tools/browser/types.js +1 -0
  87. package/dist/tools/browser/types.js.map +1 -0
  88. package/dist/tools/browser/vercel.cjs +242 -0
  89. package/dist/tools/browser/vercel.cjs.map +1 -0
  90. package/dist/tools/browser/vercel.js +49 -0
  91. package/dist/tools/browser/vercel.js.map +1 -0
  92. package/dist/tools/codebase_search/anthropic.cjs +267 -0
  93. package/dist/tools/codebase_search/anthropic.cjs.map +1 -0
  94. package/dist/tools/codebase_search/anthropic.js +11 -0
  95. package/dist/tools/codebase_search/anthropic.js.map +1 -0
  96. package/dist/tools/codebase_search/core.cjs +201 -0
  97. package/dist/tools/codebase_search/core.cjs.map +1 -0
  98. package/dist/tools/codebase_search/core.js +11 -0
  99. package/dist/tools/codebase_search/core.js.map +1 -0
  100. package/dist/tools/codebase_search/index.cjs +393 -0
  101. package/dist/tools/codebase_search/index.cjs.map +1 -0
  102. package/dist/tools/codebase_search/index.js +27 -0
  103. package/dist/tools/codebase_search/index.js.map +1 -0
  104. package/dist/tools/codebase_search/openai.cjs +316 -0
  105. package/dist/tools/codebase_search/openai.cjs.map +1 -0
  106. package/dist/tools/codebase_search/openai.js +21 -0
  107. package/dist/tools/codebase_search/openai.js.map +1 -0
  108. package/dist/tools/codebase_search/prompts.cjs +57 -0
  109. package/dist/tools/codebase_search/prompts.cjs.map +1 -0
  110. package/dist/tools/codebase_search/prompts.js +10 -0
  111. package/dist/tools/codebase_search/prompts.js.map +1 -0
  112. package/dist/tools/codebase_search/types.cjs +19 -0
  113. package/dist/tools/codebase_search/types.cjs.map +1 -0
  114. package/dist/tools/codebase_search/types.js +1 -0
  115. package/dist/tools/codebase_search/types.js.map +1 -0
  116. package/dist/tools/codebase_search/vercel.cjs +230 -0
  117. package/dist/tools/codebase_search/vercel.cjs.map +1 -0
  118. package/dist/tools/codebase_search/vercel.js +15 -0
  119. package/dist/tools/codebase_search/vercel.js.map +1 -0
  120. package/dist/tools/fastapply/anthropic.cjs +335 -0
  121. package/dist/tools/fastapply/anthropic.cjs.map +1 -0
  122. package/dist/tools/fastapply/anthropic.js +13 -0
  123. package/dist/tools/fastapply/anthropic.js.map +1 -0
  124. package/dist/tools/fastapply/core.cjs +267 -0
  125. package/dist/tools/fastapply/core.cjs.map +1 -0
  126. package/dist/tools/fastapply/core.js +15 -0
  127. package/dist/tools/fastapply/core.js.map +1 -0
  128. package/dist/tools/fastapply/index.cjs +500 -0
  129. package/dist/tools/fastapply/index.cjs.map +1 -0
  130. package/dist/tools/fastapply/index.js +32 -0
  131. package/dist/tools/fastapply/index.js.map +1 -0
  132. package/dist/tools/fastapply/openai.cjs +353 -0
  133. package/dist/tools/fastapply/openai.cjs.map +1 -0
  134. package/dist/tools/fastapply/openai.js +21 -0
  135. package/dist/tools/fastapply/openai.js.map +1 -0
  136. package/dist/tools/fastapply/prompts.cjs +68 -0
  137. package/dist/tools/fastapply/prompts.cjs.map +1 -0
  138. package/dist/tools/fastapply/prompts.js +10 -0
  139. package/dist/tools/fastapply/prompts.js.map +1 -0
  140. package/dist/tools/fastapply/types.cjs +19 -0
  141. package/dist/tools/fastapply/types.cjs.map +1 -0
  142. package/dist/tools/fastapply/types.js +1 -0
  143. package/dist/tools/fastapply/types.js.map +1 -0
  144. package/dist/tools/fastapply/vercel.cjs +347 -0
  145. package/dist/tools/fastapply/vercel.cjs.map +1 -0
  146. package/dist/tools/fastapply/vercel.js +17 -0
  147. package/dist/tools/fastapply/vercel.js.map +1 -0
  148. package/dist/tools/index.cjs +500 -0
  149. package/dist/tools/index.cjs.map +1 -0
  150. package/dist/tools/index.js +32 -0
  151. package/dist/tools/index.js.map +1 -0
  152. package/dist/tools/modelrouter/core.cjs +286 -0
  153. package/dist/tools/modelrouter/core.cjs.map +1 -0
  154. package/dist/tools/modelrouter/core.js +13 -0
  155. package/dist/tools/modelrouter/core.js.map +1 -0
  156. package/dist/tools/modelrouter/index.cjs +286 -0
  157. package/dist/tools/modelrouter/index.cjs.map +1 -0
  158. package/dist/tools/modelrouter/index.js +13 -0
  159. package/dist/tools/modelrouter/index.js.map +1 -0
  160. package/dist/tools/modelrouter/types.cjs +19 -0
  161. package/dist/tools/modelrouter/types.cjs.map +1 -0
  162. package/dist/tools/modelrouter/types.js +1 -0
  163. package/dist/tools/modelrouter/types.js.map +1 -0
  164. package/dist/tools/utils/resilience.cjs +115 -0
  165. package/dist/tools/utils/resilience.cjs.map +1 -0
  166. package/dist/tools/utils/resilience.js +12 -0
  167. package/dist/tools/utils/resilience.js.map +1 -0
  168. package/package.json +159 -0
@@ -0,0 +1,230 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // tools/codebase_search/vercel.ts
21
+ var vercel_exports = {};
22
+ __export(vercel_exports, {
23
+ createCodebaseSearchTool: () => createCodebaseSearchTool,
24
+ default: () => vercel_default,
25
+ getSystemPrompt: () => getSystemPrompt
26
+ });
27
+ module.exports = __toCommonJS(vercel_exports);
28
+ var import_ai = require("ai");
29
+ var import_zod = require("zod");
30
+
31
+ // tools/utils/resilience.ts
32
+ var DEFAULT_RETRY_CONFIG = {
33
+ maxRetries: 3,
34
+ initialDelay: 1e3,
35
+ maxDelay: 3e4,
36
+ backoffMultiplier: 2,
37
+ retryableErrors: ["ECONNREFUSED", "ETIMEDOUT", "ENOTFOUND"]
38
+ };
39
+ async function fetchWithRetry(url, options, retryConfig = {}) {
40
+ const {
41
+ maxRetries = DEFAULT_RETRY_CONFIG.maxRetries,
42
+ initialDelay = DEFAULT_RETRY_CONFIG.initialDelay,
43
+ maxDelay = DEFAULT_RETRY_CONFIG.maxDelay,
44
+ backoffMultiplier = DEFAULT_RETRY_CONFIG.backoffMultiplier,
45
+ retryableErrors = DEFAULT_RETRY_CONFIG.retryableErrors,
46
+ onRetry
47
+ } = retryConfig;
48
+ let lastError = null;
49
+ let delay = initialDelay;
50
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
51
+ try {
52
+ const response = await fetch(url, options);
53
+ if (response.status === 429 || response.status === 503) {
54
+ if (attempt < maxRetries) {
55
+ const retryAfter = response.headers.get("Retry-After");
56
+ const waitTime = retryAfter ? parseInt(retryAfter) * 1e3 : Math.min(delay, maxDelay);
57
+ const error = new Error(`HTTP ${response.status}: Retrying after ${waitTime}ms`);
58
+ if (onRetry) {
59
+ onRetry(attempt + 1, error);
60
+ }
61
+ await sleep(waitTime);
62
+ delay *= backoffMultiplier;
63
+ continue;
64
+ }
65
+ }
66
+ return response;
67
+ } catch (error) {
68
+ lastError = error;
69
+ const isRetryable = retryableErrors.some(
70
+ (errType) => lastError?.message?.includes(errType)
71
+ );
72
+ if (!isRetryable || attempt === maxRetries) {
73
+ throw lastError;
74
+ }
75
+ const waitTime = Math.min(delay, maxDelay);
76
+ if (onRetry) {
77
+ onRetry(attempt + 1, lastError);
78
+ }
79
+ await sleep(waitTime);
80
+ delay *= backoffMultiplier;
81
+ }
82
+ }
83
+ throw lastError || new Error("Max retries exceeded");
84
+ }
85
+ async function withTimeout(promise, timeoutMs, errorMessage) {
86
+ let timeoutId;
87
+ const timeoutPromise = new Promise((_, reject) => {
88
+ timeoutId = setTimeout(() => {
89
+ reject(new Error(errorMessage || `Operation timed out after ${timeoutMs}ms`));
90
+ }, timeoutMs);
91
+ });
92
+ try {
93
+ const result = await Promise.race([promise, timeoutPromise]);
94
+ clearTimeout(timeoutId);
95
+ return result;
96
+ } catch (error) {
97
+ clearTimeout(timeoutId);
98
+ throw error;
99
+ }
100
+ }
101
+ function sleep(ms) {
102
+ return new Promise((resolve) => setTimeout(resolve, ms));
103
+ }
104
+
105
+ // tools/codebase_search/core.ts
106
+ async function executeCodebaseSearch(input, config) {
107
+ const apiKey = config.apiKey || process.env.MORPH_API_KEY;
108
+ if (!apiKey) {
109
+ throw new Error("MORPH_API_KEY not found. Set environment variable or pass in config");
110
+ }
111
+ const searchUrl = config.searchUrl || process.env.MORPH_SEARCH_URL || "http://embedrerank.morphllm.com:8081";
112
+ const timeout = config.timeout || 3e4;
113
+ const debug = config.debug || false;
114
+ if (debug) {
115
+ console.log(`[CodebaseSearch] Query: "${input.query.slice(0, 60)}..." repo=${config.repoId}`);
116
+ console.log(`[CodebaseSearch] URL: ${searchUrl}/v1/codebase_search`);
117
+ }
118
+ const startTime = Date.now();
119
+ try {
120
+ const fetchPromise = fetchWithRetry(
121
+ `${searchUrl}/v1/codebase_search`,
122
+ {
123
+ method: "POST",
124
+ headers: {
125
+ "Content-Type": "application/json",
126
+ "Authorization": `Bearer ${apiKey}`
127
+ },
128
+ body: JSON.stringify({
129
+ query: input.query,
130
+ repoId: config.repoId,
131
+ targetDirectories: input.target_directories || [],
132
+ limit: input.limit || 10,
133
+ candidateLimit: 50
134
+ })
135
+ },
136
+ config.retryConfig
137
+ );
138
+ const response = await withTimeout(fetchPromise, timeout, `Codebase search timed out after ${timeout}ms`);
139
+ if (!response.ok) {
140
+ const errorText = await response.text();
141
+ if (debug) console.error(`[CodebaseSearch] Error: ${response.status} - ${errorText}`);
142
+ return {
143
+ success: false,
144
+ results: [],
145
+ stats: { totalResults: 0, candidatesRetrieved: 0, searchTimeMs: 0 },
146
+ error: `Search failed (${response.status}): ${errorText}`
147
+ };
148
+ }
149
+ const data = await response.json();
150
+ const elapsed = Date.now() - startTime;
151
+ if (debug) {
152
+ console.log(`[CodebaseSearch] \u2705 ${data.results?.length || 0} results in ${elapsed}ms`);
153
+ }
154
+ return {
155
+ success: true,
156
+ results: data.results || [],
157
+ stats: data.stats || { totalResults: 0, candidatesRetrieved: 0, searchTimeMs: elapsed }
158
+ };
159
+ } catch (error) {
160
+ if (debug) console.error(`[CodebaseSearch] Exception: ${error instanceof Error ? error.message : error}`);
161
+ return {
162
+ success: false,
163
+ results: [],
164
+ stats: { totalResults: 0, candidatesRetrieved: 0, searchTimeMs: 0 },
165
+ error: error instanceof Error ? error.message : "Unknown error"
166
+ };
167
+ }
168
+ }
169
+
170
+ // tools/codebase_search/prompts.ts
171
+ var CODEBASE_SEARCH_DESCRIPTION = `Semantic search that finds code by meaning, not exact text.
172
+
173
+ Use this to explore unfamiliar codebases or ask "how/where/what" questions:
174
+ - "How does X work?" - Find implementation details
175
+ - "Where is Y handled?" - Locate specific functionality
176
+ - "What happens when Z?" - Understand flow
177
+
178
+ The tool uses two-stage retrieval (embedding similarity + reranking) to find the most semantically relevant code chunks.
179
+
180
+ Returns code chunks with file paths, line ranges, and full content ranked by relevance.`;
181
+
182
+ // tools/codebase_search/vercel.ts
183
+ function createCodebaseSearchTool(config) {
184
+ const schema = import_zod.z.object({
185
+ query: import_zod.z.string().describe('A complete question about what you want to understand. Ask as if talking to a colleague: "How does X work?", "What happens when Y?", "Where is Z handled?"'),
186
+ target_directories: import_zod.z.array(import_zod.z.string()).describe("Prefix directory paths to limit search scope (single directory only, no glob patterns). Use [] to search entire repo."),
187
+ explanation: import_zod.z.string().describe("One sentence explanation as to why this tool is being used, and how it contributes to the goal."),
188
+ limit: import_zod.z.number().optional().describe("Max results to return (default: 10)")
189
+ });
190
+ return (0, import_ai.tool)({
191
+ description: CODEBASE_SEARCH_DESCRIPTION,
192
+ parameters: schema,
193
+ // @ts-ignore
194
+ execute: async (params) => {
195
+ const { query, target_directories, explanation, limit } = params;
196
+ const result = await executeCodebaseSearch(
197
+ { query, target_directories, explanation, limit },
198
+ config
199
+ );
200
+ if (!result.success) {
201
+ return {
202
+ error: result.error,
203
+ results: []
204
+ };
205
+ }
206
+ return {
207
+ found: result.results.length,
208
+ searchTime: `${result.stats.searchTimeMs}ms`,
209
+ results: result.results.map((r) => ({
210
+ file: r.filepath,
211
+ symbol: r.symbolPath,
212
+ lines: `${r.startLine}-${r.endLine}`,
213
+ language: r.language,
214
+ relevance: `${(r.rerankScore * 100).toFixed(1)}%`,
215
+ code: r.content
216
+ }))
217
+ };
218
+ }
219
+ });
220
+ }
221
+ function getSystemPrompt() {
222
+ return CODEBASE_SEARCH_DESCRIPTION;
223
+ }
224
+ var vercel_default = { createCodebaseSearchTool, getSystemPrompt };
225
+ // Annotate the CommonJS export names for ESM import in node:
226
+ 0 && (module.exports = {
227
+ createCodebaseSearchTool,
228
+ getSystemPrompt
229
+ });
230
+ //# sourceMappingURL=vercel.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../tools/codebase_search/vercel.ts","../../../tools/utils/resilience.ts","../../../tools/codebase_search/core.ts","../../../tools/codebase_search/prompts.ts"],"sourcesContent":["/**\n * Vercel AI SDK adapter for codebase_search tool\n */\n\nimport { tool } from 'ai';\nimport { z } from 'zod';\nimport { executeCodebaseSearch } from './core.js';\nimport { CODEBASE_SEARCH_DESCRIPTION } from './prompts.js';\nimport type { CodebaseSearchConfig } from './types.js';\n\n/**\n * Create Vercel AI SDK codebase_search tool\n * \n * @param config - Configuration with repoId\n * @returns Vercel AI SDK tool definition (execution built-in)\n * \n * @example\n * ```ts\n * import { generateText } from 'ai';\n * import { anthropic } from '@ai-sdk/anthropic';\n * import { createCodebaseSearchTool } from 'morphsdk/tools/codebase-search/vercel';\n * \n * const tool = createCodebaseSearchTool({ repoId: 'my-project' });\n * \n * const result = await generateText({\n * model: anthropic('claude-3-5-sonnet-20241022'),\n * tools: { codebaseSearch: tool },\n * prompt: \"Find authentication code\",\n * maxSteps: 5\n * });\n * \n * // Vercel AI SDK automatically executes and handles results\n * console.log(result.text);\n * ```\n */\nexport function createCodebaseSearchTool(config: CodebaseSearchConfig) {\n const schema = z.object({\n query: z.string().describe('A complete question about what you want to understand. Ask as if talking to a colleague: \"How does X work?\", \"What happens when Y?\", \"Where is Z handled?\"'),\n target_directories: z.array(z.string()).describe('Prefix directory paths to limit search scope (single directory only, no glob patterns). Use [] to search entire repo.'),\n explanation: z.string().describe('One sentence explanation as to why this tool is being used, and how it contributes to the goal.'),\n limit: z.number().optional().describe('Max results to return (default: 10)'),\n });\n\n // @ts-ignore - Vercel AI SDK tool() has execute runtime support but types are incomplete\n return tool({\n description: CODEBASE_SEARCH_DESCRIPTION,\n parameters: schema,\n // @ts-ignore\n execute: async (params) => {\n const { query, target_directories, explanation, limit } = params;\n const result = await executeCodebaseSearch(\n { query, target_directories, explanation, limit },\n config\n );\n\n if (!result.success) {\n return {\n error: result.error,\n results: [],\n };\n }\n\n // Format results for Vercel AI SDK\n return {\n found: result.results.length,\n searchTime: `${result.stats.searchTimeMs}ms`,\n results: result.results.map(r => ({\n file: r.filepath,\n symbol: r.symbolPath,\n lines: `${r.startLine}-${r.endLine}`,\n language: r.language,\n relevance: `${(r.rerankScore * 100).toFixed(1)}%`,\n code: r.content,\n })),\n };\n },\n });\n}\n\n/**\n * Get system prompt for Vercel AI SDK\n */\nexport function getSystemPrompt(): string {\n return CODEBASE_SEARCH_DESCRIPTION;\n}\n\n/**\n * Default export\n */\nexport default { createCodebaseSearchTool, getSystemPrompt };\n\n","/**\n * Resilience utilities for retry logic and timeout handling\n */\n\nexport interface RetryConfig {\n maxRetries?: number; // Default: 3\n initialDelay?: number; // Default: 1000ms\n maxDelay?: number; // Default: 30000ms\n backoffMultiplier?: number; // Default: 2\n retryableErrors?: string[]; // Default: ['ECONNREFUSED', 'ETIMEDOUT', 'ENOTFOUND']\n onRetry?: (attempt: number, error: Error) => void;\n}\n\nconst DEFAULT_RETRY_CONFIG: Required<Omit<RetryConfig, 'onRetry'>> = {\n maxRetries: 3,\n initialDelay: 1000,\n maxDelay: 30000,\n backoffMultiplier: 2,\n retryableErrors: ['ECONNREFUSED', 'ETIMEDOUT', 'ENOTFOUND'],\n};\n\n/**\n * Retry a fetch request with exponential backoff\n * \n * @param url - Request URL\n * @param options - Fetch options\n * @param retryConfig - Retry configuration\n * @returns Response from fetch\n * \n * @example\n * ```typescript\n * const response = await fetchWithRetry(\n * 'https://api.example.com/data',\n * { method: 'POST', body: JSON.stringify(data) },\n * { maxRetries: 5, initialDelay: 500 }\n * );\n * ```\n */\nexport async function fetchWithRetry(\n url: string,\n options: RequestInit,\n retryConfig: RetryConfig = {}\n): Promise<Response> {\n const {\n maxRetries = DEFAULT_RETRY_CONFIG.maxRetries,\n initialDelay = DEFAULT_RETRY_CONFIG.initialDelay,\n maxDelay = DEFAULT_RETRY_CONFIG.maxDelay,\n backoffMultiplier = DEFAULT_RETRY_CONFIG.backoffMultiplier,\n retryableErrors = DEFAULT_RETRY_CONFIG.retryableErrors,\n onRetry,\n } = retryConfig;\n\n let lastError: Error | null = null;\n let delay = initialDelay;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n const response = await fetch(url, options);\n \n // Retry on 429 (rate limit) or 503 (service unavailable)\n if (response.status === 429 || response.status === 503) {\n if (attempt < maxRetries) {\n // Check for Retry-After header\n const retryAfter = response.headers.get('Retry-After');\n const waitTime = retryAfter \n ? parseInt(retryAfter) * 1000 \n : Math.min(delay, maxDelay);\n \n const error = new Error(`HTTP ${response.status}: Retrying after ${waitTime}ms`);\n if (onRetry) {\n onRetry(attempt + 1, error);\n }\n \n await sleep(waitTime);\n delay *= backoffMultiplier;\n continue;\n }\n }\n\n return response;\n } catch (error) {\n lastError = error as Error;\n \n // Check if error is retryable\n const isRetryable = retryableErrors.some(errType => \n lastError?.message?.includes(errType)\n );\n\n if (!isRetryable || attempt === maxRetries) {\n throw lastError;\n }\n\n // Exponential backoff\n const waitTime = Math.min(delay, maxDelay);\n if (onRetry) {\n onRetry(attempt + 1, lastError);\n }\n \n await sleep(waitTime);\n delay *= backoffMultiplier;\n }\n }\n\n throw lastError || new Error('Max retries exceeded');\n}\n\n/**\n * Add timeout to any promise\n * \n * @param promise - Promise to wrap with timeout\n * @param timeoutMs - Timeout in milliseconds\n * @param errorMessage - Optional custom error message\n * @returns Promise that rejects if timeout is reached\n * \n * @example\n * ```typescript\n * const result = await withTimeout(\n * fetchData(),\n * 5000,\n * 'Data fetch timed out'\n * );\n * ```\n */\nexport async function withTimeout<T>(\n promise: Promise<T>,\n timeoutMs: number,\n errorMessage?: string\n): Promise<T> {\n let timeoutId: NodeJS.Timeout | number;\n \n const timeoutPromise = new Promise<never>((_, reject) => {\n timeoutId = setTimeout(() => {\n reject(new Error(errorMessage || `Operation timed out after ${timeoutMs}ms`));\n }, timeoutMs);\n });\n\n try {\n const result = await Promise.race([promise, timeoutPromise]);\n clearTimeout(timeoutId!);\n return result;\n } catch (error) {\n clearTimeout(timeoutId!);\n throw error;\n }\n}\n\n/**\n * Sleep for specified milliseconds\n */\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n\n/**\n * Unified error type for all tools\n */\nexport class MorphError extends Error {\n constructor(\n message: string,\n public code: string,\n public statusCode?: number,\n public retryable: boolean = false\n ) {\n super(message);\n this.name = 'MorphError';\n }\n}\n\n\n","/**\n * Core implementation for codebase search\n * Calls Morph rerank service for two-stage semantic search\n */\n\nimport { fetchWithRetry, withTimeout } from '../utils/resilience.js';\nimport type { CodebaseSearchConfig, CodebaseSearchInput, CodebaseSearchResult } from './types.js';\n\n/**\n * CodebaseSearch client for programmatic semantic search\n */\nexport class CodebaseSearchClient {\n private config: { \n apiKey?: string; \n searchUrl?: string; \n debug?: boolean; \n timeout?: number; \n retryConfig?: any;\n };\n\n constructor(config: { apiKey?: string; debug?: boolean; timeout?: number; retryConfig?: any } = {}) {\n this.config = {\n apiKey: config.apiKey,\n searchUrl: process.env.MORPH_SEARCH_URL || 'http://embedrerank.morphllm.com:8081',\n debug: config.debug,\n timeout: config.timeout || 30000,\n retryConfig: config.retryConfig,\n };\n }\n\n /**\n * Execute a semantic code search\n * \n * @param input - Search parameters including query, repoId, and target directories\n * @param overrides - Optional config overrides for this operation\n * @returns Search results with ranked code matches\n */\n async search(\n input: { query: string; repoId: string; target_directories?: string[]; explanation?: string; limit?: number },\n overrides?: any\n ): Promise<CodebaseSearchResult> {\n return executeCodebaseSearch(\n {\n query: input.query,\n target_directories: input.target_directories,\n explanation: input.explanation,\n limit: input.limit,\n },\n { ...this.config, repoId: input.repoId, ...overrides }\n );\n }\n}\n\n/**\n * Execute semantic code search\n */\nexport async function executeCodebaseSearch(\n input: CodebaseSearchInput,\n config: CodebaseSearchConfig\n): Promise<CodebaseSearchResult> {\n const apiKey = config.apiKey || process.env.MORPH_API_KEY;\n if (!apiKey) {\n throw new Error('MORPH_API_KEY not found. Set environment variable or pass in config');\n }\n\n const searchUrl = config.searchUrl || process.env.MORPH_SEARCH_URL || 'http://embedrerank.morphllm.com:8081';\n const timeout = config.timeout || 30000;\n const debug = config.debug || false;\n\n if (debug) {\n console.log(`[CodebaseSearch] Query: \"${input.query.slice(0, 60)}...\" repo=${config.repoId}`);\n console.log(`[CodebaseSearch] URL: ${searchUrl}/v1/codebase_search`);\n }\n\n const startTime = Date.now();\n\n try {\n const fetchPromise = fetchWithRetry(\n `${searchUrl}/v1/codebase_search`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${apiKey}`,\n },\n body: JSON.stringify({\n query: input.query,\n repoId: config.repoId,\n targetDirectories: input.target_directories || [],\n limit: input.limit || 10,\n candidateLimit: 50,\n }),\n },\n config.retryConfig\n );\n\n const response = await withTimeout(fetchPromise, timeout, `Codebase search timed out after ${timeout}ms`);\n\n if (!response.ok) {\n const errorText = await response.text();\n if (debug) console.error(`[CodebaseSearch] Error: ${response.status} - ${errorText}`);\n return {\n success: false,\n results: [],\n stats: { totalResults: 0, candidatesRetrieved: 0, searchTimeMs: 0 },\n error: `Search failed (${response.status}): ${errorText}`,\n };\n }\n\n const data = await response.json();\n const elapsed = Date.now() - startTime;\n\n if (debug) {\n console.log(`[CodebaseSearch] ✅ ${data.results?.length || 0} results in ${elapsed}ms`);\n }\n\n return {\n success: true,\n results: data.results || [],\n stats: data.stats || { totalResults: 0, candidatesRetrieved: 0, searchTimeMs: elapsed },\n };\n\n } catch (error) {\n if (debug) console.error(`[CodebaseSearch] Exception: ${error instanceof Error ? error.message : error}`);\n return {\n success: false,\n results: [],\n stats: { totalResults: 0, candidatesRetrieved: 0, searchTimeMs: 0 },\n error: error instanceof Error ? error.message : 'Unknown error',\n };\n }\n}\n\n","/**\n * Tool descriptions and system prompts for codebase search\n */\n\nexport const CODEBASE_SEARCH_DESCRIPTION = `Semantic search that finds code by meaning, not exact text.\n\nUse this to explore unfamiliar codebases or ask \"how/where/what\" questions:\n- \"How does X work?\" - Find implementation details\n- \"Where is Y handled?\" - Locate specific functionality\n- \"What happens when Z?\" - Understand flow\n\nThe tool uses two-stage retrieval (embedding similarity + reranking) to find the most semantically relevant code chunks.\n\nReturns code chunks with file paths, line ranges, and full content ranked by relevance.`;\n\nexport const CODEBASE_SEARCH_SYSTEM_PROMPT = `You have access to the codebase_search tool that performs semantic code search.\n\nWhen searching:\n- Use natural language queries describing what you're looking for\n- Be specific about functionality, not variable names\n- Use target_directories to narrow search if you know the area\n- Results are ranked by relevance (rerank score is most important)\n\nThe tool returns:\n- File paths with symbol names (e.g. \"src/auth.ts::AuthService@L1-L17\")\n- Line ranges for precise navigation\n- Full code content for each match\n- Dual relevance scores: embedding similarity + rerank score\n\nUse results to understand code or answer questions. The content is provided in full - avoid re-reading unless you need more context.`;\n\n"],"mappings":"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","names":[]}
@@ -0,0 +1,15 @@
1
+ import {
2
+ createCodebaseSearchTool,
3
+ getSystemPrompt,
4
+ vercel_default
5
+ } from "../../chunk-HGIFACNP.js";
6
+ import "../../chunk-YQMPVJ2L.js";
7
+ import "../../chunk-VJK4PH5V.js";
8
+ import "../../chunk-4VWJFZVS.js";
9
+ import "../../chunk-PZ5AY32C.js";
10
+ export {
11
+ createCodebaseSearchTool,
12
+ vercel_default as default,
13
+ getSystemPrompt
14
+ };
15
+ //# sourceMappingURL=vercel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,335 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // tools/fastapply/anthropic.ts
21
+ var anthropic_exports = {};
22
+ __export(anthropic_exports, {
23
+ createEditFileTool: () => createEditFileTool,
24
+ editFileTool: () => editFileTool
25
+ });
26
+ module.exports = __toCommonJS(anthropic_exports);
27
+
28
+ // tools/fastapply/core.ts
29
+ var import_promises = require("fs/promises");
30
+ var import_path = require("path");
31
+ var import_diff = require("diff");
32
+
33
+ // tools/utils/resilience.ts
34
+ var DEFAULT_RETRY_CONFIG = {
35
+ maxRetries: 3,
36
+ initialDelay: 1e3,
37
+ maxDelay: 3e4,
38
+ backoffMultiplier: 2,
39
+ retryableErrors: ["ECONNREFUSED", "ETIMEDOUT", "ENOTFOUND"]
40
+ };
41
+ async function fetchWithRetry(url, options, retryConfig = {}) {
42
+ const {
43
+ maxRetries = DEFAULT_RETRY_CONFIG.maxRetries,
44
+ initialDelay = DEFAULT_RETRY_CONFIG.initialDelay,
45
+ maxDelay = DEFAULT_RETRY_CONFIG.maxDelay,
46
+ backoffMultiplier = DEFAULT_RETRY_CONFIG.backoffMultiplier,
47
+ retryableErrors = DEFAULT_RETRY_CONFIG.retryableErrors,
48
+ onRetry
49
+ } = retryConfig;
50
+ let lastError = null;
51
+ let delay = initialDelay;
52
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
53
+ try {
54
+ const response = await fetch(url, options);
55
+ if (response.status === 429 || response.status === 503) {
56
+ if (attempt < maxRetries) {
57
+ const retryAfter = response.headers.get("Retry-After");
58
+ const waitTime = retryAfter ? parseInt(retryAfter) * 1e3 : Math.min(delay, maxDelay);
59
+ const error = new Error(`HTTP ${response.status}: Retrying after ${waitTime}ms`);
60
+ if (onRetry) {
61
+ onRetry(attempt + 1, error);
62
+ }
63
+ await sleep(waitTime);
64
+ delay *= backoffMultiplier;
65
+ continue;
66
+ }
67
+ }
68
+ return response;
69
+ } catch (error) {
70
+ lastError = error;
71
+ const isRetryable = retryableErrors.some(
72
+ (errType) => lastError?.message?.includes(errType)
73
+ );
74
+ if (!isRetryable || attempt === maxRetries) {
75
+ throw lastError;
76
+ }
77
+ const waitTime = Math.min(delay, maxDelay);
78
+ if (onRetry) {
79
+ onRetry(attempt + 1, lastError);
80
+ }
81
+ await sleep(waitTime);
82
+ delay *= backoffMultiplier;
83
+ }
84
+ }
85
+ throw lastError || new Error("Max retries exceeded");
86
+ }
87
+ async function withTimeout(promise, timeoutMs, errorMessage) {
88
+ let timeoutId;
89
+ const timeoutPromise = new Promise((_, reject) => {
90
+ timeoutId = setTimeout(() => {
91
+ reject(new Error(errorMessage || `Operation timed out after ${timeoutMs}ms`));
92
+ }, timeoutMs);
93
+ });
94
+ try {
95
+ const result = await Promise.race([promise, timeoutPromise]);
96
+ clearTimeout(timeoutId);
97
+ return result;
98
+ } catch (error) {
99
+ clearTimeout(timeoutId);
100
+ throw error;
101
+ }
102
+ }
103
+ function sleep(ms) {
104
+ return new Promise((resolve2) => setTimeout(resolve2, ms));
105
+ }
106
+
107
+ // tools/fastapply/core.ts
108
+ var DEFAULT_CONFIG = {
109
+ morphApiUrl: "https://api.morphllm.com",
110
+ baseDir: process.cwd(),
111
+ generateUdiff: true,
112
+ autoWrite: true,
113
+ timeout: 3e4,
114
+ debug: false
115
+ };
116
+ function generateUdiff(original, modified, filepath) {
117
+ return (0, import_diff.createTwoFilesPatch)(
118
+ filepath,
119
+ filepath,
120
+ original,
121
+ modified,
122
+ "Original",
123
+ "Modified"
124
+ );
125
+ }
126
+ function countChanges(original, modified) {
127
+ const diff = generateUdiff(original, modified, "file");
128
+ const lines = diff.split("\n");
129
+ let linesAdded = 0;
130
+ let linesRemoved = 0;
131
+ for (const line of lines) {
132
+ if (line.startsWith("+") && !line.startsWith("+++")) {
133
+ linesAdded++;
134
+ } else if (line.startsWith("-") && !line.startsWith("---")) {
135
+ linesRemoved++;
136
+ }
137
+ }
138
+ const linesModified = Math.min(linesAdded, linesRemoved);
139
+ return {
140
+ linesAdded: linesAdded - linesModified,
141
+ linesRemoved: linesRemoved - linesModified,
142
+ linesModified
143
+ };
144
+ }
145
+ async function callMorphAPI(originalCode, codeEdit, instructions, filepath, config) {
146
+ const apiKey = config.morphApiKey || process.env.MORPH_API_KEY;
147
+ const apiUrl = config.morphApiUrl || DEFAULT_CONFIG.morphApiUrl;
148
+ const timeout = config.timeout || DEFAULT_CONFIG.timeout;
149
+ const debug = config.debug || false;
150
+ if (!apiKey) {
151
+ throw new Error(
152
+ "Morph API key not found. Set MORPH_API_KEY environment variable or pass morphApiKey in config."
153
+ );
154
+ }
155
+ const message = `<instruction>${instructions}</instruction>
156
+ <code>${originalCode}</code>
157
+ <update>${codeEdit}</update>`;
158
+ if (debug) {
159
+ console.log(`[FastApply] Calling ${apiUrl}/v1/chat/completions`);
160
+ console.log(`[FastApply] File: ${filepath}, Instructions: ${instructions.slice(0, 60)}...`);
161
+ console.log(`[FastApply] Original: ${originalCode.length} chars, Edit: ${codeEdit.length} chars`);
162
+ }
163
+ const startTime = Date.now();
164
+ const fetchPromise = fetchWithRetry(
165
+ `${apiUrl}/v1/chat/completions`,
166
+ {
167
+ method: "POST",
168
+ headers: {
169
+ "Content-Type": "application/json",
170
+ "Authorization": `Bearer ${apiKey}`
171
+ },
172
+ body: JSON.stringify({
173
+ model: "morph-v3-fast",
174
+ messages: [{ role: "user", content: message }]
175
+ })
176
+ },
177
+ config.retryConfig
178
+ );
179
+ const response = await withTimeout(
180
+ fetchPromise,
181
+ timeout,
182
+ `Morph API request timed out after ${timeout}ms`
183
+ );
184
+ if (!response.ok) {
185
+ const error = await response.text();
186
+ if (debug) console.error(`[FastApply] API error: ${response.status} - ${error}`);
187
+ throw new Error(`Morph API error (${response.status}): ${error}`);
188
+ }
189
+ const data = await response.json();
190
+ const elapsed = Date.now() - startTime;
191
+ if (debug) {
192
+ console.log(`[FastApply] \u2705 Success in ${elapsed}ms, merged: ${data.choices[0].message.content.length} chars`);
193
+ }
194
+ return data.choices[0].message.content;
195
+ }
196
+ async function executeEditFile(input, config = {}) {
197
+ const baseDir = config.baseDir || DEFAULT_CONFIG.baseDir;
198
+ const fullPath = (0, import_path.resolve)((0, import_path.join)(baseDir, input.target_filepath));
199
+ const debug = config.debug || false;
200
+ const relativePath = (0, import_path.relative)(baseDir, fullPath);
201
+ if (relativePath.startsWith("..") || fullPath === baseDir) {
202
+ return {
203
+ success: false,
204
+ filepath: input.target_filepath,
205
+ changes: { linesAdded: 0, linesRemoved: 0, linesModified: 0 },
206
+ error: `Invalid filepath: '${input.target_filepath}' is outside baseDir`
207
+ };
208
+ }
209
+ try {
210
+ if (debug) console.log(`[FastApply] Reading file: ${input.target_filepath}`);
211
+ const originalCode = await (0, import_promises.readFile)(fullPath, "utf-8");
212
+ const mergedCode = await callMorphAPI(originalCode, input.code_edit, input.instructions, input.target_filepath, config);
213
+ const udiff = config.generateUdiff !== false ? generateUdiff(originalCode, mergedCode, input.target_filepath) : void 0;
214
+ if (config.autoWrite !== false) {
215
+ await (0, import_promises.writeFile)(fullPath, mergedCode, "utf-8");
216
+ if (debug) console.log(`[FastApply] Wrote ${mergedCode.length} chars to ${input.target_filepath}`);
217
+ }
218
+ const changes = countChanges(originalCode, mergedCode);
219
+ return {
220
+ success: true,
221
+ filepath: input.target_filepath,
222
+ udiff,
223
+ changes
224
+ };
225
+ } catch (error) {
226
+ const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
227
+ if (debug) console.error(`[FastApply] Error: ${errorMessage}`);
228
+ return {
229
+ success: false,
230
+ filepath: input.target_filepath,
231
+ changes: { linesAdded: 0, linesRemoved: 0, linesModified: 0 },
232
+ error: errorMessage
233
+ };
234
+ }
235
+ }
236
+
237
+ // tools/fastapply/prompts.ts
238
+ var EDIT_FILE_TOOL_DESCRIPTION = `Use this tool to make an edit to an existing file.
239
+
240
+ This will be read by a less intelligent model, which will quickly apply the edit. You should make it clear what the edit is, while also minimizing the unchanged code you write.
241
+
242
+ When writing the edit, you should specify each edit in sequence, with the special comment // ... existing code ... to represent unchanged code in between edited lines.
243
+
244
+ For example:
245
+
246
+ // ... existing code ...
247
+ FIRST_EDIT
248
+ // ... existing code ...
249
+ SECOND_EDIT
250
+ // ... existing code ...
251
+ THIRD_EDIT
252
+ // ... existing code ...
253
+
254
+ You should still bias towards repeating as few lines of the original file as possible to convey the change.
255
+ But, each edit should contain minimally sufficient context of unchanged lines around the code you're editing to resolve ambiguity.
256
+
257
+ DO NOT omit spans of pre-existing code (or comments) without using the // ... existing code ... comment to indicate its absence. If you omit the existing code comment, the model may inadvertently delete these lines.
258
+
259
+ If you plan on deleting a section, you must provide context before and after to delete it.
260
+
261
+ Make sure it is clear what the edit should be, and where it should be applied.
262
+ Make edits to a file in a single edit_file call instead of multiple edit_file calls to the same file. The apply model can handle many distinct edits at once.`;
263
+ var EDIT_FILE_SYSTEM_PROMPT = `When the user is asking for edits to their code, use the edit_file tool to highlight the changes necessary and add comments to indicate where unchanged code has been skipped. For example:
264
+
265
+ // ... existing code ...
266
+ {{ edit_1 }}
267
+ // ... existing code ...
268
+ {{ edit_2 }}
269
+ // ... existing code ...
270
+
271
+ Often this will mean that the start/end of the file will be skipped, but that's okay! Rewrite the entire file ONLY if specifically requested. Always provide a brief explanation of the updates, unless the user specifically requests only the code.
272
+
273
+ These edit codeblocks are also read by a less intelligent language model, colloquially called the apply model, to update the file. To help specify the edit to the apply model, you will be very careful when generating the codeblock to not introduce ambiguity. You will specify all unchanged regions (code and comments) of the file with "// ... existing code ..." comment markers. This will ensure the apply model will not delete existing unchanged code or comments when editing the file.`;
274
+
275
+ // tools/fastapply/anthropic.ts
276
+ var editFileTool = {
277
+ name: "edit_file",
278
+ description: EDIT_FILE_TOOL_DESCRIPTION,
279
+ input_schema: {
280
+ type: "object",
281
+ properties: {
282
+ target_filepath: {
283
+ type: "string",
284
+ description: "The path of the target file to modify"
285
+ },
286
+ instructions: {
287
+ type: "string",
288
+ description: "A single sentence describing what you are changing (first person)"
289
+ },
290
+ code_edit: {
291
+ type: "string",
292
+ description: "The lazy edit with // ... existing code ... markers"
293
+ }
294
+ },
295
+ required: ["target_filepath", "instructions", "code_edit"]
296
+ }
297
+ };
298
+ function formatResult(result) {
299
+ if (!result.success) {
300
+ return `Error editing file: ${result.error}`;
301
+ }
302
+ const { changes } = result;
303
+ const summary = [
304
+ changes.linesAdded && `+${changes.linesAdded} lines`,
305
+ changes.linesRemoved && `-${changes.linesRemoved} lines`,
306
+ changes.linesModified && `~${changes.linesModified} lines modified`
307
+ ].filter(Boolean).join(", ");
308
+ if (result.udiff) {
309
+ return `Successfully applied changes to ${result.filepath}:
310
+
311
+ ${result.udiff}
312
+
313
+ Summary: ${summary}`;
314
+ }
315
+ return `Successfully applied changes to ${result.filepath}. ${summary}`;
316
+ }
317
+ function createEditFileTool(config = {}) {
318
+ return Object.assign({}, editFileTool, {
319
+ execute: async (input) => {
320
+ return executeEditFile(input, config);
321
+ },
322
+ formatResult: (result) => {
323
+ return formatResult(result);
324
+ },
325
+ getSystemPrompt: () => {
326
+ return EDIT_FILE_SYSTEM_PROMPT;
327
+ }
328
+ });
329
+ }
330
+ // Annotate the CommonJS export names for ESM import in node:
331
+ 0 && (module.exports = {
332
+ createEditFileTool,
333
+ editFileTool
334
+ });
335
+ //# sourceMappingURL=anthropic.cjs.map