@knowsuchagency/fulcrum 3.0.0 → 3.0.2

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/server/index.js CHANGED
@@ -1153848,6 +1153848,9 @@ var init_memory_file_service = __esm(() => {
1153848
1153848
  });
1153849
1153849
 
1153850
1153850
  // server/services/assistant-service.ts
1153851
+ import { writeFile as writeFile3, unlink as unlink3, mkdtemp } from "fs/promises";
1153852
+ import { tmpdir as tmpdir3 } from "os";
1153853
+ import { join as join15 } from "path";
1153851
1153854
  async function createSession(options) {
1153852
1153855
  const id = nanoid();
1153853
1153856
  const now = new Date().toISOString();
@@ -1154255,53 +1154258,40 @@ ${options.editorContent}
1154255
1154258
 
1154256
1154259
  User message: ${userMessage}`;
1154257
1154260
  }
1154261
+ const tempFiles2 = [];
1154258
1154262
  let fullPrompt;
1154259
1154263
  if (options.attachments && options.attachments.length > 0) {
1154260
- const content = [];
1154264
+ const parts = [];
1154261
1154265
  for (const attachment of options.attachments) {
1154262
1154266
  switch (attachment.type) {
1154263
- case "image":
1154264
- content.push({
1154265
- type: "image",
1154266
- source: {
1154267
- type: "base64",
1154268
- media_type: attachment.mediaType,
1154269
- data: attachment.data
1154270
- }
1154271
- });
1154267
+ case "image": {
1154268
+ const ext2 = attachment.mediaType.split("/")[1] || "png";
1154269
+ const tempDir = await mkdtemp(join15(tmpdir3(), "fulcrum-img-"));
1154270
+ const tempPath = join15(tempDir, `${attachment.filename || `image.${ext2}`}`);
1154271
+ await writeFile3(tempPath, Buffer.from(attachment.data, "base64"));
1154272
+ tempFiles2.push(tempPath);
1154273
+ parts.push(`[Attached image: ${tempPath}]`);
1154272
1154274
  break;
1154275
+ }
1154273
1154276
  case "document":
1154274
- content.push({
1154275
- type: "document",
1154276
- source: {
1154277
- type: "base64",
1154278
- media_type: attachment.mediaType,
1154279
- data: attachment.data
1154280
- },
1154281
- title: attachment.filename
1154282
- });
1154277
+ {
1154278
+ const tempDir = await mkdtemp(join15(tmpdir3(), "fulcrum-doc-"));
1154279
+ const tempPath = join15(tempDir, attachment.filename || "document.pdf");
1154280
+ await writeFile3(tempPath, Buffer.from(attachment.data, "base64"));
1154281
+ tempFiles2.push(tempPath);
1154282
+ parts.push(`[Attached document: ${tempPath}]`);
1154283
+ }
1154283
1154284
  break;
1154284
1154285
  case "text":
1154285
- content.push({
1154286
- type: "text",
1154287
- text: `--- ${attachment.filename} ---
1154288
- ${attachment.data}`
1154289
- });
1154286
+ parts.push(`--- ${attachment.filename} ---
1154287
+ ${attachment.data}`);
1154290
1154288
  break;
1154291
1154289
  }
1154292
1154290
  }
1154293
- content.push({
1154294
- type: "text",
1154295
- text: textMessage || "What is in this attachment?"
1154296
- });
1154297
- fullPrompt = async function* () {
1154298
- yield {
1154299
- type: "user",
1154300
- message: { role: "user", content },
1154301
- parent_tool_use_id: null,
1154302
- session_id: sessionId
1154303
- };
1154304
- }();
1154291
+ parts.push(textMessage || "What is in this attachment?");
1154292
+ fullPrompt = parts.join(`
1154293
+
1154294
+ `);
1154305
1154295
  } else {
1154306
1154296
  fullPrompt = textMessage;
1154307
1154297
  }
@@ -1154411,6 +1154401,10 @@ ${attachment.data}`
1154411
1154401
  const errorMsg = err instanceof Error ? err.message : String(err);
1154412
1154402
  log2.assistant.error("Assistant stream error", { sessionId, error: errorMsg });
1154413
1154403
  yield { type: "error", data: { message: errorMsg } };
1154404
+ } finally {
1154405
+ for (const tempPath of tempFiles) {
1154406
+ unlink3(tempPath).catch(() => {});
1154407
+ }
1154414
1154408
  }
1154415
1154409
  }
1154416
1154410
  function extractDocumentContent(content) {
@@ -1164294,10 +1164288,10 @@ __export(exports_compose_parser, {
1164294
1164288
  findComposeFile: () => findComposeFile
1164295
1164289
  });
1164296
1164290
  import { readFile as readFile4, access } from "fs/promises";
1164297
- import { join as join27 } from "path";
1164291
+ import { join as join28 } from "path";
1164298
1164292
  async function findComposeFile(repoPath) {
1164299
1164293
  for (const fileName of COMPOSE_FILE_NAMES) {
1164300
- const filePath = join27(repoPath, fileName);
1164294
+ const filePath = join28(repoPath, fileName);
1164301
1164295
  try {
1164302
1164296
  await access(filePath);
1164303
1164297
  return fileName;
@@ -1164396,7 +1164390,7 @@ async function parseComposeFile(repoPath, composeFileName) {
1164396
1164390
  if (!fileName) {
1164397
1164391
  throw new Error(`No compose file found in ${repoPath}`);
1164398
1164392
  }
1164399
- const filePath = join27(repoPath, fileName);
1164393
+ const filePath = join28(repoPath, fileName);
1164400
1164394
  const content = await readFile4(filePath, "utf-8");
1164401
1164395
  const parsed = $parse(content);
1164402
1164396
  if (!parsed || typeof parsed !== "object") {
@@ -1164621,9 +1164615,9 @@ __export(exports_docker_swarm, {
1164621
1164615
  addCloudflaredToStack: () => addCloudflaredToStack
1164622
1164616
  });
1164623
1164617
  import { spawn as spawn7 } from "child_process";
1164624
- import { mkdir as mkdir4, readFile as readFile5, writeFile as writeFile4 } from "fs/promises";
1164618
+ import { mkdir as mkdir4, readFile as readFile5, writeFile as writeFile5 } from "fs/promises";
1164625
1164619
  import { createServer } from "net";
1164626
- import { join as join28, resolve as resolve4, isAbsolute as isAbsolute2 } from "path";
1164620
+ import { join as join29, resolve as resolve4, isAbsolute as isAbsolute2 } from "path";
1164627
1164621
  async function runDocker2(args, options = {}, onOutput) {
1164628
1164622
  if (options.signal?.aborted) {
1164629
1164623
  return { stdout: "", stderr: "Aborted", exitCode: -1, aborted: true };
@@ -1164742,7 +1164736,7 @@ async function validateAndAllocatePorts(cwd2, composeFile, env = {}, autoAllocat
1164742
1164736
  const conflicts = [];
1164743
1164737
  const allocations = new Map;
1164744
1164738
  try {
1164745
- const content = await readFile5(join28(cwd2, composeFile), "utf-8");
1164739
+ const content = await readFile5(join29(cwd2, composeFile), "utf-8");
1164746
1164740
  const parsed = $parse(content);
1164747
1164741
  const services = parsed.services;
1164748
1164742
  if (!services) {
@@ -1164820,8 +1164814,8 @@ function extractPortInfo(portSpec, env) {
1164820
1164814
  }
1164821
1164815
  async function generateSwarmComposeFile(cwd2, composeFile, projectName, externalNetwork, outputDir, env) {
1164822
1164816
  const swarmFileName = "swarm-compose.yml";
1164823
- const originalPath = join28(cwd2, composeFile);
1164824
- const swarmPath = join28(outputDir, swarmFileName);
1164817
+ const originalPath = join29(cwd2, composeFile);
1164818
+ const swarmPath = join29(outputDir, swarmFileName);
1164825
1164819
  try {
1164826
1164820
  await mkdir4(outputDir, { recursive: true });
1164827
1164821
  const content = await readFile5(originalPath, "utf-8");
@@ -1164919,7 +1164913,7 @@ async function generateSwarmComposeFile(cwd2, composeFile, projectName, external
1164919
1164913
  parsed.networks = networks;
1164920
1164914
  }
1164921
1164915
  const swarmContent = $stringify(parsed);
1164922
- await writeFile4(swarmPath, swarmContent, "utf-8");
1164916
+ await writeFile5(swarmPath, swarmContent, "utf-8");
1164923
1164917
  if (modified.length > 0 || externalNetwork) {
1164924
1164918
  log2.deploy.info("Generated Swarm compose file", {
1164925
1164919
  swarmFile: swarmPath,
@@ -1165247,7 +1165241,7 @@ async function addCloudflaredToStack(swarmFilePath, config2) {
1165247
1165241
  networks[config2.network] = { external: true };
1165248
1165242
  parsed.networks = networks;
1165249
1165243
  }
1165250
- await writeFile4(swarmFilePath, $stringify(parsed), "utf-8");
1165244
+ await writeFile5(swarmFilePath, $stringify(parsed), "utf-8");
1165251
1165245
  log2.deploy.info("Added cloudflared service to stack", { swarmFile: swarmFilePath });
1165252
1165246
  return { success: true };
1165253
1165247
  } catch (err) {
@@ -1188764,8 +1188758,8 @@ var init_cloudflare = __esm(() => {
1188764
1188758
 
1188765
1188759
  // server/services/cloudflare.ts
1188766
1188760
  import { generateKeyPairSync, createSign } from "crypto";
1188767
- import { mkdir as mkdir5, writeFile as writeFile5, readFile as readFile6, access as access2 } from "fs/promises";
1188768
- import { join as join29 } from "path";
1188761
+ import { mkdir as mkdir5, writeFile as writeFile6, readFile as readFile6, access as access2 } from "fs/promises";
1188762
+ import { join as join30 } from "path";
1188769
1188763
  function getClient2() {
1188770
1188764
  const settings = getSettings();
1188771
1188765
  const token = settings.integrations.cloudflareApiToken;
@@ -1188867,12 +1188861,12 @@ async function deleteDnsRecord(subdomain, domain) {
1188867
1188861
  }
1188868
1188862
  }
1188869
1188863
  function getCertDir(domain) {
1188870
- return join29(getFulcrumDir(), "certs", domain);
1188864
+ return join30(getFulcrumDir(), "certs", domain);
1188871
1188865
  }
1188872
1188866
  async function hasCertificate(domain) {
1188873
1188867
  const certDir = getCertDir(domain);
1188874
- const certPath = join29(certDir, "cert.pem");
1188875
- const keyPath = join29(certDir, "key.pem");
1188868
+ const certPath = join30(certDir, "cert.pem");
1188869
+ const keyPath = join30(certDir, "key.pem");
1188876
1188870
  try {
1188877
1188871
  await access2(certPath);
1188878
1188872
  await access2(keyPath);
@@ -1188887,8 +1188881,8 @@ async function getCertificatePaths(domain) {
1188887
1188881
  }
1188888
1188882
  const certDir = getCertDir(domain);
1188889
1188883
  return {
1188890
- certPath: join29(certDir, "cert.pem"),
1188891
- keyPath: join29(certDir, "key.pem")
1188884
+ certPath: join30(certDir, "cert.pem"),
1188885
+ keyPath: join30(certDir, "key.pem")
1188892
1188886
  };
1188893
1188887
  }
1188894
1188888
  function generateKeyAndCSR(hostnames) {
@@ -1189002,10 +1188996,10 @@ async function createOriginCACertificate(domain) {
1189002
1188996
  }
1189003
1188997
  const certDir = getCertDir(domain);
1189004
1188998
  await mkdir5(certDir, { recursive: true });
1189005
- const certPath = join29(certDir, "cert.pem");
1189006
- const keyPath = join29(certDir, "key.pem");
1189007
- await writeFile5(certPath, cert.certificate, "utf-8");
1189008
- await writeFile5(keyPath, privateKey, { mode: 384 });
1188999
+ const certPath = join30(certDir, "cert.pem");
1189000
+ const keyPath = join30(certDir, "key.pem");
1189001
+ await writeFile6(certPath, cert.certificate, "utf-8");
1189002
+ await writeFile6(keyPath, privateKey, { mode: 384 });
1189009
1189003
  log2.deploy.info("Origin CA certificate created and saved", {
1189010
1189004
  domain,
1189011
1189005
  certPath,
@@ -1189275,8 +1189269,8 @@ var init_cloudflare_tunnel = __esm(() => {
1189275
1189269
  });
1189276
1189270
 
1189277
1189271
  // server/services/traefik.ts
1189278
- import { writeFile as writeFile6, unlink as unlink4, access as access3, constants as constants2, readdir as readdir2, readFile as readFile7 } from "fs/promises";
1189279
- import { join as join30 } from "path";
1189272
+ import { writeFile as writeFile7, unlink as unlink5, access as access3, constants as constants2, readdir as readdir2, readFile as readFile7 } from "fs/promises";
1189273
+ import { join as join31 } from "path";
1189280
1189274
  async function detectTraefik() {
1189281
1189275
  try {
1189282
1189276
  const dokployResult = await runDocker([
@@ -1189356,7 +1189350,7 @@ function parseTraefikContainer(container, type) {
1189356
1189350
  if (type === "dokploy") {
1189357
1189351
  configDir = "/etc/dokploy/traefik/dynamic";
1189358
1189352
  } else if (dynamicMount) {
1189359
- configDir = dynamicMount.Source.includes("dynamic") ? dynamicMount.Source : join30(dynamicMount.Source, "dynamic");
1189353
+ configDir = dynamicMount.Source.includes("dynamic") ? dynamicMount.Source : join31(dynamicMount.Source, "dynamic");
1189360
1189354
  } else {
1189361
1189355
  configDir = "/etc/traefik/dynamic";
1189362
1189356
  }
@@ -1189397,7 +1189391,7 @@ async function checkRouteConflict(configDir, domain, currentAppId) {
1189397
1189391
  const files = await readdir2(configDir);
1189398
1189392
  const fulcrumFiles = files.filter((f) => f.startsWith("fulcrum-") && f.endsWith(".yml") && f !== getConfigFilename(currentAppId));
1189399
1189393
  for (const file of fulcrumFiles) {
1189400
- const filepath = join30(configDir, file);
1189394
+ const filepath = join31(configDir, file);
1189401
1189395
  const content = await readFile7(filepath, "utf-8");
1189402
1189396
  if (content.includes(`Host(\`${domain}\`)`)) {
1189403
1189397
  const match3 = file.match(/^fulcrum-(.+)\.yml$/);
@@ -1189429,7 +1189423,7 @@ async function addRoute(config2, appId, domain, upstreamUrl, options) {
1189429
1189423
  }
1189430
1189424
  const routerId = `fulcrum-${appId}`;
1189431
1189425
  const filename = getConfigFilename(appId, options?.appName);
1189432
- const filepath = join30(config2.configDir, filename);
1189426
+ const filepath = join31(config2.configDir, filename);
1189433
1189427
  let tlsConfig;
1189434
1189428
  let tlsStores;
1189435
1189429
  if (options?.tlsCert) {
@@ -1189483,7 +1189477,7 @@ async function addRoute(config2, appId, domain, upstreamUrl, options) {
1189483
1189477
  }
1189484
1189478
  try {
1189485
1189479
  const yamlContent = $stringify(traefikConfig);
1189486
- await writeFile6(filepath, yamlContent, "utf-8");
1189480
+ await writeFile7(filepath, yamlContent, "utf-8");
1189487
1189481
  log2.deploy.info("Added Traefik route", {
1189488
1189482
  appId,
1189489
1189483
  domain,
@@ -1189506,9 +1189500,9 @@ async function removeRoute(config2, appId, appName) {
1189506
1189500
  let deleted = false;
1189507
1189501
  let lastError;
1189508
1189502
  for (const filename of filesToTry) {
1189509
- const filepath = join30(config2.configDir, filename);
1189503
+ const filepath = join31(config2.configDir, filename);
1189510
1189504
  try {
1189511
- await unlink4(filepath);
1189505
+ await unlink5(filepath);
1189512
1189506
  log2.deploy.info("Removed Traefik route", { appId, filepath });
1189513
1189507
  deleted = true;
1189514
1189508
  } catch (err) {
@@ -1189533,14 +1189527,14 @@ var init_traefik = __esm(() => {
1189533
1189527
  });
1189534
1189528
 
1189535
1189529
  // server/services/traefik-docker.ts
1189536
- import { mkdir as mkdir6, writeFile as writeFile7, chmod } from "fs/promises";
1189530
+ import { mkdir as mkdir6, writeFile as writeFile8, chmod } from "fs/promises";
1189537
1189531
  import { existsSync as existsSync27 } from "fs";
1189538
- import { join as join31 } from "path";
1189532
+ import { join as join33 } from "path";
1189539
1189533
  function getTraefikConfigDir() {
1189540
- return join31(getFulcrumDir(), "traefik");
1189534
+ return join33(getFulcrumDir(), "traefik");
1189541
1189535
  }
1189542
1189536
  function getTraefikDynamicDir() {
1189543
- return join31(getFulcrumDir(), "traefik", "dynamic");
1189537
+ return join33(getFulcrumDir(), "traefik", "dynamic");
1189544
1189538
  }
1189545
1189539
  async function getTraefikContainerStatus() {
1189546
1189540
  const result = await runDocker([
@@ -1189580,7 +1189574,7 @@ async function ensureNetwork() {
1189580
1189574
  return { success: true };
1189581
1189575
  }
1189582
1189576
  function getCertsDir() {
1189583
- return join31(getFulcrumDir(), "certs");
1189577
+ return join33(getFulcrumDir(), "certs");
1189584
1189578
  }
1189585
1189579
  async function ensureConfigDirs() {
1189586
1189580
  const configDir = getTraefikConfigDir();
@@ -1189674,13 +1189668,13 @@ async function startTraefikContainer(acmeEmail) {
1189674
1189668
  await ensureConfigDirs();
1189675
1189669
  const configDir = getTraefikConfigDir();
1189676
1189670
  const dynamicDir = getTraefikDynamicDir();
1189677
- const traefikConfigPath = join31(configDir, "traefik.yml");
1189678
- await writeFile7(traefikConfigPath, generateTraefikConfig(acmeEmail), "utf-8");
1189679
- const middlewaresPath = join31(dynamicDir, "middlewares.yml");
1189680
- await writeFile7(middlewaresPath, generateMiddlewaresConfig(), "utf-8");
1189681
- const acmePath = join31(configDir, "acme.json");
1189671
+ const traefikConfigPath = join33(configDir, "traefik.yml");
1189672
+ await writeFile8(traefikConfigPath, generateTraefikConfig(acmeEmail), "utf-8");
1189673
+ const middlewaresPath = join33(dynamicDir, "middlewares.yml");
1189674
+ await writeFile8(middlewaresPath, generateMiddlewaresConfig(), "utf-8");
1189675
+ const acmePath = join33(configDir, "acme.json");
1189682
1189676
  if (!existsSync27(acmePath)) {
1189683
- await writeFile7(acmePath, "{}", "utf-8");
1189677
+ await writeFile8(acmePath, "{}", "utf-8");
1189684
1189678
  await chmod(acmePath, 384);
1189685
1189679
  }
1189686
1189680
  const isLinux = process.platform === "linux";
@@ -1189892,7 +1189886,7 @@ __export(exports_deployment, {
1189892
1189886
  broadcastProgress: () => broadcastProgress
1189893
1189887
  });
1189894
1189888
  import { spawn as spawn8 } from "child_process";
1189895
- import { join as join33 } from "path";
1189889
+ import { join as join35 } from "path";
1189896
1189890
  function getOrCreateLogState(appId) {
1189897
1189891
  let state = deploymentLogStates.get(appId);
1189898
1189892
  if (!state) {
@@ -1190116,7 +1190110,7 @@ async function deployApp(appId, options = {}, onProgress) {
1190116
1190110
  if (!buildResult.success) {
1190117
1190111
  throw new Error(`Build failed: ${buildResult.error}`);
1190118
1190112
  }
1190119
- const appDir = join33(getFulcrumDir(), "apps", appId);
1190113
+ const appDir = join35(getFulcrumDir(), "apps", appId);
1190120
1190114
  const swarmFileResult = await generateSwarmComposeFile(repo.path, app14.composeFile, projectName, traefikConfig.network, appDir, env);
1190121
1190115
  if (!swarmFileResult.success) {
1190122
1190116
  throw new Error(`Failed to generate Swarm compose file: ${swarmFileResult.error}`);
@@ -1210023,7 +1210017,7 @@ var logger = (fn = console.log) => {
1210023
1210017
 
1210024
1210018
  // server/app.ts
1210025
1210019
  import { readFile as readFile9 } from "fs/promises";
1210026
- import { join as join43 } from "path";
1210020
+ import { join as join44 } from "path";
1210027
1210021
  import { existsSync as existsSync35 } from "fs";
1210028
1210022
 
1210029
1210023
  // server/routes/health.ts
@@ -1217290,9 +1217284,9 @@ var config_default = app5;
1217290
1217284
 
1217291
1217285
  // server/routes/uploads.ts
1217292
1217286
  init_settings();
1217293
- import { mkdir as mkdir3, writeFile as writeFile3, readFile as readFile3, unlink as unlink3 } from "fs/promises";
1217287
+ import { mkdir as mkdir3, writeFile as writeFile4, readFile as readFile3, unlink as unlink4 } from "fs/promises";
1217294
1217288
  import { existsSync as existsSync19 } from "fs";
1217295
- import { join as join19 } from "path";
1217289
+ import { join as join20 } from "path";
1217296
1217290
  var mimeTypes2 = {
1217297
1217291
  png: "image/png",
1217298
1217292
  jpg: "image/jpeg",
@@ -1217331,17 +1217325,17 @@ app6.post("/sound", async (c) => {
1217331
1217325
  }
1217332
1217326
  const fulcrumDir = getFulcrumDir();
1217333
1217327
  const filename = `notification-sound.${extension}`;
1217334
- const filePath = join19(fulcrumDir, filename);
1217328
+ const filePath = join20(fulcrumDir, filename);
1217335
1217329
  for (const ext2 of ["mp3", "wav", "ogg"]) {
1217336
- const oldPath = join19(fulcrumDir, `notification-sound.${ext2}`);
1217330
+ const oldPath = join20(fulcrumDir, `notification-sound.${ext2}`);
1217337
1217331
  if (existsSync19(oldPath)) {
1217338
1217332
  try {
1217339
- await unlink3(oldPath);
1217333
+ await unlink4(oldPath);
1217340
1217334
  } catch {}
1217341
1217335
  }
1217342
1217336
  }
1217343
1217337
  const arrayBuffer = await file.arrayBuffer();
1217344
- await writeFile3(filePath, Buffer.from(arrayBuffer));
1217338
+ await writeFile4(filePath, Buffer.from(arrayBuffer));
1217345
1217339
  await updateNotificationSettings({
1217346
1217340
  sound: {
1217347
1217341
  ...getNotificationSettings().sound,
@@ -1217353,10 +1217347,10 @@ app6.post("/sound", async (c) => {
1217353
1217347
  app6.delete("/sound", async (c) => {
1217354
1217348
  const fulcrumDir = getFulcrumDir();
1217355
1217349
  for (const ext2 of ["mp3", "wav", "ogg"]) {
1217356
- const filePath = join19(fulcrumDir, `notification-sound.${ext2}`);
1217350
+ const filePath = join20(fulcrumDir, `notification-sound.${ext2}`);
1217357
1217351
  if (existsSync19(filePath)) {
1217358
1217352
  try {
1217359
- await unlink3(filePath);
1217353
+ await unlink4(filePath);
1217360
1217354
  } catch {}
1217361
1217355
  }
1217362
1217356
  }
@@ -1217398,14 +1217392,14 @@ app6.post("/", async (c) => {
1217398
1217392
  "image/svg+xml": "svg"
1217399
1217393
  };
1217400
1217394
  const extension = mimeToExt[file.type] || "png";
1217401
- const saveDir = join19(getFulcrumDir(), "uploads");
1217395
+ const saveDir = join20(getFulcrumDir(), "uploads");
1217402
1217396
  if (!existsSync19(saveDir)) {
1217403
1217397
  await mkdir3(saveDir, { recursive: true });
1217404
1217398
  }
1217405
1217399
  const filename = generateFilename(extension);
1217406
- const filePath = join19(saveDir, filename);
1217400
+ const filePath = join20(saveDir, filename);
1217407
1217401
  const arrayBuffer = await file.arrayBuffer();
1217408
- await writeFile3(filePath, Buffer.from(arrayBuffer));
1217402
+ await writeFile4(filePath, Buffer.from(arrayBuffer));
1217409
1217403
  return c.json({ path: filePath });
1217410
1217404
  });
1217411
1217405
  app6.get("/:filename", async (c) => {
@@ -1217413,7 +1217407,7 @@ app6.get("/:filename", async (c) => {
1217413
1217407
  if (!/^clipboard-\d{4}-\d{2}-\d{2}-\d{6}\.\w+$/.test(filename)) {
1217414
1217408
  return c.notFound();
1217415
1217409
  }
1217416
- const filePath = join19(getFulcrumDir(), "uploads", filename);
1217410
+ const filePath = join20(getFulcrumDir(), "uploads", filename);
1217417
1217411
  if (!existsSync19(filePath)) {
1217418
1217412
  return c.notFound();
1217419
1217413
  }
@@ -1217955,7 +1217949,7 @@ init_db2();
1217955
1217949
  init_drizzle_orm();
1217956
1217950
  init_settings();
1217957
1217951
  import { existsSync as existsSync21, readdirSync as readdirSync7 } from "fs";
1217958
- import { join as join21 } from "path";
1217952
+ import { join as join23 } from "path";
1217959
1217953
  var app9 = new Hono2;
1217960
1217954
  function toApiResponse2(row) {
1217961
1217955
  return {
@@ -1218022,7 +1218016,7 @@ app9.post("/", async (c) => {
1218022
1218016
  if (!existsSync21(repoPath)) {
1218023
1218017
  return c.json({ error: `Directory does not exist: ${repoPath}` }, 400);
1218024
1218018
  }
1218025
- const gitPath = join21(repoPath, ".git");
1218019
+ const gitPath = join23(repoPath, ".git");
1218026
1218020
  if (!existsSync21(gitPath)) {
1218027
1218021
  return c.json({ error: `Directory is not a git repository: ${repoPath}` }, 400);
1218028
1218022
  }
@@ -1218124,8 +1218118,8 @@ app9.post("/scan", async (c) => {
1218124
1218118
  continue;
1218125
1218119
  if (entry.name.startsWith("."))
1218126
1218120
  continue;
1218127
- const subPath = join21(directory, entry.name);
1218128
- const gitPath = join21(subPath, ".git");
1218121
+ const subPath = join23(directory, entry.name);
1218122
+ const gitPath = join23(subPath, ".git");
1218129
1218123
  if (existsSync21(gitPath)) {
1218130
1218124
  discovered.push({
1218131
1218125
  path: subPath,
@@ -1218155,8 +1218149,8 @@ init_nanoid();
1218155
1218149
  init_logger3();
1218156
1218150
  init_settings();
1218157
1218151
  import { existsSync as existsSync23, readFileSync as readFileSync12, writeFileSync as writeFileSync10, unlinkSync as unlinkSync7, mkdtempSync, rmSync as rmSync6 } from "fs";
1218158
- import { join as join23 } from "path";
1218159
- import { tmpdir as tmpdir3 } from "os";
1218152
+ import { join as join25 } from "path";
1218153
+ import { tmpdir as tmpdir4 } from "os";
1218160
1218154
  import { execSync as execSync6 } from "child_process";
1218161
1218155
  var app10 = new Hono2;
1218162
1218156
  function isUvInstalled() {
@@ -1218221,14 +1218215,14 @@ function parseCopierQuestions(yamlContent) {
1218221
1218215
  return questions;
1218222
1218216
  }
1218223
1218217
  function fetchCopierYamlFromGit(gitUrl) {
1218224
- const tempDir = mkdtempSync(join23(tmpdir3(), "copier-template-"));
1218218
+ const tempDir = mkdtempSync(join25(tmpdir4(), "copier-template-"));
1218225
1218219
  try {
1218226
1218220
  execSync6(`git clone --depth 1 "${gitUrl}" "${tempDir}"`, {
1218227
1218221
  encoding: "utf-8",
1218228
1218222
  stdio: "pipe"
1218229
1218223
  });
1218230
- const yamlPath = join23(tempDir, "copier.yml");
1218231
- const yamlAltPath = join23(tempDir, "copier.yaml");
1218224
+ const yamlPath = join25(tempDir, "copier.yml");
1218225
+ const yamlAltPath = join25(tempDir, "copier.yaml");
1218232
1218226
  let content = null;
1218233
1218227
  if (existsSync23(yamlPath)) {
1218234
1218228
  content = readFileSync12(yamlPath, "utf-8");
@@ -1218252,8 +1218246,8 @@ async function fetchCopierYaml(source) {
1218252
1218246
  const repo = db2.select().from(repositories).where(eq(repositories.id, source)).get();
1218253
1218247
  const templatePath = repo ? repo.path : source;
1218254
1218248
  if (existsSync23(templatePath)) {
1218255
- const yamlPath = join23(templatePath, "copier.yml");
1218256
- const yamlAltPath = join23(templatePath, "copier.yaml");
1218249
+ const yamlPath = join25(templatePath, "copier.yml");
1218250
+ const yamlAltPath = join25(templatePath, "copier.yaml");
1218257
1218251
  if (existsSync23(yamlPath)) {
1218258
1218252
  return { content: readFileSync12(yamlPath, "utf-8"), templatePath };
1218259
1218253
  }
@@ -1218309,7 +1218303,7 @@ app10.post("/create", async (c) => {
1218309
1218303
  const outputPath = expandPath(rawOutputPath);
1218310
1218304
  const repo = db2.select().from(repositories).where(eq(repositories.id, templateSource)).get();
1218311
1218305
  const templatePath = repo ? repo.path : templateSource;
1218312
- const fullOutputPath = join23(outputPath, projectName);
1218306
+ const fullOutputPath = join25(outputPath, projectName);
1218313
1218307
  if (existsSync23(fullOutputPath)) {
1218314
1218308
  return c.json({ error: `Output directory already exists: ${fullOutputPath}` }, 400);
1218315
1218309
  }
@@ -1218320,7 +1218314,7 @@ app10.post("/create", async (c) => {
1218320
1218314
  }
1218321
1218315
  filteredAnswers[key] = value;
1218322
1218316
  }
1218323
- answersFile = join23(tmpdir3(), `copier-answers-${crypto.randomUUID()}.json`);
1218317
+ answersFile = join25(tmpdir4(), `copier-answers-${crypto.randomUUID()}.json`);
1218324
1218318
  writeFileSync10(answersFile, JSON.stringify(filteredAnswers));
1218325
1218319
  try {
1218326
1218320
  const trustFlag = trust ? "--trust " : "";
@@ -1218335,7 +1218329,7 @@ app10.post("/create", async (c) => {
1218335
1218329
  log2.api.error("Copier execution failed", { templatePath, outputPath: fullOutputPath, error: errorMessage });
1218336
1218330
  return c.json({ error: errorMessage }, 500);
1218337
1218331
  }
1218338
- const gitPath = join23(fullOutputPath, ".git");
1218332
+ const gitPath = join25(fullOutputPath, ".git");
1218339
1218333
  if (!existsSync23(gitPath)) {
1218340
1218334
  try {
1218341
1218335
  execSync6("git init", {
@@ -1222141,7 +1222135,7 @@ init_dtach_service();
1222141
1222135
  import { readdirSync as readdirSync8, readFileSync as readFileSync13, readlinkSync as readlinkSync3, existsSync as existsSync25 } from "fs";
1222142
1222136
  import { execSync as execSync8 } from "child_process";
1222143
1222137
  import { homedir as homedir8 } from "os";
1222144
- import { join as join25 } from "path";
1222138
+ import { join as join26 } from "path";
1222145
1222139
 
1222146
1222140
  // server/services/metrics-collector.ts
1222147
1222141
  init_db2();
@@ -1223051,7 +1223045,7 @@ var cachedUsage = null;
1223051
1223045
  var usageCacheTimestamp = 0;
1223052
1223046
  var USAGE_CACHE_MS = 15 * 1000;
1223053
1223047
  async function getClaudeOAuthToken() {
1223054
- const primaryPath = join25(homedir8(), ".claude", ".credentials.json");
1223048
+ const primaryPath = join26(homedir8(), ".claude", ".credentials.json");
1223055
1223049
  try {
1223056
1223050
  if (existsSync25(primaryPath)) {
1223057
1223051
  const content = readFileSync13(primaryPath, "utf-8");
@@ -1223223,7 +1223217,7 @@ monitoringRoutes.get("/channel-message-counts", (_c) => {
1223223
1223217
  init_claude_code_path();
1223224
1223218
  import { execSync as execSync9 } from "child_process";
1223225
1223219
  import { existsSync as existsSync26 } from "fs";
1223226
- import { join as join26 } from "path";
1223220
+ import { join as join27 } from "path";
1223227
1223221
  import { homedir as homedir9 } from "os";
1223228
1223222
  var app12 = new Hono2;
1223229
1223223
  function isCommandAvailable(command) {
@@ -1223247,8 +1223241,8 @@ function isOpenCodeInstalled() {
1223247
1223241
  return pathCheck;
1223248
1223242
  }
1223249
1223243
  const commonPaths = [
1223250
- join26(homedir9(), ".opencode", "bin", "opencode"),
1223251
- join26(homedir9(), ".local", "bin", "opencode"),
1223244
+ join27(homedir9(), ".opencode", "bin", "opencode"),
1223245
+ join27(homedir9(), ".local", "bin", "opencode"),
1223252
1223246
  "/usr/local/bin/opencode",
1223253
1223247
  "/opt/homebrew/bin/opencode"
1223254
1223248
  ];
@@ -1223492,7 +1223486,7 @@ init_deployment();
1223492
1223486
  init_docker_swarm();
1223493
1223487
  init_docker_compose();
1223494
1223488
  import { rm, readFile as readFile8 } from "fs/promises";
1223495
- import { join as join36 } from "path";
1223489
+ import { join as join37 } from "path";
1223496
1223490
 
1223497
1223491
  // server/services/git-watcher.ts
1223498
1223492
  init_drizzle_orm();
@@ -1224026,7 +1224020,7 @@ app14.delete("/:id", async (c) => {
1224026
1224020
  }
1224027
1224021
  }
1224028
1224022
  }
1224029
- const appDir = join36(getFulcrumDir(), "apps", id);
1224023
+ const appDir = join37(getFulcrumDir(), "apps", id);
1224030
1224024
  await rm(appDir, { recursive: true, force: true }).catch((err) => {
1224031
1224025
  log2.deploy.warn("Failed to delete app directory during app deletion", {
1224032
1224026
  appId: id,
@@ -1224358,8 +1224352,8 @@ app14.get("/:id/swarm-compose", async (c) => {
1224358
1224352
  }
1224359
1224353
  const { generateSwarmComposeFile: generateSwarmComposeFile2 } = await Promise.resolve().then(() => (init_docker_swarm(), exports_docker_swarm));
1224360
1224354
  const { getProjectName: getProjectName2 } = await Promise.resolve().then(() => (init_deployment(), exports_deployment));
1224361
- const { tmpdir: tmpdir4 } = await import("os");
1224362
- const tempDir = join36(tmpdir4(), `swarm-preview-${id}-${Date.now()}`);
1224355
+ const { tmpdir: tmpdir5 } = await import("os");
1224356
+ const tempDir = join37(tmpdir5(), `swarm-preview-${id}-${Date.now()}`);
1224363
1224357
  try {
1224364
1224358
  const projectName = getProjectName2(id, repo.displayName);
1224365
1224359
  const result = await generateSwarmComposeFile2(repo.path, appRecord.composeFile, projectName, undefined, tempDir, env);
@@ -1224647,9 +1224641,9 @@ import { platform as platform4 } from "os";
1224647
1224641
  init_logger3();
1224648
1224642
  import { execSync as execSync10 } from "child_process";
1224649
1224643
  import { homedir as homedir11, platform as platform2 } from "os";
1224650
- import { join as join37 } from "path";
1224644
+ import { join as join38 } from "path";
1224651
1224645
  import { existsSync as existsSync29, mkdirSync as mkdirSync10, writeFileSync as writeFileSync11, readFileSync as readFileSync15, unlinkSync as unlinkSync8 } from "fs";
1224652
- var USER_UNIT_DIR = join37(homedir11(), ".config/systemd/user");
1224646
+ var USER_UNIT_DIR = join38(homedir11(), ".config/systemd/user");
1224653
1224647
  var systemdAvailable = null;
1224654
1224648
  function isSystemdAvailable() {
1224655
1224649
  if (systemdAvailable !== null) {
@@ -1225042,8 +1225036,8 @@ function createTimer(config2) {
1225042
1225036
  ensureUserUnitDir();
1225043
1225037
  const timerName = config2.name.endsWith(".timer") ? config2.name : `${config2.name}.timer`;
1225044
1225038
  const serviceName = timerName.replace(".timer", ".service");
1225045
- const timerPath = join37(USER_UNIT_DIR, timerName);
1225046
- const servicePath = join37(USER_UNIT_DIR, serviceName);
1225039
+ const timerPath = join38(USER_UNIT_DIR, timerName);
1225040
+ const servicePath = join38(USER_UNIT_DIR, serviceName);
1225047
1225041
  if (existsSync29(timerPath)) {
1225048
1225042
  throw new Error(`Timer ${timerName} already exists`);
1225049
1225043
  }
@@ -1225080,8 +1225074,8 @@ WantedBy=default.target
1225080
1225074
  function updateTimer(name, updates) {
1225081
1225075
  const timerName = name.endsWith(".timer") ? name : `${name}.timer`;
1225082
1225076
  const serviceName = timerName.replace(".timer", ".service");
1225083
- const timerPath = join37(USER_UNIT_DIR, timerName);
1225084
- const servicePath = join37(USER_UNIT_DIR, serviceName);
1225077
+ const timerPath = join38(USER_UNIT_DIR, timerName);
1225078
+ const servicePath = join38(USER_UNIT_DIR, serviceName);
1225085
1225079
  if (!existsSync29(timerPath)) {
1225086
1225080
  throw new Error(`Timer ${timerName} not found`);
1225087
1225081
  }
@@ -1225127,8 +1225121,8 @@ WorkingDirectory=${updates.workingDirectory}`);
1225127
1225121
  function deleteTimer(name) {
1225128
1225122
  const timerName = name.endsWith(".timer") ? name : `${name}.timer`;
1225129
1225123
  const serviceName = timerName.replace(".timer", ".service");
1225130
- const timerPath = join37(USER_UNIT_DIR, timerName);
1225131
- const servicePath = join37(USER_UNIT_DIR, serviceName);
1225124
+ const timerPath = join38(USER_UNIT_DIR, timerName);
1225125
+ const servicePath = join38(USER_UNIT_DIR, serviceName);
1225132
1225126
  try {
1225133
1225127
  systemctl(["stop", timerName], "user");
1225134
1225128
  } catch {}
@@ -1225149,9 +1225143,9 @@ function deleteTimer(name) {
1225149
1225143
  init_logger3();
1225150
1225144
  import { execSync as execSync11 } from "child_process";
1225151
1225145
  import { homedir as homedir12, platform as platform3 } from "os";
1225152
- import { join as join38 } from "path";
1225146
+ import { join as join39 } from "path";
1225153
1225147
  import { existsSync as existsSync30, readdirSync as readdirSync9 } from "fs";
1225154
- var USER_LAUNCH_AGENTS = join38(homedir12(), "Library/LaunchAgents");
1225148
+ var USER_LAUNCH_AGENTS = join39(homedir12(), "Library/LaunchAgents");
1225155
1225149
  var GLOBAL_LAUNCH_AGENTS = "/Library/LaunchAgents";
1225156
1225150
  var GLOBAL_LAUNCH_DAEMONS = "/Library/LaunchDaemons";
1225157
1225151
  var launchdAvailable = null;
@@ -1225339,7 +1225333,7 @@ function scanPlistDirectory(dir, scope) {
1225339
1225333
  const files = readdirSync9(dir);
1225340
1225334
  for (const file of files) {
1225341
1225335
  if (file.endsWith(".plist")) {
1225342
- results.push({ path: join38(dir, file), scope });
1225336
+ results.push({ path: join39(dir, file), scope });
1225343
1225337
  }
1225344
1225338
  }
1225345
1225339
  } catch (err) {
@@ -1225394,7 +1225388,7 @@ function getJob(name, scope) {
1225394
1225388
  let plist = null;
1225395
1225389
  for (const dir of directories) {
1225396
1225390
  const candidates = [
1225397
- join38(dir, `${name}.plist`)
1225391
+ join39(dir, `${name}.plist`)
1225398
1225392
  ];
1225399
1225393
  for (const candidate of candidates) {
1225400
1225394
  if (existsSync30(candidate)) {
@@ -1225413,7 +1225407,7 @@ function getJob(name, scope) {
1225413
1225407
  const files = readdirSync9(dir);
1225414
1225408
  for (const file of files) {
1225415
1225409
  if (file.endsWith(".plist")) {
1225416
- const path13 = join38(dir, file);
1225410
+ const path13 = join39(dir, file);
1225417
1225411
  const parsed = parsePlist(path13);
1225418
1225412
  if (parsed?.Label === name) {
1225419
1225413
  plistPath = path13;
@@ -1225928,7 +1225922,7 @@ init_db2();
1225928
1225922
  init_drizzle_orm();
1225929
1225923
  import { existsSync as existsSync31, rmSync as rmSync7 } from "fs";
1225930
1225924
  import { homedir as homedir13 } from "os";
1225931
- import { resolve as resolve5, join as join39 } from "path";
1225925
+ import { resolve as resolve5, join as join40 } from "path";
1225932
1225926
  init_settings();
1225933
1225927
  init_terminal_ws();
1225934
1225928
  import * as fs18 from "fs";
@@ -1226233,7 +1226227,7 @@ app19.post("/", async (c) => {
1226233
1226227
  if (repoName.includes("/") || repoName.includes("\\")) {
1226234
1226228
  return c.json({ error: "Folder name cannot contain path separators" }, 400);
1226235
1226229
  }
1226236
- const targetPath = join39(parentDir, repoName);
1226230
+ const targetPath = join40(parentDir, repoName);
1226237
1226231
  const resolvedParent = resolve5(parentDir);
1226238
1226232
  const resolvedTarget = resolve5(targetPath);
1226239
1226233
  if (!resolvedTarget.startsWith(resolvedParent + "/") && resolvedTarget !== resolvedParent) {
@@ -1226428,7 +1226422,7 @@ app19.delete("/:id", async (c) => {
1226428
1226422
  return c.json({ error: "Cannot delete system directory" }, 400);
1226429
1226423
  }
1226430
1226424
  if (existsSync31(repoPath)) {
1226431
- const gitPath = join39(repoPath, ".git");
1226425
+ const gitPath = join40(repoPath, ".git");
1226432
1226426
  if (!existsSync31(gitPath)) {
1226433
1226427
  return c.json({ error: "Directory does not appear to be a git repository" }, 400);
1226434
1226428
  }
@@ -1226775,7 +1226769,7 @@ app19.post("/:id/repositories", async (c) => {
1226775
1226769
  if (repoName.includes("/") || repoName.includes("\\")) {
1226776
1226770
  return c.json({ error: "Folder name cannot contain path separators" }, 400);
1226777
1226771
  }
1226778
- const targetPath = join39(parentDir, repoName);
1226772
+ const targetPath = join40(parentDir, repoName);
1226779
1226773
  const resolvedParent = resolve5(parentDir);
1226780
1226774
  const resolvedTarget = resolve5(targetPath);
1226781
1226775
  if (!resolvedTarget.startsWith(resolvedParent + "/") && resolvedTarget !== resolvedParent) {
@@ -1259949,7 +1259943,7 @@ function registerTools(server2, client3) {
1259949
1259943
  }
1259950
1259944
  // cli/src/utils/server.ts
1259951
1259945
  import { existsSync as existsSync33, readFileSync as readFileSync17, writeFileSync as writeFileSync13, mkdirSync as mkdirSync12, cpSync } from "fs";
1259952
- import { join as join41 } from "path";
1259946
+ import { join as join42 } from "path";
1259953
1259947
  import { homedir as homedir14 } from "os";
1259954
1259948
  var DEFAULT_PORT = 7777;
1259955
1259949
  function getPortFromSettings(settings) {
@@ -1259965,7 +1259959,7 @@ function getPortFromSettings(settings) {
1259965
1259959
  }
1259966
1259960
  function expandPath2(p) {
1259967
1259961
  if (p.startsWith("~/")) {
1259968
- return join41(homedir14(), p.slice(2));
1259962
+ return join42(homedir14(), p.slice(2));
1259969
1259963
  }
1259970
1259964
  return p;
1259971
1259965
  }
@@ -1259989,20 +1259983,20 @@ function discoverServerUrl(urlOverride, portOverride) {
1259989
1259983
  return process.env.FULCRUM_URL;
1259990
1259984
  }
1259991
1259985
  if (process.env.FULCRUM_DIR) {
1259992
- const fulcrumDirSettings = join41(expandPath2(process.env.FULCRUM_DIR), "settings.json");
1259986
+ const fulcrumDirSettings = join42(expandPath2(process.env.FULCRUM_DIR), "settings.json");
1259993
1259987
  const settings = readSettingsFile(fulcrumDirSettings);
1259994
1259988
  const port = getPortFromSettings(settings);
1259995
1259989
  if (port) {
1259996
1259990
  return `http://localhost:${port}`;
1259997
1259991
  }
1259998
1259992
  }
1259999
- const cwdSettings = join41(process.cwd(), ".fulcrum", "settings.json");
1259993
+ const cwdSettings = join42(process.cwd(), ".fulcrum", "settings.json");
1260000
1259994
  const localSettings = readSettingsFile(cwdSettings);
1260001
1259995
  const localPort = getPortFromSettings(localSettings);
1260002
1259996
  if (localPort) {
1260003
1259997
  return `http://localhost:${localPort}`;
1260004
1259998
  }
1260005
- const globalSettings = join41(homedir14(), ".fulcrum", "settings.json");
1259999
+ const globalSettings = join42(homedir14(), ".fulcrum", "settings.json");
1260006
1260000
  const homeSettings = readSettingsFile(globalSettings);
1260007
1260001
  const homePort = getPortFromSettings(homeSettings);
1260008
1260002
  if (homePort) {
@@ -1260769,7 +1260763,7 @@ mcpRoutes.all("/", async (c) => {
1260769
1260763
  });
1260770
1260764
  const server2 = new McpServer({
1260771
1260765
  name: "fulcrum",
1260772
- version: "3.0.0"
1260766
+ version: "3.0.2"
1260773
1260767
  });
1260774
1260768
  const client3 = new FulcrumClient(`http://localhost:${port}`);
1260775
1260769
  registerTools(server2, client3);
@@ -1263468,9 +1263462,9 @@ var search_default = app28;
1263468
1263462
  init_logger3();
1263469
1263463
  function getDistPath() {
1263470
1263464
  if (process.env.FULCRUM_PACKAGE_ROOT) {
1263471
- return join43(process.env.FULCRUM_PACKAGE_ROOT, "dist");
1263465
+ return join44(process.env.FULCRUM_PACKAGE_ROOT, "dist");
1263472
1263466
  }
1263473
- return join43(process.cwd(), "dist");
1263467
+ return join44(process.cwd(), "dist");
1263474
1263468
  }
1263475
1263469
  function createApp() {
1263476
1263470
  const app29 = new Hono2;
@@ -1263564,14 +1263558,14 @@ function createApp() {
1263564
1263558
  });
1263565
1263559
  };
1263566
1263560
  app29.get("/assets/*", async (c) => {
1263567
- const assetPath = join43(distPath, c.req.path);
1263561
+ const assetPath = join44(distPath, c.req.path);
1263568
1263562
  if (existsSync35(assetPath)) {
1263569
1263563
  return serveFile(assetPath, true);
1263570
1263564
  }
1263571
1263565
  return c.notFound();
1263572
1263566
  });
1263573
1263567
  app29.get("/sounds/*", async (c) => {
1263574
- const soundPath = join43(distPath, c.req.path);
1263568
+ const soundPath = join44(distPath, c.req.path);
1263575
1263569
  if (existsSync35(soundPath)) {
1263576
1263570
  return serveFile(soundPath);
1263577
1263571
  }
@@ -1263580,7 +1263574,7 @@ function createApp() {
1263580
1263574
  const staticFiles = ["fulcrum-icon.png", "fulcrum-logo.jpeg", "vite.svg", "logo.png", "goat.jpeg"];
1263581
1263575
  for (const file2 of staticFiles) {
1263582
1263576
  app29.get(`/${file2}`, async () => {
1263583
- const filePath = join43(distPath, file2);
1263577
+ const filePath = join44(distPath, file2);
1263584
1263578
  if (existsSync35(filePath)) {
1263585
1263579
  return serveFile(filePath);
1263586
1263580
  }
@@ -1263592,7 +1263586,7 @@ function createApp() {
1263592
1263586
  if (path15.startsWith("/api/") || path15.startsWith("/ws/") || path15 === "/health") {
1263593
1263587
  return next();
1263594
1263588
  }
1263595
- const html = await readFile9(join43(distPath, "index.html"), "utf-8");
1263589
+ const html = await readFile9(join44(distPath, "index.html"), "utf-8");
1263596
1263590
  return c.html(html, {
1263597
1263591
  headers: { "Cache-Control": "no-cache, must-revalidate" }
1263598
1263592
  });