@frontman-ai/astro 0.2.2 → 0.2.4

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.
@@ -1,5 +1,5 @@
1
1
  import * as Web from 'stream/web';
2
- import * as Fs3 from 'fs';
2
+ import * as Fs from 'fs';
3
3
  import { existsSync, readFileSync } from 'fs';
4
4
  import * as Nodepath from 'path';
5
5
  import { dirname, join } from 'path';
@@ -26,6 +26,97 @@ var require_lib = __commonJS({
26
26
  }
27
27
  });
28
28
 
29
+ // ../../node_modules/@rescript/runtime/lib/es6/Stdlib_JsError.js
30
+ function panic(msg) {
31
+ throw new Error(`Panic! ` + msg);
32
+ }
33
+
34
+ // ../../node_modules/@rescript/runtime/lib/es6/Primitive_option.js
35
+ function some(x) {
36
+ if (x === void 0) {
37
+ return {
38
+ BS_PRIVATE_NESTED_SOME_NONE: 0
39
+ };
40
+ } else if (x !== null && x.BS_PRIVATE_NESTED_SOME_NONE !== void 0) {
41
+ return {
42
+ BS_PRIVATE_NESTED_SOME_NONE: x.BS_PRIVATE_NESTED_SOME_NONE + 1 | 0
43
+ };
44
+ } else {
45
+ return x;
46
+ }
47
+ }
48
+ function fromNullable(x) {
49
+ if (x == null) {
50
+ return;
51
+ } else {
52
+ return some(x);
53
+ }
54
+ }
55
+ function valFromOption(x) {
56
+ if (x === null || x.BS_PRIVATE_NESTED_SOME_NONE === void 0) {
57
+ return x;
58
+ }
59
+ let depth = x.BS_PRIVATE_NESTED_SOME_NONE;
60
+ if (depth === 0) {
61
+ return;
62
+ } else {
63
+ return {
64
+ BS_PRIVATE_NESTED_SOME_NONE: depth - 1 | 0
65
+ };
66
+ }
67
+ }
68
+
69
+ // ../../node_modules/@rescript/runtime/lib/es6/Stdlib_Option.js
70
+ function forEach(opt, f) {
71
+ if (opt !== void 0) {
72
+ return f(valFromOption(opt));
73
+ }
74
+ }
75
+ function getOrThrow(x, message3) {
76
+ if (x !== void 0) {
77
+ return valFromOption(x);
78
+ } else {
79
+ return panic("Option.getOrThrow called for None value");
80
+ }
81
+ }
82
+ function mapOr(opt, $$default, f) {
83
+ if (opt !== void 0) {
84
+ return f(valFromOption(opt));
85
+ } else {
86
+ return $$default;
87
+ }
88
+ }
89
+ function map(opt, f) {
90
+ if (opt !== void 0) {
91
+ return some(f(valFromOption(opt)));
92
+ }
93
+ }
94
+ function flatMap(opt, f) {
95
+ if (opt !== void 0) {
96
+ return f(valFromOption(opt));
97
+ }
98
+ }
99
+ function getOr(opt, $$default) {
100
+ if (opt !== void 0) {
101
+ return valFromOption(opt);
102
+ } else {
103
+ return $$default;
104
+ }
105
+ }
106
+ function orElse(opt, other) {
107
+ if (opt !== void 0) {
108
+ return opt;
109
+ } else {
110
+ return other;
111
+ }
112
+ }
113
+ function isSome(x) {
114
+ return x !== void 0;
115
+ }
116
+ function isNone(x) {
117
+ return x === void 0;
118
+ }
119
+
29
120
  // src/annotation-capture.mjs
30
121
  var annotationCaptureScript = `(function() {
31
122
  var PROPS_PREFIX = '__frontman_props__:';
@@ -257,75 +348,6 @@ function renderComponent(result, displayName, Component, props, slots) {
257
348
  };
258
349
  }
259
350
 
260
- // ../../node_modules/@rescript/runtime/lib/es6/Primitive_option.js
261
- function some(x) {
262
- if (x === void 0) {
263
- return {
264
- BS_PRIVATE_NESTED_SOME_NONE: 0
265
- };
266
- } else if (x !== null && x.BS_PRIVATE_NESTED_SOME_NONE !== void 0) {
267
- return {
268
- BS_PRIVATE_NESTED_SOME_NONE: x.BS_PRIVATE_NESTED_SOME_NONE + 1 | 0
269
- };
270
- } else {
271
- return x;
272
- }
273
- }
274
- function fromNullable(x) {
275
- if (x == null) {
276
- return;
277
- } else {
278
- return some(x);
279
- }
280
- }
281
- function valFromOption(x) {
282
- if (x === null || x.BS_PRIVATE_NESTED_SOME_NONE === void 0) {
283
- return x;
284
- }
285
- let depth = x.BS_PRIVATE_NESTED_SOME_NONE;
286
- if (depth === 0) {
287
- return;
288
- } else {
289
- return {
290
- BS_PRIVATE_NESTED_SOME_NONE: depth - 1 | 0
291
- };
292
- }
293
- }
294
-
295
- // ../../node_modules/@rescript/runtime/lib/es6/Stdlib_Option.js
296
- function forEach(opt, f) {
297
- if (opt !== void 0) {
298
- return f(valFromOption(opt));
299
- }
300
- }
301
- function map(opt, f) {
302
- if (opt !== void 0) {
303
- return some(f(valFromOption(opt)));
304
- }
305
- }
306
- function flatMap(opt, f) {
307
- if (opt !== void 0) {
308
- return f(valFromOption(opt));
309
- }
310
- }
311
- function getOr(opt, $$default) {
312
- if (opt !== void 0) {
313
- return valFromOption(opt);
314
- } else {
315
- return $$default;
316
- }
317
- }
318
- function orElse(opt, other) {
319
- if (opt !== void 0) {
320
- return opt;
321
- } else {
322
- return other;
323
- }
324
- }
325
- function isSome(x) {
326
- return x !== void 0;
327
- }
328
-
329
351
  // ../frontman-core/src/FrontmanCore__Hosts.res.mjs
330
352
  var apiHost = "api.frontman.sh";
331
353
  var clientJs = "https://app.frontman.sh/frontman.es.js";
@@ -344,7 +366,8 @@ function makeFromObject(rawConfig) {
344
366
  let isDev = host2 !== apiHost;
345
367
  let projectRoot = getOr(orElse(config.projectRoot, orElse(process.env["PROJECT_ROOT"], process.env["PWD"])), ".");
346
368
  let sourceRoot = getOr(config.sourceRoot, projectRoot);
347
- let basePath = getOr(config.basePath, "frontman");
369
+ let raw = getOr(config.basePath, "frontman").replace(/^\/+|\/+$/g, "");
370
+ let basePath = raw === "" ? "frontman" : raw;
348
371
  let serverName = getOr(config.serverName, "frontman-astro");
349
372
  let serverVersion = getOr(config.serverVersion, "1.0.0");
350
373
  let isLightTheme = getOr(config.isLightTheme, false);
@@ -371,7 +394,57 @@ function makeFromObject(rawConfig) {
371
394
  };
372
395
  }
373
396
 
397
+ // ../../node_modules/@rescript/runtime/lib/es6/Stdlib_Dict.js
398
+ var forEachWithKey = ((dict3, f) => {
399
+ for (var i in dict3) {
400
+ f(dict3[i], i);
401
+ }
402
+ });
403
+
404
+ // ../frontman-core/src/FrontmanCore__CORS.res.mjs
405
+ var corsHeaders = Object.fromEntries([
406
+ [
407
+ "Access-Control-Allow-Origin",
408
+ "*"
409
+ ],
410
+ [
411
+ "Access-Control-Allow-Methods",
412
+ "GET, POST, OPTIONS"
413
+ ],
414
+ [
415
+ "Access-Control-Allow-Headers",
416
+ "Content-Type"
417
+ ]
418
+ ]);
419
+ function withCors(response) {
420
+ let headers2 = response.headers;
421
+ forEachWithKey(corsHeaders, (value, key) => {
422
+ headers2.set(key, value);
423
+ });
424
+ return response;
425
+ }
426
+ function handlePreflight() {
427
+ return new Response(null, {
428
+ status: 204,
429
+ headers: some(corsHeaders)
430
+ });
431
+ }
432
+
374
433
  // ../../node_modules/@rescript/runtime/lib/es6/Primitive_int.js
434
+ function min(x, y) {
435
+ if (x < y) {
436
+ return x;
437
+ } else {
438
+ return y;
439
+ }
440
+ }
441
+ function max(x, y) {
442
+ if (x > y) {
443
+ return x;
444
+ } else {
445
+ return y;
446
+ }
447
+ }
375
448
  function div(x, y) {
376
449
  if (y === 0) {
377
450
  throw {
@@ -381,24 +454,14 @@ function div(x, y) {
381
454
  }
382
455
  return x / y | 0;
383
456
  }
384
-
385
- // ../../node_modules/@rescript/runtime/lib/es6/Belt_Array.js
386
- function concatMany(arrs) {
387
- let lenArrs = arrs.length;
388
- let totalLen = 0;
389
- for (let i = 0; i < lenArrs; ++i) {
390
- totalLen = totalLen + arrs[i].length | 0;
391
- }
392
- let result = new Array(totalLen);
393
- totalLen = 0;
394
- for (let j2 = 0; j2 < lenArrs; ++j2) {
395
- let cur = arrs[j2];
396
- for (let k2 = 0, k_finish = cur.length; k2 < k_finish; ++k2) {
397
- result[totalLen] = cur[k2];
398
- totalLen = totalLen + 1 | 0;
399
- }
457
+ function mod_(x, y) {
458
+ if (y === 0) {
459
+ throw {
460
+ RE_EXN_ID: "Division_by_zero",
461
+ Error: new Error()
462
+ };
400
463
  }
401
- return result;
464
+ return x % y;
402
465
  }
403
466
 
404
467
  // ../../node_modules/@rescript/runtime/lib/es6/Primitive_exceptions.js
@@ -434,22 +497,22 @@ function create(str) {
434
497
  // ../../node_modules/sury/src/Sury.res.mjs
435
498
  var immutableEmpty = {};
436
499
  var immutableEmpty$1 = [];
437
- function capitalize(string4) {
438
- return string4.slice(0, 1).toUpperCase() + string4.slice(1);
500
+ function capitalize(string3) {
501
+ return string3.slice(0, 1).toUpperCase() + string3.slice(1);
439
502
  }
440
503
  var copy = ((d2) => ({ ...d2 }));
441
- function fromString(string4) {
504
+ function fromString(string3) {
442
505
  let _idx = 0;
443
506
  while (true) {
444
507
  let idx = _idx;
445
- let match = string4[idx];
508
+ let match = string3[idx];
446
509
  if (match === void 0) {
447
- return `"` + string4 + `"`;
510
+ return `"` + string3 + `"`;
448
511
  }
449
512
  switch (match) {
450
513
  case '"':
451
514
  case "\n":
452
- return JSON.stringify(string4);
515
+ return JSON.stringify(string3);
453
516
  default:
454
517
  _idx = idx + 1 | 0;
455
518
  continue;
@@ -517,14 +580,14 @@ function stringify(unknown2) {
517
580
  return "null";
518
581
  }
519
582
  if (Array.isArray(unknown2)) {
520
- let string4 = "[";
583
+ let string3 = "[";
521
584
  for (let i = 0, i_finish = unknown2.length; i < i_finish; ++i) {
522
585
  if (i !== 0) {
523
- string4 = string4 + ", ";
586
+ string3 = string3 + ", ";
524
587
  }
525
- string4 = string4 + stringify(unknown2[i]);
588
+ string3 = string3 + stringify(unknown2[i]);
526
589
  }
527
- return string4 + "]";
590
+ return string3 + "]";
528
591
  }
529
592
  if (unknown2.constructor !== Object) {
530
593
  return Object.prototype.toString.call(unknown2);
@@ -541,9 +604,9 @@ function stringify(unknown2) {
541
604
  function toExpression(schema3) {
542
605
  let tag = schema3.type;
543
606
  let $$const = schema3.const;
544
- let name11 = schema3.name;
545
- if (name11 !== void 0) {
546
- return name11;
607
+ let name14 = schema3.name;
608
+ if (name14 !== void 0) {
609
+ return name14;
547
610
  }
548
611
  if ($$const !== void 0) {
549
612
  return stringify($$const);
@@ -1088,8 +1151,8 @@ function refinement(b, inputVar, schema3, negative) {
1088
1151
  }
1089
1152
  let additionalItems = schema3.additionalItems;
1090
1153
  let items = schema3.items;
1091
- let length2 = items.length;
1092
- let code = tag === "array" ? additionalItems === "strip" || additionalItems === "strict" ? additionalItems === "strip" ? and_ + inputVar + `.length` + gt + length2 : and_ + inputVar + `.length` + eq + length2 : "" : additionalItems === "strip" ? "" : and_ + not_ + `Array.isArray(` + inputVar + `)`;
1154
+ let length3 = items.length;
1155
+ let code = tag === "array" ? additionalItems === "strip" || additionalItems === "strict" ? additionalItems === "strip" ? and_ + inputVar + `.length` + gt + length3 : and_ + inputVar + `.length` + eq + length3 : "" : additionalItems === "strip" ? "" : and_ + not_ + `Array.isArray(` + inputVar + `)`;
1093
1156
  for (let idx = 0, idx_finish = items.length; idx < idx_finish; ++idx) {
1094
1157
  let match$3 = items[idx];
1095
1158
  let location = match$3.location;
@@ -1663,10 +1726,10 @@ function isPriority(tagFlag, byKey) {
1663
1726
  }
1664
1727
  }
1665
1728
  function isWiderUnionSchema(schemaAnyOf, inputAnyOf) {
1666
- return inputAnyOf.every((inputSchema10, idx) => {
1729
+ return inputAnyOf.every((inputSchema13, idx) => {
1667
1730
  let schema3 = schemaAnyOf[idx];
1668
- if (schema3 !== void 0 && !(flags[inputSchema10.type] & 9152) && inputSchema10.type === schema3.type) {
1669
- return inputSchema10.const === schema3.const;
1731
+ if (schema3 !== void 0 && !(flags[inputSchema13.type] & 9152) && inputSchema13.type === schema3.type) {
1732
+ return inputSchema13.const === schema3.const;
1670
1733
  } else {
1671
1734
  return false;
1672
1735
  }
@@ -2241,9 +2304,9 @@ function definitionToSchema(definition) {
2241
2304
  };
2242
2305
  }
2243
2306
  let fieldNames = Object.keys(definition);
2244
- let length2 = fieldNames.length;
2307
+ let length3 = fieldNames.length;
2245
2308
  let items = [];
2246
- for (let idx$1 = 0; idx$1 < length2; ++idx$1) {
2309
+ for (let idx$1 = 0; idx$1 < length3; ++idx$1) {
2247
2310
  let location$1 = fieldNames[idx$1];
2248
2311
  let schema$1 = definitionToSchema(definition[location$1]);
2249
2312
  let item = {
@@ -2313,9 +2376,9 @@ function internalToJSONSchema(schema3, defs) {
2313
2376
  jsonSchema.maxLength = match.length;
2314
2377
  return;
2315
2378
  case "Length":
2316
- let length2 = match.length;
2317
- jsonSchema.minLength = length2;
2318
- jsonSchema.maxLength = length2;
2379
+ let length3 = match.length;
2380
+ jsonSchema.minLength = length3;
2381
+ jsonSchema.maxLength = length3;
2319
2382
  return;
2320
2383
  case "Pattern":
2321
2384
  jsonSchema.pattern = String(match.re);
@@ -2389,9 +2452,9 @@ function internalToJSONSchema(schema3, defs) {
2389
2452
  jsonSchema.maxItems = match.length;
2390
2453
  return;
2391
2454
  case "Length":
2392
- let length2 = match.length;
2393
- jsonSchema.maxItems = length2;
2394
- jsonSchema.minItems = length2;
2455
+ let length3 = match.length;
2456
+ jsonSchema.maxItems = length3;
2457
+ jsonSchema.minItems = length3;
2395
2458
  return;
2396
2459
  }
2397
2460
  });
@@ -2533,46 +2596,6 @@ var reverseConvertToJsonOrThrow2 = reverseConvertToJsonOrThrow;
2533
2596
  var schema2 = schema;
2534
2597
  var toJSONSchema2 = toJSONSchema;
2535
2598
 
2536
- // ../../node_modules/@rescript/runtime/lib/es6/Stdlib_JSON.js
2537
- function bool3(json3) {
2538
- if (typeof json3 === "boolean") {
2539
- return json3;
2540
- }
2541
- }
2542
- function $$null2(json3) {
2543
- if (json3 === null) {
2544
- return null;
2545
- }
2546
- }
2547
- function string3(json3) {
2548
- if (typeof json3 === "string") {
2549
- return json3;
2550
- }
2551
- }
2552
- function float3(json3) {
2553
- if (typeof json3 === "number") {
2554
- return json3;
2555
- }
2556
- }
2557
- function object2(json3) {
2558
- if (typeof json3 === "object" && json3 !== null && !Array.isArray(json3)) {
2559
- return json3;
2560
- }
2561
- }
2562
- function array3(json3) {
2563
- if (Array.isArray(json3)) {
2564
- return json3;
2565
- }
2566
- }
2567
- var Decode = {
2568
- bool: bool3,
2569
- $$null: $$null2,
2570
- string: string3,
2571
- float: float3,
2572
- object: object2,
2573
- array: array3
2574
- };
2575
-
2576
2599
  // ../../node_modules/@rescript/runtime/lib/es6/Stdlib_JsExn.js
2577
2600
  function fromException(exn) {
2578
2601
  if (exn.RE_EXN_ID === "JsExn") {
@@ -2582,6 +2605,11 @@ function fromException(exn) {
2582
2605
  var getOrUndefined = ((fieldName) => (t) => t && typeof t[fieldName] === "string" ? t[fieldName] : void 0);
2583
2606
  var message2 = getOrUndefined("message");
2584
2607
 
2608
+ // ../../node_modules/@rescript/runtime/lib/es6/Stdlib_Promise.js
2609
+ function $$catch(promise, callback) {
2610
+ return promise.catch((err) => callback(internalToException(err)));
2611
+ }
2612
+
2585
2613
  // ../frontman-protocol/src/FrontmanProtocol__MCP.res.mjs
2586
2614
  enableJson2();
2587
2615
  var capabilitiesSchema = schema2((s2) => ({
@@ -4266,6 +4294,24 @@ async function Te(o) {
4266
4294
  }
4267
4295
 
4268
4296
  // ../../node_modules/@rescript/runtime/lib/es6/Stdlib_Array.js
4297
+ function make2(length3, x) {
4298
+ if (length3 <= 0) {
4299
+ return [];
4300
+ }
4301
+ let arr = new Array(length3);
4302
+ arr.fill(x);
4303
+ return arr;
4304
+ }
4305
+ function fromInitializer(length3, f) {
4306
+ if (length3 <= 0) {
4307
+ return [];
4308
+ }
4309
+ let arr = new Array(length3);
4310
+ for (let i = 0; i < length3; ++i) {
4311
+ arr[i] = f(i);
4312
+ }
4313
+ return arr;
4314
+ }
4269
4315
  function reduce(arr, init, f) {
4270
4316
  return arr.reduce(f, init);
4271
4317
  }
@@ -4575,7 +4621,8 @@ var ToolNames = {
4575
4621
  searchFiles: "search_files",
4576
4622
  grep: "grep",
4577
4623
  fileExists: "file_exists",
4578
- loadAgentInstructions: "load_agent_instructions"};
4624
+ loadAgentInstructions: "load_agent_instructions",
4625
+ lighthouse: "lighthouse"};
4579
4626
 
4580
4627
  // ../frontman-core/src/tools/FrontmanCore__Tool__Grep.res.mjs
4581
4628
  var name2 = ToolNames.grep;
@@ -4870,66 +4917,665 @@ LIMITATIONS:
4870
4917
  - Results limited to max_results (default 20)
4871
4918
  - Binary files are automatically skipped
4872
4919
  - Hidden files (starting with '.') are skipped by default`;
4873
- var name3 = ToolNames.readFile;
4874
- var inputSchema2 = schema2((s2) => ({
4875
- path: s2.m(string2),
4876
- offset: s2.m(option2(int2)),
4877
- limit: s2.m(option2(int2))
4878
- }));
4879
- var pathContextSchema = schema2((s2) => ({
4880
- sourceRoot: s2.m(string2),
4881
- resolvedPath: s2.m(string2),
4882
- relativePath: s2.m(string2)
4883
- }));
4884
- var outputSchema2 = schema2((s2) => ({
4885
- content: s2.m(string2),
4886
- totalLines: s2.m(int2),
4887
- hasMore: s2.m(bool2),
4888
- _context: s2.m(option2(pathContextSchema))
4889
- }));
4890
- async function execute2(ctx2, input) {
4891
- let offset = getOr(input.offset, 0);
4892
- let limit = getOr(input.limit, 500);
4893
- let err = resolve2(ctx2.sourceRoot, input.path);
4894
- if (err.TAG !== "Ok") {
4895
- return {
4896
- TAG: "Error",
4897
- _0: formatError(err._0)
4898
- };
4899
- }
4900
- let result = err._0;
4901
- try {
4902
- let content = await Fs3.promises.readFile(result.resolvedPath, "utf8");
4903
- let lines = content.split("\n");
4904
- let totalLines = lines.length;
4905
- let selectedLines = lines.slice(offset, offset + limit | 0);
4906
- let selectedContent = selectedLines.join("\n");
4907
- let hasMore = (offset + limit | 0) < totalLines;
4920
+
4921
+ // ../frontman-core/src/FrontmanCore__FileTracker.res.mjs
4922
+ var readFiles = {
4923
+ contents: /* @__PURE__ */ new Set()
4924
+ };
4925
+ function recordRead(resolvedPath) {
4926
+ readFiles.contents.add(resolvedPath);
4927
+ }
4928
+ function assertReadBefore(resolvedPath) {
4929
+ if (readFiles.contents.has(resolvedPath)) {
4908
4930
  return {
4909
4931
  TAG: "Ok",
4910
- _0: {
4911
- content: selectedContent,
4912
- totalLines,
4913
- hasMore,
4914
- _context: {
4915
- sourceRoot: result.sourceRoot,
4916
- resolvedPath: result.resolvedPath,
4917
- relativePath: result.relativePath
4918
- }
4919
- }
4932
+ _0: void 0
4920
4933
  };
4921
- } catch (raw_exn) {
4922
- let exn = internalToException(raw_exn);
4923
- let msg = getOr(flatMap(fromException(exn), message2), "Unknown error");
4934
+ } else {
4924
4935
  return {
4925
4936
  TAG: "Error",
4926
- _0: `Failed to read file ` + input.path + `: ` + msg
4937
+ _0: `File must be read before editing. Use read_file on "` + resolvedPath + `" first to see its current content.`
4927
4938
  };
4928
4939
  }
4929
4940
  }
4930
- var description2 = `Reads a file from the filesystem.
4931
4941
 
4932
- Parameters:
4942
+ // ../../node_modules/@rescript/runtime/lib/es6/Stdlib_String.js
4943
+ function indexOfOpt(s2, search) {
4944
+ let index = s2.indexOf(search);
4945
+ if (index !== -1) {
4946
+ return index;
4947
+ }
4948
+ }
4949
+
4950
+ // ../frontman-core/src/tools/FrontmanCore__Tool__EditFile__Matcher.res.mjs
4951
+ function levenshtein(a, b) {
4952
+ let match = a.length;
4953
+ let match$1 = b.length;
4954
+ if (match === 0) {
4955
+ return b.length;
4956
+ }
4957
+ if (match$1 === 0) {
4958
+ return a.length;
4959
+ }
4960
+ let matrix = fromInitializer(match + 1 | 0, (i) => fromInitializer(match$1 + 1 | 0, (j2) => {
4961
+ if (i !== 0) {
4962
+ if (j2 !== 0) {
4963
+ return 0;
4964
+ } else {
4965
+ return i;
4966
+ }
4967
+ } else {
4968
+ return j2;
4969
+ }
4970
+ }));
4971
+ for (let i = 1; i <= match; ++i) {
4972
+ for (let j2 = 1; j2 <= match$1; ++j2) {
4973
+ let cost = a.charAt(i - 1 | 0) === b.charAt(j2 - 1 | 0) ? 0 : 1;
4974
+ let del = getOrThrow(matrix[i - 1 | 0])[j2] + 1 | 0;
4975
+ let ins = getOrThrow(matrix[i])[j2 - 1 | 0] + 1 | 0;
4976
+ let sub = getOrThrow(matrix[i - 1 | 0])[j2 - 1 | 0] + cost | 0;
4977
+ getOrThrow(matrix[i])[j2] = min(del, min(ins, sub));
4978
+ }
4979
+ }
4980
+ return getOrThrow(matrix[match])[match$1];
4981
+ }
4982
+ function lineOffset(lines, lineIndex) {
4983
+ let offset = 0;
4984
+ for (let k2 = 0; k2 < lineIndex; ++k2) {
4985
+ offset = (offset + getOrThrow(lines[k2]).length | 0) + 1 | 0;
4986
+ }
4987
+ return offset;
4988
+ }
4989
+ function extractBlock(content, lines, startLine, endLine) {
4990
+ let startIdx = lineOffset(lines, startLine);
4991
+ let endIdx = lineOffset(lines, endLine) + getOrThrow(lines[endLine]).length | 0;
4992
+ return content.slice(startIdx, endIdx);
4993
+ }
4994
+ function escapeRegex(str) {
4995
+ return str.replace(/[.*+?^${}()|[\\]\\\\]/g, "\\$&");
4996
+ }
4997
+ function exactMatch(content, find) {
4998
+ if (content.includes(find)) {
4999
+ return [find];
5000
+ } else {
5001
+ return [];
5002
+ }
5003
+ }
5004
+ function lineTrimMatch(content, find) {
5005
+ let contentLines = content.split("\n");
5006
+ let searchLines = find.split("\n");
5007
+ let last = searchLines[searchLines.length - 1 | 0];
5008
+ let searchLines$1 = last === "" ? searchLines.slice(0, searchLines.length - 1 | 0) : searchLines;
5009
+ let searchLen = searchLines$1.length;
5010
+ let results = [];
5011
+ for (let i = 0, i_finish = contentLines.length - searchLen | 0; i <= i_finish; ++i) {
5012
+ let matches2 = true;
5013
+ let j2 = 0;
5014
+ while (j2 < searchLen && matches2) {
5015
+ let origTrimmed = getOrThrow(contentLines[i + j2 | 0]).trim();
5016
+ let searchTrimmed = getOrThrow(searchLines$1[j2]).trim();
5017
+ if (origTrimmed === searchTrimmed) {
5018
+ j2 = j2 + 1 | 0;
5019
+ } else {
5020
+ matches2 = false;
5021
+ }
5022
+ }
5023
+ if (matches2) {
5024
+ results.push(extractBlock(content, contentLines, i, (i + searchLen | 0) - 1 | 0));
5025
+ }
5026
+ }
5027
+ return results;
5028
+ }
5029
+ function anchoredBlockMatch(content, find) {
5030
+ let contentLines = content.split("\n");
5031
+ let searchLines = find.split("\n");
5032
+ let last = searchLines[searchLines.length - 1 | 0];
5033
+ let searchLines$1 = last === "" ? searchLines.slice(0, searchLines.length - 1 | 0) : searchLines;
5034
+ if (searchLines$1.length < 3) {
5035
+ return [];
5036
+ }
5037
+ let firstLineSearch = getOrThrow(searchLines$1[0]).trim();
5038
+ let lastLineSearch = getOrThrow(searchLines$1[searchLines$1.length - 1 | 0]).trim();
5039
+ let searchBlockSize = searchLines$1.length;
5040
+ let candidates = [];
5041
+ for (let i = 0, i_finish = contentLines.length; i < i_finish; ++i) {
5042
+ if (getOrThrow(contentLines[i]).trim() === firstLineSearch) {
5043
+ let j2 = i + 2 | 0;
5044
+ while (j2 < contentLines.length) {
5045
+ if (getOrThrow(contentLines[j2]).trim() === lastLineSearch) {
5046
+ candidates.push({
5047
+ startLine: i,
5048
+ endLine: j2
5049
+ });
5050
+ j2 = j2 + 1 | 0;
5051
+ } else {
5052
+ j2 = j2 + 1 | 0;
5053
+ }
5054
+ }
5055
+ }
5056
+ }
5057
+ let match = candidates.length;
5058
+ if (match === 0) {
5059
+ return [];
5060
+ }
5061
+ if (match !== 1) {
5062
+ let bestMatch = {
5063
+ contents: void 0
5064
+ };
5065
+ let maxSim = {
5066
+ contents: -1
5067
+ };
5068
+ candidates.forEach((cand) => {
5069
+ let startLine2 = cand.startLine;
5070
+ let actualBlockSize2 = (cand.endLine - startLine2 | 0) + 1 | 0;
5071
+ let linesToCheck2 = min(searchBlockSize - 2 | 0, actualBlockSize2 - 2 | 0);
5072
+ let similarity2;
5073
+ if (linesToCheck2 > 0) {
5074
+ let sim = 0;
5075
+ for (let j2 = 1, j_finish = min(searchBlockSize - 2 | 0, actualBlockSize2 - 2 | 0); j2 <= j_finish; ++j2) {
5076
+ let origLine = getOrThrow(contentLines[startLine2 + j2 | 0]).trim();
5077
+ let searchLine = getOrThrow(searchLines$1[j2]).trim();
5078
+ let maxLen = max(origLine.length, searchLine.length);
5079
+ if (maxLen > 0) {
5080
+ let distance = levenshtein(origLine, searchLine);
5081
+ sim = sim + (1 - distance / maxLen);
5082
+ }
5083
+ }
5084
+ similarity2 = sim / linesToCheck2;
5085
+ } else {
5086
+ similarity2 = 1;
5087
+ }
5088
+ if (similarity2 > maxSim.contents) {
5089
+ maxSim.contents = similarity2;
5090
+ bestMatch.contents = cand;
5091
+ return;
5092
+ }
5093
+ });
5094
+ let match$1 = maxSim.contents >= 0.3;
5095
+ let match$2 = bestMatch.contents;
5096
+ if (match$1) {
5097
+ if (match$2 !== void 0) {
5098
+ return [extractBlock(content, contentLines, match$2.startLine, match$2.endLine)];
5099
+ } else {
5100
+ return [];
5101
+ }
5102
+ } else {
5103
+ return [];
5104
+ }
5105
+ }
5106
+ let match$3 = getOrThrow(candidates[0]);
5107
+ let endLine = match$3.endLine;
5108
+ let startLine = match$3.startLine;
5109
+ let actualBlockSize = (endLine - startLine | 0) + 1 | 0;
5110
+ let linesToCheck = min(searchBlockSize - 2 | 0, actualBlockSize - 2 | 0);
5111
+ let similarity;
5112
+ if (linesToCheck > 0) {
5113
+ let sim = 0;
5114
+ let j$1 = 1;
5115
+ while (j$1 < (searchBlockSize - 1 | 0) && j$1 < (actualBlockSize - 1 | 0)) {
5116
+ let origLine = getOrThrow(contentLines[startLine + j$1 | 0]).trim();
5117
+ let searchLine = getOrThrow(searchLines$1[j$1]).trim();
5118
+ let maxLen = max(origLine.length, searchLine.length);
5119
+ if (maxLen > 0) {
5120
+ let distance = levenshtein(origLine, searchLine);
5121
+ sim = sim + (1 - distance / maxLen) / linesToCheck;
5122
+ }
5123
+ j$1 = sim >= 0 ? searchBlockSize : j$1 + 1 | 0;
5124
+ }
5125
+ similarity = sim;
5126
+ } else {
5127
+ similarity = 1;
5128
+ }
5129
+ if (similarity >= 0) {
5130
+ return [extractBlock(content, contentLines, startLine, endLine)];
5131
+ } else {
5132
+ return [];
5133
+ }
5134
+ }
5135
+ function normalizedWhitespaceMatch(content, find) {
5136
+ let normalize3 = (text) => text.replace(/\s+/g, " ").trim();
5137
+ let normalizedFind = normalize3(find);
5138
+ let contentLines = content.split("\n");
5139
+ let results = [];
5140
+ contentLines.forEach((line) => {
5141
+ if (normalize3(line) === normalizedFind) {
5142
+ results.push(line);
5143
+ return;
5144
+ }
5145
+ let normalizedLine = normalize3(line);
5146
+ if (!normalizedLine.includes(normalizedFind)) {
5147
+ return;
5148
+ }
5149
+ let words = filterMap(find.trim().split(/\s+/), (x) => x);
5150
+ if (words.length === 0) {
5151
+ return;
5152
+ }
5153
+ let pattern2 = words.map(escapeRegex).join("\\s+");
5154
+ try {
5155
+ let regex = new RegExp(pattern2);
5156
+ let result = line.match(regex);
5157
+ if (result == null) {
5158
+ return;
5159
+ }
5160
+ let m = result[0];
5161
+ if (m.length > 0) {
5162
+ results.push(m);
5163
+ return;
5164
+ } else {
5165
+ return;
5166
+ }
5167
+ } catch (exn) {
5168
+ return;
5169
+ }
5170
+ });
5171
+ let findLines = find.split("\n");
5172
+ if (findLines.length > 1) {
5173
+ for (let i = 0, i_finish = contentLines.length - findLines.length | 0; i <= i_finish; ++i) {
5174
+ let block = contentLines.slice(i, i + findLines.length | 0).join("\n");
5175
+ if (normalize3(block) === normalizedFind) {
5176
+ results.push(block);
5177
+ }
5178
+ }
5179
+ }
5180
+ return results;
5181
+ }
5182
+ function flexibleIndentMatch(content, find) {
5183
+ let removeIndent = (text) => {
5184
+ let lines = text.split("\n");
5185
+ let nonEmptyLines = lines.filter((line) => line.trim().length > 0);
5186
+ let match = nonEmptyLines.length;
5187
+ if (match === 0) {
5188
+ return text;
5189
+ }
5190
+ let minIndent = reduce(nonEmptyLines, 999999, (acc, line) => {
5191
+ let m = line.match(/^(\s*)/);
5192
+ let indent = !(m == null) ? m[0].length : 0;
5193
+ return min(acc, indent);
5194
+ });
5195
+ return lines.map((line) => {
5196
+ let match2 = line.trim().length;
5197
+ if (match2 !== 0) {
5198
+ return line.slice(minIndent, line.length);
5199
+ } else {
5200
+ return line;
5201
+ }
5202
+ }).join("\n");
5203
+ };
5204
+ let normalizedFind = removeIndent(find);
5205
+ let contentLines = content.split("\n");
5206
+ let findLines = find.split("\n");
5207
+ let results = [];
5208
+ for (let i = 0, i_finish = contentLines.length - findLines.length | 0; i <= i_finish; ++i) {
5209
+ let block = contentLines.slice(i, i + findLines.length | 0).join("\n");
5210
+ if (removeIndent(block) === normalizedFind) {
5211
+ results.push(block);
5212
+ }
5213
+ }
5214
+ return results;
5215
+ }
5216
+ function escapeNormalizedMatch(content, find) {
5217
+ let unescape = (function(str) {
5218
+ return str.replace(/\\([ntr'"\\/$])/g, function(_m, c2) {
5219
+ if (c2 === "n") return String.fromCharCode(10);
5220
+ if (c2 === "t") return String.fromCharCode(9);
5221
+ if (c2 === "r") return String.fromCharCode(13);
5222
+ return c2;
5223
+ });
5224
+ });
5225
+ let unescapedFind = unescape(find);
5226
+ let results = [];
5227
+ if (content.includes(unescapedFind)) {
5228
+ results.push(unescapedFind);
5229
+ }
5230
+ let contentLines = content.split("\n");
5231
+ let findLines = unescapedFind.split("\n");
5232
+ for (let i = 0, i_finish = contentLines.length - findLines.length | 0; i <= i_finish; ++i) {
5233
+ let block = contentLines.slice(i, i + findLines.length | 0).join("\n");
5234
+ let unescapedBlock = unescape(block);
5235
+ if (unescapedBlock === unescapedFind && !results.includes(block)) {
5236
+ results.push(block);
5237
+ }
5238
+ }
5239
+ return results;
5240
+ }
5241
+ function trimmedBoundaryMatch(content, find) {
5242
+ let trimmedFind = find.trim();
5243
+ if (trimmedFind === find) {
5244
+ return [];
5245
+ }
5246
+ let results = [];
5247
+ if (content.includes(trimmedFind)) {
5248
+ results.push(trimmedFind);
5249
+ }
5250
+ let contentLines = content.split("\n");
5251
+ let findLines = find.split("\n");
5252
+ for (let i = 0, i_finish = contentLines.length - findLines.length | 0; i <= i_finish; ++i) {
5253
+ let block = contentLines.slice(i, i + findLines.length | 0).join("\n");
5254
+ if (block.trim() === trimmedFind && !results.includes(block)) {
5255
+ results.push(block);
5256
+ }
5257
+ }
5258
+ return results;
5259
+ }
5260
+ function contextAnchorMatch(content, find) {
5261
+ let findLines = find.split("\n");
5262
+ let last = findLines[findLines.length - 1 | 0];
5263
+ let findLines$1 = last === "" ? findLines.slice(0, findLines.length - 1 | 0) : findLines;
5264
+ if (findLines$1.length < 3) {
5265
+ return [];
5266
+ }
5267
+ let contentLines = content.split("\n");
5268
+ let firstLine = getOrThrow(findLines$1[0]).trim();
5269
+ let lastLine = getOrThrow(findLines$1[findLines$1.length - 1 | 0]).trim();
5270
+ let results = [];
5271
+ for (let i = 0, i_finish = contentLines.length; i < i_finish; ++i) {
5272
+ if (getOrThrow(contentLines[i]).trim() === firstLine) {
5273
+ let j2 = i + 2 | 0;
5274
+ while (j2 < contentLines.length) {
5275
+ if (getOrThrow(contentLines[j2]).trim() === lastLine) {
5276
+ let blockLines = contentLines.slice(i, j2 + 1 | 0);
5277
+ if (blockLines.length === findLines$1.length) {
5278
+ let matchingLines = 0;
5279
+ let totalNonEmpty = 0;
5280
+ for (let k2 = 1, k_finish = blockLines.length - 2 | 0; k2 <= k_finish; ++k2) {
5281
+ let blockLine = getOrThrow(blockLines[k2]).trim();
5282
+ let findLine = getOrThrow(findLines$1[k2]).trim();
5283
+ let match = blockLine.length > 0;
5284
+ let match$1 = findLine.length > 0;
5285
+ let exit = 0;
5286
+ if (match || match$1) {
5287
+ exit = 1;
5288
+ }
5289
+ if (exit === 1) {
5290
+ totalNonEmpty = totalNonEmpty + 1 | 0;
5291
+ if (blockLine === findLine) {
5292
+ matchingLines = matchingLines + 1 | 0;
5293
+ }
5294
+ }
5295
+ }
5296
+ let total = totalNonEmpty;
5297
+ let passes = total !== 0 ? matchingLines / total >= 0.5 : true;
5298
+ if (passes) {
5299
+ results.push(extractBlock(content, contentLines, i, j2));
5300
+ }
5301
+ }
5302
+ j2 = j2 + 1 | 0;
5303
+ } else {
5304
+ j2 = j2 + 1 | 0;
5305
+ }
5306
+ }
5307
+ }
5308
+ }
5309
+ return results;
5310
+ }
5311
+ function multiOccurrenceMatch(content, find) {
5312
+ let results = [];
5313
+ let startIndex = {
5314
+ contents: 0
5315
+ };
5316
+ let continue_ = true;
5317
+ while (continue_) {
5318
+ let searchContent = content.slice(startIndex.contents, content.length);
5319
+ let idx = map(indexOfOpt(searchContent, find), (i) => i + startIndex.contents | 0);
5320
+ if (idx !== void 0) {
5321
+ results.push(find);
5322
+ startIndex.contents = idx + find.length | 0;
5323
+ } else {
5324
+ continue_ = false;
5325
+ }
5326
+ }
5327
+ return results;
5328
+ }
5329
+ var strategies = [
5330
+ exactMatch,
5331
+ lineTrimMatch,
5332
+ anchoredBlockMatch,
5333
+ normalizedWhitespaceMatch,
5334
+ flexibleIndentMatch,
5335
+ escapeNormalizedMatch,
5336
+ trimmedBoundaryMatch,
5337
+ contextAnchorMatch,
5338
+ multiOccurrenceMatch
5339
+ ];
5340
+ function applyEdit(content, oldText, newText, replaceAllOpt) {
5341
+ let replaceAll = replaceAllOpt !== void 0 ? replaceAllOpt : false;
5342
+ let notFound = {
5343
+ contents: true
5344
+ };
5345
+ let result = {
5346
+ contents: void 0
5347
+ };
5348
+ let strategyIdx = 0;
5349
+ while (isNone(result.contents) && strategyIdx < strategies.length) {
5350
+ let strategy = getOrThrow(strategies[strategyIdx]);
5351
+ let candidates = strategy(content, oldText);
5352
+ let match = !replaceAll && candidates.length > 1;
5353
+ if (match) {
5354
+ notFound.contents = false;
5355
+ } else if (replaceAll) {
5356
+ candidates.forEach((candidate) => {
5357
+ let match2 = result.contents;
5358
+ if (match2 !== void 0) {
5359
+ return;
5360
+ }
5361
+ let idx = content.indexOf(candidate);
5362
+ if (idx >= 0) {
5363
+ notFound.contents = false;
5364
+ result.contents = {
5365
+ TAG: "Applied",
5366
+ _0: content.split(candidate).join(newText)
5367
+ };
5368
+ return;
5369
+ }
5370
+ });
5371
+ } else {
5372
+ let candidate = candidates[0];
5373
+ if (candidate !== void 0) {
5374
+ let idx = content.indexOf(candidate);
5375
+ if (idx >= 0) {
5376
+ notFound.contents = false;
5377
+ let lastIdx = content.lastIndexOf(candidate);
5378
+ if (idx === lastIdx) {
5379
+ let before = content.slice(0, idx);
5380
+ let after = content.slice(idx + candidate.length | 0, content.length);
5381
+ result.contents = {
5382
+ TAG: "Applied",
5383
+ _0: before + newText + after
5384
+ };
5385
+ }
5386
+ }
5387
+ }
5388
+ }
5389
+ strategyIdx = strategyIdx + 1 | 0;
5390
+ }
5391
+ let r = result.contents;
5392
+ if (r !== void 0) {
5393
+ return r;
5394
+ } else if (notFound.contents) {
5395
+ return "NotFound";
5396
+ } else {
5397
+ return "Ambiguous";
5398
+ }
5399
+ }
5400
+
5401
+ // ../frontman-core/src/tools/FrontmanCore__Tool__EditFile.res.mjs
5402
+ var inputSchema2 = schema2((s2) => ({
5403
+ path: s2.m(string2),
5404
+ oldText: s2.m(string2),
5405
+ newText: s2.m(string2),
5406
+ replaceAll: s2.m(option2(bool2))
5407
+ }));
5408
+ var pathContextSchema = schema2((s2) => ({
5409
+ sourceRoot: s2.m(string2),
5410
+ resolvedPath: s2.m(string2),
5411
+ relativePath: s2.m(string2)
5412
+ }));
5413
+ var outputSchema2 = schema2((s2) => ({
5414
+ message: s2.m(string2),
5415
+ _context: s2.m(option2(pathContextSchema))
5416
+ }));
5417
+ async function execute2(ctx2, input) {
5418
+ let replaceAll = getOr(input.replaceAll, false);
5419
+ if (input.oldText === input.newText) {
5420
+ return {
5421
+ TAG: "Error",
5422
+ _0: "oldText and newText must be different"
5423
+ };
5424
+ }
5425
+ let err = resolve2(ctx2.sourceRoot, input.path);
5426
+ if (err.TAG !== "Ok") {
5427
+ return {
5428
+ TAG: "Error",
5429
+ _0: formatError(err._0)
5430
+ };
5431
+ }
5432
+ let result = err._0;
5433
+ let pathCtx_sourceRoot = result.sourceRoot;
5434
+ let pathCtx_resolvedPath = result.resolvedPath;
5435
+ let pathCtx_relativePath = result.relativePath;
5436
+ let pathCtx = {
5437
+ sourceRoot: pathCtx_sourceRoot,
5438
+ resolvedPath: pathCtx_resolvedPath,
5439
+ relativePath: pathCtx_relativePath
5440
+ };
5441
+ if (input.oldText === "") {
5442
+ try {
5443
+ let dirPath = dirname3(result);
5444
+ await Fs.promises.mkdir(dirPath, {
5445
+ recursive: true
5446
+ });
5447
+ await Fs.promises.writeFile(result.resolvedPath, input.newText, "utf8");
5448
+ return {
5449
+ TAG: "Ok",
5450
+ _0: {
5451
+ message: "File created successfully.",
5452
+ _context: pathCtx
5453
+ }
5454
+ };
5455
+ } catch (raw_exn) {
5456
+ let exn = internalToException(raw_exn);
5457
+ let msg = getOr(flatMap(fromException(exn), message2), "Unknown error");
5458
+ return {
5459
+ TAG: "Error",
5460
+ _0: `Failed to create file ` + input.path + `: ` + msg
5461
+ };
5462
+ }
5463
+ } else {
5464
+ let msg$1 = assertReadBefore(result.resolvedPath);
5465
+ if (msg$1.TAG !== "Ok") {
5466
+ return {
5467
+ TAG: "Error",
5468
+ _0: msg$1._0
5469
+ };
5470
+ }
5471
+ try {
5472
+ let content = await Fs.promises.readFile(result.resolvedPath, "utf8");
5473
+ let newContent = applyEdit(content, input.oldText, input.newText, replaceAll);
5474
+ if (typeof newContent !== "object") {
5475
+ if (newContent === "NotFound") {
5476
+ return {
5477
+ TAG: "Error",
5478
+ _0: `oldText not found in file ` + input.path + `. Make sure the text matches exactly, or read the file again to see its current content.`
5479
+ };
5480
+ } else {
5481
+ return {
5482
+ TAG: "Error",
5483
+ _0: `Found multiple matches for oldText in ` + input.path + `. Provide more surrounding context to identify the correct match, or use replaceAll to replace all occurrences.`
5484
+ };
5485
+ }
5486
+ }
5487
+ await Fs.promises.writeFile(result.resolvedPath, newContent._0, "utf8");
5488
+ return {
5489
+ TAG: "Ok",
5490
+ _0: {
5491
+ message: "Edit applied successfully.",
5492
+ _context: pathCtx
5493
+ }
5494
+ };
5495
+ } catch (raw_exn$1) {
5496
+ let exn$1 = internalToException(raw_exn$1);
5497
+ let msg$2 = getOr(flatMap(fromException(exn$1), message2), "Unknown error");
5498
+ return {
5499
+ TAG: "Error",
5500
+ _0: `Failed to edit file ` + input.path + `: ` + msg$2
5501
+ };
5502
+ }
5503
+ }
5504
+ }
5505
+ var name3 = "edit_file";
5506
+ var description2 = `Edits a file by replacing text using fuzzy matching.
5507
+
5508
+ Parameters:
5509
+ - path (required): Path to file - either relative to source root or absolute (must be under source root)
5510
+ - oldText (required): The text to find and replace. An empty oldText creates a new file with newText as content.
5511
+ - newText (required): The replacement text (must differ from oldText)
5512
+ - replaceAll (optional): If true, replaces all occurrences. Default: false.
5513
+
5514
+ The tool uses multiple matching strategies (exact, line-trimmed, whitespace-normalized,
5515
+ indentation-flexible, etc.) to handle common formatting differences.
5516
+
5517
+ IMPORTANT: You must read_file before editing. The tool will reject edits on unread files.`;
5518
+ var name4 = ToolNames.readFile;
5519
+ var inputSchema3 = schema2((s2) => ({
5520
+ path: s2.m(string2),
5521
+ offset: s2.m(option2(int2)),
5522
+ limit: s2.m(option2(int2))
5523
+ }));
5524
+ var pathContextSchema2 = schema2((s2) => ({
5525
+ sourceRoot: s2.m(string2),
5526
+ resolvedPath: s2.m(string2),
5527
+ relativePath: s2.m(string2)
5528
+ }));
5529
+ var outputSchema3 = schema2((s2) => ({
5530
+ content: s2.m(string2),
5531
+ totalLines: s2.m(int2),
5532
+ hasMore: s2.m(bool2),
5533
+ _context: s2.m(option2(pathContextSchema2))
5534
+ }));
5535
+ async function execute3(ctx2, input) {
5536
+ let offset = getOr(input.offset, 0);
5537
+ let limit = getOr(input.limit, 500);
5538
+ let err = resolve2(ctx2.sourceRoot, input.path);
5539
+ if (err.TAG !== "Ok") {
5540
+ return {
5541
+ TAG: "Error",
5542
+ _0: formatError(err._0)
5543
+ };
5544
+ }
5545
+ let result = err._0;
5546
+ try {
5547
+ let content = await Fs.promises.readFile(result.resolvedPath, "utf8");
5548
+ let lines = content.split("\n");
5549
+ let totalLines = lines.length;
5550
+ let selectedLines = lines.slice(offset, offset + limit | 0);
5551
+ let selectedContent = selectedLines.join("\n");
5552
+ let hasMore = (offset + limit | 0) < totalLines;
5553
+ recordRead(result.resolvedPath);
5554
+ return {
5555
+ TAG: "Ok",
5556
+ _0: {
5557
+ content: selectedContent,
5558
+ totalLines,
5559
+ hasMore,
5560
+ _context: {
5561
+ sourceRoot: result.sourceRoot,
5562
+ resolvedPath: result.resolvedPath,
5563
+ relativePath: result.relativePath
5564
+ }
5565
+ }
5566
+ };
5567
+ } catch (raw_exn) {
5568
+ let exn = internalToException(raw_exn);
5569
+ let msg = getOr(flatMap(fromException(exn), message2), "Unknown error");
5570
+ return {
5571
+ TAG: "Error",
5572
+ _0: `Failed to read file ` + input.path + `: ` + msg
5573
+ };
5574
+ }
5575
+ }
5576
+ var description3 = `Reads a file from the filesystem.
5577
+
5578
+ Parameters:
4933
5579
  - path (required): Path to file - either relative to source root or absolute (must be under source root)
4934
5580
  - offset (optional): Line number to start from (0-indexed, default: 0). Pass null or 0 to start from beginning.
4935
5581
  - limit (optional): Maximum lines to read (default: 500). Pass null or 500 for default.
@@ -4950,8 +5596,8 @@ function map3(opt, f) {
4950
5596
  }
4951
5597
 
4952
5598
  // ../frontman-core/src/tools/FrontmanCore__Tool__ListFiles.res.mjs
4953
- var name4 = ToolNames.listFiles;
4954
- var inputSchema3 = schema2((s2) => ({
5599
+ var name5 = ToolNames.listFiles;
5600
+ var inputSchema4 = schema2((s2) => ({
4955
5601
  path: s2.m(option2(string2))
4956
5602
  }));
4957
5603
  var fileEntrySchema = schema2((s2) => ({
@@ -4960,7 +5606,7 @@ var fileEntrySchema = schema2((s2) => ({
4960
5606
  isFile: s2.m(bool2),
4961
5607
  isDirectory: s2.m(bool2)
4962
5608
  }));
4963
- var outputSchema3 = array2(fileEntrySchema);
5609
+ var outputSchema4 = array2(fileEntrySchema);
4964
5610
  async function getIgnoredEntries(cwd, entries) {
4965
5611
  if (entries.length === 0) {
4966
5612
  return {
@@ -5015,7 +5661,7 @@ async function getIgnoredEntries(cwd, entries) {
5015
5661
  };
5016
5662
  }
5017
5663
  }
5018
- async function execute3(ctx2, input) {
5664
+ async function execute4(ctx2, input) {
5019
5665
  let path = getOr(input.path, ".");
5020
5666
  let err = resolve2(ctx2.sourceRoot, path);
5021
5667
  if (err.TAG !== "Ok") {
@@ -5026,20 +5672,20 @@ async function execute3(ctx2, input) {
5026
5672
  }
5027
5673
  try {
5028
5674
  let fullPath = err._0.resolvedPath;
5029
- let entries = await Fs3.promises.readdir(fullPath);
5030
- let filteredEntriesResult = map3(await getIgnoredEntries(fullPath, entries), (ignored) => entries.filter((name11) => !ignored.includes(name11)));
5675
+ let entries = await Fs.promises.readdir(fullPath);
5676
+ let filteredEntriesResult = map3(await getIgnoredEntries(fullPath, entries), (ignored) => entries.filter((name14) => !ignored.includes(name14)));
5031
5677
  if (filteredEntriesResult.TAG !== "Ok") {
5032
5678
  return {
5033
5679
  TAG: "Error",
5034
5680
  _0: filteredEntriesResult._0
5035
5681
  };
5036
5682
  }
5037
- let entriesWithStats = await Promise.all(filteredEntriesResult._0.map(async (name11) => {
5038
- let entryPath = Nodepath.join(fullPath, name11);
5039
- let stats = await Fs3.promises.stat(entryPath);
5683
+ let entriesWithStats = await Promise.all(filteredEntriesResult._0.map(async (name14) => {
5684
+ let entryPath = Nodepath.join(fullPath, name14);
5685
+ let stats = await Fs.promises.stat(entryPath);
5040
5686
  return {
5041
- name: name11,
5042
- path: Nodepath.join(path, name11),
5687
+ name: name14,
5688
+ path: Nodepath.join(path, name14),
5043
5689
  isFile: stats.isFile(),
5044
5690
  isDirectory: stats.isDirectory()
5045
5691
  };
@@ -5057,35 +5703,35 @@ async function execute3(ctx2, input) {
5057
5703
  };
5058
5704
  }
5059
5705
  }
5060
- var description3 = `Lists files and directories in a given path.
5706
+ var description4 = `Lists files and directories in a given path.
5061
5707
 
5062
5708
  Parameters:
5063
5709
  - path (optional): Path to directory - either relative to source root or absolute (must be under source root). Defaults to "." (root directory).
5064
5710
 
5065
5711
  Returns array of entries with name, path, and type information.`;
5066
- var name5 = ToolNames.writeFile;
5067
- var inputSchema4 = schema2((s2) => ({
5712
+ var name6 = ToolNames.writeFile;
5713
+ var inputSchema5 = schema2((s2) => ({
5068
5714
  path: s2.m(string2),
5069
5715
  content: s2.m(option2(string2)),
5070
5716
  image_ref: s2.m(option2(string2)),
5071
5717
  encoding: s2.m(option2(literal2("base64")))
5072
5718
  }));
5073
- var pathContextSchema2 = schema2((s2) => ({
5719
+ var pathContextSchema3 = schema2((s2) => ({
5074
5720
  sourceRoot: s2.m(string2),
5075
5721
  resolvedPath: s2.m(string2),
5076
5722
  relativePath: s2.m(string2)
5077
5723
  }));
5078
- var outputSchema4 = schema2((s2) => ({
5079
- _context: s2.m(option2(pathContextSchema2))
5724
+ var outputSchema5 = schema2((s2) => ({
5725
+ _context: s2.m(option2(pathContextSchema3))
5080
5726
  }));
5081
5727
  function writeContent(resolvedPath, content, encoding) {
5082
5728
  if (encoding === void 0) {
5083
- return Fs3.promises.writeFile(resolvedPath, content, "utf8");
5729
+ return Fs.promises.writeFile(resolvedPath, content, "utf8");
5084
5730
  }
5085
5731
  let buffer = Nodebuffer.Buffer.from(content, "base64");
5086
- return Fs3.promises.writeFile(resolvedPath, buffer);
5732
+ return Fs.promises.writeFile(resolvedPath, buffer);
5087
5733
  }
5088
- async function execute4(ctx2, input) {
5734
+ async function execute5(ctx2, input) {
5089
5735
  let match = input.content;
5090
5736
  let match$1 = input.image_ref;
5091
5737
  if (match === void 0) {
@@ -5116,7 +5762,7 @@ async function execute4(ctx2, input) {
5116
5762
  }
5117
5763
  let result = err._0;
5118
5764
  try {
5119
- await Fs3.promises.mkdir(dirname3(result), {
5765
+ await Fs.promises.mkdir(dirname3(result), {
5120
5766
  recursive: true
5121
5767
  });
5122
5768
  await writeContent(result.resolvedPath, match, input.encoding);
@@ -5139,7 +5785,7 @@ async function execute4(ctx2, input) {
5139
5785
  };
5140
5786
  }
5141
5787
  }
5142
- var description4 = `Writes content to a file.
5788
+ var description5 = `Writes content to a file.
5143
5789
 
5144
5790
  Parameters:
5145
5791
  - path (required): Path to file - either relative to source root or absolute (must be under source root)
@@ -5150,11 +5796,11 @@ Parameters:
5150
5796
  Provide either content OR image_ref, not both.
5151
5797
  Creates parent directories if they don't exist. Overwrites existing files.
5152
5798
  The _context field provides path resolution details for debugging.`;
5153
- var name6 = ToolNames.fileExists;
5154
- var inputSchema5 = schema2((s2) => ({
5799
+ var name7 = ToolNames.fileExists;
5800
+ var inputSchema6 = schema2((s2) => ({
5155
5801
  path: s2.m(string2)
5156
5802
  }));
5157
- async function execute5(ctx2, input) {
5803
+ async function execute6(ctx2, input) {
5158
5804
  let msg = resolve(ctx2.sourceRoot, input.path);
5159
5805
  if (msg.TAG !== "Ok") {
5160
5806
  return {
@@ -5163,7 +5809,7 @@ async function execute5(ctx2, input) {
5163
5809
  };
5164
5810
  }
5165
5811
  try {
5166
- await Fs3.promises.access(toString(msg._0));
5812
+ await Fs.promises.access(toString(msg._0));
5167
5813
  return {
5168
5814
  TAG: "Ok",
5169
5815
  _0: true
@@ -5175,13 +5821,13 @@ async function execute5(ctx2, input) {
5175
5821
  };
5176
5822
  }
5177
5823
  }
5178
- var description5 = `Checks if a file or directory exists.
5824
+ var description6 = `Checks if a file or directory exists.
5179
5825
 
5180
5826
  Parameters:
5181
5827
  - path (required): Path to check - either relative to source root or absolute (must be under source root)
5182
5828
 
5183
5829
  Returns true if the path exists, false otherwise.`;
5184
- var outputSchema5 = bool2;
5830
+ var outputSchema6 = bool2;
5185
5831
 
5186
5832
  // ../bindings/src/Lighthouse.res.mjs
5187
5833
  var run = ((url2, flags2) => import('module').then(({ createRequire }) => {
@@ -5211,41 +5857,20 @@ var launch = ((options) => import('module').then(({ createRequire }) => {
5211
5857
  throw e;
5212
5858
  }
5213
5859
  }));
5214
-
5215
- // ../frontman-core/src/tools/FrontmanCore__Tool__Lighthouse.res.mjs
5216
- var rewriteUrlForRuntime = ((url2) => {
5217
- const override = process.env.FRONTMAN_LIGHTHOUSE_DEVPOD_LOCALHOST;
5218
- const worktreeId = process.env.WORKTREE_ID;
5219
- const overrideLower = typeof override === "string" ? override.toLowerCase() : "";
5220
- const devpodMode = overrideLower === "1" || overrideLower === "true" || overrideLower === "yes" || overrideLower === "on" || typeof worktreeId === "string";
5221
- if (!devpodMode) {
5222
- return url2;
5223
- }
5224
- let parsed;
5860
+ async function killSafely(chrome) {
5225
5861
  try {
5226
- parsed = new URL(url2);
5227
- } catch {
5228
- return url2;
5229
- }
5230
- const host2 = parsed.hostname;
5231
- const mapToLocalhost = (port2, protocol) => {
5232
- parsed.protocol = protocol;
5233
- parsed.hostname = "127.0.0.1";
5234
- parsed.port = String(port2);
5235
- return parsed.toString();
5236
- };
5237
- if (host2.endsWith(".nextjs.frontman.local")) {
5238
- return mapToLocalhost(3e3, "http:");
5239
- }
5240
- if (host2.endsWith(".vite.frontman.local")) {
5241
- return mapToLocalhost(5173, "http:");
5242
- }
5243
- if (host2.endsWith(".api.frontman.local")) {
5244
- return mapToLocalhost(4e3, "https:");
5862
+ return await chrome.kill();
5863
+ } catch (raw_exn) {
5864
+ let exn = internalToException(raw_exn);
5865
+ let msg = getOr(flatMap(fromException(exn), message2), "Unknown error");
5866
+ console.error(`[chrome-launcher] Failed to kill Chrome (pid ` + chrome.pid.toString() + `): ` + msg);
5867
+ return;
5245
5868
  }
5246
- return url2;
5247
- });
5248
- var inputSchema6 = schema2((s2) => ({
5869
+ }
5870
+
5871
+ // ../frontman-core/src/tools/FrontmanCore__Tool__Lighthouse.res.mjs
5872
+ var name8 = ToolNames.lighthouse;
5873
+ var inputSchema7 = schema2((s2) => ({
5249
5874
  url: s2.m(string2),
5250
5875
  preset: s2.m(option2(string2))
5251
5876
  }));
@@ -5262,7 +5887,7 @@ var categoryResultSchema = schema2((s2) => ({
5262
5887
  score: s2.m(int2),
5263
5888
  topIssues: s2.m(array2(auditIssueSchema))
5264
5889
  }));
5265
- var outputSchema6 = schema2((s2) => ({
5890
+ var outputSchema7 = schema2((s2) => ({
5266
5891
  url: s2.m(string2),
5267
5892
  fetchTime: s2.m(string2),
5268
5893
  categories: s2.m(array2(categoryResultSchema)),
@@ -5275,21 +5900,6 @@ var categoryIds = [
5275
5900
  "best-practices",
5276
5901
  "seo"
5277
5902
  ];
5278
- function getErrorMessage(exn) {
5279
- let jsError = fromException(exn);
5280
- if (jsError === void 0) {
5281
- return String(exn);
5282
- }
5283
- let jsError$1 = valFromOption(jsError);
5284
- let message3 = getOr(message2(jsError$1), "Unknown error");
5285
- let stack2 = jsError$1.stack;
5286
- if (stack2 !== void 0) {
5287
- return message3 + `
5288
- ` + stack2;
5289
- } else {
5290
- return message3;
5291
- }
5292
- }
5293
5903
  function getTopIssues(category, audits, maxIssues) {
5294
5904
  return filterMap(category.auditRefs, (ref) => audits[ref.id]).filter((audit) => {
5295
5905
  let score = audit.score;
@@ -5333,13 +5943,6 @@ function processLhr(lhr) {
5333
5943
  warnings: lhr.runWarnings
5334
5944
  };
5335
5945
  }
5336
- async function killChrome(chrome) {
5337
- try {
5338
- return await chrome.kill();
5339
- } catch (exn) {
5340
- return;
5341
- }
5342
- }
5343
5946
  async function runLighthouse(chrome, url2, preset) {
5344
5947
  let port2 = chrome.port;
5345
5948
  let flags_port = port2;
@@ -5362,7 +5965,7 @@ async function runLighthouse(chrome, url2, preset) {
5362
5965
  };
5363
5966
  try {
5364
5967
  let runnerResult = await run(url2, flags2);
5365
- await killChrome(chrome);
5968
+ await killSafely(chrome);
5366
5969
  if (runnerResult == null) {
5367
5970
  return {
5368
5971
  TAG: "Error",
@@ -5376,17 +5979,16 @@ async function runLighthouse(chrome, url2, preset) {
5376
5979
  }
5377
5980
  } catch (raw_exn) {
5378
5981
  let exn = internalToException(raw_exn);
5379
- await killChrome(chrome);
5380
- let msg = getErrorMessage(exn);
5982
+ await killSafely(chrome);
5983
+ let msg = getOr(flatMap(fromException(exn), message2), "Unknown error");
5381
5984
  return {
5382
5985
  TAG: "Error",
5383
5986
  _0: `Lighthouse audit failed: ` + msg
5384
5987
  };
5385
5988
  }
5386
5989
  }
5387
- async function execute6(_ctx, input) {
5990
+ async function execute7(_ctx, input) {
5388
5991
  let preset = getOr(input.preset, "desktop");
5389
- let auditUrl = rewriteUrlForRuntime(input.url);
5390
5992
  switch (preset) {
5391
5993
  case "desktop":
5392
5994
  case "mobile":
@@ -5406,42 +6008,17 @@ async function execute6(_ctx, input) {
5406
6008
  "--disable-dev-shm-usage"
5407
6009
  ]
5408
6010
  });
5409
- let result = await runLighthouse(chrome, auditUrl, preset);
5410
- if (result.TAG !== "Ok") {
5411
- return result;
5412
- }
5413
- let out = result._0;
5414
- if (auditUrl === input.url) {
5415
- return {
5416
- TAG: "Ok",
5417
- _0: out
5418
- };
5419
- }
5420
- let warning = `DevPod mode: audited local URL ` + auditUrl + ` instead of ` + input.url + `.`;
5421
- return {
5422
- TAG: "Ok",
5423
- _0: {
5424
- url: input.url,
5425
- fetchTime: out.fetchTime,
5426
- categories: out.categories,
5427
- overallScore: out.overallScore,
5428
- warnings: concatMany([
5429
- [warning],
5430
- out.warnings
5431
- ])
5432
- }
5433
- };
6011
+ return await runLighthouse(chrome, input.url, preset);
5434
6012
  } catch (raw_exn) {
5435
6013
  let exn = internalToException(raw_exn);
5436
- let msg = getErrorMessage(exn);
6014
+ let msg = getOr(flatMap(fromException(exn), message2), "Unknown error");
5437
6015
  return {
5438
6016
  TAG: "Error",
5439
6017
  _0: `Failed to launch Chrome: ` + msg + `. Make sure Chrome is installed on the system.`
5440
6018
  };
5441
6019
  }
5442
6020
  }
5443
- var name7 = "lighthouse";
5444
- var description6 = `Runs a Lighthouse audit on a URL to analyze performance, accessibility, best practices, and SEO.
6021
+ var description7 = `Runs a Lighthouse audit on a URL to analyze performance, accessibility, best practices, and SEO.
5445
6022
 
5446
6023
  WHEN TO USE THIS TOOL:
5447
6024
  - After making changes that might affect page load performance
@@ -5463,13 +6040,13 @@ LIMITATIONS:
5463
6040
  - Takes 15-30 seconds to complete
5464
6041
  - Results can vary between runs (\xB15 points is normal)
5465
6042
  - URL must be accessible from the machine running the audit`;
5466
- var name8 = ToolNames.searchFiles;
5467
- var inputSchema7 = schema2((s2) => ({
6043
+ var name9 = ToolNames.searchFiles;
6044
+ var inputSchema8 = schema2((s2) => ({
5468
6045
  pattern: s2.m(string2),
5469
6046
  path: s2.m(option2(string2)),
5470
6047
  max_results: s2.m(option2(int2))
5471
6048
  }));
5472
- var outputSchema7 = schema2((s2) => ({
6049
+ var outputSchema8 = schema2((s2) => ({
5473
6050
  files: s2.m(array2(string2)),
5474
6051
  totalResults: s2.m(int2),
5475
6052
  truncated: s2.m(bool2)
@@ -5583,7 +6160,7 @@ async function executeGitLsFiles(pattern2, searchPath, maxResults) {
5583
6160
  _0: `Git ls-files failed: ` + match.stderr
5584
6161
  };
5585
6162
  }
5586
- async function execute7(ctx2, input) {
6163
+ async function execute8(ctx2, input) {
5587
6164
  let searchPath = resolveSearchPath(ctx2.sourceRoot, input.path);
5588
6165
  let maxResults = getOr(input.max_results, 20);
5589
6166
  let rgPath = getRipgrepPath2();
@@ -5597,7 +6174,7 @@ async function execute7(ctx2, input) {
5597
6174
  return await executeGitLsFiles(input.pattern, searchPath, maxResults);
5598
6175
  }
5599
6176
  }
5600
- var description7 = `Fast file name search tool that finds files matching a pattern.
6177
+ var description8 = `Fast file name search tool that finds files matching a pattern.
5601
6178
 
5602
6179
  WHEN TO USE THIS TOOL:
5603
6180
  - Use when you need to find files by name pattern
@@ -5625,15 +6202,15 @@ LIMITATIONS:
5625
6202
  - Hidden files (starting with '.') are included
5626
6203
  - Respects .gitignore when using git ls-files fallback
5627
6204
  - Only finds files, not directories`;
5628
- var name9 = ToolNames.loadAgentInstructions;
5629
- var inputSchema8 = schema2((s2) => ({
6205
+ var name10 = ToolNames.loadAgentInstructions;
6206
+ var inputSchema9 = schema2((s2) => ({
5630
6207
  startPath: s2.m(option2(string2))
5631
6208
  }));
5632
6209
  var instructionFileSchema = schema2((s2) => ({
5633
6210
  content: s2.m(string2),
5634
6211
  fullPath: s2.m(string2)
5635
6212
  }));
5636
- var outputSchema8 = array2(instructionFileSchema);
6213
+ var outputSchema9 = array2(instructionFileSchema);
5637
6214
  var agentsVariants = [
5638
6215
  "Agents.md",
5639
6216
  ".claude/Agents.md",
@@ -5646,7 +6223,7 @@ var claudeVariants = [
5646
6223
  ];
5647
6224
  async function findFileCaseInsensitive(dir, targetFileName) {
5648
6225
  try {
5649
- let files = await Fs3.promises.readdir(dir);
6226
+ let files = await Fs.promises.readdir(dir);
5650
6227
  let targetLower = targetFileName.toLowerCase();
5651
6228
  let found = files.find((file) => file.toLowerCase() === targetLower);
5652
6229
  if (found !== void 0) {
@@ -5666,7 +6243,7 @@ async function loadIfExists(path) {
5666
6243
  return;
5667
6244
  }
5668
6245
  try {
5669
- let content = await Fs3.promises.readFile(actualPath, "utf8");
6246
+ let content = await Fs.promises.readFile(actualPath, "utf8");
5670
6247
  return {
5671
6248
  content,
5672
6249
  fullPath: actualPath
@@ -5703,7 +6280,7 @@ async function walkUpDirectories(current, acc) {
5703
6280
  let newAcc = acc.concat(filesAtLevel);
5704
6281
  return await walkUpDirectories(Nodepath.dirname(current), newAcc);
5705
6282
  }
5706
- async function execute8(ctx2, input) {
6283
+ async function execute9(ctx2, input) {
5707
6284
  let inputPath = getOr(input.startPath, ".");
5708
6285
  let msg = resolve(ctx2.sourceRoot, inputPath);
5709
6286
  if (msg.TAG !== "Ok") {
@@ -5728,7 +6305,7 @@ async function execute8(ctx2, input) {
5728
6305
  };
5729
6306
  }
5730
6307
  }
5731
- var description8 = `Discovers and loads agent instruction files (Agents.md or CLAUDE.md) following Claude Code's discovery algorithm.
6308
+ var description9 = `Discovers and loads agent instruction files (Agents.md or CLAUDE.md) following Claude Code's discovery algorithm.
5732
6309
 
5733
6310
  Parameters:
5734
6311
  - startPath (optional): Starting directory for discovery - must be under source root. Defaults to "." (source root).
@@ -5745,22 +6322,6 @@ Discovery:
5745
6322
  function coreTools() {
5746
6323
  return {
5747
6324
  tools: [
5748
- {
5749
- name: name3,
5750
- description: description2,
5751
- inputSchema: inputSchema2,
5752
- outputSchema: outputSchema2,
5753
- execute: execute2,
5754
- visibleToAgent: true
5755
- },
5756
- {
5757
- name: name5,
5758
- description: description4,
5759
- inputSchema: inputSchema4,
5760
- outputSchema: outputSchema4,
5761
- execute: execute4,
5762
- visibleToAgent: true
5763
- },
5764
6325
  {
5765
6326
  name: name4,
5766
6327
  description: description3,
@@ -5778,11 +6339,27 @@ function coreTools() {
5778
6339
  visibleToAgent: true
5779
6340
  },
5780
6341
  {
5781
- name: name9,
5782
- description: description8,
5783
- inputSchema: inputSchema8,
5784
- outputSchema: outputSchema8,
5785
- execute: execute8,
6342
+ name: name5,
6343
+ description: description4,
6344
+ inputSchema: inputSchema4,
6345
+ outputSchema: outputSchema4,
6346
+ execute: execute4,
6347
+ visibleToAgent: true
6348
+ },
6349
+ {
6350
+ name: name7,
6351
+ description: description6,
6352
+ inputSchema: inputSchema6,
6353
+ outputSchema: outputSchema6,
6354
+ execute: execute6,
6355
+ visibleToAgent: true
6356
+ },
6357
+ {
6358
+ name: name10,
6359
+ description: description9,
6360
+ inputSchema: inputSchema9,
6361
+ outputSchema: outputSchema9,
6362
+ execute: execute9,
5786
6363
  visibleToAgent: false
5787
6364
  },
5788
6365
  {
@@ -5793,6 +6370,14 @@ function coreTools() {
5793
6370
  execute,
5794
6371
  visibleToAgent: true
5795
6372
  },
6373
+ {
6374
+ name: name9,
6375
+ description: description8,
6376
+ inputSchema: inputSchema8,
6377
+ outputSchema: outputSchema8,
6378
+ execute: execute8,
6379
+ visibleToAgent: true
6380
+ },
5796
6381
  {
5797
6382
  name: name8,
5798
6383
  description: description7,
@@ -5802,11 +6387,11 @@ function coreTools() {
5802
6387
  visibleToAgent: true
5803
6388
  },
5804
6389
  {
5805
- name: name7,
5806
- description: description6,
5807
- inputSchema: inputSchema6,
5808
- outputSchema: outputSchema6,
5809
- execute: execute6,
6390
+ name: name3,
6391
+ description: description2,
6392
+ inputSchema: inputSchema2,
6393
+ outputSchema: outputSchema2,
6394
+ execute: execute2,
5810
6395
  visibleToAgent: true
5811
6396
  }
5812
6397
  ]
@@ -5817,8 +6402,19 @@ function addTools(registry, newTools) {
5817
6402
  tools: registry.tools.concat(newTools)
5818
6403
  };
5819
6404
  }
5820
- function getToolByName(registry, name11) {
5821
- return registry.tools.find((m) => m.name === name11);
6405
+ function replaceByName(registry, replacement) {
6406
+ return {
6407
+ tools: registry.tools.map((m) => {
6408
+ if (m.name === replacement.name) {
6409
+ return replacement;
6410
+ } else {
6411
+ return m;
6412
+ }
6413
+ })
6414
+ };
6415
+ }
6416
+ function getToolByName(registry, name14) {
6417
+ return registry.tools.find((m) => m.name === name14);
5822
6418
  }
5823
6419
  function serializeTool(m) {
5824
6420
  return {
@@ -5851,12 +6447,12 @@ var toolCallRequestSchema = schema2((s2) => ({
5851
6447
  var protocolVersion = "1.0";
5852
6448
 
5853
6449
  // ../frontman-core/src/FrontmanCore__Server.res.mjs
5854
- async function executeTool(registry, ctx2, name11, $$arguments) {
5855
- let toolModule = getToolByName(registry, name11);
6450
+ async function executeTool(registry, ctx2, name14, $$arguments) {
6451
+ let toolModule = getToolByName(registry, name14);
5856
6452
  if (toolModule === void 0) {
5857
6453
  return {
5858
6454
  TAG: "ToolNotFound",
5859
- _0: name11
6455
+ _0: name14
5860
6456
  };
5861
6457
  }
5862
6458
  let toolCtx_projectRoot = ctx2.projectRoot;
@@ -5948,7 +6544,23 @@ function getToolsResponse(registry, serverName, serverVersion) {
5948
6544
  };
5949
6545
  }
5950
6546
 
5951
- // src/FrontmanAstro__Server.res.mjs
6547
+ // ../frontman-core/src/FrontmanCore__RequestHandlers.res.mjs
6548
+ var resolveSourceLocationRequestSchema = schema2((s2) => ({
6549
+ componentName: s2.m(string2),
6550
+ file: s2.m(string2),
6551
+ line: s2.m(int2),
6552
+ column: s2.m(int2)
6553
+ }));
6554
+ var resolveSourceLocationResponseSchema = schema2((s2) => ({
6555
+ componentName: s2.m(string2),
6556
+ file: s2.m(string2),
6557
+ line: s2.m(int2),
6558
+ column: s2.m(int2)
6559
+ }));
6560
+ var errorResponseSchema = schema2((s2) => ({
6561
+ error: s2.m(string2),
6562
+ details: s2.m(option2(string2))
6563
+ }));
5952
6564
  function handleGetTools(registry, config) {
5953
6565
  let response = getToolsResponse(registry, config.serverName, config.serverVersion);
5954
6566
  let json3 = reverseConvertToJsonOrThrow2(response, toolsResponseSchema);
@@ -5990,13 +6602,27 @@ async function handleToolCall(registry, config, req) {
5990
6602
  let encoder = new TextEncoder();
5991
6603
  let stream = new Web.ReadableStream({
5992
6604
  start: (controller) => {
5993
- resultPromise.then((result) => {
6605
+ $$catch(resultPromise.then((result) => {
5994
6606
  let mcpResult = resultToMCP(result);
5995
6607
  let match = mcpResult.isError;
5996
6608
  let eventData = match !== void 0 && match ? errorEvent(mcpResult) : resultEvent(mcpResult);
5997
6609
  controller.enqueue(encoder.encode(eventData));
5998
6610
  controller.close();
5999
6611
  return Promise.resolve();
6612
+ }), (error) => {
6613
+ let msg = getOr(flatMap(fromException(error), message2), "Unknown error");
6614
+ let errorResult_content2 = [{
6615
+ type: "text",
6616
+ text: `Tool execution failed: ` + msg
6617
+ }];
6618
+ let errorResult_isError2 = true;
6619
+ let errorResult2 = {
6620
+ content: errorResult_content2,
6621
+ isError: errorResult_isError2
6622
+ };
6623
+ controller.enqueue(encoder.encode(errorEvent(errorResult2)));
6624
+ controller.close();
6625
+ return Promise.resolve();
6000
6626
  });
6001
6627
  }
6002
6628
  });
@@ -6018,113 +6644,582 @@ async function handleToolCall(registry, config, req) {
6018
6644
  status: 400
6019
6645
  });
6020
6646
  }
6021
- function corsHeaders() {
6022
- return Object.fromEntries([
6023
- [
6024
- "Access-Control-Allow-Origin",
6025
- "*"
6026
- ],
6027
- [
6028
- "Access-Control-Allow-Methods",
6029
- "GET, POST, OPTIONS"
6030
- ],
6031
- [
6032
- "Access-Control-Allow-Headers",
6033
- "Content-Type"
6034
- ]
6035
- ]);
6036
- }
6037
- function handleCORS() {
6038
- return new Response(null, {
6039
- status: 204,
6040
- headers: some(corsHeaders())
6041
- });
6042
- }
6043
- async function handleResolveSourceLocation(config, req) {
6647
+ async function handleResolveSourceLocation(sourceRoot, req) {
6044
6648
  let body = await req.json();
6045
- let requestObj = Decode.object(body);
6046
- if (requestObj === void 0) {
6047
- return Response.json(Object.fromEntries([[
6048
- "error",
6049
- "Invalid request body"
6050
- ]]), {
6051
- status: 400
6052
- });
6649
+ let request;
6650
+ try {
6651
+ request = {
6652
+ TAG: "Ok",
6653
+ _0: parseOrThrow2(body, resolveSourceLocationRequestSchema)
6654
+ };
6655
+ } catch (raw_e) {
6656
+ let e = internalToException(raw_e);
6657
+ if (e.RE_EXN_ID === $$Error2) {
6658
+ request = {
6659
+ TAG: "Error",
6660
+ _0: e._1.message
6661
+ };
6662
+ } else {
6663
+ throw e;
6664
+ }
6053
6665
  }
6054
- let componentName = flatMap(requestObj["componentName"], Decode.string);
6055
- let file = flatMap(requestObj["file"], Decode.string);
6056
- let line = flatMap(requestObj["line"], Decode.float);
6057
- let column = flatMap(requestObj["column"], Decode.float);
6058
- if (componentName !== void 0 && file !== void 0 && line !== void 0 && column !== void 0) {
6666
+ if (request.TAG === "Ok") {
6667
+ let request$1 = request._0;
6059
6668
  try {
6060
- let sourceLocation_line = line | 0;
6061
- let sourceLocation_column = column | 0;
6669
+ let sourceLocation_componentName = request$1.componentName;
6670
+ let sourceLocation_file = request$1.file;
6671
+ let sourceLocation_line = request$1.line;
6672
+ let sourceLocation_column = request$1.column;
6062
6673
  let sourceLocation = {
6063
- componentName,
6064
- file,
6674
+ componentName: sourceLocation_componentName,
6675
+ file: sourceLocation_file,
6065
6676
  line: sourceLocation_line,
6066
6677
  column: sourceLocation_column,
6067
6678
  componentProps: void 0,
6068
6679
  parent: void 0
6069
6680
  };
6070
6681
  let resolved = await Te(sourceLocation);
6071
- let relativeFile = toRelativePath(config.sourceRoot, resolved.file);
6072
- let responseJson = Object.fromEntries([
6073
- [
6074
- "componentName",
6075
- resolved.componentName
6076
- ],
6077
- [
6078
- "file",
6079
- relativeFile
6080
- ],
6081
- [
6082
- "line",
6083
- resolved.line
6084
- ],
6085
- [
6086
- "column",
6087
- resolved.column
6088
- ]
6089
- ]);
6682
+ let relativeFile = toRelativePath(sourceRoot, resolved.file);
6683
+ let responseJson_componentName = resolved.componentName;
6684
+ let responseJson_line = resolved.line;
6685
+ let responseJson_column = resolved.column;
6686
+ let responseJson = {
6687
+ componentName: responseJson_componentName,
6688
+ file: relativeFile,
6689
+ line: responseJson_line,
6690
+ column: responseJson_column
6691
+ };
6692
+ let json3 = reverseConvertToJsonOrThrow2(responseJson, resolveSourceLocationResponseSchema);
6090
6693
  let headers2 = Object.fromEntries([[
6091
6694
  "Content-Type",
6092
6695
  "application/json"
6093
6696
  ]]);
6094
- return Response.json(responseJson, {
6697
+ return Response.json(json3, {
6095
6698
  headers: some(headers2)
6096
6699
  });
6097
6700
  } catch (raw_exn) {
6098
6701
  let exn = internalToException(raw_exn);
6099
6702
  let msg = getOr(flatMap(fromException(exn), message2), "Unknown error");
6100
- return Response.json(Object.fromEntries([
6703
+ let json$1 = reverseConvertToJsonOrThrow2({
6704
+ error: "Failed to resolve source location",
6705
+ details: msg
6706
+ }, errorResponseSchema);
6707
+ return Response.json(json$1, {
6708
+ status: 500
6709
+ });
6710
+ }
6711
+ } else {
6712
+ let json$2 = reverseConvertToJsonOrThrow2({
6713
+ error: `Invalid request: ` + request._0,
6714
+ details: void 0
6715
+ }, errorResponseSchema);
6716
+ return Response.json(json$2, {
6717
+ status: 400
6718
+ });
6719
+ }
6720
+ }
6721
+
6722
+ // src/FrontmanAstro__Server.res.mjs
6723
+ function toHandlerConfig(config) {
6724
+ return {
6725
+ projectRoot: config.projectRoot,
6726
+ sourceRoot: config.sourceRoot,
6727
+ serverName: config.serverName,
6728
+ serverVersion: config.serverVersion
6729
+ };
6730
+ }
6731
+ function handleGetTools2(registry, config) {
6732
+ return handleGetTools(registry, toHandlerConfig(config));
6733
+ }
6734
+ async function handleToolCall2(registry, config, req) {
6735
+ return await handleToolCall(registry, toHandlerConfig(config), req);
6736
+ }
6737
+ async function handleResolveSourceLocation2(config, req) {
6738
+ return await handleResolveSourceLocation(config.sourceRoot, req);
6739
+ }
6740
+
6741
+ // ../frontman-core/src/FrontmanCore__UIShell.res.mjs
6742
+ function generateHTML(config) {
6743
+ let clientCssTag = mapOr(config.clientCssUrl, "", (url2) => `<link rel="stylesheet" href="` + url2 + `">`);
6744
+ let entrypointTemplate = mapOr(config.entrypointUrl, "", (url2) => `<script type="template" id="frontman-entrypoint-url">` + url2 + `</script>`);
6745
+ let themeClass = config.isLightTheme ? "" : "dark";
6746
+ let openrouterKey = flatMap(process.env["OPENROUTER_API_KEY"], (key) => {
6747
+ if (key !== "") {
6748
+ return key;
6749
+ }
6750
+ });
6751
+ let configObj = Object.fromEntries([[
6752
+ "framework",
6753
+ config.frameworkLabel
6754
+ ]]);
6755
+ forEach(openrouterKey, (key) => {
6756
+ configObj["openrouterKeyValue"] = key;
6757
+ });
6758
+ let payload = JSON.stringify(configObj);
6759
+ let runtimeConfigScript = `<script>window.__frontmanRuntime=` + payload + `</script>`;
6760
+ return `<!DOCTYPE html>
6761
+ <html lang="en" class="` + themeClass + `">
6762
+ <head>
6763
+ <meta charset="UTF-8">
6764
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6765
+ <title>Frontman</title>
6766
+ ` + entrypointTemplate + `
6767
+ ` + clientCssTag + `
6768
+ <style>
6769
+ html, body, #root {
6770
+ margin: 0;
6771
+ padding: 0;
6772
+ height: 100%;
6773
+ width: 100%;
6774
+ }
6775
+ </style>
6776
+ </head>
6777
+ <body>
6778
+ <div id="root"></div>
6779
+ ` + runtimeConfigScript + `
6780
+ <script>if(typeof process==="undefined"){window.process={env:{NODE_ENV:"production"}}}</script>
6781
+ <script type="module" src="` + config.clientUrl + `"></script>
6782
+ </body>
6783
+ </html>`;
6784
+ }
6785
+ function serve(config) {
6786
+ let html = generateHTML(config);
6787
+ let headers2 = Object.fromEntries([[
6788
+ "Content-Type",
6789
+ "text/html"
6790
+ ]]);
6791
+ return new Response(html, {
6792
+ headers: some(headers2)
6793
+ });
6794
+ }
6795
+
6796
+ // ../frontman-core/src/FrontmanCore__CircularBuffer.res.mjs
6797
+ function make3(capacity) {
6798
+ return {
6799
+ data: make2(capacity, void 0),
6800
+ writeIndex: 0,
6801
+ count: 0,
6802
+ maxSize: capacity
6803
+ };
6804
+ }
6805
+ function push(buffer, entry) {
6806
+ buffer.data[buffer.writeIndex] = some(entry);
6807
+ return {
6808
+ data: buffer.data,
6809
+ writeIndex: mod_(buffer.writeIndex + 1 | 0, buffer.maxSize),
6810
+ count: min(buffer.count + 1 | 0, buffer.maxSize),
6811
+ maxSize: buffer.maxSize
6812
+ };
6813
+ }
6814
+ function toArray3(buffer) {
6815
+ let c2 = buffer.count;
6816
+ if (c2 === 0) {
6817
+ return [];
6818
+ }
6819
+ if (c2 < buffer.maxSize) {
6820
+ return filterMap(buffer.data.slice(0, buffer.count), (x) => x);
6821
+ }
6822
+ let tail = filterMap(buffer.data.slice(buffer.writeIndex, buffer.maxSize), (x) => x);
6823
+ let head = filterMap(buffer.data.slice(0, buffer.writeIndex), (x) => x);
6824
+ return tail.concat(head);
6825
+ }
6826
+ function length2(buffer) {
6827
+ return buffer.count;
6828
+ }
6829
+
6830
+ // ../frontman-core/src/FrontmanCore__LogCapture.res.mjs
6831
+ enableJson2();
6832
+ function isBrowser() {
6833
+ return typeof window !== "undefined";
6834
+ }
6835
+ function getPatchedFlag() {
6836
+ return globalThis.__FRONTMAN_CORE_CONSOLE_PATCHED__;
6837
+ }
6838
+ function setPatchedFlag(_value) {
6839
+ globalThis.__FRONTMAN_CORE_CONSOLE_PATCHED__ = _value;
6840
+ }
6841
+ var logLevelSchema = union2([
6842
+ literal2("console"),
6843
+ literal2("build"),
6844
+ literal2("error")
6845
+ ]);
6846
+ var consoleMethodSchema = union2([
6847
+ literal2("log"),
6848
+ literal2("info"),
6849
+ literal2("warn"),
6850
+ literal2("error"),
6851
+ literal2("debug")
6852
+ ]);
6853
+ var logEntrySchema = schema2((s2) => ({
6854
+ timestamp: s2.m(string2),
6855
+ level: s2.m(logLevelSchema),
6856
+ message: s2.m(string2),
6857
+ attributes: s2.m(option2(json2)),
6858
+ resource: s2.m(option2(json2)),
6859
+ consoleMethod: s2.m(option2(consoleMethodSchema))
6860
+ }));
6861
+ var defaultConfig_stdoutPatterns = [
6862
+ "webpack",
6863
+ "turbopack",
6864
+ "Compiled",
6865
+ "Failed",
6866
+ "vite",
6867
+ "hmr",
6868
+ "error",
6869
+ "Error",
6870
+ "astro",
6871
+ "build"
6872
+ ];
6873
+ var defaultConfig = {
6874
+ bufferCapacity: 1024,
6875
+ stdoutPatterns: defaultConfig_stdoutPatterns
6876
+ };
6877
+ function getGlobalInstanceOpt() {
6878
+ return globalThis.__FRONTMAN_CORE_INSTANCE__;
6879
+ }
6880
+ function setGlobalInstance(_state) {
6881
+ globalThis.__FRONTMAN_CORE_INSTANCE__ = _state;
6882
+ }
6883
+ function getOrCreateInstance(config) {
6884
+ let state = getGlobalInstanceOpt();
6885
+ if (state !== void 0) {
6886
+ return state;
6887
+ }
6888
+ let state_buffer = {
6889
+ contents: make3(config.bufferCapacity)
6890
+ };
6891
+ let state$1 = {
6892
+ buffer: state_buffer,
6893
+ config
6894
+ };
6895
+ setGlobalInstance(state$1);
6896
+ return state$1;
6897
+ }
6898
+ function getInstance() {
6899
+ let state = getGlobalInstanceOpt();
6900
+ if (state !== void 0) {
6901
+ return state;
6902
+ } else {
6903
+ return getOrCreateInstance(defaultConfig);
6904
+ }
6905
+ }
6906
+ function argsToString(args) {
6907
+ return args.map((arg) => {
6908
+ let match = typeof arg;
6909
+ if (match === "string") {
6910
+ return arg;
6911
+ } else if (match === "object") {
6912
+ if (arg instanceof Error) {
6913
+ return getOr(arg.stack, arg.message);
6914
+ } else {
6915
+ return getOr(JSON.stringify(arg), "null");
6916
+ }
6917
+ } else {
6918
+ return String(arg);
6919
+ }
6920
+ }).join(" ");
6921
+ }
6922
+ function stripAnsi(str) {
6923
+ return str.replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, "");
6924
+ }
6925
+ function addLog(state, level, message3, attributes, consoleMethod) {
6926
+ let cleanMessage = stripAnsi(message3).trim();
6927
+ if (cleanMessage === "") {
6928
+ return;
6929
+ }
6930
+ let entry_timestamp = new Date(Date.now()).toISOString();
6931
+ let entry = {
6932
+ timestamp: entry_timestamp,
6933
+ level,
6934
+ message: cleanMessage,
6935
+ attributes,
6936
+ resource: void 0,
6937
+ consoleMethod
6938
+ };
6939
+ state.buffer.contents = push(state.buffer.contents, entry);
6940
+ }
6941
+ function handleConsoleLog(state, args) {
6942
+ try {
6943
+ return addLog(state, "console", argsToString(args), void 0, "log");
6944
+ } catch (exn) {
6945
+ return;
6946
+ }
6947
+ }
6948
+ function handleConsoleWarn(state, args) {
6949
+ try {
6950
+ return addLog(state, "console", argsToString(args), void 0, "warn");
6951
+ } catch (exn) {
6952
+ return;
6953
+ }
6954
+ }
6955
+ function handleConsoleError(state, args) {
6956
+ try {
6957
+ return addLog(state, "console", argsToString(args), void 0, "error");
6958
+ } catch (exn) {
6959
+ return;
6960
+ }
6961
+ }
6962
+ function handleConsoleInfo(state, args) {
6963
+ try {
6964
+ return addLog(state, "console", argsToString(args), void 0, "info");
6965
+ } catch (exn) {
6966
+ return;
6967
+ }
6968
+ }
6969
+ function handleConsoleDebug(state, args) {
6970
+ try {
6971
+ return addLog(state, "console", argsToString(args), void 0, "debug");
6972
+ } catch (exn) {
6973
+ return;
6974
+ }
6975
+ }
6976
+ var interceptConsole = (function(state) {
6977
+ const originalLog = console.log.bind(console);
6978
+ const originalWarn = console.warn.bind(console);
6979
+ const originalError = console.error.bind(console);
6980
+ const originalInfo = console.info.bind(console);
6981
+ const originalDebug = console.debug.bind(console);
6982
+ console.log = (...args) => {
6983
+ handleConsoleLog(state, args);
6984
+ originalLog(...args);
6985
+ };
6986
+ console.warn = (...args) => {
6987
+ handleConsoleWarn(state, args);
6988
+ originalWarn(...args);
6989
+ };
6990
+ console.error = (...args) => {
6991
+ handleConsoleError(state, args);
6992
+ originalError(...args);
6993
+ };
6994
+ console.info = (...args) => {
6995
+ handleConsoleInfo(state, args);
6996
+ originalInfo(...args);
6997
+ };
6998
+ console.debug = (...args) => {
6999
+ handleConsoleDebug(state, args);
7000
+ originalDebug(...args);
7001
+ };
7002
+ });
7003
+ function handleStdoutWrite(state, message3) {
7004
+ try {
7005
+ let matchesPattern2 = state.config.stdoutPatterns.some((pattern2) => message3.includes(pattern2));
7006
+ if (matchesPattern2) {
7007
+ return addLog(state, "build", message3, void 0, void 0);
7008
+ } else {
7009
+ return;
7010
+ }
7011
+ } catch (exn) {
7012
+ return;
7013
+ }
7014
+ }
7015
+ function interceptStdout(_state) {
7016
+ (function(_state2) {
7017
+ const originalWrite = process.stdout.write.bind(process.stdout);
7018
+ process.stdout.write = (chunk, ...args) => {
7019
+ const message3 = typeof chunk === "string" ? chunk : chunk.toString();
7020
+ handleStdoutWrite(_state2, message3);
7021
+ return originalWrite(chunk, ...args);
7022
+ };
7023
+ })(_state);
7024
+ }
7025
+ function interceptUncaughtErrors(state) {
7026
+ process.on("uncaughtException", (error) => {
7027
+ try {
7028
+ let errorMessage = getOr(error.message, "Unknown error");
7029
+ let attributes = Object.fromEntries([
6101
7030
  [
6102
- "error",
6103
- "Failed to resolve source location"
7031
+ "stack",
7032
+ getOr(map(error.stack, (prim) => prim), null)
6104
7033
  ],
6105
7034
  [
6106
- "details",
6107
- msg
7035
+ "name",
7036
+ error.name
6108
7037
  ]
6109
- ]), {
6110
- status: 500
6111
- });
7038
+ ]);
7039
+ return addLog(state, "error", errorMessage, attributes, void 0);
7040
+ } catch (exn) {
7041
+ return;
7042
+ }
7043
+ });
7044
+ process.on("unhandledRejection", (reason2) => {
7045
+ try {
7046
+ let reasonMessage = getOr(reason2.message, String.toString(reason2));
7047
+ let attributes = Object.fromEntries([[
7048
+ "stack",
7049
+ getOr(map(reason2.stack, (prim) => prim), null)
7050
+ ]]);
7051
+ return addLog(state, "error", reasonMessage, attributes, void 0);
7052
+ } catch (exn) {
7053
+ return;
6112
7054
  }
7055
+ });
7056
+ }
7057
+ function initialize(configOpt, param) {
7058
+ let config = defaultConfig;
7059
+ if (isBrowser()) {
7060
+ return;
6113
7061
  }
6114
- return Response.json(Object.fromEntries([[
6115
- "error",
6116
- "Missing required fields: componentName, file, line, column"
6117
- ]]), {
6118
- status: 400
7062
+ let match = getPatchedFlag();
7063
+ if (match !== void 0 && match) {
7064
+ return;
7065
+ }
7066
+ setPatchedFlag(true);
7067
+ let state = getOrCreateInstance(config);
7068
+ interceptConsole(state);
7069
+ interceptStdout(state);
7070
+ interceptUncaughtErrors(state);
7071
+ }
7072
+ var regexCache = {
7073
+ pattern: void 0,
7074
+ regex: void 0
7075
+ };
7076
+ function getCompiledRegex(pattern2) {
7077
+ let cached = regexCache.pattern;
7078
+ if (cached !== void 0 && cached === pattern2) {
7079
+ let r = regexCache.regex;
7080
+ if (r !== void 0) {
7081
+ return r;
7082
+ }
7083
+ let regex = new RegExp(pattern2, "i");
7084
+ regexCache.regex = regex;
7085
+ return regex;
7086
+ }
7087
+ let regex$1 = new RegExp(pattern2, "i");
7088
+ regexCache.pattern = pattern2;
7089
+ regexCache.regex = regex$1;
7090
+ return regex$1;
7091
+ }
7092
+ function getLogs(pattern2, level, since, tail) {
7093
+ try {
7094
+ let state = getInstance();
7095
+ let allLogs = toArray3(state.buffer.contents);
7096
+ let logs = since !== void 0 ? allLogs.filter((entry) => new Date(entry.timestamp).getTime() >= since) : allLogs;
7097
+ let logs$1 = level !== void 0 ? logs.filter((entry) => entry.level === level) : logs;
7098
+ let logs$2;
7099
+ if (pattern2 !== void 0) {
7100
+ let regex = getCompiledRegex(pattern2);
7101
+ logs$2 = logs$1.filter((entry) => regex.test(entry.message));
7102
+ } else {
7103
+ logs$2 = logs$1;
7104
+ }
7105
+ if (tail === void 0) {
7106
+ return logs$2;
7107
+ }
7108
+ let len = logs$2.length;
7109
+ return logs$2.slice(max(0, len - tail | 0), len);
7110
+ } catch (exn) {
7111
+ return [];
7112
+ }
7113
+ }
7114
+
7115
+ // src/tools/FrontmanAstro__Tool__GetLogs.res.mjs
7116
+ var inputSchema10 = schema2((s2) => ({
7117
+ pattern: s2.m(option2(string2)),
7118
+ level: s2.m(option2(logLevelSchema)),
7119
+ since: s2.m(option2(string2)),
7120
+ tail: s2.m(option2(int2))
7121
+ }));
7122
+ var outputSchema10 = schema2((s2) => ({
7123
+ logs: s2.m(array2(logEntrySchema)),
7124
+ totalMatched: s2.m(int2),
7125
+ bufferSize: s2.m(int2),
7126
+ hasMore: s2.m(bool2)
7127
+ }));
7128
+ async function execute10(_ctx, input) {
7129
+ try {
7130
+ let sinceTimestamp = map(input.since, (isoString) => new Date(isoString).getTime());
7131
+ let allMatchedLogs = getLogs(input.pattern, input.level, sinceTimestamp, void 0);
7132
+ let totalMatched = allMatchedLogs.length;
7133
+ let n = input.tail;
7134
+ let logs = n !== void 0 ? allMatchedLogs.slice(max(0, totalMatched - n | 0), totalMatched) : allMatchedLogs;
7135
+ let n$1 = input.tail;
7136
+ let hasMore = n$1 !== void 0 ? totalMatched > n$1 : false;
7137
+ let bufferSize = length2(getInstance().buffer.contents);
7138
+ return {
7139
+ TAG: "Ok",
7140
+ _0: {
7141
+ logs,
7142
+ totalMatched,
7143
+ bufferSize,
7144
+ hasMore
7145
+ }
7146
+ };
7147
+ } catch (raw_exn) {
7148
+ let exn = internalToException(raw_exn);
7149
+ let msg = getOr(flatMap(fromException(exn), message2), "Unknown error");
7150
+ return {
7151
+ TAG: "Error",
7152
+ _0: `Failed to retrieve logs: ` + msg
7153
+ };
7154
+ }
7155
+ }
7156
+ var name11 = "get_logs";
7157
+ var description10 = `Retrieves dev server logs from rotating 1024-entry buffer.
7158
+
7159
+ Captures:
7160
+ - Console output (console.log, warn, error, info, debug)
7161
+ - Astro build logs (compilation, errors, warnings)
7162
+ - Uncaught exceptions with stack traces
7163
+
7164
+ Parameters:
7165
+ - pattern (optional): JavaScript regex pattern to filter messages (case-insensitive)
7166
+ Examples: "error", "astro.*build", "TypeError"
7167
+ - level (optional): Filter by log type: "console", "build", or "error"
7168
+ - since (optional): ISO 8601 timestamp - only return logs after this time
7169
+ Example: "2025-12-28T10:30:00.000Z"
7170
+ - tail (optional): Limit to most recent N entries
7171
+ Example: 100 (returns last 100 matching logs)
7172
+
7173
+ Returns logs in chronological order (oldest first within buffer).`;
7174
+
7175
+ // src/tools/FrontmanAstro__Tool__EditFile.res.mjs
7176
+ function sleep(ms) {
7177
+ return new Promise((resolve3, param) => {
7178
+ setTimeout(() => resolve3(), ms);
7179
+ });
7180
+ }
7181
+ async function execute11(ctx2, input) {
7182
+ let beforeTimestamp = Date.now();
7183
+ let result = await execute2(ctx2, input);
7184
+ if (result.TAG !== "Ok") {
7185
+ return result;
7186
+ }
7187
+ let output = result._0;
7188
+ await sleep(800);
7189
+ let recentLogs = getLogs(void 0, "error", beforeTimestamp, void 0);
7190
+ let errorLogs = getLogs("error|Error|failed|Failed", void 0, beforeTimestamp, void 0);
7191
+ let seen = /* @__PURE__ */ new Set();
7192
+ recentLogs.forEach((entry) => {
7193
+ seen.add(entry.timestamp + "|" + entry.message);
6119
7194
  });
7195
+ let allErrors = recentLogs.concat(errorLogs.filter((entry) => !seen.has(entry.timestamp + "|" + entry.message)));
7196
+ if (allErrors.length === 0) {
7197
+ return {
7198
+ TAG: "Ok",
7199
+ _0: output
7200
+ };
7201
+ }
7202
+ let errorMessages = allErrors.slice(0, 5).map((entry) => entry.message).join("\n");
7203
+ let newrecord = { ...output };
7204
+ return {
7205
+ TAG: "Ok",
7206
+ _0: (newrecord.message = output.message + (`
7207
+
7208
+ Warning: Dev server errors detected after edit:
7209
+ ` + errorMessages), newrecord)
7210
+ };
6120
7211
  }
7212
+ var name12 = "edit_file";
7213
+ var description11 = description2;
7214
+ var inputSchema11 = inputSchema2;
7215
+ var outputSchema11 = outputSchema2;
6121
7216
  var dynamicTypeSchema = union2([
6122
7217
  literal2("static"),
6123
7218
  literal2("single"),
6124
7219
  literal2("rest"),
6125
7220
  literal2("optional")
6126
7221
  ]);
6127
- var inputSchema9 = schema2((s2) => ({
7222
+ var inputSchema12 = schema2((s2) => ({
6128
7223
  placeholder: s2.m(option2(bool2))
6129
7224
  }));
6130
7225
  var pageSchema = schema2((s2) => ({
@@ -6133,7 +7228,7 @@ var pageSchema = schema2((s2) => ({
6133
7228
  isDynamic: s2.m(bool2),
6134
7229
  dynamicType: s2.m(dynamicTypeSchema)
6135
7230
  }));
6136
- var outputSchema9 = array2(pageSchema);
7231
+ var outputSchema12 = array2(pageSchema);
6137
7232
  function analyzeDynamicSegment(segment) {
6138
7233
  if (segment.startsWith("[[") && segment.endsWith("]]")) {
6139
7234
  return "optional";
@@ -6188,10 +7283,10 @@ function getMostSignificantDynamicType(segments) {
6188
7283
  async function findPages(baseDir, currentPath, projectRoot, sourceRoot) {
6189
7284
  let fullPath = Nodepath.join(projectRoot, baseDir, currentPath);
6190
7285
  try {
6191
- let entries = await Fs3.promises.readdir(fullPath);
7286
+ let entries = await Fs.promises.readdir(fullPath);
6192
7287
  return (await Promise.all(entries.map(async (entry) => {
6193
7288
  let entryPath = Nodepath.join(fullPath, entry);
6194
- let stats = await Fs3.promises.lstat(entryPath);
7289
+ let stats = await Fs.promises.lstat(entryPath);
6195
7290
  if (stats.isSymbolicLink()) {
6196
7291
  return [];
6197
7292
  }
@@ -6228,7 +7323,7 @@ async function findPages(baseDir, currentPath, projectRoot, sourceRoot) {
6228
7323
  throw exn;
6229
7324
  }
6230
7325
  }
6231
- async function execute9(ctx2, _input) {
7326
+ async function execute12(ctx2, _input) {
6232
7327
  try {
6233
7328
  let srcPages = await findPages("src/pages", "", ctx2.projectRoot, ctx2.sourceRoot);
6234
7329
  let rootPages = await findPages("pages", "", ctx2.projectRoot, ctx2.sourceRoot);
@@ -6246,8 +7341,8 @@ async function execute9(ctx2, _input) {
6246
7341
  };
6247
7342
  }
6248
7343
  }
6249
- var name10 = "get_client_pages";
6250
- var description9 = `Lists Astro client pages from the pages directory.
7344
+ var name13 = "get_client_pages";
7345
+ var description12 = `Lists Astro client pages from the pages directory.
6251
7346
 
6252
7347
  Parameters: None
6253
7348
 
@@ -6255,70 +7350,53 @@ Returns array of page paths based on file-system routing conventions.
6255
7350
  Excludes API routes (src/pages/api/) - focuses on renderable pages only.`;
6256
7351
 
6257
7352
  // src/FrontmanAstro__ToolRegistry.res.mjs
6258
- var astroTools = [{
6259
- name: name10,
6260
- description: description9,
6261
- inputSchema: inputSchema9,
6262
- outputSchema: outputSchema9,
6263
- execute: execute9,
6264
- visibleToAgent: true
6265
- }];
6266
- function make2() {
6267
- return addTools(coreTools(), astroTools);
7353
+ var astroTools = [
7354
+ {
7355
+ name: name13,
7356
+ description: description12,
7357
+ inputSchema: inputSchema12,
7358
+ outputSchema: outputSchema12,
7359
+ execute: execute12,
7360
+ visibleToAgent: true
7361
+ },
7362
+ {
7363
+ name: name11,
7364
+ description: description10,
7365
+ inputSchema: inputSchema10,
7366
+ outputSchema: outputSchema10,
7367
+ execute: execute10,
7368
+ visibleToAgent: true
7369
+ }
7370
+ ];
7371
+ function make4() {
7372
+ return replaceByName(addTools(coreTools(), astroTools), {
7373
+ name: name12,
7374
+ description: description11,
7375
+ inputSchema: inputSchema11,
7376
+ outputSchema: outputSchema11,
7377
+ execute: execute11,
7378
+ visibleToAgent: true
7379
+ });
6268
7380
  }
6269
7381
 
6270
7382
  // src/FrontmanAstro__Middleware.res.mjs
6271
- function uiHtml(clientUrl, clientCssUrl, isLightTheme) {
6272
- let openrouterKey = flatMap(process.env["OPENROUTER_API_KEY"], (key) => {
6273
- if (key !== "") {
6274
- return key;
6275
- }
6276
- });
6277
- let configObj = Object.fromEntries([[
6278
- "framework",
6279
- "Astro"
6280
- ]]);
6281
- forEach(openrouterKey, (key) => {
6282
- configObj["openrouterKeyValue"] = key;
6283
- });
6284
- let runtimeConfig = JSON.stringify(configObj);
6285
- let themeClass = isLightTheme ? "" : "dark";
6286
- let cssLink = clientCssUrl !== void 0 ? `<link rel="stylesheet" href="` + clientCssUrl + `">` : "";
6287
- return `<!DOCTYPE html>
6288
- <html lang="en" class="` + themeClass + `">
6289
- <head>
6290
- <meta charset="UTF-8">
6291
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6292
- <title>Frontman</title>
6293
- ` + cssLink + `
6294
- <style>
6295
- html, body, #root {
6296
- margin: 0;
6297
- padding: 0;
6298
- height: 100%;
6299
- width: 100%;
6300
- }
6301
- </style>
6302
- </head>
6303
- <body>
6304
- <div id="root"></div>
6305
- <script>window.__frontmanRuntime=` + runtimeConfig + `</script>
6306
- <script type="module" src="` + clientUrl + `"></script>
6307
- </body>
6308
- </html>`;
6309
- }
6310
- function serveUI(config) {
6311
- let html = uiHtml(config.clientUrl, config.clientCssUrl, config.isLightTheme);
6312
- let headers2 = Object.fromEntries([[
6313
- "Content-Type",
6314
- "text/html"
6315
- ]]);
6316
- return new Response(html, {
6317
- headers: some(headers2)
6318
- });
7383
+ function toMiddlewareConfig(config) {
7384
+ return {
7385
+ projectRoot: config.projectRoot,
7386
+ sourceRoot: config.sourceRoot,
7387
+ basePath: config.basePath,
7388
+ serverName: config.serverName,
7389
+ serverVersion: config.serverVersion,
7390
+ clientUrl: config.clientUrl,
7391
+ clientCssUrl: config.clientCssUrl,
7392
+ entrypointUrl: void 0,
7393
+ isLightTheme: config.isLightTheme,
7394
+ frameworkLabel: "Astro"
7395
+ };
6319
7396
  }
6320
7397
  function createMiddleware(config) {
6321
- let registry = make2();
7398
+ let registry = make4();
7399
+ let middlewareConfig = toMiddlewareConfig(config);
6322
7400
  return async (request) => {
6323
7401
  let url2 = new URL(request.url);
6324
7402
  let pathname = url2.pathname;
@@ -6326,15 +7404,15 @@ function createMiddleware(config) {
6326
7404
  let basePath = `/` + config.basePath;
6327
7405
  if (pathname === basePath || pathname.startsWith(basePath + `/`)) {
6328
7406
  if (method === "OPTIONS") {
6329
- return handleCORS();
7407
+ return handlePreflight();
6330
7408
  } else if (pathname === basePath || pathname === basePath + `/`) {
6331
- return serveUI(config);
7409
+ return withCors(serve(middlewareConfig));
6332
7410
  } else if (pathname === basePath + `/tools` && method === "GET") {
6333
- return handleGetTools(registry, config);
7411
+ return withCors(handleGetTools2(registry, config));
6334
7412
  } else if (pathname === basePath + `/tools/call` && method === "POST") {
6335
- return await handleToolCall(registry, config, request);
7413
+ return withCors(await handleToolCall2(registry, config, request));
6336
7414
  } else if (pathname === basePath + `/resolve-source-location` && method === "POST") {
6337
- return await handleResolveSourceLocation(config, request);
7415
+ return withCors(await handleResolveSourceLocation2(config, request));
6338
7416
  } else {
6339
7417
  return Response.json(Object.fromEntries([[
6340
7418
  "error",
@@ -6347,11 +7425,6 @@ function createMiddleware(config) {
6347
7425
  };
6348
7426
  }
6349
7427
 
6350
- // ../../node_modules/@rescript/runtime/lib/es6/Stdlib_Promise.js
6351
- function $$catch(promise, callback) {
6352
- return promise.catch((err) => callback(internalToException(err)));
6353
- }
6354
-
6355
7428
  // ../bindings/src/NodeHttp.res.mjs
6356
7429
  var collectRequestBody = (async function(req) {
6357
7430
  const chunks = [];
@@ -6459,34 +7532,46 @@ var icon = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewB
6459
7532
  function getToolbarAppPath() {
6460
7533
  return new URL("./toolbar.js", import.meta.url).pathname;
6461
7534
  }
6462
- function make3(configInput) {
7535
+ function make5(configInput) {
6463
7536
  let config = makeFromObject(configInput);
6464
7537
  return {
6465
7538
  name: "frontman",
6466
7539
  hooks: {
6467
7540
  "astro:config:setup": (ctx2) => {
6468
- if (ctx2.command === "dev") {
6469
- if (!ctx2.config.devToolbar.enabled) {
6470
- console.warn("[Frontman] Astro devToolbar is disabled \u2014 element source detection will be limited. Set `devToolbar: { enabled: true }` in your astro.config to enable full component source resolution.");
6471
- }
6472
- ctx2.updateConfig({
6473
- vite: {
6474
- plugins: [frontmanPropsInjectionPlugin()]
6475
- }
6476
- });
6477
- ctx2.addDevToolbarApp({
6478
- id: "frontman:toolbar",
6479
- name: "Frontman",
6480
- icon,
6481
- entrypoint: getToolbarAppPath()
6482
- });
6483
- return ctx2.injectScript("head-inline", annotationCaptureScript2);
7541
+ if (ctx2.command !== "dev") {
7542
+ return;
7543
+ }
7544
+ if (!ctx2.config.devToolbar.enabled) {
7545
+ console.warn("[Frontman] Astro devToolbar is disabled \u2014 element source detection will be limited. Set `devToolbar: { enabled: true }` in your astro.config to enable full component source resolution.");
6484
7546
  }
7547
+ ctx2.updateConfig({
7548
+ vite: {
7549
+ plugins: [frontmanPropsInjectionPlugin()]
7550
+ }
7551
+ });
7552
+ ctx2.addDevToolbarApp({
7553
+ id: "frontman:toolbar",
7554
+ name: "Frontman",
7555
+ icon,
7556
+ entrypoint: getToolbarAppPath()
7557
+ });
7558
+ let safeBasePath = getOr(JSON.stringify(config.basePath), `"frontman"`);
7559
+ let basePathMeta = `{
7560
+ const meta = document.createElement('meta');
7561
+ meta.name = 'frontman-base-path';
7562
+ meta.content = ` + safeBasePath + `;
7563
+ document.head.appendChild(meta);
7564
+ }`;
7565
+ ctx2.injectScript("head-inline", basePathMeta + "\n" + annotationCaptureScript2);
6485
7566
  },
6486
7567
  "astro:server:setup": (param) => {
7568
+ initialize();
6487
7569
  let webMiddleware = createMiddleware(config);
6488
7570
  let connectMiddleware = adaptToConnect(webMiddleware, config.basePath);
6489
7571
  param.server.middlewares.use(connectMiddleware);
7572
+ param.toolbar.onAppInitialized("frontman:toolbar", () => {
7573
+ console.log("[Frontman] Dev toolbar app initialized");
7574
+ });
6490
7575
  }
6491
7576
  }
6492
7577
  };
@@ -6496,4 +7581,4 @@ var Config;
6496
7581
  var Middleware;
6497
7582
  var ViteAdapter;
6498
7583
 
6499
- export { Bindings, Config, Middleware, ViteAdapter, annotationCaptureScript2 as annotationCaptureScript, frontmanPropsInjectionPlugin2 as frontmanPropsInjectionPlugin, getToolbarAppPath, icon, make3 as make };
7584
+ export { Bindings, Config, Middleware, ViteAdapter, annotationCaptureScript2 as annotationCaptureScript, frontmanPropsInjectionPlugin2 as frontmanPropsInjectionPlugin, getToolbarAppPath, icon, make5 as make };