mirror of
https://github.com/rowboatlabs/rowboat.git
synced 2026-07-12 21:02:17 +02:00
fix(x): blank tool paths error instead of resolving to the process cwd
tools/paths.ts' lenient expandHome passed blank input through, and
both call sites feed the result to path.resolve — so a model calling
code_agent_run with cwd: '' spawned the coding agent in the Electron
process cwd, and resolveCodeProject('') could register that cwd (a
real, existing directory) as a code project.
The 'lenient variant' turns out to be filesystem/files.ts'
expandHomePath minus exactly this guard, so this deletes tools/
paths.ts and exports the filesystem one instead of keeping a third
variant. A blank path now surfaces as a clear tool error ('Path is
required') the model can react to. Also drops the stray
resolveCodeProject comment the extraction left in paths.ts.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
05545ba283
commit
3b6c30fac9
4 changed files with 8 additions and 23 deletions
|
|
@ -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');
|
||||
|
|
|
|||
|
|
@ -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<ICodeProjectsRepo>('codeProjectsRepo');
|
||||
let project: Awaited<ReturnType<ICodeProjectsRepo['add']>>;
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -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<typeof BuiltinToolsSchema> = {
|
|||
// 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 <command> ENOENT" (it blames the executable, not the
|
||||
// bad cwd), which reads as "the coding engine isn't installed" — see the enriched
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue