glassbox 0.4.4 → 0.5.0
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/cli.js +134 -24
- package/dist/client/app.global.js +8 -8
- package/dist/client/styles.css +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -395,7 +395,7 @@ init_queries();
|
|
|
395
395
|
init_connection();
|
|
396
396
|
import { mkdirSync as mkdirSync7 } from "fs";
|
|
397
397
|
import { tmpdir } from "os";
|
|
398
|
-
import { join as join10, resolve as
|
|
398
|
+
import { join as join10, resolve as resolve5 } from "path";
|
|
399
399
|
|
|
400
400
|
// src/debug.ts
|
|
401
401
|
var debugEnabled = false;
|
|
@@ -1723,7 +1723,7 @@ async function updateReviewDiffs(reviewId, newDiffs, headCommit) {
|
|
|
1723
1723
|
// src/server.ts
|
|
1724
1724
|
import { serve } from "@hono/node-server";
|
|
1725
1725
|
import { exec } from "child_process";
|
|
1726
|
-
import { existsSync as existsSync6, readFileSync as
|
|
1726
|
+
import { existsSync as existsSync6, readFileSync as readFileSync9 } from "fs";
|
|
1727
1727
|
import { Hono as Hono4 } from "hono";
|
|
1728
1728
|
import { dirname, join as join7 } from "path";
|
|
1729
1729
|
import { fileURLToPath } from "url";
|
|
@@ -2445,8 +2445,8 @@ function isRetriable(err) {
|
|
|
2445
2445
|
return msg.includes("429") || msg.includes("500") || msg.includes("502") || msg.includes("503") || msg.includes("504") || msg.includes("rate_limit");
|
|
2446
2446
|
}
|
|
2447
2447
|
function sleep(ms) {
|
|
2448
|
-
return new Promise((
|
|
2449
|
-
setTimeout(
|
|
2448
|
+
return new Promise((resolve6) => {
|
|
2449
|
+
setTimeout(resolve6, ms);
|
|
2450
2450
|
});
|
|
2451
2451
|
}
|
|
2452
2452
|
|
|
@@ -2490,8 +2490,8 @@ function randomLines(count) {
|
|
|
2490
2490
|
return lines.sort((a, b) => a.line - b.line);
|
|
2491
2491
|
}
|
|
2492
2492
|
function sleep2(ms) {
|
|
2493
|
-
return new Promise((
|
|
2494
|
-
setTimeout(
|
|
2493
|
+
return new Promise((resolve6) => {
|
|
2494
|
+
setTimeout(resolve6, ms);
|
|
2495
2495
|
});
|
|
2496
2496
|
}
|
|
2497
2497
|
async function mockRiskAnalysisBatch(files) {
|
|
@@ -4059,6 +4059,71 @@ apiRoutes.get("/outline/:fileId", async (c) => {
|
|
|
4059
4059
|
const symbols = parseOutline(content, file.file_path);
|
|
4060
4060
|
return c.json({ symbols });
|
|
4061
4061
|
});
|
|
4062
|
+
apiRoutes.get("/symbol-definition", async (c) => {
|
|
4063
|
+
const name = c.req.query("name");
|
|
4064
|
+
const currentFileId = c.req.query("currentFileId");
|
|
4065
|
+
if (!name) return c.json({ definitions: [] });
|
|
4066
|
+
const reviewId = resolveReviewId(c);
|
|
4067
|
+
const repoRoot = c.get("repoRoot");
|
|
4068
|
+
const definitions = [];
|
|
4069
|
+
const searchedPaths = /* @__PURE__ */ new Set();
|
|
4070
|
+
const reviewFiles = await getReviewFiles(reviewId);
|
|
4071
|
+
for (const file of reviewFiles) {
|
|
4072
|
+
searchedPaths.add(file.file_path);
|
|
4073
|
+
const diff = JSON.parse(file.diff_data ?? "{}");
|
|
4074
|
+
const isDeleted = diff.status === "deleted";
|
|
4075
|
+
let content = "";
|
|
4076
|
+
try {
|
|
4077
|
+
content = isDeleted ? getFileContent(file.file_path, "HEAD", repoRoot) : getFileContent(file.file_path, "working", repoRoot);
|
|
4078
|
+
} catch {
|
|
4079
|
+
continue;
|
|
4080
|
+
}
|
|
4081
|
+
if (!content) continue;
|
|
4082
|
+
const symbols = parseOutline(content, file.file_path);
|
|
4083
|
+
collectDefinitions(symbols, name, file.id, file.file_path, definitions);
|
|
4084
|
+
}
|
|
4085
|
+
if (definitions.length === 0) {
|
|
4086
|
+
try {
|
|
4087
|
+
const allFiles = execSync5("git ls-files", { cwd: repoRoot, encoding: "utf-8" }).trim().split("\n").filter(Boolean);
|
|
4088
|
+
for (const filePath of allFiles) {
|
|
4089
|
+
if (searchedPaths.has(filePath)) continue;
|
|
4090
|
+
const ext = filePath.slice(filePath.lastIndexOf("."));
|
|
4091
|
+
if (!/\.(js|mjs|cjs|jsx|ts|tsx|mts|cts|java|go|rs|c|h|cpp|cc|cxx|hpp|cs|swift|php|kt|kts|scala|dart|groovy|py|rb)$/i.test(ext)) continue;
|
|
4092
|
+
let content = "";
|
|
4093
|
+
try {
|
|
4094
|
+
content = readFileSync7(resolve3(repoRoot, filePath), "utf-8");
|
|
4095
|
+
} catch {
|
|
4096
|
+
continue;
|
|
4097
|
+
}
|
|
4098
|
+
if (!content) continue;
|
|
4099
|
+
const symbols = parseOutline(content, filePath);
|
|
4100
|
+
collectDefinitions(symbols, name, null, filePath, definitions);
|
|
4101
|
+
if (definitions.length > 0) break;
|
|
4102
|
+
}
|
|
4103
|
+
} catch {
|
|
4104
|
+
}
|
|
4105
|
+
}
|
|
4106
|
+
definitions.sort((a, b) => {
|
|
4107
|
+
if (a.fileId === currentFileId && b.fileId !== currentFileId) return -1;
|
|
4108
|
+
if (b.fileId === currentFileId && a.fileId !== currentFileId) return 1;
|
|
4109
|
+
if (a.fileId !== null && b.fileId === null) return -1;
|
|
4110
|
+
if (b.fileId !== null && a.fileId === null) return 1;
|
|
4111
|
+
if (a.kind === "class" && b.kind !== "class") return -1;
|
|
4112
|
+
if (b.kind === "class" && a.kind !== "class") return 1;
|
|
4113
|
+
return 0;
|
|
4114
|
+
});
|
|
4115
|
+
return c.json({ definitions });
|
|
4116
|
+
});
|
|
4117
|
+
function collectDefinitions(symbols, targetName, fileId, filePath, out) {
|
|
4118
|
+
for (const sym of symbols) {
|
|
4119
|
+
if (sym.name === targetName) {
|
|
4120
|
+
out.push({ fileId, filePath, name: sym.name, kind: sym.kind, line: sym.line });
|
|
4121
|
+
}
|
|
4122
|
+
if (sym.children?.length > 0) {
|
|
4123
|
+
collectDefinitions(sym.children, targetName, fileId, filePath, out);
|
|
4124
|
+
}
|
|
4125
|
+
}
|
|
4126
|
+
}
|
|
4062
4127
|
apiRoutes.get("/context/:fileId", async (c) => {
|
|
4063
4128
|
const repoRoot = c.get("repoRoot");
|
|
4064
4129
|
const file = await getReviewFile(c.req.param("fileId"));
|
|
@@ -4155,7 +4220,9 @@ apiRoutes.get("/image/:fileId/:side", async (c) => {
|
|
|
4155
4220
|
});
|
|
4156
4221
|
|
|
4157
4222
|
// src/routes/pages.tsx
|
|
4223
|
+
import { readFileSync as readFileSync8 } from "fs";
|
|
4158
4224
|
import { Hono as Hono3 } from "hono";
|
|
4225
|
+
import { resolve as resolve4 } from "path";
|
|
4159
4226
|
|
|
4160
4227
|
// src/utils/escapeHtml.ts
|
|
4161
4228
|
function escapeHtml(str) {
|
|
@@ -5059,6 +5126,11 @@ pageRoutes.get("/", async (c) => {
|
|
|
5059
5126
|
] }),
|
|
5060
5127
|
/* @__PURE__ */ jsx("p", { className: "progress-summary", id: "progress-summary" })
|
|
5061
5128
|
] }),
|
|
5129
|
+
/* @__PURE__ */ jsx("div", { className: "diff-nav-bar", id: "diff-nav-bar", style: "display:none", children: [
|
|
5130
|
+
/* @__PURE__ */ jsx("button", { className: "nav-btn disabled", id: "nav-back-btn", disabled: true, title: "Back", children: /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "m15 18-6-6 6-6" }) }) }),
|
|
5131
|
+
/* @__PURE__ */ jsx("button", { className: "nav-btn disabled", id: "nav-forward-btn", disabled: true, title: "Forward", children: /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "m9 18 6-6-6-6" }) }) }),
|
|
5132
|
+
/* @__PURE__ */ jsx("span", { className: "nav-file-path", id: "nav-file-path" })
|
|
5133
|
+
] }),
|
|
5062
5134
|
/* @__PURE__ */ jsx("div", { className: "diff-container", id: "diff-container", style: "display:none" }),
|
|
5063
5135
|
/* @__PURE__ */ jsx("div", { className: "diff-toolbar", id: "diff-toolbar", style: "display:none", children: [
|
|
5064
5136
|
/* @__PURE__ */ jsx("div", { className: "diff-toolbar-svg-toggle", style: "display:none", children: /* @__PURE__ */ jsx("div", { className: "segmented-control", children: [
|
|
@@ -5161,6 +5233,39 @@ pageRoutes.get("/file/:fileId", async (c) => {
|
|
|
5161
5233
|
const html = /* @__PURE__ */ jsx(DiffView, { file, diff: finalDiff, annotations, mode });
|
|
5162
5234
|
return c.html(html.toString());
|
|
5163
5235
|
});
|
|
5236
|
+
pageRoutes.get("/file-raw", (c) => {
|
|
5237
|
+
const filePath = c.req.query("path");
|
|
5238
|
+
if (!filePath) return c.text("Missing path", 400);
|
|
5239
|
+
const repoRoot = c.get("repoRoot");
|
|
5240
|
+
let content;
|
|
5241
|
+
try {
|
|
5242
|
+
content = readFileSync8(resolve4(repoRoot, filePath), "utf-8");
|
|
5243
|
+
} catch {
|
|
5244
|
+
return c.text("File not found", 404);
|
|
5245
|
+
}
|
|
5246
|
+
const lines = content.split("\n");
|
|
5247
|
+
const diff = {
|
|
5248
|
+
filePath,
|
|
5249
|
+
oldPath: null,
|
|
5250
|
+
status: "added",
|
|
5251
|
+
isBinary: false,
|
|
5252
|
+
hunks: [{
|
|
5253
|
+
oldStart: 0,
|
|
5254
|
+
oldCount: 0,
|
|
5255
|
+
newStart: 1,
|
|
5256
|
+
newCount: lines.length,
|
|
5257
|
+
lines: lines.map((line, i) => ({
|
|
5258
|
+
type: "context",
|
|
5259
|
+
oldNum: i + 1,
|
|
5260
|
+
newNum: i + 1,
|
|
5261
|
+
content: line
|
|
5262
|
+
}))
|
|
5263
|
+
}]
|
|
5264
|
+
};
|
|
5265
|
+
const fakeFile = { id: "", review_id: "", file_path: filePath, status: "reviewed", diff_data: null };
|
|
5266
|
+
const html = /* @__PURE__ */ jsx(DiffView, { file: fakeFile, diff, annotations: [], mode: "unified" });
|
|
5267
|
+
return c.html(html.toString());
|
|
5268
|
+
});
|
|
5164
5269
|
pageRoutes.get("/review/:reviewId", async (c) => {
|
|
5165
5270
|
const reviewId = c.req.param("reviewId");
|
|
5166
5271
|
const currentReviewId = c.get("reviewId");
|
|
@@ -5210,6 +5315,11 @@ pageRoutes.get("/review/:reviewId", async (c) => {
|
|
|
5210
5315
|
] }),
|
|
5211
5316
|
/* @__PURE__ */ jsx("p", { className: "progress-summary", id: "progress-summary" })
|
|
5212
5317
|
] }),
|
|
5318
|
+
/* @__PURE__ */ jsx("div", { className: "diff-nav-bar", id: "diff-nav-bar", style: "display:none", children: [
|
|
5319
|
+
/* @__PURE__ */ jsx("button", { className: "nav-btn disabled", id: "nav-back-btn", disabled: true, title: "Back", children: /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "m15 18-6-6 6-6" }) }) }),
|
|
5320
|
+
/* @__PURE__ */ jsx("button", { className: "nav-btn disabled", id: "nav-forward-btn", disabled: true, title: "Forward", children: /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "m9 18 6-6-6-6" }) }) }),
|
|
5321
|
+
/* @__PURE__ */ jsx("span", { className: "nav-file-path", id: "nav-file-path" })
|
|
5322
|
+
] }),
|
|
5213
5323
|
/* @__PURE__ */ jsx("div", { className: "diff-container", id: "diff-container", style: "display:none" }),
|
|
5214
5324
|
/* @__PURE__ */ jsx("div", { className: "diff-toolbar", id: "diff-toolbar", style: "display:none", children: [
|
|
5215
5325
|
/* @__PURE__ */ jsx("div", { className: "diff-toolbar-svg-toggle", style: "display:none", children: /* @__PURE__ */ jsx("div", { className: "segmented-control", children: [
|
|
@@ -5257,10 +5367,10 @@ pageRoutes.get("/history", async (c) => {
|
|
|
5257
5367
|
|
|
5258
5368
|
// src/server.ts
|
|
5259
5369
|
function tryServe(fetch2, port) {
|
|
5260
|
-
return new Promise((
|
|
5370
|
+
return new Promise((resolve6, reject) => {
|
|
5261
5371
|
const server = serve({ fetch: fetch2, port });
|
|
5262
5372
|
server.on("listening", () => {
|
|
5263
|
-
|
|
5373
|
+
resolve6(port);
|
|
5264
5374
|
});
|
|
5265
5375
|
server.on("error", (err) => {
|
|
5266
5376
|
if (err.code === "EADDRINUSE") {
|
|
@@ -5282,15 +5392,15 @@ async function startServer(port, reviewId, repoRoot, options) {
|
|
|
5282
5392
|
const selfDir = dirname(fileURLToPath(import.meta.url));
|
|
5283
5393
|
const distDir = existsSync6(join7(selfDir, "client", "styles.css")) ? join7(selfDir, "client") : join7(selfDir, "..", "dist", "client");
|
|
5284
5394
|
app.get("/static/styles.css", (c) => {
|
|
5285
|
-
const css =
|
|
5395
|
+
const css = readFileSync9(join7(distDir, "styles.css"), "utf-8");
|
|
5286
5396
|
return c.text(css, 200, { "Content-Type": "text/css", "Cache-Control": "no-cache" });
|
|
5287
5397
|
});
|
|
5288
5398
|
app.get("/static/app.js", (c) => {
|
|
5289
|
-
const js =
|
|
5399
|
+
const js = readFileSync9(join7(distDir, "app.global.js"), "utf-8");
|
|
5290
5400
|
return c.text(js, 200, { "Content-Type": "application/javascript", "Cache-Control": "no-cache" });
|
|
5291
5401
|
});
|
|
5292
5402
|
app.get("/static/history.js", (c) => {
|
|
5293
|
-
const js =
|
|
5403
|
+
const js = readFileSync9(join7(distDir, "history.global.js"), "utf-8");
|
|
5294
5404
|
return c.text(js, 200, { "Content-Type": "application/javascript", "Cache-Control": "no-cache" });
|
|
5295
5405
|
});
|
|
5296
5406
|
app.route("/api", apiRoutes);
|
|
@@ -5326,7 +5436,7 @@ async function startServer(port, reviewId, repoRoot, options) {
|
|
|
5326
5436
|
}
|
|
5327
5437
|
|
|
5328
5438
|
// src/skills.ts
|
|
5329
|
-
import { existsSync as existsSync7, mkdirSync as mkdirSync5, readFileSync as
|
|
5439
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync5, readFileSync as readFileSync10, writeFileSync as writeFileSync5 } from "fs";
|
|
5330
5440
|
import { join as join8 } from "path";
|
|
5331
5441
|
var SKILL_VERSION = 1;
|
|
5332
5442
|
function versionHeader() {
|
|
@@ -5339,7 +5449,7 @@ function parseVersionHeader(content) {
|
|
|
5339
5449
|
}
|
|
5340
5450
|
function updateFile(path, content) {
|
|
5341
5451
|
if (existsSync7(path)) {
|
|
5342
|
-
const existing =
|
|
5452
|
+
const existing = readFileSync10(path, "utf-8");
|
|
5343
5453
|
const version = parseVersionHeader(existing);
|
|
5344
5454
|
if (version !== null && version >= SKILL_VERSION) {
|
|
5345
5455
|
return false;
|
|
@@ -5443,7 +5553,7 @@ function ensureSkills() {
|
|
|
5443
5553
|
}
|
|
5444
5554
|
|
|
5445
5555
|
// src/update-check.ts
|
|
5446
|
-
import { existsSync as existsSync8, mkdirSync as mkdirSync6, readFileSync as
|
|
5556
|
+
import { existsSync as existsSync8, mkdirSync as mkdirSync6, readFileSync as readFileSync11, writeFileSync as writeFileSync6 } from "fs";
|
|
5447
5557
|
import { get } from "https";
|
|
5448
5558
|
import { homedir as homedir3 } from "os";
|
|
5449
5559
|
import { dirname as dirname2, join as join9 } from "path";
|
|
@@ -5454,7 +5564,7 @@ var PACKAGE_NAME = "glassbox";
|
|
|
5454
5564
|
function getCurrentVersion() {
|
|
5455
5565
|
try {
|
|
5456
5566
|
const dir = dirname2(fileURLToPath2(import.meta.url));
|
|
5457
|
-
const pkg = JSON.parse(
|
|
5567
|
+
const pkg = JSON.parse(readFileSync11(join9(dir, "..", "package.json"), "utf-8"));
|
|
5458
5568
|
return pkg.version;
|
|
5459
5569
|
} catch {
|
|
5460
5570
|
return "0.0.0";
|
|
@@ -5463,7 +5573,7 @@ function getCurrentVersion() {
|
|
|
5463
5573
|
function getLastCheckDate() {
|
|
5464
5574
|
try {
|
|
5465
5575
|
if (existsSync8(CHECK_FILE)) {
|
|
5466
|
-
return
|
|
5576
|
+
return readFileSync11(CHECK_FILE, "utf-8").trim();
|
|
5467
5577
|
}
|
|
5468
5578
|
} catch {
|
|
5469
5579
|
}
|
|
@@ -5480,10 +5590,10 @@ function isFirstUseToday() {
|
|
|
5480
5590
|
return last !== today;
|
|
5481
5591
|
}
|
|
5482
5592
|
function fetchLatestVersion() {
|
|
5483
|
-
return new Promise((
|
|
5593
|
+
return new Promise((resolve6) => {
|
|
5484
5594
|
const req = get(`https://registry.npmjs.org/${PACKAGE_NAME}/latest`, { timeout: 5e3 }, (res) => {
|
|
5485
5595
|
if (res.statusCode !== 200) {
|
|
5486
|
-
|
|
5596
|
+
resolve6(null);
|
|
5487
5597
|
return;
|
|
5488
5598
|
}
|
|
5489
5599
|
let data = "";
|
|
@@ -5492,18 +5602,18 @@ function fetchLatestVersion() {
|
|
|
5492
5602
|
});
|
|
5493
5603
|
res.on("end", () => {
|
|
5494
5604
|
try {
|
|
5495
|
-
|
|
5605
|
+
resolve6(JSON.parse(data).version);
|
|
5496
5606
|
} catch {
|
|
5497
|
-
|
|
5607
|
+
resolve6(null);
|
|
5498
5608
|
}
|
|
5499
5609
|
});
|
|
5500
5610
|
});
|
|
5501
5611
|
req.on("error", () => {
|
|
5502
|
-
|
|
5612
|
+
resolve6(null);
|
|
5503
5613
|
});
|
|
5504
5614
|
req.on("timeout", () => {
|
|
5505
5615
|
req.destroy();
|
|
5506
|
-
|
|
5616
|
+
resolve6(null);
|
|
5507
5617
|
});
|
|
5508
5618
|
});
|
|
5509
5619
|
}
|
|
@@ -5641,7 +5751,7 @@ function parseArgs(argv) {
|
|
|
5641
5751
|
port = parseInt(args[++i], 10);
|
|
5642
5752
|
break;
|
|
5643
5753
|
case "--data-dir":
|
|
5644
|
-
dataDir =
|
|
5754
|
+
dataDir = resolve5(args[++i]);
|
|
5645
5755
|
break;
|
|
5646
5756
|
case "--resume":
|
|
5647
5757
|
resume = true;
|
|
@@ -5697,7 +5807,7 @@ async function main() {
|
|
|
5697
5807
|
console.log("AI service test mode enabled \u2014 using mock AI responses");
|
|
5698
5808
|
}
|
|
5699
5809
|
if (debug) {
|
|
5700
|
-
console.log(`[debug] Build timestamp: ${"2026-03-
|
|
5810
|
+
console.log(`[debug] Build timestamp: ${"2026-03-23T04:00:15.529Z"}`);
|
|
5701
5811
|
}
|
|
5702
5812
|
if (projectDir) {
|
|
5703
5813
|
process.chdir(projectDir);
|