Resolve filesystem work product targets by existing file

This commit is contained in:
ZacharyZhang-NY committed 2026-04-22 20:06:01 -04:00
1 parent c1349fceab
commit d13c9d83e8
3 files changed
+118 -29

No files matched your search

+58 -28
View File
@@ -33,6 +33,38 @@ function resolveWorkspaceRoot(
return null; return null;
} }
function listCompanyWorkspaceRoots(
getDb: () => DatabaseSync,
companyId: string,
): string[] {
return (getDb()
.prepare(
"SELECT local_path AS localPath FROM workspaces WHERE company_id = ? AND local_path IS NOT NULL ORDER BY is_primary DESC, created_at ASC",
)
.all(companyId) as Array<{ localPath: string }>)
.map((row) => row.localPath)
.filter((localPath) => localPath.length > 0);
}
function orderedUnique(values: Array<string | null>): string[] {
const seen = new Set<string>();
const unique: string[] = [];
for (const value of values) {
if (!value || seen.has(value)) continue;
seen.add(value);
unique.push(value);
}
return unique;
}
function fileExists(targetPath: string): boolean {
try {
return statSync(targetPath).isFile();
} catch {
return false;
}
}
function joinWorkspaceRelative(root: string, rel: string): string | null { function joinWorkspaceRelative(root: string, rel: string): string | null {
if (isAbsolute(rel)) return null; if (isAbsolute(rel)) return null;
const joined = resolvePath(root, rel); const joined = resolvePath(root, rel);
@@ -155,7 +187,7 @@ export function buildWorkProductMethods(
companyId: string, companyId: string,
): ):
| { kind: "url" | "path"; value: string } | { kind: "url" | "path"; value: string }
| { kind: "error"; reason: "not_found" | "archived" | "no_target" | "workspace_unresolved" | "path_escape"; detail: string } { | { kind: "error"; reason: "not_found" | "archived" | "no_target" | "workspace_unresolved" | "path_escape" | "path_missing"; detail: string } {
const row = getDb().prepare( const row = getDb().prepare(
"SELECT provider, external_id, url, status, task_id, created_by_run_id, last_touched_by_run_id, workspace_id FROM work_products WHERE id = ? AND company_id = ?", "SELECT provider, external_id, url, status, task_id, created_by_run_id, last_touched_by_run_id, workspace_id FROM work_products WHERE id = ? AND company_id = ?",
).get(workProductId, companyId) as ).get(workProductId, companyId) as
@@ -169,42 +201,40 @@ export function buildWorkProductMethods(
return { kind: "error", reason: "no_target", detail: `provider=${row.provider} external_id=${row.external_id ?? "null"} url=null` }; return { kind: "error", reason: "no_target", detail: `provider=${row.provider} external_id=${row.external_id ?? "null"} url=null` };
} }
const workspaceRoot = resolveWorkspaceRoot( const workspaceRoots = orderedUnique([
getDb, resolveWorkspaceRoot(
companyId, getDb,
row.workspace_id, companyId,
row.task_id, row.workspace_id,
row.last_touched_by_run_id ?? row.created_by_run_id, row.task_id,
); row.last_touched_by_run_id ?? row.created_by_run_id,
if (workspaceRoot) { ),
...listCompanyWorkspaceRoots(getDb, companyId),
]);
let firstCandidate: string | null = null;
for (const workspaceRoot of workspaceRoots) {
const absolute = joinWorkspaceRelative(workspaceRoot, row.external_id); const absolute = joinWorkspaceRelative(workspaceRoot, row.external_id);
if (!absolute) { if (!absolute) {
return { kind: "error", reason: "path_escape", detail: `external_id=${row.external_id} escapes workspace root ${workspaceRoot}` }; return { kind: "error", reason: "path_escape", detail: `external_id=${row.external_id} escapes workspace root ${workspaceRoot}` };
} }
return { kind: "path", value: absolute }; firstCandidate ??= absolute;
} if (fileExists(absolute)) {
return { kind: "path", value: absolute };
const observation = getDb()
.prepare(
"SELECT local_path as localPath FROM workspaces WHERE company_id = ? AND local_path IS NOT NULL ORDER BY is_primary DESC, created_at ASC LIMIT 1",
)
.get(companyId) as { localPath: string } | undefined;
if (observation?.localPath) {
const candidate = joinWorkspaceRelative(observation.localPath, row.external_id);
if (candidate) {
try {
if (statSync(candidate).isFile()) {
return { kind: "path", value: candidate };
}
} catch {
// fall through to error below
}
} }
} }
if (firstCandidate) {
return {
kind: "error",
reason: "path_missing",
detail: `No registered company workspace contains ${row.external_id}; first candidate was ${firstCandidate}`,
};
}
return { return {
kind: "error", kind: "error",
reason: "workspace_unresolved", reason: "workspace_unresolved",
detail: `workspace_id=${row.workspace_id ?? "null"} task_id=${row.task_id ?? "null"} run_id=${row.last_touched_by_run_id ?? row.created_by_run_id ?? "null"} — none led to a workspace with a local_path, and ${row.external_id} is not present in the company's observation workspace${observation?.localPath ? ` (${observation.localPath})` : " (no observation workspace exists)"}`, detail: `workspace_id=${row.workspace_id ?? "null"} task_id=${row.task_id ?? "null"} run_id=${row.last_touched_by_run_id ?? row.created_by_run_id ?? "null"} — none led to a workspace with a local_path`,
}; };
}, },
+5
View File
@@ -76,7 +76,12 @@ export function registerCoreReadHandlers({
no_target: "WORK_PRODUCT_NO_TARGET", no_target: "WORK_PRODUCT_NO_TARGET",
workspace_unresolved: "WORK_PRODUCT_WORKSPACE_UNRESOLVED", workspace_unresolved: "WORK_PRODUCT_WORKSPACE_UNRESOLVED",
path_escape: "WORK_PRODUCT_PATH_ESCAPE", path_escape: "WORK_PRODUCT_PATH_ESCAPE",
path_missing: "WORK_PRODUCT_PATH_MISSING",
} as const; } as const;
if (target.reason === "path_missing") {
db.core.documents.updateWorkProduct(parsed.data.id, parsed.data.companyId, { status: "archived" });
publishDomainChanged();
}
return fail(codeByReason[target.reason], target.detail); return fail(codeByReason[target.reason], target.detail);
} }
if (target.kind === "url") { if (target.kind === "url") {
@@ -1,5 +1,6 @@
import { mkdirSync, writeFileSync } from "node:fs";
import { mkdtemp, mkdir, rm, writeFile, unlink } from "node:fs/promises"; import { mkdtemp, mkdir, rm, writeFile, unlink } from "node:fs/promises";
import { join } from "node:path"; import { dirname, join } from "node:path";
import { tmpdir } from "node:os"; import { tmpdir } from "node:os";
import { afterEach, describe, expect, it } from "vitest"; import { afterEach, describe, expect, it } from "vitest";
import { AppDatabase } from "../../src/main/database"; import { AppDatabase } from "../../src/main/database";
@@ -107,6 +108,9 @@ async function createHarness(): Promise<Harness> {
} }
function registerArtifact(harness: Harness, relativePath: string): string { function registerArtifact(harness: Harness, relativePath: string): string {
const absPath = join(harness.workspacePath, relativePath);
mkdirSync(dirname(absPath), { recursive: true });
writeFileSync(absPath, "tracked artifact", "utf8");
return harness.db.core.documents.createWorkProduct({ return harness.db.core.documents.createWorkProduct({
companyId: harness.companyId, companyId: harness.companyId,
taskId: harness.taskId, taskId: harness.taskId,
@@ -179,6 +183,56 @@ describe("work_products archived visibility", () => {
harness.db.close(); harness.db.close();
} }
}); });
it("resolves workspace-prefixed filesystem rows through another company workspace when the bound root misses", async () => {
const harness = await createHarness();
try {
const parentPath = await createTempDir("agentcompany-parent-workspace-");
const projectPath = join(parentPath, "booking-app");
await mkdir(projectPath, { recursive: true });
await writeFile(join(projectPath, "AGENTS.md"), "instructions", "utf8");
harness.db.core.workspaces.saveWorkspace({
companyId: harness.companyId,
name: "Parent",
localPath: parentPath,
repoUrl: "",
repoRef: "",
isPrimary: false,
});
const id = harness.db.core.documents.createWorkProduct({
companyId: harness.companyId,
taskId: harness.taskId,
workspaceId: harness.workspaceId,
type: "file",
provider: "filesystem",
externalId: "booking-app/AGENTS.md",
title: "AGENTS.md",
url: null,
createdByRunId: harness.runId,
});
expect(
harness.db.core.documents.resolveWorkProductTarget(id, harness.companyId),
).toEqual({ kind: "path", value: join(projectPath, "AGENTS.md") });
} finally {
harness.db.close();
}
});
it("reports missing filesystem rows when no company workspace contains the file", async () => {
const harness = await createHarness();
try {
const id = registerArtifact(harness, "docs/missing.md");
await unlink(join(harness.workspacePath, "docs/missing.md"));
expect(
harness.db.core.documents.resolveWorkProductTarget(id, harness.companyId),
).toMatchObject({ kind: "error", reason: "path_missing" });
} finally {
harness.db.close();
}
});
}); });
describe("work_products bulk retirement", () => { describe("work_products bulk retirement", () => {