Add workspace operation tracking and fix project properties JSX

This commit is contained in:
Dotta
2026-03-17 09:36:35 -05:00
parent e39ae5a400
commit 4da13984e2
19 changed files with 11537 additions and 30 deletions

View File

@@ -0,0 +1,29 @@
CREATE TABLE "workspace_operations" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"company_id" uuid NOT NULL,
"execution_workspace_id" uuid,
"heartbeat_run_id" uuid,
"phase" text NOT NULL,
"command" text,
"cwd" text,
"status" text DEFAULT 'running' NOT NULL,
"exit_code" integer,
"log_store" text,
"log_ref" text,
"log_bytes" bigint,
"log_sha256" text,
"log_compressed" boolean DEFAULT false NOT NULL,
"stdout_excerpt" text,
"stderr_excerpt" text,
"metadata" jsonb,
"started_at" timestamp with time zone DEFAULT now() NOT NULL,
"finished_at" timestamp with time zone,
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
"updated_at" timestamp with time zone DEFAULT now() NOT NULL
);
--> statement-breakpoint
ALTER TABLE "workspace_operations" ADD CONSTRAINT "workspace_operations_company_id_companies_id_fk" FOREIGN KEY ("company_id") REFERENCES "public"."companies"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "workspace_operations" ADD CONSTRAINT "workspace_operations_execution_workspace_id_execution_workspaces_id_fk" FOREIGN KEY ("execution_workspace_id") REFERENCES "public"."execution_workspaces"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "workspace_operations" ADD CONSTRAINT "workspace_operations_heartbeat_run_id_heartbeat_runs_id_fk" FOREIGN KEY ("heartbeat_run_id") REFERENCES "public"."heartbeat_runs"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
CREATE INDEX "workspace_operations_company_run_started_idx" ON "workspace_operations" USING btree ("company_id","heartbeat_run_id","started_at");--> statement-breakpoint
CREATE INDEX "workspace_operations_company_workspace_started_idx" ON "workspace_operations" USING btree ("company_id","execution_workspace_id","started_at");

File diff suppressed because it is too large Load Diff

View File

@@ -260,6 +260,13 @@
"when": 1773756213455,
"tag": "0036_cheerful_nitro",
"breakpoints": true
},
{
"idx": 37,
"version": "7",
"when": 1773756922363,
"tag": "0037_friendly_eddie_brock",
"breakpoints": true
}
]
}
}

View File

@@ -18,6 +18,7 @@ export { agentWakeupRequests } from "./agent_wakeup_requests.js";
export { projects } from "./projects.js";
export { projectWorkspaces } from "./project_workspaces.js";
export { executionWorkspaces } from "./execution_workspaces.js";
export { workspaceOperations } from "./workspace_operations.js";
export { workspaceRuntimeServices } from "./workspace_runtime_services.js";
export { projectGoals } from "./project_goals.js";
export { goals } from "./goals.js";

View File

@@ -0,0 +1,57 @@
import {
bigint,
boolean,
index,
integer,
jsonb,
pgTable,
text,
timestamp,
uuid,
} from "drizzle-orm/pg-core";
import { companies } from "./companies.js";
import { executionWorkspaces } from "./execution_workspaces.js";
import { heartbeatRuns } from "./heartbeat_runs.js";
export const workspaceOperations = pgTable(
"workspace_operations",
{
id: uuid("id").primaryKey().defaultRandom(),
companyId: uuid("company_id").notNull().references(() => companies.id),
executionWorkspaceId: uuid("execution_workspace_id").references(() => executionWorkspaces.id, {
onDelete: "set null",
}),
heartbeatRunId: uuid("heartbeat_run_id").references(() => heartbeatRuns.id, {
onDelete: "set null",
}),
phase: text("phase").notNull(),
command: text("command"),
cwd: text("cwd"),
status: text("status").notNull().default("running"),
exitCode: integer("exit_code"),
logStore: text("log_store"),
logRef: text("log_ref"),
logBytes: bigint("log_bytes", { mode: "number" }),
logSha256: text("log_sha256"),
logCompressed: boolean("log_compressed").notNull().default(false),
stdoutExcerpt: text("stdout_excerpt"),
stderrExcerpt: text("stderr_excerpt"),
metadata: jsonb("metadata").$type<Record<string, unknown>>(),
startedAt: timestamp("started_at", { withTimezone: true }).notNull().defaultNow(),
finishedAt: timestamp("finished_at", { withTimezone: true }),
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
},
(table) => ({
companyRunStartedIdx: index("workspace_operations_company_run_started_idx").on(
table.companyId,
table.heartbeatRunId,
table.startedAt,
),
companyWorkspaceStartedIdx: index("workspace_operations_company_workspace_started_idx").on(
table.companyId,
table.executionWorkspaceId,
table.startedAt,
),
}),
);

View File

@@ -138,6 +138,9 @@ export type {
ProjectWorkspace,
ExecutionWorkspace,
WorkspaceRuntimeService,
WorkspaceOperation,
WorkspaceOperationPhase,
WorkspaceOperationStatus,
ExecutionWorkspaceStrategyType,
ExecutionWorkspaceMode,
ExecutionWorkspaceProviderType,

View File

@@ -24,6 +24,11 @@ export type {
ProjectExecutionWorkspaceDefaultMode,
IssueExecutionWorkspaceSettings,
} from "./workspace-runtime.js";
export type {
WorkspaceOperation,
WorkspaceOperationPhase,
WorkspaceOperationStatus,
} from "./workspace-operation.js";
export type {
IssueWorkProduct,
IssueWorkProductType,

View File

@@ -0,0 +1,31 @@
export type WorkspaceOperationPhase =
| "worktree_prepare"
| "workspace_provision"
| "workspace_teardown"
| "worktree_cleanup";
export type WorkspaceOperationStatus = "running" | "succeeded" | "failed" | "skipped";
export interface WorkspaceOperation {
id: string;
companyId: string;
executionWorkspaceId: string | null;
heartbeatRunId: string | null;
phase: WorkspaceOperationPhase;
command: string | null;
cwd: string | null;
status: WorkspaceOperationStatus;
exitCode: number | null;
logStore: string | null;
logRef: string | null;
logBytes: number | null;
logSha256: string | null;
logCompressed: boolean;
stdoutExcerpt: string | null;
stderrExcerpt: string | null;
metadata: Record<string, unknown> | null;
startedAt: Date;
finishedAt: Date | null;
createdAt: Date;
updatedAt: Date;
}