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.
90 lines
3.0 KiB
TypeScript
90 lines
3.0 KiB
TypeScript
import { type Actor, MessageBlock, type RunActivityRow } from "@rakazo/contracts";
|
|
import { ACTIVE_RUN_STATUSES, botMessageContext } from "@rakazo/core";
|
|
import type { PrismaClient } from "@rakazo/db";
|
|
|
|
const RECENT_LIMIT = 20;
|
|
const TERMINAL_STATUSES = ["completed", "failed", "cancelled"] as const;
|
|
|
|
function promptSnippet(prompt: string, max = 120): string {
|
|
const oneLine = prompt.replace(/\s+/g, " ").trim();
|
|
if (oneLine.length <= max) return oneLine;
|
|
return `${oneLine.slice(0, max - 1)}…`;
|
|
}
|
|
|
|
export function activityPromptSnippet(
|
|
input: { trigger: string; prompt: string; sourceBlocks?: unknown },
|
|
max = 120,
|
|
): string {
|
|
if (input.trigger !== "bot_message") return promptSnippet(input.prompt, max);
|
|
const parsed = MessageBlock.array().safeParse(input.sourceBlocks);
|
|
const message = parsed.success ? botMessageContext(parsed.data) : undefined;
|
|
if (!message) return "Message from another agent";
|
|
const name = message.fromBotName.trim() || "Another agent";
|
|
const label =
|
|
message.intent === "result" || message.intent === "status" || message.intent === "fyi"
|
|
? `Update from ${name}`
|
|
: `${name} asked`;
|
|
return promptSnippet(message.text.trim() ? `${label}: ${message.text}` : label, max);
|
|
}
|
|
|
|
export function activityNotificationsEnabled(
|
|
groupId: string | null,
|
|
notifyOnFinish: boolean,
|
|
): boolean {
|
|
return groupId !== null || notifyOnFinish;
|
|
}
|
|
|
|
export async function listSpaceRuns(
|
|
prisma: PrismaClient,
|
|
actor: Actor,
|
|
filter: "active" | "recent",
|
|
): Promise<RunActivityRow[]> {
|
|
const rows = await prisma.run.findMany({
|
|
where: {
|
|
spaceId: actor.spaceId,
|
|
userId: actor.userId,
|
|
bot: { archivedAt: null },
|
|
...(filter === "active"
|
|
? { status: { in: [...ACTIVE_RUN_STATUSES] } }
|
|
: { status: { in: [...TERMINAL_STATUSES] } }),
|
|
},
|
|
include: {
|
|
bot: { select: { name: true, archivedAt: true, notifyOnFinish: true } },
|
|
task: { select: { prompt: true } },
|
|
sourceMessage: { select: { blocks: true } },
|
|
thread: {
|
|
select: {
|
|
groupId: true,
|
|
group: { select: { name: true } },
|
|
},
|
|
},
|
|
},
|
|
orderBy:
|
|
filter === "active"
|
|
? [{ updatedAt: "desc" }, { id: "desc" }]
|
|
: [{ completedAt: "desc" }, { updatedAt: "desc" }, { id: "desc" }],
|
|
take: filter === "recent" ? RECENT_LIMIT : undefined,
|
|
});
|
|
|
|
return rows.map((row) => ({
|
|
runId: row.id,
|
|
botId: row.botId,
|
|
botName: row.bot.name,
|
|
groupId: row.thread.groupId,
|
|
groupName: row.thread.group?.name ?? null,
|
|
threadId: row.threadId,
|
|
status: row.status as RunActivityRow["status"],
|
|
trigger: row.trigger as RunActivityRow["trigger"],
|
|
notificationsEnabled: activityNotificationsEnabled(row.thread.groupId, row.bot.notifyOnFinish),
|
|
promptSnippet: activityPromptSnippet({
|
|
trigger: row.trigger,
|
|
prompt: row.task.prompt,
|
|
sourceBlocks: row.sourceMessage?.blocks,
|
|
}),
|
|
updatedAt: (filter === "recent" && row.completedAt
|
|
? row.completedAt
|
|
: row.updatedAt
|
|
).toISOString(),
|
|
}));
|
|
}
|