draken 0.1.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.
Files changed (63) hide show
  1. package/README.md +108 -0
  2. package/dist/auth/middleware.d.ts +23 -0
  3. package/dist/auth/middleware.d.ts.map +1 -0
  4. package/dist/auth/middleware.js +117 -0
  5. package/dist/auth/middleware.js.map +1 -0
  6. package/dist/cli.d.ts +3 -0
  7. package/dist/cli.d.ts.map +1 -0
  8. package/dist/cli.js +70 -0
  9. package/dist/cli.js.map +1 -0
  10. package/dist/db/queries.d.ts +16 -0
  11. package/dist/db/queries.d.ts.map +1 -0
  12. package/dist/db/queries.js +91 -0
  13. package/dist/db/queries.js.map +1 -0
  14. package/dist/db/schema.d.ts +4 -0
  15. package/dist/db/schema.d.ts.map +1 -0
  16. package/dist/db/schema.js +71 -0
  17. package/dist/db/schema.js.map +1 -0
  18. package/dist/docker/dockerfile.d.ts +5 -0
  19. package/dist/docker/dockerfile.d.ts.map +1 -0
  20. package/dist/docker/dockerfile.js +32 -0
  21. package/dist/docker/dockerfile.js.map +1 -0
  22. package/dist/docker/manager.d.ts +42 -0
  23. package/dist/docker/manager.d.ts.map +1 -0
  24. package/dist/docker/manager.js +311 -0
  25. package/dist/docker/manager.js.map +1 -0
  26. package/dist/git/status.d.ts +36 -0
  27. package/dist/git/status.d.ts.map +1 -0
  28. package/dist/git/status.js +213 -0
  29. package/dist/git/status.js.map +1 -0
  30. package/dist/routes/auth.d.ts +3 -0
  31. package/dist/routes/auth.d.ts.map +1 -0
  32. package/dist/routes/auth.js +49 -0
  33. package/dist/routes/auth.js.map +1 -0
  34. package/dist/routes/browse.d.ts +3 -0
  35. package/dist/routes/browse.d.ts.map +1 -0
  36. package/dist/routes/browse.js +49 -0
  37. package/dist/routes/browse.js.map +1 -0
  38. package/dist/routes/git.d.ts +3 -0
  39. package/dist/routes/git.d.ts.map +1 -0
  40. package/dist/routes/git.js +135 -0
  41. package/dist/routes/git.js.map +1 -0
  42. package/dist/routes/projects.d.ts +3 -0
  43. package/dist/routes/projects.d.ts.map +1 -0
  44. package/dist/routes/projects.js +149 -0
  45. package/dist/routes/projects.js.map +1 -0
  46. package/dist/routes/tasks.d.ts +3 -0
  47. package/dist/routes/tasks.d.ts.map +1 -0
  48. package/dist/routes/tasks.js +313 -0
  49. package/dist/routes/tasks.js.map +1 -0
  50. package/dist/server.d.ts +2 -0
  51. package/dist/server.d.ts.map +1 -0
  52. package/dist/server.js +60 -0
  53. package/dist/server.js.map +1 -0
  54. package/dist/types.d.ts +32 -0
  55. package/dist/types.d.ts.map +1 -0
  56. package/dist/types.js +3 -0
  57. package/dist/types.js.map +1 -0
  58. package/draken.dockerfile.template +18 -0
  59. package/package.json +59 -0
  60. package/public/assets/index-B_sRrhlE.css +1 -0
  61. package/public/assets/index-DHRickdD.js +235 -0
  62. package/public/draken.svg +13 -0
  63. package/public/index.html +18 -0
@@ -0,0 +1,311 @@
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.getClaudeConfigDir = getClaudeConfigDir;
7
+ exports.hasOAuthCredentials = hasOAuthCredentials;
8
+ exports.getClaudeAuthConfig = getClaudeAuthConfig;
9
+ exports.validateClaudeAuth = validateClaudeAuth;
10
+ exports.buildProjectImage = buildProjectImage;
11
+ exports.runTask = runTask;
12
+ exports.sendInputToTask = sendInputToTask;
13
+ exports.isTaskRunning = isTaskRunning;
14
+ exports.stopContainer = stopContainer;
15
+ exports.getContainerStatus = getContainerStatus;
16
+ exports.imageExists = imageExists;
17
+ const dockerode_1 = __importDefault(require("dockerode"));
18
+ const events_1 = require("events");
19
+ const path_1 = __importDefault(require("path"));
20
+ const fs_1 = __importDefault(require("fs"));
21
+ const os_1 = __importDefault(require("os"));
22
+ const child_process_1 = require("child_process");
23
+ const dockerfile_1 = require("./dockerfile");
24
+ // Detect Docker socket path
25
+ function getDockerSocket() {
26
+ // Check DOCKER_HOST environment variable first
27
+ if (process.env.DOCKER_HOST) {
28
+ return process.env.DOCKER_HOST.replace('unix://', '');
29
+ }
30
+ // Try common socket paths
31
+ const socketPaths = [
32
+ '/var/run/docker.sock',
33
+ `${process.env.HOME}/.docker/desktop/docker.sock`,
34
+ '/run/docker.sock',
35
+ ];
36
+ for (const socketPath of socketPaths) {
37
+ if (fs_1.default.existsSync(socketPath)) {
38
+ return socketPath;
39
+ }
40
+ }
41
+ return undefined;
42
+ }
43
+ const socketPath = getDockerSocket();
44
+ const docker = socketPath ? new dockerode_1.default({ socketPath }) : new dockerode_1.default();
45
+ const IMAGE_PREFIX = 'draken-project-';
46
+ // Store active task processes for interactive input
47
+ const activeProcesses = new Map();
48
+ /**
49
+ * Get the Claude config directory path
50
+ * Uses CLAUDE_CONFIG_DIR if set, otherwise defaults to ~/.claude
51
+ */
52
+ function getClaudeConfigDir() {
53
+ return process.env.CLAUDE_CONFIG_DIR || path_1.default.join(os_1.default.homedir(), '.claude');
54
+ }
55
+ /**
56
+ * Check if OAuth credentials exist in the Claude config directory
57
+ */
58
+ function hasOAuthCredentials() {
59
+ const configDir = getClaudeConfigDir();
60
+ const credentialsPath = path_1.default.join(configDir, '.credentials.json');
61
+ return fs_1.default.existsSync(credentialsPath);
62
+ }
63
+ function getClaudeAuthConfig() {
64
+ // First, check for OAuth credentials (preferred)
65
+ if (hasOAuthCredentials()) {
66
+ return {
67
+ type: 'oauth',
68
+ configDir: getClaudeConfigDir(),
69
+ };
70
+ }
71
+ // Second, check for API key
72
+ const apiKey = process.env.ANTHROPIC_API_KEY;
73
+ if (apiKey) {
74
+ return {
75
+ type: 'api_key',
76
+ apiKey,
77
+ };
78
+ }
79
+ // No authentication available
80
+ return null;
81
+ }
82
+ /**
83
+ * Validate Claude authentication on startup
84
+ * Throws if no auth method is available
85
+ */
86
+ function validateClaudeAuth() {
87
+ const auth = getClaudeAuthConfig();
88
+ if (!auth) {
89
+ const configDir = getClaudeConfigDir();
90
+ throw new Error(`Claude authentication not configured.\n\n` +
91
+ `Option 1 (Recommended): Log in with your Anthropic account\n` +
92
+ ` Run: claude login\n` +
93
+ ` This creates OAuth credentials in ${configDir}\n\n` +
94
+ `Option 2: Use an API key\n` +
95
+ ` Set: ANTHROPIC_API_KEY=your-api-key\n`);
96
+ }
97
+ if (auth.type === 'oauth') {
98
+ console.log(`Claude auth: OAuth credentials found in ${auth.configDir}`);
99
+ }
100
+ else {
101
+ console.log('Claude auth: Using ANTHROPIC_API_KEY');
102
+ }
103
+ }
104
+ async function buildProjectImage(projectPath, projectId) {
105
+ const imageName = `${IMAGE_PREFIX}${projectId}`;
106
+ const dockerfilePath = (0, dockerfile_1.getDockerfilePath)(projectPath);
107
+ const dockerfileName = path_1.default.basename(dockerfilePath);
108
+ // Build the image using Docker CLI to avoid logging driver issues
109
+ try {
110
+ (0, child_process_1.execSync)(`docker build -t ${imageName} -f "${dockerfileName}" .`, {
111
+ cwd: projectPath,
112
+ stdio: 'pipe',
113
+ });
114
+ }
115
+ catch (err) {
116
+ const error = err;
117
+ const stderr = error.stderr?.toString() || 'Unknown build error';
118
+ throw new Error(`Docker build failed: ${stderr}`);
119
+ }
120
+ return imageName;
121
+ }
122
+ async function runTask(projectPath, projectId, prompt, taskId, resumeSessionId // Optional session ID to resume a conversation
123
+ ) {
124
+ const imageName = `${IMAGE_PREFIX}${projectId}`;
125
+ // Check if image exists, build if not (using CLI to avoid logging driver issues)
126
+ try {
127
+ (0, child_process_1.execSync)(`docker image inspect ${imageName}`, { stdio: 'pipe' });
128
+ }
129
+ catch {
130
+ await buildProjectImage(projectPath, projectId);
131
+ }
132
+ const auth = getClaudeAuthConfig();
133
+ if (!auth) {
134
+ throw new Error('Claude authentication not configured. Run "claude login" or set ANTHROPIC_API_KEY.');
135
+ }
136
+ const logEmitter = new events_1.EventEmitter();
137
+ // Create a persistent sessions directory for this project
138
+ const sessionsDir = path_1.default.join(projectPath, '.draken-sessions');
139
+ if (!fs_1.default.existsSync(sessionsDir)) {
140
+ fs_1.default.mkdirSync(sessionsDir, { recursive: true });
141
+ }
142
+ // Build docker run arguments
143
+ const dockerArgs = [
144
+ 'run',
145
+ '--rm',
146
+ '-v', `${projectPath}:/workspace`,
147
+ '--log-driver', 'json-file',
148
+ ];
149
+ // Add authentication based on type
150
+ if (auth.type === 'oauth') {
151
+ // Mount the Claude config directory for OAuth
152
+ // Note: Cannot be read-only - Claude needs to write session data, refresh tokens, etc.
153
+ dockerArgs.push('-v', `${auth.configDir}:/home/claude/.claude-config`);
154
+ dockerArgs.push('-e', 'CLAUDE_CONFIG_DIR=/home/claude/.claude-config');
155
+ // Also mount sessions dir for project-specific session persistence
156
+ dockerArgs.push('-v', `${sessionsDir}:/home/claude/.claude-sessions`);
157
+ }
158
+ else {
159
+ // API key auth
160
+ dockerArgs.push('-e', `ANTHROPIC_API_KEY=${auth.apiKey}`);
161
+ dockerArgs.push('-v', `${sessionsDir}:/home/claude/.claude`);
162
+ }
163
+ // Add the image and Claude CLI arguments
164
+ dockerArgs.push(imageName);
165
+ dockerArgs.push('-p', prompt);
166
+ dockerArgs.push('--dangerously-skip-permissions'); // Skip permission prompts for non-interactive container
167
+ dockerArgs.push('--verbose');
168
+ dockerArgs.push('--output-format', 'stream-json');
169
+ dockerArgs.push('--allowedTools', 'Read,Edit,Write,Bash,Glob,Grep');
170
+ // Add --resume if continuing a conversation
171
+ if (resumeSessionId) {
172
+ dockerArgs.push('--resume', resumeSessionId);
173
+ console.log('[runTask] Resuming session:', resumeSessionId);
174
+ }
175
+ console.log('[runTask] Docker args:', dockerArgs.join(' '));
176
+ const dockerProcess = (0, child_process_1.spawn)('docker', dockerArgs, {
177
+ stdio: ['pipe', 'pipe', 'pipe'],
178
+ });
179
+ console.log('[runTask] Docker process spawned, pid:', dockerProcess.pid);
180
+ // Close stdin immediately for print mode - we don't need input
181
+ // This signals to the container that there's no more input coming
182
+ dockerProcess.stdin.end();
183
+ // Store the process for later input
184
+ activeProcesses.set(taskId, dockerProcess);
185
+ // Generate a pseudo container ID from the process
186
+ const containerId = `pid-${dockerProcess.pid}`;
187
+ // Buffer for incomplete JSON lines
188
+ let buffer = '';
189
+ dockerProcess.stdout.on('data', (chunk) => {
190
+ const chunkStr = chunk.toString('utf-8');
191
+ console.log('[stdout chunk]', chunkStr.substring(0, 200)); // Debug: show first 200 chars
192
+ buffer += chunkStr;
193
+ const lines = buffer.split('\n');
194
+ buffer = lines.pop() || ''; // Keep incomplete line in buffer
195
+ for (const line of lines) {
196
+ if (!line.trim())
197
+ continue;
198
+ try {
199
+ const event = JSON.parse(line);
200
+ // Debug: log all event types to understand the stream format
201
+ console.log('[stream-json event]', event.type, event.session_id ? `session=${event.session_id}` : '');
202
+ // Capture session_id from any event that has it
203
+ if (event.session_id) {
204
+ logEmitter.emit('session', event.session_id);
205
+ }
206
+ // Extract text content from stream-json events
207
+ if (event.type === 'assistant' && event.message?.content) {
208
+ for (const block of event.message.content) {
209
+ if (block.type === 'text') {
210
+ console.log('[emit log] text:', block.text.substring(0, 100));
211
+ logEmitter.emit('log', block.text);
212
+ }
213
+ else if (block.type === 'tool_use') {
214
+ console.log('[emit log] tool_use:', block.name);
215
+ logEmitter.emit('log', `\n[Tool: ${block.name}]\n`);
216
+ }
217
+ }
218
+ }
219
+ else if (event.type === 'result') {
220
+ // Final result
221
+ if (event.result) {
222
+ console.log('[emit log] result:', event.result.substring(0, 100));
223
+ logEmitter.emit('log', `\n${event.result}\n`);
224
+ }
225
+ }
226
+ else if (event.type === 'error') {
227
+ console.log('[emit log] error:', event.error?.message);
228
+ logEmitter.emit('log', `\nError: ${event.error?.message || JSON.stringify(event)}\n`);
229
+ }
230
+ }
231
+ catch {
232
+ // Not JSON, emit as raw text
233
+ logEmitter.emit('log', line + '\n');
234
+ }
235
+ }
236
+ });
237
+ dockerProcess.stdout.on('end', () => {
238
+ console.log('[stdout] stream ended');
239
+ });
240
+ dockerProcess.stderr.on('data', (chunk) => {
241
+ const text = chunk.toString('utf-8');
242
+ console.log('[stderr]', text);
243
+ logEmitter.emit('log', text);
244
+ });
245
+ dockerProcess.on('close', (code) => {
246
+ activeProcesses.delete(taskId);
247
+ logEmitter.emit('end', code ?? 0);
248
+ });
249
+ dockerProcess.on('error', (err) => {
250
+ activeProcesses.delete(taskId);
251
+ logEmitter.emit('error', err);
252
+ });
253
+ return { containerId, logEmitter };
254
+ }
255
+ function sendInputToTask(taskId, input) {
256
+ const proc = activeProcesses.get(taskId);
257
+ if (proc && proc.stdin && !proc.stdin.destroyed) {
258
+ proc.stdin.write(input + '\n');
259
+ return true;
260
+ }
261
+ return false;
262
+ }
263
+ function isTaskRunning(taskId) {
264
+ return activeProcesses.has(taskId);
265
+ }
266
+ async function stopContainer(containerId) {
267
+ try {
268
+ // Handle both process IDs (pid-XXX) and actual container IDs
269
+ if (containerId.startsWith('pid-')) {
270
+ const pid = parseInt(containerId.replace('pid-', ''), 10);
271
+ process.kill(pid, 'SIGTERM');
272
+ }
273
+ else {
274
+ const container = docker.getContainer(containerId);
275
+ await container.stop({ t: 5 });
276
+ }
277
+ }
278
+ catch (err) {
279
+ const error = err;
280
+ // Container/process might already be stopped or removed
281
+ if (error.statusCode !== 404 && error.statusCode !== 304 && error.code !== 'ESRCH') {
282
+ throw err;
283
+ }
284
+ }
285
+ }
286
+ async function getContainerStatus(containerId) {
287
+ try {
288
+ if (containerId.startsWith('pid-')) {
289
+ const pid = parseInt(containerId.replace('pid-', ''), 10);
290
+ // Check if process is still running
291
+ process.kill(pid, 0);
292
+ return 'running';
293
+ }
294
+ const result = (0, child_process_1.execSync)(`docker inspect --format='{{.State.Status}}' ${containerId}`, { stdio: 'pipe' });
295
+ return result.toString().trim();
296
+ }
297
+ catch {
298
+ return 'removed';
299
+ }
300
+ }
301
+ async function imageExists(projectId) {
302
+ const imageName = `${IMAGE_PREFIX}${projectId}`;
303
+ try {
304
+ (0, child_process_1.execSync)(`docker image inspect ${imageName}`, { stdio: 'pipe' });
305
+ return true;
306
+ }
307
+ catch {
308
+ return false;
309
+ }
310
+ }
311
+ //# sourceMappingURL=manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/docker/manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ export interface GitFileChange {
2
+ path: string;
3
+ status: 'modified' | 'added' | 'deleted' | 'renamed' | 'untracked';
4
+ staged: boolean;
5
+ }
6
+ export interface GitStatus {
7
+ isRepo: boolean;
8
+ branch: string | null;
9
+ ahead: number;
10
+ behind: number;
11
+ changes: GitFileChange[];
12
+ hasUncommittedChanges: boolean;
13
+ hasUntrackedFiles: boolean;
14
+ }
15
+ export interface GitDiff {
16
+ staged: string;
17
+ unstaged: string;
18
+ }
19
+ export declare function isGitRepo(projectPath: string): boolean;
20
+ export declare function getGitStatus(projectPath: string): Promise<GitStatus>;
21
+ export declare function getGitDiff(projectPath: string, staged?: boolean): Promise<string>;
22
+ export declare function getGitDiffs(projectPath: string): Promise<GitDiff>;
23
+ export interface FileDiffContent {
24
+ oldContent: string;
25
+ newContent: string;
26
+ oldFileName: string;
27
+ newFileName: string;
28
+ }
29
+ /**
30
+ * Get old and new content for a file to display a diff
31
+ * @param projectPath - Path to the git repository
32
+ * @param filePath - Path to the file relative to repo root
33
+ * @param staged - Whether the file is staged or unstaged
34
+ */
35
+ export declare function getFileDiffContent(projectPath: string, filePath: string, staged: boolean): Promise<FileDiffContent>;
36
+ //# sourceMappingURL=status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/git/status.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,UAAU,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,CAAC;IACnE,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,qBAAqB,EAAE,OAAO,CAAC;IAC/B,iBAAiB,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,WAAW,OAAO;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,SAAS,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAGtD;AAMD,wBAAsB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAuG1E;AAED,wBAAsB,UAAU,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,GAAE,OAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAa9F;AAED,wBAAsB,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAOvE;AAaD,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;GAKG;AACH,wBAAsB,kBAAkB,CACtC,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,OAAO,GACd,OAAO,CAAC,eAAe,CAAC,CA0D1B"}
@@ -0,0 +1,213 @@
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.isGitRepo = isGitRepo;
7
+ exports.getGitStatus = getGitStatus;
8
+ exports.getGitDiff = getGitDiff;
9
+ exports.getGitDiffs = getGitDiffs;
10
+ exports.getFileDiffContent = getFileDiffContent;
11
+ const simple_git_1 = __importDefault(require("simple-git"));
12
+ const path_1 = __importDefault(require("path"));
13
+ const fs_1 = __importDefault(require("fs"));
14
+ function isGitRepo(projectPath) {
15
+ const gitDir = path_1.default.join(projectPath, '.git');
16
+ return fs_1.default.existsSync(gitDir);
17
+ }
18
+ function createGit(projectPath) {
19
+ return (0, simple_git_1.default)(projectPath, { binary: 'git', maxConcurrentProcesses: 6 });
20
+ }
21
+ async function getGitStatus(projectPath) {
22
+ if (!isGitRepo(projectPath)) {
23
+ return {
24
+ isRepo: false,
25
+ branch: null,
26
+ ahead: 0,
27
+ behind: 0,
28
+ changes: [],
29
+ hasUncommittedChanges: false,
30
+ hasUntrackedFiles: false,
31
+ };
32
+ }
33
+ try {
34
+ const git = createGit(projectPath);
35
+ const status = await git.status();
36
+ const changes = [];
37
+ // Staged files
38
+ for (const file of status.staged) {
39
+ changes.push({
40
+ path: file,
41
+ status: 'added',
42
+ staged: true,
43
+ });
44
+ }
45
+ // Modified and staged
46
+ for (const file of status.modified) {
47
+ // Check if it's staged or not by looking at other arrays
48
+ const isStaged = !status.files.some(f => f.path === file && f.working_dir !== ' ');
49
+ if (isStaged) {
50
+ changes.push({
51
+ path: file,
52
+ status: 'modified',
53
+ staged: true,
54
+ });
55
+ }
56
+ }
57
+ // Use the files array for accurate staged/unstaged detection
58
+ for (const file of status.files) {
59
+ // Index status (staged)
60
+ if (file.index && file.index !== ' ' && file.index !== '?') {
61
+ // Check if not already added
62
+ const exists = changes.some(c => c.path === file.path && c.staged);
63
+ if (!exists) {
64
+ changes.push({
65
+ path: file.path,
66
+ status: mapStatusChar(file.index),
67
+ staged: true,
68
+ });
69
+ }
70
+ }
71
+ // Working directory status (unstaged)
72
+ if (file.working_dir && file.working_dir !== ' ') {
73
+ if (file.working_dir === '?') {
74
+ changes.push({
75
+ path: file.path,
76
+ status: 'untracked',
77
+ staged: false,
78
+ });
79
+ }
80
+ else {
81
+ changes.push({
82
+ path: file.path,
83
+ status: mapStatusChar(file.working_dir),
84
+ staged: false,
85
+ });
86
+ }
87
+ }
88
+ }
89
+ // Deduplicate changes (in case of overlap)
90
+ const uniqueChanges = changes.filter((change, index, self) => index === self.findIndex(c => c.path === change.path && c.staged === change.staged));
91
+ const hasUncommittedChanges = uniqueChanges.some(c => c.status !== 'untracked');
92
+ const hasUntrackedFiles = uniqueChanges.some(c => c.status === 'untracked');
93
+ return {
94
+ isRepo: true,
95
+ branch: status.current,
96
+ ahead: status.ahead,
97
+ behind: status.behind,
98
+ changes: uniqueChanges,
99
+ hasUncommittedChanges,
100
+ hasUntrackedFiles,
101
+ };
102
+ }
103
+ catch (err) {
104
+ console.error('Error getting git status:', err);
105
+ return {
106
+ isRepo: false,
107
+ branch: null,
108
+ ahead: 0,
109
+ behind: 0,
110
+ changes: [],
111
+ hasUncommittedChanges: false,
112
+ hasUntrackedFiles: false,
113
+ };
114
+ }
115
+ }
116
+ async function getGitDiff(projectPath, staged = false) {
117
+ if (!isGitRepo(projectPath)) {
118
+ return '';
119
+ }
120
+ try {
121
+ const git = createGit(projectPath);
122
+ const options = staged ? ['--cached'] : [];
123
+ return await git.diff(options);
124
+ }
125
+ catch (err) {
126
+ console.error('Error getting git diff:', err);
127
+ return '';
128
+ }
129
+ }
130
+ async function getGitDiffs(projectPath) {
131
+ const [staged, unstaged] = await Promise.all([
132
+ getGitDiff(projectPath, true),
133
+ getGitDiff(projectPath, false),
134
+ ]);
135
+ return { staged, unstaged };
136
+ }
137
+ function mapStatusChar(char) {
138
+ switch (char) {
139
+ case 'M': return 'modified';
140
+ case 'A': return 'added';
141
+ case 'D': return 'deleted';
142
+ case 'R': return 'renamed';
143
+ case '?': return 'untracked';
144
+ default: return 'modified';
145
+ }
146
+ }
147
+ /**
148
+ * Get old and new content for a file to display a diff
149
+ * @param projectPath - Path to the git repository
150
+ * @param filePath - Path to the file relative to repo root
151
+ * @param staged - Whether the file is staged or unstaged
152
+ */
153
+ async function getFileDiffContent(projectPath, filePath, staged) {
154
+ const git = createGit(projectPath);
155
+ const fullPath = path_1.default.join(projectPath, filePath);
156
+ let oldContent = '';
157
+ let newContent = '';
158
+ try {
159
+ if (staged) {
160
+ // Staged changes: compare HEAD to staged (index)
161
+ // Old = committed version (HEAD)
162
+ // New = staged version (index)
163
+ try {
164
+ oldContent = await git.show([`HEAD:${filePath}`]);
165
+ }
166
+ catch {
167
+ // File might be newly added (no HEAD version)
168
+ oldContent = '';
169
+ }
170
+ try {
171
+ newContent = await git.show([`:${filePath}`]);
172
+ }
173
+ catch {
174
+ // Fallback to reading from disk
175
+ if (fs_1.default.existsSync(fullPath)) {
176
+ newContent = fs_1.default.readFileSync(fullPath, 'utf-8');
177
+ }
178
+ }
179
+ }
180
+ else {
181
+ // Unstaged changes: compare index/HEAD to working directory
182
+ // Old = staged version (index) or committed version (HEAD)
183
+ // New = current file on disk
184
+ try {
185
+ // Try to get from index first (staged version)
186
+ oldContent = await git.show([`:${filePath}`]);
187
+ }
188
+ catch {
189
+ try {
190
+ // Fall back to HEAD
191
+ oldContent = await git.show([`HEAD:${filePath}`]);
192
+ }
193
+ catch {
194
+ oldContent = '';
195
+ }
196
+ }
197
+ // New content is the current file on disk
198
+ if (fs_1.default.existsSync(fullPath)) {
199
+ newContent = fs_1.default.readFileSync(fullPath, 'utf-8');
200
+ }
201
+ }
202
+ }
203
+ catch (err) {
204
+ console.error('Error getting file diff content:', err);
205
+ }
206
+ return {
207
+ oldContent,
208
+ newContent,
209
+ oldFileName: filePath,
210
+ newFileName: filePath,
211
+ };
212
+ }
213
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/git/status.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ declare const router: import("express-serve-static-core").Router;
2
+ export default router;
3
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/routes/auth.ts"],"names":[],"mappings":"AAUA,QAAA,MAAM,MAAM,4CAAW,CAAC;AA2DxB,eAAe,MAAM,CAAC"}
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const express_1 = require("express");
4
+ const middleware_1 = require("../auth/middleware");
5
+ const router = (0, express_1.Router)();
6
+ // Check if auth is enabled
7
+ router.get('/status', (_req, res) => {
8
+ res.json({
9
+ enabled: (0, middleware_1.isAuthEnabled)(),
10
+ });
11
+ });
12
+ // Login endpoint
13
+ router.post('/login', (req, res) => {
14
+ const { username, password } = req.body;
15
+ if (!username || !password) {
16
+ return res.status(400).json({ error: 'Username and password are required' });
17
+ }
18
+ if (!(0, middleware_1.isAuthEnabled)()) {
19
+ return res.status(400).json({ error: 'Authentication is not configured' });
20
+ }
21
+ if (!(0, middleware_1.validateCredentials)(username, password)) {
22
+ return res.status(401).json({ error: 'Invalid credentials' });
23
+ }
24
+ const token = (0, middleware_1.generateToken)(username);
25
+ const config = (0, middleware_1.getAuthConfig)();
26
+ res.json({
27
+ token,
28
+ expiresIn: config?.tokenExpiry || '7d',
29
+ username,
30
+ });
31
+ });
32
+ // Verify token endpoint (check if current token is valid)
33
+ router.get('/verify', middleware_1.authMiddleware, (req, res) => {
34
+ if (!(0, middleware_1.isAuthEnabled)()) {
35
+ return res.json({ valid: true, authEnabled: false });
36
+ }
37
+ res.json({
38
+ valid: true,
39
+ authEnabled: true,
40
+ username: req.user?.username,
41
+ });
42
+ });
43
+ // Logout is handled client-side (just delete the token)
44
+ // But we provide an endpoint for completeness
45
+ router.post('/logout', (_req, res) => {
46
+ res.json({ message: 'Logged out successfully' });
47
+ });
48
+ exports.default = router;
49
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/routes/auth.ts"],"names":[],"mappings":";;AAAA,qCAAoD;AACpD,mDAO4B;AAE5B,MAAM,MAAM,GAAG,IAAA,gBAAM,GAAE,CAAC;AAOxB,2BAA2B;AAC3B,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,IAAa,EAAE,GAAa,EAAE,EAAE;IACrD,GAAG,CAAC,IAAI,CAAC;QACP,OAAO,EAAE,IAAA,0BAAa,GAAE;KACzB,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,iBAAiB;AACjB,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,GAAY,EAAE,GAAa,EAAE,EAAE;IACpD,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,GAAG,CAAC,IAAoB,CAAC;IAExD,IAAI,CAAC,QAAQ,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC3B,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,oCAAoC,EAAE,CAAC,CAAC;IAC/E,CAAC;IAED,IAAI,CAAC,IAAA,0BAAa,GAAE,EAAE,CAAC;QACrB,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,kCAAkC,EAAE,CAAC,CAAC;IAC7E,CAAC;IAED,IAAI,CAAC,IAAA,gCAAmB,EAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE,CAAC;QAC7C,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,qBAAqB,EAAE,CAAC,CAAC;IAChE,CAAC;IAED,MAAM,KAAK,GAAG,IAAA,0BAAa,EAAC,QAAQ,CAAC,CAAC;IACtC,MAAM,MAAM,GAAG,IAAA,0BAAa,GAAE,CAAC;IAE/B,GAAG,CAAC,IAAI,CAAC;QACP,KAAK;QACL,SAAS,EAAE,MAAM,EAAE,WAAW,IAAI,IAAI;QACtC,QAAQ;KACT,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,0DAA0D;AAC1D,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,2BAAc,EAAE,CAAC,GAAyB,EAAE,GAAa,EAAE,EAAE;IACjF,IAAI,CAAC,IAAA,0BAAa,GAAE,EAAE,CAAC;QACrB,OAAO,GAAG,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC,CAAC;IACvD,CAAC;IAED,GAAG,CAAC,IAAI,CAAC;QACP,KAAK,EAAE,IAAI;QACX,WAAW,EAAE,IAAI;QACjB,QAAQ,EAAE,GAAG,CAAC,IAAI,EAAE,QAAQ;KAC7B,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,wDAAwD;AACxD,8CAA8C;AAC9C,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,IAAa,EAAE,GAAa,EAAE,EAAE;IACtD,GAAG,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,yBAAyB,EAAE,CAAC,CAAC;AACnD,CAAC,CAAC,CAAC;AAEH,kBAAe,MAAM,CAAC"}
@@ -0,0 +1,3 @@
1
+ declare const router: import("express-serve-static-core").Router;
2
+ export default router;
3
+ //# sourceMappingURL=browse.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browse.d.ts","sourceRoot":"","sources":["../../src/routes/browse.ts"],"names":[],"mappings":"AAMA,QAAA,MAAM,MAAM,4CAAW,CAAC;AA8CxB,eAAe,MAAM,CAAC"}