@morphllm/morphsdk 0.2.162 → 0.2.164

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 (172) hide show
  1. package/dist/{chunk-OGMHU4PJ.js → chunk-3HVVQHHX.js} +9 -2
  2. package/dist/chunk-3HVVQHHX.js.map +1 -0
  3. package/dist/{chunk-JVKGSMEF.js → chunk-3NWJ74R4.js} +2 -2
  4. package/dist/{chunk-XUV5B27P.js → chunk-4DDD65QF.js} +2 -2
  5. package/dist/{chunk-DRTPCCEI.js → chunk-4FZXI4FI.js} +2 -2
  6. package/dist/chunk-5AM23TC7.js +42 -0
  7. package/dist/chunk-5AM23TC7.js.map +1 -0
  8. package/dist/{chunk-CNFHKQ42.js → chunk-BFNH475L.js} +2 -2
  9. package/dist/{chunk-ZG3YLRR5.js → chunk-CFCNSELX.js} +8 -2
  10. package/dist/chunk-CFCNSELX.js.map +1 -0
  11. package/dist/{chunk-NKUGRAYU.js → chunk-CRU3FQ54.js} +2 -2
  12. package/dist/{chunk-DXMNKPB6.js → chunk-DKPC5ZVX.js} +2 -2
  13. package/dist/{chunk-PWGBAVQ5.js → chunk-DVCIADH3.js} +2 -2
  14. package/dist/{chunk-LECHLXI4.js → chunk-EAIAZ2GD.js} +17 -6
  15. package/dist/chunk-EAIAZ2GD.js.map +1 -0
  16. package/dist/{chunk-4GQNYJBB.js → chunk-ECELX2KF.js} +9 -12
  17. package/dist/chunk-ECELX2KF.js.map +1 -0
  18. package/dist/{chunk-YRHM3RCQ.js → chunk-EPYCKNQ3.js} +2 -2
  19. package/dist/{chunk-OOE2TKKY.js → chunk-MRYULNMU.js} +12 -21
  20. package/dist/chunk-MRYULNMU.js.map +1 -0
  21. package/dist/{chunk-4U5JFT6X.js → chunk-MVMB6GBY.js} +33 -26
  22. package/dist/{chunk-4U5JFT6X.js.map → chunk-MVMB6GBY.js.map} +1 -1
  23. package/dist/{chunk-UKT3CKC7.js → chunk-N4SSQFYN.js} +2 -2
  24. package/dist/{chunk-7QMX45QD.js → chunk-NKFMGSUH.js} +33 -6
  25. package/dist/chunk-NKFMGSUH.js.map +1 -0
  26. package/dist/{chunk-LZQBVEY2.js → chunk-NMRQWMTH.js} +35 -27
  27. package/dist/chunk-NMRQWMTH.js.map +1 -0
  28. package/dist/{chunk-UVRC4LKZ.js → chunk-Q7XZ6JGW.js} +2 -2
  29. package/dist/{chunk-UZX7SY33.js → chunk-RR7P4SMP.js} +2 -2
  30. package/dist/{chunk-UETFIUIG.js → chunk-VCFUU5TL.js} +2 -2
  31. package/dist/{chunk-5XTA7GCY.js → chunk-VDMF4WWF.js} +2 -2
  32. package/dist/{chunk-YBKT2UOK.js → chunk-XULEBEBX.js} +2 -2
  33. package/dist/{chunk-Y4NYT5L6.js → chunk-YOF3N2EL.js} +11 -26
  34. package/dist/chunk-YOF3N2EL.js.map +1 -0
  35. package/dist/{chunk-4Q6VFODP.js → chunk-ZEEHRQYJ.js} +2 -2
  36. package/dist/{chunk-VQSLLYKE.js → chunk-ZEMLB2KV.js} +2 -2
  37. package/dist/client.cjs +185 -115
  38. package/dist/client.cjs.map +1 -1
  39. package/dist/client.d.ts +1 -1
  40. package/dist/client.js +25 -24
  41. package/dist/edge.cjs +83 -50
  42. package/dist/edge.cjs.map +1 -1
  43. package/dist/edge.js +5 -4
  44. package/dist/index.cjs +187 -115
  45. package/dist/index.cjs.map +1 -1
  46. package/dist/index.d.ts +1 -1
  47. package/dist/index.js +29 -28
  48. package/dist/modelrouter/core.cjs +51 -25
  49. package/dist/modelrouter/core.cjs.map +1 -1
  50. package/dist/modelrouter/core.js +4 -3
  51. package/dist/modelrouter/index.cjs +51 -25
  52. package/dist/modelrouter/index.cjs.map +1 -1
  53. package/dist/modelrouter/index.js +4 -3
  54. package/dist/subagents/anthropic.cjs +86 -12
  55. package/dist/subagents/anthropic.cjs.map +1 -1
  56. package/dist/subagents/anthropic.js +5 -4
  57. package/dist/subagents/vercel.cjs +86 -12
  58. package/dist/subagents/vercel.cjs.map +1 -1
  59. package/dist/subagents/vercel.js +5 -4
  60. package/dist/tools/browser/anthropic.cjs +48 -9
  61. package/dist/tools/browser/anthropic.cjs.map +1 -1
  62. package/dist/tools/browser/anthropic.js +6 -5
  63. package/dist/tools/browser/core.cjs +51 -19
  64. package/dist/tools/browser/core.cjs.map +1 -1
  65. package/dist/tools/browser/core.js +5 -4
  66. package/dist/tools/browser/index.cjs +51 -19
  67. package/dist/tools/browser/index.cjs.map +1 -1
  68. package/dist/tools/browser/index.js +10 -9
  69. package/dist/tools/browser/index.js.map +1 -1
  70. package/dist/tools/browser/openai.cjs +48 -9
  71. package/dist/tools/browser/openai.cjs.map +1 -1
  72. package/dist/tools/browser/openai.js +6 -5
  73. package/dist/tools/browser/profiles/core.cjs +7 -1
  74. package/dist/tools/browser/profiles/core.cjs.map +1 -1
  75. package/dist/tools/browser/profiles/core.js +3 -3
  76. package/dist/tools/browser/profiles/index.cjs +7 -1
  77. package/dist/tools/browser/profiles/index.cjs.map +1 -1
  78. package/dist/tools/browser/profiles/index.js +3 -3
  79. package/dist/tools/browser/vercel.cjs +48 -9
  80. package/dist/tools/browser/vercel.cjs.map +1 -1
  81. package/dist/tools/browser/vercel.js +6 -5
  82. package/dist/tools/codebase_search/anthropic.cjs +49 -11
  83. package/dist/tools/codebase_search/anthropic.cjs.map +1 -1
  84. package/dist/tools/codebase_search/anthropic.js +5 -4
  85. package/dist/tools/codebase_search/core.cjs +49 -11
  86. package/dist/tools/codebase_search/core.cjs.map +1 -1
  87. package/dist/tools/codebase_search/core.js +4 -3
  88. package/dist/tools/codebase_search/index.cjs +49 -11
  89. package/dist/tools/codebase_search/index.cjs.map +1 -1
  90. package/dist/tools/codebase_search/index.js +9 -8
  91. package/dist/tools/codebase_search/openai.cjs +49 -11
  92. package/dist/tools/codebase_search/openai.cjs.map +1 -1
  93. package/dist/tools/codebase_search/openai.js +5 -4
  94. package/dist/tools/codebase_search/vercel.cjs +49 -11
  95. package/dist/tools/codebase_search/vercel.cjs.map +1 -1
  96. package/dist/tools/codebase_search/vercel.js +5 -4
  97. package/dist/tools/fastapply/anthropic.cjs +95 -31
  98. package/dist/tools/fastapply/anthropic.cjs.map +1 -1
  99. package/dist/tools/fastapply/anthropic.js +5 -4
  100. package/dist/tools/fastapply/apply.cjs +75 -26
  101. package/dist/tools/fastapply/apply.cjs.map +1 -1
  102. package/dist/tools/fastapply/apply.js +3 -2
  103. package/dist/tools/fastapply/core.cjs +95 -31
  104. package/dist/tools/fastapply/core.cjs.map +1 -1
  105. package/dist/tools/fastapply/core.js +4 -3
  106. package/dist/tools/fastapply/index.cjs +95 -31
  107. package/dist/tools/fastapply/index.cjs.map +1 -1
  108. package/dist/tools/fastapply/index.js +9 -8
  109. package/dist/tools/fastapply/openai.cjs +95 -31
  110. package/dist/tools/fastapply/openai.cjs.map +1 -1
  111. package/dist/tools/fastapply/openai.js +5 -4
  112. package/dist/tools/fastapply/vercel.cjs +95 -31
  113. package/dist/tools/fastapply/vercel.cjs.map +1 -1
  114. package/dist/tools/fastapply/vercel.js +5 -4
  115. package/dist/tools/index.cjs +95 -31
  116. package/dist/tools/index.cjs.map +1 -1
  117. package/dist/tools/index.js +9 -8
  118. package/dist/tools/utils/resilience.cjs +7 -1
  119. package/dist/tools/utils/resilience.cjs.map +1 -1
  120. package/dist/tools/utils/resilience.js +2 -2
  121. package/dist/tools/warp_grep/agent/runner.cjs +75 -5
  122. package/dist/tools/warp_grep/agent/runner.cjs.map +1 -1
  123. package/dist/tools/warp_grep/agent/runner.js +3 -2
  124. package/dist/tools/warp_grep/anthropic.cjs +86 -12
  125. package/dist/tools/warp_grep/anthropic.cjs.map +1 -1
  126. package/dist/tools/warp_grep/anthropic.js +5 -4
  127. package/dist/tools/warp_grep/client.cjs +86 -12
  128. package/dist/tools/warp_grep/client.cjs.map +1 -1
  129. package/dist/tools/warp_grep/client.js +4 -3
  130. package/dist/tools/warp_grep/gemini.cjs +86 -12
  131. package/dist/tools/warp_grep/gemini.cjs.map +1 -1
  132. package/dist/tools/warp_grep/gemini.js +4 -3
  133. package/dist/tools/warp_grep/gemini.js.map +1 -1
  134. package/dist/tools/warp_grep/index.cjs +86 -12
  135. package/dist/tools/warp_grep/index.cjs.map +1 -1
  136. package/dist/tools/warp_grep/index.js +4 -3
  137. package/dist/tools/warp_grep/openai.cjs +86 -12
  138. package/dist/tools/warp_grep/openai.cjs.map +1 -1
  139. package/dist/tools/warp_grep/openai.js +5 -4
  140. package/dist/tools/warp_grep/vercel.cjs +86 -12
  141. package/dist/tools/warp_grep/vercel.cjs.map +1 -1
  142. package/dist/tools/warp_grep/vercel.d.ts +1 -1
  143. package/dist/tools/warp_grep/vercel.js +5 -4
  144. package/dist/version.cjs +7 -1
  145. package/dist/version.cjs.map +1 -1
  146. package/dist/version.js +1 -1
  147. package/package.json +7 -1
  148. package/dist/chunk-4GQNYJBB.js.map +0 -1
  149. package/dist/chunk-7QMX45QD.js.map +0 -1
  150. package/dist/chunk-LECHLXI4.js.map +0 -1
  151. package/dist/chunk-LZQBVEY2.js.map +0 -1
  152. package/dist/chunk-OGMHU4PJ.js.map +0 -1
  153. package/dist/chunk-OOE2TKKY.js.map +0 -1
  154. package/dist/chunk-Y4NYT5L6.js.map +0 -1
  155. package/dist/chunk-ZG3YLRR5.js.map +0 -1
  156. package/dist/{chunk-JVKGSMEF.js.map → chunk-3NWJ74R4.js.map} +0 -0
  157. package/dist/{chunk-XUV5B27P.js.map → chunk-4DDD65QF.js.map} +0 -0
  158. package/dist/{chunk-DRTPCCEI.js.map → chunk-4FZXI4FI.js.map} +0 -0
  159. package/dist/{chunk-CNFHKQ42.js.map → chunk-BFNH475L.js.map} +0 -0
  160. package/dist/{chunk-NKUGRAYU.js.map → chunk-CRU3FQ54.js.map} +0 -0
  161. package/dist/{chunk-DXMNKPB6.js.map → chunk-DKPC5ZVX.js.map} +0 -0
  162. package/dist/{chunk-PWGBAVQ5.js.map → chunk-DVCIADH3.js.map} +0 -0
  163. package/dist/{chunk-YRHM3RCQ.js.map → chunk-EPYCKNQ3.js.map} +0 -0
  164. package/dist/{chunk-UKT3CKC7.js.map → chunk-N4SSQFYN.js.map} +0 -0
  165. package/dist/{chunk-UVRC4LKZ.js.map → chunk-Q7XZ6JGW.js.map} +0 -0
  166. package/dist/{chunk-UZX7SY33.js.map → chunk-RR7P4SMP.js.map} +0 -0
  167. package/dist/{chunk-UETFIUIG.js.map → chunk-VCFUU5TL.js.map} +0 -0
  168. package/dist/{chunk-5XTA7GCY.js.map → chunk-VDMF4WWF.js.map} +0 -0
  169. package/dist/{chunk-YBKT2UOK.js.map → chunk-XULEBEBX.js.map} +0 -0
  170. package/dist/{chunk-4Q6VFODP.js.map → chunk-ZEEHRQYJ.js.map} +0 -0
  171. package/dist/{chunk-VQSLLYKE.js.map → chunk-ZEMLB2KV.js.map} +0 -0
  172. package/dist/{client-PkB7g9SA.d.ts → client-DsAAqupx.d.ts} +1 -1
package/dist/client.cjs CHANGED
@@ -30,13 +30,57 @@ 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 import_fs, MorphLogger, logger;
35
+ var init_logger = __esm({
36
+ "logger.ts"() {
37
+ "use strict";
38
+ import_fs = require("fs");
39
+ MorphLogger = class {
40
+ enabled;
41
+ fileStream;
42
+ constructor() {
43
+ this.enabled = process.env.MORPH_DEBUG === "1" || !!process.env.MORPH_LOG_FILE;
44
+ const f = process.env.MORPH_LOG_FILE;
45
+ this.fileStream = f ? (0, import_fs.createWriteStream)(f, { flags: "a" }) : null;
46
+ }
47
+ debug(component, msg, data) {
48
+ this._log("debug", component, msg, data);
49
+ }
50
+ info(component, msg, data) {
51
+ this._log("info", component, msg, data);
52
+ }
53
+ warn(component, msg, data) {
54
+ this._log("warn", component, msg, data);
55
+ }
56
+ error(component, msg, data) {
57
+ this._log("error", component, msg, data);
58
+ }
59
+ enable() {
60
+ this.enabled = true;
61
+ }
62
+ get isEnabled() {
63
+ return this.enabled;
64
+ }
65
+ _log(level, component, msg, data) {
66
+ if (level !== "error" && !this.enabled) return;
67
+ const ts = (/* @__PURE__ */ new Date()).toISOString();
68
+ const prefix = `[${ts}] [${level.toUpperCase()}] [${component}]`;
69
+ console.error(data ? `${prefix} ${msg} ${JSON.stringify(data)}` : `${prefix} ${msg}`);
70
+ this.fileStream?.write(JSON.stringify({ ts, level, component, msg, ...data && { data } }) + "\n");
71
+ }
72
+ };
73
+ logger = new MorphLogger();
74
+ }
75
+ });
76
+
33
77
  // package.json
34
78
  var package_default;
35
79
  var init_package = __esm({
36
80
  "package.json"() {
37
81
  package_default = {
38
82
  name: "@morphllm/morphsdk",
39
- version: "0.2.162",
83
+ version: "0.2.164",
40
84
  description: "TypeScript SDK and CLI for Morph Fast Apply integration",
41
85
  type: "module",
42
86
  main: "./dist/index.cjs",
@@ -48,6 +92,11 @@ var init_package = __esm({
48
92
  import: "./dist/index.js",
49
93
  require: "./dist/index.cjs"
50
94
  },
95
+ "./logger": {
96
+ types: "./dist/logger.d.ts",
97
+ import: "./dist/logger.js",
98
+ require: "./dist/logger.cjs"
99
+ },
51
100
  "./edge": {
52
101
  types: "./dist/edge.d.ts",
53
102
  import: "./dist/edge.js",
@@ -206,6 +255,7 @@ var init_package = __esm({
206
255
  "test:browser": "vitest run browser",
207
256
  "test:agent": "npx tsx tests/fullAgentTest.ts",
208
257
  "test:integration": "npx tsx tests/fullIntegrationTest.ts",
258
+ "test:e2e": "vitest run --config vitest.e2e.config.ts",
209
259
  "release:patch": "npm version patch && npm publish",
210
260
  "release:minor": "npm version minor && npm publish",
211
261
  "release:major": "npm version major && npm publish"
@@ -335,11 +385,14 @@ async function callMorphAPI(originalCode, codeEdit, instructions, filepath, conf
335
385
  const message = `<instruction>${instructions}</instruction>
336
386
  <code>${originalCode}</code>
337
387
  <update>${codeEdit}</update>`;
338
- if (debug) {
339
- console.log(`[FastApply] Calling ${apiUrl}/v1/chat/completions`);
340
- console.log(`[FastApply] File: ${filepath}, Instructions: ${instructions.slice(0, 60)}...`);
341
- console.log(`[FastApply] Original: ${originalCode.length} chars, Edit: ${codeEdit.length} chars`);
342
- }
388
+ logger.debug("FastApply", "http_request", {
389
+ url: `${apiUrl}/v1/chat/completions`,
390
+ model,
391
+ filepath,
392
+ instruction_len: instructions.length,
393
+ original_len: originalCode.length,
394
+ code_edit_len: codeEdit.length
395
+ });
343
396
  const startTime = Date.now();
344
397
  const client = new import_openai.default({
345
398
  apiKey,
@@ -348,30 +401,32 @@ async function callMorphAPI(originalCode, codeEdit, instructions, filepath, conf
348
401
  maxRetries: config.retryConfig?.maxRetries ?? 3,
349
402
  defaultHeaders: { "X-Morph-SDK-Version": SDK_VERSION }
350
403
  });
351
- if (debug) {
352
- console.log(`[FastApply] Using model: ${model}`);
353
- }
354
- const completion = await client.chat.completions.create({
355
- model,
356
- messages: [{ role: "user", content: message }]
357
- });
358
- const content = completion.choices[0]?.message?.content;
359
- if (!content) {
360
- throw new Error("Morph API returned empty response");
361
- }
362
- const elapsed = Date.now() - startTime;
363
- if (debug) {
364
- console.log(`[FastApply] Success in ${elapsed}ms, merged: ${content.length} chars`);
404
+ try {
405
+ const completion = await client.chat.completions.create({
406
+ model,
407
+ messages: [{ role: "user", content: message }]
408
+ });
409
+ const content = completion.choices[0]?.message?.content;
410
+ if (!content) {
411
+ throw new Error("Morph API returned empty response");
412
+ }
413
+ const elapsed = Date.now() - startTime;
414
+ logger.debug("FastApply", "http_response", { status: 200, completion_id: completion.id, content_len: content.length, latency_ms: elapsed });
415
+ return { content, completionId: completion.id };
416
+ } catch (error) {
417
+ const elapsed = Date.now() - startTime;
418
+ logger.error("FastApply", "http_error", {
419
+ status: error?.status || error?.response?.status,
420
+ error: error?.message,
421
+ latency_ms: elapsed
422
+ });
423
+ throw error;
365
424
  }
366
- return { content, completionId: completion.id };
367
425
  }
368
426
  async function applyEdit(input, config = {}) {
369
- const debug = config.debug || false;
370
427
  const filepath = input.filepath || "file";
371
428
  try {
372
- if (debug) {
373
- console.log(`[FastApply] Applying edit to code (${input.originalCode.length} chars)`);
374
- }
429
+ logger.debug("FastApply", "apply_edit_start", { original_len: input.originalCode.length, code_edit_len: input.codeEdit.length });
375
430
  const instruction = input.instruction ?? input.instructions ?? "";
376
431
  const { content: mergedCode, completionId } = await callMorphAPI(
377
432
  input.originalCode,
@@ -391,7 +446,7 @@ async function applyEdit(input, config = {}) {
391
446
  };
392
447
  } catch (error) {
393
448
  const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
394
- if (debug) console.error(`[FastApply] Error: ${errorMessage}`);
449
+ logger.error("FastApply", "apply_edit_error", { error: errorMessage });
395
450
  return {
396
451
  success: false,
397
452
  changes: { linesAdded: 0, linesRemoved: 0, linesModified: 0 },
@@ -406,6 +461,7 @@ var init_apply = __esm({
406
461
  import_diff = require("diff");
407
462
  import_openai = __toESM(require("openai"), 1);
408
463
  init_version();
464
+ init_logger();
409
465
  DEFAULT_API_URL = "https://api.morphllm.com";
410
466
  DEFAULT_TIMEOUT = 3e4;
411
467
  }
@@ -601,7 +657,7 @@ function toRepoRelative(repoRoot, absPath) {
601
657
  }
602
658
  function isSymlink(p) {
603
659
  try {
604
- const st = import_fs.default.lstatSync(p);
660
+ const st = import_fs2.default.lstatSync(p);
605
661
  return st.isSymbolicLink();
606
662
  } catch {
607
663
  return false;
@@ -624,13 +680,13 @@ function fixPathRepetition(fullPath) {
624
680
  }
625
681
  function isTextualFile(filePath, maxBytes = 2e6) {
626
682
  try {
627
- const st = import_fs.default.statSync(filePath);
683
+ const st = import_fs2.default.statSync(filePath);
628
684
  if (!st.isFile()) return false;
629
685
  if (st.size > maxBytes) return false;
630
- const fd = import_fs.default.openSync(filePath, "r");
686
+ const fd = import_fs2.default.openSync(filePath, "r");
631
687
  const buf = Buffer.alloc(512);
632
- const read = import_fs.default.readSync(fd, buf, 0, buf.length, 0);
633
- import_fs.default.closeSync(fd);
688
+ const read = import_fs2.default.readSync(fd, buf, 0, buf.length, 0);
689
+ import_fs2.default.closeSync(fd);
634
690
  for (let i = 0; i < read; i++) {
635
691
  const c = buf[i];
636
692
  if (c === 0) return false;
@@ -640,11 +696,11 @@ function isTextualFile(filePath, maxBytes = 2e6) {
640
696
  return false;
641
697
  }
642
698
  }
643
- var import_fs, import_path5;
699
+ var import_fs2, import_path5;
644
700
  var init_paths = __esm({
645
701
  "tools/warp_grep/utils/paths.ts"() {
646
702
  "use strict";
647
- import_fs = __toESM(require("fs"), 1);
703
+ import_fs2 = __toESM(require("fs"), 1);
648
704
  import_path5 = __toESM(require("path"), 1);
649
705
  }
650
706
  });
@@ -1004,9 +1060,11 @@ __export(client_exports, {
1004
1060
  MorphClient: () => MorphClient
1005
1061
  });
1006
1062
  module.exports = __toCommonJS(client_exports);
1063
+ init_logger();
1007
1064
 
1008
1065
  // tools/fastapply/core.ts
1009
1066
  var import_path = require("path");
1067
+ init_logger();
1010
1068
  init_apply();
1011
1069
  var DEFAULT_CONFIG = {
1012
1070
  morphApiUrl: "https://api.morphllm.com",
@@ -1067,9 +1125,10 @@ var FastApplyClient = class {
1067
1125
  async function executeEditFile(input, config = {}) {
1068
1126
  const baseDir = config.baseDir || DEFAULT_CONFIG.baseDir;
1069
1127
  const fullPath = (0, import_path.resolve)((0, import_path.join)(baseDir, input.target_filepath));
1070
- const debug = config.debug || false;
1128
+ logger.debug("FastApply", "execute_start", { target_filepath: input.target_filepath, baseDir, autoWrite: config.autoWrite !== false });
1071
1129
  const relativePath = (0, import_path.relative)(baseDir, fullPath);
1072
1130
  if (relativePath.startsWith("..") || fullPath === baseDir) {
1131
+ logger.warn("FastApply", "security_check_failed", { target_filepath: input.target_filepath, relative: relativePath });
1073
1132
  return {
1074
1133
  success: false,
1075
1134
  filepath: input.target_filepath,
@@ -1077,27 +1136,33 @@ async function executeEditFile(input, config = {}) {
1077
1136
  error: `Invalid filepath: '${input.target_filepath}' is outside baseDir`
1078
1137
  };
1079
1138
  }
1139
+ logger.debug("FastApply", "security_check", { resolved: fullPath, relative: relativePath });
1080
1140
  try {
1081
- if (debug) console.log(`[FastApply] Reading file: ${input.target_filepath}`);
1082
1141
  const { readFile, writeFile } = await import("fs/promises");
1083
1142
  const { callMorphAPI: callMorphAPI2, generateUdiff: generateUdiff2, countChanges: countChanges2 } = await Promise.resolve().then(() => (init_apply(), apply_exports));
1084
1143
  let originalCode = "";
1144
+ let fileExists = true;
1085
1145
  try {
1086
1146
  originalCode = await readFile(fullPath, "utf-8");
1147
+ logger.debug("FastApply", "file_read", { path: fullPath, exists: true, size_bytes: originalCode.length });
1087
1148
  } catch (error) {
1088
1149
  if (error.code !== "ENOENT") {
1089
1150
  throw error;
1090
1151
  }
1091
- if (debug) console.log(`[FastApply] File doesn't exist, will create new file`);
1152
+ fileExists = false;
1153
+ logger.debug("FastApply", "file_read", { path: fullPath, exists: false });
1092
1154
  }
1093
1155
  const instruction = input.instruction ?? input.instructions ?? "";
1156
+ logger.debug("FastApply", "api_call", { instruction_len: instruction.length, code_edit_len: input.code_edit.length, original_len: originalCode.length });
1094
1157
  const { content: mergedCode, completionId } = await callMorphAPI2(originalCode, input.code_edit, instruction, input.target_filepath, config);
1158
+ logger.debug("FastApply", "api_response", { completion_id: completionId, merged_len: mergedCode.length });
1095
1159
  const udiff = config.generateUdiff !== false ? generateUdiff2(originalCode, mergedCode, input.target_filepath) : void 0;
1096
1160
  if (config.autoWrite !== false) {
1097
1161
  await writeFile(fullPath, mergedCode, "utf-8");
1098
- if (debug) console.log(`[FastApply] Wrote ${mergedCode.length} chars to ${input.target_filepath}`);
1162
+ logger.debug("FastApply", "file_write", { path: fullPath, size_bytes: mergedCode.length });
1099
1163
  }
1100
1164
  const changes = countChanges2(originalCode, mergedCode);
1165
+ logger.debug("FastApply", "changes", { added: changes.linesAdded, removed: changes.linesRemoved, modified: changes.linesModified });
1101
1166
  return {
1102
1167
  success: true,
1103
1168
  filepath: input.target_filepath,
@@ -1107,7 +1172,7 @@ async function executeEditFile(input, config = {}) {
1107
1172
  };
1108
1173
  } catch (error) {
1109
1174
  const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
1110
- if (debug) console.error(`[FastApply] Error: ${errorMessage}`);
1175
+ logger.error("FastApply", "execute_error", { error: errorMessage, target_filepath: input.target_filepath, stack: error instanceof Error ? error.stack : void 0 });
1111
1176
  return {
1112
1177
  success: false,
1113
1178
  filepath: input.target_filepath,
@@ -1194,6 +1259,7 @@ function sleep(ms) {
1194
1259
  }
1195
1260
 
1196
1261
  // tools/codebase_search/core.ts
1262
+ init_logger();
1197
1263
  var CodebaseSearchClient = class {
1198
1264
  config;
1199
1265
  constructor(config = {}) {
@@ -1231,11 +1297,7 @@ async function executeCodebaseSearch(input, config) {
1231
1297
  }
1232
1298
  const searchUrl = config.searchUrl || process.env.MORPH_SEARCH_URL || "https://repos.morphllm.com";
1233
1299
  const timeout = config.timeout || 3e4;
1234
- const debug = config.debug || false;
1235
- if (debug) {
1236
- console.log(`[CodebaseSearch] Query: "${input.query.slice(0, 60)}..." repo=${config.repoId}`);
1237
- console.log(`[CodebaseSearch] URL: ${searchUrl}/v1/codebase_search`);
1238
- }
1300
+ logger.debug("CodebaseSearch", "request", { query: input.query.slice(0, 100), repo_id: config.repoId, url: `${searchUrl}/v1/codebase_search` });
1239
1301
  const startTime = Date.now();
1240
1302
  try {
1241
1303
  const fetchPromise = fetchWithRetry(
@@ -1259,7 +1321,7 @@ async function executeCodebaseSearch(input, config) {
1259
1321
  const response = await withTimeout(fetchPromise, timeout, `Codebase search timed out after ${timeout}ms`);
1260
1322
  if (!response.ok) {
1261
1323
  const errorText = await response.text();
1262
- if (debug) console.error(`[CodebaseSearch] Error: ${response.status} - ${errorText}`);
1324
+ logger.error("CodebaseSearch", "response_error", { status: response.status, error: errorText, latency_ms: Date.now() - startTime });
1263
1325
  return {
1264
1326
  success: false,
1265
1327
  results: [],
@@ -1269,16 +1331,14 @@ async function executeCodebaseSearch(input, config) {
1269
1331
  }
1270
1332
  const data = await response.json();
1271
1333
  const elapsed = Date.now() - startTime;
1272
- if (debug) {
1273
- console.log(`[CodebaseSearch] \u2705 ${data.results?.length || 0} results in ${elapsed}ms`);
1274
- }
1334
+ logger.debug("CodebaseSearch", "response", { results_count: data.results?.length || 0, latency_ms: elapsed });
1275
1335
  return {
1276
1336
  success: true,
1277
1337
  results: data.results || [],
1278
1338
  stats: data.stats || { totalResults: 0, candidatesRetrieved: 0, searchTimeMs: elapsed }
1279
1339
  };
1280
1340
  } catch (error) {
1281
- if (debug) console.error(`[CodebaseSearch] Exception: ${error instanceof Error ? error.message : error}`);
1341
+ logger.error("CodebaseSearch", "exception", { error: error instanceof Error ? error.message : String(error), latency_ms: Date.now() - startTime });
1282
1342
  return {
1283
1343
  success: false,
1284
1344
  results: [],
@@ -1288,6 +1348,9 @@ async function executeCodebaseSearch(input, config) {
1288
1348
  }
1289
1349
  }
1290
1350
 
1351
+ // tools/browser/core.ts
1352
+ init_logger();
1353
+
1291
1354
  // tools/browser/live.ts
1292
1355
  var LIVE_PRESETS = {
1293
1356
  /** Read-only monitoring (no interaction) */
@@ -1984,11 +2047,7 @@ var BrowserClient = class {
1984
2047
  if (!hasTask && !hasDiff) {
1985
2048
  throw new Error('Browser task requires either "task" (natural language) or "diff" (PR-review planning)');
1986
2049
  }
1987
- if (debug) {
1988
- const preview = (input.task ?? "").slice(0, 60);
1989
- console.log(`[Browser] createTask: "${preview}..." url=${input.url || "none"}`);
1990
- console.log(`[Browser] Calling async endpoint: ${apiUrl}/browser-task/async`);
1991
- }
2050
+ logger.debug("Browser", "create_task", { task: (input.task ?? "").slice(0, 100), url: input.url, endpoint: `${apiUrl}/browser-task/async` });
1992
2051
  const headers = { "Content-Type": "application/json" };
1993
2052
  if (this.config.apiKey) headers["Authorization"] = `Bearer ${this.config.apiKey}`;
1994
2053
  const response = await fetch(`${apiUrl}/browser-task/async`, {
@@ -2018,14 +2077,11 @@ var BrowserClient = class {
2018
2077
  });
2019
2078
  if (!response.ok) {
2020
2079
  const errorText = await response.text().catch(() => response.statusText);
2021
- if (debug) console.error(`[Browser] Error: ${response.status} - ${errorText}`);
2080
+ logger.error("Browser", "create_task_error", { status: response.status, error: errorText });
2022
2081
  throw new Error(`HTTP ${response.status}: ${errorText}`);
2023
2082
  }
2024
2083
  const result = mapTaskResult(await response.json());
2025
- if (debug) {
2026
- const debugUrl = result.debugUrl;
2027
- console.log(`[Browser] \u2705 Task created: recordingId=${result.recordingId ?? "none"} debugUrl=${debugUrl ? "available" : "none"}`);
2028
- }
2084
+ logger.debug("Browser", "task_created", { recording_id: result.recordingId, task_id: result.taskId, debug_url: !!result.debugUrl });
2029
2085
  if ("schema" in input) {
2030
2086
  return wrapTaskResponseWithSchema(result, this.config, input.schema);
2031
2087
  } else {
@@ -2085,10 +2141,7 @@ async function executeBrowserTask(input, config = {}) {
2085
2141
  error: "maxSteps must be between 1 and 50. Use more steps for complex multi-page flows."
2086
2142
  };
2087
2143
  }
2088
- if (debug) {
2089
- console.log(`[Browser] Task: "${input.task.slice(0, 60)}..." url=${input.url || "none"} maxSteps=${input.maxSteps ?? 10}`);
2090
- console.log(`[Browser] Recording: ${input.recordVideo ? "yes" : "no"} | Calling ${apiUrl}/browser-task`);
2091
- }
2144
+ logger.debug("Browser", "execute_start", { task: input.task.slice(0, 100), url: input.url, max_steps: input.maxSteps ?? 10, record_video: input.recordVideo ?? false });
2092
2145
  const startTime = Date.now();
2093
2146
  try {
2094
2147
  const headers = { "Content-Type": "application/json" };
@@ -2127,14 +2180,12 @@ async function executeBrowserTask(input, config = {}) {
2127
2180
  );
2128
2181
  if (!response.ok) {
2129
2182
  const errorText = await response.text().catch(() => response.statusText);
2130
- if (debug) console.error(`[Browser] Error: ${response.status} - ${errorText}`);
2183
+ logger.error("Browser", "execute_error", { status: response.status, error: errorText });
2131
2184
  throw new Error(`HTTP ${response.status}: ${errorText}`);
2132
2185
  }
2133
2186
  const result = mapTaskResult(await response.json());
2134
2187
  const elapsed = Date.now() - startTime;
2135
- if (debug) {
2136
- console.log(`[Browser] \u2705 ${result.success ? "Success" : "Failed"} in ${elapsed}ms | steps=${result.stepsTaken ?? 0} recordingId=${result.recordingId ?? "none"}`);
2137
- }
2188
+ logger.debug("Browser", "execute_complete", { success: result.success, latency_ms: elapsed, steps: result.stepsTaken ?? 0, recording_id: result.recordingId });
2138
2189
  return result;
2139
2190
  } catch (error) {
2140
2191
  if (error instanceof Error) {
@@ -2845,6 +2896,7 @@ function enforceContextLimit(messages, maxChars = AGENT_CONFIG.MAX_CONTEXT_CHARS
2845
2896
  var import_openai2 = __toESM(require("openai"), 1);
2846
2897
  init_version();
2847
2898
  var import_path4 = __toESM(require("path"), 1);
2899
+ init_logger();
2848
2900
  var DEFAULT_API_URL3 = "https://api.morphllm.com";
2849
2901
  var TOOL_SPECS = [
2850
2902
  {
@@ -2967,6 +3019,8 @@ async function callModel(messages, model, options = {}) {
2967
3019
  defaultHeaders: { "X-Morph-SDK-Version": SDK_VERSION }
2968
3020
  });
2969
3021
  const MAX_EMPTY_RETRIES = 1;
3022
+ logger.debug("WarpGrep", "model_call", { url: baseURL, model, message_count: messages.length });
3023
+ const callStartTime = Date.now();
2970
3024
  for (let attempt = 0; attempt <= MAX_EMPTY_RETRIES; attempt++) {
2971
3025
  let data;
2972
3026
  try {
@@ -2979,10 +3033,16 @@ async function callModel(messages, model, options = {}) {
2979
3033
  ...options.search_type ? { search_type: options.search_type } : {}
2980
3034
  });
2981
3035
  } catch (error) {
2982
- if (error instanceof import_openai2.default.APIError && error.status === 404) {
2983
- const defaultMsg = "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";
2984
- const errorText = error.message?.trim();
2985
- throw new Error(errorText || defaultMsg);
3036
+ const callLatencyMs = Date.now() - callStartTime;
3037
+ if (error instanceof import_openai2.default.APIError) {
3038
+ logger.error("WarpGrep", "model_call_error", { status: error.status, error: error.message, latency_ms: callLatencyMs });
3039
+ if (error.status === 404) {
3040
+ const defaultMsg = "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";
3041
+ const errorText = error.message?.trim();
3042
+ throw new Error(errorText || defaultMsg);
3043
+ }
3044
+ } else {
3045
+ logger.error("WarpGrep", "model_call_error", { status: void 0, error: error instanceof Error ? error.message : String(error), latency_ms: callLatencyMs });
2986
3046
  }
2987
3047
  throw error;
2988
3048
  }
@@ -3001,6 +3061,7 @@ async function callModel(messages, model, options = {}) {
3001
3061
  function: { name: tc.function.name, arguments: tc.function.arguments }
3002
3062
  }));
3003
3063
  if (message.content || toolCalls.length > 0) {
3064
+ logger.debug("WarpGrep", "model_call_complete", { latency_ms: Date.now() - callStartTime, tool_calls_count: toolCalls.length, finish_reason: choice?.finish_reason ?? "unknown" });
3004
3065
  return { content: message.content ?? null, tool_calls: toolCalls };
3005
3066
  }
3006
3067
  if (attempt === MAX_EMPTY_RETRIES) {
@@ -3071,9 +3132,11 @@ async function* runWarpGrepStreaming(config) {
3071
3132
  const model = config.model || DEFAULT_MODEL;
3072
3133
  const messages = [];
3073
3134
  const maxTurns = AGENT_CONFIG.MAX_TURNS;
3135
+ logger.debug("WarpGrep", "session_start", { search_term: config.searchTerm, model, max_turns: maxTurns });
3074
3136
  const initialStateStart = Date.now();
3075
3137
  const initialState = await buildInitialState(repoRoot, config.searchTerm, config.provider, { search_type: config.search_type });
3076
3138
  timings.initial_state_ms = Date.now() - initialStateStart;
3139
+ logger.debug("WarpGrep", "initial_state", { system_prompt_len: initialState.length, user_message_len: initialState.length });
3077
3140
  messages.push({ role: "user", content: initialState });
3078
3141
  const provider = config.provider;
3079
3142
  const errors = [];
@@ -3081,7 +3144,13 @@ async function* runWarpGrepStreaming(config) {
3081
3144
  let terminationReason = "terminated";
3082
3145
  for (let turn = 1; turn <= maxTurns; turn += 1) {
3083
3146
  const turnMetrics = { turn, morph_api_ms: 0, local_tools_ms: 0 };
3147
+ logger.debug("WarpGrep", "turn_start", { turn, message_count: messages.length });
3148
+ const beforeChars = messages.reduce((sum, m) => sum + (typeof m.content === "string" ? m.content.length : 0), 0);
3084
3149
  enforceContextLimit(messages);
3150
+ const afterChars = messages.reduce((sum, m) => sum + (typeof m.content === "string" ? m.content.length : 0), 0);
3151
+ if (afterChars < beforeChars) {
3152
+ logger.debug("WarpGrep", "context_truncated", { before_chars: beforeChars, after_chars: afterChars });
3153
+ }
3085
3154
  const modelCallStart = Date.now();
3086
3155
  const response = await callModel(messages, model, {
3087
3156
  morphApiKey: config.morphApiKey,
@@ -3092,6 +3161,7 @@ async function* runWarpGrepStreaming(config) {
3092
3161
  }).catch((e) => {
3093
3162
  const errMsg = e instanceof Error ? e.message : String(e);
3094
3163
  console.error(`[warp_grep] Morph API call failed on turn ${turn}:`, errMsg);
3164
+ logger.error("WarpGrep", "error", { turn, error: errMsg, phase: "model_call" });
3095
3165
  errors.push({ message: errMsg });
3096
3166
  return null;
3097
3167
  });
@@ -3101,6 +3171,7 @@ async function* runWarpGrepStreaming(config) {
3101
3171
  break;
3102
3172
  }
3103
3173
  const toolCalls = response.tool_calls;
3174
+ logger.debug("WarpGrep", "model_response", { turn, tool_calls: toolCalls.map((tc) => tc.function.name), latency_ms: turnMetrics.morph_api_ms });
3104
3175
  messages.push({
3105
3176
  role: "assistant",
3106
3177
  content: response.content,
@@ -3127,6 +3198,7 @@ async function* runWarpGrepStreaming(config) {
3127
3198
  const files = parseFinishFiles(filesStr);
3128
3199
  finishMeta = { files };
3129
3200
  terminationReason = "completed";
3201
+ logger.debug("WarpGrep", "finish", { turns: turn, files: files.map((f) => f.path) });
3130
3202
  if (files.length === 0) {
3131
3203
  const payload2 = filesStr || "No relevant code found.";
3132
3204
  timings.turns.push(turnMetrics);
@@ -3145,7 +3217,11 @@ async function* runWarpGrepStreaming(config) {
3145
3217
  const results = await Promise.all(
3146
3218
  toolCalls.map(async (tc) => {
3147
3219
  const args = safeParseJSON(tc.function.arguments);
3220
+ const argsSummary = Object.fromEntries(Object.entries(args).map(([k, v]) => [k, typeof v === "string" && v.length > 100 ? v.slice(0, 100) + "..." : v]));
3221
+ logger.debug("WarpGrep", "tool_exec", { turn, tool: tc.function.name, args_summary: argsSummary });
3222
+ const toolStart = Date.now();
3148
3223
  const output = await executeTool(provider, tc.function.name, args, repoRoot).catch((err) => String(err));
3224
+ logger.debug("WarpGrep", "tool_result", { turn, tool: tc.function.name, result_len: output.length, latency_ms: Date.now() - toolStart });
3149
3225
  return { tool_call_id: tc.id, content: output };
3150
3226
  })
3151
3227
  );
@@ -3214,6 +3290,9 @@ async function runWarpGrep(config) {
3214
3290
  return result.value;
3215
3291
  }
3216
3292
 
3293
+ // tools/warp_grep/client.ts
3294
+ init_logger();
3295
+
3217
3296
  // tools/warp_grep/providers/remote.ts
3218
3297
  init_config();
3219
3298
  var SKIP_NAMES = /* @__PURE__ */ new Set([
@@ -3653,12 +3732,16 @@ var WarpGrepClient = class {
3653
3732
  async _resolveGitHubRepo(input) {
3654
3733
  const { owner, repo } = parseGitHubUrl(input.github);
3655
3734
  const baseUrl = this.config.codeSearchUrl || DEFAULT_CODE_SEARCH_URL;
3735
+ logger.debug("WarpGrep", "github_resolve", { owner_repo: `${owner}/${repo}`, branch: input.branch });
3736
+ const resolveStart = Date.now();
3656
3737
  const importRes = await fetch(`${baseUrl}/api/code-search/get-or-create?url=${encodeURIComponent(`${owner}/${repo}`)}`);
3657
3738
  if (!importRes.ok) {
3658
3739
  const text = await importRes.text().catch(() => importRes.statusText);
3740
+ logger.error("WarpGrep", "github_resolve_failed", { owner_repo: `${owner}/${repo}`, status: importRes.status, error: text });
3659
3741
  throw new Error(`Failed to import repo ${owner}/${repo}: ${text}`);
3660
3742
  }
3661
3743
  const { repoId, defaultBranch } = await importRes.json();
3744
+ logger.debug("WarpGrep", "github_repo_fetched", { repo_id: repoId, default_branch: defaultBranch, latency_ms: Date.now() - resolveStart });
3662
3745
  return {
3663
3746
  repo,
3664
3747
  remoteCommands: createCodeStorageHttpCommands({ baseUrl, repoId, branch: input.branch || defaultBranch })
@@ -4199,7 +4282,7 @@ var GitHubClient = class {
4199
4282
  // git/client.ts
4200
4283
  var import_isomorphic_git = __toESM(require("isomorphic-git"), 1);
4201
4284
  var import_node = __toESM(require("isomorphic-git/http/node"), 1);
4202
- var import_fs2 = __toESM(require("fs"), 1);
4285
+ var import_fs3 = __toESM(require("fs"), 1);
4203
4286
  var DEFAULT_PROXY_URL = "https://repos.morphllm.com";
4204
4287
  var MorphGit = class {
4205
4288
  apiKey;
@@ -4256,12 +4339,12 @@ var MorphGit = class {
4256
4339
  throw new Error(`Failed to create repository: ${error}`);
4257
4340
  }
4258
4341
  await import_isomorphic_git.default.init({
4259
- fs: import_fs2.default,
4342
+ fs: import_fs3.default,
4260
4343
  dir,
4261
4344
  defaultBranch
4262
4345
  });
4263
4346
  await import_isomorphic_git.default.addRemote({
4264
- fs: import_fs2.default,
4347
+ fs: import_fs3.default,
4265
4348
  dir,
4266
4349
  remote: "origin",
4267
4350
  url: `${this.proxyUrl}/v1/repos/${repoId}`
@@ -4282,7 +4365,7 @@ var MorphGit = class {
4282
4365
  async clone(options) {
4283
4366
  const { repoId, dir, branch = "main", depth, singleBranch = true } = options;
4284
4367
  await import_isomorphic_git.default.clone({
4285
- fs: import_fs2.default,
4368
+ fs: import_fs3.default,
4286
4369
  http: import_node.default,
4287
4370
  dir,
4288
4371
  url: `${this.proxyUrl}/v1/repos/${repoId}`,
@@ -4311,9 +4394,9 @@ var MorphGit = class {
4311
4394
  'branch is required for push operations. Specify the branch explicitly: { dir: "./my-project", branch: "main" }'
4312
4395
  );
4313
4396
  }
4314
- const commitHash = await import_isomorphic_git.default.resolveRef({ fs: import_fs2.default, dir, ref: "HEAD" });
4397
+ const commitHash = await import_isomorphic_git.default.resolveRef({ fs: import_fs3.default, dir, ref: "HEAD" });
4315
4398
  let repoId;
4316
- const remotes = await import_isomorphic_git.default.listRemotes({ fs: import_fs2.default, dir });
4399
+ const remotes = await import_isomorphic_git.default.listRemotes({ fs: import_fs3.default, dir });
4317
4400
  const originRemote = remotes.find((r) => r.remote === remote);
4318
4401
  if (originRemote) {
4319
4402
  const match = originRemote.url.match(/\/repos\/([^\/]+)$/);
@@ -4322,7 +4405,7 @@ var MorphGit = class {
4322
4405
  }
4323
4406
  }
4324
4407
  await import_isomorphic_git.default.push({
4325
- fs: import_fs2.default,
4408
+ fs: import_fs3.default,
4326
4409
  http: import_node.default,
4327
4410
  dir,
4328
4411
  remote,
@@ -4377,7 +4460,7 @@ var MorphGit = class {
4377
4460
  );
4378
4461
  }
4379
4462
  await import_isomorphic_git.default.pull({
4380
- fs: import_fs2.default,
4463
+ fs: import_fs3.default,
4381
4464
  http: import_node.default,
4382
4465
  dir,
4383
4466
  remote,
@@ -4446,7 +4529,7 @@ var MorphGit = class {
4446
4529
  async add(options) {
4447
4530
  const { dir, filepath } = options;
4448
4531
  await import_isomorphic_git.default.add({
4449
- fs: import_fs2.default,
4532
+ fs: import_fs3.default,
4450
4533
  dir,
4451
4534
  filepath
4452
4535
  });
@@ -4465,7 +4548,7 @@ var MorphGit = class {
4465
4548
  async remove(options) {
4466
4549
  const { dir, filepath } = options;
4467
4550
  await import_isomorphic_git.default.remove({
4468
- fs: import_fs2.default,
4551
+ fs: import_fs3.default,
4469
4552
  dir,
4470
4553
  filepath
4471
4554
  });
@@ -4498,7 +4581,7 @@ var MorphGit = class {
4498
4581
  email: "sdk@morphllm.com"
4499
4582
  };
4500
4583
  const sha = await import_isomorphic_git.default.commit({
4501
- fs: import_fs2.default,
4584
+ fs: import_fs3.default,
4502
4585
  dir,
4503
4586
  message,
4504
4587
  author: commitAuthor
@@ -4511,7 +4594,7 @@ var MorphGit = class {
4511
4594
  _version: 1
4512
4595
  };
4513
4596
  await import_isomorphic_git.default.addNote({
4514
- fs: import_fs2.default,
4597
+ fs: import_fs3.default,
4515
4598
  dir,
4516
4599
  ref: "refs/notes/morph-metadata",
4517
4600
  oid: sha,
@@ -4539,7 +4622,7 @@ var MorphGit = class {
4539
4622
  throw new Error("filepath is required for status check");
4540
4623
  }
4541
4624
  const status = await import_isomorphic_git.default.status({
4542
- fs: import_fs2.default,
4625
+ fs: import_fs3.default,
4543
4626
  dir,
4544
4627
  filepath
4545
4628
  });
@@ -4559,7 +4642,7 @@ var MorphGit = class {
4559
4642
  async log(options) {
4560
4643
  const { dir, depth, ref } = options;
4561
4644
  const commits = await import_isomorphic_git.default.log({
4562
- fs: import_fs2.default,
4645
+ fs: import_fs3.default,
4563
4646
  dir,
4564
4647
  depth,
4565
4648
  ref
@@ -4580,7 +4663,7 @@ var MorphGit = class {
4580
4663
  async checkout(options) {
4581
4664
  const { dir, ref } = options;
4582
4665
  await import_isomorphic_git.default.checkout({
4583
- fs: import_fs2.default,
4666
+ fs: import_fs3.default,
4584
4667
  dir,
4585
4668
  ref
4586
4669
  });
@@ -4600,7 +4683,7 @@ var MorphGit = class {
4600
4683
  async branch(options) {
4601
4684
  const { dir, name, checkout = false } = options;
4602
4685
  await import_isomorphic_git.default.branch({
4603
- fs: import_fs2.default,
4686
+ fs: import_fs3.default,
4604
4687
  dir,
4605
4688
  ref: name,
4606
4689
  checkout
@@ -4619,7 +4702,7 @@ var MorphGit = class {
4619
4702
  async listBranches(options) {
4620
4703
  const { dir } = options;
4621
4704
  const branches = await import_isomorphic_git.default.listBranches({
4622
- fs: import_fs2.default,
4705
+ fs: import_fs3.default,
4623
4706
  dir
4624
4707
  });
4625
4708
  return branches;
@@ -4637,7 +4720,7 @@ var MorphGit = class {
4637
4720
  async currentBranch(options) {
4638
4721
  const { dir } = options;
4639
4722
  const branch = await import_isomorphic_git.default.currentBranch({
4640
- fs: import_fs2.default,
4723
+ fs: import_fs3.default,
4641
4724
  dir
4642
4725
  });
4643
4726
  return branch || void 0;
@@ -4655,7 +4738,7 @@ var MorphGit = class {
4655
4738
  async statusMatrix(options) {
4656
4739
  const { dir } = options;
4657
4740
  const matrix = await import_isomorphic_git.default.statusMatrix({
4658
- fs: import_fs2.default,
4741
+ fs: import_fs3.default,
4659
4742
  dir
4660
4743
  });
4661
4744
  return matrix.map(([filepath, HEADStatus, workdirStatus, stageStatus]) => {
@@ -4697,7 +4780,7 @@ var MorphGit = class {
4697
4780
  async resolveRef(options) {
4698
4781
  const { dir, ref } = options;
4699
4782
  const oid = await import_isomorphic_git.default.resolveRef({
4700
- fs: import_fs2.default,
4783
+ fs: import_fs3.default,
4701
4784
  dir,
4702
4785
  ref
4703
4786
  });
@@ -4723,7 +4806,7 @@ var MorphGit = class {
4723
4806
  async getCommitMetadata(options) {
4724
4807
  try {
4725
4808
  const note = await import_isomorphic_git.default.readNote({
4726
- fs: import_fs2.default,
4809
+ fs: import_fs3.default,
4727
4810
  dir: options.dir,
4728
4811
  ref: "refs/notes/morph-metadata",
4729
4812
  oid: options.commitSha
@@ -4741,6 +4824,7 @@ var import_isomorphic_git2 = __toESM(require("isomorphic-git"), 1);
4741
4824
  var import_node2 = __toESM(require("isomorphic-git/http/node"), 1);
4742
4825
 
4743
4826
  // modelrouter/core.ts
4827
+ init_logger();
4744
4828
  var DEFAULT_CONFIG3 = {
4745
4829
  apiUrl: "https://api.morphllm.com",
4746
4830
  timeout: 5e3,
@@ -4776,12 +4860,7 @@ var BaseRouter = class {
4776
4860
  input: input.input,
4777
4861
  mode
4778
4862
  };
4779
- if (this.config.debug) {
4780
- console.log(`[ModelRouter] Requesting ${this.provider} model selection:`, {
4781
- mode,
4782
- inputLength: input.input.length
4783
- });
4784
- }
4863
+ logger.debug("ModelRouter", "request", { provider: this.provider, mode, input_len: input.input.length, url });
4785
4864
  try {
4786
4865
  const fetchPromise = fetchWithRetry(
4787
4866
  url,
@@ -4810,14 +4889,10 @@ var BaseRouter = class {
4810
4889
  const result = {
4811
4890
  model: apiResult.model
4812
4891
  };
4813
- if (this.config.debug) {
4814
- console.log(`[ModelRouter] Selected model: ${apiResult.model}, Confidence: ${apiResult.confidence?.toFixed(3)}`);
4815
- }
4892
+ logger.debug("ModelRouter", "selected", { provider: this.provider, model: apiResult.model, confidence: apiResult.confidence });
4816
4893
  return result;
4817
4894
  } catch (error) {
4818
- if (this.config.debug) {
4819
- console.error(`[ModelRouter] Error selecting model:`, error);
4820
- }
4895
+ logger.error("ModelRouter", "error", { provider: this.provider, error: error instanceof Error ? error.message : String(error) });
4821
4896
  throw error;
4822
4897
  }
4823
4898
  }
@@ -4887,12 +4962,7 @@ var RawRouter = class extends BaseRouter {
4887
4962
  input: input.input,
4888
4963
  mode
4889
4964
  };
4890
- if (this.config.debug) {
4891
- console.log(`[RawRouter] Requesting raw difficulty classification:`, {
4892
- mode,
4893
- inputLength: input.input.length
4894
- });
4895
- }
4965
+ logger.debug("RawRouter", "request", { mode, input_len: input.input.length, url });
4896
4966
  try {
4897
4967
  const fetchPromise = fetchWithRetry(
4898
4968
  url,
@@ -4927,14 +4997,10 @@ var RawRouter = class extends BaseRouter {
4927
4997
  const result = {
4928
4998
  difficulty
4929
4999
  };
4930
- if (this.config.debug) {
4931
- console.log(`[RawRouter] Classified as: ${difficulty}`);
4932
- }
5000
+ logger.debug("RawRouter", "classified", { difficulty });
4933
5001
  return result;
4934
5002
  } catch (error) {
4935
- if (this.config.debug) {
4936
- console.error(`[RawRouter] Error classifying:`, error);
4937
- }
5003
+ logger.error("RawRouter", "error", { error: error instanceof Error ? error.message : String(error) });
4938
5004
  throw error;
4939
5005
  }
4940
5006
  }
@@ -6360,6 +6426,10 @@ var MorphClient = class {
6360
6426
  */
6361
6427
  constructor(config = {}) {
6362
6428
  this.config = config;
6429
+ if (config.debug) {
6430
+ logger.enable();
6431
+ }
6432
+ logger.debug("MorphClient", "initialized", { debug: !!config.debug, timeout: config.timeout });
6363
6433
  this.fastApply = new FastApplyClient({
6364
6434
  apiKey: config.apiKey,
6365
6435
  debug: config.debug,