@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/index.cjs
CHANGED
|
@@ -454,7 +454,8 @@ function buildLiveUrl(debugUrl, options = {}) {
|
|
|
454
454
|
"debugUrl is required. Ensure your backend returns debugUrl in the task response. Contact support@morphllm.com if you need help."
|
|
455
455
|
);
|
|
456
456
|
}
|
|
457
|
-
const
|
|
457
|
+
const normalized = normalizeLiveUrl(debugUrl);
|
|
458
|
+
const url = new URL(normalized);
|
|
458
459
|
if (options.interactive !== void 0) {
|
|
459
460
|
url.searchParams.set("interactive", String(options.interactive));
|
|
460
461
|
}
|
|
@@ -472,6 +473,29 @@ function buildLiveUrl(debugUrl, options = {}) {
|
|
|
472
473
|
}
|
|
473
474
|
return url.toString();
|
|
474
475
|
}
|
|
476
|
+
function normalizeLiveUrl(debugUrl) {
|
|
477
|
+
const trimmed = debugUrl.trim();
|
|
478
|
+
if (!trimmed) {
|
|
479
|
+
return trimmed;
|
|
480
|
+
}
|
|
481
|
+
if (trimmed.startsWith("wss://") || trimmed.startsWith("ws://")) {
|
|
482
|
+
return `https://live.browser-use.com?wss=${encodeURIComponent(trimmed)}`;
|
|
483
|
+
}
|
|
484
|
+
let url;
|
|
485
|
+
try {
|
|
486
|
+
url = new URL(trimmed);
|
|
487
|
+
} catch {
|
|
488
|
+
return trimmed;
|
|
489
|
+
}
|
|
490
|
+
if (url.protocol === "wss:" || url.protocol === "ws:") {
|
|
491
|
+
return `https://live.browser-use.com?wss=${encodeURIComponent(trimmed)}`;
|
|
492
|
+
}
|
|
493
|
+
const wssParam = url.searchParams.get("wss");
|
|
494
|
+
if (wssParam && (wssParam.startsWith("wss://") || wssParam.startsWith("ws://"))) {
|
|
495
|
+
url.searchParams.set("wss", wssParam);
|
|
496
|
+
}
|
|
497
|
+
return url.toString();
|
|
498
|
+
}
|
|
475
499
|
function buildLiveIframe(debugUrl, options = {}) {
|
|
476
500
|
const {
|
|
477
501
|
width = "100%",
|
|
@@ -702,7 +726,7 @@ function transformCreateInput(input) {
|
|
|
702
726
|
function transformSession(api) {
|
|
703
727
|
return {
|
|
704
728
|
sessionId: api.session_id,
|
|
705
|
-
debugUrl: api.debug_url ||
|
|
729
|
+
debugUrl: api.debug_url || ""
|
|
706
730
|
};
|
|
707
731
|
}
|
|
708
732
|
function transformSaveInput(input) {
|
|
@@ -727,22 +751,24 @@ var ProfilesClient = class {
|
|
|
727
751
|
this.config = config;
|
|
728
752
|
}
|
|
729
753
|
/**
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
754
|
+
* Create a new browser profile and immediately start a live session.
|
|
755
|
+
*
|
|
756
|
+
* @param input - Profile creation parameters
|
|
757
|
+
* @returns Profile setup handle with live URL + save()
|
|
758
|
+
* @throws {MorphValidationError} If input validation fails
|
|
759
|
+
* @throws {MorphProfileLimitError} If profile limit is exceeded
|
|
760
|
+
* @throws {MorphAuthenticationError} If API key is missing or invalid
|
|
761
|
+
*
|
|
762
|
+
* @example
|
|
763
|
+
* ```typescript
|
|
764
|
+
* const setup = await morph.browser.profiles.createProfile({
|
|
765
|
+
* name: 'LinkedIn Production',
|
|
766
|
+
* repoId: 'owner/repo'
|
|
767
|
+
* });
|
|
768
|
+
* console.log(setup.session.debugUrl);
|
|
769
|
+
* await setup.save();
|
|
770
|
+
* ```
|
|
771
|
+
*/
|
|
746
772
|
async createProfile(input) {
|
|
747
773
|
return createProfile(input, this.config);
|
|
748
774
|
}
|
|
@@ -758,7 +784,7 @@ var ProfilesClient = class {
|
|
|
758
784
|
* const allProfiles = await morph.browser.profiles.listProfiles();
|
|
759
785
|
*
|
|
760
786
|
* // List profiles for a specific repo
|
|
761
|
-
* const repoProfiles = await morph.browser.profiles.listProfiles('repo
|
|
787
|
+
* const repoProfiles = await morph.browser.profiles.listProfiles('owner/repo');
|
|
762
788
|
* ```
|
|
763
789
|
*/
|
|
764
790
|
async listProfiles(repoId) {
|
|
@@ -782,14 +808,13 @@ var ProfilesClient = class {
|
|
|
782
808
|
return getProfile(id, this.config);
|
|
783
809
|
}
|
|
784
810
|
/**
|
|
785
|
-
* Update a profile
|
|
811
|
+
* Update a profile by opening a live session (no rename).
|
|
786
812
|
*
|
|
787
813
|
* @param id - Profile ID
|
|
788
|
-
* @
|
|
789
|
-
* @returns Updated profile
|
|
814
|
+
* @returns Profile setup handle with live URL + save()
|
|
790
815
|
*/
|
|
791
|
-
async updateProfile(id
|
|
792
|
-
return updateProfile(id,
|
|
816
|
+
async updateProfile(id) {
|
|
817
|
+
return updateProfile(id, this.config);
|
|
793
818
|
}
|
|
794
819
|
/**
|
|
795
820
|
* Delete a profile.
|
|
@@ -833,6 +858,14 @@ var ProfilesClient = class {
|
|
|
833
858
|
async saveSession(sessionId, profileId) {
|
|
834
859
|
return saveProfileSession({ sessionId, profileId }, this.config);
|
|
835
860
|
}
|
|
861
|
+
/**
|
|
862
|
+
* List available repo IDs (discovery).
|
|
863
|
+
*
|
|
864
|
+
* @returns Repo summaries with profile counts
|
|
865
|
+
*/
|
|
866
|
+
async listRepos() {
|
|
867
|
+
return listRepos(this.config);
|
|
868
|
+
}
|
|
836
869
|
/**
|
|
837
870
|
* Get the presigned URL for a profile's state.
|
|
838
871
|
*
|
|
@@ -891,7 +924,9 @@ async function createProfile(input, config = {}) {
|
|
|
891
924
|
throw parseAPIError(response.status, errorText, requestId);
|
|
892
925
|
}
|
|
893
926
|
const apiProfile = await response.json();
|
|
894
|
-
|
|
927
|
+
const profile = transformProfile(apiProfile);
|
|
928
|
+
const session = await startProfileSession(config, { profileId: profile.id });
|
|
929
|
+
return buildProfileSetup(profile, session, config);
|
|
895
930
|
}
|
|
896
931
|
async function listProfiles(config = {}, repoId) {
|
|
897
932
|
const apiUrl = config.apiUrl || DEFAULT_API_URL;
|
|
@@ -932,37 +967,11 @@ async function getProfile(id, config = {}) {
|
|
|
932
967
|
delete: () => deleteProfile(id, config)
|
|
933
968
|
};
|
|
934
969
|
}
|
|
935
|
-
async function updateProfile(id,
|
|
970
|
+
async function updateProfile(id, config = {}) {
|
|
936
971
|
validateId(id, "id");
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
}
|
|
941
|
-
if (input.name.trim().length === 0) {
|
|
942
|
-
throw new MorphValidationError("name cannot be empty", "name");
|
|
943
|
-
}
|
|
944
|
-
if (input.name.length > 100) {
|
|
945
|
-
throw new MorphValidationError("name must be 100 characters or less", "name");
|
|
946
|
-
}
|
|
947
|
-
}
|
|
948
|
-
const apiUrl = config.apiUrl || DEFAULT_API_URL;
|
|
949
|
-
const headers = buildHeaders(config);
|
|
950
|
-
const response = await fetchWithRetry(
|
|
951
|
-
`${apiUrl}/profiles/${encodeURIComponent(id)}`,
|
|
952
|
-
{
|
|
953
|
-
method: "PATCH",
|
|
954
|
-
headers,
|
|
955
|
-
body: JSON.stringify(input)
|
|
956
|
-
},
|
|
957
|
-
config.retryConfig
|
|
958
|
-
);
|
|
959
|
-
if (!response.ok) {
|
|
960
|
-
const errorText = await response.text().catch(() => response.statusText);
|
|
961
|
-
const requestId = response.headers.get("x-request-id") || void 0;
|
|
962
|
-
throw parseAPIError(response.status, errorText, requestId);
|
|
963
|
-
}
|
|
964
|
-
const apiProfile = await response.json();
|
|
965
|
-
return transformProfile(apiProfile);
|
|
972
|
+
const profile = await fetchProfile(id, config);
|
|
973
|
+
const session = await startProfileSession(config, { profileId: profile.id });
|
|
974
|
+
return buildProfileSetup(profile, session, config);
|
|
966
975
|
}
|
|
967
976
|
async function deleteProfile(id, config = {}) {
|
|
968
977
|
validateId(id, "id");
|
|
@@ -1025,6 +1034,27 @@ async function saveProfileSession(input, config = {}) {
|
|
|
1025
1034
|
const apiProfile = await response.json();
|
|
1026
1035
|
return transformProfile(apiProfile);
|
|
1027
1036
|
}
|
|
1037
|
+
async function listRepos(config = {}) {
|
|
1038
|
+
const apiUrl = config.apiUrl || DEFAULT_API_URL;
|
|
1039
|
+
const headers = buildHeaders(config);
|
|
1040
|
+
const response = await fetchWithRetry(
|
|
1041
|
+
`${apiUrl}/repos`,
|
|
1042
|
+
{ method: "GET", headers },
|
|
1043
|
+
config.retryConfig
|
|
1044
|
+
);
|
|
1045
|
+
if (!response.ok) {
|
|
1046
|
+
const errorText = await response.text().catch(() => response.statusText);
|
|
1047
|
+
const requestId = response.headers.get("x-request-id") || void 0;
|
|
1048
|
+
throw parseAPIError(response.status, errorText, requestId);
|
|
1049
|
+
}
|
|
1050
|
+
const data = await response.json();
|
|
1051
|
+
const repos = Array.isArray(data?.repos) ? data.repos : [];
|
|
1052
|
+
return repos.map((repo) => ({
|
|
1053
|
+
repoId: repo.repo_id,
|
|
1054
|
+
repoFullName: repo.repo_full_name,
|
|
1055
|
+
profileCount: repo.profile_count ?? 0
|
|
1056
|
+
}));
|
|
1057
|
+
}
|
|
1028
1058
|
async function getProfileState(profileId, config = {}) {
|
|
1029
1059
|
validateId(profileId, "profileId");
|
|
1030
1060
|
const apiUrl = config.apiUrl || DEFAULT_API_URL;
|
|
@@ -1049,6 +1079,29 @@ function buildHeaders(config) {
|
|
|
1049
1079
|
}
|
|
1050
1080
|
return headers;
|
|
1051
1081
|
}
|
|
1082
|
+
async function fetchProfile(id, config) {
|
|
1083
|
+
const apiUrl = config.apiUrl || DEFAULT_API_URL;
|
|
1084
|
+
const headers = buildHeaders(config);
|
|
1085
|
+
const response = await fetchWithRetry(
|
|
1086
|
+
`${apiUrl}/profiles/${encodeURIComponent(id)}`,
|
|
1087
|
+
{ method: "GET", headers },
|
|
1088
|
+
config.retryConfig
|
|
1089
|
+
);
|
|
1090
|
+
if (!response.ok) {
|
|
1091
|
+
const errorText = await response.text().catch(() => response.statusText);
|
|
1092
|
+
const requestId = response.headers.get("x-request-id") || void 0;
|
|
1093
|
+
throw parseAPIError(response.status, errorText, requestId);
|
|
1094
|
+
}
|
|
1095
|
+
const apiProfile = await response.json();
|
|
1096
|
+
return transformProfile(apiProfile);
|
|
1097
|
+
}
|
|
1098
|
+
function buildProfileSetup(profile, session, config) {
|
|
1099
|
+
return {
|
|
1100
|
+
profile,
|
|
1101
|
+
session,
|
|
1102
|
+
save: () => saveProfileSession({ sessionId: session.sessionId, profileId: profile.id }, config)
|
|
1103
|
+
};
|
|
1104
|
+
}
|
|
1052
1105
|
|
|
1053
1106
|
// tools/browser/core.ts
|
|
1054
1107
|
var DEFAULT_CONFIG2 = {
|
|
@@ -1091,20 +1144,21 @@ var BrowserClient = class {
|
|
|
1091
1144
|
body: JSON.stringify({
|
|
1092
1145
|
task: input.task,
|
|
1093
1146
|
url: input.url,
|
|
1094
|
-
max_steps: input.
|
|
1147
|
+
max_steps: input.maxSteps ?? 10,
|
|
1095
1148
|
model: input.model ?? "morph-computer-use-v0",
|
|
1096
|
-
viewport_width: input.
|
|
1097
|
-
viewport_height: input.
|
|
1098
|
-
external_id: input.
|
|
1099
|
-
repo_id: input.
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1149
|
+
viewport_width: input.viewportWidth ?? 1280,
|
|
1150
|
+
viewport_height: input.viewportHeight ?? 720,
|
|
1151
|
+
external_id: input.externalId,
|
|
1152
|
+
repo_id: input.repoId,
|
|
1153
|
+
repo_full_name: input.repoFullName,
|
|
1154
|
+
commit_id: input.commitId,
|
|
1155
|
+
record_video: input.recordVideo ?? false,
|
|
1156
|
+
video_width: input.videoWidth ?? input.viewportWidth ?? 1280,
|
|
1157
|
+
video_height: input.videoHeight ?? input.viewportHeight ?? 720,
|
|
1158
|
+
allow_resizing: input.allowResizing ?? false,
|
|
1105
1159
|
structured_output: "schema" in input ? stringifyStructuredOutput(input.schema) : void 0,
|
|
1106
1160
|
auth: input.auth,
|
|
1107
|
-
profile_id: input.
|
|
1161
|
+
profile_id: input.profileId
|
|
1108
1162
|
})
|
|
1109
1163
|
});
|
|
1110
1164
|
if (!response.ok) {
|
|
@@ -1112,9 +1166,10 @@ var BrowserClient = class {
|
|
|
1112
1166
|
if (debug) console.error(`[Browser] Error: ${response.status} - ${errorText}`);
|
|
1113
1167
|
throw new Error(`HTTP ${response.status}: ${errorText}`);
|
|
1114
1168
|
}
|
|
1115
|
-
const result = await response.json();
|
|
1169
|
+
const result = mapTaskResult(await response.json());
|
|
1116
1170
|
if (debug) {
|
|
1117
|
-
|
|
1171
|
+
const debugUrl = result.debugUrl;
|
|
1172
|
+
console.log(`[Browser] \u2705 Task created: recordingId=${result.recordingId ?? "none"} debugUrl=${debugUrl ? "available" : "none"}`);
|
|
1118
1173
|
}
|
|
1119
1174
|
if ("schema" in input) {
|
|
1120
1175
|
return wrapTaskResponseWithSchema(result, this.config, input.schema);
|
|
@@ -1169,15 +1224,15 @@ async function executeBrowserTask(input, config = {}) {
|
|
|
1169
1224
|
error: 'Task description is required. Example: "Go to example.com and click the login button"'
|
|
1170
1225
|
};
|
|
1171
1226
|
}
|
|
1172
|
-
if (input.
|
|
1227
|
+
if (input.maxSteps !== void 0 && (input.maxSteps < 1 || input.maxSteps > 50)) {
|
|
1173
1228
|
return {
|
|
1174
1229
|
success: false,
|
|
1175
|
-
error: "
|
|
1230
|
+
error: "maxSteps must be between 1 and 50. Use more steps for complex multi-page flows."
|
|
1176
1231
|
};
|
|
1177
1232
|
}
|
|
1178
1233
|
if (debug) {
|
|
1179
|
-
console.log(`[Browser] Task: "${input.task.slice(0, 60)}..." url=${input.url || "none"} maxSteps=${input.
|
|
1180
|
-
console.log(`[Browser] Recording: ${input.
|
|
1234
|
+
console.log(`[Browser] Task: "${input.task.slice(0, 60)}..." url=${input.url || "none"} maxSteps=${input.maxSteps ?? 10}`);
|
|
1235
|
+
console.log(`[Browser] Recording: ${input.recordVideo ? "yes" : "no"} | Calling ${apiUrl}/browser-task`);
|
|
1181
1236
|
}
|
|
1182
1237
|
const startTime = Date.now();
|
|
1183
1238
|
try {
|
|
@@ -1191,20 +1246,20 @@ async function executeBrowserTask(input, config = {}) {
|
|
|
1191
1246
|
body: JSON.stringify({
|
|
1192
1247
|
task: input.task,
|
|
1193
1248
|
url: input.url,
|
|
1194
|
-
max_steps: input.
|
|
1249
|
+
max_steps: input.maxSteps ?? 10,
|
|
1195
1250
|
model: input.model ?? "morph-computer-use-v0",
|
|
1196
|
-
viewport_width: input.
|
|
1197
|
-
viewport_height: input.
|
|
1198
|
-
external_id: input.
|
|
1199
|
-
repo_id: input.
|
|
1200
|
-
commit_id: input.
|
|
1201
|
-
record_video: input.
|
|
1202
|
-
video_width: input.
|
|
1203
|
-
video_height: input.
|
|
1204
|
-
allow_resizing: input.
|
|
1205
|
-
structured_output: input.
|
|
1251
|
+
viewport_width: input.viewportWidth ?? 1280,
|
|
1252
|
+
viewport_height: input.viewportHeight ?? 720,
|
|
1253
|
+
external_id: input.externalId,
|
|
1254
|
+
repo_id: input.repoId,
|
|
1255
|
+
commit_id: input.commitId,
|
|
1256
|
+
record_video: input.recordVideo ?? false,
|
|
1257
|
+
video_width: input.videoWidth ?? input.viewportWidth ?? 1280,
|
|
1258
|
+
video_height: input.videoHeight ?? input.viewportHeight ?? 720,
|
|
1259
|
+
allow_resizing: input.allowResizing ?? false,
|
|
1260
|
+
structured_output: input.structuredOutput,
|
|
1206
1261
|
auth: input.auth,
|
|
1207
|
-
profile_id: input.
|
|
1262
|
+
profile_id: input.profileId
|
|
1208
1263
|
})
|
|
1209
1264
|
},
|
|
1210
1265
|
config.retryConfig
|
|
@@ -1212,17 +1267,17 @@ async function executeBrowserTask(input, config = {}) {
|
|
|
1212
1267
|
const response = await withTimeout(
|
|
1213
1268
|
fetchPromise,
|
|
1214
1269
|
timeout,
|
|
1215
|
-
`Browser task timed out after ${timeout}ms. Consider increasing timeout or reducing
|
|
1270
|
+
`Browser task timed out after ${timeout}ms. Consider increasing timeout or reducing maxSteps.`
|
|
1216
1271
|
);
|
|
1217
1272
|
if (!response.ok) {
|
|
1218
1273
|
const errorText = await response.text().catch(() => response.statusText);
|
|
1219
1274
|
if (debug) console.error(`[Browser] Error: ${response.status} - ${errorText}`);
|
|
1220
1275
|
throw new Error(`HTTP ${response.status}: ${errorText}`);
|
|
1221
1276
|
}
|
|
1222
|
-
const result = await response.json();
|
|
1277
|
+
const result = mapTaskResult(await response.json());
|
|
1223
1278
|
const elapsed = Date.now() - startTime;
|
|
1224
1279
|
if (debug) {
|
|
1225
|
-
console.log(`[Browser] \u2705 ${result.success ? "Success" : "Failed"} in ${elapsed}ms | steps=${result.
|
|
1280
|
+
console.log(`[Browser] \u2705 ${result.success ? "Success" : "Failed"} in ${elapsed}ms | steps=${result.stepsTaken ?? 0} recordingId=${result.recordingId ?? "none"}`);
|
|
1226
1281
|
}
|
|
1227
1282
|
return result;
|
|
1228
1283
|
} catch (error) {
|
|
@@ -1260,7 +1315,7 @@ async function getRecording(recordingId, config = {}) {
|
|
|
1260
1315
|
if (debug) console.error(`[Browser] getRecording error: ${response.status} - ${errorText}`);
|
|
1261
1316
|
throw new Error(`HTTP ${response.status}: ${errorText}`);
|
|
1262
1317
|
}
|
|
1263
|
-
const data = await response.json();
|
|
1318
|
+
const data = mapRecordingStatus(await response.json());
|
|
1264
1319
|
if (debug) console.log(`[Browser] Recording status: ${data.status}`);
|
|
1265
1320
|
return {
|
|
1266
1321
|
...data,
|
|
@@ -1283,10 +1338,10 @@ async function waitForRecording(recordingId, config = {}, options = {}) {
|
|
|
1283
1338
|
}
|
|
1284
1339
|
async function executeWithRecording(input, config = {}) {
|
|
1285
1340
|
const taskResult = await executeBrowserTask(input, config);
|
|
1286
|
-
if (taskResult.
|
|
1341
|
+
if (taskResult.recordingId) {
|
|
1287
1342
|
try {
|
|
1288
1343
|
const recording = await waitForRecording(
|
|
1289
|
-
taskResult.
|
|
1344
|
+
taskResult.recordingId,
|
|
1290
1345
|
config,
|
|
1291
1346
|
{ timeout: 6e4, pollInterval: 2e3 }
|
|
1292
1347
|
);
|
|
@@ -1296,12 +1351,12 @@ async function executeWithRecording(input, config = {}) {
|
|
|
1296
1351
|
};
|
|
1297
1352
|
} catch (error) {
|
|
1298
1353
|
const errorRecording = {
|
|
1299
|
-
id: taskResult.
|
|
1354
|
+
id: taskResult.recordingId,
|
|
1300
1355
|
status: "ERROR",
|
|
1301
1356
|
error: error instanceof Error ? error.message : String(error),
|
|
1302
|
-
|
|
1303
|
-
getWebp: (options) => getWebp(taskResult.
|
|
1304
|
-
getErrors: () => getErrors(taskResult.
|
|
1357
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1358
|
+
getWebp: (options) => getWebp(taskResult.recordingId, config, options),
|
|
1359
|
+
getErrors: () => getErrors(taskResult.recordingId, config)
|
|
1305
1360
|
};
|
|
1306
1361
|
return {
|
|
1307
1362
|
...taskResult,
|
|
@@ -1327,8 +1382,8 @@ async function getErrors(recordingId, config = {}) {
|
|
|
1327
1382
|
if (debug) console.error(`[Browser] getErrors error: ${response.status} - ${errorText}`);
|
|
1328
1383
|
throw new Error(`HTTP ${response.status}: ${errorText}`);
|
|
1329
1384
|
}
|
|
1330
|
-
const errors = await response.json();
|
|
1331
|
-
if (debug) console.log(`[Browser] Found ${errors.
|
|
1385
|
+
const errors = mapErrorsResponse(await response.json());
|
|
1386
|
+
if (debug) console.log(`[Browser] Found ${errors.totalErrors} errors`);
|
|
1332
1387
|
return errors;
|
|
1333
1388
|
}
|
|
1334
1389
|
function stringifyStructuredOutput(schema) {
|
|
@@ -1361,6 +1416,84 @@ function parseStructuredTaskOutput(result, schema) {
|
|
|
1361
1416
|
throw error;
|
|
1362
1417
|
}
|
|
1363
1418
|
}
|
|
1419
|
+
function mapTaskResult(api) {
|
|
1420
|
+
if (!api || typeof api !== "object") {
|
|
1421
|
+
return api;
|
|
1422
|
+
}
|
|
1423
|
+
return {
|
|
1424
|
+
success: api.success,
|
|
1425
|
+
result: api.result,
|
|
1426
|
+
error: api.error,
|
|
1427
|
+
stepsTaken: api.steps_taken,
|
|
1428
|
+
executionTimeMs: api.execution_time_ms,
|
|
1429
|
+
urls: api.urls,
|
|
1430
|
+
actionNames: api.action_names,
|
|
1431
|
+
errors: api.errors,
|
|
1432
|
+
modelActions: api.model_actions,
|
|
1433
|
+
isDone: api.is_done,
|
|
1434
|
+
actionHistory: api.action_history,
|
|
1435
|
+
actionResults: api.action_results,
|
|
1436
|
+
hasErrors: api.has_errors,
|
|
1437
|
+
numberOfSteps: api.number_of_steps,
|
|
1438
|
+
judgement: api.judgement,
|
|
1439
|
+
isValidated: api.is_validated,
|
|
1440
|
+
replayId: api.replay_id,
|
|
1441
|
+
replayUrl: api.replay_url,
|
|
1442
|
+
recordingId: api.recording_id,
|
|
1443
|
+
recordingStatus: api.recording_status,
|
|
1444
|
+
taskId: api.task_id,
|
|
1445
|
+
status: api.status,
|
|
1446
|
+
output: api.output,
|
|
1447
|
+
debugUrl: api.debug_url
|
|
1448
|
+
};
|
|
1449
|
+
}
|
|
1450
|
+
function mapRecordingStatus(api) {
|
|
1451
|
+
return {
|
|
1452
|
+
id: api.id,
|
|
1453
|
+
status: api.status,
|
|
1454
|
+
replayUrl: api.replay_url,
|
|
1455
|
+
networkUrl: api.network_url,
|
|
1456
|
+
consoleUrl: api.console_url,
|
|
1457
|
+
videoUrl: api.video_url,
|
|
1458
|
+
totalEvents: api.total_events,
|
|
1459
|
+
fileSize: api.file_size,
|
|
1460
|
+
duration: api.duration,
|
|
1461
|
+
error: api.error,
|
|
1462
|
+
createdAt: api.created_at
|
|
1463
|
+
};
|
|
1464
|
+
}
|
|
1465
|
+
function mapBrowserError(api) {
|
|
1466
|
+
return {
|
|
1467
|
+
type: api.type,
|
|
1468
|
+
message: api.message,
|
|
1469
|
+
url: api.url,
|
|
1470
|
+
timestamp: api.timestamp,
|
|
1471
|
+
screenshotUrl: api.screenshot_url,
|
|
1472
|
+
capturedAt: api.captured_at,
|
|
1473
|
+
status: api.status
|
|
1474
|
+
};
|
|
1475
|
+
}
|
|
1476
|
+
function mapErrorsResponse(api) {
|
|
1477
|
+
return {
|
|
1478
|
+
recordingId: api.recording_id,
|
|
1479
|
+
totalErrors: api.total_errors,
|
|
1480
|
+
errors: Array.isArray(api.errors) ? api.errors.map(mapBrowserError) : []
|
|
1481
|
+
};
|
|
1482
|
+
}
|
|
1483
|
+
function mapWebpResponse(api) {
|
|
1484
|
+
return {
|
|
1485
|
+
webpUrl: api.webp_url,
|
|
1486
|
+
cached: api.cached,
|
|
1487
|
+
width: api.width,
|
|
1488
|
+
fps: api.fps,
|
|
1489
|
+
maxDuration: api.max_duration,
|
|
1490
|
+
fileSize: api.file_size,
|
|
1491
|
+
maxSizeMb: api.max_size_mb,
|
|
1492
|
+
budgetMet: api.budget_met,
|
|
1493
|
+
qualityUsed: api.quality_used,
|
|
1494
|
+
attempts: api.attempts
|
|
1495
|
+
};
|
|
1496
|
+
}
|
|
1364
1497
|
async function getTaskStatus(taskId, config) {
|
|
1365
1498
|
const apiUrl = config.apiUrl || DEFAULT_CONFIG2.apiUrl;
|
|
1366
1499
|
const debug = config.debug || false;
|
|
@@ -1376,7 +1509,7 @@ async function getTaskStatus(taskId, config) {
|
|
|
1376
1509
|
if (debug) console.error(`[Browser] getTaskStatus error: ${response.status} - ${errorText}`);
|
|
1377
1510
|
throw new Error(`HTTP ${response.status}: ${errorText}`);
|
|
1378
1511
|
}
|
|
1379
|
-
const result = await response.json();
|
|
1512
|
+
const result = mapTaskResult(await response.json());
|
|
1380
1513
|
if (debug) console.log(`[Browser] Task status: ${result.status}`);
|
|
1381
1514
|
return result;
|
|
1382
1515
|
}
|
|
@@ -1399,42 +1532,44 @@ async function pollTaskUntilComplete(taskId, config, pollConfig = {}) {
|
|
|
1399
1532
|
throw new Error(`Task polling timeout after ${timeout}ms`);
|
|
1400
1533
|
}
|
|
1401
1534
|
function wrapTaskResponse(result, config) {
|
|
1535
|
+
const debugUrl = result.debugUrl ?? "";
|
|
1402
1536
|
const wrapped = {
|
|
1403
1537
|
...result,
|
|
1404
|
-
|
|
1405
|
-
|
|
1538
|
+
debugUrl,
|
|
1539
|
+
taskId: result.taskId || "",
|
|
1540
|
+
liveUrl: result.taskId ? generateLiveUrl(result.taskId, config) : debugUrl,
|
|
1406
1541
|
complete: async (pollConfig) => {
|
|
1407
|
-
if (result.
|
|
1408
|
-
return pollTaskUntilComplete(result.
|
|
1542
|
+
if (result.taskId) {
|
|
1543
|
+
return pollTaskUntilComplete(result.taskId, config, pollConfig);
|
|
1409
1544
|
}
|
|
1410
|
-
if (result.
|
|
1545
|
+
if (result.recordingId) {
|
|
1411
1546
|
const recording = await waitForRecording(
|
|
1412
|
-
result.
|
|
1547
|
+
result.recordingId,
|
|
1413
1548
|
config,
|
|
1414
1549
|
pollConfig
|
|
1415
1550
|
);
|
|
1416
1551
|
return {
|
|
1417
1552
|
...result,
|
|
1418
|
-
|
|
1553
|
+
recordingStatus: recording.status
|
|
1419
1554
|
};
|
|
1420
1555
|
}
|
|
1421
|
-
throw new Error("Cannot poll completion: no
|
|
1556
|
+
throw new Error("Cannot poll completion: no taskId or recordingId available");
|
|
1422
1557
|
},
|
|
1423
1558
|
// Add Steel live session helpers - either functional or error-throwing
|
|
1424
|
-
getLiveUrl:
|
|
1559
|
+
getLiveUrl: debugUrl ? (options) => buildLiveUrl(debugUrl, options) : () => {
|
|
1425
1560
|
throw new Error(
|
|
1426
1561
|
"Live sessions not available. Your backend must return a debugUrl in the response. Contact support@morphllm.com if you need help."
|
|
1427
1562
|
);
|
|
1428
1563
|
},
|
|
1429
|
-
getLiveIframe:
|
|
1564
|
+
getLiveIframe: debugUrl ? (optionsOrPreset) => {
|
|
1430
1565
|
const options = resolvePreset(optionsOrPreset);
|
|
1431
|
-
return buildLiveIframe(
|
|
1566
|
+
return buildLiveIframe(debugUrl, options);
|
|
1432
1567
|
} : () => {
|
|
1433
1568
|
throw new Error(
|
|
1434
1569
|
"Live sessions not available. Your backend must return a debugUrl in the response. Contact support@morphllm.com if you need help."
|
|
1435
1570
|
);
|
|
1436
1571
|
},
|
|
1437
|
-
getEmbedCode:
|
|
1572
|
+
getEmbedCode: debugUrl ? () => buildEmbedCode(debugUrl) : () => {
|
|
1438
1573
|
throw new Error(
|
|
1439
1574
|
"Live sessions not available. Your backend must return a debugUrl in the response. Contact support@morphllm.com if you need help."
|
|
1440
1575
|
);
|
|
@@ -1443,44 +1578,46 @@ function wrapTaskResponse(result, config) {
|
|
|
1443
1578
|
return wrapped;
|
|
1444
1579
|
}
|
|
1445
1580
|
function wrapTaskResponseWithSchema(result, config, schema) {
|
|
1581
|
+
const debugUrl = result.debugUrl ?? "";
|
|
1446
1582
|
const parsed = result.output ? parseStructuredTaskOutput(result, schema) : { ...result, parsed: null };
|
|
1447
1583
|
const wrapped = {
|
|
1448
1584
|
...parsed,
|
|
1449
|
-
|
|
1450
|
-
|
|
1585
|
+
debugUrl,
|
|
1586
|
+
taskId: result.taskId || "",
|
|
1587
|
+
liveUrl: result.taskId ? generateLiveUrl(result.taskId, config) : debugUrl,
|
|
1451
1588
|
complete: async (pollConfig) => {
|
|
1452
|
-
if (result.
|
|
1453
|
-
const finalResult = await pollTaskUntilComplete(result.
|
|
1589
|
+
if (result.taskId) {
|
|
1590
|
+
const finalResult = await pollTaskUntilComplete(result.taskId, config, pollConfig);
|
|
1454
1591
|
return parseStructuredTaskOutput(finalResult, schema);
|
|
1455
1592
|
}
|
|
1456
|
-
if (result.
|
|
1593
|
+
if (result.recordingId) {
|
|
1457
1594
|
const recording = await waitForRecording(
|
|
1458
|
-
result.
|
|
1595
|
+
result.recordingId,
|
|
1459
1596
|
config,
|
|
1460
1597
|
pollConfig
|
|
1461
1598
|
);
|
|
1462
1599
|
return {
|
|
1463
1600
|
...parsed,
|
|
1464
|
-
|
|
1601
|
+
recordingStatus: recording.status
|
|
1465
1602
|
};
|
|
1466
1603
|
}
|
|
1467
|
-
throw new Error("Cannot poll completion: no
|
|
1604
|
+
throw new Error("Cannot poll completion: no taskId or recordingId available");
|
|
1468
1605
|
},
|
|
1469
1606
|
// Add Steel live session helpers - either functional or error-throwing
|
|
1470
|
-
getLiveUrl:
|
|
1607
|
+
getLiveUrl: debugUrl ? (options) => buildLiveUrl(debugUrl, options) : () => {
|
|
1471
1608
|
throw new Error(
|
|
1472
1609
|
"Live sessions not available. Your backend must return a debugUrl in the response. Contact support@morphllm.com if you need help enabling live sessions. "
|
|
1473
1610
|
);
|
|
1474
1611
|
},
|
|
1475
|
-
getLiveIframe:
|
|
1612
|
+
getLiveIframe: debugUrl ? (optionsOrPreset) => {
|
|
1476
1613
|
const options = resolvePreset(optionsOrPreset);
|
|
1477
|
-
return buildLiveIframe(
|
|
1614
|
+
return buildLiveIframe(debugUrl, options);
|
|
1478
1615
|
} : () => {
|
|
1479
1616
|
throw new Error(
|
|
1480
1617
|
"Live sessions not available. Your backend must return a debugUrl in the response. Contact support@morphllm.com if you need help enabling live sessions."
|
|
1481
1618
|
);
|
|
1482
1619
|
},
|
|
1483
|
-
getEmbedCode:
|
|
1620
|
+
getEmbedCode: debugUrl ? () => buildEmbedCode(debugUrl) : () => {
|
|
1484
1621
|
throw new Error(
|
|
1485
1622
|
"Live sessions not available. Your backend must return a debugUrl in the response. Contact support@morphllm.com if you need help enabling live sessions."
|
|
1486
1623
|
);
|
|
@@ -1495,10 +1632,11 @@ async function getWebp(recordingId, config = {}, options = {}) {
|
|
|
1495
1632
|
throw new Error("API key required for getWebp");
|
|
1496
1633
|
}
|
|
1497
1634
|
const params = new URLSearchParams();
|
|
1498
|
-
if (options.
|
|
1635
|
+
if (options.maxDuration !== void 0) params.set("max_duration", String(options.maxDuration));
|
|
1499
1636
|
if (options.fps !== void 0) params.set("fps", String(options.fps));
|
|
1500
1637
|
if (options.width !== void 0) params.set("width", String(options.width));
|
|
1501
1638
|
if (options.quality !== void 0) params.set("quality", String(options.quality));
|
|
1639
|
+
if (options.maxSizeMb !== void 0) params.set("max_size_mb", String(options.maxSizeMb));
|
|
1502
1640
|
const url = `${apiUrl}/recordings/${recordingId}/webp${params.toString() ? "?" + params.toString() : ""}`;
|
|
1503
1641
|
if (debug) console.log(`[Browser] getWebp: ${url}`);
|
|
1504
1642
|
const response = await fetch(url, {
|
|
@@ -1510,8 +1648,8 @@ async function getWebp(recordingId, config = {}, options = {}) {
|
|
|
1510
1648
|
if (debug) console.error(`[Browser] getWebp error: ${response.status} - ${errorText}`);
|
|
1511
1649
|
throw new Error(`HTTP ${response.status}: ${errorText}`);
|
|
1512
1650
|
}
|
|
1513
|
-
const result = await response.json();
|
|
1514
|
-
if (debug) console.log(`[Browser] WebP ready: ${result.
|
|
1651
|
+
const result = mapWebpResponse(await response.json());
|
|
1652
|
+
if (debug) console.log(`[Browser] WebP ready: ${result.webpUrl} (cached: ${result.cached})`);
|
|
1515
1653
|
return result;
|
|
1516
1654
|
}
|
|
1517
1655
|
async function checkHealth(config = {}) {
|
|
@@ -2407,42 +2545,36 @@ function enforceContextLimit(messages, maxChars = AGENT_CONFIG.MAX_CONTEXT_CHARS
|
|
|
2407
2545
|
}
|
|
2408
2546
|
|
|
2409
2547
|
// tools/warp_grep/agent/runner.ts
|
|
2548
|
+
var import_openai = __toESM(require("openai"), 1);
|
|
2410
2549
|
var import_path3 = __toESM(require("path"), 1);
|
|
2411
2550
|
var parser = new LLMResponseParser();
|
|
2412
2551
|
var DEFAULT_API_URL2 = "https://api.morphllm.com";
|
|
2413
2552
|
async function callModel(messages, model, options = {}) {
|
|
2414
2553
|
const baseUrl = options.morphApiUrl || DEFAULT_API_URL2;
|
|
2415
2554
|
const apiKey = options.morphApiKey || process.env.MORPH_API_KEY || "";
|
|
2416
|
-
const fetchPromise = fetchWithRetry(
|
|
2417
|
-
`${baseUrl}/v1/chat/completions`,
|
|
2418
|
-
{
|
|
2419
|
-
method: "POST",
|
|
2420
|
-
headers: {
|
|
2421
|
-
"Content-Type": "application/json",
|
|
2422
|
-
Authorization: `Bearer ${apiKey}`
|
|
2423
|
-
},
|
|
2424
|
-
body: JSON.stringify({
|
|
2425
|
-
model,
|
|
2426
|
-
temperature: 0,
|
|
2427
|
-
max_tokens: 1024,
|
|
2428
|
-
repetition_penalty: 1.05,
|
|
2429
|
-
messages
|
|
2430
|
-
})
|
|
2431
|
-
},
|
|
2432
|
-
options.retryConfig
|
|
2433
|
-
);
|
|
2434
2555
|
const timeoutMs = options.timeout ?? AGENT_CONFIG.TIMEOUT_MS;
|
|
2435
|
-
const
|
|
2436
|
-
|
|
2437
|
-
|
|
2556
|
+
const client = new import_openai.default({
|
|
2557
|
+
apiKey,
|
|
2558
|
+
baseURL: `${baseUrl}/v1`,
|
|
2559
|
+
maxRetries: options.retryConfig?.maxRetries,
|
|
2560
|
+
timeout: timeoutMs
|
|
2561
|
+
});
|
|
2562
|
+
let data;
|
|
2563
|
+
try {
|
|
2564
|
+
data = await client.chat.completions.create({
|
|
2565
|
+
model,
|
|
2566
|
+
temperature: 0,
|
|
2567
|
+
max_tokens: 1024,
|
|
2568
|
+
messages
|
|
2569
|
+
});
|
|
2570
|
+
} catch (error) {
|
|
2571
|
+
if (error instanceof import_openai.default.APIError && error.status === 404) {
|
|
2438
2572
|
throw new Error(
|
|
2439
2573
|
"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"
|
|
2440
2574
|
);
|
|
2441
2575
|
}
|
|
2442
|
-
|
|
2443
|
-
throw new Error(`morph-warp-grep error ${resp.status}: ${t}`);
|
|
2576
|
+
throw error;
|
|
2444
2577
|
}
|
|
2445
|
-
const data = await resp.json();
|
|
2446
2578
|
const content = data?.choices?.[0]?.message?.content;
|
|
2447
2579
|
if (!content || typeof content !== "string") {
|
|
2448
2580
|
throw new Error("Invalid response from model");
|
|
@@ -4398,13 +4530,6 @@ function formatResult3(result) {
|
|
|
4398
4530
|
changes.linesRemoved && `-${changes.linesRemoved} lines`,
|
|
4399
4531
|
changes.linesModified && `~${changes.linesModified} lines modified`
|
|
4400
4532
|
].filter(Boolean).join(", ");
|
|
4401
|
-
if (result.udiff) {
|
|
4402
|
-
return `Successfully applied changes to ${result.filepath}:
|
|
4403
|
-
|
|
4404
|
-
${result.udiff}
|
|
4405
|
-
|
|
4406
|
-
Summary: ${summary}`;
|
|
4407
|
-
}
|
|
4408
4533
|
return `Successfully applied changes to ${result.filepath}. ${summary}`;
|
|
4409
4534
|
}
|
|
4410
4535
|
function createEditFileTool(config = {}) {
|
|
@@ -4605,13 +4730,6 @@ function formatResult5(result) {
|
|
|
4605
4730
|
changes.linesRemoved && `-${changes.linesRemoved} lines`,
|
|
4606
4731
|
changes.linesModified && `~${changes.linesModified} lines modified`
|
|
4607
4732
|
].filter(Boolean).join(", ");
|
|
4608
|
-
if (result.udiff) {
|
|
4609
|
-
return `Successfully applied changes to ${result.filepath}:
|
|
4610
|
-
|
|
4611
|
-
${result.udiff}
|
|
4612
|
-
|
|
4613
|
-
Summary: ${summary}`;
|
|
4614
|
-
}
|
|
4615
4733
|
return `Successfully applied changes to ${result.filepath}. ${summary}`;
|
|
4616
4734
|
}
|
|
4617
4735
|
function createEditFileTool2(config = {}) {
|