Address runtime workspace review feedback
Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
parent
b3d61a7561
commit
92ebad3d42
3 changed files with 47 additions and 38 deletions
|
|
@ -62,6 +62,36 @@ export const executionWorkspaceCloseGitReadinessSchema = z.object({
|
|||
createdByRuntime: z.boolean(),
|
||||
}).strict();
|
||||
|
||||
export const workspaceRuntimeServiceSchema = z.object({
|
||||
id: z.string(),
|
||||
companyId: z.string().uuid(),
|
||||
projectId: z.string().uuid().nullable(),
|
||||
projectWorkspaceId: z.string().uuid().nullable(),
|
||||
executionWorkspaceId: z.string().uuid().nullable(),
|
||||
issueId: z.string().uuid().nullable(),
|
||||
scopeType: z.enum(["project_workspace", "execution_workspace", "run", "agent"]),
|
||||
scopeId: z.string().nullable(),
|
||||
serviceName: z.string(),
|
||||
status: z.enum(["starting", "running", "stopped", "failed"]),
|
||||
lifecycle: z.enum(["shared", "ephemeral"]),
|
||||
reuseKey: z.string().nullable(),
|
||||
command: z.string().nullable(),
|
||||
cwd: z.string().nullable(),
|
||||
port: z.number().int().nullable(),
|
||||
url: z.string().nullable(),
|
||||
provider: z.enum(["local_process", "adapter_managed"]),
|
||||
providerRef: z.string().nullable(),
|
||||
ownerAgentId: z.string().uuid().nullable(),
|
||||
startedByRunId: z.string().uuid().nullable(),
|
||||
lastUsedAt: z.coerce.date(),
|
||||
startedAt: z.coerce.date(),
|
||||
stoppedAt: z.coerce.date().nullable(),
|
||||
stopPolicy: z.record(z.unknown()).nullable(),
|
||||
healthStatus: z.enum(["unknown", "healthy", "unhealthy"]),
|
||||
createdAt: z.coerce.date(),
|
||||
updatedAt: z.coerce.date(),
|
||||
}).strict();
|
||||
|
||||
export const executionWorkspaceCloseReadinessSchema = z.object({
|
||||
workspaceId: z.string().uuid(),
|
||||
state: executionWorkspaceCloseReadinessStateSchema,
|
||||
|
|
@ -73,35 +103,7 @@ export const executionWorkspaceCloseReadinessSchema = z.object({
|
|||
isSharedWorkspace: z.boolean(),
|
||||
isProjectPrimaryWorkspace: z.boolean(),
|
||||
git: executionWorkspaceCloseGitReadinessSchema.nullable(),
|
||||
runtimeServices: z.array(z.object({
|
||||
id: z.string(),
|
||||
companyId: z.string().uuid(),
|
||||
projectId: z.string().uuid().nullable(),
|
||||
projectWorkspaceId: z.string().uuid().nullable(),
|
||||
executionWorkspaceId: z.string().uuid().nullable(),
|
||||
issueId: z.string().uuid().nullable(),
|
||||
scopeType: z.enum(["project_workspace", "execution_workspace", "run", "agent"]),
|
||||
scopeId: z.string().nullable(),
|
||||
serviceName: z.string(),
|
||||
status: z.enum(["starting", "running", "stopped", "failed"]),
|
||||
lifecycle: z.enum(["shared", "ephemeral"]),
|
||||
reuseKey: z.string().nullable(),
|
||||
command: z.string().nullable(),
|
||||
cwd: z.string().nullable(),
|
||||
port: z.number().int().nullable(),
|
||||
url: z.string().nullable(),
|
||||
provider: z.enum(["local_process", "adapter_managed"]),
|
||||
providerRef: z.string().nullable(),
|
||||
ownerAgentId: z.string().uuid().nullable(),
|
||||
startedByRunId: z.string().uuid().nullable(),
|
||||
lastUsedAt: z.coerce.date(),
|
||||
startedAt: z.coerce.date(),
|
||||
stoppedAt: z.coerce.date().nullable(),
|
||||
stopPolicy: z.record(z.unknown()).nullable(),
|
||||
healthStatus: z.enum(["unknown", "healthy", "unhealthy"]),
|
||||
createdAt: z.coerce.date(),
|
||||
updatedAt: z.coerce.date(),
|
||||
}).strict()),
|
||||
runtimeServices: z.array(workspaceRuntimeServiceSchema),
|
||||
}).strict();
|
||||
|
||||
export const updateExecutionWorkspaceSchema = z.object({
|
||||
|
|
|
|||
|
|
@ -1192,6 +1192,8 @@ export function normalizeAdapterManagedRuntimeServices(input: {
|
|||
async function startLocalRuntimeService(input: {
|
||||
db?: Db;
|
||||
runId: string;
|
||||
leaseRunId?: string | null;
|
||||
startedByRunId?: string | null;
|
||||
agent: ExecutionWorkspaceAgentRef;
|
||||
issue: ExecutionWorkspaceIssueRef | null;
|
||||
workspace: RealizedExecutionWorkspace;
|
||||
|
|
@ -1203,6 +1205,8 @@ async function startLocalRuntimeService(input: {
|
|||
scopeType: "project_workspace" | "execution_workspace" | "run" | "agent";
|
||||
scopeId: string | null;
|
||||
}): Promise<RuntimeServiceRecord> {
|
||||
const leaseRunId = input.leaseRunId === undefined ? input.runId : input.leaseRunId;
|
||||
const startedByRunId = input.startedByRunId === undefined ? input.runId : input.startedByRunId;
|
||||
const identity = resolveRuntimeServiceReuseIdentity({
|
||||
service: input.service,
|
||||
workspace: input.workspace,
|
||||
|
|
@ -1299,7 +1303,7 @@ async function startLocalRuntimeService(input: {
|
|||
provider: "local_process",
|
||||
providerRef: String(adoptedRecord.pid),
|
||||
ownerAgentId: input.agent.id ?? null,
|
||||
startedByRunId: input.runId,
|
||||
startedByRunId,
|
||||
lastUsedAt: new Date().toISOString(),
|
||||
startedAt: adoptedRecord.startedAt,
|
||||
stoppedAt: null,
|
||||
|
|
@ -1308,7 +1312,7 @@ async function startLocalRuntimeService(input: {
|
|||
reused: true,
|
||||
db: input.db,
|
||||
child: null,
|
||||
leaseRunIds: new Set([input.runId]),
|
||||
leaseRunIds: leaseRunId ? new Set([leaseRunId]) : new Set(),
|
||||
idleTimer: null,
|
||||
envFingerprint,
|
||||
serviceKey,
|
||||
|
|
@ -1373,7 +1377,7 @@ async function startLocalRuntimeService(input: {
|
|||
provider: "local_process",
|
||||
providerRef: child.pid ? String(child.pid) : null,
|
||||
ownerAgentId: input.agent.id ?? null,
|
||||
startedByRunId: input.runId,
|
||||
startedByRunId,
|
||||
lastUsedAt: new Date().toISOString(),
|
||||
startedAt: new Date().toISOString(),
|
||||
stoppedAt: null,
|
||||
|
|
@ -1382,7 +1386,7 @@ async function startLocalRuntimeService(input: {
|
|||
reused: false,
|
||||
db: input.db,
|
||||
child,
|
||||
leaseRunIds: new Set([input.runId]),
|
||||
leaseRunIds: leaseRunId ? new Set([leaseRunId]) : new Set(),
|
||||
idleTimer: null,
|
||||
envFingerprint,
|
||||
serviceKey,
|
||||
|
|
@ -1648,9 +1652,13 @@ export async function startRuntimeServicesForWorkspaceControl(input: {
|
|||
}
|
||||
}
|
||||
|
||||
// Manually controlled services are not tied to a heartbeat run lifecycle, so they do not
|
||||
// retain a run lease and never persist a startedByRunId foreign key.
|
||||
const record = await startLocalRuntimeService({
|
||||
db: input.db,
|
||||
runId: invocationId,
|
||||
leaseRunId: null,
|
||||
startedByRunId: null,
|
||||
agent: input.actor,
|
||||
issue: input.issue,
|
||||
workspace: input.workspace,
|
||||
|
|
@ -1662,7 +1670,6 @@ export async function startRuntimeServicesForWorkspaceControl(input: {
|
|||
scopeType,
|
||||
scopeId,
|
||||
});
|
||||
record.startedByRunId = null;
|
||||
registerRuntimeService(input.db, record);
|
||||
await persistRuntimeServiceRecord(input.db, record);
|
||||
refs.push(toRuntimeServiceRef(record));
|
||||
|
|
|
|||
|
|
@ -149,8 +149,8 @@ export function ExecutionWorkspaceCloseDialog({
|
|||
<section className="space-y-2">
|
||||
<h3 className="text-sm font-medium">Blocking reasons</h3>
|
||||
<ul className="space-y-2 text-sm text-muted-foreground">
|
||||
{readiness.blockingReasons.map((reason) => (
|
||||
<li key={reason} className="break-words rounded-lg border border-destructive/20 bg-destructive/5 px-3 py-2 text-destructive">
|
||||
{readiness.blockingReasons.map((reason, idx) => (
|
||||
<li key={`blocking-${idx}`} className="break-words rounded-lg border border-destructive/20 bg-destructive/5 px-3 py-2 text-destructive">
|
||||
{reason}
|
||||
</li>
|
||||
))}
|
||||
|
|
@ -162,8 +162,8 @@ export function ExecutionWorkspaceCloseDialog({
|
|||
<section className="space-y-2">
|
||||
<h3 className="text-sm font-medium">Warnings</h3>
|
||||
<ul className="space-y-2 text-sm text-muted-foreground">
|
||||
{readiness.warnings.map((warning) => (
|
||||
<li key={warning} className="break-words rounded-lg border border-amber-500/20 bg-amber-500/5 px-3 py-2">
|
||||
{readiness.warnings.map((warning, idx) => (
|
||||
<li key={`warning-${idx}`} className="break-words rounded-lg border border-amber-500/20 bg-amber-500/5 px-3 py-2">
|
||||
{warning}
|
||||
</li>
|
||||
))}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue