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;
}
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 {
if (isAbsolute(rel)) return null;
const joined = resolvePath(root, rel);
@@ -155,7 +187,7 @@ export function buildWorkProductMethods(
companyId: 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(
"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
@@ -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` };
}
const workspaceRoot = resolveWorkspaceRoot(
getDb,
companyId,
row.workspace_id,
row.task_id,
row.last_touched_by_run_id ?? row.created_by_run_id,
);
if (workspaceRoot) {
const workspaceRoots = orderedUnique([
resolveWorkspaceRoot(
getDb,
companyId,
row.workspace_id,
row.task_id,
row.last_touched_by_run_id ?? row.created_by_run_id,
),
...listCompanyWorkspaceRoots(getDb, companyId),
]);
let firstCandidate: string | null = null;
for (const workspaceRoot of workspaceRoots) {
const absolute = joinWorkspaceRelative(workspaceRoot, row.external_id);
if (!absolute) {
return { kind: "error", reason: "path_escape", detail: `external_id=${row.external_id} escapes workspace root ${workspaceRoot}` };
}
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
}
firstCandidate ??= absolute;
if (fileExists(absolute)) {
return { kind: "path", value: absolute };
}
}
if (firstCandidate) {
return {
kind: "error",
reason: "path_missing",
detail: `No registered company workspace contains ${row.external_id}; first candidate was ${firstCandidate}`,
};
}
return {
kind: "error",
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",
workspace_unresolved: "WORK_PRODUCT_WORKSPACE_UNRESOLVED",
path_escape: "WORK_PRODUCT_PATH_ESCAPE",
path_missing: "WORK_PRODUCT_PATH_MISSING",
} 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);
}
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 { join } from "node:path";
import { dirname, join } from "node:path";
import { tmpdir } from "node:os";
import { afterEach, describe, expect, it } from "vitest";
import { AppDatabase } from "../../src/main/database";
@@ -107,6 +108,9 @@ async function createHarness(): Promise<Harness> {
}
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({
companyId: harness.companyId,
taskId: harness.taskId,
@@ -179,6 +183,56 @@ describe("work_products archived visibility", () => {
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", () => {