@morphllm/morphsdk 0.2.94 → 0.2.95

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. package/dist/{chunk-YJ354BA2.js → chunk-2AMEQAO2.js} +2 -2
  2. package/dist/chunk-2AMEQAO2.js.map +1 -0
  3. package/dist/{chunk-EI4UKP24.js → chunk-2HMEZZKK.js} +2 -2
  4. package/dist/{chunk-EI4UKP24.js.map → chunk-2HMEZZKK.js.map} +1 -1
  5. package/dist/{chunk-UJ7LVT5G.js → chunk-2VERUKO2.js} +1 -1
  6. package/dist/chunk-2VERUKO2.js.map +1 -0
  7. package/dist/{chunk-VHOWYK66.js → chunk-43LQLGP6.js} +23 -33
  8. package/dist/chunk-43LQLGP6.js.map +1 -0
  9. package/dist/{chunk-R7WN43L2.js → chunk-4KMBU6T3.js} +4 -4
  10. package/dist/{chunk-BVVDDTI7.js → chunk-73RV6EXR.js} +2 -2
  11. package/dist/{chunk-IH3KN4AT.js → chunk-7D6TXC7X.js} +2 -2
  12. package/dist/{chunk-FIA6LBW2.js → chunk-O7LDZA52.js} +2 -2
  13. package/dist/{chunk-5QIWYEHJ.js → chunk-PE4KGDA6.js} +1 -8
  14. package/dist/chunk-PE4KGDA6.js.map +1 -0
  15. package/dist/{chunk-SQN4DUQS.js → chunk-Q6Y4R236.js} +26 -2
  16. package/dist/chunk-Q6Y4R236.js.map +1 -0
  17. package/dist/{chunk-TXYCM4NP.js → chunk-QAT5UVPX.js} +3 -3
  18. package/dist/{chunk-M7GFXRKL.js → chunk-QJP62BXH.js} +157 -72
  19. package/dist/chunk-QJP62BXH.js.map +1 -0
  20. package/dist/{chunk-AV6YV2MH.js → chunk-R7IQWNSA.js} +8 -8
  21. package/dist/chunk-R7IQWNSA.js.map +1 -0
  22. package/dist/{chunk-ESRZJRTQ.js → chunk-SI2CKRKJ.js} +86 -56
  23. package/dist/chunk-SI2CKRKJ.js.map +1 -0
  24. package/dist/{chunk-FMWNVTJJ.js → chunk-TSENDJQI.js} +6 -6
  25. package/dist/chunk-TSENDJQI.js.map +1 -0
  26. package/dist/{chunk-IUG2FHNN.js → chunk-XH7P7HVT.js} +1 -8
  27. package/dist/chunk-XH7P7HVT.js.map +1 -0
  28. package/dist/{chunk-WSQMWVSD.js → chunk-YZ5NCWO2.js} +6 -6
  29. package/dist/chunk-YZ5NCWO2.js.map +1 -0
  30. package/dist/{chunk-4WO7PJNT.js → chunk-ZYTAKEBW.js} +8 -8
  31. package/dist/client.cjs +280 -162
  32. package/dist/client.cjs.map +1 -1
  33. package/dist/client.js +18 -18
  34. package/dist/index.cjs +280 -162
  35. package/dist/index.cjs.map +1 -1
  36. package/dist/index.js +18 -18
  37. package/dist/tools/browser/anthropic.cjs +54 -23
  38. package/dist/tools/browser/anthropic.cjs.map +1 -1
  39. package/dist/tools/browser/anthropic.js +7 -7
  40. package/dist/tools/browser/core.cjs +262 -124
  41. package/dist/tools/browser/core.cjs.map +1 -1
  42. package/dist/tools/browser/core.d.ts +24 -24
  43. package/dist/tools/browser/core.js +5 -5
  44. package/dist/tools/browser/errors.cjs.map +1 -1
  45. package/dist/tools/browser/errors.d.ts +1 -1
  46. package/dist/tools/browser/errors.js +1 -1
  47. package/dist/tools/browser/index.cjs +277 -139
  48. package/dist/tools/browser/index.cjs.map +1 -1
  49. package/dist/tools/browser/index.d.ts +3 -3
  50. package/dist/tools/browser/index.js +12 -12
  51. package/dist/tools/browser/index.js.map +1 -1
  52. package/dist/tools/browser/live.cjs +25 -1
  53. package/dist/tools/browser/live.cjs.map +1 -1
  54. package/dist/tools/browser/live.js +1 -1
  55. package/dist/tools/browser/openai.cjs +54 -23
  56. package/dist/tools/browser/openai.cjs.map +1 -1
  57. package/dist/tools/browser/openai.js +7 -7
  58. package/dist/tools/browser/profiles/core.cjs +85 -54
  59. package/dist/tools/browser/profiles/core.cjs.map +1 -1
  60. package/dist/tools/browser/profiles/core.d.ts +33 -25
  61. package/dist/tools/browser/profiles/core.js +5 -3
  62. package/dist/tools/browser/profiles/index.cjs +85 -54
  63. package/dist/tools/browser/profiles/index.cjs.map +1 -1
  64. package/dist/tools/browser/profiles/index.d.ts +2 -2
  65. package/dist/tools/browser/profiles/index.js +5 -3
  66. package/dist/tools/browser/profiles/types.cjs +1 -1
  67. package/dist/tools/browser/profiles/types.cjs.map +1 -1
  68. package/dist/tools/browser/profiles/types.d.ts +28 -9
  69. package/dist/tools/browser/profiles/types.js +1 -1
  70. package/dist/tools/browser/prompts.cjs +1 -1
  71. package/dist/tools/browser/prompts.cjs.map +1 -1
  72. package/dist/tools/browser/prompts.d.ts +1 -1
  73. package/dist/tools/browser/prompts.js +1 -1
  74. package/dist/tools/browser/types.cjs.map +1 -1
  75. package/dist/tools/browser/types.d.ts +54 -52
  76. package/dist/tools/browser/vercel.cjs +56 -25
  77. package/dist/tools/browser/vercel.cjs.map +1 -1
  78. package/dist/tools/browser/vercel.d.ts +1 -1
  79. package/dist/tools/browser/vercel.js +7 -7
  80. package/dist/tools/fastapply/anthropic.cjs +0 -7
  81. package/dist/tools/fastapply/anthropic.cjs.map +1 -1
  82. package/dist/tools/fastapply/anthropic.js +1 -1
  83. package/dist/tools/fastapply/index.cjs +0 -14
  84. package/dist/tools/fastapply/index.cjs.map +1 -1
  85. package/dist/tools/fastapply/index.js +2 -2
  86. package/dist/tools/fastapply/openai.cjs +0 -7
  87. package/dist/tools/fastapply/openai.cjs.map +1 -1
  88. package/dist/tools/fastapply/openai.js +1 -1
  89. package/dist/tools/index.cjs +0 -14
  90. package/dist/tools/index.cjs.map +1 -1
  91. package/dist/tools/index.js +2 -2
  92. package/dist/tools/warp_grep/agent/runner.cjs +18 -98
  93. package/dist/tools/warp_grep/agent/runner.cjs.map +1 -1
  94. package/dist/tools/warp_grep/agent/runner.js +2 -3
  95. package/dist/tools/warp_grep/anthropic.cjs +18 -98
  96. package/dist/tools/warp_grep/anthropic.cjs.map +1 -1
  97. package/dist/tools/warp_grep/anthropic.js +8 -9
  98. package/dist/tools/warp_grep/client.cjs +18 -98
  99. package/dist/tools/warp_grep/client.cjs.map +1 -1
  100. package/dist/tools/warp_grep/client.js +7 -8
  101. package/dist/tools/warp_grep/gemini.cjs +18 -98
  102. package/dist/tools/warp_grep/gemini.cjs.map +1 -1
  103. package/dist/tools/warp_grep/gemini.js +7 -8
  104. package/dist/tools/warp_grep/gemini.js.map +1 -1
  105. package/dist/tools/warp_grep/harness.js +10 -10
  106. package/dist/tools/warp_grep/index.cjs +18 -98
  107. package/dist/tools/warp_grep/index.cjs.map +1 -1
  108. package/dist/tools/warp_grep/index.js +10 -11
  109. package/dist/tools/warp_grep/openai.cjs +18 -98
  110. package/dist/tools/warp_grep/openai.cjs.map +1 -1
  111. package/dist/tools/warp_grep/openai.js +8 -9
  112. package/dist/tools/warp_grep/providers/local.js +2 -2
  113. package/dist/tools/warp_grep/vercel.cjs +18 -98
  114. package/dist/tools/warp_grep/vercel.cjs.map +1 -1
  115. package/dist/tools/warp_grep/vercel.js +8 -9
  116. package/dist/{vercel-CsnNSdze.d.ts → vercel-CVF27qFK.d.ts} +10 -10
  117. package/package.json +1 -1
  118. package/dist/chunk-5QIWYEHJ.js.map +0 -1
  119. package/dist/chunk-AV6YV2MH.js.map +0 -1
  120. package/dist/chunk-ESRZJRTQ.js.map +0 -1
  121. package/dist/chunk-FMWNVTJJ.js.map +0 -1
  122. package/dist/chunk-IUG2FHNN.js.map +0 -1
  123. package/dist/chunk-M7GFXRKL.js.map +0 -1
  124. package/dist/chunk-SQN4DUQS.js.map +0 -1
  125. package/dist/chunk-UJ7LVT5G.js.map +0 -1
  126. package/dist/chunk-VHOWYK66.js.map +0 -1
  127. package/dist/chunk-WSQMWVSD.js.map +0 -1
  128. package/dist/chunk-YJ354BA2.js.map +0 -1
  129. /package/dist/{chunk-R7WN43L2.js.map → chunk-4KMBU6T3.js.map} +0 -0
  130. /package/dist/{chunk-BVVDDTI7.js.map → chunk-73RV6EXR.js.map} +0 -0
  131. /package/dist/{chunk-IH3KN4AT.js.map → chunk-7D6TXC7X.js.map} +0 -0
  132. /package/dist/{chunk-FIA6LBW2.js.map → chunk-O7LDZA52.js.map} +0 -0
  133. /package/dist/{chunk-TXYCM4NP.js.map → chunk-QAT5UVPX.js.map} +0 -0
  134. /package/dist/{chunk-4WO7PJNT.js.map → chunk-ZYTAKEBW.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 url = new URL(debugUrl);
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 || api.debugUrl || ""
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
- * Create a new browser profile.
717
- *
718
- * @param input - Profile creation parameters
719
- * @returns The created profile
720
- * @throws {MorphValidationError} If input validation fails
721
- * @throws {MorphProfileLimitError} If profile limit is exceeded
722
- * @throws {MorphAuthenticationError} If API key is missing or invalid
723
- *
724
- * @example
725
- * ```typescript
726
- * const profile = await morph.browser.profiles.createProfile({
727
- * name: 'LinkedIn Production',
728
- * repoId: 'repo-uuid-here'
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-uuid');
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's name.
797
+ * Update a profile by opening a live session (no rename).
772
798
  *
773
799
  * @param id - Profile ID
774
- * @param input - Update parameters
775
- * @returns Updated profile
800
+ * @returns Profile setup handle with live URL + save()
776
801
  */
777
- async updateProfile(id, input) {
778
- return updateProfile(id, input, this.config);
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
- return transformProfile(apiProfile);
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, input, config = {}) {
956
+ async function updateProfile(id, config = {}) {
922
957
  validateId(id, "id");
923
- if (input.name !== void 0) {
924
- if (typeof input.name !== "string") {
925
- throw new MorphValidationError("name must be a string", "name");
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.max_steps ?? 10,
1133
+ max_steps: input.maxSteps ?? 10,
1081
1134
  model: input.model ?? "morph-computer-use-v0",
1082
- viewport_width: input.viewport_width ?? 1280,
1083
- viewport_height: input.viewport_height ?? 720,
1084
- external_id: input.external_id,
1085
- repo_id: input.repo_id,
1086
- commit_id: input.commit_id,
1087
- record_video: input.record_video ?? false,
1088
- video_width: input.video_width ?? input.viewport_width ?? 1280,
1089
- video_height: input.video_height ?? input.viewport_height ?? 720,
1090
- allow_resizing: input.allow_resizing ?? false,
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.profile_id
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
- console.log(`[Browser] \u2705 Task created: recording_id=${result.recording_id ?? "none"} debug_url=${result.debugUrl ? "available" : "none"}`);
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.max_steps !== void 0 && (input.max_steps < 1 || input.max_steps > 50)) {
1213
+ if (input.maxSteps !== void 0 && (input.maxSteps < 1 || input.maxSteps > 50)) {
1159
1214
  return {
1160
1215
  success: false,
1161
- error: "max_steps must be between 1 and 50. Use more steps for complex multi-page flows."
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.max_steps ?? 10}`);
1166
- console.log(`[Browser] Recording: ${input.record_video ? "yes" : "no"} | Calling ${apiUrl}/browser-task`);
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.max_steps ?? 10,
1235
+ max_steps: input.maxSteps ?? 10,
1181
1236
  model: input.model ?? "morph-computer-use-v0",
1182
- viewport_width: input.viewport_width ?? 1280,
1183
- viewport_height: input.viewport_height ?? 720,
1184
- external_id: input.external_id,
1185
- repo_id: input.repo_id,
1186
- commit_id: input.commit_id,
1187
- record_video: input.record_video ?? false,
1188
- video_width: input.video_width ?? input.viewport_width ?? 1280,
1189
- video_height: input.video_height ?? input.viewport_height ?? 720,
1190
- allow_resizing: input.allow_resizing ?? false,
1191
- structured_output: input.structured_output,
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.profile_id
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 max_steps.`
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.steps_taken ?? 0} recordingId=${result.recording_id ?? "none"}`);
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.recording_id) {
1327
+ if (taskResult.recordingId) {
1273
1328
  try {
1274
1329
  const recording = await waitForRecording(
1275
- taskResult.recording_id,
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.recording_id,
1340
+ id: taskResult.recordingId,
1286
1341
  status: "ERROR",
1287
1342
  error: error instanceof Error ? error.message : String(error),
1288
- created_at: (/* @__PURE__ */ new Date()).toISOString(),
1289
- getWebp: (options) => getWebp(taskResult.recording_id, config, options),
1290
- getErrors: () => getErrors(taskResult.recording_id, config)
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.total_errors} 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
- task_id: result.task_id || "",
1391
- liveUrl: result.task_id ? generateLiveUrl(result.task_id, config) : result.debugUrl || "",
1524
+ debugUrl,
1525
+ taskId: result.taskId || "",
1526
+ liveUrl: result.taskId ? generateLiveUrl(result.taskId, config) : debugUrl,
1392
1527
  complete: async (pollConfig) => {
1393
- if (result.task_id) {
1394
- return pollTaskUntilComplete(result.task_id, config, pollConfig);
1528
+ if (result.taskId) {
1529
+ return pollTaskUntilComplete(result.taskId, config, pollConfig);
1395
1530
  }
1396
- if (result.recording_id) {
1531
+ if (result.recordingId) {
1397
1532
  const recording = await waitForRecording(
1398
- result.recording_id,
1533
+ result.recordingId,
1399
1534
  config,
1400
1535
  pollConfig
1401
1536
  );
1402
1537
  return {
1403
1538
  ...result,
1404
- recording_status: recording.status
1539
+ recordingStatus: recording.status
1405
1540
  };
1406
1541
  }
1407
- throw new Error("Cannot poll completion: no task_id or recording_id available");
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: result.debugUrl ? (options) => buildLiveUrl(result.debugUrl, options) : () => {
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: result.debugUrl ? (optionsOrPreset) => {
1550
+ getLiveIframe: debugUrl ? (optionsOrPreset) => {
1416
1551
  const options = resolvePreset(optionsOrPreset);
1417
- return buildLiveIframe(result.debugUrl, options);
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: result.debugUrl ? () => buildEmbedCode(result.debugUrl) : () => {
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
- task_id: result.task_id || "",
1436
- liveUrl: result.task_id ? generateLiveUrl(result.task_id, config) : result.debugUrl || "",
1571
+ debugUrl,
1572
+ taskId: result.taskId || "",
1573
+ liveUrl: result.taskId ? generateLiveUrl(result.taskId, config) : debugUrl,
1437
1574
  complete: async (pollConfig) => {
1438
- if (result.task_id) {
1439
- const finalResult = await pollTaskUntilComplete(result.task_id, config, pollConfig);
1575
+ if (result.taskId) {
1576
+ const finalResult = await pollTaskUntilComplete(result.taskId, config, pollConfig);
1440
1577
  return parseStructuredTaskOutput(finalResult, schema);
1441
1578
  }
1442
- if (result.recording_id) {
1579
+ if (result.recordingId) {
1443
1580
  const recording = await waitForRecording(
1444
- result.recording_id,
1581
+ result.recordingId,
1445
1582
  config,
1446
1583
  pollConfig
1447
1584
  );
1448
1585
  return {
1449
1586
  ...parsed,
1450
- recording_status: recording.status
1587
+ recordingStatus: recording.status
1451
1588
  };
1452
1589
  }
1453
- throw new Error("Cannot poll completion: no task_id or recording_id available");
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: result.debugUrl ? (options) => buildLiveUrl(result.debugUrl, options) : () => {
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: result.debugUrl ? (optionsOrPreset) => {
1598
+ getLiveIframe: debugUrl ? (optionsOrPreset) => {
1462
1599
  const options = resolvePreset(optionsOrPreset);
1463
- return buildLiveIframe(result.debugUrl, options);
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: result.debugUrl ? () => buildEmbedCode(result.debugUrl) : () => {
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.max_duration !== void 0) params.set("max_duration", String(options.max_duration));
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.webp_url} (cached: ${result.cached})`);
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 resp = await withTimeout(fetchPromise, timeoutMs, "morph-warp-grep request timed out");
2422
- if (!resp.ok) {
2423
- if (resp.status === 404) {
2542
+ const client = new import_openai.default({
2543
+ apiKey,
2544
+ baseURL: baseUrl,
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
- const t = await resp.text();
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 = {}) {