@ycniuqton/devlens 0.1.3 → 0.1.5

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/init.js CHANGED
@@ -156,21 +156,43 @@ function initDevlens(projectDir, port) {
156
156
  }
157
157
  const skillContent = `---
158
158
  name: devlens
159
- description: Show the Devlens dashboard URL and status
159
+ description: Show the Devlens dashboard URL and status for the current project
160
160
  ---
161
161
 
162
- Show the Devlens dashboard status by reading the runtime file:
162
+ Show the Devlens dashboard URLs for the current project by inspecting running processes (no AI reasoning needed — just print whatever the script returns):
163
163
 
164
164
  \`\`\`!
165
- cat "$CLAUDE_PROJECT_DIR/.devlens/runtime.json" 2>/dev/null || echo "NOT_RUNNING"
166
- \`\`\`
165
+ DIR="\${CLAUDE_PROJECT_DIR:-$PWD}"
166
+ # Match any node process running devlens (binary, dist/index.js, or symlink) for this dir
167
+ PROC=$(ps -eo pid,args 2>/dev/null | grep -E "node.*(devlens|dist/index\\.js).*start.*--dir[= ]?\${DIR}([ /]|$)" | grep -v grep | head -1)
168
+
169
+ if [ -z "$PROC" ]; then
170
+ echo "DEVLENS_NOT_RUNNING for \${DIR}"
171
+ exit 0
172
+ fi
173
+
174
+ PID=$(echo "$PROC" | awk '{print $1}')
175
+ PORT=$(echo "$PROC" | grep -oE -- "--port[= ]?[0-9]+" | grep -oE "[0-9]+" | head -1)
176
+ [ -z "$PORT" ] && PORT=$(grep -oE '"port"[[:space:]]*:[[:space:]]*[0-9]+' "\${DIR}/.devlens/runtime.json" 2>/dev/null | grep -oE "[0-9]+" | head -1)
177
+
178
+ if [ -z "$PORT" ]; then
179
+ echo "DEVLENS_RUNNING but could not determine port (PID $PID)"
180
+ exit 0
181
+ fi
167
182
 
168
- If the output is NOT_RUNNING, tell the user Devlens is not running and suggest they restart their Claude Code session.
183
+ echo "DEVLENS_RUNNING"
184
+ echo " PID: $PID"
185
+ echo " Project: \${DIR}"
186
+ echo " Local: http://localhost:\${PORT}"
187
+ for ip in $(hostname -I 2>/dev/null || true); do
188
+ case "$ip" in
189
+ 127.*|::1|fe80*|*:*) continue ;;
190
+ *) echo " Network: http://\${ip}:\${PORT}" ;;
191
+ esac
192
+ done
193
+ \`\`\`
169
194
 
170
- Otherwise, parse the JSON and display a clean summary:
171
- - Local URL: http://localhost:{port}
172
- - Network URLs: http://{each ip}:{port}
173
- - PID and start time
195
+ Just print the script output verbatim. If it starts with \`DEVLENS_NOT_RUNNING\`, tell the user Devlens is not running for this project and suggest restarting the Claude Code session.
174
196
  `;
175
197
  fs_1.default.writeFileSync(path_1.default.join(skillDir, 'SKILL.md'), skillContent);
176
198
  console.log(` Created skill: .claude/skills/devlens (use /devlens in Claude)`);
package/dist/init.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"init.js","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare const browserRouter: import("express-serve-static-core").Router;
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.browserRouter = void 0;
4
+ const express_1 = require("express");
5
+ const files_1 = require("../services/files");
6
+ exports.browserRouter = (0, express_1.Router)();
7
+ // GET /api/browser/branch — current branch name
8
+ exports.browserRouter.get('/branch', async (req, res) => {
9
+ const git = req.app.locals.gitService;
10
+ try {
11
+ const branch = await git.getCurrentBranch();
12
+ res.json({ branch });
13
+ }
14
+ catch (err) {
15
+ res.status(500).json({ error: err.message });
16
+ }
17
+ });
18
+ // GET /api/browser/commits?limit=50 — recent commits in current branch
19
+ exports.browserRouter.get('/commits', async (req, res) => {
20
+ const git = req.app.locals.gitService;
21
+ try {
22
+ const limit = parseInt(req.query.limit) || 50;
23
+ const log = await git.getLog(limit);
24
+ res.json(log);
25
+ }
26
+ catch (err) {
27
+ res.status(500).json({ error: err.message });
28
+ }
29
+ });
30
+ // GET /api/browser/commit/:hash — show commit details (files + diff)
31
+ exports.browserRouter.get('/commit/:hash', async (req, res) => {
32
+ const git = req.app.locals.gitService;
33
+ try {
34
+ const files = await git.getCommitFiles(req.params.hash);
35
+ const diff = await git.getCommitDiff(req.params.hash);
36
+ res.json({ hash: req.params.hash, files, diff });
37
+ }
38
+ catch (err) {
39
+ res.status(500).json({ error: err.message });
40
+ }
41
+ });
42
+ // GET /api/browser/files?path=... — list directory contents
43
+ exports.browserRouter.get('/files', (req, res) => {
44
+ const projectDir = req.app.locals.projectDir;
45
+ const relPath = req.query.path || '';
46
+ const entries = (0, files_1.listDirectory)(projectDir, relPath);
47
+ res.json({ path: relPath, entries });
48
+ });
49
+ // GET /api/browser/file?path=... — read file content
50
+ exports.browserRouter.get('/file', (req, res) => {
51
+ const projectDir = req.app.locals.projectDir;
52
+ const relPath = req.query.path || '';
53
+ if (!relPath)
54
+ return res.status(400).json({ error: 'path required' });
55
+ const result = (0, files_1.readFile)(projectDir, relPath);
56
+ if (!result)
57
+ return res.status(404).json({ error: 'not found' });
58
+ res.json({ path: relPath, ...result });
59
+ });
60
+ //# sourceMappingURL=browser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.js","sourceRoot":"","sources":["../../src/routes/browser.ts"],"names":[],"mappings":"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"}
package/dist/server.js CHANGED
@@ -17,6 +17,7 @@ const diff_1 = require("./routes/diff");
17
17
  const tasks_1 = require("./routes/tasks");
18
18
  const integrations_1 = require("./routes/integrations");
19
19
  const rules_2 = require("./routes/rules");
20
+ const browser_1 = require("./routes/browser");
20
21
  function createServer(options) {
21
22
  const app = (0, express_1.default)();
22
23
  const httpServer = http_1.default.createServer(app);
@@ -46,6 +47,7 @@ function createServer(options) {
46
47
  app.use('/api/tasks', tasks_1.tasksRouter);
47
48
  app.use('/api/integrations', integrations_1.integrationsRouter);
48
49
  app.use('/api/rules', rules_2.rulesRouter);
50
+ app.use('/api/browser', browser_1.browserRouter);
49
51
  // Static files
50
52
  const publicDir = path_1.default.resolve(__dirname, '../public');
51
53
  app.use(express_1.default.static(publicDir));
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":";;;;;AAeA,oCA8GC;AA7HD,sDAA8B;AAC9B,gDAAwB;AACxB,gDAAwB;AACxB,2BAAgD;AAEhD,wDAAgC;AAChC,wCAAkD;AAClD,gDAAmD;AACnD,oDAAuD;AACvD,4CAAsD;AACtD,wCAA2C;AAC3C,0CAAmE;AACnE,wDAA2D;AAC3D,0CAA6C;AAE7C,SAAgB,YAAY,CAAC,OAAsB;IACjD,MAAM,GAAG,GAAG,IAAA,iBAAO,GAAE,CAAC;IACtB,MAAM,UAAU,GAAG,cAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;IAC1C,MAAM,GAAG,GAAG,IAAI,oBAAe,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAErE,aAAa;IACb,GAAG,CAAC,GAAG,CAAC,iBAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IAExB,WAAW;IACX,MAAM,UAAU,GAAG,IAAA,sBAAgB,EAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACxD,MAAM,SAAS,GAAG,IAAA,2BAAe,EAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACtD,MAAM,YAAY,GAAG,IAAA,0BAAkB,EAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAC5D,YAAY,CAAC,aAAa,EAAE,CAAC;IAE7B,wCAAwC;IACxC,GAAG,CAAC,MAAM,CAAC,UAAU,GAAG,UAAU,CAAC;IACnC,GAAG,CAAC,MAAM,CAAC,SAAS,GAAG,SAAS,CAAC;IACjC,GAAG,CAAC,MAAM,CAAC,YAAY,GAAG,YAAY,CAAC;IACvC,GAAG,CAAC,MAAM,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;IAC3C,GAAG,CAAC,MAAM,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAE/B,aAAa;IACb,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE;QACjC,GAAG,CAAC,IAAI,CAAC;YACP,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,WAAW,EAAE,cAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,UAAU,CAAC;YAC9C,IAAI,EAAE,OAAO,CAAC,IAAI;SACnB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IACH,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,iBAAU,CAAC,CAAC;IAC5B,GAAG,CAAC,GAAG,CAAC,YAAY,EAAE,mBAAW,CAAC,CAAC;IACnC,GAAG,CAAC,GAAG,CAAC,mBAAmB,EAAE,iCAAkB,CAAC,CAAC;IACjD,GAAG,CAAC,GAAG,CAAC,YAAY,EAAE,mBAAW,CAAC,CAAC;IAEnC,eAAe;IACf,MAAM,SAAS,GAAG,cAAI,CAAC,OAAO,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;IACvD,GAAG,CAAC,GAAG,CAAC,iBAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;IAEnC,eAAe;IACf,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE;QACzB,GAAG,CAAC,QAAQ,CAAC,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,6BAA6B;IAC7B,SAAS,SAAS,CAAC,OAAkB;QACnC,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QACrC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE;YAC7B,IAAI,MAAM,CAAC,UAAU,KAAK,cAAS,CAAC,IAAI,EAAE,CAAC;gBACzC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACpB,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAED,sCAAsC;IACtC,MAAM,OAAO,GAAG,IAAA,uBAAa,EAAC,OAAO,CAAC,UAAU,EAAE,KAAK,IAAI,EAAE;QAC3D,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,OAAO,EAAE,CAAC;YACxC,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,SAAS,EAAE,CAAC;YAC5C,SAAS,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;YACtD,SAAS,CAAC,EAAE,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC;QAC5D,CAAC;QAAC,MAAM,CAAC;YACP,yCAAyC;QAC3C,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,sCAAsC;IACtC,MAAM,SAAS,GAAG,cAAI,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC;IACxE,MAAM,YAAY,GAAG,kBAAQ,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IACxE,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE;QAC7B,SAAS,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,YAAY,CAAC,QAAQ,EAAE,EAAE,EAAS,CAAC,CAAC;IAC1F,CAAC,CAAC,CAAC;IAEH,8BAA8B;IAC9B,MAAM,UAAU,GAAG,cAAI,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;IAC7D,MAAM,eAAe,GAAG,kBAAQ,CAAC,KAAK,CAAC;QACrC,cAAI,CAAC,IAAI,CAAC,UAAU,EAAE,mBAAmB,CAAC;QAC1C,cAAI,CAAC,IAAI,CAAC,UAAU,EAAE,oBAAoB,CAAC;KAC5C,EAAE,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC,CAAC;IAE7B,SAAS,sBAAsB;QAC7B,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QACzB,MAAM,WAAW,GAAG,cAAI,CAAC,IAAI,CAAC,UAAU,EAAE,mBAAmB,CAAC,CAAC;QAC/D,MAAM,YAAY,GAAG,cAAI,CAAC,IAAI,CAAC,UAAU,EAAE,oBAAoB,CAAC,CAAC;QACjE,IAAI,OAAO,GAAkB,IAAI,CAAC;QAClC,IAAI,QAAQ,GAAG,KAAK,CAAC;QACrB,IAAI,UAAU,GAAkB,IAAI,CAAC;QACrC,IAAI,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC;YAAE,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;QACvF,IAAI,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;YAChC,QAAQ,GAAG,IAAI,CAAC;YAChB,MAAM,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;YAC5E,IAAI,CAAC;gBAAE,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAClC,CAAC;QACD,SAAS,CAAC,EAAE,IAAI,EAAE,wBAAwB,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAS,CAAC,CAAC;IACnG,CAAC;IAED,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,sBAAsB,CAAC,CAAC;IAClD,eAAe,CAAC,EAAE,CAAC,QAAQ,EAAE,sBAAsB,CAAC,CAAC;IACrD,eAAe,CAAC,EAAE,CAAC,QAAQ,EAAE,sBAAsB,CAAC,CAAC;IAErD,0CAA0C;IAC1C,MAAM,gBAAgB,GAAG,WAAW,CAAC,GAAG,EAAE;QACxC,IAAA,4BAAoB,EAAC,SAAS,CAAC,CAAC;IAClC,CAAC,EAAE,KAAK,CAAC,CAAC;IAEV,2CAA2C;IAC3C,GAAG,CAAC,MAAM,CAAC,SAAS,GAAG,SAAS,CAAC;IACjC,GAAG,CAAC,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC;IAC7B,GAAG,CAAC,MAAM,CAAC,gBAAgB,GAAG,gBAAgB,CAAC;IAE/C,OAAO,EAAE,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC;AAClC,CAAC"}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ export interface FileEntry {
2
+ name: string;
3
+ path: string;
4
+ type: 'file' | 'dir';
5
+ size?: number;
6
+ }
7
+ export declare function listDirectory(projectDir: string, relPath: string): FileEntry[];
8
+ export declare function readFile(projectDir: string, relPath: string, maxBytes?: number): {
9
+ content: string;
10
+ truncated: boolean;
11
+ size: number;
12
+ } | null;
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.listDirectory = listDirectory;
7
+ exports.readFile = readFile;
8
+ const fs_1 = __importDefault(require("fs"));
9
+ const path_1 = __importDefault(require("path"));
10
+ const IGNORE = new Set(['.git', 'node_modules', '.devlens', 'dist', '.next', '.nuxt', '.cache']);
11
+ function isSafePath(projectDir, target) {
12
+ const abs = path_1.default.resolve(projectDir, target);
13
+ const root = path_1.default.resolve(projectDir);
14
+ return abs === root || abs.startsWith(root + path_1.default.sep);
15
+ }
16
+ function listDirectory(projectDir, relPath) {
17
+ if (!isSafePath(projectDir, relPath))
18
+ return [];
19
+ const abs = path_1.default.resolve(projectDir, relPath);
20
+ if (!fs_1.default.existsSync(abs) || !fs_1.default.statSync(abs).isDirectory())
21
+ return [];
22
+ const entries = fs_1.default.readdirSync(abs, { withFileTypes: true });
23
+ const result = [];
24
+ for (const entry of entries) {
25
+ if (IGNORE.has(entry.name))
26
+ continue;
27
+ if (entry.name.startsWith('.') && entry.name !== '.gitignore' && entry.name !== '.env.example')
28
+ continue;
29
+ const entryRel = relPath ? path_1.default.posix.join(relPath, entry.name) : entry.name;
30
+ const entryAbs = path_1.default.join(abs, entry.name);
31
+ if (entry.isDirectory()) {
32
+ result.push({ name: entry.name, path: entryRel, type: 'dir' });
33
+ }
34
+ else if (entry.isFile()) {
35
+ let size = 0;
36
+ try {
37
+ size = fs_1.default.statSync(entryAbs).size;
38
+ }
39
+ catch { }
40
+ result.push({ name: entry.name, path: entryRel, type: 'file', size });
41
+ }
42
+ }
43
+ // Folders first, then alphabetical
44
+ result.sort((a, b) => {
45
+ if (a.type !== b.type)
46
+ return a.type === 'dir' ? -1 : 1;
47
+ return a.name.localeCompare(b.name);
48
+ });
49
+ return result;
50
+ }
51
+ function readFile(projectDir, relPath, maxBytes = 200000) {
52
+ if (!isSafePath(projectDir, relPath))
53
+ return null;
54
+ const abs = path_1.default.resolve(projectDir, relPath);
55
+ if (!fs_1.default.existsSync(abs) || !fs_1.default.statSync(abs).isFile())
56
+ return null;
57
+ const stat = fs_1.default.statSync(abs);
58
+ const size = stat.size;
59
+ const truncated = size > maxBytes;
60
+ const buf = fs_1.default.readFileSync(abs);
61
+ const content = truncated ? buf.subarray(0, maxBytes).toString('utf-8') + '\n\n... [truncated]' : buf.toString('utf-8');
62
+ return { content, truncated, size };
63
+ }
64
+ //# sourceMappingURL=files.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"files.js","sourceRoot":"","sources":["../../src/services/files.ts"],"names":[],"mappings":"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"}
@@ -4,5 +4,11 @@ export interface GitService {
4
4
  getStatus(): Promise<FileStatus[]>;
5
5
  getLog(limit?: number): Promise<LogEntry[]>;
6
6
  isRepo(): Promise<boolean>;
7
+ getCurrentBranch(): Promise<string>;
8
+ getCommitDiff(hash: string): Promise<string>;
9
+ getCommitFiles(hash: string): Promise<{
10
+ path: string;
11
+ status: string;
12
+ }[]>;
7
13
  }
8
14
  export declare function createGitService(projectDir: string): GitService;
@@ -85,6 +85,43 @@ function createGitService(projectDir) {
85
85
  async isRepo() {
86
86
  return git.checkIsRepo();
87
87
  },
88
+ async getCurrentBranch() {
89
+ try {
90
+ const status = await git.status();
91
+ return status.current || 'HEAD';
92
+ }
93
+ catch {
94
+ return 'unknown';
95
+ }
96
+ },
97
+ async getCommitDiff(hash) {
98
+ try {
99
+ return await git.show([hash]);
100
+ }
101
+ catch {
102
+ return '';
103
+ }
104
+ },
105
+ async getCommitFiles(hash) {
106
+ try {
107
+ const raw = await git.raw(['show', '--name-status', '--format=', hash]);
108
+ const lines = raw.split('\n').filter(Boolean);
109
+ const result = [];
110
+ for (const line of lines) {
111
+ const parts = line.split('\t');
112
+ if (parts.length < 2)
113
+ continue;
114
+ const code = parts[0].trim();
115
+ const file = parts[parts.length - 1];
116
+ const statusMap = { A: 'added', M: 'modified', D: 'deleted', R: 'renamed' };
117
+ result.push({ path: file, status: statusMap[code[0]] || 'modified' });
118
+ }
119
+ return result;
120
+ }
121
+ catch {
122
+ return [];
123
+ }
124
+ },
88
125
  };
89
126
  }
90
127
  //# sourceMappingURL=git.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/services/git.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/services/git.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ycniuqton/devlens",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -29,7 +29,7 @@
29
29
  },
30
30
  "homepage": "https://github.com/ycniuqton/Devlens#readme",
31
31
  "dependencies": {
32
- "@ycniuqton/devlens": "^0.1.2",
32
+ "@ycniuqton/devlens": "^0.1.3",
33
33
  "better-sqlite3": "^12.8.0",
34
34
  "chokidar": "^3.6.0",
35
35
  "commander": "^12.0.0",
@@ -144,6 +144,7 @@ body {
144
144
  gap: var(--sp-3);
145
145
  padding: var(--sp-2) var(--sp-2);
146
146
  margin-bottom: var(--sp-8);
147
+ min-width: 0;
147
148
  }
148
149
 
149
150
  .brand-icon {
@@ -184,8 +185,9 @@ body {
184
185
  padding: 2px 6px;
185
186
  background: var(--color-primary-subtle);
186
187
  border-radius: var(--radius-sm);
187
- display: inline-block;
188
- align-self: flex-start;
188
+ display: block;
189
+ max-width: 100%;
190
+ min-width: 0;
189
191
  }
190
192
 
191
193
  .sidebar-nav {
@@ -1473,6 +1475,398 @@ body {
1473
1475
  .file-status-untracked .file-name { color: var(--color-text-muted); font-style: italic; }
1474
1476
  .file-status-added .file-name { color: var(--color-success); }
1475
1477
 
1478
+ /* ============================================================
1479
+ Files Tab — VSCode-style Explorer
1480
+ ============================================================ */
1481
+ .file-breadcrumb {
1482
+ font-family: var(--font-mono);
1483
+ font-size: var(--text-xs);
1484
+ color: var(--color-text-secondary);
1485
+ background: var(--color-surface-2);
1486
+ padding: 4px 10px;
1487
+ border-radius: var(--radius-sm);
1488
+ max-width: 480px;
1489
+ overflow: hidden;
1490
+ text-overflow: ellipsis;
1491
+ white-space: nowrap;
1492
+ }
1493
+
1494
+ .explorer-container {
1495
+ display: flex;
1496
+ gap: var(--sp-3);
1497
+ flex: 1;
1498
+ min-height: calc(100vh - 200px);
1499
+ height: calc(100vh - 200px);
1500
+ }
1501
+
1502
+ .explorer-tree-pane {
1503
+ width: 280px;
1504
+ flex-shrink: 0;
1505
+ background: var(--color-surface);
1506
+ border: 1px solid var(--color-border);
1507
+ border-radius: var(--radius-lg);
1508
+ display: flex;
1509
+ flex-direction: column;
1510
+ overflow: hidden;
1511
+ }
1512
+
1513
+ .explorer-pane-header {
1514
+ padding: var(--sp-3) var(--sp-4);
1515
+ border-bottom: 1px solid var(--color-border-subtle);
1516
+ display: flex;
1517
+ align-items: center;
1518
+ justify-content: space-between;
1519
+ }
1520
+
1521
+ .explorer-pane-header h3 {
1522
+ font-size: 10px;
1523
+ font-weight: 700;
1524
+ letter-spacing: 0.1em;
1525
+ color: var(--color-text-muted);
1526
+ }
1527
+
1528
+ .explorer-tree {
1529
+ flex: 1;
1530
+ overflow-y: auto;
1531
+ padding: var(--sp-2) 0;
1532
+ }
1533
+
1534
+ .explorer-row {
1535
+ display: flex;
1536
+ align-items: center;
1537
+ gap: 6px;
1538
+ padding-right: var(--sp-3);
1539
+ cursor: pointer;
1540
+ font-size: var(--text-sm);
1541
+ color: var(--color-text-secondary);
1542
+ height: 24px;
1543
+ transition: background var(--duration-fast) var(--ease);
1544
+ user-select: none;
1545
+ }
1546
+
1547
+ .explorer-row:hover { background: var(--color-surface-hover); }
1548
+
1549
+ .explorer-row.folder-row { color: var(--color-text); font-weight: 500; }
1550
+
1551
+ .explorer-row.file-row.active {
1552
+ background: var(--color-primary-subtle);
1553
+ color: var(--color-primary-hover);
1554
+ }
1555
+
1556
+ .explorer-row .explorer-name {
1557
+ flex: 1;
1558
+ overflow: hidden;
1559
+ text-overflow: ellipsis;
1560
+ white-space: nowrap;
1561
+ }
1562
+
1563
+ .explorer-row svg { flex-shrink: 0; }
1564
+
1565
+ .explorer-chevron {
1566
+ color: var(--color-text-muted);
1567
+ transition: transform var(--duration-fast) var(--ease);
1568
+ }
1569
+
1570
+ .explorer-chevron.expanded { transform: rotate(90deg); }
1571
+
1572
+ .explorer-viewer-pane {
1573
+ flex: 1;
1574
+ background: var(--color-surface);
1575
+ border: 1px solid var(--color-border);
1576
+ border-radius: var(--radius-lg);
1577
+ display: flex;
1578
+ flex-direction: column;
1579
+ overflow: hidden;
1580
+ min-width: 0;
1581
+ }
1582
+
1583
+ .explorer-viewer {
1584
+ flex: 1;
1585
+ overflow: auto;
1586
+ display: flex;
1587
+ flex-direction: column;
1588
+ }
1589
+
1590
+ .code-viewer {
1591
+ display: flex;
1592
+ flex-direction: column;
1593
+ height: 100%;
1594
+ }
1595
+
1596
+ .code-viewer-header {
1597
+ padding: var(--sp-3) var(--sp-4);
1598
+ background: var(--color-surface-2);
1599
+ border-bottom: 1px solid var(--color-border-subtle);
1600
+ display: flex;
1601
+ align-items: center;
1602
+ justify-content: space-between;
1603
+ gap: var(--sp-3);
1604
+ flex-shrink: 0;
1605
+ }
1606
+
1607
+ .code-file-path {
1608
+ font-family: var(--font-mono);
1609
+ font-size: var(--text-xs);
1610
+ color: var(--color-text);
1611
+ overflow: hidden;
1612
+ text-overflow: ellipsis;
1613
+ white-space: nowrap;
1614
+ }
1615
+
1616
+ .code-file-meta {
1617
+ font-size: var(--text-xs);
1618
+ color: var(--color-text-muted);
1619
+ flex-shrink: 0;
1620
+ }
1621
+
1622
+ .code-viewer-body {
1623
+ flex: 1;
1624
+ overflow: auto;
1625
+ font-family: var(--font-mono);
1626
+ font-size: var(--text-sm);
1627
+ line-height: 1.5;
1628
+ background: var(--color-bg);
1629
+ }
1630
+
1631
+ .code-line {
1632
+ display: flex;
1633
+ min-height: 21px;
1634
+ }
1635
+
1636
+ .code-line:hover { background: var(--color-surface-hover); }
1637
+
1638
+ .code-line-num {
1639
+ display: inline-block;
1640
+ min-width: 50px;
1641
+ padding: 0 12px;
1642
+ text-align: right;
1643
+ color: var(--color-text-muted);
1644
+ user-select: none;
1645
+ flex-shrink: 0;
1646
+ border-right: 1px solid var(--color-border-subtle);
1647
+ }
1648
+
1649
+ .code-line-text {
1650
+ padding: 0 12px;
1651
+ color: var(--color-text);
1652
+ white-space: pre;
1653
+ flex: 1;
1654
+ overflow-x: auto;
1655
+ }
1656
+
1657
+ /* ============================================================
1658
+ History Tab — Git Commits
1659
+ ============================================================ */
1660
+ .branch-pill {
1661
+ display: inline-flex;
1662
+ align-items: center;
1663
+ gap: var(--sp-2);
1664
+ padding: 4px 10px;
1665
+ background: var(--color-primary-subtle);
1666
+ color: var(--color-primary-hover);
1667
+ border-radius: var(--radius-full);
1668
+ font-family: var(--font-mono);
1669
+ font-size: var(--text-xs);
1670
+ font-weight: 600;
1671
+ }
1672
+
1673
+ .history-container {
1674
+ display: flex;
1675
+ gap: var(--sp-3);
1676
+ flex: 1;
1677
+ min-height: calc(100vh - 200px);
1678
+ height: calc(100vh - 200px);
1679
+ }
1680
+
1681
+ .history-list-pane {
1682
+ width: 360px;
1683
+ flex-shrink: 0;
1684
+ background: var(--color-surface);
1685
+ border: 1px solid var(--color-border);
1686
+ border-radius: var(--radius-lg);
1687
+ display: flex;
1688
+ flex-direction: column;
1689
+ overflow: hidden;
1690
+ }
1691
+
1692
+ .commit-count {
1693
+ font-size: 10px;
1694
+ font-weight: 600;
1695
+ color: var(--color-text-muted);
1696
+ background: var(--color-surface-3);
1697
+ padding: 2px 8px;
1698
+ border-radius: var(--radius-full);
1699
+ }
1700
+
1701
+ .commits-list {
1702
+ list-style: none;
1703
+ flex: 1;
1704
+ overflow-y: auto;
1705
+ padding: var(--sp-2);
1706
+ }
1707
+
1708
+ .commit-item {
1709
+ display: flex;
1710
+ gap: var(--sp-3);
1711
+ padding: var(--sp-3) var(--sp-3);
1712
+ border-radius: var(--radius-md);
1713
+ cursor: pointer;
1714
+ margin-bottom: 2px;
1715
+ transition: background var(--duration-fast) var(--ease);
1716
+ position: relative;
1717
+ }
1718
+
1719
+ .commit-item:hover { background: var(--color-surface-hover); }
1720
+
1721
+ .commit-item.selected {
1722
+ background: var(--color-primary-subtle);
1723
+ }
1724
+
1725
+ .commit-item.selected .commit-marker { background: var(--color-primary); }
1726
+
1727
+ .commit-marker {
1728
+ width: 8px;
1729
+ height: 8px;
1730
+ border-radius: var(--radius-full);
1731
+ background: var(--color-text-muted);
1732
+ flex-shrink: 0;
1733
+ margin-top: 6px;
1734
+ }
1735
+
1736
+ .commit-content { flex: 1; min-width: 0; }
1737
+
1738
+ .commit-message {
1739
+ font-size: var(--text-sm);
1740
+ color: var(--color-text);
1741
+ font-weight: 500;
1742
+ margin-bottom: 4px;
1743
+ overflow: hidden;
1744
+ text-overflow: ellipsis;
1745
+ white-space: nowrap;
1746
+ }
1747
+
1748
+ .commit-meta {
1749
+ display: flex;
1750
+ gap: var(--sp-2);
1751
+ font-size: var(--text-xs);
1752
+ color: var(--color-text-muted);
1753
+ align-items: center;
1754
+ }
1755
+
1756
+ .commit-hash {
1757
+ font-family: var(--font-mono);
1758
+ background: var(--color-surface-3);
1759
+ padding: 1px 6px;
1760
+ border-radius: var(--radius-sm);
1761
+ }
1762
+
1763
+ .commit-author { font-weight: 500; }
1764
+
1765
+ .history-detail-pane {
1766
+ flex: 1;
1767
+ background: var(--color-surface);
1768
+ border: 1px solid var(--color-border);
1769
+ border-radius: var(--radius-lg);
1770
+ display: flex;
1771
+ flex-direction: column;
1772
+ overflow: hidden;
1773
+ min-width: 0;
1774
+ }
1775
+
1776
+ .commit-detail-header {
1777
+ padding: var(--sp-4) var(--sp-5);
1778
+ background: var(--color-surface-2);
1779
+ border-bottom: 1px solid var(--color-border-subtle);
1780
+ flex-shrink: 0;
1781
+ }
1782
+
1783
+ .commit-header-content {
1784
+ display: flex;
1785
+ align-items: center;
1786
+ gap: var(--sp-3);
1787
+ }
1788
+
1789
+ .commit-header-hash {
1790
+ font-family: var(--font-mono);
1791
+ font-size: var(--text-sm);
1792
+ font-weight: 600;
1793
+ color: var(--color-primary-hover);
1794
+ background: var(--color-primary-subtle);
1795
+ padding: 4px 10px;
1796
+ border-radius: var(--radius-sm);
1797
+ }
1798
+
1799
+ .commit-header-files {
1800
+ font-size: var(--text-xs);
1801
+ color: var(--color-text-muted);
1802
+ }
1803
+
1804
+ .commit-header-actions {
1805
+ margin-left: auto;
1806
+ display: flex;
1807
+ gap: var(--sp-2);
1808
+ }
1809
+
1810
+ .commit-detail-diff {
1811
+ flex: 1;
1812
+ overflow: auto;
1813
+ padding: var(--sp-3);
1814
+ }
1815
+
1816
+ .commit-file-section {
1817
+ border: 1px solid var(--color-border);
1818
+ border-radius: var(--radius-md);
1819
+ margin-bottom: var(--sp-2);
1820
+ overflow: hidden;
1821
+ }
1822
+
1823
+ .commit-file-header {
1824
+ display: flex;
1825
+ align-items: center;
1826
+ gap: var(--sp-3);
1827
+ padding: var(--sp-3) var(--sp-4);
1828
+ background: var(--color-surface-2);
1829
+ cursor: pointer;
1830
+ user-select: none;
1831
+ transition: background var(--duration-fast) var(--ease);
1832
+ min-height: 40px;
1833
+ }
1834
+
1835
+ .commit-file-header:hover { background: var(--color-surface-3); }
1836
+
1837
+ .commit-file-chevron {
1838
+ color: var(--color-text-muted);
1839
+ flex-shrink: 0;
1840
+ transition: transform var(--duration-fast) var(--ease);
1841
+ }
1842
+
1843
+ .commit-file-section.expanded .commit-file-chevron { transform: rotate(90deg); }
1844
+
1845
+ .commit-file-name {
1846
+ font-family: var(--font-mono);
1847
+ font-size: var(--text-sm);
1848
+ color: var(--color-text);
1849
+ overflow: hidden;
1850
+ text-overflow: ellipsis;
1851
+ white-space: nowrap;
1852
+ }
1853
+
1854
+ .commit-file-body {
1855
+ display: none;
1856
+ overflow-x: auto;
1857
+ }
1858
+
1859
+ .commit-file-section.expanded .commit-file-body { display: block; }
1860
+
1861
+ .raw-diff {
1862
+ margin: 0;
1863
+ padding: var(--sp-4);
1864
+ font-family: var(--font-mono);
1865
+ font-size: var(--text-sm);
1866
+ white-space: pre-wrap;
1867
+ color: var(--color-text);
1868
+ }
1869
+
1476
1870
  /* ============================================================
1477
1871
  Rules Tab
1478
1872
  ============================================================ */
package/public/index.html CHANGED
@@ -39,6 +39,18 @@
39
39
  </svg>
40
40
  <span>Tasks</span>
41
41
  </button>
42
+ <button class="nav-item" data-tab="browser" aria-label="File explorer">
43
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
44
+ <path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/>
45
+ </svg>
46
+ <span>Files</span>
47
+ </button>
48
+ <button class="nav-item" data-tab="history" aria-label="Git history">
49
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
50
+ <circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/>
51
+ </svg>
52
+ <span>History</span>
53
+ </button>
42
54
  <button class="nav-item" data-tab="rules" aria-label="View rules">
43
55
  <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
44
56
  <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="9" y1="13" x2="15" y2="13"/><line x1="9" y1="17" x2="15" y2="17"/>
@@ -192,6 +204,81 @@
192
204
 
193
205
  </section>
194
206
 
207
+ <!-- Files View — VSCode-style file explorer -->
208
+ <section id="browser-view" class="tab-content">
209
+ <header class="view-header">
210
+ <h1>Files</h1>
211
+ <div class="header-actions">
212
+ <span class="file-breadcrumb" id="file-breadcrumb">No file selected</span>
213
+ <button class="btn btn-ghost btn-sm" id="browser-refresh-btn" title="Refresh tree">Refresh</button>
214
+ </div>
215
+ </header>
216
+
217
+ <div class="explorer-container">
218
+ <!-- Left: persistent file tree -->
219
+ <aside class="explorer-tree-pane">
220
+ <div class="explorer-pane-header">
221
+ <h3>EXPLORER</h3>
222
+ </div>
223
+ <div id="explorer-tree" class="explorer-tree">
224
+ <div class="empty-state-inline">Loading...</div>
225
+ </div>
226
+ </aside>
227
+
228
+ <!-- Right: file viewer -->
229
+ <main class="explorer-viewer-pane">
230
+ <div id="explorer-viewer" class="explorer-viewer">
231
+ <div class="empty-state">
232
+ <svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" opacity="0.3">
233
+ <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/>
234
+ </svg>
235
+ <p>Select a file to view</p>
236
+ <span>Click any file in the tree on the left</span>
237
+ </div>
238
+ </div>
239
+ </main>
240
+ </div>
241
+ </section>
242
+
243
+ <!-- History View — git commits + diff viewer -->
244
+ <section id="history-view" class="tab-content">
245
+ <header class="view-header">
246
+ <h1>History</h1>
247
+ <div class="header-actions">
248
+ <span class="branch-pill" id="current-branch">
249
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="6" y1="3" x2="6" y2="15"/><circle cx="18" cy="6" r="3"/><circle cx="6" cy="18" r="3"/><path d="M18 9a9 9 0 0 1-9 9"/></svg>
250
+ <span id="current-branch-name">—</span>
251
+ </span>
252
+ <button class="btn btn-ghost btn-sm" id="history-refresh-btn">Refresh</button>
253
+ </div>
254
+ </header>
255
+
256
+ <div class="history-container">
257
+ <aside class="history-list-pane">
258
+ <div class="explorer-pane-header">
259
+ <h3>COMMITS</h3>
260
+ <span class="commit-count" id="commit-count">0</span>
261
+ </div>
262
+ <ul id="commits-list" class="commits-list">
263
+ <li class="empty-state-inline">Loading commits...</li>
264
+ </ul>
265
+ </aside>
266
+
267
+ <main class="history-detail-pane">
268
+ <div id="commit-detail-header" class="commit-detail-header">
269
+ <div class="empty-state">
270
+ <svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" opacity="0.3">
271
+ <circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/>
272
+ </svg>
273
+ <p>Select a commit</p>
274
+ <span>Click any commit on the left to see its diff</span>
275
+ </div>
276
+ </div>
277
+ <div id="commit-detail-diff" class="commit-detail-diff"></div>
278
+ </main>
279
+ </div>
280
+ </section>
281
+
195
282
  <!-- Rules View -->
196
283
  <section id="rules-view" class="tab-content">
197
284
  <header class="view-header">
@@ -393,6 +480,8 @@
393
480
  <script src="/js/diff.js"></script>
394
481
  <script src="/js/tasks.js"></script>
395
482
  <script src="/js/rules.js"></script>
483
+ <script src="/js/browser.js"></script>
484
+ <script src="/js/history.js"></script>
396
485
  <script src="/js/integrations.js"></script>
397
486
  </body>
398
487
  </html>
package/public/js/app.js CHANGED
@@ -40,7 +40,7 @@ window.addEventListener('popstate', () => {
40
40
  // Load initial tab from URL — redirect / to /diff
41
41
  (function() {
42
42
  const path = location.pathname.replace('/', '');
43
- const tab = ['diff', 'tasks', 'rules', 'integrations'].includes(path) ? path : 'diff';
43
+ const tab = ['diff', 'tasks', 'browser', 'history', 'rules', 'integrations'].includes(path) ? path : 'diff';
44
44
  if (!path || path === '') {
45
45
  history.replaceState(null, '', '/diff');
46
46
  }
@@ -0,0 +1,163 @@
1
+ // Files tab — VSCode-style file explorer
2
+
3
+ var explorerExpanded = new Set(JSON.parse(localStorage.getItem('devlens-explorer-expanded') || '[]'));
4
+ var explorerActiveFile = null;
5
+ var explorerCache = {}; // path → entries[]
6
+
7
+ function saveExplorerState() {
8
+ localStorage.setItem('devlens-explorer-expanded', JSON.stringify(Array.from(explorerExpanded)));
9
+ }
10
+
11
+ async function fetchDir(path) {
12
+ if (explorerCache[path]) return explorerCache[path];
13
+ try {
14
+ const res = await fetch(`/api/browser/files?path=${encodeURIComponent(path)}`);
15
+ const data = await res.json();
16
+ explorerCache[path] = data.entries || [];
17
+ return explorerCache[path];
18
+ } catch {
19
+ return [];
20
+ }
21
+ }
22
+
23
+ function fileIconSvg() {
24
+ return '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/></svg>';
25
+ }
26
+
27
+ function chevronSvg(expanded) {
28
+ return `<svg class="explorer-chevron ${expanded ? 'expanded' : ''}" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"/></svg>`;
29
+ }
30
+
31
+ function folderIconSvg() {
32
+ return '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/></svg>';
33
+ }
34
+
35
+ async function renderTree() {
36
+ const tree = document.getElementById('explorer-tree');
37
+ if (!tree) return;
38
+ const html = await renderNode('', 0);
39
+ tree.innerHTML = html || '<div class="empty-state-inline">Empty</div>';
40
+ attachTreeHandlers();
41
+ }
42
+
43
+ async function renderNode(path, depth) {
44
+ const entries = await fetchDir(path);
45
+ if (!entries.length) return '';
46
+
47
+ let html = '';
48
+ for (const entry of entries) {
49
+ const indent = depth * 12;
50
+ if (entry.type === 'dir') {
51
+ const expanded = explorerExpanded.has(entry.path);
52
+ html += `<div class="explorer-row folder-row" data-path="${escapeAttr(entry.path)}" data-type="dir" style="padding-left:${indent + 8}px">
53
+ ${chevronSvg(expanded)}
54
+ ${folderIconSvg()}
55
+ <span class="explorer-name">${escapeHtmlBrowser(entry.name)}</span>
56
+ </div>`;
57
+ if (expanded) {
58
+ html += await renderNode(entry.path, depth + 1);
59
+ }
60
+ } else {
61
+ const isActive = explorerActiveFile === entry.path;
62
+ html += `<div class="explorer-row file-row ${isActive ? 'active' : ''}" data-path="${escapeAttr(entry.path)}" data-type="file" style="padding-left:${indent + 24}px">
63
+ ${fileIconSvg()}
64
+ <span class="explorer-name">${escapeHtmlBrowser(entry.name)}</span>
65
+ </div>`;
66
+ }
67
+ }
68
+ return html;
69
+ }
70
+
71
+ function attachTreeHandlers() {
72
+ const tree = document.getElementById('explorer-tree');
73
+ if (!tree) return;
74
+ tree.querySelectorAll('.explorer-row').forEach(row => {
75
+ row.addEventListener('click', async (e) => {
76
+ e.stopPropagation();
77
+ const path = row.dataset.path;
78
+ const type = row.dataset.type;
79
+ if (type === 'dir') {
80
+ if (explorerExpanded.has(path)) explorerExpanded.delete(path);
81
+ else explorerExpanded.add(path);
82
+ saveExplorerState();
83
+ renderTree();
84
+ } else {
85
+ explorerActiveFile = path;
86
+ loadFileContent(path);
87
+ // Update active highlight without full re-render
88
+ tree.querySelectorAll('.file-row.active').forEach(r => r.classList.remove('active'));
89
+ row.classList.add('active');
90
+ }
91
+ });
92
+ });
93
+ }
94
+
95
+ async function loadFileContent(path) {
96
+ const viewer = document.getElementById('explorer-viewer');
97
+ const breadcrumb = document.getElementById('file-breadcrumb');
98
+ if (!viewer) return;
99
+
100
+ viewer.innerHTML = '<div class="empty-state"><span>Loading...</span></div>';
101
+ breadcrumb.textContent = path;
102
+
103
+ try {
104
+ const res = await fetch(`/api/browser/file?path=${encodeURIComponent(path)}`);
105
+ if (!res.ok) {
106
+ viewer.innerHTML = '<div class="empty-state"><p>Failed to load</p></div>';
107
+ return;
108
+ }
109
+ const data = await res.json();
110
+ const lines = data.content.split('\n');
111
+
112
+ const linesHtml = lines.map((line, i) => `
113
+ <div class="code-line">
114
+ <span class="code-line-num">${i + 1}</span>
115
+ <span class="code-line-text">${escapeHtmlBrowser(line) || ' '}</span>
116
+ </div>
117
+ `).join('');
118
+
119
+ viewer.innerHTML = `
120
+ <div class="code-viewer">
121
+ <div class="code-viewer-header">
122
+ <span class="code-file-path">${escapeHtmlBrowser(path)}</span>
123
+ <span class="code-file-meta">${formatSize(data.size)}${data.truncated ? ' · truncated' : ''}</span>
124
+ </div>
125
+ <div class="code-viewer-body">${linesHtml}</div>
126
+ </div>
127
+ `;
128
+ } catch {
129
+ viewer.innerHTML = '<div class="empty-state"><p>Failed to load file</p></div>';
130
+ }
131
+ }
132
+
133
+ function escapeHtmlBrowser(str) {
134
+ if (str == null) return '';
135
+ const div = document.createElement('div');
136
+ div.textContent = str;
137
+ return div.innerHTML;
138
+ }
139
+
140
+ function escapeAttr(str) {
141
+ return String(str).replace(/"/g, '&quot;');
142
+ }
143
+
144
+ function formatSize(bytes) {
145
+ if (bytes == null) return '';
146
+ if (bytes < 1024) return bytes + ' B';
147
+ if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB';
148
+ return (bytes / (1024 * 1024)).toFixed(1) + ' MB';
149
+ }
150
+
151
+ document.getElementById('browser-refresh-btn')?.addEventListener('click', () => {
152
+ explorerCache = {};
153
+ renderTree();
154
+ });
155
+
156
+ // Lazy load when tab opens
157
+ document.querySelector('[data-tab="browser"]')?.addEventListener('click', () => {
158
+ if (!Object.keys(explorerCache).length) renderTree();
159
+ });
160
+
161
+ if (location.pathname === '/browser') {
162
+ renderTree();
163
+ }
@@ -0,0 +1,219 @@
1
+ // History tab — git commits + diff viewer
2
+
3
+ var historyLoaded = false;
4
+ var historySelectedHash = null;
5
+ var historyViewMode = localStorage.getItem('devlens-history-view') || 'line-by-line';
6
+ var historyCachedData = null; // last loaded commit { hash, files, diff }
7
+
8
+ async function loadBranchInfo() {
9
+ try {
10
+ const res = await fetch('/api/browser/branch');
11
+ const data = await res.json();
12
+ document.getElementById('current-branch-name').textContent = data.branch || '—';
13
+ } catch {}
14
+ }
15
+
16
+ async function loadCommits() {
17
+ const list = document.getElementById('commits-list');
18
+ if (!list) return;
19
+ list.innerHTML = '<li class="empty-state-inline">Loading commits...</li>';
20
+ try {
21
+ const res = await fetch('/api/browser/commits?limit=100');
22
+ const commits = await res.json();
23
+ document.getElementById('commit-count').textContent = commits.length;
24
+
25
+ if (!commits.length) {
26
+ list.innerHTML = '<li class="empty-state-inline">No commits</li>';
27
+ return;
28
+ }
29
+
30
+ list.innerHTML = commits.map(c => `
31
+ <li class="commit-item" data-hash="${c.hash}">
32
+ <div class="commit-marker"></div>
33
+ <div class="commit-content">
34
+ <div class="commit-message">${escapeHtmlHistory(c.message)}</div>
35
+ <div class="commit-meta">
36
+ <span class="commit-hash">${c.hash}</span>
37
+ <span class="commit-author">${escapeHtmlHistory(c.author)}</span>
38
+ <span class="commit-date">${formatRelativeDate(c.date)}</span>
39
+ </div>
40
+ </div>
41
+ </li>
42
+ `).join('');
43
+
44
+ list.querySelectorAll('.commit-item').forEach(item => {
45
+ item.addEventListener('click', () => {
46
+ list.querySelectorAll('.commit-item').forEach(i => i.classList.remove('selected'));
47
+ item.classList.add('selected');
48
+ historySelectedHash = item.dataset.hash;
49
+ loadCommitDetails(item.dataset.hash);
50
+ });
51
+ });
52
+
53
+ historyLoaded = true;
54
+ } catch {
55
+ list.innerHTML = '<li class="empty-state-inline">Failed to load</li>';
56
+ }
57
+ }
58
+
59
+ // Split a unified diff into per-file chunks (reused pattern from diff.js)
60
+ function historySplitDiffByFile(rawDiff) {
61
+ if (!rawDiff || !rawDiff.trim()) return [];
62
+ const files = [];
63
+ const lines = rawDiff.split('\n');
64
+ let current = null;
65
+ for (const line of lines) {
66
+ if (line.startsWith('diff --git')) {
67
+ if (current) files.push(current);
68
+ const match = line.match(/diff --git a\/(.*) b\/(.*)/);
69
+ current = { name: match ? match[2] : 'unknown', lines: [line] };
70
+ } else if (current) {
71
+ current.lines.push(line);
72
+ }
73
+ }
74
+ if (current) files.push(current);
75
+ return files.map(f => ({ name: f.name, diff: f.lines.join('\n') }));
76
+ }
77
+
78
+ async function loadCommitDetails(hash) {
79
+ const headerEl = document.getElementById('commit-detail-header');
80
+ const diffEl = document.getElementById('commit-detail-diff');
81
+ if (!headerEl || !diffEl) return;
82
+
83
+ headerEl.innerHTML = '<div class="empty-state"><span>Loading...</span></div>';
84
+ diffEl.innerHTML = '';
85
+
86
+ try {
87
+ const res = await fetch(`/api/browser/commit/${hash}`);
88
+ const data = await res.json();
89
+ historyCachedData = data;
90
+ renderCommitDetails(hash, data);
91
+ } catch {
92
+ headerEl.innerHTML = '<div class="empty-state"><p>Failed to load commit</p></div>';
93
+ }
94
+ }
95
+
96
+ function renderCommitDetails(hash, data) {
97
+ const headerEl = document.getElementById('commit-detail-header');
98
+ const diffEl = document.getElementById('commit-detail-diff');
99
+ if (!headerEl || !diffEl) return;
100
+
101
+ const isUnified = historyViewMode === 'line-by-line';
102
+
103
+ headerEl.innerHTML = `
104
+ <div class="commit-header-content">
105
+ <div class="commit-header-hash">${hash}</div>
106
+ <div class="commit-header-files">${data.files.length} file(s) changed</div>
107
+ <div class="commit-header-actions">
108
+ <div class="btn-group">
109
+ <button class="btn btn-ghost btn-sm ${!isUnified ? 'active' : ''}" id="history-view-split" title="Side by side">
110
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="8" height="18" rx="1"/><rect x="13" y="3" width="8" height="18" rx="1"/></svg>
111
+ Split
112
+ </button>
113
+ <button class="btn btn-ghost btn-sm ${isUnified ? 'active' : ''}" id="history-view-unified" title="Unified">
114
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="18" height="18" rx="1"/><line x1="3" y1="12" x2="21" y2="12"/></svg>
115
+ Unified
116
+ </button>
117
+ </div>
118
+ <button class="btn btn-ghost btn-sm" id="commit-expand-all" title="Expand all files">
119
+ <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg>
120
+ Expand all
121
+ </button>
122
+ <button class="btn btn-ghost btn-sm" id="commit-collapse-all" title="Collapse all files">
123
+ <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="18 15 12 9 6 15"/></svg>
124
+ Collapse all
125
+ </button>
126
+ </div>
127
+ </div>
128
+ `;
129
+
130
+ if (!data.diff) {
131
+ diffEl.innerHTML = `<pre class="raw-diff">(no diff)</pre>`;
132
+ return;
133
+ }
134
+
135
+ const files = historySplitDiffByFile(data.diff);
136
+ diffEl.innerHTML = files.map((file) => {
137
+ const html = Diff2Html.html(file.diff, {
138
+ drawFileList: false,
139
+ matching: 'lines',
140
+ outputFormat: historyViewMode,
141
+ colorScheme: 'dark',
142
+ });
143
+ return `
144
+ <div class="commit-file-section" data-file="${escapeAttrHistory(file.name)}">
145
+ <div class="commit-file-header">
146
+ <svg class="commit-file-chevron" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"/></svg>
147
+ <span class="commit-file-name">${escapeHtmlHistory(file.name)}</span>
148
+ </div>
149
+ <div class="commit-file-body">${html}</div>
150
+ </div>
151
+ `;
152
+ }).join('');
153
+
154
+ // Wire interactions
155
+ diffEl.querySelectorAll('.commit-file-header').forEach(h => {
156
+ h.addEventListener('click', () => {
157
+ h.closest('.commit-file-section').classList.toggle('expanded');
158
+ });
159
+ });
160
+
161
+ document.getElementById('commit-expand-all')?.addEventListener('click', () => {
162
+ diffEl.querySelectorAll('.commit-file-section').forEach(s => s.classList.add('expanded'));
163
+ });
164
+ document.getElementById('commit-collapse-all')?.addEventListener('click', () => {
165
+ diffEl.querySelectorAll('.commit-file-section').forEach(s => s.classList.remove('expanded'));
166
+ });
167
+ document.getElementById('history-view-split')?.addEventListener('click', () => {
168
+ if (historyViewMode === 'side-by-side') return;
169
+ historyViewMode = 'side-by-side';
170
+ localStorage.setItem('devlens-history-view', historyViewMode);
171
+ if (historyCachedData) renderCommitDetails(hash, historyCachedData);
172
+ });
173
+ document.getElementById('history-view-unified')?.addEventListener('click', () => {
174
+ if (historyViewMode === 'line-by-line') return;
175
+ historyViewMode = 'line-by-line';
176
+ localStorage.setItem('devlens-history-view', historyViewMode);
177
+ if (historyCachedData) renderCommitDetails(hash, historyCachedData);
178
+ });
179
+ }
180
+
181
+ function escapeAttrHistory(str) {
182
+ return String(str).replace(/"/g, '&quot;');
183
+ }
184
+
185
+ function escapeHtmlHistory(str) {
186
+ if (str == null) return '';
187
+ const div = document.createElement('div');
188
+ div.textContent = str;
189
+ return div.innerHTML;
190
+ }
191
+
192
+ function formatRelativeDate(iso) {
193
+ const now = Date.now();
194
+ const then = new Date(iso).getTime();
195
+ const diff = (now - then) / 1000;
196
+ if (diff < 60) return 'just now';
197
+ if (diff < 3600) return `${Math.floor(diff / 60)}m ago`;
198
+ if (diff < 86400) return `${Math.floor(diff / 3600)}h ago`;
199
+ if (diff < 86400 * 7) return `${Math.floor(diff / 86400)}d ago`;
200
+ return new Date(iso).toLocaleDateString();
201
+ }
202
+
203
+ document.getElementById('history-refresh-btn')?.addEventListener('click', () => {
204
+ loadBranchInfo();
205
+ loadCommits();
206
+ });
207
+
208
+ // Lazy load when tab opens
209
+ document.querySelector('[data-tab="history"]')?.addEventListener('click', () => {
210
+ if (!historyLoaded) {
211
+ loadBranchInfo();
212
+ loadCommits();
213
+ }
214
+ });
215
+
216
+ if (location.pathname === '/history') {
217
+ loadBranchInfo();
218
+ loadCommits();
219
+ }