@morphllm/morphsdk 0.2.94 → 0.2.96
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-YJ354BA2.js → chunk-2AMEQAO2.js} +2 -2
- package/dist/chunk-2AMEQAO2.js.map +1 -0
- package/dist/{chunk-EI4UKP24.js → chunk-2HMEZZKK.js} +2 -2
- package/dist/{chunk-EI4UKP24.js.map → chunk-2HMEZZKK.js.map} +1 -1
- package/dist/{chunk-UJ7LVT5G.js → chunk-2VERUKO2.js} +1 -1
- package/dist/chunk-2VERUKO2.js.map +1 -0
- package/dist/{chunk-R7WN43L2.js → chunk-4KMBU6T3.js} +4 -4
- package/dist/{chunk-IH3KN4AT.js → chunk-AIXF4GQC.js} +2 -2
- package/dist/{chunk-VHOWYK66.js → chunk-BGEEES52.js} +23 -33
- package/dist/chunk-BGEEES52.js.map +1 -0
- package/dist/{chunk-4WO7PJNT.js → chunk-EZEYREHA.js} +8 -8
- package/dist/{chunk-BVVDDTI7.js → chunk-L5WXPMCH.js} +2 -2
- package/dist/{chunk-FIA6LBW2.js → chunk-OTPYEYMZ.js} +2 -2
- package/dist/{chunk-5QIWYEHJ.js → chunk-PE4KGDA6.js} +1 -8
- package/dist/chunk-PE4KGDA6.js.map +1 -0
- package/dist/{chunk-SQN4DUQS.js → chunk-Q6Y4R236.js} +26 -2
- package/dist/chunk-Q6Y4R236.js.map +1 -0
- package/dist/{chunk-TXYCM4NP.js → chunk-QH4BSXOD.js} +3 -3
- package/dist/{chunk-M7GFXRKL.js → chunk-QJP62BXH.js} +157 -72
- package/dist/chunk-QJP62BXH.js.map +1 -0
- package/dist/{chunk-AV6YV2MH.js → chunk-R7IQWNSA.js} +8 -8
- package/dist/chunk-R7IQWNSA.js.map +1 -0
- package/dist/{chunk-ESRZJRTQ.js → chunk-SI2CKRKJ.js} +86 -56
- package/dist/chunk-SI2CKRKJ.js.map +1 -0
- package/dist/{chunk-FMWNVTJJ.js → chunk-TSENDJQI.js} +6 -6
- package/dist/chunk-TSENDJQI.js.map +1 -0
- package/dist/{chunk-IUG2FHNN.js → chunk-XH7P7HVT.js} +1 -8
- package/dist/chunk-XH7P7HVT.js.map +1 -0
- package/dist/{chunk-WSQMWVSD.js → chunk-YZ5NCWO2.js} +6 -6
- package/dist/chunk-YZ5NCWO2.js.map +1 -0
- package/dist/client.cjs +280 -162
- package/dist/client.cjs.map +1 -1
- package/dist/client.js +18 -18
- package/dist/index.cjs +280 -162
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +18 -18
- package/dist/tools/browser/anthropic.cjs +54 -23
- package/dist/tools/browser/anthropic.cjs.map +1 -1
- package/dist/tools/browser/anthropic.js +7 -7
- package/dist/tools/browser/core.cjs +262 -124
- package/dist/tools/browser/core.cjs.map +1 -1
- package/dist/tools/browser/core.d.ts +24 -24
- package/dist/tools/browser/core.js +5 -5
- package/dist/tools/browser/errors.cjs.map +1 -1
- package/dist/tools/browser/errors.d.ts +1 -1
- package/dist/tools/browser/errors.js +1 -1
- package/dist/tools/browser/index.cjs +277 -139
- package/dist/tools/browser/index.cjs.map +1 -1
- package/dist/tools/browser/index.d.ts +3 -3
- package/dist/tools/browser/index.js +12 -12
- package/dist/tools/browser/index.js.map +1 -1
- package/dist/tools/browser/live.cjs +25 -1
- package/dist/tools/browser/live.cjs.map +1 -1
- package/dist/tools/browser/live.js +1 -1
- package/dist/tools/browser/openai.cjs +54 -23
- package/dist/tools/browser/openai.cjs.map +1 -1
- package/dist/tools/browser/openai.js +7 -7
- package/dist/tools/browser/profiles/core.cjs +85 -54
- package/dist/tools/browser/profiles/core.cjs.map +1 -1
- package/dist/tools/browser/profiles/core.d.ts +33 -25
- package/dist/tools/browser/profiles/core.js +5 -3
- package/dist/tools/browser/profiles/index.cjs +85 -54
- package/dist/tools/browser/profiles/index.cjs.map +1 -1
- package/dist/tools/browser/profiles/index.d.ts +2 -2
- package/dist/tools/browser/profiles/index.js +5 -3
- package/dist/tools/browser/profiles/types.cjs +1 -1
- package/dist/tools/browser/profiles/types.cjs.map +1 -1
- package/dist/tools/browser/profiles/types.d.ts +28 -9
- package/dist/tools/browser/profiles/types.js +1 -1
- package/dist/tools/browser/prompts.cjs +1 -1
- package/dist/tools/browser/prompts.cjs.map +1 -1
- package/dist/tools/browser/prompts.d.ts +1 -1
- package/dist/tools/browser/prompts.js +1 -1
- package/dist/tools/browser/types.cjs.map +1 -1
- package/dist/tools/browser/types.d.ts +54 -52
- package/dist/tools/browser/vercel.cjs +56 -25
- package/dist/tools/browser/vercel.cjs.map +1 -1
- package/dist/tools/browser/vercel.d.ts +1 -1
- package/dist/tools/browser/vercel.js +7 -7
- package/dist/tools/fastapply/anthropic.cjs +0 -7
- package/dist/tools/fastapply/anthropic.cjs.map +1 -1
- package/dist/tools/fastapply/anthropic.js +1 -1
- package/dist/tools/fastapply/index.cjs +0 -14
- package/dist/tools/fastapply/index.cjs.map +1 -1
- package/dist/tools/fastapply/index.js +2 -2
- package/dist/tools/fastapply/openai.cjs +0 -7
- package/dist/tools/fastapply/openai.cjs.map +1 -1
- package/dist/tools/fastapply/openai.js +1 -1
- package/dist/tools/index.cjs +0 -14
- package/dist/tools/index.cjs.map +1 -1
- package/dist/tools/index.js +2 -2
- package/dist/tools/warp_grep/agent/runner.cjs +18 -98
- package/dist/tools/warp_grep/agent/runner.cjs.map +1 -1
- package/dist/tools/warp_grep/agent/runner.js +2 -3
- package/dist/tools/warp_grep/anthropic.cjs +18 -98
- package/dist/tools/warp_grep/anthropic.cjs.map +1 -1
- package/dist/tools/warp_grep/anthropic.js +8 -9
- package/dist/tools/warp_grep/client.cjs +18 -98
- package/dist/tools/warp_grep/client.cjs.map +1 -1
- package/dist/tools/warp_grep/client.js +7 -8
- package/dist/tools/warp_grep/gemini.cjs +18 -98
- package/dist/tools/warp_grep/gemini.cjs.map +1 -1
- package/dist/tools/warp_grep/gemini.js +7 -8
- package/dist/tools/warp_grep/gemini.js.map +1 -1
- package/dist/tools/warp_grep/harness.js +10 -10
- package/dist/tools/warp_grep/index.cjs +18 -98
- package/dist/tools/warp_grep/index.cjs.map +1 -1
- package/dist/tools/warp_grep/index.js +10 -11
- package/dist/tools/warp_grep/openai.cjs +18 -98
- package/dist/tools/warp_grep/openai.cjs.map +1 -1
- package/dist/tools/warp_grep/openai.js +8 -9
- package/dist/tools/warp_grep/providers/local.js +2 -2
- package/dist/tools/warp_grep/vercel.cjs +18 -98
- package/dist/tools/warp_grep/vercel.cjs.map +1 -1
- package/dist/tools/warp_grep/vercel.js +8 -9
- package/dist/{vercel-CsnNSdze.d.ts → vercel-CVF27qFK.d.ts} +10 -10
- package/package.json +1 -1
- package/dist/chunk-5QIWYEHJ.js.map +0 -1
- package/dist/chunk-AV6YV2MH.js.map +0 -1
- package/dist/chunk-ESRZJRTQ.js.map +0 -1
- package/dist/chunk-FMWNVTJJ.js.map +0 -1
- package/dist/chunk-IUG2FHNN.js.map +0 -1
- package/dist/chunk-M7GFXRKL.js.map +0 -1
- package/dist/chunk-SQN4DUQS.js.map +0 -1
- package/dist/chunk-UJ7LVT5G.js.map +0 -1
- package/dist/chunk-VHOWYK66.js.map +0 -1
- package/dist/chunk-WSQMWVSD.js.map +0 -1
- package/dist/chunk-YJ354BA2.js.map +0 -1
- /package/dist/{chunk-R7WN43L2.js.map → chunk-4KMBU6T3.js.map} +0 -0
- /package/dist/{chunk-IH3KN4AT.js.map → chunk-AIXF4GQC.js.map} +0 -0
- /package/dist/{chunk-4WO7PJNT.js.map → chunk-EZEYREHA.js.map} +0 -0
- /package/dist/{chunk-BVVDDTI7.js.map → chunk-L5WXPMCH.js.map} +0 -0
- /package/dist/{chunk-FIA6LBW2.js.map → chunk-OTPYEYMZ.js.map} +0 -0
- /package/dist/{chunk-TXYCM4NP.js.map → chunk-QH4BSXOD.js.map} +0 -0
package/dist/client.cjs
CHANGED
|
@@ -440,7 +440,8 @@ function buildLiveUrl(debugUrl, options = {}) {
|
|
|
440
440
|
"debugUrl is required. Ensure your backend returns debugUrl in the task response. Contact support@morphllm.com if you need help."
|
|
441
441
|
);
|
|
442
442
|
}
|
|
443
|
-
const
|
|
443
|
+
const normalized = normalizeLiveUrl(debugUrl);
|
|
444
|
+
const url = new URL(normalized);
|
|
444
445
|
if (options.interactive !== void 0) {
|
|
445
446
|
url.searchParams.set("interactive", String(options.interactive));
|
|
446
447
|
}
|
|
@@ -458,6 +459,29 @@ function buildLiveUrl(debugUrl, options = {}) {
|
|
|
458
459
|
}
|
|
459
460
|
return url.toString();
|
|
460
461
|
}
|
|
462
|
+
function normalizeLiveUrl(debugUrl) {
|
|
463
|
+
const trimmed = debugUrl.trim();
|
|
464
|
+
if (!trimmed) {
|
|
465
|
+
return trimmed;
|
|
466
|
+
}
|
|
467
|
+
if (trimmed.startsWith("wss://") || trimmed.startsWith("ws://")) {
|
|
468
|
+
return `https://live.browser-use.com?wss=${encodeURIComponent(trimmed)}`;
|
|
469
|
+
}
|
|
470
|
+
let url;
|
|
471
|
+
try {
|
|
472
|
+
url = new URL(trimmed);
|
|
473
|
+
} catch {
|
|
474
|
+
return trimmed;
|
|
475
|
+
}
|
|
476
|
+
if (url.protocol === "wss:" || url.protocol === "ws:") {
|
|
477
|
+
return `https://live.browser-use.com?wss=${encodeURIComponent(trimmed)}`;
|
|
478
|
+
}
|
|
479
|
+
const wssParam = url.searchParams.get("wss");
|
|
480
|
+
if (wssParam && (wssParam.startsWith("wss://") || wssParam.startsWith("ws://"))) {
|
|
481
|
+
url.searchParams.set("wss", wssParam);
|
|
482
|
+
}
|
|
483
|
+
return url.toString();
|
|
484
|
+
}
|
|
461
485
|
function buildLiveIframe(debugUrl, options = {}) {
|
|
462
486
|
const {
|
|
463
487
|
width = "100%",
|
|
@@ -688,7 +712,7 @@ function transformCreateInput(input) {
|
|
|
688
712
|
function transformSession(api) {
|
|
689
713
|
return {
|
|
690
714
|
sessionId: api.session_id,
|
|
691
|
-
debugUrl: api.debug_url ||
|
|
715
|
+
debugUrl: api.debug_url || ""
|
|
692
716
|
};
|
|
693
717
|
}
|
|
694
718
|
function transformSaveInput(input) {
|
|
@@ -713,22 +737,24 @@ var ProfilesClient = class {
|
|
|
713
737
|
this.config = config;
|
|
714
738
|
}
|
|
715
739
|
/**
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
740
|
+
* Create a new browser profile and immediately start a live session.
|
|
741
|
+
*
|
|
742
|
+
* @param input - Profile creation parameters
|
|
743
|
+
* @returns Profile setup handle with live URL + save()
|
|
744
|
+
* @throws {MorphValidationError} If input validation fails
|
|
745
|
+
* @throws {MorphProfileLimitError} If profile limit is exceeded
|
|
746
|
+
* @throws {MorphAuthenticationError} If API key is missing or invalid
|
|
747
|
+
*
|
|
748
|
+
* @example
|
|
749
|
+
* ```typescript
|
|
750
|
+
* const setup = await morph.browser.profiles.createProfile({
|
|
751
|
+
* name: 'LinkedIn Production',
|
|
752
|
+
* repoId: 'owner/repo'
|
|
753
|
+
* });
|
|
754
|
+
* console.log(setup.session.debugUrl);
|
|
755
|
+
* await setup.save();
|
|
756
|
+
* ```
|
|
757
|
+
*/
|
|
732
758
|
async createProfile(input) {
|
|
733
759
|
return createProfile(input, this.config);
|
|
734
760
|
}
|
|
@@ -744,7 +770,7 @@ var ProfilesClient = class {
|
|
|
744
770
|
* const allProfiles = await morph.browser.profiles.listProfiles();
|
|
745
771
|
*
|
|
746
772
|
* // List profiles for a specific repo
|
|
747
|
-
* const repoProfiles = await morph.browser.profiles.listProfiles('repo
|
|
773
|
+
* const repoProfiles = await morph.browser.profiles.listProfiles('owner/repo');
|
|
748
774
|
* ```
|
|
749
775
|
*/
|
|
750
776
|
async listProfiles(repoId) {
|
|
@@ -768,14 +794,13 @@ var ProfilesClient = class {
|
|
|
768
794
|
return getProfile(id, this.config);
|
|
769
795
|
}
|
|
770
796
|
/**
|
|
771
|
-
* Update a profile
|
|
797
|
+
* Update a profile by opening a live session (no rename).
|
|
772
798
|
*
|
|
773
799
|
* @param id - Profile ID
|
|
774
|
-
* @
|
|
775
|
-
* @returns Updated profile
|
|
800
|
+
* @returns Profile setup handle with live URL + save()
|
|
776
801
|
*/
|
|
777
|
-
async updateProfile(id
|
|
778
|
-
return updateProfile(id,
|
|
802
|
+
async updateProfile(id) {
|
|
803
|
+
return updateProfile(id, this.config);
|
|
779
804
|
}
|
|
780
805
|
/**
|
|
781
806
|
* Delete a profile.
|
|
@@ -819,6 +844,14 @@ var ProfilesClient = class {
|
|
|
819
844
|
async saveSession(sessionId, profileId) {
|
|
820
845
|
return saveProfileSession({ sessionId, profileId }, this.config);
|
|
821
846
|
}
|
|
847
|
+
/**
|
|
848
|
+
* List available repo IDs (discovery).
|
|
849
|
+
*
|
|
850
|
+
* @returns Repo summaries with profile counts
|
|
851
|
+
*/
|
|
852
|
+
async listRepos() {
|
|
853
|
+
return listRepos(this.config);
|
|
854
|
+
}
|
|
822
855
|
/**
|
|
823
856
|
* Get the presigned URL for a profile's state.
|
|
824
857
|
*
|
|
@@ -877,7 +910,9 @@ async function createProfile(input, config = {}) {
|
|
|
877
910
|
throw parseAPIError(response.status, errorText, requestId);
|
|
878
911
|
}
|
|
879
912
|
const apiProfile = await response.json();
|
|
880
|
-
|
|
913
|
+
const profile = transformProfile(apiProfile);
|
|
914
|
+
const session = await startProfileSession(config, { profileId: profile.id });
|
|
915
|
+
return buildProfileSetup(profile, session, config);
|
|
881
916
|
}
|
|
882
917
|
async function listProfiles(config = {}, repoId) {
|
|
883
918
|
const apiUrl = config.apiUrl || DEFAULT_API_URL;
|
|
@@ -918,37 +953,11 @@ async function getProfile(id, config = {}) {
|
|
|
918
953
|
delete: () => deleteProfile(id, config)
|
|
919
954
|
};
|
|
920
955
|
}
|
|
921
|
-
async function updateProfile(id,
|
|
956
|
+
async function updateProfile(id, config = {}) {
|
|
922
957
|
validateId(id, "id");
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
}
|
|
927
|
-
if (input.name.trim().length === 0) {
|
|
928
|
-
throw new MorphValidationError("name cannot be empty", "name");
|
|
929
|
-
}
|
|
930
|
-
if (input.name.length > 100) {
|
|
931
|
-
throw new MorphValidationError("name must be 100 characters or less", "name");
|
|
932
|
-
}
|
|
933
|
-
}
|
|
934
|
-
const apiUrl = config.apiUrl || DEFAULT_API_URL;
|
|
935
|
-
const headers = buildHeaders(config);
|
|
936
|
-
const response = await fetchWithRetry(
|
|
937
|
-
`${apiUrl}/profiles/${encodeURIComponent(id)}`,
|
|
938
|
-
{
|
|
939
|
-
method: "PATCH",
|
|
940
|
-
headers,
|
|
941
|
-
body: JSON.stringify(input)
|
|
942
|
-
},
|
|
943
|
-
config.retryConfig
|
|
944
|
-
);
|
|
945
|
-
if (!response.ok) {
|
|
946
|
-
const errorText = await response.text().catch(() => response.statusText);
|
|
947
|
-
const requestId = response.headers.get("x-request-id") || void 0;
|
|
948
|
-
throw parseAPIError(response.status, errorText, requestId);
|
|
949
|
-
}
|
|
950
|
-
const apiProfile = await response.json();
|
|
951
|
-
return transformProfile(apiProfile);
|
|
958
|
+
const profile = await fetchProfile(id, config);
|
|
959
|
+
const session = await startProfileSession(config, { profileId: profile.id });
|
|
960
|
+
return buildProfileSetup(profile, session, config);
|
|
952
961
|
}
|
|
953
962
|
async function deleteProfile(id, config = {}) {
|
|
954
963
|
validateId(id, "id");
|
|
@@ -1011,6 +1020,27 @@ async function saveProfileSession(input, config = {}) {
|
|
|
1011
1020
|
const apiProfile = await response.json();
|
|
1012
1021
|
return transformProfile(apiProfile);
|
|
1013
1022
|
}
|
|
1023
|
+
async function listRepos(config = {}) {
|
|
1024
|
+
const apiUrl = config.apiUrl || DEFAULT_API_URL;
|
|
1025
|
+
const headers = buildHeaders(config);
|
|
1026
|
+
const response = await fetchWithRetry(
|
|
1027
|
+
`${apiUrl}/repos`,
|
|
1028
|
+
{ method: "GET", headers },
|
|
1029
|
+
config.retryConfig
|
|
1030
|
+
);
|
|
1031
|
+
if (!response.ok) {
|
|
1032
|
+
const errorText = await response.text().catch(() => response.statusText);
|
|
1033
|
+
const requestId = response.headers.get("x-request-id") || void 0;
|
|
1034
|
+
throw parseAPIError(response.status, errorText, requestId);
|
|
1035
|
+
}
|
|
1036
|
+
const data = await response.json();
|
|
1037
|
+
const repos = Array.isArray(data?.repos) ? data.repos : [];
|
|
1038
|
+
return repos.map((repo) => ({
|
|
1039
|
+
repoId: repo.repo_id,
|
|
1040
|
+
repoFullName: repo.repo_full_name,
|
|
1041
|
+
profileCount: repo.profile_count ?? 0
|
|
1042
|
+
}));
|
|
1043
|
+
}
|
|
1014
1044
|
async function getProfileState(profileId, config = {}) {
|
|
1015
1045
|
validateId(profileId, "profileId");
|
|
1016
1046
|
const apiUrl = config.apiUrl || DEFAULT_API_URL;
|
|
@@ -1035,6 +1065,29 @@ function buildHeaders(config) {
|
|
|
1035
1065
|
}
|
|
1036
1066
|
return headers;
|
|
1037
1067
|
}
|
|
1068
|
+
async function fetchProfile(id, config) {
|
|
1069
|
+
const apiUrl = config.apiUrl || DEFAULT_API_URL;
|
|
1070
|
+
const headers = buildHeaders(config);
|
|
1071
|
+
const response = await fetchWithRetry(
|
|
1072
|
+
`${apiUrl}/profiles/${encodeURIComponent(id)}`,
|
|
1073
|
+
{ method: "GET", headers },
|
|
1074
|
+
config.retryConfig
|
|
1075
|
+
);
|
|
1076
|
+
if (!response.ok) {
|
|
1077
|
+
const errorText = await response.text().catch(() => response.statusText);
|
|
1078
|
+
const requestId = response.headers.get("x-request-id") || void 0;
|
|
1079
|
+
throw parseAPIError(response.status, errorText, requestId);
|
|
1080
|
+
}
|
|
1081
|
+
const apiProfile = await response.json();
|
|
1082
|
+
return transformProfile(apiProfile);
|
|
1083
|
+
}
|
|
1084
|
+
function buildProfileSetup(profile, session, config) {
|
|
1085
|
+
return {
|
|
1086
|
+
profile,
|
|
1087
|
+
session,
|
|
1088
|
+
save: () => saveProfileSession({ sessionId: session.sessionId, profileId: profile.id }, config)
|
|
1089
|
+
};
|
|
1090
|
+
}
|
|
1038
1091
|
|
|
1039
1092
|
// tools/browser/core.ts
|
|
1040
1093
|
var DEFAULT_CONFIG2 = {
|
|
@@ -1077,20 +1130,21 @@ var BrowserClient = class {
|
|
|
1077
1130
|
body: JSON.stringify({
|
|
1078
1131
|
task: input.task,
|
|
1079
1132
|
url: input.url,
|
|
1080
|
-
max_steps: input.
|
|
1133
|
+
max_steps: input.maxSteps ?? 10,
|
|
1081
1134
|
model: input.model ?? "morph-computer-use-v0",
|
|
1082
|
-
viewport_width: input.
|
|
1083
|
-
viewport_height: input.
|
|
1084
|
-
external_id: input.
|
|
1085
|
-
repo_id: input.
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1135
|
+
viewport_width: input.viewportWidth ?? 1280,
|
|
1136
|
+
viewport_height: input.viewportHeight ?? 720,
|
|
1137
|
+
external_id: input.externalId,
|
|
1138
|
+
repo_id: input.repoId,
|
|
1139
|
+
repo_full_name: input.repoFullName,
|
|
1140
|
+
commit_id: input.commitId,
|
|
1141
|
+
record_video: input.recordVideo ?? false,
|
|
1142
|
+
video_width: input.videoWidth ?? input.viewportWidth ?? 1280,
|
|
1143
|
+
video_height: input.videoHeight ?? input.viewportHeight ?? 720,
|
|
1144
|
+
allow_resizing: input.allowResizing ?? false,
|
|
1091
1145
|
structured_output: "schema" in input ? stringifyStructuredOutput(input.schema) : void 0,
|
|
1092
1146
|
auth: input.auth,
|
|
1093
|
-
profile_id: input.
|
|
1147
|
+
profile_id: input.profileId
|
|
1094
1148
|
})
|
|
1095
1149
|
});
|
|
1096
1150
|
if (!response.ok) {
|
|
@@ -1098,9 +1152,10 @@ var BrowserClient = class {
|
|
|
1098
1152
|
if (debug) console.error(`[Browser] Error: ${response.status} - ${errorText}`);
|
|
1099
1153
|
throw new Error(`HTTP ${response.status}: ${errorText}`);
|
|
1100
1154
|
}
|
|
1101
|
-
const result = await response.json();
|
|
1155
|
+
const result = mapTaskResult(await response.json());
|
|
1102
1156
|
if (debug) {
|
|
1103
|
-
|
|
1157
|
+
const debugUrl = result.debugUrl;
|
|
1158
|
+
console.log(`[Browser] \u2705 Task created: recordingId=${result.recordingId ?? "none"} debugUrl=${debugUrl ? "available" : "none"}`);
|
|
1104
1159
|
}
|
|
1105
1160
|
if ("schema" in input) {
|
|
1106
1161
|
return wrapTaskResponseWithSchema(result, this.config, input.schema);
|
|
@@ -1155,15 +1210,15 @@ async function executeBrowserTask(input, config = {}) {
|
|
|
1155
1210
|
error: 'Task description is required. Example: "Go to example.com and click the login button"'
|
|
1156
1211
|
};
|
|
1157
1212
|
}
|
|
1158
|
-
if (input.
|
|
1213
|
+
if (input.maxSteps !== void 0 && (input.maxSteps < 1 || input.maxSteps > 50)) {
|
|
1159
1214
|
return {
|
|
1160
1215
|
success: false,
|
|
1161
|
-
error: "
|
|
1216
|
+
error: "maxSteps must be between 1 and 50. Use more steps for complex multi-page flows."
|
|
1162
1217
|
};
|
|
1163
1218
|
}
|
|
1164
1219
|
if (debug) {
|
|
1165
|
-
console.log(`[Browser] Task: "${input.task.slice(0, 60)}..." url=${input.url || "none"} maxSteps=${input.
|
|
1166
|
-
console.log(`[Browser] Recording: ${input.
|
|
1220
|
+
console.log(`[Browser] Task: "${input.task.slice(0, 60)}..." url=${input.url || "none"} maxSteps=${input.maxSteps ?? 10}`);
|
|
1221
|
+
console.log(`[Browser] Recording: ${input.recordVideo ? "yes" : "no"} | Calling ${apiUrl}/browser-task`);
|
|
1167
1222
|
}
|
|
1168
1223
|
const startTime = Date.now();
|
|
1169
1224
|
try {
|
|
@@ -1177,20 +1232,20 @@ async function executeBrowserTask(input, config = {}) {
|
|
|
1177
1232
|
body: JSON.stringify({
|
|
1178
1233
|
task: input.task,
|
|
1179
1234
|
url: input.url,
|
|
1180
|
-
max_steps: input.
|
|
1235
|
+
max_steps: input.maxSteps ?? 10,
|
|
1181
1236
|
model: input.model ?? "morph-computer-use-v0",
|
|
1182
|
-
viewport_width: input.
|
|
1183
|
-
viewport_height: input.
|
|
1184
|
-
external_id: input.
|
|
1185
|
-
repo_id: input.
|
|
1186
|
-
commit_id: input.
|
|
1187
|
-
record_video: input.
|
|
1188
|
-
video_width: input.
|
|
1189
|
-
video_height: input.
|
|
1190
|
-
allow_resizing: input.
|
|
1191
|
-
structured_output: input.
|
|
1237
|
+
viewport_width: input.viewportWidth ?? 1280,
|
|
1238
|
+
viewport_height: input.viewportHeight ?? 720,
|
|
1239
|
+
external_id: input.externalId,
|
|
1240
|
+
repo_id: input.repoId,
|
|
1241
|
+
commit_id: input.commitId,
|
|
1242
|
+
record_video: input.recordVideo ?? false,
|
|
1243
|
+
video_width: input.videoWidth ?? input.viewportWidth ?? 1280,
|
|
1244
|
+
video_height: input.videoHeight ?? input.viewportHeight ?? 720,
|
|
1245
|
+
allow_resizing: input.allowResizing ?? false,
|
|
1246
|
+
structured_output: input.structuredOutput,
|
|
1192
1247
|
auth: input.auth,
|
|
1193
|
-
profile_id: input.
|
|
1248
|
+
profile_id: input.profileId
|
|
1194
1249
|
})
|
|
1195
1250
|
},
|
|
1196
1251
|
config.retryConfig
|
|
@@ -1198,17 +1253,17 @@ async function executeBrowserTask(input, config = {}) {
|
|
|
1198
1253
|
const response = await withTimeout(
|
|
1199
1254
|
fetchPromise,
|
|
1200
1255
|
timeout,
|
|
1201
|
-
`Browser task timed out after ${timeout}ms. Consider increasing timeout or reducing
|
|
1256
|
+
`Browser task timed out after ${timeout}ms. Consider increasing timeout or reducing maxSteps.`
|
|
1202
1257
|
);
|
|
1203
1258
|
if (!response.ok) {
|
|
1204
1259
|
const errorText = await response.text().catch(() => response.statusText);
|
|
1205
1260
|
if (debug) console.error(`[Browser] Error: ${response.status} - ${errorText}`);
|
|
1206
1261
|
throw new Error(`HTTP ${response.status}: ${errorText}`);
|
|
1207
1262
|
}
|
|
1208
|
-
const result = await response.json();
|
|
1263
|
+
const result = mapTaskResult(await response.json());
|
|
1209
1264
|
const elapsed = Date.now() - startTime;
|
|
1210
1265
|
if (debug) {
|
|
1211
|
-
console.log(`[Browser] \u2705 ${result.success ? "Success" : "Failed"} in ${elapsed}ms | steps=${result.
|
|
1266
|
+
console.log(`[Browser] \u2705 ${result.success ? "Success" : "Failed"} in ${elapsed}ms | steps=${result.stepsTaken ?? 0} recordingId=${result.recordingId ?? "none"}`);
|
|
1212
1267
|
}
|
|
1213
1268
|
return result;
|
|
1214
1269
|
} catch (error) {
|
|
@@ -1246,7 +1301,7 @@ async function getRecording(recordingId, config = {}) {
|
|
|
1246
1301
|
if (debug) console.error(`[Browser] getRecording error: ${response.status} - ${errorText}`);
|
|
1247
1302
|
throw new Error(`HTTP ${response.status}: ${errorText}`);
|
|
1248
1303
|
}
|
|
1249
|
-
const data = await response.json();
|
|
1304
|
+
const data = mapRecordingStatus(await response.json());
|
|
1250
1305
|
if (debug) console.log(`[Browser] Recording status: ${data.status}`);
|
|
1251
1306
|
return {
|
|
1252
1307
|
...data,
|
|
@@ -1269,10 +1324,10 @@ async function waitForRecording(recordingId, config = {}, options = {}) {
|
|
|
1269
1324
|
}
|
|
1270
1325
|
async function executeWithRecording(input, config = {}) {
|
|
1271
1326
|
const taskResult = await executeBrowserTask(input, config);
|
|
1272
|
-
if (taskResult.
|
|
1327
|
+
if (taskResult.recordingId) {
|
|
1273
1328
|
try {
|
|
1274
1329
|
const recording = await waitForRecording(
|
|
1275
|
-
taskResult.
|
|
1330
|
+
taskResult.recordingId,
|
|
1276
1331
|
config,
|
|
1277
1332
|
{ timeout: 6e4, pollInterval: 2e3 }
|
|
1278
1333
|
);
|
|
@@ -1282,12 +1337,12 @@ async function executeWithRecording(input, config = {}) {
|
|
|
1282
1337
|
};
|
|
1283
1338
|
} catch (error) {
|
|
1284
1339
|
const errorRecording = {
|
|
1285
|
-
id: taskResult.
|
|
1340
|
+
id: taskResult.recordingId,
|
|
1286
1341
|
status: "ERROR",
|
|
1287
1342
|
error: error instanceof Error ? error.message : String(error),
|
|
1288
|
-
|
|
1289
|
-
getWebp: (options) => getWebp(taskResult.
|
|
1290
|
-
getErrors: () => getErrors(taskResult.
|
|
1343
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1344
|
+
getWebp: (options) => getWebp(taskResult.recordingId, config, options),
|
|
1345
|
+
getErrors: () => getErrors(taskResult.recordingId, config)
|
|
1291
1346
|
};
|
|
1292
1347
|
return {
|
|
1293
1348
|
...taskResult,
|
|
@@ -1313,8 +1368,8 @@ async function getErrors(recordingId, config = {}) {
|
|
|
1313
1368
|
if (debug) console.error(`[Browser] getErrors error: ${response.status} - ${errorText}`);
|
|
1314
1369
|
throw new Error(`HTTP ${response.status}: ${errorText}`);
|
|
1315
1370
|
}
|
|
1316
|
-
const errors = await response.json();
|
|
1317
|
-
if (debug) console.log(`[Browser] Found ${errors.
|
|
1371
|
+
const errors = mapErrorsResponse(await response.json());
|
|
1372
|
+
if (debug) console.log(`[Browser] Found ${errors.totalErrors} errors`);
|
|
1318
1373
|
return errors;
|
|
1319
1374
|
}
|
|
1320
1375
|
function stringifyStructuredOutput(schema) {
|
|
@@ -1347,6 +1402,84 @@ function parseStructuredTaskOutput(result, schema) {
|
|
|
1347
1402
|
throw error;
|
|
1348
1403
|
}
|
|
1349
1404
|
}
|
|
1405
|
+
function mapTaskResult(api) {
|
|
1406
|
+
if (!api || typeof api !== "object") {
|
|
1407
|
+
return api;
|
|
1408
|
+
}
|
|
1409
|
+
return {
|
|
1410
|
+
success: api.success,
|
|
1411
|
+
result: api.result,
|
|
1412
|
+
error: api.error,
|
|
1413
|
+
stepsTaken: api.steps_taken,
|
|
1414
|
+
executionTimeMs: api.execution_time_ms,
|
|
1415
|
+
urls: api.urls,
|
|
1416
|
+
actionNames: api.action_names,
|
|
1417
|
+
errors: api.errors,
|
|
1418
|
+
modelActions: api.model_actions,
|
|
1419
|
+
isDone: api.is_done,
|
|
1420
|
+
actionHistory: api.action_history,
|
|
1421
|
+
actionResults: api.action_results,
|
|
1422
|
+
hasErrors: api.has_errors,
|
|
1423
|
+
numberOfSteps: api.number_of_steps,
|
|
1424
|
+
judgement: api.judgement,
|
|
1425
|
+
isValidated: api.is_validated,
|
|
1426
|
+
replayId: api.replay_id,
|
|
1427
|
+
replayUrl: api.replay_url,
|
|
1428
|
+
recordingId: api.recording_id,
|
|
1429
|
+
recordingStatus: api.recording_status,
|
|
1430
|
+
taskId: api.task_id,
|
|
1431
|
+
status: api.status,
|
|
1432
|
+
output: api.output,
|
|
1433
|
+
debugUrl: api.debug_url
|
|
1434
|
+
};
|
|
1435
|
+
}
|
|
1436
|
+
function mapRecordingStatus(api) {
|
|
1437
|
+
return {
|
|
1438
|
+
id: api.id,
|
|
1439
|
+
status: api.status,
|
|
1440
|
+
replayUrl: api.replay_url,
|
|
1441
|
+
networkUrl: api.network_url,
|
|
1442
|
+
consoleUrl: api.console_url,
|
|
1443
|
+
videoUrl: api.video_url,
|
|
1444
|
+
totalEvents: api.total_events,
|
|
1445
|
+
fileSize: api.file_size,
|
|
1446
|
+
duration: api.duration,
|
|
1447
|
+
error: api.error,
|
|
1448
|
+
createdAt: api.created_at
|
|
1449
|
+
};
|
|
1450
|
+
}
|
|
1451
|
+
function mapBrowserError(api) {
|
|
1452
|
+
return {
|
|
1453
|
+
type: api.type,
|
|
1454
|
+
message: api.message,
|
|
1455
|
+
url: api.url,
|
|
1456
|
+
timestamp: api.timestamp,
|
|
1457
|
+
screenshotUrl: api.screenshot_url,
|
|
1458
|
+
capturedAt: api.captured_at,
|
|
1459
|
+
status: api.status
|
|
1460
|
+
};
|
|
1461
|
+
}
|
|
1462
|
+
function mapErrorsResponse(api) {
|
|
1463
|
+
return {
|
|
1464
|
+
recordingId: api.recording_id,
|
|
1465
|
+
totalErrors: api.total_errors,
|
|
1466
|
+
errors: Array.isArray(api.errors) ? api.errors.map(mapBrowserError) : []
|
|
1467
|
+
};
|
|
1468
|
+
}
|
|
1469
|
+
function mapWebpResponse(api) {
|
|
1470
|
+
return {
|
|
1471
|
+
webpUrl: api.webp_url,
|
|
1472
|
+
cached: api.cached,
|
|
1473
|
+
width: api.width,
|
|
1474
|
+
fps: api.fps,
|
|
1475
|
+
maxDuration: api.max_duration,
|
|
1476
|
+
fileSize: api.file_size,
|
|
1477
|
+
maxSizeMb: api.max_size_mb,
|
|
1478
|
+
budgetMet: api.budget_met,
|
|
1479
|
+
qualityUsed: api.quality_used,
|
|
1480
|
+
attempts: api.attempts
|
|
1481
|
+
};
|
|
1482
|
+
}
|
|
1350
1483
|
async function getTaskStatus(taskId, config) {
|
|
1351
1484
|
const apiUrl = config.apiUrl || DEFAULT_CONFIG2.apiUrl;
|
|
1352
1485
|
const debug = config.debug || false;
|
|
@@ -1362,7 +1495,7 @@ async function getTaskStatus(taskId, config) {
|
|
|
1362
1495
|
if (debug) console.error(`[Browser] getTaskStatus error: ${response.status} - ${errorText}`);
|
|
1363
1496
|
throw new Error(`HTTP ${response.status}: ${errorText}`);
|
|
1364
1497
|
}
|
|
1365
|
-
const result = await response.json();
|
|
1498
|
+
const result = mapTaskResult(await response.json());
|
|
1366
1499
|
if (debug) console.log(`[Browser] Task status: ${result.status}`);
|
|
1367
1500
|
return result;
|
|
1368
1501
|
}
|
|
@@ -1385,42 +1518,44 @@ async function pollTaskUntilComplete(taskId, config, pollConfig = {}) {
|
|
|
1385
1518
|
throw new Error(`Task polling timeout after ${timeout}ms`);
|
|
1386
1519
|
}
|
|
1387
1520
|
function wrapTaskResponse(result, config) {
|
|
1521
|
+
const debugUrl = result.debugUrl ?? "";
|
|
1388
1522
|
const wrapped = {
|
|
1389
1523
|
...result,
|
|
1390
|
-
|
|
1391
|
-
|
|
1524
|
+
debugUrl,
|
|
1525
|
+
taskId: result.taskId || "",
|
|
1526
|
+
liveUrl: result.taskId ? generateLiveUrl(result.taskId, config) : debugUrl,
|
|
1392
1527
|
complete: async (pollConfig) => {
|
|
1393
|
-
if (result.
|
|
1394
|
-
return pollTaskUntilComplete(result.
|
|
1528
|
+
if (result.taskId) {
|
|
1529
|
+
return pollTaskUntilComplete(result.taskId, config, pollConfig);
|
|
1395
1530
|
}
|
|
1396
|
-
if (result.
|
|
1531
|
+
if (result.recordingId) {
|
|
1397
1532
|
const recording = await waitForRecording(
|
|
1398
|
-
result.
|
|
1533
|
+
result.recordingId,
|
|
1399
1534
|
config,
|
|
1400
1535
|
pollConfig
|
|
1401
1536
|
);
|
|
1402
1537
|
return {
|
|
1403
1538
|
...result,
|
|
1404
|
-
|
|
1539
|
+
recordingStatus: recording.status
|
|
1405
1540
|
};
|
|
1406
1541
|
}
|
|
1407
|
-
throw new Error("Cannot poll completion: no
|
|
1542
|
+
throw new Error("Cannot poll completion: no taskId or recordingId available");
|
|
1408
1543
|
},
|
|
1409
1544
|
// Add Steel live session helpers - either functional or error-throwing
|
|
1410
|
-
getLiveUrl:
|
|
1545
|
+
getLiveUrl: debugUrl ? (options) => buildLiveUrl(debugUrl, options) : () => {
|
|
1411
1546
|
throw new Error(
|
|
1412
1547
|
"Live sessions not available. Your backend must return a debugUrl in the response. Contact support@morphllm.com if you need help."
|
|
1413
1548
|
);
|
|
1414
1549
|
},
|
|
1415
|
-
getLiveIframe:
|
|
1550
|
+
getLiveIframe: debugUrl ? (optionsOrPreset) => {
|
|
1416
1551
|
const options = resolvePreset(optionsOrPreset);
|
|
1417
|
-
return buildLiveIframe(
|
|
1552
|
+
return buildLiveIframe(debugUrl, options);
|
|
1418
1553
|
} : () => {
|
|
1419
1554
|
throw new Error(
|
|
1420
1555
|
"Live sessions not available. Your backend must return a debugUrl in the response. Contact support@morphllm.com if you need help."
|
|
1421
1556
|
);
|
|
1422
1557
|
},
|
|
1423
|
-
getEmbedCode:
|
|
1558
|
+
getEmbedCode: debugUrl ? () => buildEmbedCode(debugUrl) : () => {
|
|
1424
1559
|
throw new Error(
|
|
1425
1560
|
"Live sessions not available. Your backend must return a debugUrl in the response. Contact support@morphllm.com if you need help."
|
|
1426
1561
|
);
|
|
@@ -1429,44 +1564,46 @@ function wrapTaskResponse(result, config) {
|
|
|
1429
1564
|
return wrapped;
|
|
1430
1565
|
}
|
|
1431
1566
|
function wrapTaskResponseWithSchema(result, config, schema) {
|
|
1567
|
+
const debugUrl = result.debugUrl ?? "";
|
|
1432
1568
|
const parsed = result.output ? parseStructuredTaskOutput(result, schema) : { ...result, parsed: null };
|
|
1433
1569
|
const wrapped = {
|
|
1434
1570
|
...parsed,
|
|
1435
|
-
|
|
1436
|
-
|
|
1571
|
+
debugUrl,
|
|
1572
|
+
taskId: result.taskId || "",
|
|
1573
|
+
liveUrl: result.taskId ? generateLiveUrl(result.taskId, config) : debugUrl,
|
|
1437
1574
|
complete: async (pollConfig) => {
|
|
1438
|
-
if (result.
|
|
1439
|
-
const finalResult = await pollTaskUntilComplete(result.
|
|
1575
|
+
if (result.taskId) {
|
|
1576
|
+
const finalResult = await pollTaskUntilComplete(result.taskId, config, pollConfig);
|
|
1440
1577
|
return parseStructuredTaskOutput(finalResult, schema);
|
|
1441
1578
|
}
|
|
1442
|
-
if (result.
|
|
1579
|
+
if (result.recordingId) {
|
|
1443
1580
|
const recording = await waitForRecording(
|
|
1444
|
-
result.
|
|
1581
|
+
result.recordingId,
|
|
1445
1582
|
config,
|
|
1446
1583
|
pollConfig
|
|
1447
1584
|
);
|
|
1448
1585
|
return {
|
|
1449
1586
|
...parsed,
|
|
1450
|
-
|
|
1587
|
+
recordingStatus: recording.status
|
|
1451
1588
|
};
|
|
1452
1589
|
}
|
|
1453
|
-
throw new Error("Cannot poll completion: no
|
|
1590
|
+
throw new Error("Cannot poll completion: no taskId or recordingId available");
|
|
1454
1591
|
},
|
|
1455
1592
|
// Add Steel live session helpers - either functional or error-throwing
|
|
1456
|
-
getLiveUrl:
|
|
1593
|
+
getLiveUrl: debugUrl ? (options) => buildLiveUrl(debugUrl, options) : () => {
|
|
1457
1594
|
throw new Error(
|
|
1458
1595
|
"Live sessions not available. Your backend must return a debugUrl in the response. Contact support@morphllm.com if you need help enabling live sessions. "
|
|
1459
1596
|
);
|
|
1460
1597
|
},
|
|
1461
|
-
getLiveIframe:
|
|
1598
|
+
getLiveIframe: debugUrl ? (optionsOrPreset) => {
|
|
1462
1599
|
const options = resolvePreset(optionsOrPreset);
|
|
1463
|
-
return buildLiveIframe(
|
|
1600
|
+
return buildLiveIframe(debugUrl, options);
|
|
1464
1601
|
} : () => {
|
|
1465
1602
|
throw new Error(
|
|
1466
1603
|
"Live sessions not available. Your backend must return a debugUrl in the response. Contact support@morphllm.com if you need help enabling live sessions."
|
|
1467
1604
|
);
|
|
1468
1605
|
},
|
|
1469
|
-
getEmbedCode:
|
|
1606
|
+
getEmbedCode: debugUrl ? () => buildEmbedCode(debugUrl) : () => {
|
|
1470
1607
|
throw new Error(
|
|
1471
1608
|
"Live sessions not available. Your backend must return a debugUrl in the response. Contact support@morphllm.com if you need help enabling live sessions."
|
|
1472
1609
|
);
|
|
@@ -1481,10 +1618,11 @@ async function getWebp(recordingId, config = {}, options = {}) {
|
|
|
1481
1618
|
throw new Error("API key required for getWebp");
|
|
1482
1619
|
}
|
|
1483
1620
|
const params = new URLSearchParams();
|
|
1484
|
-
if (options.
|
|
1621
|
+
if (options.maxDuration !== void 0) params.set("max_duration", String(options.maxDuration));
|
|
1485
1622
|
if (options.fps !== void 0) params.set("fps", String(options.fps));
|
|
1486
1623
|
if (options.width !== void 0) params.set("width", String(options.width));
|
|
1487
1624
|
if (options.quality !== void 0) params.set("quality", String(options.quality));
|
|
1625
|
+
if (options.maxSizeMb !== void 0) params.set("max_size_mb", String(options.maxSizeMb));
|
|
1488
1626
|
const url = `${apiUrl}/recordings/${recordingId}/webp${params.toString() ? "?" + params.toString() : ""}`;
|
|
1489
1627
|
if (debug) console.log(`[Browser] getWebp: ${url}`);
|
|
1490
1628
|
const response = await fetch(url, {
|
|
@@ -1496,8 +1634,8 @@ async function getWebp(recordingId, config = {}, options = {}) {
|
|
|
1496
1634
|
if (debug) console.error(`[Browser] getWebp error: ${response.status} - ${errorText}`);
|
|
1497
1635
|
throw new Error(`HTTP ${response.status}: ${errorText}`);
|
|
1498
1636
|
}
|
|
1499
|
-
const result = await response.json();
|
|
1500
|
-
if (debug) console.log(`[Browser] WebP ready: ${result.
|
|
1637
|
+
const result = mapWebpResponse(await response.json());
|
|
1638
|
+
if (debug) console.log(`[Browser] WebP ready: ${result.webpUrl} (cached: ${result.cached})`);
|
|
1501
1639
|
return result;
|
|
1502
1640
|
}
|
|
1503
1641
|
async function checkHealth(config = {}) {
|
|
@@ -2393,42 +2531,36 @@ function enforceContextLimit(messages, maxChars = AGENT_CONFIG.MAX_CONTEXT_CHARS
|
|
|
2393
2531
|
}
|
|
2394
2532
|
|
|
2395
2533
|
// tools/warp_grep/agent/runner.ts
|
|
2534
|
+
var import_openai = __toESM(require("openai"), 1);
|
|
2396
2535
|
var import_path3 = __toESM(require("path"), 1);
|
|
2397
2536
|
var parser = new LLMResponseParser();
|
|
2398
2537
|
var DEFAULT_API_URL2 = "https://api.morphllm.com";
|
|
2399
2538
|
async function callModel(messages, model, options = {}) {
|
|
2400
2539
|
const baseUrl = options.morphApiUrl || DEFAULT_API_URL2;
|
|
2401
2540
|
const apiKey = options.morphApiKey || process.env.MORPH_API_KEY || "";
|
|
2402
|
-
const fetchPromise = fetchWithRetry(
|
|
2403
|
-
`${baseUrl}/v1/chat/completions`,
|
|
2404
|
-
{
|
|
2405
|
-
method: "POST",
|
|
2406
|
-
headers: {
|
|
2407
|
-
"Content-Type": "application/json",
|
|
2408
|
-
Authorization: `Bearer ${apiKey}`
|
|
2409
|
-
},
|
|
2410
|
-
body: JSON.stringify({
|
|
2411
|
-
model,
|
|
2412
|
-
temperature: 0,
|
|
2413
|
-
max_tokens: 1024,
|
|
2414
|
-
repetition_penalty: 1.05,
|
|
2415
|
-
messages
|
|
2416
|
-
})
|
|
2417
|
-
},
|
|
2418
|
-
options.retryConfig
|
|
2419
|
-
);
|
|
2420
2541
|
const timeoutMs = options.timeout ?? AGENT_CONFIG.TIMEOUT_MS;
|
|
2421
|
-
const
|
|
2422
|
-
|
|
2423
|
-
|
|
2542
|
+
const client = new import_openai.default({
|
|
2543
|
+
apiKey,
|
|
2544
|
+
baseURL: `${baseUrl}/v1`,
|
|
2545
|
+
maxRetries: options.retryConfig?.maxRetries,
|
|
2546
|
+
timeout: timeoutMs
|
|
2547
|
+
});
|
|
2548
|
+
let data;
|
|
2549
|
+
try {
|
|
2550
|
+
data = await client.chat.completions.create({
|
|
2551
|
+
model,
|
|
2552
|
+
temperature: 0,
|
|
2553
|
+
max_tokens: 1024,
|
|
2554
|
+
messages
|
|
2555
|
+
});
|
|
2556
|
+
} catch (error) {
|
|
2557
|
+
if (error instanceof import_openai.default.APIError && error.status === 404) {
|
|
2424
2558
|
throw new Error(
|
|
2425
2559
|
"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"
|
|
2426
2560
|
);
|
|
2427
2561
|
}
|
|
2428
|
-
|
|
2429
|
-
throw new Error(`morph-warp-grep error ${resp.status}: ${t}`);
|
|
2562
|
+
throw error;
|
|
2430
2563
|
}
|
|
2431
|
-
const data = await resp.json();
|
|
2432
2564
|
const content = data?.choices?.[0]?.message?.content;
|
|
2433
2565
|
if (!content || typeof content !== "string") {
|
|
2434
2566
|
throw new Error("Invalid response from model");
|
|
@@ -4384,13 +4516,6 @@ function formatResult3(result) {
|
|
|
4384
4516
|
changes.linesRemoved && `-${changes.linesRemoved} lines`,
|
|
4385
4517
|
changes.linesModified && `~${changes.linesModified} lines modified`
|
|
4386
4518
|
].filter(Boolean).join(", ");
|
|
4387
|
-
if (result.udiff) {
|
|
4388
|
-
return `Successfully applied changes to ${result.filepath}:
|
|
4389
|
-
|
|
4390
|
-
${result.udiff}
|
|
4391
|
-
|
|
4392
|
-
Summary: ${summary}`;
|
|
4393
|
-
}
|
|
4394
4519
|
return `Successfully applied changes to ${result.filepath}. ${summary}`;
|
|
4395
4520
|
}
|
|
4396
4521
|
function createEditFileTool(config = {}) {
|
|
@@ -4591,13 +4716,6 @@ function formatResult5(result) {
|
|
|
4591
4716
|
changes.linesRemoved && `-${changes.linesRemoved} lines`,
|
|
4592
4717
|
changes.linesModified && `~${changes.linesModified} lines modified`
|
|
4593
4718
|
].filter(Boolean).join(", ");
|
|
4594
|
-
if (result.udiff) {
|
|
4595
|
-
return `Successfully applied changes to ${result.filepath}:
|
|
4596
|
-
|
|
4597
|
-
${result.udiff}
|
|
4598
|
-
|
|
4599
|
-
Summary: ${summary}`;
|
|
4600
|
-
}
|
|
4601
4719
|
return `Successfully applied changes to ${result.filepath}. ${summary}`;
|
|
4602
4720
|
}
|
|
4603
4721
|
function createEditFileTool2(config = {}) {
|