@morphllm/morphsdk 0.2.112 → 0.2.114
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.
- package/dist/{chunk-EQHP36A2.js → chunk-3U7AWFBN.js} +5 -5
- package/dist/{chunk-2MAUPERG.js → chunk-FXBT4UDY.js} +19 -34
- package/dist/chunk-FXBT4UDY.js.map +1 -0
- package/dist/{chunk-HDRLLCAD.js → chunk-HMAX2FEE.js} +2 -2
- package/dist/{chunk-TLC3QKE6.js → chunk-M5DR2WOZ.js} +4 -3
- package/dist/{chunk-TLC3QKE6.js.map → chunk-M5DR2WOZ.js.map} +1 -1
- package/dist/{chunk-I3IN742Q.js → chunk-UNHHRMU7.js} +2 -2
- package/dist/{chunk-KQP6ZPYB.js → chunk-Y5BB7JFH.js} +2 -2
- package/dist/client.cjs +99 -123
- package/dist/client.cjs.map +1 -1
- package/dist/client.js +6 -6
- package/dist/edge.cjs +102 -104
- package/dist/edge.cjs.map +1 -1
- package/dist/edge.js +1 -1
- package/dist/index.cjs +99 -123
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +6 -6
- package/dist/tools/fastapply/anthropic.cjs +22 -112
- package/dist/tools/fastapply/anthropic.cjs.map +1 -1
- package/dist/tools/fastapply/anthropic.js +3 -4
- package/dist/tools/fastapply/apply.cjs +28 -104
- package/dist/tools/fastapply/apply.cjs.map +1 -1
- package/dist/tools/fastapply/apply.d.ts +7 -3
- package/dist/tools/fastapply/apply.js +1 -2
- package/dist/tools/fastapply/core.cjs +22 -112
- package/dist/tools/fastapply/core.cjs.map +1 -1
- package/dist/tools/fastapply/core.js +2 -3
- package/dist/tools/fastapply/index.cjs +22 -112
- package/dist/tools/fastapply/index.cjs.map +1 -1
- package/dist/tools/fastapply/index.js +5 -6
- package/dist/tools/fastapply/openai.cjs +22 -112
- package/dist/tools/fastapply/openai.cjs.map +1 -1
- package/dist/tools/fastapply/openai.js +3 -4
- package/dist/tools/fastapply/types.cjs.map +1 -1
- package/dist/tools/fastapply/types.d.ts +5 -0
- package/dist/tools/fastapply/vercel.cjs +22 -112
- package/dist/tools/fastapply/vercel.cjs.map +1 -1
- package/dist/tools/fastapply/vercel.js +3 -4
- package/dist/tools/index.cjs +22 -112
- package/dist/tools/index.cjs.map +1 -1
- package/dist/tools/index.js +5 -6
- package/package.json +1 -1
- package/dist/chunk-2MAUPERG.js.map +0 -1
- /package/dist/{chunk-EQHP36A2.js.map → chunk-3U7AWFBN.js.map} +0 -0
- /package/dist/{chunk-HDRLLCAD.js.map → chunk-HMAX2FEE.js.map} +0 -0
- /package/dist/{chunk-I3IN742Q.js.map → chunk-UNHHRMU7.js.map} +0 -0
- /package/dist/{chunk-KQP6ZPYB.js.map → chunk-Y5BB7JFH.js.map} +0 -0
|
@@ -24,16 +24,16 @@ import {
|
|
|
24
24
|
} from "./chunk-WM77HRKO.js";
|
|
25
25
|
import {
|
|
26
26
|
createEditFileTool as createEditFileTool3
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-HMAX2FEE.js";
|
|
28
28
|
import {
|
|
29
29
|
createEditFileTool as createEditFileTool2
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-Y5BB7JFH.js";
|
|
31
31
|
import {
|
|
32
32
|
createEditFileTool
|
|
33
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-UNHHRMU7.js";
|
|
34
34
|
import {
|
|
35
35
|
FastApplyClient
|
|
36
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-M5DR2WOZ.js";
|
|
37
37
|
import {
|
|
38
38
|
BrowserClient
|
|
39
39
|
} from "./chunk-4IOC2D5Y.js";
|
|
@@ -643,4 +643,4 @@ export {
|
|
|
643
643
|
VercelToolFactory,
|
|
644
644
|
MorphClient
|
|
645
645
|
};
|
|
646
|
-
//# sourceMappingURL=chunk-
|
|
646
|
+
//# sourceMappingURL=chunk-3U7AWFBN.js.map
|
|
@@ -1,10 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
fetchWithRetry,
|
|
3
|
-
withTimeout
|
|
4
|
-
} from "./chunk-4VWJFZVS.js";
|
|
5
|
-
|
|
6
1
|
// tools/fastapply/apply.ts
|
|
7
2
|
import { createTwoFilesPatch } from "diff";
|
|
3
|
+
import OpenAI from "openai";
|
|
8
4
|
var DEFAULT_API_URL = "https://api.morphllm.com";
|
|
9
5
|
var DEFAULT_TIMEOUT = 3e4;
|
|
10
6
|
function generateUdiff(original, modified, filepath) {
|
|
@@ -55,37 +51,25 @@ async function callMorphAPI(originalCode, codeEdit, instructions, filepath, conf
|
|
|
55
51
|
console.log(`[FastApply] Original: ${originalCode.length} chars, Edit: ${codeEdit.length} chars`);
|
|
56
52
|
}
|
|
57
53
|
const startTime = Date.now();
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
{
|
|
61
|
-
method: "POST",
|
|
62
|
-
headers: {
|
|
63
|
-
"Content-Type": "application/json",
|
|
64
|
-
"Authorization": `Bearer ${apiKey}`
|
|
65
|
-
},
|
|
66
|
-
body: JSON.stringify({
|
|
67
|
-
model: "morph-v3-fast",
|
|
68
|
-
messages: [{ role: "user", content: message }]
|
|
69
|
-
})
|
|
70
|
-
},
|
|
71
|
-
config.retryConfig
|
|
72
|
-
);
|
|
73
|
-
const response = await withTimeout(
|
|
74
|
-
fetchPromise,
|
|
54
|
+
const client = new OpenAI({
|
|
55
|
+
apiKey,
|
|
56
|
+
baseURL: `${apiUrl}/v1`,
|
|
75
57
|
timeout,
|
|
76
|
-
|
|
77
|
-
);
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
58
|
+
maxRetries: config.retryConfig?.maxRetries ?? 3
|
|
59
|
+
});
|
|
60
|
+
const completion = await client.chat.completions.create({
|
|
61
|
+
model: "morph-v3-fast",
|
|
62
|
+
messages: [{ role: "user", content: message }]
|
|
63
|
+
});
|
|
64
|
+
const content = completion.choices[0]?.message?.content;
|
|
65
|
+
if (!content) {
|
|
66
|
+
throw new Error("Morph API returned empty response");
|
|
82
67
|
}
|
|
83
|
-
const data = await response.json();
|
|
84
68
|
const elapsed = Date.now() - startTime;
|
|
85
69
|
if (debug) {
|
|
86
|
-
console.log(`[FastApply]
|
|
70
|
+
console.log(`[FastApply] Success in ${elapsed}ms, merged: ${content.length} chars`);
|
|
87
71
|
}
|
|
88
|
-
return
|
|
72
|
+
return { content, completionId: completion.id };
|
|
89
73
|
}
|
|
90
74
|
async function applyEdit(input, config = {}) {
|
|
91
75
|
const debug = config.debug || false;
|
|
@@ -94,7 +78,7 @@ async function applyEdit(input, config = {}) {
|
|
|
94
78
|
if (debug) {
|
|
95
79
|
console.log(`[FastApply] Applying edit to code (${input.originalCode.length} chars)`);
|
|
96
80
|
}
|
|
97
|
-
const mergedCode = await callMorphAPI(
|
|
81
|
+
const { content: mergedCode, completionId } = await callMorphAPI(
|
|
98
82
|
input.originalCode,
|
|
99
83
|
input.codeEdit,
|
|
100
84
|
input.instructions,
|
|
@@ -107,7 +91,8 @@ async function applyEdit(input, config = {}) {
|
|
|
107
91
|
success: true,
|
|
108
92
|
mergedCode,
|
|
109
93
|
udiff,
|
|
110
|
-
changes
|
|
94
|
+
changes,
|
|
95
|
+
completionId
|
|
111
96
|
};
|
|
112
97
|
} catch (error) {
|
|
113
98
|
const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
|
|
@@ -126,4 +111,4 @@ export {
|
|
|
126
111
|
callMorphAPI,
|
|
127
112
|
applyEdit
|
|
128
113
|
};
|
|
129
|
-
//# sourceMappingURL=chunk-
|
|
114
|
+
//# sourceMappingURL=chunk-FXBT4UDY.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../tools/fastapply/apply.ts"],"sourcesContent":["/**\n * Edge-compatible code application API\n *\n * This module works on:\n * - Node.js\n * - Cloudflare Workers\n * - Vercel Edge Functions\n * - Deno Deploy\n * - Browser environments\n *\n * For file-based operations, use executeEditFile from core.ts\n */\n\nimport { createTwoFilesPatch } from 'diff';\nimport OpenAI from 'openai';\nimport type {\n EditChanges,\n ApplyEditInput,\n ApplyEditResult,\n ApplyEditConfig,\n} from './types.js';\n\nconst DEFAULT_API_URL = 'https://api.morphllm.com';\nconst DEFAULT_TIMEOUT = 30000;\n\n/**\n * Generate a unified diff between two strings\n */\nexport function generateUdiff(\n original: string,\n modified: string,\n filepath: string\n): string {\n return createTwoFilesPatch(\n filepath,\n filepath,\n original,\n modified,\n 'Original',\n 'Modified'\n );\n}\n\n/**\n * Count changes from a unified diff\n */\nexport function countChanges(original: string, modified: string): EditChanges {\n const diff = generateUdiff(original, modified, 'file');\n const lines = diff.split('\\n');\n\n let linesAdded = 0;\n let linesRemoved = 0;\n\n for (const line of lines) {\n if (line.startsWith('+') && !line.startsWith('+++')) {\n linesAdded++;\n } else if (line.startsWith('-') && !line.startsWith('---')) {\n linesRemoved++;\n }\n }\n\n const linesModified = Math.min(linesAdded, linesRemoved);\n\n return {\n linesAdded: linesAdded - linesModified,\n linesRemoved: linesRemoved - linesModified,\n linesModified,\n };\n}\n\n/**\n * Call Morph Apply API to merge code edits\n * Uses OpenAI SDK for reliable connection handling, retries, and timeouts\n */\nexport async function callMorphAPI(\n originalCode: string,\n codeEdit: string,\n instructions: string,\n filepath: string,\n config: ApplyEditConfig\n): Promise<{ content: string; completionId?: string }> {\n const apiKey = config.morphApiKey || (typeof process !== 'undefined' ? process.env?.MORPH_API_KEY : undefined);\n const apiUrl = config.morphApiUrl || DEFAULT_API_URL;\n const timeout = config.timeout || DEFAULT_TIMEOUT;\n const debug = config.debug || false;\n\n if (!apiKey) {\n throw new Error(\n 'Morph API key not found. Set MORPH_API_KEY environment variable or pass morphApiKey in config.'\n );\n }\n\n // Format message with XML tags as per Morph Fast Apply spec\n const message = `<instruction>${instructions}</instruction>\\n<code>${originalCode}</code>\\n<update>${codeEdit}</update>`;\n\n if (debug) {\n console.log(`[FastApply] Calling ${apiUrl}/v1/chat/completions`);\n console.log(`[FastApply] File: ${filepath}, Instructions: ${instructions.slice(0, 60)}...`);\n console.log(`[FastApply] Original: ${originalCode.length} chars, Edit: ${codeEdit.length} chars`);\n }\n\n const startTime = Date.now();\n\n const client = new OpenAI({\n apiKey,\n baseURL: `${apiUrl}/v1`,\n timeout,\n maxRetries: config.retryConfig?.maxRetries ?? 3,\n });\n\n const completion = await client.chat.completions.create({\n model: 'morph-v3-fast',\n messages: [{ role: 'user', content: message }],\n });\n\n const content = completion.choices[0]?.message?.content;\n if (!content) {\n throw new Error('Morph API returned empty response');\n }\n\n const elapsed = Date.now() - startTime;\n\n if (debug) {\n console.log(`[FastApply] Success in ${elapsed}ms, merged: ${content.length} chars`);\n }\n\n return { content, completionId: completion.id };\n}\n\n/**\n * Apply an edit to code directly without file I/O\n *\n * This is the edge-compatible code-in/code-out API that accepts code content directly\n * and returns the merged result without reading or writing any files.\n *\n * Works on Cloudflare Workers, Vercel Edge Functions, Deno, and browsers.\n *\n * @param input - Code and edit parameters\n * @param config - Optional configuration\n * @returns Result with merged code\n *\n * @example\n * ```typescript\n * import { applyEdit } from '@morphllm/morphsdk';\n *\n * const result = await applyEdit({\n * originalCode: fs.readFileSync('file.ts', 'utf-8'),\n * codeEdit: '// ... existing code ...\\nconst newVar = 42;\\n// ... existing code ...',\n * instructions: 'Add a new variable',\n * filepath: 'file.ts' // optional, for udiff context\n * });\n *\n * if (result.success) {\n * fs.writeFileSync('file.ts', result.mergedCode);\n * }\n * ```\n */\nexport async function applyEdit(\n input: ApplyEditInput,\n config: ApplyEditConfig = {}\n): Promise<ApplyEditResult> {\n const debug = config.debug || false;\n const filepath = input.filepath || 'file';\n\n try {\n if (debug) {\n console.log(`[FastApply] Applying edit to code (${input.originalCode.length} chars)`);\n }\n\n const { content: mergedCode, completionId } = await callMorphAPI(\n input.originalCode,\n input.codeEdit,\n input.instructions,\n filepath,\n config\n );\n\n const udiff = config.generateUdiff !== false\n ? generateUdiff(input.originalCode, mergedCode, filepath)\n : undefined;\n\n const changes = countChanges(input.originalCode, mergedCode);\n\n return {\n success: true,\n mergedCode,\n udiff,\n changes,\n completionId,\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';\n if (debug) console.error(`[FastApply] Error: ${errorMessage}`);\n\n return {\n success: false,\n changes: { linesAdded: 0, linesRemoved: 0, linesModified: 0 },\n error: errorMessage,\n };\n }\n}\n"],"mappings":";AAaA,SAAS,2BAA2B;AACpC,OAAO,YAAY;AAQnB,IAAM,kBAAkB;AACxB,IAAM,kBAAkB;AAKjB,SAAS,cACd,UACA,UACA,UACQ;AACR,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAKO,SAAS,aAAa,UAAkB,UAA+B;AAC5E,QAAM,OAAO,cAAc,UAAU,UAAU,MAAM;AACrD,QAAM,QAAQ,KAAK,MAAM,IAAI;AAE7B,MAAI,aAAa;AACjB,MAAI,eAAe;AAEnB,aAAW,QAAQ,OAAO;AACxB,QAAI,KAAK,WAAW,GAAG,KAAK,CAAC,KAAK,WAAW,KAAK,GAAG;AACnD;AAAA,IACF,WAAW,KAAK,WAAW,GAAG,KAAK,CAAC,KAAK,WAAW,KAAK,GAAG;AAC1D;AAAA,IACF;AAAA,EACF;AAEA,QAAM,gBAAgB,KAAK,IAAI,YAAY,YAAY;AAEvD,SAAO;AAAA,IACL,YAAY,aAAa;AAAA,IACzB,cAAc,eAAe;AAAA,IAC7B;AAAA,EACF;AACF;AAMA,eAAsB,aACpB,cACA,UACA,cACA,UACA,QACqD;AACrD,QAAM,SAAS,OAAO,gBAAgB,OAAO,YAAY,cAAc,QAAQ,KAAK,gBAAgB;AACpG,QAAM,SAAS,OAAO,eAAe;AACrC,QAAM,UAAU,OAAO,WAAW;AAClC,QAAM,QAAQ,OAAO,SAAS;AAE9B,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAGA,QAAM,UAAU,gBAAgB,YAAY;AAAA,QAAyB,YAAY;AAAA,UAAoB,QAAQ;AAE7G,MAAI,OAAO;AACT,YAAQ,IAAI,uBAAuB,MAAM,sBAAsB;AAC/D,YAAQ,IAAI,qBAAqB,QAAQ,mBAAmB,aAAa,MAAM,GAAG,EAAE,CAAC,KAAK;AAC1F,YAAQ,IAAI,yBAAyB,aAAa,MAAM,iBAAiB,SAAS,MAAM,QAAQ;AAAA,EAClG;AAEA,QAAM,YAAY,KAAK,IAAI;AAE3B,QAAM,SAAS,IAAI,OAAO;AAAA,IACxB;AAAA,IACA,SAAS,GAAG,MAAM;AAAA,IAClB;AAAA,IACA,YAAY,OAAO,aAAa,cAAc;AAAA,EAChD,CAAC;AAED,QAAM,aAAa,MAAM,OAAO,KAAK,YAAY,OAAO;AAAA,IACtD,OAAO;AAAA,IACP,UAAU,CAAC,EAAE,MAAM,QAAQ,SAAS,QAAQ,CAAC;AAAA,EAC/C,CAAC;AAED,QAAM,UAAU,WAAW,QAAQ,CAAC,GAAG,SAAS;AAChD,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,MAAM,mCAAmC;AAAA,EACrD;AAEA,QAAM,UAAU,KAAK,IAAI,IAAI;AAE7B,MAAI,OAAO;AACT,YAAQ,IAAI,0BAA0B,OAAO,eAAe,QAAQ,MAAM,QAAQ;AAAA,EACpF;AAEA,SAAO,EAAE,SAAS,cAAc,WAAW,GAAG;AAChD;AA8BA,eAAsB,UACpB,OACA,SAA0B,CAAC,GACD;AAC1B,QAAM,QAAQ,OAAO,SAAS;AAC9B,QAAM,WAAW,MAAM,YAAY;AAEnC,MAAI;AACF,QAAI,OAAO;AACT,cAAQ,IAAI,sCAAsC,MAAM,aAAa,MAAM,SAAS;AAAA,IACtF;AAEA,UAAM,EAAE,SAAS,YAAY,aAAa,IAAI,MAAM;AAAA,MAClD,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,MACN;AAAA,MACA;AAAA,IACF;AAEA,UAAM,QAAQ,OAAO,kBAAkB,QACnC,cAAc,MAAM,cAAc,YAAY,QAAQ,IACtD;AAEJ,UAAM,UAAU,aAAa,MAAM,cAAc,UAAU;AAE3D,WAAO;AAAA,MACL,SAAS;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF,SAAS,OAAO;AACd,UAAM,eAAe,iBAAiB,QAAQ,MAAM,UAAU;AAC9D,QAAI,MAAO,SAAQ,MAAM,sBAAsB,YAAY,EAAE;AAE7D,WAAO;AAAA,MACL,SAAS;AAAA,MACT,SAAS,EAAE,YAAY,GAAG,cAAc,GAAG,eAAe,EAAE;AAAA,MAC5D,OAAO;AAAA,IACT;AAAA,EACF;AACF;","names":[]}
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
} from "./chunk-63WE2C5R.js";
|
|
5
5
|
import {
|
|
6
6
|
executeEditFile
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-M5DR2WOZ.js";
|
|
8
8
|
import {
|
|
9
9
|
__export
|
|
10
10
|
} from "./chunk-PZ5AY32C.js";
|
|
@@ -86,4 +86,4 @@ export {
|
|
|
86
86
|
vercel_default,
|
|
87
87
|
vercel_exports
|
|
88
88
|
};
|
|
89
|
-
//# sourceMappingURL=chunk-
|
|
89
|
+
//# sourceMappingURL=chunk-HMAX2FEE.js.map
|
|
@@ -82,7 +82,7 @@ async function executeEditFile(input, config = {}) {
|
|
|
82
82
|
}
|
|
83
83
|
if (debug) console.log(`[FastApply] File doesn't exist, will create new file`);
|
|
84
84
|
}
|
|
85
|
-
const mergedCode = await callMorphAPI2(originalCode, input.code_edit, input.instructions, input.target_filepath, config);
|
|
85
|
+
const { content: mergedCode, completionId } = await callMorphAPI2(originalCode, input.code_edit, input.instructions, input.target_filepath, config);
|
|
86
86
|
const udiff = config.generateUdiff !== false ? generateUdiff2(originalCode, mergedCode, input.target_filepath) : void 0;
|
|
87
87
|
if (config.autoWrite !== false) {
|
|
88
88
|
await writeFile(fullPath, mergedCode, "utf-8");
|
|
@@ -93,7 +93,8 @@ async function executeEditFile(input, config = {}) {
|
|
|
93
93
|
success: true,
|
|
94
94
|
filepath: input.target_filepath,
|
|
95
95
|
udiff,
|
|
96
|
-
changes
|
|
96
|
+
changes,
|
|
97
|
+
completionId
|
|
97
98
|
};
|
|
98
99
|
} catch (error) {
|
|
99
100
|
const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
|
|
@@ -111,4 +112,4 @@ export {
|
|
|
111
112
|
FastApplyClient,
|
|
112
113
|
executeEditFile
|
|
113
114
|
};
|
|
114
|
-
//# sourceMappingURL=chunk-
|
|
115
|
+
//# sourceMappingURL=chunk-M5DR2WOZ.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../tools/fastapply/core.ts"],"sourcesContent":["/**\n * Core implementation of Morph Fast Apply\n *\n * This module provides file-based operations that require Node.js.\n * For edge-compatible code-in/code-out operations, use applyEdit from ./apply.ts\n */\n\nimport { join, resolve, relative } from 'path';\nimport type {\n EditFileInput,\n EditFileResult,\n EditFileConfig,\n} from './types.js';\n\n// Re-export edge-compatible functions\nexport { applyEdit, generateUdiff, countChanges, callMorphAPI } from './apply.js';\n\nconst DEFAULT_CONFIG: Required<Omit<EditFileConfig, 'morphApiKey' | 'systemPrompt' | 'retryConfig' | 'description'>> = {\n morphApiUrl: 'https://api.morphllm.com',\n baseDir: process.cwd(),\n generateUdiff: true,\n autoWrite: true,\n timeout: 30000,\n debug: false,\n};\n\n/**\n * FastApply client for programmatic file editing\n * Note: This client requires Node.js for file operations\n */\nexport class FastApplyClient {\n private config: EditFileConfig;\n\n constructor(config: { apiKey?: string; debug?: boolean; timeout?: number; retryConfig?: any } = {}) {\n this.config = {\n morphApiKey: config.apiKey,\n morphApiUrl: DEFAULT_CONFIG.morphApiUrl,\n debug: config.debug,\n timeout: config.timeout || DEFAULT_CONFIG.timeout,\n retryConfig: config.retryConfig,\n generateUdiff: DEFAULT_CONFIG.generateUdiff,\n autoWrite: DEFAULT_CONFIG.autoWrite,\n };\n }\n\n /**\n * Execute a file edit operation\n *\n * @param input - Edit parameters including filepath, instructions, and code_edit\n * @param overrides - Optional config overrides for this operation\n * @returns Edit result with success status and changes\n */\n async execute(input: EditFileInput, overrides?: Partial<EditFileConfig>): Promise<EditFileResult> {\n return executeEditFile(input, { ...this.config, ...overrides });\n }\n\n /**\n * Apply an edit to code directly without file I/O\n *\n * Useful for sandbox environments or when you manage your own file system.\n * Compatible with the earlier OpenAI client API contract.\n *\n * @param input - Code and edit parameters\n * @param overrides - Optional config overrides for this operation\n * @returns Result with merged code\n *\n * @example\n * ```typescript\n * const result = await client.applyEdit({\n * originalCode: 'function hello() { return \"world\"; }',\n * codeEdit: 'function hello() { return \"universe\"; }',\n * instructions: 'Change return value'\n * });\n * console.log(result.mergedCode);\n * ```\n */\n async applyEdit(input: import('./types.js').ApplyEditInput, overrides?: Partial<import('./types.js').ApplyEditConfig>): Promise<import('./types.js').ApplyEditResult> {\n const { applyEdit } = await import('./apply.js');\n return applyEdit(input, { ...this.config, ...overrides });\n }\n}\n\n/**\n * Execute a file edit using Morph Fast Apply\n * Note: This function requires Node.js for file I/O\n */\nexport async function executeEditFile(\n input: EditFileInput,\n config: EditFileConfig = {}\n): Promise<EditFileResult> {\n const baseDir = config.baseDir || DEFAULT_CONFIG.baseDir;\n const fullPath = resolve(join(baseDir, input.target_filepath));\n const debug = config.debug || false;\n\n // Security: ensure file is within baseDir\n const relativePath = relative(baseDir, fullPath);\n if (relativePath.startsWith('..') || fullPath === baseDir) {\n return {\n success: false,\n filepath: input.target_filepath,\n changes: { linesAdded: 0, linesRemoved: 0, linesModified: 0 },\n error: `Invalid filepath: '${input.target_filepath}' is outside baseDir`,\n };\n }\n\n try {\n if (debug) console.log(`[FastApply] Reading file: ${input.target_filepath}`);\n\n // Dynamic import to avoid loading Node.js fs module at module evaluation time\n const { readFile, writeFile } = await import('fs/promises');\n const { callMorphAPI, generateUdiff, countChanges } = await import('./apply.js');\n\n // Handle both existing and non-existent files\n let originalCode = '';\n try {\n originalCode = await readFile(fullPath, 'utf-8');\n } catch (error: any) {\n if (error.code !== 'ENOENT') {\n throw error; // Re-throw if it's not a \"file not found\" error\n }\n // File doesn't exist, proceed with empty content (will create new file)\n if (debug) console.log(`[FastApply] File doesn't exist, will create new file`);\n }\n\n const mergedCode = await callMorphAPI(originalCode, input.code_edit, input.instructions, input.target_filepath, config);\n\n const udiff = config.generateUdiff !== false ? generateUdiff(originalCode, mergedCode, input.target_filepath) : undefined;\n\n if (config.autoWrite !== false) {\n await writeFile(fullPath, mergedCode, 'utf-8');\n if (debug) console.log(`[FastApply] Wrote ${mergedCode.length} chars to ${input.target_filepath}`);\n }\n\n const changes = countChanges(originalCode, mergedCode);\n\n return {\n success: true,\n filepath: input.target_filepath,\n udiff,\n changes,\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';\n if (debug) console.error(`[FastApply] Error: ${errorMessage}`);\n\n return {\n success: false,\n filepath: input.target_filepath,\n changes: { linesAdded: 0, linesRemoved: 0, linesModified: 0 },\n error: errorMessage,\n };\n }\n}\n"],"mappings":";AAOA,SAAS,MAAM,SAAS,gBAAgB;AAUxC,IAAM,iBAAiH;AAAA,EACrH,aAAa;AAAA,EACb,SAAS,QAAQ,IAAI;AAAA,EACrB,eAAe;AAAA,EACf,WAAW;AAAA,EACX,SAAS;AAAA,EACT,OAAO;AACT;AAMO,IAAM,kBAAN,MAAsB;AAAA,EACnB;AAAA,EAER,YAAY,SAAoF,CAAC,GAAG;AAClG,SAAK,SAAS;AAAA,MACZ,aAAa,OAAO;AAAA,MACpB,aAAa,eAAe;AAAA,MAC5B,OAAO,OAAO;AAAA,MACd,SAAS,OAAO,WAAW,eAAe;AAAA,MAC1C,aAAa,OAAO;AAAA,MACpB,eAAe,eAAe;AAAA,MAC9B,WAAW,eAAe;AAAA,IAC5B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,QAAQ,OAAsB,WAA8D;AAChG,WAAO,gBAAgB,OAAO,EAAE,GAAG,KAAK,QAAQ,GAAG,UAAU,CAAC;AAAA,EAChE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsBA,MAAM,UAAU,OAA4C,WAA0G;AACpK,UAAM,EAAE,WAAAA,WAAU,IAAI,MAAM,OAAO,4BAAY;AAC/C,WAAOA,WAAU,OAAO,EAAE,GAAG,KAAK,QAAQ,GAAG,UAAU,CAAC;AAAA,EAC1D;AACF;AAMA,eAAsB,gBACpB,OACA,SAAyB,CAAC,GACD;AACzB,QAAM,UAAU,OAAO,WAAW,eAAe;AACjD,QAAM,WAAW,QAAQ,KAAK,SAAS,MAAM,eAAe,CAAC;AAC7D,QAAM,QAAQ,OAAO,SAAS;AAG9B,QAAM,eAAe,SAAS,SAAS,QAAQ;AAC/C,MAAI,aAAa,WAAW,IAAI,KAAK,aAAa,SAAS;AACzD,WAAO;AAAA,MACL,SAAS;AAAA,MACT,UAAU,MAAM;AAAA,MAChB,SAAS,EAAE,YAAY,GAAG,cAAc,GAAG,eAAe,EAAE;AAAA,MAC5D,OAAO,sBAAsB,MAAM,eAAe;AAAA,IACpD;AAAA,EACF;AAEA,MAAI;AACF,QAAI,MAAO,SAAQ,IAAI,6BAA6B,MAAM,eAAe,EAAE;AAG3E,UAAM,EAAE,UAAU,UAAU,IAAI,MAAM,OAAO,aAAa;AAC1D,UAAM,EAAE,cAAAC,eAAc,eAAAC,gBAAe,cAAAC,cAAa,IAAI,MAAM,OAAO,4BAAY;AAG/E,QAAI,eAAe;AACnB,QAAI;AACF,qBAAe,MAAM,SAAS,UAAU,OAAO;AAAA,IACjD,SAAS,OAAY;AACnB,UAAI,MAAM,SAAS,UAAU;AAC3B,cAAM;AAAA,MACR;AAEA,UAAI,MAAO,SAAQ,IAAI,sDAAsD;AAAA,IAC/E;AAEA,UAAM,aAAa,MAAMF,cAAa,cAAc,MAAM,WAAW,MAAM,cAAc,MAAM,iBAAiB,MAAM;
|
|
1
|
+
{"version":3,"sources":["../tools/fastapply/core.ts"],"sourcesContent":["/**\n * Core implementation of Morph Fast Apply\n *\n * This module provides file-based operations that require Node.js.\n * For edge-compatible code-in/code-out operations, use applyEdit from ./apply.ts\n */\n\nimport { join, resolve, relative } from 'path';\nimport type {\n EditFileInput,\n EditFileResult,\n EditFileConfig,\n} from './types.js';\n\n// Re-export edge-compatible functions\nexport { applyEdit, generateUdiff, countChanges, callMorphAPI } from './apply.js';\n\nconst DEFAULT_CONFIG: Required<Omit<EditFileConfig, 'morphApiKey' | 'systemPrompt' | 'retryConfig' | 'description'>> = {\n morphApiUrl: 'https://api.morphllm.com',\n baseDir: process.cwd(),\n generateUdiff: true,\n autoWrite: true,\n timeout: 30000,\n debug: false,\n};\n\n/**\n * FastApply client for programmatic file editing\n * Note: This client requires Node.js for file operations\n */\nexport class FastApplyClient {\n private config: EditFileConfig;\n\n constructor(config: { apiKey?: string; debug?: boolean; timeout?: number; retryConfig?: any } = {}) {\n this.config = {\n morphApiKey: config.apiKey,\n morphApiUrl: DEFAULT_CONFIG.morphApiUrl,\n debug: config.debug,\n timeout: config.timeout || DEFAULT_CONFIG.timeout,\n retryConfig: config.retryConfig,\n generateUdiff: DEFAULT_CONFIG.generateUdiff,\n autoWrite: DEFAULT_CONFIG.autoWrite,\n };\n }\n\n /**\n * Execute a file edit operation\n *\n * @param input - Edit parameters including filepath, instructions, and code_edit\n * @param overrides - Optional config overrides for this operation\n * @returns Edit result with success status and changes\n */\n async execute(input: EditFileInput, overrides?: Partial<EditFileConfig>): Promise<EditFileResult> {\n return executeEditFile(input, { ...this.config, ...overrides });\n }\n\n /**\n * Apply an edit to code directly without file I/O\n *\n * Useful for sandbox environments or when you manage your own file system.\n * Compatible with the earlier OpenAI client API contract.\n *\n * @param input - Code and edit parameters\n * @param overrides - Optional config overrides for this operation\n * @returns Result with merged code\n *\n * @example\n * ```typescript\n * const result = await client.applyEdit({\n * originalCode: 'function hello() { return \"world\"; }',\n * codeEdit: 'function hello() { return \"universe\"; }',\n * instructions: 'Change return value'\n * });\n * console.log(result.mergedCode);\n * ```\n */\n async applyEdit(input: import('./types.js').ApplyEditInput, overrides?: Partial<import('./types.js').ApplyEditConfig>): Promise<import('./types.js').ApplyEditResult> {\n const { applyEdit } = await import('./apply.js');\n return applyEdit(input, { ...this.config, ...overrides });\n }\n}\n\n/**\n * Execute a file edit using Morph Fast Apply\n * Note: This function requires Node.js for file I/O\n */\nexport async function executeEditFile(\n input: EditFileInput,\n config: EditFileConfig = {}\n): Promise<EditFileResult> {\n const baseDir = config.baseDir || DEFAULT_CONFIG.baseDir;\n const fullPath = resolve(join(baseDir, input.target_filepath));\n const debug = config.debug || false;\n\n // Security: ensure file is within baseDir\n const relativePath = relative(baseDir, fullPath);\n if (relativePath.startsWith('..') || fullPath === baseDir) {\n return {\n success: false,\n filepath: input.target_filepath,\n changes: { linesAdded: 0, linesRemoved: 0, linesModified: 0 },\n error: `Invalid filepath: '${input.target_filepath}' is outside baseDir`,\n };\n }\n\n try {\n if (debug) console.log(`[FastApply] Reading file: ${input.target_filepath}`);\n\n // Dynamic import to avoid loading Node.js fs module at module evaluation time\n const { readFile, writeFile } = await import('fs/promises');\n const { callMorphAPI, generateUdiff, countChanges } = await import('./apply.js');\n\n // Handle both existing and non-existent files\n let originalCode = '';\n try {\n originalCode = await readFile(fullPath, 'utf-8');\n } catch (error: any) {\n if (error.code !== 'ENOENT') {\n throw error; // Re-throw if it's not a \"file not found\" error\n }\n // File doesn't exist, proceed with empty content (will create new file)\n if (debug) console.log(`[FastApply] File doesn't exist, will create new file`);\n }\n\n const { content: mergedCode, completionId } = await callMorphAPI(originalCode, input.code_edit, input.instructions, input.target_filepath, config);\n\n const udiff = config.generateUdiff !== false ? generateUdiff(originalCode, mergedCode, input.target_filepath) : undefined;\n\n if (config.autoWrite !== false) {\n await writeFile(fullPath, mergedCode, 'utf-8');\n if (debug) console.log(`[FastApply] Wrote ${mergedCode.length} chars to ${input.target_filepath}`);\n }\n\n const changes = countChanges(originalCode, mergedCode);\n\n return {\n success: true,\n filepath: input.target_filepath,\n udiff,\n changes,\n completionId,\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';\n if (debug) console.error(`[FastApply] Error: ${errorMessage}`);\n\n return {\n success: false,\n filepath: input.target_filepath,\n changes: { linesAdded: 0, linesRemoved: 0, linesModified: 0 },\n error: errorMessage,\n };\n }\n}\n"],"mappings":"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","names":["applyEdit","callMorphAPI","generateUdiff","countChanges"]}
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
} from "./chunk-63WE2C5R.js";
|
|
5
5
|
import {
|
|
6
6
|
executeEditFile
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-M5DR2WOZ.js";
|
|
8
8
|
import {
|
|
9
9
|
__export
|
|
10
10
|
} from "./chunk-PZ5AY32C.js";
|
|
@@ -91,4 +91,4 @@ export {
|
|
|
91
91
|
openai_default,
|
|
92
92
|
openai_exports
|
|
93
93
|
};
|
|
94
|
-
//# sourceMappingURL=chunk-
|
|
94
|
+
//# sourceMappingURL=chunk-UNHHRMU7.js.map
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
} from "./chunk-63WE2C5R.js";
|
|
5
5
|
import {
|
|
6
6
|
executeEditFile
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-M5DR2WOZ.js";
|
|
8
8
|
import {
|
|
9
9
|
__export
|
|
10
10
|
} from "./chunk-PZ5AY32C.js";
|
|
@@ -79,4 +79,4 @@ export {
|
|
|
79
79
|
getSystemPrompt,
|
|
80
80
|
anthropic_exports
|
|
81
81
|
};
|
|
82
|
-
//# sourceMappingURL=chunk-
|
|
82
|
+
//# sourceMappingURL=chunk-Y5BB7JFH.js.map
|
package/dist/client.cjs
CHANGED
|
@@ -30,86 +30,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
30
30
|
));
|
|
31
31
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
32
32
|
|
|
33
|
-
// tools/utils/resilience.ts
|
|
34
|
-
async function fetchWithRetry(url, options, retryConfig = {}) {
|
|
35
|
-
const {
|
|
36
|
-
maxRetries = DEFAULT_RETRY_CONFIG.maxRetries,
|
|
37
|
-
initialDelay = DEFAULT_RETRY_CONFIG.initialDelay,
|
|
38
|
-
maxDelay = DEFAULT_RETRY_CONFIG.maxDelay,
|
|
39
|
-
backoffMultiplier = DEFAULT_RETRY_CONFIG.backoffMultiplier,
|
|
40
|
-
retryableErrors = DEFAULT_RETRY_CONFIG.retryableErrors,
|
|
41
|
-
onRetry
|
|
42
|
-
} = retryConfig;
|
|
43
|
-
let lastError = null;
|
|
44
|
-
let delay = initialDelay;
|
|
45
|
-
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
46
|
-
try {
|
|
47
|
-
const response = await fetch(url, options);
|
|
48
|
-
if (response.status === 429 || response.status === 503) {
|
|
49
|
-
if (attempt < maxRetries) {
|
|
50
|
-
const retryAfter = response.headers.get("Retry-After");
|
|
51
|
-
const waitTime = retryAfter ? parseInt(retryAfter) * 1e3 : Math.min(delay, maxDelay);
|
|
52
|
-
const error = new Error(`HTTP ${response.status}: Retrying after ${waitTime}ms`);
|
|
53
|
-
if (onRetry) {
|
|
54
|
-
onRetry(attempt + 1, error);
|
|
55
|
-
}
|
|
56
|
-
await sleep(waitTime);
|
|
57
|
-
delay *= backoffMultiplier;
|
|
58
|
-
continue;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
return response;
|
|
62
|
-
} catch (error) {
|
|
63
|
-
lastError = error;
|
|
64
|
-
const isRetryable = retryableErrors.some(
|
|
65
|
-
(errType) => lastError?.message?.includes(errType)
|
|
66
|
-
);
|
|
67
|
-
if (!isRetryable || attempt === maxRetries) {
|
|
68
|
-
throw lastError;
|
|
69
|
-
}
|
|
70
|
-
const waitTime = Math.min(delay, maxDelay);
|
|
71
|
-
if (onRetry) {
|
|
72
|
-
onRetry(attempt + 1, lastError);
|
|
73
|
-
}
|
|
74
|
-
await sleep(waitTime);
|
|
75
|
-
delay *= backoffMultiplier;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
throw lastError || new Error("Max retries exceeded");
|
|
79
|
-
}
|
|
80
|
-
async function withTimeout(promise, timeoutMs, errorMessage) {
|
|
81
|
-
let timeoutId;
|
|
82
|
-
const timeoutPromise = new Promise((_, reject) => {
|
|
83
|
-
timeoutId = setTimeout(() => {
|
|
84
|
-
reject(new Error(errorMessage || `Operation timed out after ${timeoutMs}ms`));
|
|
85
|
-
}, timeoutMs);
|
|
86
|
-
});
|
|
87
|
-
try {
|
|
88
|
-
const result = await Promise.race([promise, timeoutPromise]);
|
|
89
|
-
clearTimeout(timeoutId);
|
|
90
|
-
return result;
|
|
91
|
-
} catch (error) {
|
|
92
|
-
clearTimeout(timeoutId);
|
|
93
|
-
throw error;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
function sleep(ms) {
|
|
97
|
-
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
98
|
-
}
|
|
99
|
-
var DEFAULT_RETRY_CONFIG;
|
|
100
|
-
var init_resilience = __esm({
|
|
101
|
-
"tools/utils/resilience.ts"() {
|
|
102
|
-
"use strict";
|
|
103
|
-
DEFAULT_RETRY_CONFIG = {
|
|
104
|
-
maxRetries: 3,
|
|
105
|
-
initialDelay: 1e3,
|
|
106
|
-
maxDelay: 3e4,
|
|
107
|
-
backoffMultiplier: 2,
|
|
108
|
-
retryableErrors: ["ECONNREFUSED", "ETIMEDOUT", "ENOTFOUND"]
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
});
|
|
112
|
-
|
|
113
33
|
// tools/fastapply/apply.ts
|
|
114
34
|
var apply_exports = {};
|
|
115
35
|
__export(apply_exports, {
|
|
@@ -166,37 +86,25 @@ async function callMorphAPI(originalCode, codeEdit, instructions, filepath, conf
|
|
|
166
86
|
console.log(`[FastApply] Original: ${originalCode.length} chars, Edit: ${codeEdit.length} chars`);
|
|
167
87
|
}
|
|
168
88
|
const startTime = Date.now();
|
|
169
|
-
const
|
|
170
|
-
|
|
171
|
-
{
|
|
172
|
-
method: "POST",
|
|
173
|
-
headers: {
|
|
174
|
-
"Content-Type": "application/json",
|
|
175
|
-
"Authorization": `Bearer ${apiKey}`
|
|
176
|
-
},
|
|
177
|
-
body: JSON.stringify({
|
|
178
|
-
model: "morph-v3-fast",
|
|
179
|
-
messages: [{ role: "user", content: message }]
|
|
180
|
-
})
|
|
181
|
-
},
|
|
182
|
-
config.retryConfig
|
|
183
|
-
);
|
|
184
|
-
const response = await withTimeout(
|
|
185
|
-
fetchPromise,
|
|
89
|
+
const client = new import_openai.default({
|
|
90
|
+
apiKey,
|
|
91
|
+
baseURL: `${apiUrl}/v1`,
|
|
186
92
|
timeout,
|
|
187
|
-
|
|
188
|
-
);
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
93
|
+
maxRetries: config.retryConfig?.maxRetries ?? 3
|
|
94
|
+
});
|
|
95
|
+
const completion = await client.chat.completions.create({
|
|
96
|
+
model: "morph-v3-fast",
|
|
97
|
+
messages: [{ role: "user", content: message }]
|
|
98
|
+
});
|
|
99
|
+
const content = completion.choices[0]?.message?.content;
|
|
100
|
+
if (!content) {
|
|
101
|
+
throw new Error("Morph API returned empty response");
|
|
193
102
|
}
|
|
194
|
-
const data = await response.json();
|
|
195
103
|
const elapsed = Date.now() - startTime;
|
|
196
104
|
if (debug) {
|
|
197
|
-
console.log(`[FastApply]
|
|
105
|
+
console.log(`[FastApply] Success in ${elapsed}ms, merged: ${content.length} chars`);
|
|
198
106
|
}
|
|
199
|
-
return
|
|
107
|
+
return { content, completionId: completion.id };
|
|
200
108
|
}
|
|
201
109
|
async function applyEdit(input, config = {}) {
|
|
202
110
|
const debug = config.debug || false;
|
|
@@ -205,7 +113,7 @@ async function applyEdit(input, config = {}) {
|
|
|
205
113
|
if (debug) {
|
|
206
114
|
console.log(`[FastApply] Applying edit to code (${input.originalCode.length} chars)`);
|
|
207
115
|
}
|
|
208
|
-
const mergedCode = await callMorphAPI(
|
|
116
|
+
const { content: mergedCode, completionId } = await callMorphAPI(
|
|
209
117
|
input.originalCode,
|
|
210
118
|
input.codeEdit,
|
|
211
119
|
input.instructions,
|
|
@@ -218,7 +126,8 @@ async function applyEdit(input, config = {}) {
|
|
|
218
126
|
success: true,
|
|
219
127
|
mergedCode,
|
|
220
128
|
udiff,
|
|
221
|
-
changes
|
|
129
|
+
changes,
|
|
130
|
+
completionId
|
|
222
131
|
};
|
|
223
132
|
} catch (error) {
|
|
224
133
|
const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
|
|
@@ -230,12 +139,12 @@ async function applyEdit(input, config = {}) {
|
|
|
230
139
|
};
|
|
231
140
|
}
|
|
232
141
|
}
|
|
233
|
-
var import_diff, DEFAULT_API_URL, DEFAULT_TIMEOUT;
|
|
142
|
+
var import_diff, import_openai, DEFAULT_API_URL, DEFAULT_TIMEOUT;
|
|
234
143
|
var init_apply = __esm({
|
|
235
144
|
"tools/fastapply/apply.ts"() {
|
|
236
145
|
"use strict";
|
|
237
146
|
import_diff = require("diff");
|
|
238
|
-
|
|
147
|
+
import_openai = __toESM(require("openai"), 1);
|
|
239
148
|
DEFAULT_API_URL = "https://api.morphllm.com";
|
|
240
149
|
DEFAULT_TIMEOUT = 3e4;
|
|
241
150
|
}
|
|
@@ -867,7 +776,7 @@ async function executeEditFile(input, config = {}) {
|
|
|
867
776
|
}
|
|
868
777
|
if (debug) console.log(`[FastApply] File doesn't exist, will create new file`);
|
|
869
778
|
}
|
|
870
|
-
const mergedCode = await callMorphAPI2(originalCode, input.code_edit, input.instructions, input.target_filepath, config);
|
|
779
|
+
const { content: mergedCode, completionId } = await callMorphAPI2(originalCode, input.code_edit, input.instructions, input.target_filepath, config);
|
|
871
780
|
const udiff = config.generateUdiff !== false ? generateUdiff2(originalCode, mergedCode, input.target_filepath) : void 0;
|
|
872
781
|
if (config.autoWrite !== false) {
|
|
873
782
|
await writeFile(fullPath, mergedCode, "utf-8");
|
|
@@ -878,7 +787,8 @@ async function executeEditFile(input, config = {}) {
|
|
|
878
787
|
success: true,
|
|
879
788
|
filepath: input.target_filepath,
|
|
880
789
|
udiff,
|
|
881
|
-
changes
|
|
790
|
+
changes,
|
|
791
|
+
completionId
|
|
882
792
|
};
|
|
883
793
|
} catch (error) {
|
|
884
794
|
const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
|
|
@@ -892,8 +802,81 @@ async function executeEditFile(input, config = {}) {
|
|
|
892
802
|
}
|
|
893
803
|
}
|
|
894
804
|
|
|
805
|
+
// tools/utils/resilience.ts
|
|
806
|
+
var DEFAULT_RETRY_CONFIG = {
|
|
807
|
+
maxRetries: 3,
|
|
808
|
+
initialDelay: 1e3,
|
|
809
|
+
maxDelay: 3e4,
|
|
810
|
+
backoffMultiplier: 2,
|
|
811
|
+
retryableErrors: ["ECONNREFUSED", "ETIMEDOUT", "ENOTFOUND"]
|
|
812
|
+
};
|
|
813
|
+
async function fetchWithRetry(url, options, retryConfig = {}) {
|
|
814
|
+
const {
|
|
815
|
+
maxRetries = DEFAULT_RETRY_CONFIG.maxRetries,
|
|
816
|
+
initialDelay = DEFAULT_RETRY_CONFIG.initialDelay,
|
|
817
|
+
maxDelay = DEFAULT_RETRY_CONFIG.maxDelay,
|
|
818
|
+
backoffMultiplier = DEFAULT_RETRY_CONFIG.backoffMultiplier,
|
|
819
|
+
retryableErrors = DEFAULT_RETRY_CONFIG.retryableErrors,
|
|
820
|
+
onRetry
|
|
821
|
+
} = retryConfig;
|
|
822
|
+
let lastError = null;
|
|
823
|
+
let delay = initialDelay;
|
|
824
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
825
|
+
try {
|
|
826
|
+
const response = await fetch(url, options);
|
|
827
|
+
if (response.status === 429 || response.status === 503) {
|
|
828
|
+
if (attempt < maxRetries) {
|
|
829
|
+
const retryAfter = response.headers.get("Retry-After");
|
|
830
|
+
const waitTime = retryAfter ? parseInt(retryAfter) * 1e3 : Math.min(delay, maxDelay);
|
|
831
|
+
const error = new Error(`HTTP ${response.status}: Retrying after ${waitTime}ms`);
|
|
832
|
+
if (onRetry) {
|
|
833
|
+
onRetry(attempt + 1, error);
|
|
834
|
+
}
|
|
835
|
+
await sleep(waitTime);
|
|
836
|
+
delay *= backoffMultiplier;
|
|
837
|
+
continue;
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
return response;
|
|
841
|
+
} catch (error) {
|
|
842
|
+
lastError = error;
|
|
843
|
+
const isRetryable = retryableErrors.some(
|
|
844
|
+
(errType) => lastError?.message?.includes(errType)
|
|
845
|
+
);
|
|
846
|
+
if (!isRetryable || attempt === maxRetries) {
|
|
847
|
+
throw lastError;
|
|
848
|
+
}
|
|
849
|
+
const waitTime = Math.min(delay, maxDelay);
|
|
850
|
+
if (onRetry) {
|
|
851
|
+
onRetry(attempt + 1, lastError);
|
|
852
|
+
}
|
|
853
|
+
await sleep(waitTime);
|
|
854
|
+
delay *= backoffMultiplier;
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
throw lastError || new Error("Max retries exceeded");
|
|
858
|
+
}
|
|
859
|
+
async function withTimeout(promise, timeoutMs, errorMessage) {
|
|
860
|
+
let timeoutId;
|
|
861
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
862
|
+
timeoutId = setTimeout(() => {
|
|
863
|
+
reject(new Error(errorMessage || `Operation timed out after ${timeoutMs}ms`));
|
|
864
|
+
}, timeoutMs);
|
|
865
|
+
});
|
|
866
|
+
try {
|
|
867
|
+
const result = await Promise.race([promise, timeoutPromise]);
|
|
868
|
+
clearTimeout(timeoutId);
|
|
869
|
+
return result;
|
|
870
|
+
} catch (error) {
|
|
871
|
+
clearTimeout(timeoutId);
|
|
872
|
+
throw error;
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
function sleep(ms) {
|
|
876
|
+
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
877
|
+
}
|
|
878
|
+
|
|
895
879
|
// tools/codebase_search/core.ts
|
|
896
|
-
init_resilience();
|
|
897
880
|
var CodebaseSearchClient = class {
|
|
898
881
|
config;
|
|
899
882
|
constructor(config = {}) {
|
|
@@ -988,9 +971,6 @@ async function executeCodebaseSearch(input, config) {
|
|
|
988
971
|
}
|
|
989
972
|
}
|
|
990
973
|
|
|
991
|
-
// tools/browser/core.ts
|
|
992
|
-
init_resilience();
|
|
993
|
-
|
|
994
974
|
// tools/browser/live.ts
|
|
995
975
|
var LIVE_PRESETS = {
|
|
996
976
|
/** Read-only monitoring (no interaction) */
|
|
@@ -1091,9 +1071,6 @@ function resolvePreset(optionsOrPreset) {
|
|
|
1091
1071
|
return optionsOrPreset;
|
|
1092
1072
|
}
|
|
1093
1073
|
|
|
1094
|
-
// tools/browser/profiles/core.ts
|
|
1095
|
-
init_resilience();
|
|
1096
|
-
|
|
1097
1074
|
// tools/browser/errors.ts
|
|
1098
1075
|
var MorphError = class extends Error {
|
|
1099
1076
|
/** Error code for programmatic handling */
|
|
@@ -3023,7 +3000,7 @@ function enforceContextLimit(messages, maxChars = AGENT_CONFIG.MAX_CONTEXT_CHARS
|
|
|
3023
3000
|
}
|
|
3024
3001
|
|
|
3025
3002
|
// tools/warp_grep/agent/runner.ts
|
|
3026
|
-
var
|
|
3003
|
+
var import_openai2 = __toESM(require("openai"), 1);
|
|
3027
3004
|
var import_path3 = __toESM(require("path"), 1);
|
|
3028
3005
|
var parser = new LLMResponseParser();
|
|
3029
3006
|
var DEFAULT_API_URL3 = "https://api.morphllm.com";
|
|
@@ -3031,7 +3008,7 @@ async function callModel(messages, model, options = {}) {
|
|
|
3031
3008
|
const baseUrl = options.morphApiUrl || DEFAULT_API_URL3;
|
|
3032
3009
|
const apiKey = options.morphApiKey || process.env.MORPH_API_KEY || "";
|
|
3033
3010
|
const timeoutMs = options.timeout ?? AGENT_CONFIG.TIMEOUT_MS;
|
|
3034
|
-
const client = new
|
|
3011
|
+
const client = new import_openai2.default({
|
|
3035
3012
|
apiKey,
|
|
3036
3013
|
baseURL: `${baseUrl}/v1`,
|
|
3037
3014
|
maxRetries: options.retryConfig?.maxRetries,
|
|
@@ -3046,7 +3023,7 @@ async function callModel(messages, model, options = {}) {
|
|
|
3046
3023
|
messages
|
|
3047
3024
|
});
|
|
3048
3025
|
} catch (error) {
|
|
3049
|
-
if (error instanceof
|
|
3026
|
+
if (error instanceof import_openai2.default.APIError && error.status === 404) {
|
|
3050
3027
|
throw new Error(
|
|
3051
3028
|
"The endpoint you are trying to call is likely deprecated. Please update with: npm cache clean --force && npx -y @morphllm/morphmcp@latest or visit: https://morphllm.com/mcp"
|
|
3052
3029
|
);
|
|
@@ -4553,7 +4530,6 @@ var import_isomorphic_git2 = __toESM(require("isomorphic-git"), 1);
|
|
|
4553
4530
|
var import_node2 = __toESM(require("isomorphic-git/http/node"), 1);
|
|
4554
4531
|
|
|
4555
4532
|
// modelrouter/core.ts
|
|
4556
|
-
init_resilience();
|
|
4557
4533
|
var DEFAULT_CONFIG3 = {
|
|
4558
4534
|
apiUrl: "https://api.morphllm.com",
|
|
4559
4535
|
timeout: 5e3,
|