/**
 * Workspace path safety.
 *
 * The pi harness runs untrusted model output. Every file-touching tool must
 * resolve its path through `safeResolve()` so the agent can't read or write
 * outside the workspace via traversal (`../../etc/passwd`) or absolute paths.
 */
import path from 'path';
import fs from 'fs';

export function safeResolve(cwd: string, requested: string): string {
  if (!requested || typeof requested !== 'string') {
    throw new Error('Missing file path');
  }
  // Canonicalize cwd (resolves symlinks) so the traversal check below compares real
  // paths. Falls back to a plain resolve when cwd doesn't exist yet (realpath throws).
  let root: string;
  try {
    root = fs.realpathSync.native(cwd);
  } catch {
    root = path.resolve(cwd);
  }
  const abs = path.isAbsolute(requested)
    ? path.normalize(requested)
    : path.normalize(path.join(root, requested));
  const rel = path.relative(root, abs);
  if (rel.startsWith('..') || path.isAbsolute(rel)) {
    throw new Error(`Path escapes workspace: ${requested}`);
  }
  return abs;
}

export function displayPath(cwd: string, abs: string): string {
  const rel = path.relative(cwd, abs);
  return rel || path.basename(abs);
}
