@morphllm/morphsdk 0.2.170 → 0.2.172

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 (260) hide show
  1. package/dist/{chunk-IY7DESC3.js → chunk-2SNAXTUJ.js} +4 -4
  2. package/dist/chunk-453ZV2AX.js +120 -0
  3. package/dist/chunk-453ZV2AX.js.map +1 -0
  4. package/dist/chunk-53ZJMCWU.js +142 -0
  5. package/dist/chunk-53ZJMCWU.js.map +1 -0
  6. package/dist/{chunk-5KFQBI4J.js → chunk-5DA6SZQJ.js} +2 -2
  7. package/dist/chunk-66OHYI24.js +78 -0
  8. package/dist/chunk-66OHYI24.js.map +1 -0
  9. package/dist/chunk-6X6QMRQG.js +158 -0
  10. package/dist/chunk-6X6QMRQG.js.map +1 -0
  11. package/dist/{chunk-76XER44U.js → chunk-7PVVPLRL.js} +2 -2
  12. package/dist/{chunk-BCPZAPWY.js → chunk-AE7M2I52.js} +2 -2
  13. package/dist/{chunk-LNXIVRPY.js → chunk-CQF76HJC.js} +30 -6
  14. package/dist/chunk-CQF76HJC.js.map +1 -0
  15. package/dist/{chunk-OJQYBWHR.js → chunk-ESXCQBMU.js} +2 -2
  16. package/dist/{chunk-LAGN62H5.js → chunk-FOIDGIY4.js} +29 -10
  17. package/dist/chunk-FOIDGIY4.js.map +1 -0
  18. package/dist/{chunk-KUPSW5QN.js → chunk-GJZXDRH5.js} +8 -3
  19. package/dist/{chunk-KUPSW5QN.js.map → chunk-GJZXDRH5.js.map} +1 -1
  20. package/dist/{chunk-5IR3YE77.js → chunk-IJ33I7P5.js} +4 -4
  21. package/dist/{chunk-E5QWXVTF.js → chunk-IN2U7AAI.js} +99 -143
  22. package/dist/chunk-IN2U7AAI.js.map +1 -0
  23. package/dist/{chunk-LE66XCOI.js → chunk-JWZ5DLAS.js} +27 -10
  24. package/dist/chunk-JWZ5DLAS.js.map +1 -0
  25. package/dist/chunk-LKFZBBTD.js +12 -0
  26. package/dist/chunk-LKFZBBTD.js.map +1 -0
  27. package/dist/{chunk-6LPWEZ6H.js → chunk-MO6S2LRD.js} +2 -2
  28. package/dist/{chunk-S4IEM5EG.js → chunk-NI7PWQ3B.js} +4 -4
  29. package/dist/{chunk-GLQWEINZ.js → chunk-QAXXE4AD.js} +2 -2
  30. package/dist/{chunk-YG2I377B.js → chunk-QFE5523Q.js} +18 -3
  31. package/dist/chunk-QFE5523Q.js.map +1 -0
  32. package/dist/{chunk-G4FPDEUP.js → chunk-QQXNZIVK.js} +4 -4
  33. package/dist/{chunk-A3ZUWLYX.js → chunk-QZ3V2BP7.js} +2 -2
  34. package/dist/chunk-QZR7SJ5N.js +24 -0
  35. package/dist/chunk-QZR7SJ5N.js.map +1 -0
  36. package/dist/{chunk-SYD6BRQX.js → chunk-SJVLAGUL.js} +4 -4
  37. package/dist/{chunk-JMEQ6FLB.js → chunk-U4J3BVAQ.js} +4 -4
  38. package/dist/{chunk-QAWYDWDW.js → chunk-U4MRSZQQ.js} +2 -2
  39. package/dist/{chunk-WU3D46MH.js → chunk-UADW6FYD.js} +2 -2
  40. package/dist/{chunk-K7NY5SVR.js → chunk-VBARKJWL.js} +2 -2
  41. package/dist/{chunk-OPNTDMHH.js → chunk-VLZ6PNAD.js} +4 -4
  42. package/dist/chunk-VZ7BOH2K.js +1 -0
  43. package/dist/chunk-VZ7BOH2K.js.map +1 -0
  44. package/dist/{chunk-GUGHUAJU.js → chunk-XJDXV5VX.js} +2 -2
  45. package/dist/{chunk-GPNUS3H2.js → chunk-XYTYIAMQ.js} +2 -2
  46. package/dist/{chunk-MKBVWPU7.js → chunk-Z4GJVN52.js} +23 -8
  47. package/dist/chunk-Z4GJVN52.js.map +1 -0
  48. package/dist/chunk-ZLSNL6M2.js +97 -0
  49. package/dist/chunk-ZLSNL6M2.js.map +1 -0
  50. package/dist/{client-DsAAqupx.d.ts → client-Dh6yzCm4.d.ts} +14 -5
  51. package/dist/client.cjs +741 -525
  52. package/dist/client.cjs.map +1 -1
  53. package/dist/client.d.ts +5 -1
  54. package/dist/client.js +31 -27
  55. package/dist/core/client.cjs +540 -0
  56. package/dist/core/client.cjs.map +1 -0
  57. package/dist/core/client.d.ts +79 -0
  58. package/dist/core/client.js +12 -0
  59. package/dist/core/client.js.map +1 -0
  60. package/dist/core/error.cjs +309 -0
  61. package/dist/core/error.cjs.map +1 -0
  62. package/dist/core/error.d.ts +18 -0
  63. package/dist/core/error.js +10 -0
  64. package/dist/core/error.js.map +1 -0
  65. package/dist/core/index.cjs +552 -0
  66. package/dist/core/index.cjs.map +1 -0
  67. package/dist/core/index.d.ts +4 -0
  68. package/dist/core/index.js +20 -0
  69. package/dist/core/index.js.map +1 -0
  70. package/dist/core/resource.cjs +36 -0
  71. package/dist/core/resource.cjs.map +1 -0
  72. package/dist/core/resource.d.ts +18 -0
  73. package/dist/core/resource.js +8 -0
  74. package/dist/core/resource.js.map +1 -0
  75. package/dist/edge.cjs +252 -174
  76. package/dist/edge.cjs.map +1 -1
  77. package/dist/edge.d.ts +2 -0
  78. package/dist/edge.js +8 -5
  79. package/dist/git/client.cjs +529 -9
  80. package/dist/git/client.cjs.map +1 -1
  81. package/dist/git/client.d.ts +8 -2
  82. package/dist/git/client.js +7 -1
  83. package/dist/git/index.cjs +529 -9
  84. package/dist/git/index.cjs.map +1 -1
  85. package/dist/git/index.d.ts +2 -0
  86. package/dist/git/index.js +7 -1
  87. package/dist/index.cjs +688 -466
  88. package/dist/index.cjs.map +1 -1
  89. package/dist/index.d.ts +6 -2
  90. package/dist/index.js +49 -33
  91. package/dist/modelrouter/core.cjs +204 -125
  92. package/dist/modelrouter/core.cjs.map +1 -1
  93. package/dist/modelrouter/core.d.ts +36 -9
  94. package/dist/modelrouter/core.js +6 -3
  95. package/dist/modelrouter/index.cjs +204 -125
  96. package/dist/modelrouter/index.cjs.map +1 -1
  97. package/dist/modelrouter/index.d.ts +3 -0
  98. package/dist/modelrouter/index.js +6 -3
  99. package/dist/subagents/anthropic.cjs +268 -52
  100. package/dist/subagents/anthropic.cjs.map +1 -1
  101. package/dist/subagents/anthropic.js +10 -6
  102. package/dist/subagents/vercel.cjs +268 -52
  103. package/dist/subagents/vercel.cjs.map +1 -1
  104. package/dist/subagents/vercel.js +10 -6
  105. package/dist/tools/browser/anthropic.cjs +7 -2
  106. package/dist/tools/browser/anthropic.cjs.map +1 -1
  107. package/dist/tools/browser/anthropic.js +9 -6
  108. package/dist/tools/browser/core.cjs +162 -10
  109. package/dist/tools/browser/core.cjs.map +1 -1
  110. package/dist/tools/browser/core.d.ts +8 -2
  111. package/dist/tools/browser/core.js +8 -5
  112. package/dist/tools/browser/index.cjs +163 -11
  113. package/dist/tools/browser/index.cjs.map +1 -1
  114. package/dist/tools/browser/index.d.ts +2 -0
  115. package/dist/tools/browser/index.js +18 -15
  116. package/dist/tools/browser/index.js.map +1 -1
  117. package/dist/tools/browser/openai.cjs +7 -2
  118. package/dist/tools/browser/openai.cjs.map +1 -1
  119. package/dist/tools/browser/openai.js +9 -6
  120. package/dist/tools/browser/profiles/core.cjs +7 -2
  121. package/dist/tools/browser/profiles/core.cjs.map +1 -1
  122. package/dist/tools/browser/profiles/core.js +3 -3
  123. package/dist/tools/browser/profiles/index.cjs +7 -2
  124. package/dist/tools/browser/profiles/index.cjs.map +1 -1
  125. package/dist/tools/browser/profiles/index.js +3 -3
  126. package/dist/tools/browser/vercel.cjs +7 -2
  127. package/dist/tools/browser/vercel.cjs.map +1 -1
  128. package/dist/tools/browser/vercel.js +9 -6
  129. package/dist/tools/codebase_search/anthropic.cjs +162 -41
  130. package/dist/tools/codebase_search/anthropic.cjs.map +1 -1
  131. package/dist/tools/codebase_search/anthropic.js +7 -4
  132. package/dist/tools/codebase_search/core.cjs +195 -66
  133. package/dist/tools/codebase_search/core.cjs.map +1 -1
  134. package/dist/tools/codebase_search/core.d.ts +18 -7
  135. package/dist/tools/codebase_search/core.js +6 -3
  136. package/dist/tools/codebase_search/index.cjs +162 -41
  137. package/dist/tools/codebase_search/index.cjs.map +1 -1
  138. package/dist/tools/codebase_search/index.d.ts +2 -0
  139. package/dist/tools/codebase_search/index.js +13 -10
  140. package/dist/tools/codebase_search/openai.cjs +162 -41
  141. package/dist/tools/codebase_search/openai.cjs.map +1 -1
  142. package/dist/tools/codebase_search/openai.js +7 -4
  143. package/dist/tools/codebase_search/vercel.cjs +162 -41
  144. package/dist/tools/codebase_search/vercel.cjs.map +1 -1
  145. package/dist/tools/codebase_search/vercel.js +7 -4
  146. package/dist/tools/compact/core.cjs +551 -47
  147. package/dist/tools/compact/core.cjs.map +1 -1
  148. package/dist/tools/compact/core.d.ts +16 -3
  149. package/dist/tools/compact/core.js +7 -1
  150. package/dist/tools/compact/index.cjs +549 -47
  151. package/dist/tools/compact/index.cjs.map +1 -1
  152. package/dist/tools/compact/index.d.ts +2 -0
  153. package/dist/tools/compact/index.js +8 -2
  154. package/dist/tools/fastapply/anthropic.cjs +32 -3
  155. package/dist/tools/fastapply/anthropic.cjs.map +1 -1
  156. package/dist/tools/fastapply/anthropic.js +8 -4
  157. package/dist/tools/fastapply/apply.cjs +23 -3
  158. package/dist/tools/fastapply/apply.cjs.map +1 -1
  159. package/dist/tools/fastapply/apply.js +2 -2
  160. package/dist/tools/fastapply/core.cjs +258 -13
  161. package/dist/tools/fastapply/core.cjs.map +1 -1
  162. package/dist/tools/fastapply/core.d.ts +8 -2
  163. package/dist/tools/fastapply/core.js +7 -3
  164. package/dist/tools/fastapply/index.cjs +32 -3
  165. package/dist/tools/fastapply/index.cjs.map +1 -1
  166. package/dist/tools/fastapply/index.d.ts +2 -0
  167. package/dist/tools/fastapply/index.js +13 -9
  168. package/dist/tools/fastapply/openai.cjs +32 -3
  169. package/dist/tools/fastapply/openai.cjs.map +1 -1
  170. package/dist/tools/fastapply/openai.js +8 -4
  171. package/dist/tools/fastapply/vercel.cjs +32 -3
  172. package/dist/tools/fastapply/vercel.cjs.map +1 -1
  173. package/dist/tools/fastapply/vercel.js +8 -4
  174. package/dist/tools/index.cjs +32 -3
  175. package/dist/tools/index.cjs.map +1 -1
  176. package/dist/tools/index.d.ts +2 -0
  177. package/dist/tools/index.js +13 -9
  178. package/dist/tools/reflex/core.cjs +693 -0
  179. package/dist/tools/reflex/core.cjs.map +1 -0
  180. package/dist/tools/reflex/core.d.ts +53 -0
  181. package/dist/tools/reflex/core.js +16 -0
  182. package/dist/tools/reflex/core.js.map +1 -0
  183. package/dist/tools/reflex/index.cjs +693 -0
  184. package/dist/tools/reflex/index.cjs.map +1 -0
  185. package/dist/tools/reflex/index.d.ts +5 -0
  186. package/dist/tools/reflex/index.js +16 -0
  187. package/dist/tools/reflex/index.js.map +1 -0
  188. package/dist/tools/reflex/types.cjs +19 -0
  189. package/dist/tools/reflex/types.cjs.map +1 -0
  190. package/dist/tools/reflex/types.d.ts +113 -0
  191. package/dist/tools/reflex/types.js +1 -0
  192. package/dist/tools/reflex/types.js.map +1 -0
  193. package/dist/tools/utils/resilience.cjs +7 -2
  194. package/dist/tools/utils/resilience.cjs.map +1 -1
  195. package/dist/tools/utils/resilience.js +2 -2
  196. package/dist/tools/warp_grep/agent/runner.cjs +7 -2
  197. package/dist/tools/warp_grep/agent/runner.cjs.map +1 -1
  198. package/dist/tools/warp_grep/agent/runner.js +2 -2
  199. package/dist/tools/warp_grep/anthropic.cjs +268 -52
  200. package/dist/tools/warp_grep/anthropic.cjs.map +1 -1
  201. package/dist/tools/warp_grep/anthropic.d.ts +2 -0
  202. package/dist/tools/warp_grep/anthropic.js +10 -6
  203. package/dist/tools/warp_grep/client.cjs +268 -52
  204. package/dist/tools/warp_grep/client.cjs.map +1 -1
  205. package/dist/tools/warp_grep/client.d.ts +8 -2
  206. package/dist/tools/warp_grep/client.js +9 -5
  207. package/dist/tools/warp_grep/gemini.cjs +268 -52
  208. package/dist/tools/warp_grep/gemini.cjs.map +1 -1
  209. package/dist/tools/warp_grep/gemini.d.ts +2 -0
  210. package/dist/tools/warp_grep/gemini.js +9 -5
  211. package/dist/tools/warp_grep/gemini.js.map +1 -1
  212. package/dist/tools/warp_grep/harness.js +5 -5
  213. package/dist/tools/warp_grep/index.cjs +268 -52
  214. package/dist/tools/warp_grep/index.cjs.map +1 -1
  215. package/dist/tools/warp_grep/index.d.ts +2 -0
  216. package/dist/tools/warp_grep/index.js +12 -8
  217. package/dist/tools/warp_grep/openai.cjs +268 -52
  218. package/dist/tools/warp_grep/openai.cjs.map +1 -1
  219. package/dist/tools/warp_grep/openai.d.ts +2 -0
  220. package/dist/tools/warp_grep/openai.js +10 -6
  221. package/dist/tools/warp_grep/providers/local.js +2 -2
  222. package/dist/tools/warp_grep/vercel.cjs +268 -52
  223. package/dist/tools/warp_grep/vercel.cjs.map +1 -1
  224. package/dist/tools/warp_grep/vercel.d.ts +2 -0
  225. package/dist/tools/warp_grep/vercel.js +10 -6
  226. package/dist/version.cjs +7 -2
  227. package/dist/version.cjs.map +1 -1
  228. package/dist/version.js +1 -1
  229. package/package.json +7 -2
  230. package/dist/chunk-E5QWXVTF.js.map +0 -1
  231. package/dist/chunk-INBZD4EX.js +0 -197
  232. package/dist/chunk-INBZD4EX.js.map +0 -1
  233. package/dist/chunk-LAGN62H5.js.map +0 -1
  234. package/dist/chunk-LE66XCOI.js.map +0 -1
  235. package/dist/chunk-LNXIVRPY.js.map +0 -1
  236. package/dist/chunk-MKBVWPU7.js.map +0 -1
  237. package/dist/chunk-SCVWDNQP.js +0 -84
  238. package/dist/chunk-SCVWDNQP.js.map +0 -1
  239. package/dist/chunk-VE7J6VYX.js +0 -102
  240. package/dist/chunk-VE7J6VYX.js.map +0 -1
  241. package/dist/chunk-YG2I377B.js.map +0 -1
  242. /package/dist/{chunk-IY7DESC3.js.map → chunk-2SNAXTUJ.js.map} +0 -0
  243. /package/dist/{chunk-5KFQBI4J.js.map → chunk-5DA6SZQJ.js.map} +0 -0
  244. /package/dist/{chunk-76XER44U.js.map → chunk-7PVVPLRL.js.map} +0 -0
  245. /package/dist/{chunk-BCPZAPWY.js.map → chunk-AE7M2I52.js.map} +0 -0
  246. /package/dist/{chunk-OJQYBWHR.js.map → chunk-ESXCQBMU.js.map} +0 -0
  247. /package/dist/{chunk-5IR3YE77.js.map → chunk-IJ33I7P5.js.map} +0 -0
  248. /package/dist/{chunk-6LPWEZ6H.js.map → chunk-MO6S2LRD.js.map} +0 -0
  249. /package/dist/{chunk-S4IEM5EG.js.map → chunk-NI7PWQ3B.js.map} +0 -0
  250. /package/dist/{chunk-GLQWEINZ.js.map → chunk-QAXXE4AD.js.map} +0 -0
  251. /package/dist/{chunk-G4FPDEUP.js.map → chunk-QQXNZIVK.js.map} +0 -0
  252. /package/dist/{chunk-A3ZUWLYX.js.map → chunk-QZ3V2BP7.js.map} +0 -0
  253. /package/dist/{chunk-SYD6BRQX.js.map → chunk-SJVLAGUL.js.map} +0 -0
  254. /package/dist/{chunk-JMEQ6FLB.js.map → chunk-U4J3BVAQ.js.map} +0 -0
  255. /package/dist/{chunk-QAWYDWDW.js.map → chunk-U4MRSZQQ.js.map} +0 -0
  256. /package/dist/{chunk-WU3D46MH.js.map → chunk-UADW6FYD.js.map} +0 -0
  257. /package/dist/{chunk-K7NY5SVR.js.map → chunk-VBARKJWL.js.map} +0 -0
  258. /package/dist/{chunk-OPNTDMHH.js.map → chunk-VLZ6PNAD.js.map} +0 -0
  259. /package/dist/{chunk-GUGHUAJU.js.map → chunk-XJDXV5VX.js.map} +0 -0
  260. /package/dist/{chunk-GPNUS3H2.js.map → chunk-XYTYIAMQ.js.map} +0 -0
package/dist/client.cjs CHANGED
@@ -30,66 +30,13 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
30
30
  ));
31
31
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
32
32
 
33
- // logger.ts
34
- var MorphLogger, logger;
35
- var init_logger = __esm({
36
- "logger.ts"() {
37
- "use strict";
38
- MorphLogger = class {
39
- enabled;
40
- fileStream;
41
- /** Resolves once the file stream is initialized (or immediately if no file logging). */
42
- ready;
43
- constructor() {
44
- this.enabled = typeof process !== "undefined" && (process.env.MORPH_DEBUG === "1" || !!process.env.MORPH_LOG_FILE);
45
- this.fileStream = null;
46
- const f = typeof process !== "undefined" ? process.env.MORPH_LOG_FILE : void 0;
47
- if (f) {
48
- this.ready = import("fs").then((fs5) => {
49
- this.fileStream = fs5.createWriteStream(f, { flags: "a" });
50
- }).catch(() => {
51
- });
52
- } else {
53
- this.ready = Promise.resolve();
54
- }
55
- }
56
- debug(component, msg, data) {
57
- this._log("debug", component, msg, data);
58
- }
59
- info(component, msg, data) {
60
- this._log("info", component, msg, data);
61
- }
62
- warn(component, msg, data) {
63
- this._log("warn", component, msg, data);
64
- }
65
- error(component, msg, data) {
66
- this._log("error", component, msg, data);
67
- }
68
- enable() {
69
- this.enabled = true;
70
- }
71
- get isEnabled() {
72
- return this.enabled;
73
- }
74
- _log(level, component, msg, data) {
75
- if (level !== "error" && !this.enabled) return;
76
- const ts = (/* @__PURE__ */ new Date()).toISOString();
77
- const prefix = `[${ts}] [${level.toUpperCase()}] [${component}]`;
78
- console.error(data ? `${prefix} ${msg} ${JSON.stringify(data)}` : `${prefix} ${msg}`);
79
- this.fileStream?.write(JSON.stringify({ ts, level, component, msg, ...data && { data } }) + "\n");
80
- }
81
- };
82
- logger = new MorphLogger();
83
- }
84
- });
85
-
86
33
  // package.json
87
34
  var package_default;
88
35
  var init_package = __esm({
89
36
  "package.json"() {
90
37
  package_default = {
91
38
  name: "@morphllm/morphsdk",
92
- version: "0.2.170",
39
+ version: "0.2.172",
93
40
  description: "TypeScript SDK and CLI for Morph Fast Apply integration",
94
41
  type: "module",
95
42
  main: "./dist/index.cjs",
@@ -226,6 +173,11 @@ var init_package = __esm({
226
173
  import: "./dist/tools/compact/index.js",
227
174
  require: "./dist/tools/compact/index.cjs"
228
175
  },
176
+ "./tools/reflex": {
177
+ types: "./dist/tools/reflex/index.d.ts",
178
+ import: "./dist/tools/reflex/index.js",
179
+ require: "./dist/tools/reflex/index.cjs"
180
+ },
229
181
  "./subagents": {
230
182
  types: "./dist/subagents/index.d.ts",
231
183
  import: "./dist/subagents/index.js",
@@ -251,7 +203,7 @@ var init_package = __esm({
251
203
  "!dist/**/*.test.*"
252
204
  ],
253
205
  scripts: {
254
- build: "tsup version.ts index.ts edge.ts client.ts tools/index.ts tools/fastapply/index.ts tools/fastapply/core.ts tools/fastapply/apply.ts tools/fastapply/types.ts tools/fastapply/prompts.ts tools/fastapply/anthropic.ts tools/fastapply/openai.ts tools/fastapply/vercel.ts tools/codebase_search/index.ts tools/codebase_search/core.ts tools/codebase_search/types.ts tools/codebase_search/prompts.ts tools/codebase_search/anthropic.ts tools/codebase_search/openai.ts tools/codebase_search/vercel.ts tools/warp_grep/index.ts tools/warp_grep/client.ts tools/warp_grep/openai.ts tools/warp_grep/anthropic.ts tools/warp_grep/vercel.ts tools/warp_grep/gemini.ts tools/warp_grep/harness.ts tools/warp_grep/agent/config.ts tools/warp_grep/agent/parser.ts tools/warp_grep/agent/runner.ts tools/warp_grep/agent/types.ts tools/warp_grep/agent/formatter.ts tools/warp_grep/providers/types.ts tools/warp_grep/providers/local.ts tools/warp_grep/providers/remote.ts tools/warp_grep/providers/code_storage_http.ts tools/warp_grep/tools/grep.ts tools/warp_grep/tools/analyse.ts tools/warp_grep/tools/read.ts tools/warp_grep/tools/finish.ts tools/warp_grep/utils/paths.ts tools/warp_grep/utils/github.ts tools/warp_grep/utils/ripgrep.ts tools/warp_grep/utils/format.ts tools/warp_grep/utils/files.ts git/index.ts git/client.ts git/config.ts git/types.ts tools/browser/index.ts tools/browser/core.ts tools/browser/types.ts tools/browser/prompts.ts tools/browser/anthropic.ts tools/browser/openai.ts tools/browser/vercel.ts tools/browser/live.ts tools/browser/errors.ts tools/browser/profiles/index.ts tools/browser/profiles/core.ts tools/browser/profiles/types.ts modelrouter/index.ts modelrouter/core.ts modelrouter/types.ts tools/compact/index.ts tools/compact/core.ts tools/compact/types.ts tools/utils/resilience.ts subagents/index.ts subagents/types.ts subagents/prompts.ts subagents/vercel.ts subagents/anthropic.ts --format esm,cjs --sourcemap --clean --dts --dts-resolve",
206
+ build: "tsup version.ts index.ts edge.ts client.ts core/index.ts core/client.ts core/resource.ts core/error.ts tools/index.ts tools/fastapply/index.ts tools/fastapply/core.ts tools/fastapply/apply.ts tools/fastapply/types.ts tools/fastapply/prompts.ts tools/fastapply/anthropic.ts tools/fastapply/openai.ts tools/fastapply/vercel.ts tools/codebase_search/index.ts tools/codebase_search/core.ts tools/codebase_search/types.ts tools/codebase_search/prompts.ts tools/codebase_search/anthropic.ts tools/codebase_search/openai.ts tools/codebase_search/vercel.ts tools/warp_grep/index.ts tools/warp_grep/client.ts tools/warp_grep/openai.ts tools/warp_grep/anthropic.ts tools/warp_grep/vercel.ts tools/warp_grep/gemini.ts tools/warp_grep/harness.ts tools/warp_grep/agent/config.ts tools/warp_grep/agent/parser.ts tools/warp_grep/agent/runner.ts tools/warp_grep/agent/types.ts tools/warp_grep/agent/formatter.ts tools/warp_grep/providers/types.ts tools/warp_grep/providers/local.ts tools/warp_grep/providers/remote.ts tools/warp_grep/providers/code_storage_http.ts tools/warp_grep/tools/grep.ts tools/warp_grep/tools/analyse.ts tools/warp_grep/tools/read.ts tools/warp_grep/tools/finish.ts tools/warp_grep/utils/paths.ts tools/warp_grep/utils/github.ts tools/warp_grep/utils/ripgrep.ts tools/warp_grep/utils/format.ts tools/warp_grep/utils/files.ts git/index.ts git/client.ts git/config.ts git/types.ts tools/browser/index.ts tools/browser/core.ts tools/browser/types.ts tools/browser/prompts.ts tools/browser/anthropic.ts tools/browser/openai.ts tools/browser/vercel.ts tools/browser/live.ts tools/browser/errors.ts tools/browser/profiles/index.ts tools/browser/profiles/core.ts tools/browser/profiles/types.ts modelrouter/index.ts modelrouter/core.ts modelrouter/types.ts tools/compact/index.ts tools/compact/core.ts tools/compact/types.ts tools/reflex/index.ts tools/reflex/core.ts tools/reflex/types.ts tools/utils/resilience.ts subagents/index.ts subagents/types.ts subagents/prompts.ts subagents/vercel.ts subagents/anthropic.ts --format esm,cjs --sourcemap --clean --dts --dts-resolve",
255
207
  prepare: "npm run build",
256
208
  typecheck: "tsc --noEmit",
257
209
  lint: "eslint .",
@@ -342,6 +294,59 @@ var init_version = __esm({
342
294
  }
343
295
  });
344
296
 
297
+ // logger.ts
298
+ var MorphLogger, logger;
299
+ var init_logger = __esm({
300
+ "logger.ts"() {
301
+ "use strict";
302
+ MorphLogger = class {
303
+ enabled;
304
+ fileStream;
305
+ /** Resolves once the file stream is initialized (or immediately if no file logging). */
306
+ ready;
307
+ constructor() {
308
+ this.enabled = typeof process !== "undefined" && (process.env.MORPH_DEBUG === "1" || !!process.env.MORPH_LOG_FILE);
309
+ this.fileStream = null;
310
+ const f = typeof process !== "undefined" ? process.env.MORPH_LOG_FILE : void 0;
311
+ if (f) {
312
+ this.ready = import("fs").then((fs5) => {
313
+ this.fileStream = fs5.createWriteStream(f, { flags: "a" });
314
+ }).catch(() => {
315
+ });
316
+ } else {
317
+ this.ready = Promise.resolve();
318
+ }
319
+ }
320
+ debug(component, msg, data) {
321
+ this._log("debug", component, msg, data);
322
+ }
323
+ info(component, msg, data) {
324
+ this._log("info", component, msg, data);
325
+ }
326
+ warn(component, msg, data) {
327
+ this._log("warn", component, msg, data);
328
+ }
329
+ error(component, msg, data) {
330
+ this._log("error", component, msg, data);
331
+ }
332
+ enable() {
333
+ this.enabled = true;
334
+ }
335
+ get isEnabled() {
336
+ return this.enabled;
337
+ }
338
+ _log(level, component, msg, data) {
339
+ if (level !== "error" && !this.enabled) return;
340
+ const ts = (/* @__PURE__ */ new Date()).toISOString();
341
+ const prefix = `[${ts}] [${level.toUpperCase()}] [${component}]`;
342
+ console.error(data ? `${prefix} ${msg} ${JSON.stringify(data)}` : `${prefix} ${msg}`);
343
+ this.fileStream?.write(JSON.stringify({ ts, level, component, msg, ...data && { data } }) + "\n");
344
+ }
345
+ };
346
+ logger = new MorphLogger();
347
+ }
348
+ });
349
+
345
350
  // tools/fastapply/apply.ts
346
351
  var apply_exports = {};
347
352
  __export(apply_exports, {
@@ -384,7 +389,7 @@ async function callMorphAPI(originalCode, codeEdit, instructions, filepath, conf
384
389
  const apiUrl = config.morphApiUrl || DEFAULT_API_URL;
385
390
  const useLarge = config.large ?? (typeof process !== "undefined" ? process.env?.MORPH_LARGE_APPLY !== "false" : true);
386
391
  const model = useLarge ? "morph-v3-large" : "morph-v3-fast";
387
- const timeout = config.timeout || DEFAULT_TIMEOUT;
392
+ const timeout = config.timeout || DEFAULT_TIMEOUT2;
388
393
  const debug = config.debug || false;
389
394
  if (!apiKey) {
390
395
  throw new Error(
@@ -424,11 +429,26 @@ async function callMorphAPI(originalCode, codeEdit, instructions, filepath, conf
424
429
  return { content, completionId: completion.id };
425
430
  } catch (error) {
426
431
  const elapsed = Date.now() - startTime;
432
+ const status = error?.status || error?.response?.status;
427
433
  logger.error("FastApply", "http_error", {
428
- status: error?.status || error?.response?.status,
434
+ status,
429
435
  error: error?.message,
430
436
  latency_ms: elapsed
431
437
  });
438
+ if (status === 401) {
439
+ const err = new Error(
440
+ "Authentication failed: Your Morph API key is invalid or has been revoked. Please visit https://morphllm.com to get a valid API key, then update your MCP configuration."
441
+ );
442
+ err.status = 401;
443
+ throw err;
444
+ }
445
+ if (status === 429) {
446
+ const err = new Error(
447
+ "Rate limited: You've exceeded your Morph API usage limits. Please visit https://morphllm.com to check your plan and purchase additional credits."
448
+ );
449
+ err.status = 429;
450
+ throw err;
451
+ }
432
452
  throw error;
433
453
  }
434
454
  }
@@ -463,7 +483,7 @@ async function applyEdit(input, config = {}) {
463
483
  };
464
484
  }
465
485
  }
466
- var import_diff, import_openai, DEFAULT_API_URL, DEFAULT_TIMEOUT;
486
+ var import_diff, import_openai, DEFAULT_API_URL, DEFAULT_TIMEOUT2;
467
487
  var init_apply = __esm({
468
488
  "tools/fastapply/apply.ts"() {
469
489
  "use strict";
@@ -472,7 +492,7 @@ var init_apply = __esm({
472
492
  init_version();
473
493
  init_logger();
474
494
  DEFAULT_API_URL = "https://api.morphllm.com";
475
- DEFAULT_TIMEOUT = 9e4;
495
+ DEFAULT_TIMEOUT2 = 9e4;
476
496
  }
477
497
  });
478
498
 
@@ -1069,11 +1089,229 @@ __export(client_exports, {
1069
1089
  MorphClient: () => MorphClient
1070
1090
  });
1071
1091
  module.exports = __toCommonJS(client_exports);
1092
+
1093
+ // tools/utils/resilience.ts
1094
+ init_version();
1095
+ var DEFAULT_RETRY_CONFIG = {
1096
+ maxRetries: 3,
1097
+ initialDelay: 1e3,
1098
+ maxDelay: 3e4,
1099
+ backoffMultiplier: 2,
1100
+ retryableErrors: ["ECONNREFUSED", "ETIMEDOUT", "ENOTFOUND"]
1101
+ };
1102
+ async function fetchWithRetry(url, options, retryConfig = {}) {
1103
+ const {
1104
+ maxRetries = DEFAULT_RETRY_CONFIG.maxRetries,
1105
+ initialDelay = DEFAULT_RETRY_CONFIG.initialDelay,
1106
+ maxDelay = DEFAULT_RETRY_CONFIG.maxDelay,
1107
+ backoffMultiplier = DEFAULT_RETRY_CONFIG.backoffMultiplier,
1108
+ retryableErrors = DEFAULT_RETRY_CONFIG.retryableErrors,
1109
+ onRetry
1110
+ } = retryConfig;
1111
+ let lastError = null;
1112
+ let delay = initialDelay;
1113
+ options = { ...options, headers: { "X-Morph-SDK-Version": SDK_VERSION, ...options.headers } };
1114
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
1115
+ try {
1116
+ const response = await fetch(url, options);
1117
+ if (response.status === 429 || response.status === 503) {
1118
+ if (attempt < maxRetries) {
1119
+ const retryAfter = response.headers.get("Retry-After");
1120
+ const waitTime = retryAfter ? parseInt(retryAfter) * 1e3 : Math.min(delay, maxDelay);
1121
+ const error = new Error(`HTTP ${response.status}: Retrying after ${waitTime}ms`);
1122
+ if (onRetry) {
1123
+ onRetry(attempt + 1, error);
1124
+ }
1125
+ await sleep(waitTime);
1126
+ delay *= backoffMultiplier;
1127
+ continue;
1128
+ }
1129
+ }
1130
+ return response;
1131
+ } catch (error) {
1132
+ lastError = error;
1133
+ const isRetryable = retryableErrors.some(
1134
+ (errType) => lastError?.message?.includes(errType)
1135
+ );
1136
+ if (!isRetryable || attempt === maxRetries) {
1137
+ throw lastError;
1138
+ }
1139
+ const waitTime = Math.min(delay, maxDelay);
1140
+ if (onRetry) {
1141
+ onRetry(attempt + 1, lastError);
1142
+ }
1143
+ await sleep(waitTime);
1144
+ delay *= backoffMultiplier;
1145
+ }
1146
+ }
1147
+ throw lastError || new Error("Max retries exceeded");
1148
+ }
1149
+ async function withTimeout(promise, timeoutMs, errorMessage) {
1150
+ let timeoutId;
1151
+ const timeoutPromise = new Promise((_, reject) => {
1152
+ timeoutId = setTimeout(() => {
1153
+ reject(new Error(errorMessage || `Operation timed out after ${timeoutMs}ms`));
1154
+ }, timeoutMs);
1155
+ });
1156
+ try {
1157
+ const result = await Promise.race([promise, timeoutPromise]);
1158
+ clearTimeout(timeoutId);
1159
+ return result;
1160
+ } catch (error) {
1161
+ clearTimeout(timeoutId);
1162
+ throw error;
1163
+ }
1164
+ }
1165
+ function sleep(ms) {
1166
+ return new Promise((resolve2) => setTimeout(resolve2, ms));
1167
+ }
1168
+ var MorphError = class extends Error {
1169
+ constructor(message, code, statusCode, retryable = false) {
1170
+ super(message);
1171
+ this.code = code;
1172
+ this.statusCode = statusCode;
1173
+ this.retryable = retryable;
1174
+ this.name = "MorphError";
1175
+ }
1176
+ };
1177
+
1178
+ // core/client.ts
1179
+ init_logger();
1180
+ init_version();
1181
+
1182
+ // core/error.ts
1183
+ async function toMorphError(response) {
1184
+ let message = `Morph API request failed (${response.status})`;
1185
+ let code = "api_error";
1186
+ try {
1187
+ const body = await response.json();
1188
+ message = body.error?.message ?? body.message ?? message;
1189
+ code = body.error?.code ?? body.error?.type ?? code;
1190
+ } catch {
1191
+ }
1192
+ if (response.status === 401) code = "authentication_error";
1193
+ if (response.status === 429) code = "rate_limit_exceeded";
1194
+ const retryable = response.status === 429 || response.status === 503;
1195
+ return new MorphError(message, code, response.status, retryable);
1196
+ }
1197
+
1198
+ // core/client.ts
1199
+ var DEFAULT_BASE_URL = "https://api.morphllm.com";
1200
+ var DEFAULT_REPOS_URL = "https://repos.morphllm.com";
1201
+ var DEFAULT_BROWSER_URL = "https://browser.morphllm.com";
1202
+ var DEFAULT_TIMEOUT = 6e4;
1203
+ var env = (name) => typeof process !== "undefined" ? process.env?.[name] : void 0;
1204
+ var stripTrailingSlash = (url) => url.replace(/\/+$/, "");
1205
+ var MorphAPIClient = class {
1206
+ /** Explicit key as provided; resolved against env at request time. */
1207
+ apiKey;
1208
+ baseURL;
1209
+ reposURL;
1210
+ browserURL;
1211
+ /** Explicit default timeout (ms), if set. The request default is applied lazily so
1212
+ * resources can read an undefined value and supply their own fallback. */
1213
+ timeout;
1214
+ retryConfig;
1215
+ debug;
1216
+ constructor(options = {}) {
1217
+ this.apiKey = options.apiKey;
1218
+ this.baseURL = stripTrailingSlash(options.baseURL ?? DEFAULT_BASE_URL);
1219
+ this.reposURL = stripTrailingSlash(options.reposURL ?? env("MORPH_SEARCH_URL") ?? DEFAULT_REPOS_URL);
1220
+ this.browserURL = stripTrailingSlash(
1221
+ options.browserURL ?? (env("MORPH_ENVIRONMENT") === "DEV" ? "http://localhost:8000" : DEFAULT_BROWSER_URL)
1222
+ );
1223
+ this.timeout = options.timeout;
1224
+ this.retryConfig = options.retryConfig;
1225
+ this.debug = options.debug ?? false;
1226
+ if (this.debug) logger.enable();
1227
+ }
1228
+ /** The key actually used for requests: explicit, else `MORPH_API_KEY`. */
1229
+ resolveApiKey() {
1230
+ return this.apiKey ?? env("MORPH_API_KEY");
1231
+ }
1232
+ /** Headers shared with tools that bring their own HTTP client (FastApply/WarpGrep via the `openai` package). */
1233
+ defaultHeaders() {
1234
+ return { "X-Morph-SDK-Version": SDK_VERSION };
1235
+ }
1236
+ buildURL(path6, baseURL) {
1237
+ if (/^https?:\/\//i.test(path6)) return path6;
1238
+ const base = stripTrailingSlash(baseURL ?? this.baseURL);
1239
+ return `${base}${path6.startsWith("/") ? "" : "/"}${path6}`;
1240
+ }
1241
+ buildHeaders(apiKey, extra) {
1242
+ return {
1243
+ "Content-Type": "application/json",
1244
+ "X-Morph-SDK-Version": SDK_VERSION,
1245
+ Authorization: `Bearer ${apiKey}`,
1246
+ ...extra
1247
+ };
1248
+ }
1249
+ applyQuery(url, query) {
1250
+ if (!query) return url;
1251
+ const params = new URLSearchParams();
1252
+ for (const [key, value] of Object.entries(query)) {
1253
+ if (value !== void 0 && value !== null) params.set(key, String(value));
1254
+ }
1255
+ const qs = params.toString();
1256
+ return qs ? `${url}${url.includes("?") ? "&" : "?"}${qs}` : url;
1257
+ }
1258
+ async request(method, path6, opts = {}) {
1259
+ const apiKey = this.resolveApiKey();
1260
+ if (!apiKey) {
1261
+ throw new MorphError(
1262
+ "Morph API key not found. Set the MORPH_API_KEY environment variable or pass apiKey in config.",
1263
+ "missing_api_key",
1264
+ 401
1265
+ );
1266
+ }
1267
+ const url = this.applyQuery(this.buildURL(path6, opts.baseURL), opts.query);
1268
+ const timeout = opts.timeout ?? this.timeout ?? DEFAULT_TIMEOUT;
1269
+ const init = {
1270
+ method,
1271
+ headers: this.buildHeaders(apiKey, opts.headers),
1272
+ ...opts.body !== void 0 ? { body: JSON.stringify(opts.body) } : {},
1273
+ ...opts.signal ? { signal: opts.signal } : {}
1274
+ };
1275
+ logger.debug("MorphAPIClient", "request", { method, url });
1276
+ const response = await withTimeout(
1277
+ fetchWithRetry(url, init, this.retryConfig ?? {}),
1278
+ timeout,
1279
+ `Morph request to ${url} timed out after ${timeout}ms`
1280
+ );
1281
+ if (opts.raw) return response;
1282
+ if (!response.ok) throw await toMorphError(response);
1283
+ if (opts.stream) return response;
1284
+ if (response.status === 204) return void 0;
1285
+ const text = await response.text();
1286
+ return text ? JSON.parse(text) : void 0;
1287
+ }
1288
+ get(path6, opts) {
1289
+ return this.request("GET", path6, opts);
1290
+ }
1291
+ post(path6, opts) {
1292
+ return this.request("POST", path6, opts);
1293
+ }
1294
+ delete(path6, opts) {
1295
+ return this.request("DELETE", path6, opts);
1296
+ }
1297
+ };
1298
+
1299
+ // client.ts
1072
1300
  init_logger();
1073
1301
 
1074
1302
  // tools/fastapply/core.ts
1075
1303
  var import_path = require("path");
1076
1304
  init_logger();
1305
+
1306
+ // core/resource.ts
1307
+ var APIResource = class {
1308
+ _client;
1309
+ constructor(client) {
1310
+ this._client = client;
1311
+ }
1312
+ };
1313
+
1314
+ // tools/fastapply/core.ts
1077
1315
  init_apply();
1078
1316
  var DEFAULT_CONFIG = {
1079
1317
  morphApiUrl: "https://api.morphllm.com",
@@ -1083,15 +1321,24 @@ var DEFAULT_CONFIG = {
1083
1321
  timeout: 9e4,
1084
1322
  debug: false
1085
1323
  };
1086
- var FastApplyClient = class {
1324
+ var FastApplyClient = class extends APIResource {
1087
1325
  config;
1088
- constructor(config = {}) {
1326
+ constructor(clientOrConfig = {}) {
1327
+ const isClient = clientOrConfig instanceof MorphAPIClient;
1328
+ super(
1329
+ isClient ? clientOrConfig : new MorphAPIClient({
1330
+ apiKey: clientOrConfig.apiKey,
1331
+ timeout: clientOrConfig.timeout ?? DEFAULT_CONFIG.timeout,
1332
+ retryConfig: clientOrConfig.retryConfig,
1333
+ debug: clientOrConfig.debug
1334
+ })
1335
+ );
1089
1336
  this.config = {
1090
- morphApiKey: config.apiKey,
1091
- morphApiUrl: DEFAULT_CONFIG.morphApiUrl,
1092
- debug: config.debug,
1093
- timeout: config.timeout || DEFAULT_CONFIG.timeout,
1094
- retryConfig: config.retryConfig,
1337
+ morphApiKey: this._client.resolveApiKey(),
1338
+ morphApiUrl: this._client.baseURL,
1339
+ debug: this._client.debug,
1340
+ timeout: (isClient ? void 0 : clientOrConfig.timeout) ?? DEFAULT_CONFIG.timeout,
1341
+ retryConfig: this._client.retryConfig,
1095
1342
  generateUdiff: DEFAULT_CONFIG.generateUdiff,
1096
1343
  autoWrite: DEFAULT_CONFIG.autoWrite
1097
1344
  };
@@ -1189,156 +1436,30 @@ async function executeEditFile(input, config = {}) {
1189
1436
  error: errorMessage
1190
1437
  };
1191
1438
  }
1192
- }
1193
-
1194
- // tools/utils/resilience.ts
1195
- init_version();
1196
- var DEFAULT_RETRY_CONFIG = {
1197
- maxRetries: 3,
1198
- initialDelay: 1e3,
1199
- maxDelay: 3e4,
1200
- backoffMultiplier: 2,
1201
- retryableErrors: ["ECONNREFUSED", "ETIMEDOUT", "ENOTFOUND"]
1202
- };
1203
- async function fetchWithRetry(url, options, retryConfig = {}) {
1204
- const {
1205
- maxRetries = DEFAULT_RETRY_CONFIG.maxRetries,
1206
- initialDelay = DEFAULT_RETRY_CONFIG.initialDelay,
1207
- maxDelay = DEFAULT_RETRY_CONFIG.maxDelay,
1208
- backoffMultiplier = DEFAULT_RETRY_CONFIG.backoffMultiplier,
1209
- retryableErrors = DEFAULT_RETRY_CONFIG.retryableErrors,
1210
- onRetry
1211
- } = retryConfig;
1212
- let lastError = null;
1213
- let delay = initialDelay;
1214
- options = { ...options, headers: { "X-Morph-SDK-Version": SDK_VERSION, ...options.headers } };
1215
- for (let attempt = 0; attempt <= maxRetries; attempt++) {
1216
- try {
1217
- const response = await fetch(url, options);
1218
- if (response.status === 429 || response.status === 503) {
1219
- if (attempt < maxRetries) {
1220
- const retryAfter = response.headers.get("Retry-After");
1221
- const waitTime = retryAfter ? parseInt(retryAfter) * 1e3 : Math.min(delay, maxDelay);
1222
- const error = new Error(`HTTP ${response.status}: Retrying after ${waitTime}ms`);
1223
- if (onRetry) {
1224
- onRetry(attempt + 1, error);
1225
- }
1226
- await sleep(waitTime);
1227
- delay *= backoffMultiplier;
1228
- continue;
1229
- }
1230
- }
1231
- return response;
1232
- } catch (error) {
1233
- lastError = error;
1234
- const isRetryable = retryableErrors.some(
1235
- (errType) => lastError?.message?.includes(errType)
1236
- );
1237
- if (!isRetryable || attempt === maxRetries) {
1238
- throw lastError;
1239
- }
1240
- const waitTime = Math.min(delay, maxDelay);
1241
- if (onRetry) {
1242
- onRetry(attempt + 1, lastError);
1243
- }
1244
- await sleep(waitTime);
1245
- delay *= backoffMultiplier;
1246
- }
1247
- }
1248
- throw lastError || new Error("Max retries exceeded");
1249
- }
1250
- async function withTimeout(promise, timeoutMs, errorMessage) {
1251
- let timeoutId;
1252
- const timeoutPromise = new Promise((_, reject) => {
1253
- timeoutId = setTimeout(() => {
1254
- reject(new Error(errorMessage || `Operation timed out after ${timeoutMs}ms`));
1255
- }, timeoutMs);
1256
- });
1257
- try {
1258
- const result = await Promise.race([promise, timeoutPromise]);
1259
- clearTimeout(timeoutId);
1260
- return result;
1261
- } catch (error) {
1262
- clearTimeout(timeoutId);
1263
- throw error;
1264
- }
1265
- }
1266
- function sleep(ms) {
1267
- return new Promise((resolve2) => setTimeout(resolve2, ms));
1268
- }
1269
-
1270
- // tools/codebase_search/core.ts
1271
- init_logger();
1272
- var CodebaseSearchClient = class {
1273
- config;
1274
- constructor(config = {}) {
1275
- this.config = {
1276
- apiKey: config.apiKey,
1277
- searchUrl: process.env.MORPH_SEARCH_URL || "https://repos.morphllm.com",
1278
- debug: config.debug,
1279
- timeout: config.timeout || 3e4,
1280
- retryConfig: config.retryConfig
1281
- };
1282
- }
1283
- /**
1284
- * Execute a semantic code search
1285
- *
1286
- * @param input - Search parameters including query, repoId, and target directories
1287
- * @param overrides - Optional config overrides for this operation
1288
- * @returns Search results with ranked code matches
1289
- */
1290
- async search(input, overrides) {
1291
- return executeCodebaseSearch(
1292
- {
1293
- query: input.query,
1294
- target_directories: input.target_directories,
1295
- explanation: input.explanation,
1296
- limit: input.limit
1297
- },
1298
- { ...this.config, repoId: input.repoId, ...overrides }
1299
- );
1300
- }
1301
- };
1302
- async function executeCodebaseSearch(input, config) {
1303
- const apiKey = config.apiKey || process.env.MORPH_API_KEY;
1304
- if (!apiKey) {
1305
- throw new Error("MORPH_API_KEY not found. Set environment variable or pass in config");
1306
- }
1307
- const searchUrl = config.searchUrl || process.env.MORPH_SEARCH_URL || "https://repos.morphllm.com";
1308
- const timeout = config.timeout || 3e4;
1309
- logger.debug("CodebaseSearch", "request", { query: input.query.slice(0, 100), repo_id: config.repoId, url: `${searchUrl}/v1/codebase_search` });
1439
+ }
1440
+
1441
+ // tools/codebase_search/core.ts
1442
+ init_logger();
1443
+ var DEFAULT_TIMEOUT3 = 3e4;
1444
+ var emptyStats = { totalResults: 0, candidatesRetrieved: 0, searchTimeMs: 0 };
1445
+ async function runSearch(client, input, repoId, timeout, baseURL) {
1310
1446
  const startTime = Date.now();
1447
+ logger.debug("CodebaseSearch", "request", { query: input.query.slice(0, 100), repo_id: repoId });
1311
1448
  try {
1312
- const fetchPromise = fetchWithRetry(
1313
- `${searchUrl}/v1/codebase_search`,
1449
+ const data = await client.post(
1450
+ "/v1/codebase_search",
1314
1451
  {
1315
- method: "POST",
1316
- headers: {
1317
- "Content-Type": "application/json",
1318
- "Authorization": `Bearer ${apiKey}`
1319
- },
1320
- body: JSON.stringify({
1452
+ baseURL: baseURL ?? client.reposURL,
1453
+ timeout,
1454
+ body: {
1321
1455
  query: input.query,
1322
- repoId: config.repoId,
1456
+ repoId,
1323
1457
  targetDirectories: input.target_directories || [],
1324
1458
  limit: input.limit || 10,
1325
1459
  candidateLimit: 50
1326
- })
1327
- },
1328
- config.retryConfig
1460
+ }
1461
+ }
1329
1462
  );
1330
- const response = await withTimeout(fetchPromise, timeout, `Codebase search timed out after ${timeout}ms`);
1331
- if (!response.ok) {
1332
- const errorText = await response.text();
1333
- logger.error("CodebaseSearch", "response_error", { status: response.status, error: errorText, latency_ms: Date.now() - startTime });
1334
- return {
1335
- success: false,
1336
- results: [],
1337
- stats: { totalResults: 0, candidatesRetrieved: 0, searchTimeMs: 0 },
1338
- error: `Search failed (${response.status}): ${errorText}`
1339
- };
1340
- }
1341
- const data = await response.json();
1342
1463
  const elapsed = Date.now() - startTime;
1343
1464
  logger.debug("CodebaseSearch", "response", { results_count: data.results?.length || 0, latency_ms: elapsed });
1344
1465
  return {
@@ -1347,14 +1468,54 @@ async function executeCodebaseSearch(input, config) {
1347
1468
  stats: data.stats || { totalResults: 0, candidatesRetrieved: 0, searchTimeMs: elapsed }
1348
1469
  };
1349
1470
  } catch (error) {
1350
- logger.error("CodebaseSearch", "exception", { error: error instanceof Error ? error.message : String(error), latency_ms: Date.now() - startTime });
1351
- return {
1352
- success: false,
1353
- results: [],
1354
- stats: { totalResults: 0, candidatesRetrieved: 0, searchTimeMs: 0 },
1355
- error: error instanceof Error ? error.message : "Unknown error"
1356
- };
1471
+ const message = error instanceof MorphError && error.statusCode ? `Search failed (${error.statusCode}): ${error.message}` : error instanceof Error ? error.message : "Unknown error";
1472
+ logger.error("CodebaseSearch", "error", { error: message, latency_ms: Date.now() - startTime });
1473
+ return { success: false, results: [], stats: { ...emptyStats }, error: message };
1474
+ }
1475
+ }
1476
+ var CodebaseSearchClient = class extends APIResource {
1477
+ timeout;
1478
+ constructor(clientOrConfig = {}) {
1479
+ super(
1480
+ clientOrConfig instanceof MorphAPIClient ? clientOrConfig : new MorphAPIClient({
1481
+ apiKey: clientOrConfig.apiKey,
1482
+ timeout: clientOrConfig.timeout ?? DEFAULT_TIMEOUT3,
1483
+ retryConfig: clientOrConfig.retryConfig,
1484
+ debug: clientOrConfig.debug
1485
+ })
1486
+ );
1487
+ this.timeout = (clientOrConfig instanceof MorphAPIClient ? void 0 : clientOrConfig.timeout) ?? DEFAULT_TIMEOUT3;
1488
+ }
1489
+ /**
1490
+ * Execute a semantic code search
1491
+ *
1492
+ * @param input - Search parameters including query, repoId, and target directories
1493
+ * @param overrides - Optional config overrides for this operation
1494
+ * @returns Search results with ranked code matches
1495
+ */
1496
+ async search(input, overrides) {
1497
+ return runSearch(
1498
+ this._client,
1499
+ { query: input.query, target_directories: input.target_directories, explanation: input.explanation, limit: input.limit },
1500
+ input.repoId,
1501
+ overrides?.timeout ?? this.timeout,
1502
+ overrides?.searchUrl
1503
+ );
1504
+ }
1505
+ };
1506
+ async function executeCodebaseSearch(input, config) {
1507
+ const apiKey = config.apiKey || process.env.MORPH_API_KEY;
1508
+ if (!apiKey) {
1509
+ throw new Error("MORPH_API_KEY not found. Set environment variable or pass in config");
1357
1510
  }
1511
+ const client = new MorphAPIClient({
1512
+ apiKey,
1513
+ reposURL: config.searchUrl,
1514
+ timeout: config.timeout ?? DEFAULT_TIMEOUT3,
1515
+ retryConfig: config.retryConfig,
1516
+ debug: config.debug
1517
+ });
1518
+ return runSearch(client, input, config.repoId, config.timeout ?? DEFAULT_TIMEOUT3, config.searchUrl);
1358
1519
  }
1359
1520
 
1360
1521
  // tools/browser/core.ts
@@ -1459,7 +1620,7 @@ function resolvePreset(optionsOrPreset) {
1459
1620
  }
1460
1621
 
1461
1622
  // tools/browser/errors.ts
1462
- var MorphError = class extends Error {
1623
+ var MorphError2 = class extends Error {
1463
1624
  /** Error code for programmatic handling */
1464
1625
  code;
1465
1626
  /** Original cause of the error, if any */
@@ -1485,7 +1646,7 @@ var MorphError = class extends Error {
1485
1646
  };
1486
1647
  }
1487
1648
  };
1488
- var MorphValidationError = class extends MorphError {
1649
+ var MorphValidationError = class extends MorphError2 {
1489
1650
  /** The field that failed validation */
1490
1651
  field;
1491
1652
  constructor(message, field) {
@@ -1500,7 +1661,7 @@ var MorphValidationError = class extends MorphError {
1500
1661
  };
1501
1662
  }
1502
1663
  };
1503
- var MorphAPIError = class extends MorphError {
1664
+ var MorphAPIError = class extends MorphError2 {
1504
1665
  /** HTTP status code */
1505
1666
  statusCode;
1506
1667
  /** Request ID for debugging (if available) */
@@ -2029,17 +2190,30 @@ var DEFAULT_CONFIG2 = {
2029
2190
  // 10 minutes for complex tasks
2030
2191
  debug: false
2031
2192
  };
2032
- var BrowserClient = class {
2193
+ var BrowserClient = class extends APIResource {
2033
2194
  config;
2034
2195
  /**
2035
2196
  * Profile management - create and manage browser profiles for storing login state.
2036
2197
  */
2037
2198
  profiles;
2038
- constructor(config = {}) {
2039
- this.config = {
2199
+ constructor(clientOrConfig = {}) {
2200
+ const isClient = clientOrConfig instanceof MorphAPIClient;
2201
+ super(
2202
+ isClient ? clientOrConfig : new MorphAPIClient({
2203
+ apiKey: clientOrConfig.apiKey,
2204
+ browserURL: clientOrConfig.apiUrl,
2205
+ timeout: clientOrConfig.timeout,
2206
+ retryConfig: clientOrConfig.retryConfig,
2207
+ debug: clientOrConfig.debug
2208
+ })
2209
+ );
2210
+ this.config = isClient ? {
2040
2211
  ...DEFAULT_CONFIG2,
2041
- ...config
2042
- };
2212
+ apiUrl: clientOrConfig.browserURL,
2213
+ apiKey: clientOrConfig.resolveApiKey(),
2214
+ retryConfig: clientOrConfig.retryConfig,
2215
+ debug: clientOrConfig.debug
2216
+ } : { ...DEFAULT_CONFIG2, ...clientOrConfig };
2043
2217
  this.profiles = new ProfilesClient(this.config);
2044
2218
  }
2045
2219
  /**
@@ -3561,14 +3735,27 @@ function parseGitHubUrl(input) {
3561
3735
 
3562
3736
  // tools/compact/core.ts
3563
3737
  var DEFAULT_API_URL4 = "https://api.morphllm.com";
3564
- var DEFAULT_TIMEOUT2 = 12e4;
3565
- var CompactClient = class {
3738
+ var DEFAULT_TIMEOUT4 = 12e4;
3739
+ function resolveClient(clientOrConfig) {
3740
+ if (clientOrConfig instanceof MorphAPIClient) return clientOrConfig;
3741
+ return new MorphAPIClient({
3742
+ apiKey: clientOrConfig.morphApiKey,
3743
+ baseURL: clientOrConfig.morphApiUrl ?? DEFAULT_API_URL4,
3744
+ timeout: clientOrConfig.timeout ?? DEFAULT_TIMEOUT4,
3745
+ retryConfig: clientOrConfig.retryConfig,
3746
+ debug: clientOrConfig.debug
3747
+ });
3748
+ }
3749
+ var CompactClient = class extends APIResource {
3750
+ /** Resolved URL/timeout, exposed for backwards-compatible introspection. */
3566
3751
  config;
3567
- constructor(config = {}) {
3752
+ constructor(clientOrConfig = {}) {
3753
+ super(resolveClient(clientOrConfig));
3754
+ const cfg = clientOrConfig instanceof MorphAPIClient ? {} : clientOrConfig;
3568
3755
  this.config = {
3569
- ...config,
3570
- morphApiUrl: config.morphApiUrl ?? DEFAULT_API_URL4,
3571
- timeout: config.timeout ?? DEFAULT_TIMEOUT2
3756
+ morphApiUrl: this._client.baseURL,
3757
+ timeout: cfg.timeout ?? DEFAULT_TIMEOUT4,
3758
+ debug: cfg.debug ?? false
3572
3759
  };
3573
3760
  }
3574
3761
  /**
@@ -3587,17 +3774,6 @@ var CompactClient = class {
3587
3774
  * ```
3588
3775
  */
3589
3776
  async compact(input) {
3590
- const apiKey = this.config.morphApiKey || (typeof process !== "undefined" ? process.env?.MORPH_API_KEY : void 0);
3591
- const debug = this.config.debug || false;
3592
- if (!apiKey) {
3593
- throw new Error(
3594
- "Morph API key not found. Set MORPH_API_KEY environment variable or pass morphApiKey in config."
3595
- );
3596
- }
3597
- const url = `${this.config.morphApiUrl}/v1/compact`;
3598
- if (debug) {
3599
- console.log(`[Compact] Calling ${url}`);
3600
- }
3601
3777
  const body = {
3602
3778
  compression_ratio: input.compressionRatio ?? 0.5,
3603
3779
  preserve_recent: input.preserveRecent ?? 2,
@@ -3605,37 +3781,19 @@ var CompactClient = class {
3605
3781
  include_line_ranges: input.includeLineRanges ?? true,
3606
3782
  include_markers: input.includeMarkers ?? true
3607
3783
  };
3608
- if (input.query !== void 0) {
3609
- body.query = input.query;
3610
- }
3611
- if (input.messages) {
3612
- body.messages = input.messages;
3613
- } else if (typeof input.input === "string") {
3614
- body.input = input.input;
3615
- } else if (Array.isArray(input.input)) {
3616
- body.messages = input.input;
3617
- } else {
3618
- throw new Error("Either 'input' or 'messages' must be provided");
3619
- }
3620
- const startTime = Date.now();
3621
- const response = await fetch(url, {
3622
- method: "POST",
3623
- headers: {
3624
- "Authorization": `Bearer ${apiKey}`,
3625
- "Content-Type": "application/json"
3626
- },
3627
- body: JSON.stringify(body),
3628
- signal: AbortSignal.timeout(this.config.timeout)
3629
- });
3630
- if (!response.ok) {
3631
- const text = await response.text();
3632
- throw new Error(`Compact API error ${response.status}: ${text}`);
3633
- }
3634
- const data = await response.json();
3635
- if (debug) {
3636
- console.log(`[Compact] compact() done in ${Date.now() - startTime}ms`);
3784
+ if (input.query !== void 0) body.query = input.query;
3785
+ if (input.messages) body.messages = input.messages;
3786
+ else if (typeof input.input === "string") body.input = input.input;
3787
+ else if (Array.isArray(input.input)) body.messages = input.input;
3788
+ else throw new Error("Either 'input' or 'messages' must be provided");
3789
+ try {
3790
+ return await this._client.post("/v1/compact", { body, timeout: this.config.timeout });
3791
+ } catch (err) {
3792
+ if (err instanceof MorphError) {
3793
+ throw new Error(`Compact API error ${err.statusCode}: ${err.message}`);
3794
+ }
3795
+ throw err;
3637
3796
  }
3638
- return data;
3639
3797
  }
3640
3798
  };
3641
3799
 
@@ -3691,10 +3849,28 @@ async function getLocalProvider(repoRoot, excludes, allowNames) {
3691
3849
  const opts = allowNames?.length ? { allowNames } : void 0;
3692
3850
  return new LocalRipgrepProvider2(repoRoot, excludes, opts);
3693
3851
  }
3694
- var WarpGrepClient = class {
3852
+ var WarpGrepClient = class extends APIResource {
3695
3853
  config;
3696
- constructor(config = {}) {
3697
- this.config = { ...config };
3854
+ constructor(clientOrConfig = {}) {
3855
+ const isClient = clientOrConfig instanceof MorphAPIClient;
3856
+ super(
3857
+ isClient ? clientOrConfig : new MorphAPIClient({
3858
+ apiKey: clientOrConfig.morphApiKey,
3859
+ baseURL: clientOrConfig.morphApiUrl,
3860
+ timeout: clientOrConfig.timeout,
3861
+ retryConfig: clientOrConfig.retryConfig,
3862
+ debug: clientOrConfig.debug
3863
+ })
3864
+ );
3865
+ const cfg = isClient ? {} : clientOrConfig;
3866
+ this.config = {
3867
+ ...cfg,
3868
+ morphApiKey: this._client.resolveApiKey(),
3869
+ morphApiUrl: this._client.baseURL,
3870
+ timeout: this._client.timeout,
3871
+ retryConfig: this._client.retryConfig,
3872
+ debug: this._client.debug
3873
+ };
3698
3874
  }
3699
3875
  execute(input) {
3700
3876
  const toolConfig = {
@@ -3968,11 +4144,9 @@ var PermissionError = class extends GitHubError {
3968
4144
  };
3969
4145
 
3970
4146
  // tools/github/core.ts
3971
- var DEFAULT_BASE_URL = "https://api.morphllm.com";
3972
- var DEFAULT_TIMEOUT3 = 3e4;
3973
- var GitHubClient = class {
3974
- apiKey;
3975
- baseUrl;
4147
+ var DEFAULT_BASE_URL2 = "https://api.morphllm.com";
4148
+ var DEFAULT_TIMEOUT5 = 3e4;
4149
+ var GitHubClient = class extends APIResource {
3976
4150
  timeout;
3977
4151
  debug;
3978
4152
  defaultInstallationId;
@@ -3997,13 +4171,21 @@ var GitHubClient = class {
3997
4171
  getInstallUrl() {
3998
4172
  return "https://github.com/apps/morph-subagents/installations/new";
3999
4173
  }
4000
- constructor(config = {}) {
4001
- this.apiKey = config.apiKey || process.env.MORPH_API_KEY || "";
4002
- this.baseUrl = config.baseUrl || DEFAULT_BASE_URL;
4003
- this.timeout = config.timeout || DEFAULT_TIMEOUT3;
4174
+ constructor(clientOrConfig = {}, options = {}) {
4175
+ const isClient = clientOrConfig instanceof MorphAPIClient;
4176
+ const config = isClient ? {} : clientOrConfig;
4177
+ super(
4178
+ isClient ? clientOrConfig : new MorphAPIClient({
4179
+ apiKey: config.apiKey,
4180
+ baseURL: config.baseUrl ?? DEFAULT_BASE_URL2,
4181
+ timeout: config.timeout ?? DEFAULT_TIMEOUT5,
4182
+ debug: config.debug
4183
+ })
4184
+ );
4185
+ this.timeout = config.timeout || DEFAULT_TIMEOUT5;
4004
4186
  this.debug = config.debug || false;
4005
- this.defaultInstallationId = config.installationId;
4006
- if (!this.apiKey) {
4187
+ this.defaultInstallationId = isClient ? options.installationId : config.installationId;
4188
+ if (!this._client.resolveApiKey()) {
4007
4189
  throw new Error("API key required. Set MORPH_API_KEY or pass apiKey in config.");
4008
4190
  }
4009
4191
  this.installations = {
@@ -4047,59 +4229,44 @@ var GitHubClient = class {
4047
4229
  * Make an authenticated API request
4048
4230
  */
4049
4231
  async request(method, path6, body) {
4050
- const url = `${this.baseUrl}${path6}`;
4051
4232
  if (this.debug) {
4052
4233
  console.log(`[GitHub SDK] ${method} ${path6}`, body || "");
4053
4234
  }
4054
- const controller = new AbortController();
4055
- const timeoutId = setTimeout(() => controller.abort(), this.timeout);
4235
+ let response;
4056
4236
  try {
4057
- const response = await fetch(url, {
4058
- method,
4059
- headers: {
4060
- "Content-Type": "application/json",
4061
- Authorization: `Bearer ${this.apiKey}`
4062
- },
4063
- body: body ? JSON.stringify(body) : void 0,
4064
- signal: controller.signal
4237
+ response = await this._client.request(method, path6, {
4238
+ body,
4239
+ timeout: this.timeout,
4240
+ raw: true
4065
4241
  });
4066
- clearTimeout(timeoutId);
4067
- if (!response.ok) {
4068
- const errorData = await response.json().catch(() => ({}));
4069
- const message = errorData.error || errorData.detail || errorData.message || response.statusText;
4070
- if (this.debug) {
4071
- console.error(`[GitHub SDK] Error ${response.status}:`, message);
4072
- }
4073
- if (response.status === 404) {
4074
- if (message.includes("installation")) {
4075
- throw new NoInstallationError(message);
4076
- }
4077
- throw new NotFoundError(message);
4078
- }
4079
- if (response.status === 403) {
4080
- throw new PermissionError(message);
4081
- }
4082
- throw new GitHubError(message, response.status, errorData.code);
4242
+ } catch (error) {
4243
+ if (error instanceof Error && /timed out/i.test(error.message)) {
4244
+ throw new GitHubError("Request timeout", 408, "TIMEOUT");
4083
4245
  }
4084
- const data = await response.json();
4246
+ throw new GitHubError(error instanceof Error ? error.message : "Unknown error", 500, "UNKNOWN");
4247
+ }
4248
+ if (!response.ok) {
4249
+ const errorData = await response.json().catch(() => ({}));
4250
+ const message = errorData.error || errorData.detail || errorData.message || response.statusText;
4085
4251
  if (this.debug) {
4086
- console.log(`[GitHub SDK] Response:`, JSON.stringify(data).slice(0, 200));
4252
+ console.error(`[GitHub SDK] Error ${response.status}:`, message);
4087
4253
  }
4088
- return data;
4089
- } catch (error) {
4090
- clearTimeout(timeoutId);
4091
- if (error instanceof GitHubError) {
4092
- throw error;
4254
+ if (response.status === 404) {
4255
+ if (message.includes("installation")) {
4256
+ throw new NoInstallationError(message);
4257
+ }
4258
+ throw new NotFoundError(message);
4093
4259
  }
4094
- if (error instanceof Error && error.name === "AbortError") {
4095
- throw new GitHubError("Request timeout", 408, "TIMEOUT");
4260
+ if (response.status === 403) {
4261
+ throw new PermissionError(message);
4096
4262
  }
4097
- throw new GitHubError(
4098
- error instanceof Error ? error.message : "Unknown error",
4099
- 500,
4100
- "UNKNOWN"
4101
- );
4263
+ throw new GitHubError(message, response.status, errorData.code);
4102
4264
  }
4265
+ const data = await response.json();
4266
+ if (this.debug) {
4267
+ console.log(`[GitHub SDK] Response:`, JSON.stringify(data).slice(0, 200));
4268
+ }
4269
+ return data;
4103
4270
  }
4104
4271
  /**
4105
4272
  * Get the installation ID to use for a request
@@ -4293,18 +4460,28 @@ var import_isomorphic_git = __toESM(require("isomorphic-git"), 1);
4293
4460
  var import_node = __toESM(require("isomorphic-git/http/node"), 1);
4294
4461
  var import_fs2 = __toESM(require("fs"), 1);
4295
4462
  var DEFAULT_PROXY_URL = "https://repos.morphllm.com";
4296
- var MorphGit = class {
4463
+ var MorphGit = class extends APIResource {
4297
4464
  apiKey;
4298
4465
  proxyUrl;
4299
- constructor(config) {
4300
- if (!config.apiKey) {
4301
- throw new Error("API key is required. Get one at https://morphllm.com/dashboard");
4302
- }
4303
- if (!config.apiKey.startsWith("sk-") && !config.apiKey.startsWith("morph-")) {
4304
- throw new Error("Invalid API key format. Expected: sk-... or morph-...");
4466
+ constructor(clientOrConfig) {
4467
+ const isClient = clientOrConfig instanceof MorphAPIClient;
4468
+ if (!isClient) {
4469
+ if (!clientOrConfig.apiKey) {
4470
+ throw new Error("API key is required. Get one at https://morphllm.com/dashboard");
4471
+ }
4472
+ if (!clientOrConfig.apiKey.startsWith("sk-") && !clientOrConfig.apiKey.startsWith("morph-")) {
4473
+ throw new Error("Invalid API key format. Expected: sk-... or morph-...");
4474
+ }
4305
4475
  }
4306
- this.apiKey = config.apiKey;
4307
- this.proxyUrl = config.proxyUrl || DEFAULT_PROXY_URL;
4476
+ super(
4477
+ isClient ? clientOrConfig : new MorphAPIClient({
4478
+ apiKey: clientOrConfig.apiKey,
4479
+ reposURL: clientOrConfig.proxyUrl,
4480
+ retryConfig: clientOrConfig.retryConfig
4481
+ })
4482
+ );
4483
+ this.apiKey = this._client.resolveApiKey() ?? "";
4484
+ this.proxyUrl = isClient ? this._client.reposURL : clientOrConfig.proxyUrl || DEFAULT_PROXY_URL;
4308
4485
  }
4309
4486
  /**
4310
4487
  * Get auth callback for isomorphic-git operations
@@ -4832,87 +5009,212 @@ var MorphGit = class {
4832
5009
  var import_isomorphic_git2 = __toESM(require("isomorphic-git"), 1);
4833
5010
  var import_node2 = __toESM(require("isomorphic-git/http/node"), 1);
4834
5011
 
5012
+ // tools/reflex/core.ts
5013
+ var BASE_MODEL = "morph-reflex-v1";
5014
+ function resolveClient2(clientOrConfig) {
5015
+ if (clientOrConfig instanceof MorphAPIClient) return clientOrConfig;
5016
+ return new MorphAPIClient({
5017
+ apiKey: clientOrConfig.apiKey,
5018
+ baseURL: clientOrConfig.baseUrl,
5019
+ timeout: clientOrConfig.timeout,
5020
+ retryConfig: clientOrConfig.retryConfig,
5021
+ debug: clientOrConfig.debug
5022
+ });
5023
+ }
5024
+ var ReflexClient = class extends APIResource {
5025
+ /** Train, retrieve, and manage classifier jobs. */
5026
+ jobs;
5027
+ constructor(clientOrConfig = {}) {
5028
+ super(resolveClient2(clientOrConfig));
5029
+ this.jobs = new ReflexJobsResource(this._client);
5030
+ }
5031
+ /** Classify text against a trained model. The model must be `succeeded`. */
5032
+ async predict(input) {
5033
+ const raw = await this._client.post("/v1/reflex/predict", {
5034
+ body: { model: input.model, text: input.text }
5035
+ });
5036
+ return {
5037
+ model: raw.model,
5038
+ label: raw.label,
5039
+ confidence: raw.confidence,
5040
+ allScores: raw.all_scores ?? {},
5041
+ inferenceTimeMs: raw.inference_time_ms
5042
+ };
5043
+ }
5044
+ };
5045
+ var ReflexJobsResource = class extends APIResource {
5046
+ /** Start a training job from labeled data, a description, or unlabeled text. */
5047
+ async create(input) {
5048
+ return toReflexJob(await this._client.post("/v1/fine_tuning/jobs", { body: createBody(input) }));
5049
+ }
5050
+ /** Fetch a job by id. */
5051
+ async retrieve(id) {
5052
+ return toReflexJob(await this._client.get(`/v1/fine_tuning/jobs/${encodeURIComponent(id)}`));
5053
+ }
5054
+ /** List the caller's jobs, newest first. */
5055
+ async list(input = {}) {
5056
+ const raw = await this._client.get("/v1/fine_tuning/jobs", {
5057
+ query: { limit: input.limit, after: input.after }
5058
+ });
5059
+ return { data: (raw.data ?? []).map(toReflexJob), hasMore: Boolean(raw.has_more) };
5060
+ }
5061
+ /** Stop a queued or running job. */
5062
+ async cancel(id) {
5063
+ return toReflexJob(await this._client.post(`/v1/fine_tuning/jobs/${encodeURIComponent(id)}/cancel`));
5064
+ }
5065
+ /** Delete a job and its trained model. */
5066
+ async delete(id) {
5067
+ const raw = await this._client.delete(
5068
+ `/v1/fine_tuning/jobs/${encodeURIComponent(id)}`
5069
+ );
5070
+ return { id: raw.id, deleted: Boolean(raw.deleted) };
5071
+ }
5072
+ /** The training loss curve as events, plus a terminal event. */
5073
+ async events(id) {
5074
+ const raw = await this._client.get(
5075
+ `/v1/fine_tuning/jobs/${encodeURIComponent(id)}/events`
5076
+ );
5077
+ return (raw.data ?? []).map(toReflexEvent);
5078
+ }
5079
+ /**
5080
+ * Poll until the job reaches a terminal status and return it on success.
5081
+ * Throws a `MorphError` if it fails, is cancelled, or exceeds `timeoutMs`.
5082
+ */
5083
+ async waitForReady(id, opts = {}) {
5084
+ const pollMs = opts.pollMs ?? 3e3;
5085
+ const deadline = Date.now() + (opts.timeoutMs ?? 15 * 6e4);
5086
+ for (; ; ) {
5087
+ const job = await this.retrieve(id);
5088
+ if (job.status === "succeeded") return job;
5089
+ if (job.status === "failed" || job.status === "cancelled") {
5090
+ throw new MorphError(job.error?.message ?? `Reflex job ${job.status}`, `reflex_job_${job.status}`);
5091
+ }
5092
+ if (Date.now() >= deadline) {
5093
+ throw new MorphError(`Reflex job ${id} did not finish in time`, "reflex_timeout");
5094
+ }
5095
+ await sleep2(pollMs);
5096
+ }
5097
+ }
5098
+ };
5099
+ function createBody(input) {
5100
+ const base = { model: BASE_MODEL };
5101
+ if (input.suffix) base.suffix = input.suffix;
5102
+ if ("trainingData" in input) {
5103
+ if (input.labels) base.labels = input.labels;
5104
+ return { ...base, training_data: input.trainingData };
5105
+ }
5106
+ if ("generate" in input) {
5107
+ return {
5108
+ ...base,
5109
+ labels: input.labels,
5110
+ generate: {
5111
+ description: input.generate.description,
5112
+ ...input.generate.examplesPerLabel != null ? { examples_per_label: input.generate.examplesPerLabel } : {}
5113
+ }
5114
+ };
5115
+ }
5116
+ return {
5117
+ ...base,
5118
+ labels: input.labels,
5119
+ label_data: {
5120
+ texts: input.labelData.texts,
5121
+ ...input.labelData.description ? { description: input.labelData.description } : {}
5122
+ }
5123
+ };
5124
+ }
5125
+ function toReflexJob(raw) {
5126
+ return {
5127
+ id: raw.id,
5128
+ object: "fine_tuning.job",
5129
+ model: raw.model,
5130
+ createdAt: raw.created_at,
5131
+ finishedAt: raw.finished_at ?? null,
5132
+ fineTunedModel: raw.fine_tuned_model ?? null,
5133
+ status: raw.status,
5134
+ labels: raw.labels ?? [],
5135
+ trainedExamples: raw.trained_examples ?? 0,
5136
+ result: raw.result ? { accuracy: raw.result.accuracy ?? null, f1Score: raw.result.f1_score ?? null } : null,
5137
+ error: raw.error ? { message: raw.error.message } : null,
5138
+ suffix: raw.suffix ?? null
5139
+ };
5140
+ }
5141
+ function toReflexEvent(raw) {
5142
+ return {
5143
+ id: raw.id,
5144
+ createdAt: raw.created_at,
5145
+ level: raw.level,
5146
+ message: raw.message,
5147
+ type: raw.type,
5148
+ data: { epoch: raw.data?.epoch ?? 0, step: raw.data?.step ?? 0, trainLoss: raw.data?.train_loss ?? 0 }
5149
+ };
5150
+ }
5151
+ function sleep2(ms) {
5152
+ return new Promise((resolve2) => setTimeout(resolve2, ms));
5153
+ }
5154
+
4835
5155
  // modelrouter/core.ts
4836
5156
  init_logger();
4837
- var DEFAULT_CONFIG3 = {
4838
- apiUrl: "https://api.morphllm.com",
4839
- timeout: 5e3,
4840
- // 5 seconds (responses typically <500ms)
4841
- debug: false
4842
- };
4843
- var BaseRouter = class {
4844
- config;
5157
+ var DEFAULT_API_URL5 = "https://api.morphllm.com";
5158
+ var DEFAULT_TIMEOUT6 = 5e3;
5159
+ function resolveClient3(clientOrConfig) {
5160
+ if (clientOrConfig instanceof MorphAPIClient) return clientOrConfig;
5161
+ return new MorphAPIClient({
5162
+ apiKey: clientOrConfig.apiKey,
5163
+ baseURL: clientOrConfig.apiUrl ?? DEFAULT_API_URL5,
5164
+ timeout: clientOrConfig.timeout ?? DEFAULT_TIMEOUT6,
5165
+ retryConfig: clientOrConfig.retryConfig,
5166
+ debug: clientOrConfig.debug
5167
+ });
5168
+ }
5169
+ var BaseRouter = class extends APIResource {
4845
5170
  provider;
4846
- constructor(provider, config = {}) {
5171
+ timeout;
5172
+ constructor(provider, clientOrConfig = {}) {
5173
+ super(resolveClient3(clientOrConfig));
4847
5174
  this.provider = provider;
4848
- this.config = {
4849
- apiKey: config.apiKey,
4850
- apiUrl: config.apiUrl || DEFAULT_CONFIG3.apiUrl,
4851
- timeout: config.timeout || DEFAULT_CONFIG3.timeout,
4852
- debug: config.debug || DEFAULT_CONFIG3.debug,
4853
- retryConfig: config.retryConfig
4854
- };
5175
+ const cfg = clientOrConfig instanceof MorphAPIClient ? {} : clientOrConfig;
5176
+ this.timeout = cfg.timeout ?? DEFAULT_TIMEOUT6;
4855
5177
  }
4856
- /**
4857
- * Select the optimal model for a given input and mode
4858
- */
4859
- async selectModel(input) {
4860
- const mode = input.mode || "balanced";
4861
- const apiKey = this.config.apiKey || (typeof process !== "undefined" ? process.env?.MORPH_API_KEY : void 0);
4862
- if (!apiKey) {
5178
+ /** Throw the historical "API key is required" message when no key is resolvable. */
5179
+ requireApiKey() {
5180
+ if (!this._client.resolveApiKey()) {
4863
5181
  throw new Error(
4864
5182
  "Morph API key is required. Set MORPH_API_KEY environment variable or pass apiKey in config."
4865
5183
  );
4866
5184
  }
4867
- const url = `${this.config.apiUrl}/v1/router/${this.provider}`;
4868
- const payload = {
4869
- input: input.input,
4870
- mode
4871
- };
4872
- logger.debug("ModelRouter", "request", { provider: this.provider, mode, input_len: input.input.length, url });
5185
+ }
5186
+ /** POST to the router and surface failures as `Router API error (<status>): ...`. */
5187
+ async route(provider, input) {
4873
5188
  try {
4874
- const fetchPromise = fetchWithRetry(
4875
- url,
4876
- {
4877
- method: "POST",
4878
- headers: {
4879
- "Content-Type": "application/json",
4880
- Authorization: `Bearer ${apiKey}`
4881
- },
4882
- body: JSON.stringify(payload)
4883
- },
4884
- this.config.retryConfig
4885
- );
4886
- const response = await withTimeout(
4887
- fetchPromise,
4888
- this.config.timeout,
4889
- `Router API request timed out after ${this.config.timeout}ms`
4890
- );
4891
- if (!response.ok) {
4892
- const errorText = await response.text();
4893
- throw new Error(
4894
- `Router API error (${response.status}): ${errorText || response.statusText}`
4895
- );
4896
- }
4897
- const apiResult = await response.json();
4898
- const result = {
4899
- model: apiResult.model
4900
- };
4901
- logger.debug("ModelRouter", "selected", { provider: this.provider, model: apiResult.model, confidence: apiResult.confidence });
4902
- return result;
5189
+ return await this._client.post(`/v1/router/${provider}`, {
5190
+ body: { input: input.input, mode: input.mode || "balanced" },
5191
+ timeout: this.timeout
5192
+ });
4903
5193
  } catch (error) {
4904
- logger.error("ModelRouter", "error", { provider: this.provider, error: error instanceof Error ? error.message : String(error) });
5194
+ if (error instanceof MorphError) {
5195
+ throw new Error(`Router API error (${error.statusCode}): ${error.message}`);
5196
+ }
4905
5197
  throw error;
4906
5198
  }
4907
5199
  }
5200
+ /**
5201
+ * Select the optimal model for a given input and mode
5202
+ */
5203
+ async selectModel(input) {
5204
+ this.requireApiKey();
5205
+ logger.debug("ModelRouter", "request", { provider: this.provider, mode: input.mode || "balanced" });
5206
+ const apiResult = await this.route(this.provider, input);
5207
+ logger.debug("ModelRouter", "selected", { provider: this.provider, model: apiResult.model });
5208
+ return { model: apiResult.model };
5209
+ }
4908
5210
  };
4909
5211
  var OpenAIRouter = class extends BaseRouter {
4910
- constructor(config = {}) {
4911
- super("openai", config);
5212
+ constructor(clientOrConfig = {}) {
5213
+ super("openai", clientOrConfig);
4912
5214
  }
4913
5215
  /**
4914
5216
  * Select optimal GPT-5 model
4915
- *
5217
+ *
4916
5218
  * @param input - User input and mode
4917
5219
  * @returns Selected model name (gpt-5-mini | gpt-5-low | gpt-5-medium | gpt-5-high)
4918
5220
  */
@@ -4921,12 +5223,12 @@ var OpenAIRouter = class extends BaseRouter {
4921
5223
  }
4922
5224
  };
4923
5225
  var AnthropicRouter = class extends BaseRouter {
4924
- constructor(config = {}) {
4925
- super("anthropic", config);
5226
+ constructor(clientOrConfig = {}) {
5227
+ super("anthropic", clientOrConfig);
4926
5228
  }
4927
5229
  /**
4928
5230
  * Select optimal Claude model
4929
- *
5231
+ *
4930
5232
  * @param input - User input and mode
4931
5233
  * @returns Selected model name (claude-4.5-haiku | claude-4.5-sonnet)
4932
5234
  */
@@ -4935,12 +5237,12 @@ var AnthropicRouter = class extends BaseRouter {
4935
5237
  }
4936
5238
  };
4937
5239
  var GeminiRouter = class extends BaseRouter {
4938
- constructor(config = {}) {
4939
- super("gemini", config);
5240
+ constructor(clientOrConfig = {}) {
5241
+ super("gemini", clientOrConfig);
4940
5242
  }
4941
5243
  /**
4942
5244
  * Select optimal Gemini model
4943
- *
5245
+ *
4944
5246
  * @param input - User input and mode
4945
5247
  * @returns Selected model name (gemini-2.5-flash | gemini-2.5-pro)
4946
5248
  */
@@ -4949,69 +5251,27 @@ var GeminiRouter = class extends BaseRouter {
4949
5251
  }
4950
5252
  };
4951
5253
  var RawRouter = class extends BaseRouter {
4952
- constructor(config = {}) {
4953
- super("raw", config);
5254
+ constructor(clientOrConfig = {}) {
5255
+ super("raw", clientOrConfig);
4954
5256
  }
4955
5257
  /**
4956
5258
  * Get raw difficulty classification
4957
- *
5259
+ *
4958
5260
  * @param input - User input and mode
4959
5261
  * @returns Raw difficulty (easy | medium | hard | needs_info)
4960
5262
  */
4961
5263
  async classify(input) {
4962
- const mode = input.mode || "balanced";
4963
- const apiKey = this.config.apiKey || (typeof process !== "undefined" ? process.env?.MORPH_API_KEY : void 0);
4964
- if (!apiKey) {
4965
- throw new Error(
4966
- "Morph API key is required. Set MORPH_API_KEY environment variable or pass apiKey in config."
4967
- );
4968
- }
4969
- const url = `${this.config.apiUrl}/v1/router/raw`;
4970
- const payload = {
4971
- input: input.input,
4972
- mode
4973
- };
4974
- logger.debug("RawRouter", "request", { mode, input_len: input.input.length, url });
4975
- try {
4976
- const fetchPromise = fetchWithRetry(
4977
- url,
4978
- {
4979
- method: "POST",
4980
- headers: {
4981
- "Content-Type": "application/json",
4982
- Authorization: `Bearer ${apiKey}`
4983
- },
4984
- body: JSON.stringify(payload)
4985
- },
4986
- this.config.retryConfig
4987
- );
4988
- const response = await withTimeout(
4989
- fetchPromise,
4990
- this.config.timeout,
4991
- `Router API request timed out after ${this.config.timeout}ms`
4992
- );
4993
- if (!response.ok) {
4994
- const errorText = await response.text();
4995
- throw new Error(
4996
- `Router API error (${response.status}): ${errorText || response.statusText}`
4997
- );
4998
- }
4999
- const apiResult = await response.json();
5000
- let difficulty;
5001
- if (apiResult.difficulty === "") {
5002
- difficulty = "medium";
5003
- } else {
5004
- difficulty = apiResult.difficulty || apiResult.model;
5005
- }
5006
- const result = {
5007
- difficulty
5008
- };
5009
- logger.debug("RawRouter", "classified", { difficulty });
5010
- return result;
5011
- } catch (error) {
5012
- logger.error("RawRouter", "error", { error: error instanceof Error ? error.message : String(error) });
5013
- throw error;
5264
+ this.requireApiKey();
5265
+ logger.debug("RawRouter", "request", { mode: input.mode || "balanced" });
5266
+ const apiResult = await this.route("raw", input);
5267
+ let difficulty;
5268
+ if (apiResult.difficulty === "") {
5269
+ difficulty = "medium";
5270
+ } else {
5271
+ difficulty = apiResult.difficulty || apiResult.model;
5014
5272
  }
5273
+ logger.debug("RawRouter", "classified", { difficulty });
5274
+ return { difficulty };
5015
5275
  }
5016
5276
  };
5017
5277
 
@@ -6394,7 +6654,7 @@ var VercelToolFactory = class {
6394
6654
  };
6395
6655
 
6396
6656
  // client.ts
6397
- var MorphClient = class {
6657
+ var MorphClient = class extends MorphAPIClient {
6398
6658
  /** Client configuration */
6399
6659
  config;
6400
6660
  /** FastApply tool for editing files with AI-powered merge */
@@ -6419,6 +6679,8 @@ var MorphClient = class {
6419
6679
  vercel;
6420
6680
  /** Compact context with line ranges */
6421
6681
  compact;
6682
+ /** Reflex: train and serve small text classifiers */
6683
+ reflex;
6422
6684
  /**
6423
6685
  * Create a new Morph SDK client
6424
6686
  *
@@ -6434,78 +6696,32 @@ var MorphClient = class {
6434
6696
  * ```
6435
6697
  */
6436
6698
  constructor(config = {}) {
6437
- this.config = config;
6438
- if (config.debug) {
6439
- logger.enable();
6440
- }
6441
- logger.debug("MorphClient", "initialized", { debug: !!config.debug, timeout: config.timeout });
6442
- this.fastApply = new FastApplyClient({
6443
- apiKey: config.apiKey,
6444
- debug: config.debug,
6445
- timeout: config.timeout,
6446
- retryConfig: config.retryConfig
6447
- });
6448
- this.codebaseSearch = new CodebaseSearchClient({
6449
- apiKey: config.apiKey,
6450
- debug: config.debug,
6451
- timeout: config.timeout,
6452
- retryConfig: config.retryConfig
6453
- });
6454
- this.warpGrep = new WarpGrepClient({
6455
- morphApiKey: config.apiKey,
6456
- debug: config.debug,
6457
- timeout: config.timeout,
6458
- retryConfig: config.retryConfig
6459
- });
6460
- this.browser = new BrowserClient({
6461
- apiKey: config.apiKey,
6462
- debug: config.debug,
6463
- timeout: config.timeout,
6464
- retryConfig: config.retryConfig
6465
- });
6466
- this.github = new GitHubClient({
6467
- apiKey: config.apiKey,
6468
- debug: config.debug,
6469
- timeout: config.timeout,
6470
- installationId: config.github?.installationId
6471
- });
6472
- this.git = new MorphGit({
6699
+ super({
6473
6700
  apiKey: config.apiKey,
6474
- retryConfig: config.retryConfig
6475
- });
6476
- this.routers = {
6477
- openai: new OpenAIRouter({
6478
- apiKey: config.apiKey,
6479
- debug: config.debug,
6480
- timeout: config.timeout,
6481
- retryConfig: config.retryConfig
6482
- }),
6483
- anthropic: new AnthropicRouter({
6484
- apiKey: config.apiKey,
6485
- debug: config.debug,
6486
- timeout: config.timeout,
6487
- retryConfig: config.retryConfig
6488
- }),
6489
- gemini: new GeminiRouter({
6490
- apiKey: config.apiKey,
6491
- debug: config.debug,
6492
- timeout: config.timeout,
6493
- retryConfig: config.retryConfig
6494
- }),
6495
- raw: new RawRouter({
6496
- apiKey: config.apiKey,
6497
- debug: config.debug,
6498
- timeout: config.timeout,
6499
- retryConfig: config.retryConfig
6500
- })
6501
- };
6502
- const compactClient = new CompactClient({
6503
- morphApiKey: config.apiKey,
6504
6701
  timeout: config.timeout,
6505
6702
  retryConfig: config.retryConfig,
6506
6703
  debug: config.debug
6507
6704
  });
6705
+ if (!config.apiKey) {
6706
+ throw new Error("Morph API key is required. Pass it as { apiKey } when constructing MorphClient.");
6707
+ }
6708
+ this.config = config;
6709
+ logger.debug("MorphClient", "initialized", { debug: !!config.debug, timeout: config.timeout });
6710
+ this.fastApply = new FastApplyClient(this);
6711
+ this.codebaseSearch = new CodebaseSearchClient(this);
6712
+ this.warpGrep = new WarpGrepClient(this);
6713
+ this.browser = new BrowserClient(this);
6714
+ this.github = new GitHubClient(this, { installationId: config.github?.installationId });
6715
+ this.git = new MorphGit(this);
6716
+ this.routers = {
6717
+ openai: new OpenAIRouter(this),
6718
+ anthropic: new AnthropicRouter(this),
6719
+ gemini: new GeminiRouter(this),
6720
+ raw: new RawRouter(this)
6721
+ };
6722
+ const compactClient = new CompactClient(this);
6508
6723
  this.compact = compactClient.compact.bind(compactClient);
6724
+ this.reflex = new ReflexClient(this);
6509
6725
  this.openai = new OpenAIToolFactory(config);
6510
6726
  this.anthropic = new AnthropicToolFactory(config);
6511
6727
  this.vercel = new VercelToolFactory(config);