@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/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 url = new URL(debugUrl);
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 || api.debugUrl || ""
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
- * Create a new browser profile.
731
- *
732
- * @param input - Profile creation parameters
733
- * @returns The created profile
734
- * @throws {MorphValidationError} If input validation fails
735
- * @throws {MorphProfileLimitError} If profile limit is exceeded
736
- * @throws {MorphAuthenticationError} If API key is missing or invalid
737
- *
738
- * @example
739
- * ```typescript
740
- * const profile = await morph.browser.profiles.createProfile({
741
- * name: 'LinkedIn Production',
742
- * repoId: 'repo-uuid-here'
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-uuid');
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's name.
811
+ * Update a profile by opening a live session (no rename).
786
812
  *
787
813
  * @param id - Profile ID
788
- * @param input - Update parameters
789
- * @returns Updated profile
814
+ * @returns Profile setup handle with live URL + save()
790
815
  */
791
- async updateProfile(id, input) {
792
- return updateProfile(id, input, this.config);
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
- return transformProfile(apiProfile);
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, input, config = {}) {
970
+ async function updateProfile(id, config = {}) {
936
971
  validateId(id, "id");
937
- if (input.name !== void 0) {
938
- if (typeof input.name !== "string") {
939
- throw new MorphValidationError("name must be a string", "name");
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.max_steps ?? 10,
1147
+ max_steps: input.maxSteps ?? 10,
1095
1148
  model: input.model ?? "morph-computer-use-v0",
1096
- viewport_width: input.viewport_width ?? 1280,
1097
- viewport_height: input.viewport_height ?? 720,
1098
- external_id: input.external_id,
1099
- repo_id: input.repo_id,
1100
- commit_id: input.commit_id,
1101
- record_video: input.record_video ?? false,
1102
- video_width: input.video_width ?? input.viewport_width ?? 1280,
1103
- video_height: input.video_height ?? input.viewport_height ?? 720,
1104
- allow_resizing: input.allow_resizing ?? false,
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.profile_id
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
- console.log(`[Browser] \u2705 Task created: recording_id=${result.recording_id ?? "none"} debug_url=${result.debugUrl ? "available" : "none"}`);
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.max_steps !== void 0 && (input.max_steps < 1 || input.max_steps > 50)) {
1227
+ if (input.maxSteps !== void 0 && (input.maxSteps < 1 || input.maxSteps > 50)) {
1173
1228
  return {
1174
1229
  success: false,
1175
- error: "max_steps must be between 1 and 50. Use more steps for complex multi-page flows."
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.max_steps ?? 10}`);
1180
- console.log(`[Browser] Recording: ${input.record_video ? "yes" : "no"} | Calling ${apiUrl}/browser-task`);
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.max_steps ?? 10,
1249
+ max_steps: input.maxSteps ?? 10,
1195
1250
  model: input.model ?? "morph-computer-use-v0",
1196
- viewport_width: input.viewport_width ?? 1280,
1197
- viewport_height: input.viewport_height ?? 720,
1198
- external_id: input.external_id,
1199
- repo_id: input.repo_id,
1200
- commit_id: input.commit_id,
1201
- record_video: input.record_video ?? false,
1202
- video_width: input.video_width ?? input.viewport_width ?? 1280,
1203
- video_height: input.video_height ?? input.viewport_height ?? 720,
1204
- allow_resizing: input.allow_resizing ?? false,
1205
- structured_output: input.structured_output,
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.profile_id
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 max_steps.`
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.steps_taken ?? 0} recordingId=${result.recording_id ?? "none"}`);
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.recording_id) {
1341
+ if (taskResult.recordingId) {
1287
1342
  try {
1288
1343
  const recording = await waitForRecording(
1289
- taskResult.recording_id,
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.recording_id,
1354
+ id: taskResult.recordingId,
1300
1355
  status: "ERROR",
1301
1356
  error: error instanceof Error ? error.message : String(error),
1302
- created_at: (/* @__PURE__ */ new Date()).toISOString(),
1303
- getWebp: (options) => getWebp(taskResult.recording_id, config, options),
1304
- getErrors: () => getErrors(taskResult.recording_id, config)
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.total_errors} 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
- task_id: result.task_id || "",
1405
- liveUrl: result.task_id ? generateLiveUrl(result.task_id, config) : result.debugUrl || "",
1538
+ debugUrl,
1539
+ taskId: result.taskId || "",
1540
+ liveUrl: result.taskId ? generateLiveUrl(result.taskId, config) : debugUrl,
1406
1541
  complete: async (pollConfig) => {
1407
- if (result.task_id) {
1408
- return pollTaskUntilComplete(result.task_id, config, pollConfig);
1542
+ if (result.taskId) {
1543
+ return pollTaskUntilComplete(result.taskId, config, pollConfig);
1409
1544
  }
1410
- if (result.recording_id) {
1545
+ if (result.recordingId) {
1411
1546
  const recording = await waitForRecording(
1412
- result.recording_id,
1547
+ result.recordingId,
1413
1548
  config,
1414
1549
  pollConfig
1415
1550
  );
1416
1551
  return {
1417
1552
  ...result,
1418
- recording_status: recording.status
1553
+ recordingStatus: recording.status
1419
1554
  };
1420
1555
  }
1421
- throw new Error("Cannot poll completion: no task_id or recording_id available");
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: result.debugUrl ? (options) => buildLiveUrl(result.debugUrl, options) : () => {
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: result.debugUrl ? (optionsOrPreset) => {
1564
+ getLiveIframe: debugUrl ? (optionsOrPreset) => {
1430
1565
  const options = resolvePreset(optionsOrPreset);
1431
- return buildLiveIframe(result.debugUrl, options);
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: result.debugUrl ? () => buildEmbedCode(result.debugUrl) : () => {
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
- task_id: result.task_id || "",
1450
- liveUrl: result.task_id ? generateLiveUrl(result.task_id, config) : result.debugUrl || "",
1585
+ debugUrl,
1586
+ taskId: result.taskId || "",
1587
+ liveUrl: result.taskId ? generateLiveUrl(result.taskId, config) : debugUrl,
1451
1588
  complete: async (pollConfig) => {
1452
- if (result.task_id) {
1453
- const finalResult = await pollTaskUntilComplete(result.task_id, config, pollConfig);
1589
+ if (result.taskId) {
1590
+ const finalResult = await pollTaskUntilComplete(result.taskId, config, pollConfig);
1454
1591
  return parseStructuredTaskOutput(finalResult, schema);
1455
1592
  }
1456
- if (result.recording_id) {
1593
+ if (result.recordingId) {
1457
1594
  const recording = await waitForRecording(
1458
- result.recording_id,
1595
+ result.recordingId,
1459
1596
  config,
1460
1597
  pollConfig
1461
1598
  );
1462
1599
  return {
1463
1600
  ...parsed,
1464
- recording_status: recording.status
1601
+ recordingStatus: recording.status
1465
1602
  };
1466
1603
  }
1467
- throw new Error("Cannot poll completion: no task_id or recording_id available");
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: result.debugUrl ? (options) => buildLiveUrl(result.debugUrl, options) : () => {
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: result.debugUrl ? (optionsOrPreset) => {
1612
+ getLiveIframe: debugUrl ? (optionsOrPreset) => {
1476
1613
  const options = resolvePreset(optionsOrPreset);
1477
- return buildLiveIframe(result.debugUrl, options);
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: result.debugUrl ? () => buildEmbedCode(result.debugUrl) : () => {
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.max_duration !== void 0) params.set("max_duration", String(options.max_duration));
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.webp_url} (cached: ${result.cached})`);
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 resp = await withTimeout(fetchPromise, timeoutMs, "morph-warp-grep request timed out");
2436
- if (!resp.ok) {
2437
- if (resp.status === 404) {
2556
+ const client = new import_openai.default({
2557
+ apiKey,
2558
+ baseURL: baseUrl,
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
- const t = await resp.text();
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 = {}) {