stashes 0.1.56 → 0.1.58

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.
package/dist/mcp.js CHANGED
@@ -26,8 +26,8 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
26
26
  import { z } from "zod";
27
27
 
28
28
  // ../core/dist/generation.js
29
- import { readFileSync as readFileSync2, existsSync as existsSync7 } from "fs";
30
- import { join as join7 } from "path";
29
+ import { readFileSync as readFileSync2, existsSync as existsSync6 } from "fs";
30
+ import { join as join6 } from "path";
31
31
  var {spawn: spawn3 } = globalThis.Bun;
32
32
  import simpleGit3 from "simple-git";
33
33
  // ../shared/dist/constants/index.js
@@ -529,65 +529,19 @@ class PersistenceService {
529
529
 
530
530
  // ../core/dist/ai-process.js
531
531
  var {spawn } = globalThis.Bun;
532
- import { writeFileSync as writeFileSync2, existsSync as existsSync4, mkdirSync as mkdirSync3 } from "fs";
533
- import { join as join4 } from "path";
534
- import { tmpdir } from "os";
535
532
  var CLAUDE_BIN = "/opt/homebrew/bin/claude";
536
- function getPlaywrightMcpConfigPath() {
537
- const configDir = join4(tmpdir(), "stashes-mcp");
538
- const configPath = join4(configDir, "playwright.json");
539
- if (!existsSync4(configPath)) {
540
- mkdirSync3(configDir, { recursive: true });
541
- writeFileSync2(configPath, JSON.stringify({
542
- mcpServers: {
543
- playwright: { command: "npx", args: ["@playwright/mcp@latest"] }
544
- }
545
- }), "utf-8");
546
- }
547
- return configPath;
548
- }
549
- var OVERHEAD_TOOLS = [
550
- "Agent",
551
- "TodoWrite",
552
- "TaskCreate",
553
- "TaskUpdate",
554
- "TaskList",
555
- "TaskGet",
556
- "Skill",
557
- "ToolSearch",
558
- "EnterPlanMode",
559
- "ExitPlanMode",
560
- "WebSearch",
561
- "WebFetch",
562
- "NotebookEdit",
563
- "mcp__UseAI__*",
564
- "mcp__stashes__*",
565
- "mcp__plugin_drills*",
566
- "mcp__plugin_coverit*"
567
- ];
568
533
  var processes = new Map;
569
534
  function startAiProcess(idOrOpts, prompt, cwd, resumeSessionId, model) {
570
535
  const opts = typeof idOrOpts === "string" ? { id: idOrOpts, prompt, cwd, resumeSessionId, model } : idOrOpts;
571
- const restricted = opts.tools !== undefined;
572
536
  killAiProcess(opts.id);
573
537
  logger.info("claude", `spawning process: ${opts.id}`, {
574
538
  cwd: opts.cwd,
575
539
  promptLength: opts.prompt.length,
576
540
  promptPreview: opts.prompt.substring(0, 100),
577
541
  resumeSessionId: opts.resumeSessionId,
578
- model: opts.model,
579
- restricted,
580
- tools: restricted ? opts.tools.join(",") || "none" : "all"
542
+ model: opts.model
581
543
  });
582
544
  const cmd = [CLAUDE_BIN, "-p", opts.prompt, "--output-format=stream-json", "--verbose", "--dangerously-skip-permissions"];
583
- if (restricted) {
584
- cmd.push("--tools", opts.tools.length > 0 ? opts.tools.join(",") : "");
585
- cmd.push("--disallowedTools", OVERHEAD_TOOLS.join(","));
586
- cmd.push("--strict-mcp-config");
587
- if (opts.mcpConfigPath) {
588
- cmd.push("--mcp-config", opts.mcpConfigPath);
589
- }
590
- }
591
545
  if (opts.resumeSessionId) {
592
546
  cmd.push("--resume", opts.resumeSessionId);
593
547
  }
@@ -718,35 +672,47 @@ async function* parseClaudeStream(proc) {
718
672
  }
719
673
 
720
674
  // ../core/dist/smart-screenshot.js
721
- import { join as join6 } from "path";
722
- import { mkdirSync as mkdirSync5, existsSync as existsSync6 } from "fs";
675
+ import { join as join5 } from "path";
676
+ import { mkdirSync as mkdirSync4, existsSync as existsSync5 } from "fs";
723
677
  import simpleGit2 from "simple-git";
724
678
 
725
679
  // ../core/dist/screenshot.js
726
680
  var {spawn: spawn2 } = globalThis.Bun;
727
- import { join as join5 } from "path";
728
- import { mkdirSync as mkdirSync4, existsSync as existsSync5 } from "fs";
681
+ import { join as join4 } from "path";
682
+ import { mkdirSync as mkdirSync3, existsSync as existsSync4 } from "fs";
729
683
  var SCREENSHOTS_DIR = ".stashes/screenshots";
730
- async function captureScreenshot(port, projectPath, stashId) {
731
- const screenshotsDir = join5(projectPath, SCREENSHOTS_DIR);
732
- if (!existsSync5(screenshotsDir)) {
733
- mkdirSync4(screenshotsDir, { recursive: true });
734
- }
735
- const filename = `${stashId}.png`;
736
- const outputPath = join5(screenshotsDir, filename);
684
+ async function captureScreenshot(portOrOpts, projectPath, stashId) {
685
+ const opts = typeof portOrOpts === "number" ? { port: portOrOpts, projectPath, stashId } : portOrOpts;
686
+ const screenshotsDir = join4(opts.projectPath, SCREENSHOTS_DIR);
687
+ if (!existsSync4(screenshotsDir)) {
688
+ mkdirSync3(screenshotsDir, { recursive: true });
689
+ }
690
+ const filename = `${opts.stashId}.png`;
691
+ const outputPath = join4(screenshotsDir, filename);
692
+ const url = `http://localhost:${opts.port}${opts.route || "/"}`;
693
+ const scrollCode = opts.scrollToSelector ? `
694
+ try {
695
+ const el = await page.waitForSelector('${opts.scrollToSelector.replace(/'/g, "\\'")}', { timeout: 5000 });
696
+ if (el) {
697
+ await el.scrollIntoViewIfNeeded();
698
+ await page.waitForTimeout(500);
699
+ }
700
+ } catch(e) { /* selector not found, capture viewport */ }
701
+ ` : "";
737
702
  const playwrightScript = `
738
703
  const { chromium } = require('playwright');
739
704
  (async () => {
740
705
  const browser = await chromium.launch({ headless: true });
741
706
  const page = await browser.newPage({ viewport: { width: 1280, height: 720 } });
742
707
  try {
743
- await page.goto('http://localhost:${port}', { waitUntil: 'networkidle', timeout: 20000 });
708
+ await page.goto('${url}', { waitUntil: 'networkidle', timeout: 20000 });
744
709
  await page.waitForTimeout(2000);
745
710
  } catch(e) {
746
- await page.goto('http://localhost:${port}', { waitUntil: 'domcontentloaded', timeout: 10000 });
711
+ await page.goto('${url}', { waitUntil: 'domcontentloaded', timeout: 10000 });
747
712
  await page.waitForTimeout(3000);
748
713
  }
749
- await page.screenshot({ path: '${outputPath.replace(/'/g, "\\'")}', type: 'png' });
714
+ ${scrollCode}
715
+ await page.screenshot({ path: '${outputPath.replace(/'/g, "\\'")}', type: 'png'${opts.fullPage ? ", fullPage: true" : ""} });
750
716
  await browser.close();
751
717
  })();
752
718
  `;
@@ -782,62 +748,67 @@ ${diffStat}
782
748
  ## Partial diff (truncated):
783
749
  ${truncatedDiff}`;
784
750
  } catch (err) {
785
- logger.warn("smart-screenshot", `git diff failed, falling back`, {
751
+ logger.warn("smart-screenshot", `git diff failed`, {
786
752
  error: err instanceof Error ? err.message : String(err)
787
753
  });
788
754
  return "";
789
755
  }
790
756
  }
791
- function buildScreenshotPrompt(port, diff, screenshotDir, stashId) {
792
- const outputPath = join6(screenshotDir, `${stashId}.png`);
757
+ function buildScreenshotPrompt(port, diff, screenshotDir, stashId, componentPath) {
758
+ const outputPath = join5(screenshotDir, `${stashId}.png`);
793
759
  return [
794
- "You are a screenshot assistant. Take a screenshot of a running web app.",
795
- "Be fast \u2014 you have a strict time limit.",
760
+ "## You are a screenshot agent. Your goal: capture a screenshot showing the UI changes described in the diff below.",
796
761
  "",
797
- `The app is running at: http://localhost:${port}`,
762
+ "## RULES",
763
+ "- ONLY use Playwright MCP tools (prefixed with mcp__plugin_playwright_playwright__)",
764
+ "- Do NOT call: ToolSearch, Skill, Agent, TodoWrite, TaskCreate, TaskUpdate,",
765
+ " mcp__UseAI__*, mcp__stashes__*, mcp__plugin_drills__*, mcp__plugin_coverit__*,",
766
+ " EnterPlanMode, ExitPlanMode, WebSearch, WebFetch, LSP, Read, Write, Edit, Glob, Grep",
767
+ "- You have a strict time budget. Be fast and decisive.",
798
768
  "",
799
- "## Git diff of changes (tells you what was modified):",
769
+ `## App: http://localhost:${port}`,
770
+ componentPath ? `## Target component file: ${componentPath}` : "",
771
+ "",
772
+ "## Git diff of changes:",
800
773
  "```",
801
774
  diff,
802
775
  "```",
803
776
  "",
804
- "## Instructions",
805
- "Use mcp__playwright__browser_run_code to navigate AND screenshot in a single call.",
806
- "From the diff, determine the route/section that shows the changes.",
777
+ "## Your task",
778
+ "Study the diff above to understand:",
779
+ "1. WHAT changed (component, styles, layout, content)",
780
+ "2. WHERE it lives in the app (which route? which section of the page? is it behind a tab/modal/click?)",
781
+ "3. WHAT STATE is needed to see it (does a button need to be clicked? a tab selected? a form filled?)",
807
782
  "",
808
- "**Call this tool:**",
809
- "```",
810
- "mcp__playwright__browser_run_code",
811
- "```",
783
+ "Then use Playwright tools to navigate there and capture it:",
812
784
  "",
813
- "**With this code parameter** (adjust the URL path and scroll if needed):",
814
- "```javascript",
815
- `async (page) => {`,
816
- ` await page.setViewportSize({ width: 1280, height: 720 });`,
817
- ` await page.goto('http://localhost:${port}', { waitUntil: 'networkidle', timeout: 15000 });`,
818
- ` // If the changed component is further down, scroll to it:`,
819
- ` // await page.evaluate(() => window.scrollTo(0, 500));`,
820
- ` // await page.waitForTimeout(500);`,
821
- ` await page.waitForTimeout(2000);`,
822
- ` await page.screenshot({ path: '${outputPath.replace(/'/g, "\\'")}', type: 'png' });`,
823
- ` return 'saved';`,
824
- `}`,
825
- "```",
785
+ "**Available Playwright tools:**",
786
+ "- `mcp__plugin_playwright_playwright__browser_navigate` \u2014 go to a URL",
787
+ "- `mcp__plugin_playwright_playwright__browser_snapshot` \u2014 get the page accessibility tree (use this to find elements)",
788
+ "- `mcp__plugin_playwright_playwright__browser_click` \u2014 click an element (use ref from snapshot)",
789
+ "- `mcp__plugin_playwright_playwright__browser_hover` \u2014 hover over an element",
790
+ "- `mcp__plugin_playwright_playwright__browser_evaluate` \u2014 run JS on the page (e.g. scroll, trigger state)",
791
+ "- `mcp__plugin_playwright_playwright__browser_take_screenshot` \u2014 capture the screenshot",
826
792
  "",
827
- "If the diff shows changes to a component that requires scrolling or navigation,",
828
- "adjust the code: change the URL path, add scrollTo, or click a tab first.",
793
+ "**Typical flow:**",
794
+ `1. Navigate to http://localhost:${port} (or a sub-route if the diff indicates one)`,
795
+ "2. Take a snapshot to understand the page layout",
796
+ "3. If the changed component is not visible: scroll to it, click a tab, open a modal \u2014 whatever is needed",
797
+ "4. Take the screenshot once the changed component is visible",
829
798
  "",
830
- `After the tool call succeeds, respond with ONLY this JSON:`,
799
+ `## Output \u2014 after taking the screenshot, respond with ONLY this JSON:`,
800
+ "```json",
831
801
  "{",
832
802
  ' "screenshots": [',
833
803
  " {",
834
804
  ` "path": "${outputPath}",`,
835
- ' "label": "Short description of what is shown",',
836
- ' "route": "/the-url-path",',
805
+ ' "label": "Brief description of what the screenshot shows",',
806
+ ' "route": "/the-route-you-navigated-to",',
837
807
  ' "isPrimary": true',
838
808
  " }",
839
809
  " ]",
840
- "}"
810
+ "}",
811
+ "```"
841
812
  ].join(`
842
813
  `);
843
814
  }
@@ -871,10 +842,10 @@ async function fallbackScreenshot(port, projectPath, stashId) {
871
842
  }
872
843
  }
873
844
  async function captureSmartScreenshots(opts) {
874
- const { projectPath, stashId, stashBranch, parentBranch, worktreePath, port, model = "sonnet", timeout = DEFAULT_TIMEOUT } = opts;
875
- const screenshotDir = join6(projectPath, SCREENSHOTS_DIR2);
876
- if (!existsSync6(screenshotDir)) {
877
- mkdirSync5(screenshotDir, { recursive: true });
845
+ const { projectPath, stashId, stashBranch, parentBranch, worktreePath, port, model = "sonnet", timeout = DEFAULT_TIMEOUT, componentPath } = opts;
846
+ const screenshotDir = join5(projectPath, SCREENSHOTS_DIR2);
847
+ if (!existsSync5(screenshotDir)) {
848
+ mkdirSync4(screenshotDir, { recursive: true });
878
849
  }
879
850
  const diff = await getStashDiff(worktreePath, parentBranch);
880
851
  if (!diff) {
@@ -882,15 +853,13 @@ async function captureSmartScreenshots(opts) {
882
853
  return fallbackScreenshot(port, projectPath, stashId);
883
854
  }
884
855
  const processId = `screenshot-ai-${stashId}`;
885
- const prompt = buildScreenshotPrompt(port, diff, screenshotDir, stashId);
856
+ const prompt = buildScreenshotPrompt(port, diff, screenshotDir, stashId, componentPath);
886
857
  const modelFlag = model === "sonnet" ? "sonnet" : "haiku";
887
858
  const aiProcess = startAiProcess({
888
859
  id: processId,
889
860
  prompt,
890
861
  cwd: worktreePath,
891
- model: modelFlag,
892
- tools: [],
893
- mcpConfigPath: getPlaywrightMcpConfigPath()
862
+ model: modelFlag
894
863
  });
895
864
  let textOutput = "";
896
865
  let timedOut = false;
@@ -916,9 +885,9 @@ async function captureSmartScreenshots(opts) {
916
885
  }
917
886
  const result = parseAiResult(textOutput);
918
887
  if (!result || !result.screenshots || result.screenshots.length === 0) {
919
- const expectedPath = join6(screenshotDir, `${stashId}.png`);
920
- if (existsSync6(expectedPath)) {
921
- logger.info("smart-screenshot", `AI saved screenshot for ${stashId} via browser_run_code (no JSON response)`);
888
+ const expectedPath = join5(screenshotDir, `${stashId}.png`);
889
+ if (existsSync5(expectedPath)) {
890
+ logger.info("smart-screenshot", `AI saved screenshot for ${stashId} (no JSON response, but file exists)`);
922
891
  const url = `/api/screenshots/${stashId}.png`;
923
892
  return {
924
893
  primary: url,
@@ -932,18 +901,12 @@ async function captureSmartScreenshots(opts) {
932
901
  let primaryUrl = "";
933
902
  for (const shot of result.screenshots) {
934
903
  const filename = shot.path.split("/").pop() || "";
935
- if (!existsSync6(shot.path)) {
904
+ if (!existsSync5(shot.path)) {
936
905
  logger.warn("smart-screenshot", `Screenshot file not found: ${shot.path}`);
937
906
  continue;
938
907
  }
939
908
  const url = `/api/screenshots/${filename}`;
940
- const screenshot = {
941
- url,
942
- label: shot.label,
943
- route: shot.route,
944
- isPrimary: shot.isPrimary
945
- };
946
- screenshots.push(screenshot);
909
+ screenshots.push({ url, label: shot.label, route: shot.route, isPrimary: shot.isPrimary });
947
910
  if (shot.isPrimary)
948
911
  primaryUrl = url;
949
912
  }
@@ -1026,8 +989,8 @@ async function generate(opts) {
1026
989
  const selectedDirectives = directives.slice(0, count);
1027
990
  let sourceCode = "";
1028
991
  if (component?.filePath) {
1029
- const sourceFile = join7(projectPath, component.filePath);
1030
- if (existsSync7(sourceFile)) {
992
+ const sourceFile = join6(projectPath, component.filePath);
993
+ if (existsSync6(sourceFile)) {
1031
994
  sourceCode = readFileSync2(sourceFile, "utf-8");
1032
995
  }
1033
996
  }
@@ -1162,7 +1125,8 @@ async function generate(opts) {
1162
1125
  worktreePath: screenshotWorktree.path,
1163
1126
  port,
1164
1127
  model: opts.screenshotModel,
1165
- timeout: opts.screenshotTimeout
1128
+ timeout: opts.screenshotTimeout,
1129
+ componentPath: stash.componentPath ?? undefined
1166
1130
  });
1167
1131
  const readyStash = { ...generatedStash, status: "ready", screenshotUrl: primary, screenshots };
1168
1132
  completedStashes.push(readyStash);
@@ -1328,7 +1292,8 @@ async function vary(opts) {
1328
1292
  worktreePath: screenshotWorktree.path,
1329
1293
  port,
1330
1294
  model: opts.screenshotModel,
1331
- timeout: opts.screenshotTimeout
1295
+ timeout: opts.screenshotTimeout,
1296
+ componentPath: stash.componentPath ?? undefined
1332
1297
  });
1333
1298
  screenshotPath = result.primary;
1334
1299
  screenshots = [...result.screenshots];
@@ -1626,18 +1591,18 @@ async function handleRemove(args, projectPath) {
1626
1591
  // ../server/dist/index.js
1627
1592
  import { Hono as Hono2 } from "hono";
1628
1593
  import { cors } from "hono/cors";
1629
- import { join as join11, dirname as dirname3 } from "path";
1594
+ import { join as join10, dirname as dirname3 } from "path";
1630
1595
  import { fileURLToPath } from "url";
1631
- import { existsSync as existsSync11, readFileSync as readFileSync6 } from "fs";
1596
+ import { existsSync as existsSync10, readFileSync as readFileSync6 } from "fs";
1632
1597
 
1633
1598
  // ../server/dist/routes/api.js
1634
1599
  import { Hono } from "hono";
1635
- import { join as join10, basename } from "path";
1636
- import { existsSync as existsSync10, readFileSync as readFileSync5 } from "fs";
1600
+ import { join as join9, basename } from "path";
1601
+ import { existsSync as existsSync9, readFileSync as readFileSync5 } from "fs";
1637
1602
 
1638
1603
  // ../server/dist/services/stash-service.js
1639
- import { readFileSync as readFileSync3, existsSync as existsSync8 } from "fs";
1640
- import { join as join8 } from "path";
1604
+ import { readFileSync as readFileSync3, existsSync as existsSync7 } from "fs";
1605
+ import { join as join7 } from "path";
1641
1606
 
1642
1607
  // ../server/dist/services/app-proxy.js
1643
1608
  import { spawn as spawn5 } from "child_process";
@@ -2173,8 +2138,7 @@ class StashService {
2173
2138
  id: "resolve-component",
2174
2139
  prompt,
2175
2140
  cwd: this.projectPath,
2176
- model: "claude-haiku-4-5-20251001",
2177
- tools: ["Read", "Grep", "Glob", "Bash"]
2141
+ model: "claude-haiku-4-5-20251001"
2178
2142
  });
2179
2143
  let resolvedPath = "";
2180
2144
  try {
@@ -2236,8 +2200,8 @@ class StashService {
2236
2200
  let sourceCode = "";
2237
2201
  const filePath = component?.filePath || "";
2238
2202
  if (filePath && filePath !== "auto-detect") {
2239
- const sourceFile = join8(this.projectPath, filePath);
2240
- if (existsSync8(sourceFile)) {
2203
+ const sourceFile = join7(this.projectPath, filePath);
2204
+ if (existsSync7(sourceFile)) {
2241
2205
  sourceCode = readFileSync3(sourceFile, "utf-8");
2242
2206
  }
2243
2207
  }
@@ -2589,8 +2553,8 @@ ${refDescriptions.join(`
2589
2553
  }
2590
2554
 
2591
2555
  // ../server/dist/services/activity-store.js
2592
- import { appendFileSync as appendFileSync2, readFileSync as readFileSync4, existsSync as existsSync9, mkdirSync as mkdirSync6, rmSync as rmSync3 } from "fs";
2593
- import { join as join9, dirname as dirname2 } from "path";
2556
+ import { appendFileSync as appendFileSync2, readFileSync as readFileSync4, existsSync as existsSync8, mkdirSync as mkdirSync5, rmSync as rmSync3 } from "fs";
2557
+ import { join as join8, dirname as dirname2 } from "path";
2594
2558
 
2595
2559
  class ActivityStore {
2596
2560
  cache = new Map;
@@ -2599,7 +2563,7 @@ class ActivityStore {
2599
2563
  this.projectPath = projectPath;
2600
2564
  }
2601
2565
  jsonlPath(stashId) {
2602
- return join9(this.projectPath, ".stashes", "activity", `${stashId}.jsonl`);
2566
+ return join8(this.projectPath, ".stashes", "activity", `${stashId}.jsonl`);
2603
2567
  }
2604
2568
  append(event) {
2605
2569
  const existing = this.cache.get(event.stashId) ?? [];
@@ -2607,8 +2571,8 @@ class ActivityStore {
2607
2571
  this.cache.set(event.stashId, existing);
2608
2572
  const filePath = this.jsonlPath(event.stashId);
2609
2573
  const dir = dirname2(filePath);
2610
- if (!existsSync9(dir))
2611
- mkdirSync6(dir, { recursive: true });
2574
+ if (!existsSync8(dir))
2575
+ mkdirSync5(dir, { recursive: true });
2612
2576
  appendFileSync2(filePath, JSON.stringify(event) + `
2613
2577
  `, "utf-8");
2614
2578
  }
@@ -2617,7 +2581,7 @@ class ActivityStore {
2617
2581
  if (cached && cached.length > 0)
2618
2582
  return cached;
2619
2583
  const filePath = this.jsonlPath(stashId);
2620
- if (!existsSync9(filePath))
2584
+ if (!existsSync8(filePath))
2621
2585
  return [];
2622
2586
  const lines = readFileSync4(filePath, "utf-8").trim().split(`
2623
2587
  `).filter(Boolean);
@@ -2643,14 +2607,14 @@ class ActivityStore {
2643
2607
  clear(stashId) {
2644
2608
  this.cache.delete(stashId);
2645
2609
  const filePath = this.jsonlPath(stashId);
2646
- if (existsSync9(filePath)) {
2610
+ if (existsSync8(filePath)) {
2647
2611
  rmSync3(filePath);
2648
2612
  }
2649
2613
  }
2650
2614
  has(stashId) {
2651
2615
  if (this.cache.has(stashId) && (this.cache.get(stashId)?.length ?? 0) > 0)
2652
2616
  return true;
2653
- return existsSync9(this.jsonlPath(stashId));
2617
+ return existsSync8(this.jsonlPath(stashId));
2654
2618
  }
2655
2619
  }
2656
2620
 
@@ -2892,8 +2856,8 @@ app.get("/dev-server-status", async (c) => {
2892
2856
  });
2893
2857
  app.get("/screenshots/:filename", (c) => {
2894
2858
  const filename = c.req.param("filename");
2895
- const filePath = join10(serverState.projectPath, ".stashes", "screenshots", filename);
2896
- if (!existsSync10(filePath))
2859
+ const filePath = join9(serverState.projectPath, ".stashes", "screenshots", filename);
2860
+ if (!existsSync9(filePath))
2897
2861
  return c.json({ error: "Not found" }, 404);
2898
2862
  const content = readFileSync5(filePath);
2899
2863
  return new Response(content, {
@@ -2945,12 +2909,12 @@ app2.route("/api", apiRoutes);
2945
2909
  app2.get("/*", async (c) => {
2946
2910
  const path = c.req.path;
2947
2911
  const selfDir = dirname3(fileURLToPath(import.meta.url));
2948
- const bundledWebDir = join11(selfDir, "web");
2949
- const monorepoWebDir = join11(selfDir, "../../web/dist");
2950
- const webDistDir = existsSync11(join11(bundledWebDir, "index.html")) ? bundledWebDir : monorepoWebDir;
2912
+ const bundledWebDir = join10(selfDir, "web");
2913
+ const monorepoWebDir = join10(selfDir, "../../web/dist");
2914
+ const webDistDir = existsSync10(join10(bundledWebDir, "index.html")) ? bundledWebDir : monorepoWebDir;
2951
2915
  const requestPath = path === "/" ? "/index.html" : path;
2952
- const filePath = join11(webDistDir, requestPath);
2953
- if (existsSync11(filePath) && !filePath.includes("..")) {
2916
+ const filePath = join10(webDistDir, requestPath);
2917
+ if (existsSync10(filePath) && !filePath.includes("..")) {
2954
2918
  const content = readFileSync6(filePath);
2955
2919
  const ext = filePath.split(".").pop() || "";
2956
2920
  const contentTypes = {
@@ -2969,8 +2933,8 @@ app2.get("/*", async (c) => {
2969
2933
  headers: { "content-type": contentTypes[ext] || "application/octet-stream" }
2970
2934
  });
2971
2935
  }
2972
- const indexPath = join11(webDistDir, "index.html");
2973
- if (existsSync11(indexPath)) {
2936
+ const indexPath = join10(webDistDir, "index.html");
2937
+ if (existsSync10(indexPath)) {
2974
2938
  const html = readFileSync6(indexPath, "utf-8");
2975
2939
  return new Response(html, {
2976
2940
  headers: { "content-type": "text/html; charset=utf-8" }
@@ -3034,11 +2998,11 @@ async function startServer(projectPath, userDevPort, requestedPort = STASHES_POR
3034
2998
  import open from "open";
3035
2999
 
3036
3000
  // ../server/dist/services/detector.js
3037
- import { existsSync as existsSync12, readFileSync as readFileSync7 } from "fs";
3038
- import { join as join12 } from "path";
3001
+ import { existsSync as existsSync11, readFileSync as readFileSync7 } from "fs";
3002
+ import { join as join11 } from "path";
3039
3003
  function detectFramework(projectPath) {
3040
- const packageJsonPath = join12(projectPath, "package.json");
3041
- if (!existsSync12(packageJsonPath)) {
3004
+ const packageJsonPath = join11(projectPath, "package.json");
3005
+ if (!existsSync11(packageJsonPath)) {
3042
3006
  return {
3043
3007
  framework: "unknown",
3044
3008
  devCommand: "npm run dev",
@@ -3100,7 +3064,7 @@ function getDevCommand(packageJson, fallback) {
3100
3064
  }
3101
3065
  function findConfig(projectPath, candidates) {
3102
3066
  for (const candidate of candidates) {
3103
- if (existsSync12(join12(projectPath, candidate))) {
3067
+ if (existsSync11(join11(projectPath, candidate))) {
3104
3068
  return candidate;
3105
3069
  }
3106
3070
  }