diff --git a/apps/x/packages/core/src/filesystem/files.ts b/apps/x/packages/core/src/filesystem/files.ts index facb697b..85c634c9 100644 --- a/apps/x/packages/core/src/filesystem/files.ts +++ b/apps/x/packages/core/src/filesystem/files.ts @@ -73,7 +73,10 @@ function isPathInside(parent: string, child: string): boolean { return relative === '' || (!!relative && !relative.startsWith('..') && !path.isAbsolute(relative)); } -function expandHomePath(inputPath: string): string { +// Exported for tool inputs that take user/model-supplied paths (code cwd, +// bg-task projectDir): the blank guard matters there because callers feed +// the result to path.resolve, and resolve('') silently becomes process.cwd(). +export function expandHomePath(inputPath: string): string { const trimmed = inputPath.trim(); if (!trimmed) { throw new Error('Path is required'); diff --git a/apps/x/packages/core/src/runtime/tools/domains/background-tasks.ts b/apps/x/packages/core/src/runtime/tools/domains/background-tasks.ts index 2fbe53a3..8eb7fa50 100644 --- a/apps/x/packages/core/src/runtime/tools/domains/background-tasks.ts +++ b/apps/x/packages/core/src/runtime/tools/domains/background-tasks.ts @@ -10,7 +10,7 @@ import container from "../../../di/container.js"; import { BackgroundTaskSchema, TriggersSchema } from "@x/shared/dist/background-task.js"; import * as gitService from "../../../code-mode/git/service.js"; import type { ICodeProjectsRepo } from "../../../code-mode/projects/repo.js"; -import { expandHome } from "../paths.js"; +import { expandHomePath } from "../../../filesystem/files.js"; // Inputs for the bg-task builtin tools. Reuse the canonical schema field // descriptions; only `triggers` gets a tighter contextual override (the @@ -45,7 +45,7 @@ export const PatchBackgroundTaskInput = BackgroundTaskSchema.pick({ export async function resolveCodeProject(dirPath: string): Promise< { ok: true; projectId: string; path: string; warning?: string } | { ok: false; error: string } > { - const abs = path.resolve(expandHome(dirPath)); + const abs = path.resolve(expandHomePath(dirPath)); const projectsRepo = container.resolve('codeProjectsRepo'); let project: Awaited>; try { diff --git a/apps/x/packages/core/src/runtime/tools/domains/code.ts b/apps/x/packages/core/src/runtime/tools/domains/code.ts index d220b1ae..4a34a2ca 100644 --- a/apps/x/packages/core/src/runtime/tools/domains/code.ts +++ b/apps/x/packages/core/src/runtime/tools/domains/code.ts @@ -12,7 +12,7 @@ import { ICodeModeConfigRepo } from "../../../code-mode/repo.js"; import type { ApprovalPolicy, CodeRunEvent as CodeRunEventType } from "@x/shared/dist/code-mode.js"; import type { CodeRunFeed } from "../../../code-mode/feed.js"; import type { ToolContext } from "../exec-tool.js"; -import { expandHome } from "../paths.js"; +import { expandHomePath } from "../../../filesystem/files.js"; import { BuiltinToolsSchema } from "../types.js"; @@ -61,7 +61,7 @@ export const codeAgentRunTools: z.infer = { // cwd argument over the session's. Expand `~` and resolve to an absolute path: // the engine is spawned with this as the child's cwd, and `child_process.spawn` // does NO shell tilde expansion. - const effectiveCwd = path.resolve(expandHome(ctx.codeCwd ?? cwd)); + const effectiveCwd = path.resolve(expandHomePath(ctx.codeCwd ?? cwd)); // Fail loudly if the directory is missing. Otherwise the spawn below fails with // Node's misleading "spawn ENOENT" (it blames the executable, not the // bad cwd), which reads as "the coding engine isn't installed" — see the enriched diff --git a/apps/x/packages/core/src/runtime/tools/paths.ts b/apps/x/packages/core/src/runtime/tools/paths.ts deleted file mode 100644 index 80fc0528..00000000 --- a/apps/x/packages/core/src/runtime/tools/paths.ts +++ /dev/null @@ -1,18 +0,0 @@ -// Lenient ~-expansion for user-supplied paths in tool inputs. Distinct from -// filesystem/files.ts' private expandHomePath, which throws on empty input — -// tool entries want pass-through semantics for their own validation. - -import * as path from "path"; -import * as os from "os"; - -// Turn a user-supplied directory into a registered code project id. Reuses the -// same idempotent registry the Code-section picker writes to (add() validates the -// dir exists & is a directory, and dedupes by resolved path). Returns a soft -// `warning` — not an error — when the repo isn't yet worktree-ready, so the task -// still gets created and the copilot can tell the user what to fix. -export function expandHome(p: string): string { - const t = p.trim(); - if (t === '~') return os.homedir(); - if (t.startsWith('~/') || t.startsWith(`~${path.sep}`)) return path.join(os.homedir(), t.slice(2)); - return t; -}