@frontman-ai/astro 0.1.6 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/index.js +1103 -439
  2. package/dist/integration.js +1103 -439
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,9 +1,11 @@
1
1
  import * as Web from 'stream/web';
2
- import * as Fs2 from 'fs';
2
+ import * as Fs3 from 'fs';
3
3
  import { existsSync, readFileSync } from 'fs';
4
4
  import * as Nodepath from 'path';
5
5
  import { dirname, join } from 'path';
6
6
  import { createRequire } from 'module';
7
+ import * as Nodebuffer from 'buffer';
8
+ import * as Nodechild_process from 'child_process';
7
9
 
8
10
  var __getOwnPropNames = Object.getOwnPropertyNames;
9
11
  var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
@@ -16,9 +18,9 @@ var __commonJS = (cb, mod) => function __require2() {
16
18
  return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
17
19
  };
18
20
 
19
- // ../../node_modules/vscode-ripgrep/lib/index.js
21
+ // ../../node_modules/@vscode/ripgrep/lib/index.js
20
22
  var require_lib = __commonJS({
21
- "../../node_modules/vscode-ripgrep/lib/index.js"(exports$1, module) {
23
+ "../../node_modules/@vscode/ripgrep/lib/index.js"(exports$1, module) {
22
24
  var path = __require("path");
23
25
  module.exports.rgPath = path.join(__dirname, `../bin/rg${process.platform === "win32" ? ".exe" : ""}`);
24
26
  }
@@ -89,6 +91,9 @@ function orElse(opt, other) {
89
91
  return other;
90
92
  }
91
93
  }
94
+ function isSome(x) {
95
+ return x !== void 0;
96
+ }
92
97
 
93
98
  // ../frontman-core/src/FrontmanCore__Hosts.res.mjs
94
99
  var apiHost = "api.frontman.sh";
@@ -135,6 +140,267 @@ function makeFromObject(rawConfig) {
135
140
  };
136
141
  }
137
142
 
143
+ // src/annotation-capture.mjs
144
+ var annotationCaptureScript = `(function() {
145
+ var PROPS_PREFIX = '__frontman_props__:';
146
+
147
+ function parsePropsPayload(text) {
148
+ text = text.trim();
149
+ if (text.indexOf(PROPS_PREFIX) !== 0) return null;
150
+ try {
151
+ var encoded = text.slice(PROPS_PREFIX.length).trim();
152
+ return JSON.parse(atob(encoded));
153
+ } catch(e) {
154
+ return null;
155
+ }
156
+ }
157
+
158
+ function captureAnnotations() {
159
+ var annotations = new Map();
160
+ var propsMap = new Map();
161
+ var pendingProps = [];
162
+
163
+ var walker = document.createTreeWalker(
164
+ document.documentElement,
165
+ NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_ELEMENT,
166
+ null
167
+ );
168
+
169
+ var node;
170
+ while (node = walker.nextNode()) {
171
+ if (node.nodeType === 8) {
172
+ var parsed = parsePropsPayload(node.textContent);
173
+ if (parsed) {
174
+ pendingProps.push(parsed);
175
+ }
176
+ } else if (node.nodeType === 1) {
177
+ if (pendingProps.length > 0 && node.hasAttribute('data-astro-source-file')) {
178
+ propsMap.set(node, pendingProps.slice());
179
+ pendingProps = [];
180
+ }
181
+ }
182
+ }
183
+
184
+ document.querySelectorAll('[data-astro-source-file]').forEach(function(el) {
185
+ var sourceFile = el.getAttribute('data-astro-source-file');
186
+ var annotation = {
187
+ file: sourceFile,
188
+ loc: el.getAttribute('data-astro-source-loc')
189
+ };
190
+
191
+ var propsChain = propsMap.get(el);
192
+
193
+ if (!propsChain) {
194
+ var parent = el.parentElement;
195
+ var maxSteps = 30;
196
+ while (parent && maxSteps-- > 0) {
197
+ propsChain = propsMap.get(parent);
198
+ if (propsChain) break;
199
+ parent = parent.parentElement;
200
+ }
201
+ }
202
+
203
+ if (propsChain && propsChain.length > 0) {
204
+ var match = null;
205
+ for (var i = 0; i < propsChain.length; i++) {
206
+ var entry = propsChain[i];
207
+ if (entry.moduleId) {
208
+ var entryFile = entry.moduleId.split('/').pop() || '';
209
+ var srcFile = sourceFile.split('/').pop() || '';
210
+ if (entryFile === srcFile && entryFile !== '') {
211
+ match = entry;
212
+ break;
213
+ }
214
+ }
215
+ }
216
+ if (!match) match = propsChain[0];
217
+
218
+ if (match) {
219
+ annotation.componentProps = match.props || null;
220
+ if (match.displayName) {
221
+ annotation.displayName = match.displayName;
222
+ }
223
+ }
224
+ }
225
+
226
+ annotations.set(el, annotation);
227
+ });
228
+
229
+ window.__frontman_annotations__ = {
230
+ _map: annotations,
231
+ get: function(el) { return annotations.get(el); },
232
+ has: function(el) { return annotations.has(el); },
233
+ size: function() { return annotations.size; }
234
+ };
235
+ }
236
+
237
+ document.addEventListener('DOMContentLoaded', captureAnnotations);
238
+
239
+ var initialLoad = true;
240
+ document.addEventListener('astro:page-load', function() {
241
+ if (initialLoad) { initialLoad = false; return; }
242
+ captureAnnotations();
243
+ });
244
+ })();`;
245
+
246
+ // src/vite-plugin-props-injection.mjs
247
+ function frontmanPropsInjectionPlugin() {
248
+ return {
249
+ name: "frontman:props-injection",
250
+ enforce: "pre",
251
+ apply: "serve",
252
+ // Only apply in SSR (server-side rendering) mode
253
+ transform(code, id, options) {
254
+ if (!options?.ssr) return null;
255
+ if (!id.includes("astro/dist/runtime/server/render/component") && !id.includes("astro/runtime/server/render/component")) {
256
+ return null;
257
+ }
258
+ if (!code.includes("function renderComponent(")) {
259
+ console.warn(
260
+ "[Frontman] Could not find renderComponent in Astro internals \u2014 component props injection will be disabled. This may happen after an Astro upgrade. File: " + id
261
+ );
262
+ return null;
263
+ }
264
+ let transformed = code.replace(
265
+ "function renderComponent(",
266
+ "function __original_renderComponent("
267
+ );
268
+ const wrapperCode = `
269
+
270
+ // --- Frontman props injection wrapper ---
271
+
272
+ function __frontman_safeSerialize(displayName, Component, props) {
273
+ try {
274
+ const clean = {};
275
+ for (const [key, value] of Object.entries(props || {})) {
276
+ // Skip internal Astro props (scoped CSS hashes)
277
+ if (key.startsWith('data-astro-cid-')) continue;
278
+ // Skip class (styling detail, not semantic)
279
+ if (key === 'class' || key === 'class:list') continue;
280
+
281
+ const t = typeof value;
282
+ if (t === 'string' || t === 'number' || t === 'boolean') {
283
+ clean[key] = value;
284
+ } else if (value === null || value === undefined) {
285
+ clean[key] = value;
286
+ } else if (Array.isArray(value)) {
287
+ try {
288
+ const serialized = JSON.stringify(value);
289
+ clean[key] = serialized.length < 1000 ? value : '[Array(' + value.length + ')]';
290
+ } catch {
291
+ clean[key] = '[Array]';
292
+ }
293
+ } else if (t === 'object') {
294
+ try {
295
+ const serialized = JSON.stringify(value);
296
+ clean[key] = serialized.length < 500 ? value : '{...}';
297
+ } catch {
298
+ clean[key] = '{...}';
299
+ }
300
+ }
301
+ // Skip functions, symbols, etc.
302
+ }
303
+
304
+ const entry = { displayName, props: clean };
305
+ // Include the component's moduleId (file path) if available
306
+ if (Component && Component.moduleId) {
307
+ entry.moduleId = Component.moduleId;
308
+ }
309
+ return JSON.stringify(entry);
310
+ } catch {
311
+ return null;
312
+ }
313
+ }
314
+
315
+ function __frontman_toBase64(str) {
316
+ if (typeof Buffer !== 'undefined') return Buffer.from(str, 'utf-8').toString('base64');
317
+ if (typeof btoa === 'function') return btoa(unescape(encodeURIComponent(str)));
318
+ return null;
319
+ }
320
+
321
+ function __frontman_wrapInstance(renderInstance, displayName, Component, props) {
322
+ // If no render method (e.g. fragment), pass through
323
+ if (!renderInstance || typeof renderInstance.render !== 'function') {
324
+ return renderInstance;
325
+ }
326
+
327
+ const serialized = __frontman_safeSerialize(displayName, Component, props);
328
+ if (!serialized) return renderInstance;
329
+
330
+ const encoded = __frontman_toBase64(serialized);
331
+ if (!encoded) return renderInstance;
332
+
333
+ const originalRender = renderInstance.render;
334
+
335
+ renderInstance.render = function(destination) {
336
+ // Write the props comment BEFORE the component renders.
337
+ // This creates a Comment node in the DOM immediately preceding
338
+ // the component's first rendered element.
339
+ // Guard: markHTMLString is assumed to be in scope from Astro's module.
340
+ // If it's missing (e.g., after an Astro upgrade), skip injection gracefully.
341
+ if (typeof markHTMLString === 'function') {
342
+ destination.write(markHTMLString('<!-- __frontman_props__:' + encoded + ' -->'));
343
+ }
344
+ return originalRender.call(renderInstance, destination);
345
+ };
346
+
347
+ return renderInstance;
348
+ }
349
+
350
+ function renderComponent(result, displayName, Component, props, slots) {
351
+ const renderInstance = __original_renderComponent(result, displayName, Component, props, slots);
352
+
353
+ // Handle promise (async component resolution)
354
+ if (renderInstance && typeof renderInstance.then === 'function') {
355
+ return renderInstance.then(function(resolved) {
356
+ return __frontman_wrapInstance(resolved, displayName, Component, props);
357
+ });
358
+ }
359
+
360
+ return __frontman_wrapInstance(renderInstance, displayName, Component, props);
361
+ }
362
+
363
+ // --- End Frontman props injection wrapper ---
364
+ `;
365
+ transformed += wrapperCode;
366
+ return {
367
+ code: transformed,
368
+ map: null
369
+ };
370
+ }
371
+ };
372
+ }
373
+
374
+ // ../../node_modules/@rescript/runtime/lib/es6/Primitive_int.js
375
+ function div(x, y) {
376
+ if (y === 0) {
377
+ throw {
378
+ RE_EXN_ID: "Division_by_zero",
379
+ Error: new Error()
380
+ };
381
+ }
382
+ return x / y | 0;
383
+ }
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
+ }
400
+ }
401
+ return result;
402
+ }
403
+
138
404
  // ../../node_modules/@rescript/runtime/lib/es6/Primitive_exceptions.js
139
405
  function isExtension(e) {
140
406
  if (e == null) {
@@ -275,9 +541,9 @@ function stringify(unknown2) {
275
541
  function toExpression(schema3) {
276
542
  let tag = schema3.type;
277
543
  let $$const = schema3.const;
278
- let name10 = schema3.name;
279
- if (name10 !== void 0) {
280
- return name10;
544
+ let name11 = schema3.name;
545
+ if (name11 !== void 0) {
546
+ return name11;
281
547
  }
282
548
  if ($$const !== void 0) {
283
549
  return stringify($$const);
@@ -1397,10 +1663,10 @@ function isPriority(tagFlag, byKey) {
1397
1663
  }
1398
1664
  }
1399
1665
  function isWiderUnionSchema(schemaAnyOf, inputAnyOf) {
1400
- return inputAnyOf.every((inputSchema9, idx) => {
1666
+ return inputAnyOf.every((inputSchema10, idx) => {
1401
1667
  let schema3 = schemaAnyOf[idx];
1402
- if (schema3 !== void 0 && !(flags[inputSchema9.type] & 9152) && inputSchema9.type === schema3.type) {
1403
- return inputSchema9.const === schema3.const;
1668
+ if (schema3 !== void 0 && !(flags[inputSchema10.type] & 9152) && inputSchema10.type === schema3.type) {
1669
+ return inputSchema10.const === schema3.const;
1404
1670
  } else {
1405
1671
  return false;
1406
1672
  }
@@ -2003,6 +2269,7 @@ var ctx = {
2003
2269
  function factory$4(definer) {
2004
2270
  return definitionToSchema(definer(ctx));
2005
2271
  }
2272
+ var js_schema = definitionToSchema;
2006
2273
  function option(item) {
2007
2274
  return factory$1(item, unit);
2008
2275
  }
@@ -2242,8 +2509,10 @@ function toJSONSchema(schema3) {
2242
2509
  }
2243
2510
  return jsonSchema;
2244
2511
  }
2512
+ var literal = js_schema;
2245
2513
  var array = factory$2;
2246
2514
  var dict = factory$3;
2515
+ var union = factory;
2247
2516
  var schema = factory$4;
2248
2517
 
2249
2518
  // ../../node_modules/sury/src/S.res.mjs
@@ -2251,11 +2520,14 @@ var $$Error2 = $$Error;
2251
2520
  var string2 = string;
2252
2521
  var bool2 = bool;
2253
2522
  var int2 = int;
2523
+ var float2 = float;
2254
2524
  var json2 = json;
2255
2525
  var enableJson2 = enableJson;
2526
+ var literal2 = literal;
2256
2527
  var array2 = array;
2257
2528
  var dict2 = dict;
2258
2529
  var option2 = option;
2530
+ var union2 = union;
2259
2531
  var parseOrThrow2 = parseOrThrow;
2260
2532
  var reverseConvertToJsonOrThrow2 = reverseConvertToJsonOrThrow;
2261
2533
  var schema2 = schema;
@@ -2277,7 +2549,7 @@ function string3(json3) {
2277
2549
  return json3;
2278
2550
  }
2279
2551
  }
2280
- function float2(json3) {
2552
+ function float3(json3) {
2281
2553
  if (typeof json3 === "number") {
2282
2554
  return json3;
2283
2555
  }
@@ -2296,7 +2568,7 @@ var Decode = {
2296
2568
  bool: bool3,
2297
2569
  $$null: $$null2,
2298
2570
  string: string3,
2299
- float: float2,
2571
+ float: float3,
2300
2572
  object: object2,
2301
2573
  array: array3
2302
2574
  };
@@ -4000,6 +4272,21 @@ function reduce(arr, init, f) {
4000
4272
  function reduceWithIndex(arr, init, f) {
4001
4273
  return arr.reduce(f, init);
4002
4274
  }
4275
+ function filterMap(a, f) {
4276
+ let l = a.length;
4277
+ let r = new Array(l);
4278
+ let j2 = 0;
4279
+ for (let i = 0; i < l; ++i) {
4280
+ let v = a[i];
4281
+ let v$1 = f(v);
4282
+ if (v$1 !== void 0) {
4283
+ r[j2] = valFromOption(v$1);
4284
+ j2 = j2 + 1 | 0;
4285
+ }
4286
+ }
4287
+ r.length = j2;
4288
+ return r;
4289
+ }
4003
4290
 
4004
4291
  // ../../node_modules/@rescript/runtime/lib/es6/Stdlib_Int.js
4005
4292
  function fromString2(x, radix) {
@@ -4010,69 +4297,160 @@ function fromString2(x, radix) {
4010
4297
  return maybeInt | 0;
4011
4298
  }
4012
4299
  }
4013
-
4014
- // ../bindings/src/ChildProcess.res.mjs
4015
- var execPromise = (async function(command, options) {
4016
- const { exec: exec2 } = await import('child_process');
4017
- const { promisify } = await import('util');
4018
- const execP = promisify(exec2);
4019
- return await execP(command, options);
4020
- });
4021
- var bufferToString = (function(value) {
4022
- if (value == null) return "";
4023
- if (typeof value === "string") return value;
4024
- if (Buffer.isBuffer(value)) return value.toString("utf8");
4025
- return String(value);
4026
- });
4027
- async function exec(command) {
4028
- try {
4029
- let result = await execPromise(command, {
4030
- maxBuffer: 52428800
4031
- });
4032
- return {
4033
- TAG: "Ok",
4034
- _0: {
4035
- stdout: bufferToString(result.stdout),
4036
- stderr: bufferToString(result.stderr)
4300
+ function execPromise(command, options) {
4301
+ return new Promise((resolve3, _reject) => {
4302
+ let cwd = options.cwd;
4303
+ let env = options.env;
4304
+ let maxBuffer = getOr(options.maxBuffer, 52428800);
4305
+ Nodechild_process.exec(command, {
4306
+ cwd,
4307
+ env,
4308
+ maxBuffer,
4309
+ encoding: "utf8"
4310
+ }, (err, stdout, stderr) => {
4311
+ if (err == null) {
4312
+ return resolve3({
4313
+ TAG: "Ok",
4314
+ _0: {
4315
+ stdout,
4316
+ stderr
4317
+ }
4318
+ });
4319
+ } else {
4320
+ return resolve3({
4321
+ TAG: "Error",
4322
+ _0: {
4323
+ code: fromNullable(err.code),
4324
+ stdout,
4325
+ stderr,
4326
+ message: err.message
4327
+ }
4328
+ });
4037
4329
  }
4330
+ });
4331
+ });
4332
+ }
4333
+ function spawnPromise(command, args, options) {
4334
+ let maxBuffer = getOr(options.maxBuffer, 52428800);
4335
+ return new Promise((resolve3, _reject) => {
4336
+ let cwd = options.cwd;
4337
+ let env = options.env;
4338
+ let proc = Nodechild_process.spawn(command, args, {
4339
+ cwd,
4340
+ env
4341
+ });
4342
+ let stdoutChunks = {
4343
+ contents: []
4038
4344
  };
4039
- } catch (raw_exn) {
4040
- let exn = internalToException(raw_exn);
4041
- let actualError = getOr(fromNullable(exn._1), exn);
4042
- return {
4043
- TAG: "Error",
4044
- _0: {
4045
- code: fromNullable(actualError.code),
4046
- stdout: getOr(map(fromNullable(actualError.stdout), bufferToString), ""),
4047
- stderr: getOr(map(fromNullable(actualError.stderr), bufferToString), "")
4048
- }
4345
+ let stderrChunks = {
4346
+ contents: []
4049
4347
  };
4050
- }
4051
- }
4052
- async function execWithOptions(command, options) {
4053
- try {
4054
- let newrecord = { ...options };
4055
- newrecord.maxBuffer = getOr(options.maxBuffer, 52428800);
4056
- let result = await execPromise(command, newrecord);
4057
- return {
4058
- TAG: "Ok",
4059
- _0: {
4060
- stdout: bufferToString(result.stdout),
4061
- stderr: bufferToString(result.stderr)
4348
+ let stdoutLen = {
4349
+ contents: 0
4350
+ };
4351
+ let stderrLen = {
4352
+ contents: 0
4353
+ };
4354
+ let resolved = {
4355
+ contents: false
4356
+ };
4357
+ let guardedResolve = (value) => {
4358
+ if (resolved.contents) {
4359
+ return;
4360
+ } else {
4361
+ resolved.contents = true;
4362
+ return resolve3(value);
4062
4363
  }
4063
4364
  };
4064
- } catch (raw_exn) {
4065
- let exn = internalToException(raw_exn);
4066
- let actualError = getOr(fromNullable(exn._1), exn);
4067
- return {
4365
+ proc.stdout.on("data", (chunk) => {
4366
+ if (resolved.contents) {
4367
+ return;
4368
+ } else {
4369
+ stdoutChunks.contents.push(chunk);
4370
+ stdoutLen.contents = stdoutLen.contents + chunk.byteLength | 0;
4371
+ if (stdoutLen.contents > maxBuffer) {
4372
+ proc.kill("SIGTERM");
4373
+ return guardedResolve({
4374
+ TAG: "Error",
4375
+ _0: {
4376
+ code: void 0,
4377
+ stdout: Nodebuffer.Buffer.concat(stdoutChunks.contents).toString("utf8"),
4378
+ stderr: Nodebuffer.Buffer.concat(stderrChunks.contents).toString("utf8"),
4379
+ message: "stdout maxBuffer exceeded"
4380
+ }
4381
+ });
4382
+ } else {
4383
+ return;
4384
+ }
4385
+ }
4386
+ });
4387
+ proc.stderr.on("data", (chunk) => {
4388
+ if (resolved.contents) {
4389
+ return;
4390
+ } else {
4391
+ stderrChunks.contents.push(chunk);
4392
+ stderrLen.contents = stderrLen.contents + chunk.byteLength | 0;
4393
+ if (stderrLen.contents > maxBuffer) {
4394
+ proc.kill("SIGTERM");
4395
+ return guardedResolve({
4396
+ TAG: "Error",
4397
+ _0: {
4398
+ code: void 0,
4399
+ stdout: Nodebuffer.Buffer.concat(stdoutChunks.contents).toString("utf8"),
4400
+ stderr: Nodebuffer.Buffer.concat(stderrChunks.contents).toString("utf8"),
4401
+ message: "stderr maxBuffer exceeded"
4402
+ }
4403
+ });
4404
+ } else {
4405
+ return;
4406
+ }
4407
+ }
4408
+ });
4409
+ proc.on("error", (err) => guardedResolve({
4068
4410
  TAG: "Error",
4069
4411
  _0: {
4070
- code: fromNullable(actualError.code),
4071
- stdout: getOr(map(fromNullable(actualError.stdout), bufferToString), ""),
4072
- stderr: getOr(map(fromNullable(actualError.stderr), bufferToString), "")
4412
+ code: void 0,
4413
+ stdout: Nodebuffer.Buffer.concat(stdoutChunks.contents).toString("utf8"),
4414
+ stderr: Nodebuffer.Buffer.concat(stderrChunks.contents).toString("utf8"),
4415
+ message: err.message
4073
4416
  }
4074
- };
4075
- }
4417
+ }));
4418
+ proc.on("close", (nullableCode) => {
4419
+ let code = nullableCode == null ? void 0 : some(nullableCode);
4420
+ if (!(nullableCode == null) && nullableCode === 0) {
4421
+ return guardedResolve({
4422
+ TAG: "Ok",
4423
+ _0: {
4424
+ stdout: Nodebuffer.Buffer.concat(stdoutChunks.contents).toString("utf8"),
4425
+ stderr: Nodebuffer.Buffer.concat(stderrChunks.contents).toString("utf8")
4426
+ }
4427
+ });
4428
+ }
4429
+ let codeStr = nullableCode == null ? "null" : nullableCode.toString();
4430
+ guardedResolve({
4431
+ TAG: "Error",
4432
+ _0: {
4433
+ code,
4434
+ stdout: Nodebuffer.Buffer.concat(stdoutChunks.contents).toString("utf8"),
4435
+ stderr: Nodebuffer.Buffer.concat(stderrChunks.contents).toString("utf8"),
4436
+ message: `Process exited with code ` + codeStr
4437
+ }
4438
+ });
4439
+ });
4440
+ });
4441
+ }
4442
+ async function execWithOptions(command, options) {
4443
+ let newrecord = { ...options };
4444
+ newrecord.maxBuffer = getOr(options.maxBuffer, 52428800);
4445
+ return await execPromise(command, newrecord);
4446
+ }
4447
+ async function spawnResult(command, args, cwd) {
4448
+ let options_maxBuffer = 52428800;
4449
+ let options = {
4450
+ cwd,
4451
+ maxBuffer: options_maxBuffer
4452
+ };
4453
+ return await spawnPromise(command, args, options);
4076
4454
  }
4077
4455
  function resolve(sourceRoot, inputPath) {
4078
4456
  let normalizedRoot = Nodepath.normalize(sourceRoot);
@@ -4189,7 +4567,18 @@ Hint: ` + hint;
4189
4567
  }
4190
4568
  }
4191
4569
 
4570
+ // ../frontman-protocol/src/FrontmanProtocol__Tool.res.mjs
4571
+ var ToolNames = {
4572
+ writeFile: "write_file",
4573
+ readFile: "read_file",
4574
+ listFiles: "list_files",
4575
+ searchFiles: "search_files",
4576
+ grep: "grep",
4577
+ fileExists: "file_exists",
4578
+ loadAgentInstructions: "load_agent_instructions"};
4579
+
4192
4580
  // ../frontman-core/src/tools/FrontmanCore__Tool__Grep.res.mjs
4581
+ var name2 = ToolNames.grep;
4193
4582
  var inputSchema = schema2((s2) => ({
4194
4583
  pattern: s2.m(string2),
4195
4584
  path: s2.m(option2(string2)),
@@ -4220,14 +4609,14 @@ function getRipgrepPath() {
4220
4609
  return;
4221
4610
  }
4222
4611
  }
4223
- function buildRipgrepArgs(pattern2, searchPath, type_, glob, caseInsensitive, literal2, maxResults) {
4612
+ function buildRipgrepArgs(pattern2, searchPath, type_, glob, caseInsensitive, literal3, maxResults) {
4224
4613
  let args = [];
4225
4614
  args.push("-n");
4226
4615
  args.push("-H");
4227
4616
  if (caseInsensitive) {
4228
4617
  args.push("-i");
4229
4618
  }
4230
- if (literal2) {
4619
+ if (literal3) {
4231
4620
  args.push("-F");
4232
4621
  }
4233
4622
  args.push("-m");
@@ -4244,7 +4633,7 @@ function buildRipgrepArgs(pattern2, searchPath, type_, glob, caseInsensitive, li
4244
4633
  args.push(searchPath);
4245
4634
  return args;
4246
4635
  }
4247
- function buildGitGrepArgs(pattern2, caseInsensitive, literal2, maxResults) {
4636
+ function buildGitGrepArgs(pattern2, caseInsensitive, literal3, maxResults, glob, type_) {
4248
4637
  let args = [
4249
4638
  "grep",
4250
4639
  "-n",
@@ -4253,12 +4642,22 @@ function buildGitGrepArgs(pattern2, caseInsensitive, literal2, maxResults) {
4253
4642
  if (caseInsensitive) {
4254
4643
  args.push("-i");
4255
4644
  }
4256
- if (literal2) {
4645
+ if (literal3) {
4257
4646
  args.push("-F");
4258
4647
  }
4259
4648
  args.push("--max-count");
4260
4649
  args.push(maxResults.toString());
4261
4650
  args.push(pattern2);
4651
+ let hasPathspec = isSome(glob) || isSome(type_);
4652
+ if (hasPathspec) {
4653
+ args.push("--");
4654
+ if (glob !== void 0) {
4655
+ args.push(glob);
4656
+ }
4657
+ if (type_ !== void 0 && glob === void 0) {
4658
+ args.push(`*.` + type_);
4659
+ }
4660
+ }
4262
4661
  return args;
4263
4662
  }
4264
4663
  function parseGrepOutput(output, maxResults) {
@@ -4293,122 +4692,154 @@ function parseGrepOutput(output, maxResults) {
4293
4692
  });
4294
4693
  fileMap[filePath] = matches2;
4295
4694
  });
4296
- let files = Object.entries(fileMap).map((param) => ({
4695
+ let allFiles = Object.entries(fileMap).map((param) => ({
4297
4696
  path: param[0],
4298
4697
  matches: param[1]
4299
- })).slice(0, maxResults);
4698
+ }));
4699
+ let totalFiles = allFiles.length;
4700
+ let files = allFiles.slice(0, maxResults);
4300
4701
  return {
4301
4702
  files,
4302
4703
  totalMatches: totalMatches.contents,
4303
- truncated: totalMatches.contents > maxResults
4704
+ truncated: totalFiles > maxResults
4304
4705
  };
4305
4706
  }
4306
- async function executeRipgrep(rgPath, pattern2, searchPath, type_, glob, caseInsensitive, literal2, maxResults) {
4307
- let args = buildRipgrepArgs(pattern2, searchPath, type_, glob, caseInsensitive, literal2, maxResults);
4308
- let command = rgPath + ` ` + args.join(" ");
4309
- try {
4310
- let result = await exec(command);
4311
- if (result.TAG === "Ok") {
4312
- return {
4313
- TAG: "Ok",
4314
- _0: parseGrepOutput(result._0.stdout, maxResults)
4315
- };
4316
- }
4317
- let match = result._0;
4318
- let match$1 = match.code;
4319
- let exit = 0;
4320
- if (match$1 !== void 0) {
4321
- if (match$1 === 1) {
4322
- return {
4323
- TAG: "Ok",
4324
- _0: {
4325
- files: [],
4326
- totalMatches: 0,
4327
- truncated: false
4328
- }
4329
- };
4707
+ async function executeRipgrep(rgPath, pattern2, searchPath, type_, glob, caseInsensitive, literal3, maxResults) {
4708
+ let args = buildRipgrepArgs(pattern2, searchPath, type_, glob, caseInsensitive, literal3, maxResults);
4709
+ let result = await spawnResult(rgPath, args, void 0);
4710
+ if (result.TAG === "Ok") {
4711
+ return {
4712
+ TAG: "Ok",
4713
+ _0: parseGrepOutput(result._0.stdout, maxResults)
4714
+ };
4715
+ }
4716
+ let match = result._0;
4717
+ let match$1 = match.code;
4718
+ if (match$1 === 1) {
4719
+ return {
4720
+ TAG: "Ok",
4721
+ _0: {
4722
+ files: [],
4723
+ totalMatches: 0,
4724
+ truncated: false
4330
4725
  }
4331
- exit = 1;
4332
- } else {
4333
- exit = 1;
4334
- }
4335
- if (exit === 1) {
4336
- return {
4337
- TAG: "Error",
4338
- _0: `Ripgrep failed: ` + match.stderr
4339
- };
4340
- }
4341
- } catch (raw_exn) {
4342
- let exn = internalToException(raw_exn);
4343
- let msg = getOr(flatMap(fromException(exn), message2), "Unknown error");
4726
+ };
4727
+ }
4728
+ let stderr = match.stderr;
4729
+ let detail = stderr === "" ? match.message : stderr;
4730
+ return {
4731
+ TAG: "Error",
4732
+ _0: `Ripgrep failed: ` + detail
4733
+ };
4734
+ }
4735
+ async function executeGitGrep(pattern2, searchPath, caseInsensitive, literal3, maxResults, glob, type_) {
4736
+ let args = buildGitGrepArgs(pattern2, caseInsensitive, literal3, maxResults, glob, type_);
4737
+ let result = await spawnResult("git", args, searchPath);
4738
+ if (result.TAG === "Ok") {
4344
4739
  return {
4345
- TAG: "Error",
4346
- _0: `Ripgrep execution failed: ` + msg
4740
+ TAG: "Ok",
4741
+ _0: parseGrepOutput(result._0.stdout, maxResults)
4742
+ };
4743
+ }
4744
+ let match = result._0;
4745
+ let code = match.code;
4746
+ if (code === 1) {
4747
+ return {
4748
+ TAG: "Ok",
4749
+ _0: {
4750
+ files: [],
4751
+ totalMatches: 0,
4752
+ truncated: false
4753
+ }
4347
4754
  };
4348
4755
  }
4756
+ let stderr = match.stderr;
4757
+ let codeStr = getOr(map(code, (c2) => c2.toString()), "unknown");
4758
+ let detail = stderr === "" ? match.message : stderr;
4759
+ return {
4760
+ TAG: "Error",
4761
+ _0: `Git grep failed (exit ` + codeStr + `): ` + detail
4762
+ };
4349
4763
  }
4350
- async function executeGitGrep(pattern2, searchPath, caseInsensitive, literal2, maxResults) {
4351
- let args = buildGitGrepArgs(pattern2, caseInsensitive, literal2, maxResults);
4352
- try {
4353
- let result = await execWithOptions(`git ` + args.join(" "), {
4354
- cwd: searchPath
4355
- });
4356
- if (result.TAG === "Ok") {
4357
- return {
4358
- TAG: "Ok",
4359
- _0: parseGrepOutput(result._0.stdout, maxResults)
4360
- };
4361
- }
4362
- let match = result._0;
4363
- let match$1 = match.code;
4364
- let exit = 0;
4365
- if (match$1 !== void 0) {
4366
- if (match$1 === 1) {
4367
- return {
4368
- TAG: "Ok",
4369
- _0: {
4370
- files: [],
4371
- totalMatches: 0,
4372
- truncated: false
4373
- }
4374
- };
4375
- }
4376
- exit = 1;
4377
- } else {
4378
- exit = 1;
4379
- }
4380
- if (exit === 1) {
4381
- return {
4382
- TAG: "Error",
4383
- _0: `Git grep failed: ` + match.stderr
4384
- };
4385
- }
4386
- } catch (raw_exn) {
4387
- let exn = internalToException(raw_exn);
4388
- let msg = getOr(flatMap(fromException(exn), message2), "Unknown error");
4764
+ function buildPlainGrepArgs(pattern2, searchPath, caseInsensitive, literal3, maxResults, glob, type_) {
4765
+ let args = ["-rn"];
4766
+ if (caseInsensitive) {
4767
+ args.push("-i");
4768
+ }
4769
+ if (literal3) {
4770
+ args.push("-F");
4771
+ }
4772
+ args.push("-m");
4773
+ args.push(maxResults.toString());
4774
+ if (glob !== void 0) {
4775
+ args.push("--include");
4776
+ args.push(glob);
4777
+ } else if (type_ !== void 0) {
4778
+ args.push("--include");
4779
+ args.push(`*.` + type_);
4780
+ }
4781
+ args.push("--exclude-dir=node_modules");
4782
+ args.push("--exclude-dir=.git");
4783
+ args.push("--exclude-dir=dist");
4784
+ args.push("--exclude-dir=build");
4785
+ args.push("--exclude-dir=_build");
4786
+ args.push(pattern2);
4787
+ args.push(searchPath);
4788
+ return args;
4789
+ }
4790
+ async function executePlainGrep(pattern2, searchPath, caseInsensitive, literal3, maxResults, glob, type_) {
4791
+ let args = buildPlainGrepArgs(pattern2, searchPath, caseInsensitive, literal3, maxResults, glob, type_);
4792
+ let result = await spawnResult("grep", args, void 0);
4793
+ if (result.TAG === "Ok") {
4389
4794
  return {
4390
- TAG: "Error",
4391
- _0: `Git grep execution failed: ` + msg
4795
+ TAG: "Ok",
4796
+ _0: parseGrepOutput(result._0.stdout, maxResults)
4392
4797
  };
4393
4798
  }
4799
+ let match = result._0;
4800
+ let code = match.code;
4801
+ if (code === 1) {
4802
+ return {
4803
+ TAG: "Ok",
4804
+ _0: {
4805
+ files: [],
4806
+ totalMatches: 0,
4807
+ truncated: false
4808
+ }
4809
+ };
4810
+ }
4811
+ let stderr = match.stderr;
4812
+ let codeStr = getOr(map(code, (c2) => c2.toString()), "unknown");
4813
+ let detail = stderr === "" ? match.message : stderr;
4814
+ return {
4815
+ TAG: "Error",
4816
+ _0: `Grep failed (exit ` + codeStr + `): ` + detail
4817
+ };
4394
4818
  }
4395
4819
  async function execute(ctx2, input) {
4396
4820
  let searchPath = resolveSearchPath(ctx2.sourceRoot, input.path);
4397
4821
  let caseInsensitive = getOr(input.case_insensitive, false);
4398
- let literal2 = getOr(input.literal, false);
4399
- let maxResults = getOr(input.max_results, 100);
4822
+ let literal3 = getOr(input.literal, false);
4823
+ let maxResults = getOr(input.max_results, 20);
4824
+ let gitGrepWithFallback = async () => {
4825
+ let gitResult = await executeGitGrep(input.pattern, searchPath, caseInsensitive, literal3, maxResults, input.glob, input.type);
4826
+ if (gitResult.TAG === "Ok") {
4827
+ return gitResult;
4828
+ } else {
4829
+ return await executePlainGrep(input.pattern, searchPath, caseInsensitive, literal3, maxResults, input.glob, input.type);
4830
+ }
4831
+ };
4400
4832
  let rgPath = getRipgrepPath();
4401
4833
  if (rgPath === void 0) {
4402
- return await executeGitGrep(input.pattern, searchPath, caseInsensitive, literal2, maxResults);
4834
+ return await gitGrepWithFallback();
4403
4835
  }
4404
- let result = await executeRipgrep(rgPath, input.pattern, searchPath, input.type, input.glob, caseInsensitive, literal2, maxResults);
4836
+ let result = await executeRipgrep(rgPath, input.pattern, searchPath, input.type, input.glob, caseInsensitive, literal3, maxResults);
4405
4837
  if (result.TAG === "Ok") {
4406
4838
  return result;
4407
4839
  } else {
4408
- return await executeGitGrep(input.pattern, searchPath, caseInsensitive, literal2, maxResults);
4840
+ return await gitGrepWithFallback();
4409
4841
  }
4410
4842
  }
4411
- var name2 = "grep";
4412
4843
  var description = `Fast content search tool that finds files containing specific text or patterns, returning matching lines sorted by file modification time.
4413
4844
 
4414
4845
  WHEN TO USE THIS TOOL:
@@ -4439,6 +4870,7 @@ LIMITATIONS:
4439
4870
  - Results limited to max_results (default 20)
4440
4871
  - Binary files are automatically skipped
4441
4872
  - Hidden files (starting with '.') are skipped by default`;
4873
+ var name3 = ToolNames.readFile;
4442
4874
  var inputSchema2 = schema2((s2) => ({
4443
4875
  path: s2.m(string2),
4444
4876
  offset: s2.m(option2(int2)),
@@ -4467,7 +4899,7 @@ async function execute2(ctx2, input) {
4467
4899
  }
4468
4900
  let result = err._0;
4469
4901
  try {
4470
- let content = await Fs2.promises.readFile(result.resolvedPath, "utf8");
4902
+ let content = await Fs3.promises.readFile(result.resolvedPath, "utf8");
4471
4903
  let lines = content.split("\n");
4472
4904
  let totalLines = lines.length;
4473
4905
  let selectedLines = lines.slice(offset, offset + limit | 0);
@@ -4495,7 +4927,6 @@ async function execute2(ctx2, input) {
4495
4927
  };
4496
4928
  }
4497
4929
  }
4498
- var name3 = "read_file";
4499
4930
  var description2 = `Reads a file from the filesystem.
4500
4931
 
4501
4932
  Parameters:
@@ -4519,6 +4950,7 @@ function map3(opt, f) {
4519
4950
  }
4520
4951
 
4521
4952
  // ../frontman-core/src/tools/FrontmanCore__Tool__ListFiles.res.mjs
4953
+ var name4 = ToolNames.listFiles;
4522
4954
  var inputSchema3 = schema2((s2) => ({
4523
4955
  path: s2.m(option2(string2))
4524
4956
  }));
@@ -4594,20 +5026,20 @@ async function execute3(ctx2, input) {
4594
5026
  }
4595
5027
  try {
4596
5028
  let fullPath = err._0.resolvedPath;
4597
- let entries = await Fs2.promises.readdir(fullPath);
4598
- let filteredEntriesResult = map3(await getIgnoredEntries(fullPath, entries), (ignored) => entries.filter((name10) => !ignored.includes(name10)));
5029
+ let entries = await Fs3.promises.readdir(fullPath);
5030
+ let filteredEntriesResult = map3(await getIgnoredEntries(fullPath, entries), (ignored) => entries.filter((name11) => !ignored.includes(name11)));
4599
5031
  if (filteredEntriesResult.TAG !== "Ok") {
4600
5032
  return {
4601
5033
  TAG: "Error",
4602
5034
  _0: filteredEntriesResult._0
4603
5035
  };
4604
5036
  }
4605
- let entriesWithStats = await Promise.all(filteredEntriesResult._0.map(async (name10) => {
4606
- let entryPath = Nodepath.join(fullPath, name10);
4607
- let stats = await Fs2.promises.stat(entryPath);
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);
4608
5040
  return {
4609
- name: name10,
4610
- path: Nodepath.join(path, name10),
5041
+ name: name11,
5042
+ path: Nodepath.join(path, name11),
4611
5043
  isFile: stats.isFile(),
4612
5044
  isDirectory: stats.isDirectory()
4613
5045
  };
@@ -4625,16 +5057,18 @@ async function execute3(ctx2, input) {
4625
5057
  };
4626
5058
  }
4627
5059
  }
4628
- var name4 = "list_files";
4629
5060
  var description3 = `Lists files and directories in a given path.
4630
5061
 
4631
5062
  Parameters:
4632
5063
  - path (optional): Path to directory - either relative to source root or absolute (must be under source root). Defaults to "." (root directory).
4633
5064
 
4634
5065
  Returns array of entries with name, path, and type information.`;
5066
+ var name5 = ToolNames.writeFile;
4635
5067
  var inputSchema4 = schema2((s2) => ({
4636
5068
  path: s2.m(string2),
4637
- content: s2.m(string2)
5069
+ content: s2.m(option2(string2)),
5070
+ image_ref: s2.m(option2(string2)),
5071
+ encoding: s2.m(option2(literal2("base64")))
4638
5072
  }));
4639
5073
  var pathContextSchema2 = schema2((s2) => ({
4640
5074
  sourceRoot: s2.m(string2),
@@ -4644,7 +5078,35 @@ var pathContextSchema2 = schema2((s2) => ({
4644
5078
  var outputSchema4 = schema2((s2) => ({
4645
5079
  _context: s2.m(option2(pathContextSchema2))
4646
5080
  }));
5081
+ function writeContent(resolvedPath, content, encoding) {
5082
+ if (encoding === void 0) {
5083
+ return Fs3.promises.writeFile(resolvedPath, content, "utf8");
5084
+ }
5085
+ let buffer = Nodebuffer.Buffer.from(content, "base64");
5086
+ return Fs3.promises.writeFile(resolvedPath, buffer);
5087
+ }
4647
5088
  async function execute4(ctx2, input) {
5089
+ let match = input.content;
5090
+ let match$1 = input.image_ref;
5091
+ if (match === void 0) {
5092
+ if (match$1 !== void 0) {
5093
+ return {
5094
+ TAG: "Error",
5095
+ _0: "image_ref must be resolved to content before execution"
5096
+ };
5097
+ } else {
5098
+ return {
5099
+ TAG: "Error",
5100
+ _0: "Either content or image_ref must be provided"
5101
+ };
5102
+ }
5103
+ }
5104
+ if (match$1 !== void 0) {
5105
+ return {
5106
+ TAG: "Error",
5107
+ _0: "Provide either content or image_ref, not both"
5108
+ };
5109
+ }
4648
5110
  let err = resolve2(ctx2.sourceRoot, input.path);
4649
5111
  if (err.TAG !== "Ok") {
4650
5112
  return {
@@ -4653,12 +5115,11 @@ async function execute4(ctx2, input) {
4653
5115
  };
4654
5116
  }
4655
5117
  let result = err._0;
4656
- let dirPath = dirname3(result);
4657
5118
  try {
4658
- await Fs2.promises.mkdir(dirPath, {
5119
+ await Fs3.promises.mkdir(dirname3(result), {
4659
5120
  recursive: true
4660
5121
  });
4661
- await Fs2.promises.writeFile(result.resolvedPath, input.content, "utf8");
5122
+ await writeContent(result.resolvedPath, match, input.encoding);
4662
5123
  return {
4663
5124
  TAG: "Ok",
4664
5125
  _0: {
@@ -4678,15 +5139,18 @@ async function execute4(ctx2, input) {
4678
5139
  };
4679
5140
  }
4680
5141
  }
4681
- var name5 = "write_file";
4682
5142
  var description4 = `Writes content to a file.
4683
5143
 
4684
5144
  Parameters:
4685
5145
  - path (required): Path to file - either relative to source root or absolute (must be under source root)
4686
- - content (required): Content to write
5146
+ - content: Text content to write (mutually exclusive with image_ref)
5147
+ - image_ref: URI of a user-attached image to save (e.g., "attachment://att_abc123/photo.png"). Use this to save images the user has pasted into the chat. Mutually exclusive with content.
5148
+ - encoding: Set to "base64" when writing binary data (used internally when image_ref is resolved)
4687
5149
 
5150
+ Provide either content OR image_ref, not both.
4688
5151
  Creates parent directories if they don't exist. Overwrites existing files.
4689
5152
  The _context field provides path resolution details for debugging.`;
5153
+ var name6 = ToolNames.fileExists;
4690
5154
  var inputSchema5 = schema2((s2) => ({
4691
5155
  path: s2.m(string2)
4692
5156
  }));
@@ -4699,7 +5163,7 @@ async function execute5(ctx2, input) {
4699
5163
  };
4700
5164
  }
4701
5165
  try {
4702
- await Fs2.promises.access(toString(msg._0));
5166
+ await Fs3.promises.access(toString(msg._0));
4703
5167
  return {
4704
5168
  TAG: "Ok",
4705
5169
  _0: true
@@ -4711,7 +5175,6 @@ async function execute5(ctx2, input) {
4711
5175
  };
4712
5176
  }
4713
5177
  }
4714
- var name6 = "file_exists";
4715
5178
  var description5 = `Checks if a file or directory exists.
4716
5179
 
4717
5180
  Parameters:
@@ -4719,13 +5182,294 @@ Parameters:
4719
5182
 
4720
5183
  Returns true if the path exists, false otherwise.`;
4721
5184
  var outputSchema5 = bool2;
5185
+
5186
+ // ../bindings/src/Lighthouse.res.mjs
5187
+ var run = ((url2, flags2) => import('module').then(({ createRequire }) => {
5188
+ const req = createRequire(import.meta.url);
5189
+ try {
5190
+ const mod = req("lighthouse");
5191
+ const lighthouse = mod.default ?? mod;
5192
+ return lighthouse(url2, flags2);
5193
+ } catch (e) {
5194
+ if (e.code === "MODULE_NOT_FOUND") {
5195
+ throw new Error("lighthouse is not installed. Run: npm install lighthouse");
5196
+ }
5197
+ throw e;
5198
+ }
5199
+ }));
5200
+
5201
+ // ../bindings/src/ChromeLauncher.res.mjs
5202
+ var launch = ((options) => import('module').then(({ createRequire }) => {
5203
+ const req = createRequire(import.meta.url);
5204
+ try {
5205
+ const mod = req("chrome-launcher");
5206
+ return mod.launch(options);
5207
+ } catch (e) {
5208
+ if (e.code === "MODULE_NOT_FOUND") {
5209
+ throw new Error("chrome-launcher is not installed. Run: npm install chrome-launcher");
5210
+ }
5211
+ throw e;
5212
+ }
5213
+ }));
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;
5225
+ 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:");
5245
+ }
5246
+ return url2;
5247
+ });
4722
5248
  var inputSchema6 = schema2((s2) => ({
5249
+ url: s2.m(string2),
5250
+ preset: s2.m(option2(string2))
5251
+ }));
5252
+ var auditIssueSchema = schema2((s2) => ({
5253
+ id: s2.m(string2),
5254
+ title: s2.m(string2),
5255
+ description: s2.m(string2),
5256
+ score: s2.m(float2),
5257
+ displayValue: s2.m(option2(string2))
5258
+ }));
5259
+ var categoryResultSchema = schema2((s2) => ({
5260
+ id: s2.m(string2),
5261
+ title: s2.m(string2),
5262
+ score: s2.m(int2),
5263
+ topIssues: s2.m(array2(auditIssueSchema))
5264
+ }));
5265
+ var outputSchema6 = schema2((s2) => ({
5266
+ url: s2.m(string2),
5267
+ fetchTime: s2.m(string2),
5268
+ categories: s2.m(array2(categoryResultSchema)),
5269
+ overallScore: s2.m(int2),
5270
+ warnings: s2.m(array2(string2))
5271
+ }));
5272
+ var categoryIds = [
5273
+ "performance",
5274
+ "accessibility",
5275
+ "best-practices",
5276
+ "seo"
5277
+ ];
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
+ function getTopIssues(category, audits, maxIssues) {
5294
+ return filterMap(category.auditRefs, (ref) => audits[ref.id]).filter((audit) => {
5295
+ let score = audit.score;
5296
+ if (!(score == null) && (audit.scoreDisplayMode === "binary" || audit.scoreDisplayMode === "numeric" || audit.scoreDisplayMode === "metricSavings")) {
5297
+ return score < 1;
5298
+ } else {
5299
+ return false;
5300
+ }
5301
+ }).toSorted((a, b) => {
5302
+ let scoreA = getOr(fromNullable(a.score), 0);
5303
+ let scoreB = getOr(fromNullable(b.score), 0);
5304
+ return scoreA - scoreB;
5305
+ }).slice(0, maxIssues).map((audit) => ({
5306
+ id: audit.id,
5307
+ title: audit.title,
5308
+ description: audit.description,
5309
+ score: getOr(fromNullable(audit.score), 0),
5310
+ displayValue: audit.displayValue
5311
+ }));
5312
+ }
5313
+ function processLhr(lhr) {
5314
+ let categories = filterMap(categoryIds, (id) => lhr.categories[id]).map((category) => {
5315
+ let s2 = category.score;
5316
+ let score = !(s2 == null) ? Math.round(s2 * 100) | 0 : 0;
5317
+ let topIssues = getTopIssues(category, lhr.audits, 3);
5318
+ return {
5319
+ id: category.id,
5320
+ title: category.title,
5321
+ score,
5322
+ topIssues
5323
+ };
5324
+ });
5325
+ let totalScore = reduce(categories, 0, (acc, cat) => acc + cat.score | 0);
5326
+ let len = categories.length;
5327
+ let overallScore = len !== 0 ? div(totalScore, len) : 0;
5328
+ return {
5329
+ url: lhr.finalDisplayedUrl,
5330
+ fetchTime: lhr.fetchTime,
5331
+ categories,
5332
+ overallScore,
5333
+ warnings: lhr.runWarnings
5334
+ };
5335
+ }
5336
+ async function killChrome(chrome) {
5337
+ try {
5338
+ return await chrome.kill();
5339
+ } catch (exn) {
5340
+ return;
5341
+ }
5342
+ }
5343
+ async function runLighthouse(chrome, url2, preset) {
5344
+ let port2 = chrome.port;
5345
+ let flags_port = port2;
5346
+ let flags_output = "json";
5347
+ let flags_logLevel = "error";
5348
+ let flags_onlyCategories = categoryIds;
5349
+ let flags_formFactor = preset;
5350
+ let flags_screenEmulation = {
5351
+ disabled: preset === "desktop"
5352
+ };
5353
+ let flags_throttlingMethod = "simulate";
5354
+ let flags2 = {
5355
+ port: flags_port,
5356
+ output: flags_output,
5357
+ logLevel: flags_logLevel,
5358
+ onlyCategories: flags_onlyCategories,
5359
+ formFactor: flags_formFactor,
5360
+ screenEmulation: flags_screenEmulation,
5361
+ throttlingMethod: flags_throttlingMethod
5362
+ };
5363
+ try {
5364
+ let runnerResult = await run(url2, flags2);
5365
+ await killChrome(chrome);
5366
+ if (runnerResult == null) {
5367
+ return {
5368
+ TAG: "Error",
5369
+ _0: "Lighthouse returned no results. The URL may be unreachable."
5370
+ };
5371
+ } else {
5372
+ return {
5373
+ TAG: "Ok",
5374
+ _0: processLhr(runnerResult.lhr)
5375
+ };
5376
+ }
5377
+ } catch (raw_exn) {
5378
+ let exn = internalToException(raw_exn);
5379
+ await killChrome(chrome);
5380
+ let msg = getErrorMessage(exn);
5381
+ return {
5382
+ TAG: "Error",
5383
+ _0: `Lighthouse audit failed: ` + msg
5384
+ };
5385
+ }
5386
+ }
5387
+ async function execute6(_ctx, input) {
5388
+ let preset = getOr(input.preset, "desktop");
5389
+ let auditUrl = rewriteUrlForRuntime(input.url);
5390
+ switch (preset) {
5391
+ case "desktop":
5392
+ case "mobile":
5393
+ break;
5394
+ default:
5395
+ return {
5396
+ TAG: "Error",
5397
+ _0: `Invalid preset "` + preset + `". Must be "desktop" or "mobile".`
5398
+ };
5399
+ }
5400
+ try {
5401
+ let chrome = await launch({
5402
+ chromeFlags: [
5403
+ "--headless",
5404
+ "--disable-gpu",
5405
+ "--no-sandbox",
5406
+ "--disable-dev-shm-usage"
5407
+ ]
5408
+ });
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
+ };
5434
+ } catch (raw_exn) {
5435
+ let exn = internalToException(raw_exn);
5436
+ let msg = getErrorMessage(exn);
5437
+ return {
5438
+ TAG: "Error",
5439
+ _0: `Failed to launch Chrome: ` + msg + `. Make sure Chrome is installed on the system.`
5440
+ };
5441
+ }
5442
+ }
5443
+ var name7 = "lighthouse";
5444
+ var description6 = `Runs a Lighthouse audit on a URL to analyze performance, accessibility, best practices, and SEO.
5445
+
5446
+ WHEN TO USE THIS TOOL:
5447
+ - After making changes that might affect page load performance
5448
+ - When implementing new UI components to check accessibility
5449
+ - Before deploying to verify web best practices
5450
+ - To diagnose why a page feels slow
5451
+
5452
+ PARAMETERS:
5453
+ - url (required): The full URL to audit (e.g., "http://localhost:3000/")
5454
+ - preset (optional): "desktop" (default) or "mobile" for mobile emulation
5455
+ IMPORTANT: Check the current_page context for device_emulation - if a mobile device is being emulated (e.g., iPhone, Pixel), use preset: "mobile" to match the user's testing context.
5456
+
5457
+ OUTPUT:
5458
+ Returns scores (0-100) for each category plus the top 3 issues to fix in each category.
5459
+ Higher scores are better. Issues include actionable descriptions.
5460
+
5461
+ LIMITATIONS:
5462
+ - Requires Chrome to be installed on the system
5463
+ - Takes 15-30 seconds to complete
5464
+ - Results can vary between runs (\xB15 points is normal)
5465
+ - URL must be accessible from the machine running the audit`;
5466
+ var name8 = ToolNames.searchFiles;
5467
+ var inputSchema7 = schema2((s2) => ({
4723
5468
  pattern: s2.m(string2),
4724
5469
  path: s2.m(option2(string2)),
4725
- type: s2.m(option2(string2)),
4726
5470
  max_results: s2.m(option2(int2))
4727
5471
  }));
4728
- var outputSchema6 = schema2((s2) => ({
5472
+ var outputSchema7 = schema2((s2) => ({
4729
5473
  files: s2.m(array2(string2)),
4730
5474
  totalResults: s2.m(int2),
4731
5475
  truncated: s2.m(bool2)
@@ -4746,56 +5490,38 @@ function buildRipgrepArgs2(searchPath) {
4746
5490
  args.push(searchPath);
4747
5491
  return args;
4748
5492
  }
4749
- function parseRipgrepOutput(output, pattern2, type_, maxResults) {
4750
- let lines = output.trim().split("\n").filter((line) => line !== "");
4751
- let patternLower = pattern2.toLowerCase();
4752
- let matchedFiles = lines.filter((filePath) => {
4753
- let fileName2 = Nodepath.basename(filePath).toLowerCase();
4754
- let patternMatches;
4755
- if (patternLower === "") {
4756
- patternMatches = true;
4757
- } else if (patternLower.includes("*")) {
4758
- let parts = patternLower.split("*");
4759
- let partsLength = parts.length;
4760
- patternMatches = reduceWithIndex(parts, true, (matches2, part, idx) => {
4761
- if (matches2) {
4762
- if (part === "") {
4763
- return true;
4764
- } else if (idx === 0) {
4765
- return fileName2.startsWith(part);
4766
- } else if (idx === (partsLength - 1 | 0)) {
4767
- return fileName2.endsWith(part);
4768
- } else {
4769
- return fileName2.includes(part);
4770
- }
4771
- } else {
4772
- return false;
4773
- }
4774
- });
4775
- } else {
4776
- patternMatches = fileName2.includes(patternLower);
4777
- }
4778
- let typeMatches;
4779
- if (type_ !== void 0) {
4780
- switch (type_) {
4781
- case "directory":
4782
- typeMatches = filePath.endsWith("/");
4783
- break;
4784
- case "file":
4785
- typeMatches = !filePath.endsWith("/");
4786
- break;
4787
- default:
4788
- typeMatches = true;
5493
+ function matchesPattern(fileName2, patternLower) {
5494
+ let fileNameLower = fileName2.toLowerCase();
5495
+ if (patternLower === "") {
5496
+ return true;
5497
+ }
5498
+ if (!patternLower.includes("*")) {
5499
+ return fileNameLower.includes(patternLower);
5500
+ }
5501
+ let parts = patternLower.split("*");
5502
+ let partsLength = parts.length;
5503
+ return reduceWithIndex(parts, true, (matches2, part, idx) => {
5504
+ if (matches2) {
5505
+ if (part === "") {
5506
+ return true;
5507
+ } else if (idx === 0) {
5508
+ return fileNameLower.startsWith(part);
5509
+ } else if (idx === (partsLength - 1 | 0)) {
5510
+ return fileNameLower.endsWith(part);
5511
+ } else {
5512
+ return fileNameLower.includes(part);
4789
5513
  }
4790
- } else {
4791
- typeMatches = true;
4792
- }
4793
- if (patternMatches) {
4794
- return typeMatches;
4795
5514
  } else {
4796
5515
  return false;
4797
5516
  }
4798
5517
  });
5518
+ }
5519
+ function filterAndPaginate(lines, pattern2, maxResults) {
5520
+ let patternLower = pattern2.toLowerCase();
5521
+ let matchedFiles = lines.filter((filePath) => {
5522
+ let fileName2 = Nodepath.basename(filePath);
5523
+ return matchesPattern(fileName2, patternLower);
5524
+ });
4799
5525
  let truncated = matchedFiles.length > maxResults;
4800
5526
  let files = matchedFiles.slice(0, maxResults);
4801
5527
  return {
@@ -4804,156 +5530,110 @@ function parseRipgrepOutput(output, pattern2, type_, maxResults) {
4804
5530
  truncated
4805
5531
  };
4806
5532
  }
4807
- function parseGitLsFilesOutput(output, maxResults) {
4808
- let lines = output.trim().split("\n").filter((line) => line !== "");
4809
- let truncated = lines.length > maxResults;
4810
- let files = lines.slice(0, maxResults);
4811
- return {
4812
- files,
4813
- totalResults: lines.length,
4814
- truncated
4815
- };
4816
- }
4817
- async function executeRipgrep2(rgPath, pattern2, searchPath, type_, maxResults) {
5533
+ async function executeRipgrep2(rgPath, pattern2, searchPath, maxResults) {
4818
5534
  let args = buildRipgrepArgs2(searchPath);
4819
- let command = rgPath + ` ` + args.join(" ");
4820
- try {
4821
- let result = await exec(command);
4822
- if (result.TAG === "Ok") {
4823
- return {
4824
- TAG: "Ok",
4825
- _0: parseRipgrepOutput(result._0.stdout, pattern2, type_, maxResults)
4826
- };
4827
- }
4828
- let match = result._0;
4829
- let match$1 = match.code;
4830
- let exit = 0;
4831
- if (match$1 !== void 0) {
4832
- if (match$1 === 1) {
4833
- return {
4834
- TAG: "Ok",
4835
- _0: {
4836
- files: [],
4837
- totalResults: 0,
4838
- truncated: false
4839
- }
4840
- };
4841
- }
4842
- exit = 1;
4843
- } else {
4844
- exit = 1;
4845
- }
4846
- if (exit === 1) {
4847
- return {
4848
- TAG: "Error",
4849
- _0: `Ripgrep failed: ` + match.stderr
4850
- };
4851
- }
4852
- } catch (raw_exn) {
4853
- let exn = internalToException(raw_exn);
4854
- let msg = getOr(flatMap(fromException(exn), message2), "Unknown error");
5535
+ let result = await spawnResult(rgPath, args, void 0);
5536
+ if (result.TAG === "Ok") {
5537
+ let lines = result._0.stdout.trim().split("\n").filter((line) => line !== "");
4855
5538
  return {
4856
- TAG: "Error",
4857
- _0: `Ripgrep execution failed: ` + msg
5539
+ TAG: "Ok",
5540
+ _0: filterAndPaginate(lines, pattern2, maxResults)
4858
5541
  };
4859
5542
  }
5543
+ let match = result._0;
5544
+ let match$1 = match.code;
5545
+ if (match$1 === 1) {
5546
+ return {
5547
+ TAG: "Ok",
5548
+ _0: {
5549
+ files: [],
5550
+ totalResults: 0,
5551
+ truncated: false
5552
+ }
5553
+ };
5554
+ }
5555
+ return {
5556
+ TAG: "Error",
5557
+ _0: `Ripgrep failed: ` + match.stderr
5558
+ };
4860
5559
  }
4861
5560
  async function executeGitLsFiles(pattern2, searchPath, maxResults) {
4862
- try {
4863
- let command = `git ls-files | grep -i "` + pattern2 + `"`;
4864
- let result = await execWithOptions(command, {
4865
- cwd: searchPath
4866
- });
4867
- if (result.TAG === "Ok") {
4868
- return {
4869
- TAG: "Ok",
4870
- _0: parseGitLsFilesOutput(result._0.stdout, maxResults)
4871
- };
4872
- }
4873
- let match = result._0;
4874
- let match$1 = match.code;
4875
- let exit = 0;
4876
- if (match$1 !== void 0) {
4877
- if (match$1 === 1) {
4878
- return {
4879
- TAG: "Ok",
4880
- _0: {
4881
- files: [],
4882
- totalResults: 0,
4883
- truncated: false
4884
- }
4885
- };
4886
- }
4887
- exit = 1;
4888
- } else {
4889
- exit = 1;
4890
- }
4891
- if (exit === 1) {
4892
- return {
4893
- TAG: "Error",
4894
- _0: `Git ls-files failed: ` + match.stderr
4895
- };
4896
- }
4897
- } catch (raw_exn) {
4898
- let exn = internalToException(raw_exn);
4899
- let msg = getOr(flatMap(fromException(exn), message2), "Unknown error");
5561
+ let result = await spawnResult("git", ["ls-files"], searchPath);
5562
+ if (result.TAG === "Ok") {
5563
+ let lines = result._0.stdout.trim().split("\n").filter((line) => line !== "");
4900
5564
  return {
4901
- TAG: "Error",
4902
- _0: `Git ls-files execution failed: ` + msg
5565
+ TAG: "Ok",
5566
+ _0: filterAndPaginate(lines, pattern2, maxResults)
5567
+ };
5568
+ }
5569
+ let match = result._0;
5570
+ let match$1 = match.code;
5571
+ if (match$1 === 1) {
5572
+ return {
5573
+ TAG: "Ok",
5574
+ _0: {
5575
+ files: [],
5576
+ totalResults: 0,
5577
+ truncated: false
5578
+ }
4903
5579
  };
4904
5580
  }
5581
+ return {
5582
+ TAG: "Error",
5583
+ _0: `Git ls-files failed: ` + match.stderr
5584
+ };
4905
5585
  }
4906
- async function execute6(ctx2, input) {
5586
+ async function execute7(ctx2, input) {
4907
5587
  let searchPath = resolveSearchPath(ctx2.sourceRoot, input.path);
4908
- let maxResults = getOr(input.max_results, 100);
5588
+ let maxResults = getOr(input.max_results, 20);
4909
5589
  let rgPath = getRipgrepPath2();
4910
5590
  if (rgPath === void 0) {
4911
5591
  return await executeGitLsFiles(input.pattern, searchPath, maxResults);
4912
5592
  }
4913
- let result = await executeRipgrep2(rgPath, input.pattern, searchPath, input.type, maxResults);
5593
+ let result = await executeRipgrep2(rgPath, input.pattern, searchPath, maxResults);
4914
5594
  if (result.TAG === "Ok") {
4915
5595
  return result;
4916
5596
  } else {
4917
5597
  return await executeGitLsFiles(input.pattern, searchPath, maxResults);
4918
5598
  }
4919
5599
  }
4920
- var name7 = "search_files";
4921
- var description6 = `Fast file and directory name search tool that finds files/directories matching a pattern.
5600
+ var description7 = `Fast file name search tool that finds files matching a pattern.
4922
5601
 
4923
5602
  WHEN TO USE THIS TOOL:
4924
- - Use when you need to find files or directories by name pattern
5603
+ - Use when you need to find files by name pattern
4925
5604
  - Great for locating specific files like "config.json" or "*.test.ts"
4926
5605
  - Useful for finding all files with a specific extension or naming convention
4927
5606
  - When you need to discover the file structure of a project
5607
+ - Note: this tool only searches file names, not directory names. Use list_files to browse directories.
4928
5608
 
4929
5609
  PARAMETERS:
4930
5610
  - pattern (required): The filename pattern to search for (supports glob-like patterns)
4931
5611
  - path (optional): Directory to search in (defaults to source root)
4932
- - type (optional): Filter by type - "file" for files only, "directory" for directories only
4933
5612
  - max_results (optional): Maximum number of results to return (default: 20)
4934
5613
 
4935
5614
  EXAMPLES:
4936
5615
  - Find all config files: pattern="config"
4937
5616
  - Find TypeScript test files: pattern="*.test.ts"
4938
- - Find directories named "components": pattern="components", type="directory"
4939
5617
  - Find files in specific directory: pattern="*.json", path="src/config"
4940
5618
 
4941
5619
  OUTPUT:
4942
- Returns list of matching file/directory paths.
5620
+ Returns list of matching file paths.
4943
5621
  Results are sorted by modification time (newest first).
4944
5622
 
4945
5623
  LIMITATIONS:
4946
5624
  - Results limited to max_results (default 20)
4947
5625
  - Hidden files (starting with '.') are included
4948
- - Respects .gitignore when using git ls-files fallback`;
4949
- var inputSchema7 = schema2((s2) => ({
5626
+ - Respects .gitignore when using git ls-files fallback
5627
+ - Only finds files, not directories`;
5628
+ var name9 = ToolNames.loadAgentInstructions;
5629
+ var inputSchema8 = schema2((s2) => ({
4950
5630
  startPath: s2.m(option2(string2))
4951
5631
  }));
4952
5632
  var instructionFileSchema = schema2((s2) => ({
4953
5633
  content: s2.m(string2),
4954
5634
  fullPath: s2.m(string2)
4955
5635
  }));
4956
- var outputSchema7 = array2(instructionFileSchema);
5636
+ var outputSchema8 = array2(instructionFileSchema);
4957
5637
  var agentsVariants = [
4958
5638
  "Agents.md",
4959
5639
  ".claude/Agents.md",
@@ -4966,7 +5646,7 @@ var claudeVariants = [
4966
5646
  ];
4967
5647
  async function findFileCaseInsensitive(dir, targetFileName) {
4968
5648
  try {
4969
- let files = await Fs2.promises.readdir(dir);
5649
+ let files = await Fs3.promises.readdir(dir);
4970
5650
  let targetLower = targetFileName.toLowerCase();
4971
5651
  let found = files.find((file) => file.toLowerCase() === targetLower);
4972
5652
  if (found !== void 0) {
@@ -4986,7 +5666,7 @@ async function loadIfExists(path) {
4986
5666
  return;
4987
5667
  }
4988
5668
  try {
4989
- let content = await Fs2.promises.readFile(actualPath, "utf8");
5669
+ let content = await Fs3.promises.readFile(actualPath, "utf8");
4990
5670
  return {
4991
5671
  content,
4992
5672
  fullPath: actualPath
@@ -5023,7 +5703,7 @@ async function walkUpDirectories(current, acc) {
5023
5703
  let newAcc = acc.concat(filesAtLevel);
5024
5704
  return await walkUpDirectories(Nodepath.dirname(current), newAcc);
5025
5705
  }
5026
- async function execute7(ctx2, input) {
5706
+ async function execute8(ctx2, input) {
5027
5707
  let inputPath = getOr(input.startPath, ".");
5028
5708
  let msg = resolve(ctx2.sourceRoot, inputPath);
5029
5709
  if (msg.TAG !== "Ok") {
@@ -5048,8 +5728,7 @@ async function execute7(ctx2, input) {
5048
5728
  };
5049
5729
  }
5050
5730
  }
5051
- var name8 = "load_agent_instructions";
5052
- var description7 = `Discovers and loads agent instruction files (Agents.md or CLAUDE.md) following Claude Code's discovery algorithm.
5731
+ var description8 = `Discovers and loads agent instruction files (Agents.md or CLAUDE.md) following Claude Code's discovery algorithm.
5053
5732
 
5054
5733
  Parameters:
5055
5734
  - startPath (optional): Starting directory for discovery - must be under source root. Defaults to "." (source root).
@@ -5099,11 +5778,11 @@ function coreTools() {
5099
5778
  visibleToAgent: true
5100
5779
  },
5101
5780
  {
5102
- name: name8,
5103
- description: description7,
5104
- inputSchema: inputSchema7,
5105
- outputSchema: outputSchema7,
5106
- execute: execute7,
5781
+ name: name9,
5782
+ description: description8,
5783
+ inputSchema: inputSchema8,
5784
+ outputSchema: outputSchema8,
5785
+ execute: execute8,
5107
5786
  visibleToAgent: false
5108
5787
  },
5109
5788
  {
@@ -5114,6 +5793,14 @@ function coreTools() {
5114
5793
  execute,
5115
5794
  visibleToAgent: true
5116
5795
  },
5796
+ {
5797
+ name: name8,
5798
+ description: description7,
5799
+ inputSchema: inputSchema7,
5800
+ outputSchema: outputSchema7,
5801
+ execute: execute7,
5802
+ visibleToAgent: true
5803
+ },
5117
5804
  {
5118
5805
  name: name7,
5119
5806
  description: description6,
@@ -5130,8 +5817,8 @@ function addTools(registry, newTools) {
5130
5817
  tools: registry.tools.concat(newTools)
5131
5818
  };
5132
5819
  }
5133
- function getToolByName(registry, name10) {
5134
- return registry.tools.find((m) => m.name === name10);
5820
+ function getToolByName(registry, name11) {
5821
+ return registry.tools.find((m) => m.name === name11);
5135
5822
  }
5136
5823
  function serializeTool(m) {
5137
5824
  return {
@@ -5164,12 +5851,12 @@ var toolCallRequestSchema = schema2((s2) => ({
5164
5851
  var protocolVersion = "1.0";
5165
5852
 
5166
5853
  // ../frontman-core/src/FrontmanCore__Server.res.mjs
5167
- async function executeTool(registry, ctx2, name10, $$arguments) {
5168
- let toolModule = getToolByName(registry, name10);
5854
+ async function executeTool(registry, ctx2, name11, $$arguments) {
5855
+ let toolModule = getToolByName(registry, name11);
5169
5856
  if (toolModule === void 0) {
5170
5857
  return {
5171
5858
  TAG: "ToolNotFound",
5172
- _0: name10
5859
+ _0: name11
5173
5860
  };
5174
5861
  }
5175
5862
  let toolCtx_projectRoot = ctx2.projectRoot;
@@ -5331,16 +6018,6 @@ async function handleToolCall(registry, config, req) {
5331
6018
  status: 400
5332
6019
  });
5333
6020
  }
5334
- function toRelativePath2(absolutePath, sourceRoot) {
5335
- let normalizedRoot = sourceRoot.endsWith("/") ? sourceRoot : sourceRoot + "/";
5336
- if (absolutePath.startsWith(normalizedRoot)) {
5337
- return absolutePath.slice(normalizedRoot.length, absolutePath.length);
5338
- } else if (absolutePath.startsWith(sourceRoot)) {
5339
- return absolutePath.slice(sourceRoot.length, absolutePath.length);
5340
- } else {
5341
- return absolutePath;
5342
- }
5343
- }
5344
6021
  function corsHeaders() {
5345
6022
  return Object.fromEntries([
5346
6023
  [
@@ -5391,7 +6068,7 @@ async function handleResolveSourceLocation(config, req) {
5391
6068
  parent: void 0
5392
6069
  };
5393
6070
  let resolved = await Te(sourceLocation);
5394
- let relativeFile = toRelativePath2(resolved.file, config.sourceRoot);
6071
+ let relativeFile = toRelativePath(config.sourceRoot, resolved.file);
5395
6072
  let responseJson = Object.fromEntries([
5396
6073
  [
5397
6074
  "componentName",
@@ -5441,41 +6118,35 @@ async function handleResolveSourceLocation(config, req) {
5441
6118
  status: 400
5442
6119
  });
5443
6120
  }
5444
- var inputSchema8 = schema2((s2) => ({
6121
+ var dynamicTypeSchema = union2([
6122
+ literal2("static"),
6123
+ literal2("single"),
6124
+ literal2("rest"),
6125
+ literal2("optional")
6126
+ ]);
6127
+ var inputSchema9 = schema2((s2) => ({
5445
6128
  placeholder: s2.m(option2(bool2))
5446
6129
  }));
5447
6130
  var pageSchema = schema2((s2) => ({
5448
6131
  path: s2.m(string2),
5449
6132
  file: s2.m(string2),
5450
6133
  isDynamic: s2.m(bool2),
5451
- dynamicType: s2.m(string2)
6134
+ dynamicType: s2.m(dynamicTypeSchema)
5452
6135
  }));
5453
- var outputSchema8 = array2(pageSchema);
6136
+ var outputSchema9 = array2(pageSchema);
5454
6137
  function analyzeDynamicSegment(segment) {
5455
6138
  if (segment.startsWith("[[") && segment.endsWith("]]")) {
5456
- return "OptionalParam";
6139
+ return "optional";
5457
6140
  } else if (segment.startsWith("[...") && segment.endsWith("]")) {
5458
- return "RestParam";
6141
+ return "rest";
5459
6142
  } else if (segment.startsWith("[") && segment.endsWith("]")) {
5460
- return "SingleParam";
6143
+ return "single";
5461
6144
  } else {
5462
- return "Static";
5463
- }
5464
- }
5465
- function dynamicTypeToString(dt) {
5466
- switch (dt) {
5467
- case "Static":
5468
- return "static";
5469
- case "SingleParam":
5470
- return "single";
5471
- case "RestParam":
5472
- return "rest";
5473
- case "OptionalParam":
5474
- return "optional";
6145
+ return "static";
5475
6146
  }
5476
6147
  }
5477
6148
  function isDynamicSegment(segment) {
5478
- return analyzeDynamicSegment(segment) !== "Static";
6149
+ return analyzeDynamicSegment(segment) !== "static";
5479
6150
  }
5480
6151
  function fileToRoute(filePath) {
5481
6152
  let p2 = filePath.replace(/\.(astro|md|mdx|html)$/, "").replace(/\/index$/, "");
@@ -5486,71 +6157,81 @@ function fileToRoute(filePath) {
5486
6157
  }
5487
6158
  }
5488
6159
  function getMostSignificantDynamicType(segments) {
5489
- return reduce(segments, "Static", (acc, segment) => {
6160
+ return reduce(segments, "static", (acc, segment) => {
5490
6161
  let segType = analyzeDynamicSegment(segment);
5491
- if (segType === "RestParam") {
5492
- return "RestParam";
6162
+ if (segType === "rest") {
6163
+ return "rest";
5493
6164
  }
5494
6165
  switch (acc) {
5495
- case "Static":
5496
- case "SingleParam":
6166
+ case "static":
6167
+ case "single":
5497
6168
  break;
5498
- case "RestParam":
5499
- return "RestParam";
5500
- case "OptionalParam":
5501
- return "OptionalParam";
6169
+ case "rest":
6170
+ return "rest";
6171
+ case "optional":
6172
+ return "optional";
5502
6173
  }
5503
6174
  switch (segType) {
5504
- case "Static":
5505
- if (acc === "Static") {
5506
- return "Static";
6175
+ case "static":
6176
+ if (acc === "static") {
6177
+ return "static";
5507
6178
  } else {
5508
- return "SingleParam";
6179
+ return "single";
5509
6180
  }
5510
- case "SingleParam":
5511
- return "SingleParam";
5512
- case "OptionalParam":
5513
- return "OptionalParam";
6181
+ case "single":
6182
+ return "single";
6183
+ case "optional":
6184
+ return "optional";
5514
6185
  }
5515
6186
  });
5516
6187
  }
5517
- async function findPages(baseDir, currentPath, projectRoot) {
6188
+ async function findPages(baseDir, currentPath, projectRoot, sourceRoot) {
5518
6189
  let fullPath = Nodepath.join(projectRoot, baseDir, currentPath);
5519
6190
  try {
5520
- let entries = await Fs2.promises.readdir(fullPath);
6191
+ let entries = await Fs3.promises.readdir(fullPath);
5521
6192
  return (await Promise.all(entries.map(async (entry) => {
5522
6193
  let entryPath = Nodepath.join(fullPath, entry);
5523
- let stats = await Fs2.promises.stat(entryPath);
6194
+ let stats = await Fs3.promises.lstat(entryPath);
6195
+ if (stats.isSymbolicLink()) {
6196
+ return [];
6197
+ }
5524
6198
  if (stats.isDirectory()) {
5525
6199
  if (entry.startsWith("_") || entry === "api" || entry === "components") {
5526
6200
  return [];
5527
6201
  } else {
5528
- return await findPages(baseDir, Nodepath.join(currentPath, entry), projectRoot);
6202
+ return await findPages(baseDir, Nodepath.join(currentPath, entry), projectRoot, sourceRoot);
5529
6203
  }
5530
6204
  }
5531
6205
  if (!(entry.endsWith(".astro") || entry.endsWith(".md") || entry.endsWith(".mdx") || entry.endsWith(".html"))) {
5532
6206
  return [];
5533
6207
  }
5534
- let fileName2 = entry.replace(/\.(astro|md|mdx|html)$/, "");
5535
- let routePath = fileToRoute(Nodepath.join(currentPath, fileName2));
5536
- let segments = Nodepath.join(currentPath, fileName2).split("/");
6208
+ let filePath = Nodepath.join(currentPath, entry);
6209
+ let routePath = fileToRoute(filePath);
6210
+ let filePathNoExt = filePath.replace(/\.(astro|md|mdx|html)$/, "");
6211
+ let segments = filePathNoExt.split("/");
5537
6212
  let hasDynamic = segments.some(isDynamicSegment);
5538
6213
  let dynType = getMostSignificantDynamicType(segments);
6214
+ let relativeToSourceRoot = toRelativePath(sourceRoot, entryPath);
5539
6215
  return [{
5540
6216
  path: routePath,
5541
- file: Nodepath.join(baseDir, currentPath, entry),
6217
+ file: relativeToSourceRoot,
5542
6218
  isDynamic: hasDynamic,
5543
- dynamicType: dynamicTypeToString(dynType)
6219
+ dynamicType: dynType
5544
6220
  }];
5545
6221
  }))).flat();
5546
- } catch (exn) {
5547
- return [];
6222
+ } catch (raw_exn) {
6223
+ let exn = internalToException(raw_exn);
6224
+ let msg = getOr(flatMap(fromException(exn), message2), "");
6225
+ if (msg.includes("ENOENT")) {
6226
+ return [];
6227
+ }
6228
+ throw exn;
5548
6229
  }
5549
6230
  }
5550
- async function execute8(ctx2, _input) {
6231
+ async function execute9(ctx2, _input) {
5551
6232
  try {
5552
- let srcPages = await findPages("src/pages", "", ctx2.projectRoot);
5553
- let rootPages = await findPages("pages", "", ctx2.projectRoot);
6233
+ let srcPages = await findPages("src/pages", "", ctx2.projectRoot, ctx2.sourceRoot);
6234
+ let rootPages = await findPages("pages", "", ctx2.projectRoot, ctx2.sourceRoot);
5554
6235
  let allPages = srcPages.concat(rootPages);
5555
6236
  return {
5556
6237
  TAG: "Ok",
@@ -5565,8 +6246,8 @@ async function execute8(ctx2, _input) {
5565
6246
  };
5566
6247
  }
5567
6248
  }
5568
- var name9 = "get_client_pages";
5569
- var description8 = `Lists Astro client pages from the pages directory.
6249
+ var name10 = "get_client_pages";
6250
+ var description9 = `Lists Astro client pages from the pages directory.
5570
6251
 
5571
6252
  Parameters: None
5572
6253
 
@@ -5575,11 +6256,11 @@ Excludes API routes (src/pages/api/) - focuses on renderable pages only.`;
5575
6256
 
5576
6257
  // src/FrontmanAstro__ToolRegistry.res.mjs
5577
6258
  var astroTools = [{
5578
- name: name9,
5579
- description: description8,
5580
- inputSchema: inputSchema8,
5581
- outputSchema: outputSchema8,
5582
- execute: execute8,
6259
+ name: name10,
6260
+ description: description9,
6261
+ inputSchema: inputSchema9,
6262
+ outputSchema: outputSchema9,
6263
+ execute: execute9,
5583
6264
  visibleToAgent: true
5584
6265
  }];
5585
6266
  function make2() {
@@ -5677,8 +6358,8 @@ var collectRequestBody = (async function(req) {
5677
6358
  for await (const chunk of req) {
5678
6359
  chunks.push(chunk);
5679
6360
  }
5680
- const { Buffer: Buffer2 } = await import('buffer');
5681
- return Buffer2.concat(chunks);
6361
+ const { Buffer: Buffer4 } = await import('buffer');
6362
+ return Buffer4.concat(chunks);
5682
6363
  });
5683
6364
 
5684
6365
  // src/FrontmanAstro__ViteAdapter.res.mjs
@@ -5770,36 +6451,11 @@ function adaptToConnect(middleware, basePath) {
5770
6451
  }
5771
6452
 
5772
6453
  // src/FrontmanAstro__Integration.res.mjs
6454
+ var annotationCaptureScript2 = annotationCaptureScript;
5773
6455
  var icon = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><circle cx="12" cy="12" r="3"/></svg>`;
5774
6456
  function getToolbarAppPath() {
5775
6457
  return new URL("./toolbar.js", import.meta.url).pathname;
5776
6458
  }
5777
- var annotationCaptureScript = `(function() {
5778
- function captureAnnotations() {
5779
- var annotations = new Map();
5780
- document.querySelectorAll('[data-astro-source-file]').forEach(function(el) {
5781
- annotations.set(el, {
5782
- file: el.getAttribute('data-astro-source-file'),
5783
- loc: el.getAttribute('data-astro-source-loc')
5784
- });
5785
- });
5786
- window.__frontman_annotations__ = {
5787
- _map: annotations,
5788
- get: function(el) { return annotations.get(el); },
5789
- has: function(el) { return annotations.has(el); },
5790
- size: function() { return annotations.size; }
5791
- };
5792
- }
5793
- // Capture once on initial DOM parse
5794
- document.addEventListener('DOMContentLoaded', captureAnnotations);
5795
- // Re-capture on View Transitions (SPA navigations) \u2014 skips the initial
5796
- // page-load event since DOMContentLoaded already captured
5797
- var initialLoad = true;
5798
- document.addEventListener('astro:page-load', function() {
5799
- if (initialLoad) { initialLoad = false; return; }
5800
- captureAnnotations();
5801
- });
5802
- })();`;
5803
6459
  function make3(configInput) {
5804
6460
  let config = makeFromObject(configInput);
5805
6461
  return {
@@ -5810,13 +6466,18 @@ function make3(configInput) {
5810
6466
  if (!ctx2.config.devToolbar.enabled) {
5811
6467
  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.");
5812
6468
  }
6469
+ ctx2.updateConfig({
6470
+ vite: {
6471
+ plugins: [frontmanPropsInjectionPlugin()]
6472
+ }
6473
+ });
5813
6474
  ctx2.addDevToolbarApp({
5814
6475
  id: "frontman:toolbar",
5815
6476
  name: "Frontman",
5816
6477
  icon,
5817
6478
  entrypoint: getToolbarAppPath()
5818
6479
  });
5819
- return ctx2.injectScript("head-inline", annotationCaptureScript);
6480
+ return ctx2.injectScript("head-inline", annotationCaptureScript2);
5820
6481
  }
5821
6482
  },
5822
6483
  "astro:server:setup": (param) => {
@@ -5831,4 +6492,7 @@ function make3(configInput) {
5831
6492
  // src/FrontmanAstro.res.mjs
5832
6493
  var frontmanIntegration = make3;
5833
6494
 
5834
- export { frontmanIntegration as default, frontmanIntegration };
6495
+ // index.mjs
6496
+ var index_default = frontmanIntegration;
6497
+
6498
+ export { index_default as default, frontmanIntegration };