Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions ergon-dashboard/scripts/generate-event-contracts.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,15 @@ import { GraphMutationDtoSchema } from "@/features/graph/contracts/graphMutation
export const DashboardGraphMutationEventSchema = z.object({
mutation: GraphMutationDtoSchema,
}).catchall(z.any());
`;
}
if (entry.modelName === "DashboardSampleRuntimeEvent") {
return `import { z } from "zod";
import { SampleRuntimeEventViewSchema } from "@/lib/contracts/rest";

export const DashboardSampleRuntimeEventSchema = z.object({
event: SampleRuntimeEventViewSchema,
}).catchall(z.any());
`;
}
return null;
Expand Down
50 changes: 49 additions & 1 deletion ergon-dashboard/scripts/generate-rest-contracts.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const contractsPath = path.resolve(__dirname, "../src/generated/rest/contracts.ts");

const source = readFileSync(contractsPath, "utf8")
let source = readFileSync(contractsPath, "utf8")
.replace('import { makeApi, Zodios, type ZodiosOptions } from "@zodios/core";\n', "")
// openapi-zod-client generates z.record(V) but Zod requires z.record(K, V).
.replace(/z\.record\((?!z\.string\(\))/g, "z.record(z.string(), ")
Expand All @@ -26,6 +26,54 @@ const source = readFileSync(contractsPath, "utf8")
/const JsonValue_(Input|Output): z\.ZodType<JsonValue_\1> = z\.union\(\[\n([\s\S]*?)\n\]\);/g,
"const JsonValue_$1: z.ZodType<JsonValue_$1> = z.lazy(() => z.union([\n$2\n]));",
);

const sampleRuntimeEventDiscriminators = {
SampleStatusChangedEventView: "sample.status_changed",
SampleTaskAddedEventView: "task.added",
SampleTaskRemovedEventView: "task.removed",
SampleTaskStatusChangedEventView: "task.status_changed",
SampleEdgeAddedEventView: "edge.added",
SampleEdgeRemovedEventView: "edge.removed",
SampleEdgeStatusChangedEventView: "edge.status_changed",
SampleWorkerAddedEventView: "worker.added",
SampleWorkerRemovedEventView: "worker.removed",
SampleEvaluatorAddedEventView: "evaluator.added",
SampleEvaluatorRemovedEventView: "evaluator.removed",
SampleSandboxAddedEventView: "sandbox.added",
SampleSandboxRemovedEventView: "sandbox.removed",
SampleAnnotationSetEventView: "annotation.set",
SampleAnnotationUpdatedEventView: "annotation.updated",
SampleAnnotationDeletedEventView: "annotation.deleted",
};

for (const [schemaName, eventType] of Object.entries(sampleRuntimeEventDiscriminators)) {
const pattern = new RegExp(`(const ${schemaName} = z[\\s\\S]*?eventType: )z\\.string\\(\\)(,)`);
source = source.replace(pattern, `$1z.literal("${eventType}")$2`);
}

const sampleRuntimeEventUnion = `const SampleRuntimeEventView = z.discriminatedUnion("eventType", [
SampleStatusChangedEventView,
SampleTaskAddedEventView,
SampleTaskRemovedEventView,
SampleTaskStatusChangedEventView,
SampleEdgeAddedEventView,
SampleEdgeRemovedEventView,
SampleEdgeStatusChangedEventView,
SampleWorkerAddedEventView,
SampleWorkerRemovedEventView,
SampleEvaluatorAddedEventView,
SampleEvaluatorRemovedEventView,
SampleSandboxAddedEventView,
SampleSandboxRemovedEventView,
SampleAnnotationSetEventView,
SampleAnnotationUpdatedEventView,
SampleAnnotationDeletedEventView,
]);
`;

source = source.replace("\nconst SampleEventsView =", `\n${sampleRuntimeEventUnion}const SampleEventsView =`);
source = source.replace(" SampleEventsView,", " SampleRuntimeEventView,\n SampleEventsView,");

const endpointMarker = "\nconst endpoints = makeApi([";
const markerIndex = source.indexOf(endpointMarker);

Expand Down
54 changes: 32 additions & 22 deletions ergon-dashboard/src/components/sample/SampleWorkspacePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,15 +77,14 @@ function payloadRecord(value: unknown): Record<string, unknown> {

function graphMutationValue(event: SampleRuntimeEventView, mutationType: MutationType): Record<string, unknown> {
const payload = payloadRecord(event.payload);
const task = payloadRecord(payload.task);
const edge = payloadRecord(payload.edge);

if (mutationType === "node.added") {
if (event.eventType === "task.added" && mutationType === "node.added") {
const task = payloadRecord(event.task);
return {
task_slug: String(payload.task_slug ?? task.task_slug ?? task.name ?? event.target_id ?? "task"),
instance_key: String(task.instance_key ?? payload.instance_key ?? event.target_id ?? "task"),
task_slug: String(event.taskSlug ?? task.task_slug ?? task.name ?? event.targetId ?? "task"),
instance_key: String(task.instance_key ?? payload.instance_key ?? event.targetId ?? "task"),
description: String(task.description ?? payload.description ?? ""),
status: String(payload.status ?? task.status ?? "pending"),
status: String(event.status ?? task.status ?? "pending"),
assigned_worker_slug:
typeof task.assigned_worker_slug === "string"
? task.assigned_worker_slug
Expand All @@ -95,22 +94,32 @@ function graphMutationValue(event: SampleRuntimeEventView, mutationType: Mutatio
};
}

if (mutationType === "node.status_changed" || mutationType === "edge.status_changed") {
return { status: String(payload.status ?? "pending") };
if (
(event.eventType === "task.status_changed" && mutationType === "node.status_changed") ||
(event.eventType === "edge.status_changed" && mutationType === "edge.status_changed")
) {
return { status: event.status };
}

if (mutationType === "edge.added" || mutationType === "edge.removed") {
if (
(event.eventType === "edge.added" || event.eventType === "edge.removed") &&
(mutationType === "edge.added" || mutationType === "edge.removed")
) {
const edge = event.eventType === "edge.added" ? payloadRecord(event.edge) : {};
return {
source_task_id: String(payload.source_task_id ?? edge.source_task_id ?? event.target_id),
target_task_id: String(payload.target_task_id ?? edge.target_task_id ?? event.target_id),
status: String(payload.status ?? edge.status ?? "pending"),
source_task_id: event.sourceTaskId,
target_task_id: event.targetTaskId,
status: String(event.eventType === "edge.added" ? (event.status ?? edge.status ?? "pending") : "removed"),
};
}

if (mutationType === "annotation.set" || mutationType === "annotation.deleted") {
if (
(event.eventType === "annotation.set" || event.eventType === "annotation.deleted") &&
(mutationType === "annotation.set" || mutationType === "annotation.deleted")
) {
return {
namespace: String(payload.namespace ?? payload.key ?? "runtime"),
payload: payloadRecord(payload.value ?? payload.payload),
namespace: event.key,
payload: event.eventType === "annotation.set" ? payloadRecord(event.value) : payload,
};
}

Expand All @@ -119,23 +128,24 @@ function graphMutationValue(event: SampleRuntimeEventView, mutationType: Mutatio

function sampleRuntimeEventsToGraphMutations(events: SampleRuntimeEventView[]): GraphMutationDto[] {
return events.flatMap((event, index) => {
const mutationType = graphMutationType(event.event_type);
if (mutationType === null || event.target_id === null) return [];
const targetType = event.target_type === "edge" ? "edge" : "node";
const mutationType = graphMutationType(event.eventType);
const targetId = event.targetId;
if (mutationType === null || !targetId) return [];
const targetType = event.targetType === "edge" ? "edge" : "node";
const newValue = graphMutationValue(event, mutationType);
return [
{
id: event.id,
sample_id: event.sample_id,
id: event.eventId,
sample_id: event.sampleId,
sequence: index + 1,
mutation_type: mutationType,
target_type: targetType,
target_id: event.target_id,
target_id: targetId,
actor: "runtime",
old_value: null,
new_value: newValue,
reason: null,
created_at: event.event_timestamp,
created_at: event.timestamp,
},
];
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import { z } from "zod"
import { z } from "zod";
import { SampleRuntimeEventViewSchema } from "@/lib/contracts/rest";

export const DashboardSampleRuntimeEventSchema = z.object({ "event": z.any() }).catchall(z.any())
export const DashboardSampleRuntimeEventSchema = z.object({
event: SampleRuntimeEventViewSchema,
}).catchall(z.any());
Loading
Loading