glassbox 0.4.4 → 0.5.1

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 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 resolve4 } from "path";
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 readFileSync8 } from "fs";
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((resolve5) => {
2449
- setTimeout(resolve5, ms);
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((resolve5) => {
2494
- setTimeout(resolve5, ms);
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((resolve5, reject) => {
5370
+ return new Promise((resolve6, reject) => {
5261
5371
  const server = serve({ fetch: fetch2, port });
5262
5372
  server.on("listening", () => {
5263
- resolve5(port);
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 = readFileSync8(join7(distDir, "styles.css"), "utf-8");
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 = readFileSync8(join7(distDir, "app.global.js"), "utf-8");
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 = readFileSync8(join7(distDir, "history.global.js"), "utf-8");
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 readFileSync9, writeFileSync as writeFileSync5 } from "fs";
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 = readFileSync9(path, "utf-8");
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 readFileSync10, writeFileSync as writeFileSync6 } from "fs";
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(readFileSync10(join9(dir, "..", "package.json"), "utf-8"));
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 readFileSync10(CHECK_FILE, "utf-8").trim();
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((resolve5) => {
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
- resolve5(null);
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
- resolve5(JSON.parse(data).version);
5605
+ resolve6(JSON.parse(data).version);
5496
5606
  } catch {
5497
- resolve5(null);
5607
+ resolve6(null);
5498
5608
  }
5499
5609
  });
5500
5610
  });
5501
5611
  req.on("error", () => {
5502
- resolve5(null);
5612
+ resolve6(null);
5503
5613
  });
5504
5614
  req.on("timeout", () => {
5505
5615
  req.destroy();
5506
- resolve5(null);
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 = resolve4(args[++i]);
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-21T23:17:12.455Z"}`);
5810
+ console.log(`[debug] Build timestamp: ${"2026-03-26T23:51:09.647Z"}`);
5701
5811
  }
5702
5812
  if (projectDir) {
5703
5813
  process.chdir(projectDir);