|
6 | 6 |
|
7 | 7 | import { FastifyInstance } from 'fastify'; |
8 | 8 | import { join, dirname } from 'node:path'; |
| 9 | +import { homedir } from 'node:os'; |
9 | 10 | import { existsSync, statSync, mkdirSync, writeFileSync } from 'node:fs'; |
10 | 11 | import { execFile } from 'node:child_process'; |
11 | 12 | import fs from 'node:fs/promises'; |
@@ -53,6 +54,9 @@ import { RunSummaryTracker } from '../../run-summary.js'; |
53 | 54 |
|
54 | 55 | import { MAX_INPUT_LENGTH, MAX_SESSION_NAME_LENGTH } from '../../config/terminal-limits.js'; |
55 | 56 |
|
| 57 | +// Path to linked-cases registry (same file used by case-routes resolveCasePath) |
| 58 | +const LINKED_CASES_FILE = join(homedir(), '.codeman', 'linked-cases.json'); |
| 59 | + |
56 | 60 | // Pre-compiled regex for terminal buffer cleaning (avoids per-request compilation) |
57 | 61 | // eslint-disable-next-line no-control-regex |
58 | 62 | const CLAUDE_BANNER_PATTERN = /\x1b\[1mClaud/; |
@@ -919,12 +923,23 @@ export function registerSessionRoutes( |
919 | 923 | } |
920 | 924 | } |
921 | 925 |
|
922 | | - const casePath = validatePathWithinBase(caseName, CASES_DIR); |
| 926 | + // Resolve case path: check linked-cases registry first, then fall back to CASES_DIR. |
| 927 | + // This mirrors the behaviour of resolveCasePath() in case-routes so that linked |
| 928 | + // external project directories are honoured by quick-start just like regular case routes. |
| 929 | + let linkedCases: Record<string, string> = {}; |
| 930 | + try { |
| 931 | + const raw = await fs.readFile(LINKED_CASES_FILE, 'utf-8'); |
| 932 | + linkedCases = JSON.parse(raw); |
| 933 | + } catch { |
| 934 | + // File missing or unparseable — treat as empty registry |
| 935 | + } |
| 936 | + const linkedCasePath = linkedCases[caseName]; |
| 937 | + const casePath = linkedCasePath || validatePathWithinBase(caseName, CASES_DIR); |
923 | 938 | if (!casePath) { |
924 | 939 | return createErrorResponse(ApiErrorCode.INVALID_INPUT, 'Invalid case path'); |
925 | 940 | } |
926 | 941 |
|
927 | | - // Create case folder and CLAUDE.md if it doesn't exist |
| 942 | + // Create case folder and CLAUDE.md if it doesn't exist (only for non-linked cases) |
928 | 943 | if (!existsSync(casePath)) { |
929 | 944 | try { |
930 | 945 | mkdirSync(casePath, { recursive: true }); |
@@ -1098,7 +1113,7 @@ export function registerSessionRoutes( |
1098 | 1113 | text.length < 8 |
1099 | 1114 | ) |
1100 | 1115 | continue; |
1101 | | - return text.length > MAX_PROMPT_LEN ? text.slice(0, MAX_PROMPT_LEN) + '…' : text; |
| 1116 | + return text.length > MAX_PROMPT_LEN ? text.slice(0, MAX_PROMPT_LEN) + '\u2026' : text; |
1102 | 1117 | } catch { |
1103 | 1118 | // Malformed line — skip |
1104 | 1119 | } |
|
0 commit comments