evOo-local/packages/adapter-kit/src/background-jobs.ts
Claude a663764ee8
feat(media): contracts and foundation for Media Studio
Freeze the shared contracts every Media Studio slice builds on: zod DTOs,
EDL, platform profile, brand kit, gate and render plan schemas; the media
RPC surface with a scaffold router; provider interfaces for sources,
inference, rendering, motion graphics and publishing; media background
jobs; the Prisma models and migration; and the @rakazo/media domain
package signatures.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0138YqDj3ttfayRwuMKKrqVj
2026-10-03 17:32:52 +00:00

212 lines
6.4 KiB
TypeScript

import type { MediaAnalysisKind } from "@rakazo/contracts";
import { MediaAnalysisKindSchema } from "@rakazo/contracts";
import { z } from "zod";
import type {
BackgroundJob,
BackgroundJobHandlers,
BackgroundJobName,
BackgroundJobPayloads,
} from "./types.js";
const payloadSchemas = {
"run.continue": z.object({ runId: z.string().min(1) }),
"routine.wakeup": z.object({
routineId: z.string().min(1),
scheduledFor: z.string().datetime({ offset: true }),
}),
"computer.update": z.object({ updateId: z.string().min(1) }),
"computer.sleep": z.object({ computerId: z.string().min(1) }),
"computer.control-expire": z.object({
computerId: z.string().min(1),
leaseId: z.string().min(1),
}),
"skill.teaching-expire": z.object({ skillId: z.string().min(1) }),
"history.compact": z.object({ threadId: z.string().min(1) }),
"messaging.deliver": z.object({ runId: z.string().min(1).optional() }),
"cloud_agent.poll": z.object({ agentId: z.string().min(1) }),
"profile.consolidate": z.object({ userId: z.string().min(1) }),
"media.sync": z.object({ sourceId: z.string().min(1) }),
"media.proxy": z.object({ assetId: z.string().min(1) }),
"media.analyze": z.object({
assetId: z.string().min(1),
kinds: z.array(MediaAnalysisKindSchema).optional(),
}),
"media.cluster": z.object({ spaceId: z.string().min(1) }),
"media.render": z.object({ renderId: z.string().min(1) }),
"media.publish": z.object({ publicationId: z.string().min(1) }),
} satisfies { [Name in BackgroundJobName]: z.ZodType<BackgroundJobPayloads[Name]> };
export function parseBackgroundJob(name: string, payload: unknown): BackgroundJob {
if (!(name in payloadSchemas)) throw new Error(`Unknown background job: ${name}`);
const typedName = name as BackgroundJobName;
const parsed = payloadSchemas[typedName].parse(payload);
return { name: typedName, payload: parsed } as BackgroundJob;
}
export async function dispatchBackgroundJob(
handlers: BackgroundJobHandlers,
name: string,
payload: unknown,
): Promise<void> {
const job = parseBackgroundJob(name, payload);
const handler = handlers[job.name] as (payload: typeof job.payload) => Promise<void>;
await handler(job.payload);
}
export function runJobKey(runId: string): string {
return `run:${runId}`;
}
export function routineJobKey(routineId: string): string {
return `routine:${routineId}`;
}
export function computerSleepJobKey(computerId: string): string {
return `computer.sleep:${computerId}`;
}
export function computerControlExpireJobKey(computerId: string, leaseId?: string): string {
return leaseId
? `computer.control-expire:${computerId}:${leaseId}`
: `computer.control-expire:${computerId}`;
}
export function skillTeachingExpireJobKey(skillId: string): string {
return `skill.teaching-expire:${skillId}`;
}
export function runContinueJob(runId: string): BackgroundJob {
return {
name: "run.continue",
payload: { runId },
replaceKey: runJobKey(runId),
};
}
export function routineWakeupJob(routineId: string, scheduledFor: Date): BackgroundJob {
return {
name: "routine.wakeup",
payload: { routineId, scheduledFor: scheduledFor.toISOString() },
availableAt: scheduledFor,
replaceKey: routineJobKey(routineId),
};
}
export function computerSleepJob(computerId: string, availableAt: Date): BackgroundJob {
return {
name: "computer.sleep",
payload: { computerId },
availableAt,
replaceKey: computerSleepJobKey(computerId),
};
}
export function computerControlExpireJob(
computerId: string,
leaseId: string,
availableAt: Date,
): BackgroundJob {
return {
name: "computer.control-expire",
payload: { computerId, leaseId },
availableAt,
replaceKey: computerControlExpireJobKey(computerId, leaseId),
};
}
export function skillTeachingExpireJob(skillId: string, availableAt: Date): BackgroundJob {
return {
name: "skill.teaching-expire",
payload: { skillId },
availableAt,
replaceKey: skillTeachingExpireJobKey(skillId),
};
}
export function historyCompactJobKey(threadId: string): string {
return `history.compact:${threadId}`;
}
export function messagingDeliverJob(runId?: string, availableAt?: Date): BackgroundJob {
return {
name: "messaging.deliver",
payload: runId ? { runId } : {},
replaceKey: `messaging.deliver:${runId ?? "drain"}`,
...(availableAt ? { availableAt } : {}),
};
}
export function historyCompactJob(threadId: string): BackgroundJob {
return {
name: "history.compact",
payload: { threadId },
replaceKey: historyCompactJobKey(threadId),
};
}
export function cloudAgentPollJobKey(agentId: string): string {
return `cloud_agent.poll:${agentId}`;
}
export function cloudAgentPollJob(
payload: BackgroundJobPayloads["cloud_agent.poll"],
availableAt?: Date,
): BackgroundJob {
return {
name: "cloud_agent.poll",
payload,
replaceKey: cloudAgentPollJobKey(payload.agentId),
...(availableAt ? { availableAt } : {}),
};
}
export function profileConsolidateJobKey(userId: string): string {
return `profile.consolidate:${userId}`;
}
export function profileConsolidateJob(userId: string): BackgroundJob {
return {
name: "profile.consolidate",
payload: { userId },
replaceKey: profileConsolidateJobKey(userId),
};
}
export function mediaSyncJob(sourceId: string): BackgroundJob {
return { name: "media.sync", payload: { sourceId }, replaceKey: `media.sync:${sourceId}` };
}
export function mediaProxyJob(assetId: string): BackgroundJob {
return { name: "media.proxy", payload: { assetId }, replaceKey: `media.proxy:${assetId}` };
}
export function mediaAnalyzeJob(assetId: string, kinds?: MediaAnalysisKind[]): BackgroundJob {
return {
name: "media.analyze",
payload: kinds ? { assetId, kinds } : { assetId },
replaceKey: `media.analyze:${assetId}`,
};
}
export function mediaClusterJob(spaceId: string, availableAt?: Date): BackgroundJob {
return {
name: "media.cluster",
payload: { spaceId },
replaceKey: `media.cluster:${spaceId}`,
...(availableAt ? { availableAt } : {}),
};
}
export function mediaRenderJob(renderId: string): BackgroundJob {
return { name: "media.render", payload: { renderId }, replaceKey: `media.render:${renderId}` };
}
export function mediaPublishJob(publicationId: string, availableAt?: Date): BackgroundJob {
return {
name: "media.publish",
payload: { publicationId },
replaceKey: `media.publish:${publicationId}`,
...(availableAt ? { availableAt } : {}),
};
}