45 lines
1.5 KiB
JavaScript
45 lines
1.5 KiB
JavaScript
import fs from "node:fs";
|
|
import os from "node:os";
|
|
import path from "node:path";
|
|
|
|
import { ensureAbsolutePath } from "./fs.mjs";
|
|
|
|
export const TRANSCRIPT_PATH_ENV = "CODEX_COMPANION_TRANSCRIPT_PATH";
|
|
const CLAUDE_PROJECTS_DIR = path.join(os.homedir(), ".claude", "projects");
|
|
|
|
function resolveUserPath(cwd, value) {
|
|
if (value === "~") {
|
|
return os.homedir();
|
|
}
|
|
if (String(value).startsWith("~/")) {
|
|
return path.join(os.homedir(), String(value).slice(2));
|
|
}
|
|
return ensureAbsolutePath(cwd, value);
|
|
}
|
|
|
|
export function resolveClaudeSessionPath(cwd, options = {}) {
|
|
const requestedPath = options.source || process.env[TRANSCRIPT_PATH_ENV];
|
|
if (!requestedPath) {
|
|
throw new Error("Could not identify the current Claude transcript. Retry with --source <path-to-claude-jsonl>.");
|
|
}
|
|
|
|
const sourcePath = resolveUserPath(cwd, requestedPath);
|
|
if (path.extname(sourcePath) !== ".jsonl") {
|
|
throw new Error(`Claude session source must be a JSONL file: ${sourcePath}`);
|
|
}
|
|
|
|
let source;
|
|
let projects;
|
|
try {
|
|
source = fs.realpathSync(sourcePath);
|
|
projects = fs.realpathSync(CLAUDE_PROJECTS_DIR);
|
|
} catch {
|
|
throw new Error(`Claude session file not found: ${sourcePath}`);
|
|
}
|
|
const relative = path.relative(projects, source);
|
|
if (relative === "" || relative === ".." || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative)) {
|
|
throw new Error(`Codex can import Claude sessions only from ${CLAUDE_PROJECTS_DIR}: ${source}`);
|
|
}
|
|
return source;
|
|
}
|