evOo-local/packages/adapters/src/background-job-handlers.ts
cynarAI 6c7eed7580 Initial clean evOo-local from f00577b
Fresh history cut from cynarAI/evoo antigravity-handoff/project-timeline
(Voice First + project timeline). Brand docs/titles as evOo; keep @rakazo/*
packages as tech debt. Excludes node_modules, caches, secrets, voice blobs.
2026-09-20 17:15:16 +02:00

116 lines
4.1 KiB
TypeScript

import type {
AgentHomeStore,
AgentRuntime,
BackgroundJobHandlers,
JobPublisher,
MessagingSurface,
SandboxProvider,
} from "@rakazo/adapter-kit";
import { messagingDeliverJob } from "@rakazo/adapter-kit";
import type { PrismaClient, ThreadEvents } from "@rakazo/db";
import { getLogger } from "@rakazo/logging";
import type { CloudAgentConnection } from "./cloud-agent-factory.js";
import { pollCloudAgent } from "./cloud-agent-poll.js";
import { expireComputerControl } from "./computer-control.js";
import { scheduleComputerSleep, sleepComputerIfIdle } from "./computer-idle.js";
import { performComputerUpdate } from "./computer-update.js";
import type { createRunExecutor } from "./executor.js";
import { compactHistory } from "./history-compaction.js";
import type { MemoryProviderResolver } from "./memory-provider-factory.js";
import { deliverMessagingOutbound, mirrorMessagingOutbound } from "./messaging-delivery.js";
import type { EncryptedSecretStore } from "./secrets.js";
import { expireTaughtSkillTeaching } from "./teaching-session.js";
export function createBackgroundJobHandlers(deps: {
executor: ReturnType<typeof createRunExecutor>;
prisma: PrismaClient;
sandbox: SandboxProvider;
home: AgentHomeStore;
jobs: JobPublisher;
events: ThreadEvents;
workerId: string;
runtime: AgentRuntime;
secretStore: EncryptedSecretStore;
memoryProviders: MemoryProviderResolver;
deploymentModelKey?: string;
messaging?: MessagingSurface;
cloudAgent?: CloudAgentConnection | null;
}): BackgroundJobHandlers {
const deliverMessaging = async (runId?: string) => {
if (!deps.messaging) return;
await deliverMessagingOutbound(
{ prisma: deps.prisma, messaging: deps.messaging, events: deps.events, jobs: deps.jobs },
{ runId },
{
operationId: `messaging.deliver:${runId ?? "drain"}`,
traceId: `messaging.deliver:${runId ?? "drain"}`,
spaceId: "",
userId: "",
signal: new AbortController().signal,
},
);
};
return {
"run.continue": async (payload) => {
await deps.executor.continueRun(payload.runId, deps.workerId);
// Automatic messaging mirror: once the run's bot messages are durable,
// copy them into the outbox. Never let mirror failures fail the run.
if (deps.messaging) {
await mirrorMessagingOutbound(
{ prisma: deps.prisma, messaging: deps.messaging, events: deps.events, jobs: deps.jobs },
payload.runId,
);
await deps.jobs.enqueue(messagingDeliverJob()).catch(async (error) => {
getLogger().error("messaging.deliver enqueue error", error);
await deliverMessaging();
});
}
},
"messaging.deliver": async (payload) => {
await deliverMessaging(payload.runId);
},
"routine.wakeup": async (payload) => {
await deps.executor.wakeRoutine(payload.routineId, payload.scheduledFor);
},
"computer.update": async ({ updateId }) => {
await performComputerUpdate(deps, updateId);
},
"computer.sleep": async (payload) => {
await sleepComputerIfIdle(deps, payload.computerId);
},
"computer.control-expire": async (payload) => {
if (await expireComputerControl(deps, payload.computerId, payload.leaseId)) {
scheduleComputerSleep(deps.jobs, payload.computerId);
}
},
"skill.teaching-expire": async (payload) => {
await expireTaughtSkillTeaching(deps, payload.skillId);
},
"cloud_agent.poll": async (payload) => {
await pollCloudAgent(
{
prisma: deps.prisma,
jobs: deps.jobs,
events: deps.events,
cloudAgent: deps.cloudAgent,
},
payload,
);
},
"history.compact": async (payload) => {
await compactHistory(
{
prisma: deps.prisma,
runtime: deps.runtime,
jobs: deps.jobs,
memoryProviders: deps.memoryProviders,
deploymentModelKey: deps.deploymentModelKey,
...(deps.executor.resolveModel ? { resolveModel: deps.executor.resolveModel } : {}),
},
payload.threadId,
);
},
};
}