diff --git a/src/web/routes/session-routes.ts b/src/web/routes/session-routes.ts index 7f20c5d4..2a4a85e7 100644 --- a/src/web/routes/session-routes.ts +++ b/src/web/routes/session-routes.ts @@ -6,6 +6,7 @@ import { FastifyInstance } from 'fastify'; import { join, dirname } from 'node:path'; +import { homedir } from 'node:os'; import { existsSync, statSync, mkdirSync, writeFileSync } from 'node:fs'; import { execFile } from 'node:child_process'; import fs from 'node:fs/promises'; @@ -53,6 +54,9 @@ import { RunSummaryTracker } from '../../run-summary.js'; import { MAX_INPUT_LENGTH, MAX_SESSION_NAME_LENGTH } from '../../config/terminal-limits.js'; +// Path to linked-cases registry (same file used by case-routes resolveCasePath) +const LINKED_CASES_FILE = join(homedir(), '.codeman', 'linked-cases.json'); + // Pre-compiled regex for terminal buffer cleaning (avoids per-request compilation) // eslint-disable-next-line no-control-regex const CLAUDE_BANNER_PATTERN = /\x1b\[1mClaud/; @@ -919,12 +923,23 @@ export function registerSessionRoutes( } } - const casePath = validatePathWithinBase(caseName, CASES_DIR); + // Resolve case path: check linked-cases registry first, then fall back to CASES_DIR. + // This mirrors the behaviour of resolveCasePath() in case-routes so that linked + // external project directories are honoured by quick-start just like regular case routes. + let linkedCases: Record = {}; + try { + const raw = await fs.readFile(LINKED_CASES_FILE, 'utf-8'); + linkedCases = JSON.parse(raw); + } catch { + // File missing or unparseable — treat as empty registry + } + const linkedCasePath = linkedCases[caseName]; + const casePath = linkedCasePath || validatePathWithinBase(caseName, CASES_DIR); if (!casePath) { return createErrorResponse(ApiErrorCode.INVALID_INPUT, 'Invalid case path'); } - // Create case folder and CLAUDE.md if it doesn't exist + // Create case folder and CLAUDE.md if it doesn't exist (only for non-linked cases) if (!existsSync(casePath)) { try { mkdirSync(casePath, { recursive: true }); @@ -1098,7 +1113,7 @@ export function registerSessionRoutes( text.length < 8 ) continue; - return text.length > MAX_PROMPT_LEN ? text.slice(0, MAX_PROMPT_LEN) + '…' : text; + return text.length > MAX_PROMPT_LEN ? text.slice(0, MAX_PROMPT_LEN) + '\u2026' : text; } catch { // Malformed line — skip }