1import {
2 type OrchestrationV2Actor,
3 type OrchestrationV2CreationSource,
4 ScheduledTaskId,
5} from "@t3tools/contracts";
6
7const LEGACY_AUTOMATION_PREFIX = /^\[Triggered by schedule task: [^\r\n]+\]\r?\n\r?\n/;
8const LEGACY_AUTOMATION_MESSAGE_ID = /^scheduled-task-message:(.+):\d+:(?:scheduled|manual)$/;
9
10/**
11 * Text and sender label for a user-role message. Older scheduled messages
12 * stored their attribution in the prompt itself.
13 */
14export function resolveUserMessagePresentation(message: {
15 readonly id?: string;
16 readonly role: string;
17 readonly text: string;
18 readonly createdBy?: OrchestrationV2Actor;
19 readonly creationSource?: OrchestrationV2CreationSource;
20 readonly scheduledTaskId?: ScheduledTaskId;
21}): {
22 readonly text: string;
23 /** Who sent a user-role message the user did not type. */
24 readonly attribution: "automation" | "agent" | "t3code" | null;
25 readonly scheduledTaskId: ScheduledTaskId | undefined;
26} {
27 if (message.role !== "user") {
28 return { text: message.text, attribution: null, scheduledTaskId: undefined };
29 }
30 if (message.scheduledTaskId !== undefined) {
31 return {
32 text: message.text,
33 attribution: "automation",
34 scheduledTaskId: message.scheduledTaskId,
35 };
36 }
37 const legacyPrefix = LEGACY_AUTOMATION_PREFIX.exec(message.text);
38 const legacyTaskId = legacyPrefix
39 ? LEGACY_AUTOMATION_MESSAGE_ID.exec(message.id ?? "")?.[1]
40 : undefined;
41 if (legacyPrefix !== null && (legacyTaskId !== undefined || message.createdBy === "agent")) {
42 return {
43 text: message.text.slice(legacyPrefix[0].length),
44 attribution: "automation",
45 scheduledTaskId: legacyTaskId === undefined ? undefined : ScheduledTaskId.make(legacyTaskId),
46 };
47 }
48 return {
49 text: message.text,
50 // Restart continuations were sent as the agent before they became notices.
51 attribution:
52 message.createdBy !== "agent"
53 ? null
54 : message.creationSource === "server"
55 ? "t3code"
56 : "agent",
57 scheduledTaskId: undefined,
58 };
59}