feat: workspace improvements - nullable cwd, repo-only workspaces, and resolution refactor

Make workspace cwd optional to support repo-only workspaces that don't require
a local directory. Refactor workspace resolution in heartbeat service to pass
all workspace hints to adapters, add fallback logic when project workspaces
have no valid local cwd, and improve workspace name derivation. Also adds limit
param to heartbeat runs list endpoint.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Forgotten
2026-02-25 21:35:33 -06:00
parent 30522f3f11
commit 20a4ca08a5
10 changed files with 5822 additions and 67 deletions

View File

@@ -20,17 +20,34 @@ export const updateProjectSchema = createProjectSchema.partial();
export type UpdateProject = z.infer<typeof updateProjectSchema>;
export const createProjectWorkspaceSchema = z.object({
name: z.string().min(1),
cwd: z.string().min(1),
const projectWorkspaceFields = {
name: z.string().min(1).optional(),
cwd: z.string().min(1).optional().nullable(),
repoUrl: z.string().url().optional().nullable(),
repoRef: z.string().optional().nullable(),
metadata: z.record(z.unknown()).optional().nullable(),
};
export const createProjectWorkspaceSchema = z.object({
...projectWorkspaceFields,
isPrimary: z.boolean().optional().default(false),
}).superRefine((value, ctx) => {
const hasCwd = typeof value.cwd === "string" && value.cwd.trim().length > 0;
const hasRepo = typeof value.repoUrl === "string" && value.repoUrl.trim().length > 0;
if (!hasCwd && !hasRepo) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: "Workspace requires at least one of cwd or repoUrl.",
path: ["cwd"],
});
}
});
export type CreateProjectWorkspace = z.infer<typeof createProjectWorkspaceSchema>;
export const updateProjectWorkspaceSchema = createProjectWorkspaceSchema.partial();
export const updateProjectWorkspaceSchema = z.object({
...projectWorkspaceFields,
isPrimary: z.boolean().optional(),
}).partial();
export type UpdateProjectWorkspace = z.infer<typeof updateProjectWorkspaceSchema>;