@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/README.md +1 -1
- package/bin/fulcrum.js +3 -3
- package/dist/assets/index-Ck5YiSQm.css +1 -0
- package/dist/assets/{index-BPydksdv.js → index-Dr24efhZ.js} +32 -32
- package/dist/index.html +2 -2
- package/package.json +1 -1
- package/server/index.js +137 -143
- package/dist/assets/index-XD1DMF7S.css +0 -1
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
|
|
1154264
|
+
const parts = [];
|
|
1154261
1154265
|
for (const attachment of options.attachments) {
|
|
1154262
1154266
|
switch (attachment.type) {
|
|
1154263
|
-
case "image":
|
|
1154264
|
-
|
|
1154265
|
-
|
|
1154266
|
-
|
|
1154267
|
-
|
|
1154268
|
-
|
|
1154269
|
-
|
|
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
|
-
|
|
1154275
|
-
|
|
1154276
|
-
|
|
1154277
|
-
|
|
1154278
|
-
|
|
1154279
|
-
|
|
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
|
-
|
|
1154286
|
-
|
|
1154287
|
-
text: `--- ${attachment.filename} ---
|
|
1154288
|
-
${attachment.data}`
|
|
1154289
|
-
});
|
|
1154286
|
+
parts.push(`--- ${attachment.filename} ---
|
|
1154287
|
+
${attachment.data}`);
|
|
1154290
1154288
|
break;
|
|
1154291
1154289
|
}
|
|
1154292
1154290
|
}
|
|
1154293
|
-
|
|
1154294
|
-
|
|
1154295
|
-
|
|
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
|
|
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 =
|
|
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 =
|
|
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
|
|
1164618
|
+
import { mkdir as mkdir4, readFile as readFile5, writeFile as writeFile5 } from "fs/promises";
|
|
1164625
1164619
|
import { createServer } from "net";
|
|
1164626
|
-
import { join as
|
|
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(
|
|
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 =
|
|
1164824
|
-
const swarmPath =
|
|
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
|
|
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
|
|
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
|
|
1188768
|
-
import { join as
|
|
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
|
|
1188864
|
+
return join30(getFulcrumDir(), "certs", domain);
|
|
1188871
1188865
|
}
|
|
1188872
1188866
|
async function hasCertificate(domain) {
|
|
1188873
1188867
|
const certDir = getCertDir(domain);
|
|
1188874
|
-
const certPath =
|
|
1188875
|
-
const keyPath =
|
|
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:
|
|
1188891
|
-
keyPath:
|
|
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 =
|
|
1189006
|
-
const keyPath =
|
|
1189007
|
-
await
|
|
1189008
|
-
await
|
|
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
|
|
1189279
|
-
import { join as
|
|
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 :
|
|
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 =
|
|
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 =
|
|
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
|
|
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 =
|
|
1189503
|
+
const filepath = join31(config2.configDir, filename);
|
|
1189510
1189504
|
try {
|
|
1189511
|
-
await
|
|
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
|
|
1189530
|
+
import { mkdir as mkdir6, writeFile as writeFile8, chmod } from "fs/promises";
|
|
1189537
1189531
|
import { existsSync as existsSync27 } from "fs";
|
|
1189538
|
-
import { join as
|
|
1189532
|
+
import { join as join33 } from "path";
|
|
1189539
1189533
|
function getTraefikConfigDir() {
|
|
1189540
|
-
return
|
|
1189534
|
+
return join33(getFulcrumDir(), "traefik");
|
|
1189541
1189535
|
}
|
|
1189542
1189536
|
function getTraefikDynamicDir() {
|
|
1189543
|
-
return
|
|
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
|
|
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 =
|
|
1189678
|
-
await
|
|
1189679
|
-
const middlewaresPath =
|
|
1189680
|
-
await
|
|
1189681
|
-
const acmePath =
|
|
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
|
|
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
|
|
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 =
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
1217328
|
+
const filePath = join20(fulcrumDir, filename);
|
|
1217335
1217329
|
for (const ext2 of ["mp3", "wav", "ogg"]) {
|
|
1217336
|
-
const oldPath =
|
|
1217330
|
+
const oldPath = join20(fulcrumDir, `notification-sound.${ext2}`);
|
|
1217337
1217331
|
if (existsSync19(oldPath)) {
|
|
1217338
1217332
|
try {
|
|
1217339
|
-
await
|
|
1217333
|
+
await unlink4(oldPath);
|
|
1217340
1217334
|
} catch {}
|
|
1217341
1217335
|
}
|
|
1217342
1217336
|
}
|
|
1217343
1217337
|
const arrayBuffer = await file.arrayBuffer();
|
|
1217344
|
-
await
|
|
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 =
|
|
1217350
|
+
const filePath = join20(fulcrumDir, `notification-sound.${ext2}`);
|
|
1217357
1217351
|
if (existsSync19(filePath)) {
|
|
1217358
1217352
|
try {
|
|
1217359
|
-
await
|
|
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 =
|
|
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 =
|
|
1217400
|
+
const filePath = join20(saveDir, filename);
|
|
1217407
1217401
|
const arrayBuffer = await file.arrayBuffer();
|
|
1217408
|
-
await
|
|
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 =
|
|
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
|
|
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 =
|
|
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 =
|
|
1218128
|
-
const gitPath =
|
|
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
|
|
1218159
|
-
import { tmpdir as
|
|
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(
|
|
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 =
|
|
1218231
|
-
const yamlAltPath =
|
|
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 =
|
|
1218256
|
-
const yamlAltPath =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
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
|
-
|
|
1223251
|
-
|
|
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
|
|
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 =
|
|
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:
|
|
1224362
|
-
const tempDir =
|
|
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
|
|
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 =
|
|
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 =
|
|
1225046
|
-
const servicePath =
|
|
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 =
|
|
1225084
|
-
const servicePath =
|
|
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 =
|
|
1225131
|
-
const servicePath =
|
|
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
|
|
1225146
|
+
import { join as join39 } from "path";
|
|
1225153
1225147
|
import { existsSync as existsSync30, readdirSync as readdirSync9 } from "fs";
|
|
1225154
|
-
var USER_LAUNCH_AGENTS =
|
|
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:
|
|
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
|
-
|
|
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 =
|
|
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
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
|
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
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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.
|
|
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
|
|
1263465
|
+
return join44(process.env.FULCRUM_PACKAGE_ROOT, "dist");
|
|
1263472
1263466
|
}
|
|
1263473
|
-
return
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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(
|
|
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
|
});
|