@letta-ai/letta-code 0.30.0 → 0.30.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,189 @@
1
+ // src/cron/scheduled-task-prompt.ts
2
+ var SYSTEM_REMINDER_OPEN = "<system-reminder>";
3
+ var SYSTEM_REMINDER_CLOSE = "</system-reminder>";
4
+ var AUTONOMOUS_NOTICE_PREFIX = "You are running autonomously:";
5
+ var AUTONOMOUS_NOTICE = "You are running autonomously: no user is watching this turn and questions will not be answered. Deliver results through your available channels or record them in memory, and work until the task is done or genuinely blocked.";
6
+ function pad(value, width) {
7
+ return String(value).padStart(width, "0");
8
+ }
9
+ function formatOffset(minutes) {
10
+ const sign = minutes >= 0 ? "+" : "-";
11
+ const abs = Math.abs(minutes);
12
+ return `${sign}${pad(Math.floor(abs / 60), 2)}:${pad(abs % 60, 2)}`;
13
+ }
14
+ function getLocalDateTimeParts(date) {
15
+ return {
16
+ year: date.getFullYear(),
17
+ month: date.getMonth() + 1,
18
+ day: date.getDate(),
19
+ hour: date.getHours(),
20
+ minute: date.getMinutes(),
21
+ second: date.getSeconds()
22
+ };
23
+ }
24
+ function isValidTimezone(timezone) {
25
+ try {
26
+ new Intl.DateTimeFormat("en-US", { timeZone: timezone });
27
+ return true;
28
+ } catch {
29
+ return false;
30
+ }
31
+ }
32
+ function getSystemTimezone() {
33
+ const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
34
+ if (!timezone || !isValidTimezone(timezone)) {
35
+ return null;
36
+ }
37
+ return timezone;
38
+ }
39
+ function getEffectiveTimezone(timezone) {
40
+ const trimmed = timezone.trim();
41
+ if (trimmed && isValidTimezone(trimmed)) {
42
+ return trimmed;
43
+ }
44
+ return getSystemTimezone();
45
+ }
46
+ function formatTimezoneDisplay(timezone) {
47
+ const trimmed = timezone.trim();
48
+ if (!trimmed) {
49
+ return "local time";
50
+ }
51
+ if (isValidTimezone(trimmed)) {
52
+ return trimmed;
53
+ }
54
+ return `${trimmed} (invalid; using local time)`;
55
+ }
56
+ function getZonedDateTimeParts(date, timezone) {
57
+ const formatter = new Intl.DateTimeFormat("en-US", {
58
+ timeZone: timezone,
59
+ calendar: "iso8601",
60
+ numberingSystem: "latn",
61
+ hourCycle: "h23",
62
+ year: "numeric",
63
+ month: "2-digit",
64
+ day: "2-digit",
65
+ hour: "2-digit",
66
+ minute: "2-digit",
67
+ second: "2-digit"
68
+ });
69
+ const parts = new Map(formatter.formatToParts(date).map((part) => [part.type, part.value]));
70
+ return {
71
+ year: Number.parseInt(parts.get("year") ?? "0", 10),
72
+ month: Number.parseInt(parts.get("month") ?? "1", 10),
73
+ day: Number.parseInt(parts.get("day") ?? "1", 10),
74
+ hour: Number.parseInt(parts.get("hour") ?? "0", 10),
75
+ minute: Number.parseInt(parts.get("minute") ?? "0", 10),
76
+ second: Number.parseInt(parts.get("second") ?? "0", 10)
77
+ };
78
+ }
79
+ function formatTimezoneQualifiedIso(date, timezone) {
80
+ const effectiveTimezone = getEffectiveTimezone(timezone);
81
+ const parts = effectiveTimezone ? getZonedDateTimeParts(date, effectiveTimezone) : getLocalDateTimeParts(date);
82
+ const millis = date.getMilliseconds();
83
+ const zonedAsUtcMs = Date.UTC(parts.year, parts.month - 1, parts.day, parts.hour, parts.minute, parts.second, millis);
84
+ const offsetMinutes = Math.round((zonedAsUtcMs - date.getTime()) / 60000);
85
+ return `${pad(parts.year, 4)}-${pad(parts.month, 2)}-${pad(parts.day, 2)}T${pad(parts.hour, 2)}:${pad(parts.minute, 2)}:${pad(parts.second, 2)}.${pad(millis, 3)}${formatOffset(offsetMinutes)}[${effectiveTimezone ?? "local"}]`;
86
+ }
87
+ function formatRecurrence(recurrence) {
88
+ if (recurrence.type === "one-off") {
89
+ return "This is a one-off scheduled task.";
90
+ }
91
+ if (recurrence.fireNumber !== undefined) {
92
+ return `This is fire #${recurrence.fireNumber} (cron: ${recurrence.cron}).`;
93
+ }
94
+ return `This is a recurring scheduled task (cron: ${recurrence.cron}).`;
95
+ }
96
+ function formatScheduledTaskPrompt(input) {
97
+ const lines = [
98
+ `Scheduled task "${input.name}" is firing.`,
99
+ ...input.description ? [`Description: ${input.description}`] : [],
100
+ `Timezone: ${formatTimezoneDisplay(input.timezone)}`,
101
+ `Scheduled for: ${formatTimezoneQualifiedIso(input.scheduledFor, input.timezone)}`,
102
+ `Current time: ${formatTimezoneQualifiedIso(input.currentTime, input.timezone)}`,
103
+ formatRecurrence(input.recurrence),
104
+ "",
105
+ AUTONOMOUS_NOTICE,
106
+ "",
107
+ `Prompt: ${input.prompt}`
108
+ ];
109
+ return lines.join(`
110
+ `);
111
+ }
112
+ function unwrapSystemReminder(text) {
113
+ const trimmed = text.trim();
114
+ if (trimmed.startsWith(SYSTEM_REMINDER_OPEN) && trimmed.endsWith(SYSTEM_REMINDER_CLOSE)) {
115
+ return trimmed.slice(SYSTEM_REMINDER_OPEN.length, -SYSTEM_REMINDER_CLOSE.length).trim();
116
+ }
117
+ return trimmed;
118
+ }
119
+ function getField(lines, prefix) {
120
+ const line = lines.find((candidate) => candidate.startsWith(prefix));
121
+ const value = line?.slice(prefix.length).trim();
122
+ return value || null;
123
+ }
124
+ function getPrompt(text, recurrenceLineIndex) {
125
+ const promptMarker = `
126
+ Prompt: `;
127
+ const promptIndex = text.indexOf(promptMarker);
128
+ if (promptIndex >= 0) {
129
+ return text.slice(promptIndex + promptMarker.length).trim() || null;
130
+ }
131
+ const trailingLines = text.split(`
132
+ `).slice(recurrenceLineIndex + 1);
133
+ while (trailingLines[0]?.trim() === "")
134
+ trailingLines.shift();
135
+ if (trailingLines[0]?.startsWith(AUTONOMOUS_NOTICE_PREFIX)) {
136
+ trailingLines.shift();
137
+ while (trailingLines[0]?.trim() === "")
138
+ trailingLines.shift();
139
+ }
140
+ return trailingLines.join(`
141
+ `).trim() || null;
142
+ }
143
+ function parseScheduledTaskPrompt(rawText) {
144
+ const text = unwrapSystemReminder(rawText).replace(/\r\n/g, `
145
+ `);
146
+ const lines = text.split(`
147
+ `);
148
+ const titleMatch = /^Scheduled task ["“](.+)["”] is firing\.$/.exec(lines[0]?.trim() ?? "");
149
+ if (!titleMatch?.[1])
150
+ return null;
151
+ const recurrenceLineIndex = lines.findIndex((line) => {
152
+ const trimmed = line.trim();
153
+ return trimmed === "This is a one-off scheduled task." || /^This is fire #\d+ \(cron: .+\)\.$/.test(trimmed) || /^This is a recurring scheduled task \(cron: .+\)\.$/.test(trimmed);
154
+ });
155
+ if (recurrenceLineIndex < 0)
156
+ return null;
157
+ const recurrenceLine = lines[recurrenceLineIndex]?.trim() ?? "";
158
+ const countedRecurringMatch = /^This is fire #(\d+) \(cron: (.+)\)\.$/.exec(recurrenceLine);
159
+ const recurringMatch = /^This is a recurring scheduled task \(cron: (.+)\)\.$/.exec(recurrenceLine);
160
+ let recurrence;
161
+ if (countedRecurringMatch) {
162
+ recurrence = {
163
+ type: "recurring",
164
+ fireNumber: Number.parseInt(countedRecurringMatch[1] ?? "0", 10),
165
+ cron: countedRecurringMatch[2] ?? ""
166
+ };
167
+ } else if (recurringMatch) {
168
+ recurrence = { type: "recurring", cron: recurringMatch[1] ?? "" };
169
+ } else {
170
+ recurrence = { type: "one-off" };
171
+ }
172
+ const prompt = getPrompt(text, recurrenceLineIndex);
173
+ if (!prompt)
174
+ return null;
175
+ return {
176
+ name: titleMatch[1],
177
+ description: getField(lines, "Description:"),
178
+ timezone: getField(lines, "Timezone:"),
179
+ scheduledFor: getField(lines, "Scheduled for:"),
180
+ recurrence,
181
+ prompt
182
+ };
183
+ }
184
+ export {
185
+ parseScheduledTaskPrompt,
186
+ formatScheduledTaskPrompt
187
+ };
188
+
189
+ //# debugId=07276DD08883835A64756E2164756E21
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/cron/scheduled-task-prompt.ts"],
4
+ "sourcesContent": [
5
+ "export type ScheduledTaskRecurrence =\n | { type: \"one-off\" }\n | { type: \"recurring\"; cron: string; fireNumber?: number };\n\nexport interface ScheduledTaskPromptInput {\n name: string;\n description?: string | null;\n timezone: string;\n scheduledFor: Date;\n currentTime: Date;\n recurrence: ScheduledTaskRecurrence;\n prompt: string;\n}\n\nexport interface ScheduledTaskPromptInfo {\n name: string;\n description: string | null;\n timezone: string | null;\n scheduledFor: string | null;\n recurrence: ScheduledTaskRecurrence;\n prompt: string;\n}\n\ninterface ZonedDateTimeParts {\n year: number;\n month: number;\n day: number;\n hour: number;\n minute: number;\n second: number;\n}\n\nconst SYSTEM_REMINDER_OPEN = \"<system-reminder>\";\nconst SYSTEM_REMINDER_CLOSE = \"</system-reminder>\";\nconst AUTONOMOUS_NOTICE_PREFIX = \"You are running autonomously:\";\nconst AUTONOMOUS_NOTICE =\n \"You are running autonomously: no user is watching this turn and questions will not be answered. Deliver results through your available channels or record them in memory, and work until the task is done or genuinely blocked.\";\n\nfunction pad(value: number, width: number): string {\n return String(value).padStart(width, \"0\");\n}\n\nfunction formatOffset(minutes: number): string {\n const sign = minutes >= 0 ? \"+\" : \"-\";\n const abs = Math.abs(minutes);\n return `${sign}${pad(Math.floor(abs / 60), 2)}:${pad(abs % 60, 2)}`;\n}\n\nfunction getLocalDateTimeParts(date: Date): ZonedDateTimeParts {\n return {\n year: date.getFullYear(),\n month: date.getMonth() + 1,\n day: date.getDate(),\n hour: date.getHours(),\n minute: date.getMinutes(),\n second: date.getSeconds(),\n };\n}\n\nfunction isValidTimezone(timezone: string): boolean {\n try {\n new Intl.DateTimeFormat(\"en-US\", { timeZone: timezone });\n return true;\n } catch {\n return false;\n }\n}\n\nfunction getSystemTimezone(): string | null {\n const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;\n if (!timezone || !isValidTimezone(timezone)) {\n return null;\n }\n return timezone;\n}\n\nfunction getEffectiveTimezone(timezone: string): string | null {\n const trimmed = timezone.trim();\n if (trimmed && isValidTimezone(trimmed)) {\n return trimmed;\n }\n return getSystemTimezone();\n}\n\nfunction formatTimezoneDisplay(timezone: string): string {\n const trimmed = timezone.trim();\n if (!trimmed) {\n return \"local time\";\n }\n if (isValidTimezone(trimmed)) {\n return trimmed;\n }\n return `${trimmed} (invalid; using local time)`;\n}\n\nfunction getZonedDateTimeParts(\n date: Date,\n timezone: string,\n): ZonedDateTimeParts {\n const formatter = new Intl.DateTimeFormat(\"en-US\", {\n timeZone: timezone,\n calendar: \"iso8601\",\n numberingSystem: \"latn\",\n hourCycle: \"h23\",\n year: \"numeric\",\n month: \"2-digit\",\n day: \"2-digit\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n });\n const parts = new Map(\n formatter.formatToParts(date).map((part) => [part.type, part.value]),\n );\n\n return {\n year: Number.parseInt(parts.get(\"year\") ?? \"0\", 10),\n month: Number.parseInt(parts.get(\"month\") ?? \"1\", 10),\n day: Number.parseInt(parts.get(\"day\") ?? \"1\", 10),\n hour: Number.parseInt(parts.get(\"hour\") ?? \"0\", 10),\n minute: Number.parseInt(parts.get(\"minute\") ?? \"0\", 10),\n second: Number.parseInt(parts.get(\"second\") ?? \"0\", 10),\n };\n}\n\nexport function formatTimezoneQualifiedIso(\n date: Date,\n timezone: string,\n): string {\n const effectiveTimezone = getEffectiveTimezone(timezone);\n const parts = effectiveTimezone\n ? getZonedDateTimeParts(date, effectiveTimezone)\n : getLocalDateTimeParts(date);\n const millis = date.getMilliseconds();\n const zonedAsUtcMs = Date.UTC(\n parts.year,\n parts.month - 1,\n parts.day,\n parts.hour,\n parts.minute,\n parts.second,\n millis,\n );\n const offsetMinutes = Math.round((zonedAsUtcMs - date.getTime()) / 60_000);\n\n return `${pad(parts.year, 4)}-${pad(parts.month, 2)}-${pad(parts.day, 2)}T${pad(parts.hour, 2)}:${pad(parts.minute, 2)}:${pad(parts.second, 2)}.${pad(millis, 3)}${formatOffset(offsetMinutes)}[${effectiveTimezone ?? \"local\"}]`;\n}\n\nfunction formatRecurrence(recurrence: ScheduledTaskRecurrence): string {\n if (recurrence.type === \"one-off\") {\n return \"This is a one-off scheduled task.\";\n }\n if (recurrence.fireNumber !== undefined) {\n return `This is fire #${recurrence.fireNumber} (cron: ${recurrence.cron}).`;\n }\n return `This is a recurring scheduled task (cron: ${recurrence.cron}).`;\n}\n\n/**\n * Build the canonical prompt envelope for a scheduled agent turn.\n *\n * Every schedule runner should call this immediately before dispatch while\n * keeping its stored authored prompt separate from runtime metadata.\n */\nexport function formatScheduledTaskPrompt(\n input: ScheduledTaskPromptInput,\n): string {\n const lines = [\n `Scheduled task \"${input.name}\" is firing.`,\n ...(input.description ? [`Description: ${input.description}`] : []),\n `Timezone: ${formatTimezoneDisplay(input.timezone)}`,\n `Scheduled for: ${formatTimezoneQualifiedIso(input.scheduledFor, input.timezone)}`,\n `Current time: ${formatTimezoneQualifiedIso(input.currentTime, input.timezone)}`,\n formatRecurrence(input.recurrence),\n \"\",\n AUTONOMOUS_NOTICE,\n \"\",\n `Prompt: ${input.prompt}`,\n ];\n return lines.join(\"\\n\");\n}\n\nfunction unwrapSystemReminder(text: string): string {\n const trimmed = text.trim();\n if (\n trimmed.startsWith(SYSTEM_REMINDER_OPEN) &&\n trimmed.endsWith(SYSTEM_REMINDER_CLOSE)\n ) {\n return trimmed\n .slice(SYSTEM_REMINDER_OPEN.length, -SYSTEM_REMINDER_CLOSE.length)\n .trim();\n }\n return trimmed;\n}\n\nfunction getField(lines: string[], prefix: string): string | null {\n const line = lines.find((candidate) => candidate.startsWith(prefix));\n const value = line?.slice(prefix.length).trim();\n return value || null;\n}\n\nfunction getPrompt(text: string, recurrenceLineIndex: number): string | null {\n const promptMarker = \"\\nPrompt: \";\n const promptIndex = text.indexOf(promptMarker);\n if (promptIndex >= 0) {\n return text.slice(promptIndex + promptMarker.length).trim() || null;\n }\n\n const trailingLines = text.split(\"\\n\").slice(recurrenceLineIndex + 1);\n while (trailingLines[0]?.trim() === \"\") trailingLines.shift();\n if (trailingLines[0]?.startsWith(AUTONOMOUS_NOTICE_PREFIX)) {\n trailingLines.shift();\n while (trailingLines[0]?.trim() === \"\") trailingLines.shift();\n }\n return trailingLines.join(\"\\n\").trim() || null;\n}\n\n/** Parse canonical and legacy scheduled-task envelopes from persisted messages. */\nexport function parseScheduledTaskPrompt(\n rawText: string,\n): ScheduledTaskPromptInfo | null {\n const text = unwrapSystemReminder(rawText).replace(/\\r\\n/g, \"\\n\");\n const lines = text.split(\"\\n\");\n const titleMatch = /^Scheduled task [\"“](.+)[\"”] is firing\\.$/.exec(\n lines[0]?.trim() ?? \"\",\n );\n if (!titleMatch?.[1]) return null;\n\n const recurrenceLineIndex = lines.findIndex((line) => {\n const trimmed = line.trim();\n return (\n trimmed === \"This is a one-off scheduled task.\" ||\n /^This is fire #\\d+ \\(cron: .+\\)\\.$/.test(trimmed) ||\n /^This is a recurring scheduled task \\(cron: .+\\)\\.$/.test(trimmed)\n );\n });\n if (recurrenceLineIndex < 0) return null;\n\n const recurrenceLine = lines[recurrenceLineIndex]?.trim() ?? \"\";\n const countedRecurringMatch = /^This is fire #(\\d+) \\(cron: (.+)\\)\\.$/.exec(\n recurrenceLine,\n );\n const recurringMatch =\n /^This is a recurring scheduled task \\(cron: (.+)\\)\\.$/.exec(\n recurrenceLine,\n );\n let recurrence: ScheduledTaskRecurrence;\n if (countedRecurringMatch) {\n recurrence = {\n type: \"recurring\",\n fireNumber: Number.parseInt(countedRecurringMatch[1] ?? \"0\", 10),\n cron: countedRecurringMatch[2] ?? \"\",\n };\n } else if (recurringMatch) {\n recurrence = { type: \"recurring\", cron: recurringMatch[1] ?? \"\" };\n } else {\n recurrence = { type: \"one-off\" };\n }\n\n const prompt = getPrompt(text, recurrenceLineIndex);\n if (!prompt) return null;\n\n return {\n name: titleMatch[1],\n description: getField(lines, \"Description:\"),\n timezone: getField(lines, \"Timezone:\"),\n scheduledFor: getField(lines, \"Scheduled for:\"),\n recurrence,\n prompt,\n };\n}\n"
6
+ ],
7
+ "mappings": "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",
8
+ "debugId": "07276DD08883835A64756E2164756E21",
9
+ "names": []
10
+ }
@@ -0,0 +1,35 @@
1
+ export type ScheduledTaskRecurrence = {
2
+ type: "one-off";
3
+ } | {
4
+ type: "recurring";
5
+ cron: string;
6
+ fireNumber?: number;
7
+ };
8
+ export interface ScheduledTaskPromptInput {
9
+ name: string;
10
+ description?: string | null;
11
+ timezone: string;
12
+ scheduledFor: Date;
13
+ currentTime: Date;
14
+ recurrence: ScheduledTaskRecurrence;
15
+ prompt: string;
16
+ }
17
+ export interface ScheduledTaskPromptInfo {
18
+ name: string;
19
+ description: string | null;
20
+ timezone: string | null;
21
+ scheduledFor: string | null;
22
+ recurrence: ScheduledTaskRecurrence;
23
+ prompt: string;
24
+ }
25
+ export declare function formatTimezoneQualifiedIso(date: Date, timezone: string): string;
26
+ /**
27
+ * Build the canonical prompt envelope for a scheduled agent turn.
28
+ *
29
+ * Every schedule runner should call this immediately before dispatch while
30
+ * keeping its stored authored prompt separate from runtime metadata.
31
+ */
32
+ export declare function formatScheduledTaskPrompt(input: ScheduledTaskPromptInput): string;
33
+ /** Parse canonical and legacy scheduled-task envelopes from persisted messages. */
34
+ export declare function parseScheduledTaskPrompt(rawText: string): ScheduledTaskPromptInfo | null;
35
+ //# sourceMappingURL=scheduled-task-prompt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduled-task-prompt.d.ts","sourceRoot":"","sources":["../../../src/cron/scheduled-task-prompt.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,uBAAuB,GAC/B;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,GACnB;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAE7D,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,IAAI,CAAC;IACnB,WAAW,EAAE,IAAI,CAAC;IAClB,UAAU,EAAE,uBAAuB,CAAC;IACpC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,EAAE,uBAAuB,CAAC;IACpC,MAAM,EAAE,MAAM,CAAC;CAChB;AAwGD,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,MAAM,GACf,MAAM,CAkBR;AAYD;;;;;GAKG;AACH,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,wBAAwB,GAC9B,MAAM,CAcR;AAqCD,mFAAmF;AACnF,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,MAAM,GACd,uBAAuB,GAAG,IAAI,CAkDhC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Package export: `@letta-ai/letta-code/schedules`
3
+ *
4
+ * Pure scheduled-turn envelope contract shared by every scheduler producer and
5
+ * transcript consumer. This entry must remain free of Node and backend imports.
6
+ */
7
+ export { formatScheduledTaskPrompt, parseScheduledTaskPrompt, type ScheduledTaskPromptInfo, type ScheduledTaskPromptInput, type ScheduledTaskRecurrence, } from "./cron/scheduled-task-prompt";
8
+ //# sourceMappingURL=schedules.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schedules.d.ts","sourceRoot":"","sources":["../../src/schedules.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EACL,yBAAyB,EACzB,wBAAwB,EACxB,KAAK,uBAAuB,EAC5B,KAAK,wBAAwB,EAC7B,KAAK,uBAAuB,GAC7B,MAAM,8BAA8B,CAAC"}