codexapp 0.1.22 → 0.1.23
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/index.html
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<title>Codex Web Local</title>
|
|
7
|
-
<script type="module" crossorigin src="/assets/index-
|
|
8
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
7
|
+
<script type="module" crossorigin src="/assets/index-oKlr-X4X.js"></script>
|
|
8
|
+
<link rel="stylesheet" crossorigin href="/assets/index-BNrLRqWJ.css">
|
|
9
9
|
</head>
|
|
10
10
|
<body class="bg-slate-950">
|
|
11
11
|
<div id="app"></div>
|
package/dist-cli/index.js
CHANGED
|
@@ -14,8 +14,9 @@ import qrcode from "qrcode-terminal";
|
|
|
14
14
|
|
|
15
15
|
// src/server/httpServer.ts
|
|
16
16
|
import { fileURLToPath } from "url";
|
|
17
|
-
import {
|
|
17
|
+
import { dirname, extname, isAbsolute as isAbsolute2, join as join2 } from "path";
|
|
18
18
|
import { existsSync } from "fs";
|
|
19
|
+
import { readdir as readdir2, stat as stat2 } from "fs/promises";
|
|
19
20
|
import express from "express";
|
|
20
21
|
|
|
21
22
|
// src/server/codexAppServerBridge.ts
|
|
@@ -1486,6 +1487,57 @@ function normalizeLocalPath(rawPath) {
|
|
|
1486
1487
|
}
|
|
1487
1488
|
return trimmed;
|
|
1488
1489
|
}
|
|
1490
|
+
function decodeBrowsePath(rawPath) {
|
|
1491
|
+
if (!rawPath) return "";
|
|
1492
|
+
try {
|
|
1493
|
+
return decodeURIComponent(rawPath);
|
|
1494
|
+
} catch {
|
|
1495
|
+
return rawPath;
|
|
1496
|
+
}
|
|
1497
|
+
}
|
|
1498
|
+
function escapeHtml(value) {
|
|
1499
|
+
return value.replace(/&/gu, "&").replace(/</gu, "<").replace(/>/gu, ">").replace(/"/gu, """).replace(/'/gu, "'");
|
|
1500
|
+
}
|
|
1501
|
+
function toBrowseHref(pathValue) {
|
|
1502
|
+
return `/codex-local-browse${encodeURI(pathValue)}`;
|
|
1503
|
+
}
|
|
1504
|
+
async function renderDirectoryListing(res, localPath) {
|
|
1505
|
+
const entries = await readdir2(localPath, { withFileTypes: true });
|
|
1506
|
+
const sorted = entries.slice().sort((a, b) => {
|
|
1507
|
+
if (a.isDirectory() && !b.isDirectory()) return -1;
|
|
1508
|
+
if (!a.isDirectory() && b.isDirectory()) return 1;
|
|
1509
|
+
return a.name.localeCompare(b.name);
|
|
1510
|
+
});
|
|
1511
|
+
const parentPath = dirname(localPath);
|
|
1512
|
+
const rows = sorted.map((entry) => {
|
|
1513
|
+
const entryPath = join2(localPath, entry.name);
|
|
1514
|
+
const suffix = entry.isDirectory() ? "/" : "";
|
|
1515
|
+
return `<li><a href="${escapeHtml(toBrowseHref(entryPath))}">${escapeHtml(entry.name)}${suffix}</a></li>`;
|
|
1516
|
+
}).join("\n");
|
|
1517
|
+
const parentLink = localPath !== parentPath ? `<p><a href="${escapeHtml(toBrowseHref(parentPath))}">..</a></p>` : "";
|
|
1518
|
+
const html = `<!doctype html>
|
|
1519
|
+
<html lang="en">
|
|
1520
|
+
<head>
|
|
1521
|
+
<meta charset="utf-8" />
|
|
1522
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
1523
|
+
<title>Index of ${escapeHtml(localPath)}</title>
|
|
1524
|
+
<style>
|
|
1525
|
+
body { font-family: ui-monospace, Menlo, Monaco, monospace; margin: 24px; background: #0b1020; color: #dbe6ff; }
|
|
1526
|
+
a { color: #8cc2ff; text-decoration: none; }
|
|
1527
|
+
a:hover { text-decoration: underline; }
|
|
1528
|
+
ul { list-style: none; padding: 0; margin: 12px 0 0; }
|
|
1529
|
+
li { padding: 3px 0; }
|
|
1530
|
+
h1 { font-size: 18px; margin: 0; word-break: break-all; }
|
|
1531
|
+
</style>
|
|
1532
|
+
</head>
|
|
1533
|
+
<body>
|
|
1534
|
+
<h1>Index of ${escapeHtml(localPath)}</h1>
|
|
1535
|
+
${parentLink}
|
|
1536
|
+
<ul>${rows}</ul>
|
|
1537
|
+
</body>
|
|
1538
|
+
</html>`;
|
|
1539
|
+
res.status(200).type("text/html; charset=utf-8").send(html);
|
|
1540
|
+
}
|
|
1489
1541
|
function createServer(options = {}) {
|
|
1490
1542
|
const app = express();
|
|
1491
1543
|
const bridge = createCodexBridgeMiddleware();
|
|
@@ -1521,11 +1573,34 @@ function createServer(options = {}) {
|
|
|
1521
1573
|
return;
|
|
1522
1574
|
}
|
|
1523
1575
|
res.setHeader("Cache-Control", "private, no-store");
|
|
1524
|
-
res.
|
|
1576
|
+
res.setHeader("Content-Disposition", "inline");
|
|
1577
|
+
res.sendFile(localPath, { dotfiles: "allow" }, (error) => {
|
|
1525
1578
|
if (!error) return;
|
|
1526
1579
|
if (!res.headersSent) res.status(404).json({ error: "File not found." });
|
|
1527
1580
|
});
|
|
1528
1581
|
});
|
|
1582
|
+
app.get("/codex-local-browse/*path", async (req, res) => {
|
|
1583
|
+
const rawPath = typeof req.params.path === "string" ? req.params.path : "";
|
|
1584
|
+
const localPath = decodeBrowsePath(`/${rawPath}`);
|
|
1585
|
+
if (!localPath || !isAbsolute2(localPath)) {
|
|
1586
|
+
res.status(400).json({ error: "Expected absolute local file path." });
|
|
1587
|
+
return;
|
|
1588
|
+
}
|
|
1589
|
+
try {
|
|
1590
|
+
const fileStat = await stat2(localPath);
|
|
1591
|
+
res.setHeader("Cache-Control", "private, no-store");
|
|
1592
|
+
if (fileStat.isDirectory()) {
|
|
1593
|
+
await renderDirectoryListing(res, localPath);
|
|
1594
|
+
return;
|
|
1595
|
+
}
|
|
1596
|
+
res.sendFile(localPath, { dotfiles: "allow" }, (error) => {
|
|
1597
|
+
if (!error) return;
|
|
1598
|
+
if (!res.headersSent) res.status(404).json({ error: "File not found." });
|
|
1599
|
+
});
|
|
1600
|
+
} catch {
|
|
1601
|
+
res.status(404).json({ error: "File not found." });
|
|
1602
|
+
}
|
|
1603
|
+
});
|
|
1529
1604
|
const hasFrontendAssets = existsSync(spaEntryFile);
|
|
1530
1605
|
if (hasFrontendAssets) {
|
|
1531
1606
|
app.use(express.static(distDir));
|