Files
airship/packages/core/src/index.ts
T
Nayan b60eabfc7c fix(core): give paths and line endings one identity across platforms
Four features key on a path — `--safe` containment, DiffCapture's before/after
map, the history store's per-repo directory, and the editor handler's
containment check — and each canonicalized differently, or not at all. They now
share ./paths.

`realpathSync` was never enough on Windows: it resolves links while preserving
whatever spelling the caller passed, and Windows filesystems are
case-insensitive, so `C:\Proj` and `c:\proj` compared unequal. Drive-letter
case alone triggers it — process.cwd() upper-cases it while `--cwd c:/proj`
does not. `realpathSync.native` canonicalizes case through
GetFinalPathNameByHandle. The failures were all quiet: `--safe` refusing edits
inside the project, DiffCapture attributing the user's own uncommitted work to
the agent and undoing it with the turn.

isPathInside also appended a separator to a root that already ended in one, so
a project at a filesystem root matched nothing at all. repoDir keeps a
read-only fallback to the pre-canonicalization directory, or existing history
would vanish on upgrade for anyone whose project is reached through a symlink.

Line endings get the same treatment in DiffCapture. With core.autocrlf=true the
working tree is CRLF while every agent's edit tool writes LF — and the HEAD
blob the Codex path reads back is LF too — so a one-line edit diffed as a
whole-file rewrite with garbage counts and review comments anchored to the
wrong lines. A leading BOM, which Visual Studio writes and edit tools drop, did
the same to the first line. Both are flattened for comparison and diffing only;
FileDiff.before/after keep the bytes on disk, because restoreFiles writes
`before` back verbatim and undo has to round-trip exactly.

Paths leaving the filesystem are now forward-slashed: a git pathspec (where
backslash is wildmatch's escape character), the JSON an MCP tool returns (where
each backslash arrives doubled), and the overlay's display labels.

The `--safe` command screen was POSIX-shell shaped throughout, so on Windows it
was a no-op while the launch banner still said it was on. Each added pattern
names the flags the real command takes rather than matching the verb loosely —
a bare /\bdel\s+\// fires on `sed -i 's/del /x/'`, and a false deny is not free.
2026-08-11 23:11:29 +05:30

37 lines
1.1 KiB
TypeScript

export type {
AgentAdapter,
AgentKind,
AgentRunContext,
AgentRunOutcome,
} from "./agent";
export { getAdapter } from "./agent";
export { DiffCapture } from "./diff-capture";
/** Path identity, shared so containment, diff keys and history keys agree. */
export {
canonicalPath,
isPathInside,
pathKey,
toPosixPath,
} from "./paths";
export type { EditPromptInput } from "./prompt";
export { buildEditPrompt, PIKA_SYSTEM_PROMPT, systemPrompt } from "./prompt";
export type { CodexConfigValue, CodexSettings } from "./providers/codex";
export type { OpencodeSettings } from "./providers/opencode-server";
/** Stops the shared `opencode serve` child, which otherwise outlives the run. */
export { shutdownServer as shutdownOpencodeServer } from "./providers/opencode-server";
export type {
RunEditEvents,
RunEditInput,
RunEditResult,
} from "./runner";
export { checkAuth, rewindEdit, runEdit } from "./runner";
export type { TimelineSink } from "./timeline";
export { TimelineRecorder } from "./timeline";
export {
describeTool,
shortenPath,
summarizeToolResult,
toolArgs,
toolTitle,
} from "./tool-summary";