@mastra/code-sdk 1.9.0-alpha.9 → 1.10.0-alpha.0

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.
Files changed (97) hide show
  1. package/README.md +23 -0
  2. package/dist/agent-connections/tools.d.ts.map +1 -1
  3. package/dist/agent-connections/tools.js +5 -5
  4. package/dist/agent-connections/tools.js.map +1 -1
  5. package/dist/agents/tools.d.ts +1 -1
  6. package/dist/agents/tools.d.ts.map +1 -1
  7. package/dist/agents/tools.js +2 -1
  8. package/dist/agents/tools.js.map +1 -1
  9. package/dist/analytics.d.ts.map +1 -1
  10. package/dist/analytics.js +2 -3
  11. package/dist/analytics.js.map +1 -1
  12. package/dist/auth/account-rotation-processor.d.ts.map +1 -1
  13. package/dist/auth/account-rotation-processor.js +17 -10
  14. package/dist/auth/account-rotation-processor.js.map +1 -1
  15. package/dist/auth/providers/kimi-coding.d.ts.map +1 -1
  16. package/dist/auth/providers/kimi-coding.js +1 -2
  17. package/dist/auth/providers/kimi-coding.js.map +1 -1
  18. package/dist/auth/providers/openai-codex.d.ts +1 -1
  19. package/dist/auth/providers/openai-codex.d.ts.map +1 -1
  20. package/dist/auth/providers/openai-codex.js +7 -19
  21. package/dist/auth/providers/openai-codex.js.map +1 -1
  22. package/dist/auth/storage.js +3 -3
  23. package/dist/auth/storage.js.map +1 -1
  24. package/dist/experimental-agent.d.ts +11 -0
  25. package/dist/experimental-agent.d.ts.map +1 -0
  26. package/dist/experimental-agent.js +36 -0
  27. package/dist/experimental-agent.js.map +1 -0
  28. package/dist/goal-manager.d.ts +39 -3
  29. package/dist/goal-manager.d.ts.map +1 -1
  30. package/dist/goal-manager.js +113 -31
  31. package/dist/goal-manager.js.map +1 -1
  32. package/dist/index.d.ts +12 -0
  33. package/dist/index.d.ts.map +1 -1
  34. package/dist/index.js +95 -12
  35. package/dist/index.js.map +1 -1
  36. package/dist/knowledge-inspector.d.ts.map +1 -1
  37. package/dist/knowledge-inspector.js +1 -2
  38. package/dist/knowledge-inspector.js.map +1 -1
  39. package/dist/onboarding/settings.d.ts +11 -0
  40. package/dist/onboarding/settings.d.ts.map +1 -1
  41. package/dist/onboarding/settings.js +39 -5
  42. package/dist/onboarding/settings.js.map +1 -1
  43. package/dist/permissions.d.ts.map +1 -1
  44. package/dist/permissions.js +6 -1
  45. package/dist/permissions.js.map +1 -1
  46. package/dist/plugins/loader.d.ts.map +1 -1
  47. package/dist/plugins/loader.js +1 -2
  48. package/dist/plugins/loader.js.map +1 -1
  49. package/dist/process-memory-diagnostics.d.ts.map +1 -1
  50. package/dist/process-memory-diagnostics.js +2 -3
  51. package/dist/process-memory-diagnostics.js.map +1 -1
  52. package/dist/schedules/index.d.ts +10 -0
  53. package/dist/schedules/index.d.ts.map +1 -0
  54. package/dist/schedules/index.js +6 -0
  55. package/dist/schedules/interval.d.ts +49 -0
  56. package/dist/schedules/interval.d.ts.map +1 -0
  57. package/dist/schedules/interval.js +215 -0
  58. package/dist/schedules/interval.js.map +1 -0
  59. package/dist/schedules/prompt.d.ts +36 -0
  60. package/dist/schedules/prompt.d.ts.map +1 -0
  61. package/dist/schedules/prompt.js +39 -0
  62. package/dist/schedules/prompt.js.map +1 -0
  63. package/dist/schedules/run-script.d.ts +8 -0
  64. package/dist/schedules/run-script.d.ts.map +1 -0
  65. package/dist/schedules/run-script.js +83 -0
  66. package/dist/schedules/run-script.js.map +1 -0
  67. package/dist/schedules/scheduler.d.ts +101 -0
  68. package/dist/schedules/scheduler.d.ts.map +1 -0
  69. package/dist/schedules/scheduler.js +169 -0
  70. package/dist/schedules/scheduler.js.map +1 -0
  71. package/dist/schedules/tools.d.ts +57 -0
  72. package/dist/schedules/tools.d.ts.map +1 -0
  73. package/dist/schedules/tools.js +220 -0
  74. package/dist/schedules/tools.js.map +1 -0
  75. package/dist/tools/workflows/ephemeral-memory.d.ts +21 -0
  76. package/dist/tools/workflows/ephemeral-memory.d.ts.map +1 -1
  77. package/dist/tools/workflows/ephemeral-memory.js +1 -2
  78. package/dist/tools/workflows/ephemeral-memory.js.map +1 -1
  79. package/dist/utils/discarding-scores-storage.d.ts +33 -0
  80. package/dist/utils/discarding-scores-storage.d.ts.map +1 -0
  81. package/dist/utils/discarding-scores-storage.js +54 -0
  82. package/dist/utils/discarding-scores-storage.js.map +1 -0
  83. package/dist/utils/maintenance-lock.d.ts +42 -0
  84. package/dist/utils/maintenance-lock.d.ts.map +1 -0
  85. package/dist/utils/maintenance-lock.js +199 -0
  86. package/dist/utils/maintenance-lock.js.map +1 -0
  87. package/dist/utils/prune-cli.d.ts +24 -0
  88. package/dist/utils/prune-cli.d.ts.map +1 -0
  89. package/dist/utils/prune-cli.js +125 -0
  90. package/dist/utils/prune-cli.js.map +1 -0
  91. package/dist/utils/signals-pubsub.d.ts.map +1 -1
  92. package/dist/utils/signals-pubsub.js +1 -2
  93. package/dist/utils/signals-pubsub.js.map +1 -1
  94. package/dist/utils/storage-maintenance.d.ts.map +1 -1
  95. package/dist/utils/storage-maintenance.js +33 -3
  96. package/dist/utils/storage-maintenance.js.map +1 -1
  97. package/package.json +21 -15
@@ -0,0 +1,220 @@
1
+ import { parseInterval, validateInterval } from "./interval.js";
2
+ import { describeScheduleSource, shortScheduleId } from "./scheduler.js";
3
+ import { resolveScriptCommand } from "./run-script.js";
4
+ import * as path$1 from "path";
5
+ import { createTool } from "@mastra/core/tools";
6
+ import { z } from "zod";
7
+ //#region src/schedules/tools.ts
8
+ /**
9
+ * Agent-facing tools for the process-local `/schedules` scheduler.
10
+ *
11
+ * Opt-in (experimental setting). Every tool is bound to the thread of the run
12
+ * that calls it — the model never picks a thread or resource — and can only
13
+ * see or manage schedules on that thread.
14
+ */
15
+ const SCHEDULE_TOOL_IDS = {
16
+ create: "schedule_create",
17
+ list: "schedule_list",
18
+ update: "schedule_update",
19
+ resume: "schedule_resume",
20
+ run: "schedule_run"
21
+ };
22
+ const resultSchema = z.object({
23
+ content: z.string(),
24
+ isError: z.boolean().optional()
25
+ });
26
+ const intervalSchema = z.string().min(1).transform((value, ctx) => {
27
+ const interval = parseInterval(value);
28
+ if ("error" in interval) {
29
+ ctx.addIssue({
30
+ code: "custom",
31
+ message: interval.error
32
+ });
33
+ return z.NEVER;
34
+ }
35
+ const check = validateInterval(interval);
36
+ if ("error" in check) {
37
+ const suggestion = check.suggestion ? ` Try ${check.suggestion}.` : "";
38
+ ctx.addIssue({
39
+ code: "custom",
40
+ message: `${check.error}${suggestion}`
41
+ });
42
+ return z.NEVER;
43
+ }
44
+ return interval;
45
+ }).describe("Cadence such as \"5m\", \"2h\", or \"1d\". Minute steps must divide 60, hour steps must divide 24.");
46
+ const triggerSchema = z.discriminatedUnion("kind", [z.object({
47
+ kind: z.literal("every"),
48
+ interval: intervalSchema
49
+ })]).describe("When the schedule fires. \"every\" repeats on wall-clock boundaries (5m fires at :00, :05, …).");
50
+ const idSchema = z.string().min(1).describe("Schedule id, or a unique prefix of it (the 8-character short id works).");
51
+ function threadOf(context) {
52
+ const agent = context?.agent;
53
+ return agent?.threadId && agent.resourceId ? {
54
+ threadId: agent.threadId,
55
+ resourceId: agent.resourceId
56
+ } : void 0;
57
+ }
58
+ const NO_THREAD = {
59
+ content: "Schedules require a memory-backed thread.",
60
+ isError: true
61
+ };
62
+ function resolveFile(token, mode, options) {
63
+ const expanded = token.startsWith("~/") && options.homeDir ? path$1.join(options.homeDir, token.slice(2)) : token;
64
+ const absPath = path$1.resolve(options.cwd, expanded);
65
+ return options.fileExists(absPath) ? {
66
+ path: absPath,
67
+ displayPath: token,
68
+ mode
69
+ } : void 0;
70
+ }
71
+ function formatSchedule(schedule) {
72
+ const timing = schedule.status === "paused" ? "paused" : `next at ${new Date(schedule.nextFireAt).toLocaleTimeString()}`;
73
+ return `${shortScheduleId(schedule.id)} every ${schedule.trigger.interval.label} ${timing} ${describeScheduleSource(schedule)} (created by ${schedule.createdBy})`;
74
+ }
75
+ function errorMessage(error) {
76
+ return error instanceof Error ? error.message : String(error);
77
+ }
78
+ function findOne(scheduler, threadId, id) {
79
+ const needle = id.toLowerCase();
80
+ const matches = scheduler.list({ threadId }).filter((schedule) => schedule.id.toLowerCase().startsWith(needle));
81
+ if (matches.length === 1) return { schedule: matches[0] };
82
+ return {
83
+ content: matches.length === 0 ? `No schedule "${id}" on this thread.` : `"${id}" matches several schedules.`,
84
+ isError: true
85
+ };
86
+ }
87
+ function createScheduleTools({ scheduler, fileOptions }) {
88
+ const scheduleCreateTool = createTool({
89
+ id: SCHEDULE_TOOL_IDS.create,
90
+ description: `Schedule a recurring prompt on this thread. Each fire arrives as a new user turn labelled "schedule".
91
+
92
+ Pass exactly one source: "prompt" (text sent each fire), "promptFile" (a file re-read and sent as the prompt each fire), or "script" (run each fire; its output is sent, followed by "extraPrompt" if given). Schedules live only until Mastra Code exits.`,
93
+ inputSchema: z.object({
94
+ trigger: triggerSchema,
95
+ prompt: z.string().trim().min(1).optional().describe("Prompt text to send on every fire."),
96
+ promptFile: z.string().trim().min(1).optional().describe("Path to a file to re-read and send on every fire."),
97
+ script: z.string().trim().min(1).optional().describe("Path to a script to run on every fire."),
98
+ extraPrompt: z.string().trim().min(1).optional().describe("Text sent after the script output.")
99
+ }).refine((input) => [
100
+ input.prompt,
101
+ input.promptFile,
102
+ input.script
103
+ ].filter(Boolean).length === 1, { message: "Provide exactly one of \"prompt\", \"promptFile\", or \"script\"." }).refine((input) => !input.extraPrompt || input.script, { message: "\"extraPrompt\" only applies with \"script\"." }),
104
+ outputSchema: resultSchema,
105
+ execute: async (input, context) => {
106
+ const target = threadOf(context);
107
+ if (!target) return NO_THREAD;
108
+ let schedule;
109
+ if (input.prompt) schedule = scheduler.create({
110
+ trigger: input.trigger,
111
+ prompt: input.prompt,
112
+ createdBy: "agent"
113
+ }, target);
114
+ else {
115
+ const token = input.script ?? input.promptFile;
116
+ const file = resolveFile(token, input.script ? "script" : "prompt", fileOptions());
117
+ if (!file) return {
118
+ content: `File not found: ${token}`,
119
+ isError: true
120
+ };
121
+ if (file.mode === "script") try {
122
+ resolveScriptCommand(file.path);
123
+ } catch (error) {
124
+ return {
125
+ content: `Can't run ${token}: ${error instanceof Error ? error.message : String(error)}`,
126
+ isError: true
127
+ };
128
+ }
129
+ schedule = scheduler.create({
130
+ trigger: input.trigger,
131
+ file,
132
+ ...input.extraPrompt ? { extraPrompt: input.extraPrompt } : {},
133
+ createdBy: "agent"
134
+ }, target);
135
+ }
136
+ return { content: `Created schedule ${formatSchedule(schedule)}` };
137
+ }
138
+ });
139
+ const scheduleListTool = createTool({
140
+ id: SCHEDULE_TOOL_IDS.list,
141
+ description: "List the recurring prompt schedules on this thread, including ones the user created with /schedules.",
142
+ inputSchema: z.object({}),
143
+ outputSchema: resultSchema,
144
+ execute: async (_input, context) => {
145
+ const target = threadOf(context);
146
+ if (!target) return NO_THREAD;
147
+ const schedules = scheduler.list({ threadId: target.threadId });
148
+ if (schedules.length === 0) return { content: "No schedules on this thread." };
149
+ return { content: [`Schedules on this thread (${schedules.length}):`, ...schedules.map(formatSchedule)].join("\n") };
150
+ }
151
+ });
152
+ const scheduleUpdateTool = createTool({
153
+ id: SCHEDULE_TOOL_IDS.update,
154
+ description: "Pause or delete a schedule on this thread. Use schedule_resume to resume a paused one.",
155
+ inputSchema: z.object({
156
+ id: idSchema,
157
+ action: z.enum(["pause", "delete"])
158
+ }),
159
+ outputSchema: resultSchema,
160
+ execute: async ({ id, action }, context) => {
161
+ const target = threadOf(context);
162
+ if (!target) return NO_THREAD;
163
+ const found = findOne(scheduler, target.threadId, id);
164
+ if (!("schedule" in found)) return found;
165
+ scheduler[action](found.schedule.id);
166
+ return { content: `${action === "pause" ? "Paused" : "Deleted"} schedule ${shortScheduleId(found.schedule.id)}.` };
167
+ }
168
+ });
169
+ const scheduleResumeTool = createTool({
170
+ id: SCHEDULE_TOOL_IDS.resume,
171
+ description: "Resume a paused schedule on this thread. It fires again from the next clock boundary.",
172
+ inputSchema: z.object({ id: idSchema }),
173
+ outputSchema: resultSchema,
174
+ execute: async ({ id }, context) => {
175
+ const target = threadOf(context);
176
+ if (!target) return NO_THREAD;
177
+ const found = findOne(scheduler, target.threadId, id);
178
+ if (!("schedule" in found)) return found;
179
+ scheduler.resume(found.schedule.id);
180
+ return { content: `Resumed schedule ${shortScheduleId(found.schedule.id)}.` };
181
+ }
182
+ });
183
+ const scheduleRunTool = createTool({
184
+ id: SCHEDULE_TOOL_IDS.run,
185
+ description: "Fire a schedule on this thread once now, even if it is paused, without changing its cadence. Its prompt arrives as the next user turn.",
186
+ inputSchema: z.object({ id: idSchema }),
187
+ outputSchema: resultSchema,
188
+ execute: async ({ id }, context) => {
189
+ const target = threadOf(context);
190
+ if (!target) return NO_THREAD;
191
+ const found = findOne(scheduler, target.threadId, id);
192
+ if (!("schedule" in found)) return found;
193
+ const short = shortScheduleId(found.schedule.id);
194
+ const result = await scheduler.run(found.schedule.id);
195
+ switch (result.status) {
196
+ case "fired": return { content: `Triggered schedule ${short}; its prompt arrives as the next turn.` };
197
+ case "busy": return { content: `Schedule ${short} is already firing; skipped so its prompt isn't sent twice.` };
198
+ case "not-found": return {
199
+ content: `Schedule ${short} was deleted before it fired.`,
200
+ isError: true
201
+ };
202
+ case "failed": return {
203
+ content: `Schedule ${short} failed to fire: ${errorMessage(result.error)}`,
204
+ isError: true
205
+ };
206
+ }
207
+ }
208
+ });
209
+ return {
210
+ [SCHEDULE_TOOL_IDS.create]: scheduleCreateTool,
211
+ [SCHEDULE_TOOL_IDS.list]: scheduleListTool,
212
+ [SCHEDULE_TOOL_IDS.update]: scheduleUpdateTool,
213
+ [SCHEDULE_TOOL_IDS.resume]: scheduleResumeTool,
214
+ [SCHEDULE_TOOL_IDS.run]: scheduleRunTool
215
+ };
216
+ }
217
+ //#endregion
218
+ export { SCHEDULE_TOOL_IDS, createScheduleTools };
219
+
220
+ //# sourceMappingURL=tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.js","names":["path"],"sources":["../../src/schedules/tools.ts"],"sourcesContent":["/**\n * Agent-facing tools for the process-local `/schedules` scheduler.\n *\n * Opt-in (experimental setting). Every tool is bound to the thread of the run\n * that calls it — the model never picks a thread or resource — and can only\n * see or manage schedules on that thread.\n */\nimport * as path from 'node:path';\nimport { createTool } from '@mastra/core/tools';\nimport { z } from 'zod';\n\nimport { parseInterval, validateInterval } from './interval.js';\nimport { resolveScriptCommand } from './run-script.js';\nimport { describeScheduleSource, shortScheduleId } from './scheduler.js';\nimport type { ScheduleFile, ThreadSchedule, ThreadScheduler } from './scheduler.js';\n\nexport const SCHEDULE_TOOL_IDS = {\n create: 'schedule_create',\n list: 'schedule_list',\n update: 'schedule_update',\n resume: 'schedule_resume',\n run: 'schedule_run',\n} as const;\n\nexport type ScheduleFileOptions = {\n /** Directory relative paths resolve against (the project root). */\n cwd: string;\n homeDir?: string;\n fileExists: (absPath: string) => boolean;\n};\n\nexport type ScheduleToolsOptions = {\n scheduler: ThreadScheduler;\n fileOptions: () => ScheduleFileOptions;\n};\n\ntype ToolRunContext = { agent?: { threadId?: string; resourceId?: string } };\n\nconst resultSchema = z.object({\n content: z.string(),\n isError: z.boolean().optional(),\n});\ntype ScheduleToolResult = z.infer<typeof resultSchema>;\n\nconst intervalSchema = z\n .string()\n .min(1)\n .transform((value, ctx) => {\n const interval = parseInterval(value);\n if ('error' in interval) {\n ctx.addIssue({ code: 'custom', message: interval.error });\n return z.NEVER;\n }\n const check = validateInterval(interval);\n if ('error' in check) {\n const suggestion = check.suggestion ? ` Try ${check.suggestion}.` : '';\n ctx.addIssue({ code: 'custom', message: `${check.error}${suggestion}` });\n return z.NEVER;\n }\n return interval;\n })\n .describe('Cadence such as \"5m\", \"2h\", or \"1d\". Minute steps must divide 60, hour steps must divide 24.');\n\nconst triggerSchema = z\n .discriminatedUnion('kind', [\n z.object({\n kind: z.literal('every'),\n interval: intervalSchema,\n }),\n ])\n .describe('When the schedule fires. \"every\" repeats on wall-clock boundaries (5m fires at :00, :05, …).');\n\nconst idSchema = z.string().min(1).describe('Schedule id, or a unique prefix of it (the 8-character short id works).');\n\nfunction threadOf(context: unknown): { threadId: string; resourceId: string } | undefined {\n const agent = (context as ToolRunContext | undefined)?.agent;\n return agent?.threadId && agent.resourceId ? { threadId: agent.threadId, resourceId: agent.resourceId } : undefined;\n}\n\nconst NO_THREAD: ScheduleToolResult = { content: 'Schedules require a memory-backed thread.', isError: true };\n\nfunction resolveFile(\n token: string,\n mode: ScheduleFile['mode'],\n options: ScheduleFileOptions,\n): ScheduleFile | undefined {\n const expanded = token.startsWith('~/') && options.homeDir ? path.join(options.homeDir, token.slice(2)) : token;\n const absPath = path.resolve(options.cwd, expanded);\n return options.fileExists(absPath) ? { path: absPath, displayPath: token, mode } : undefined;\n}\n\nfunction formatSchedule(schedule: ThreadSchedule): string {\n const timing =\n schedule.status === 'paused' ? 'paused' : `next at ${new Date(schedule.nextFireAt).toLocaleTimeString()}`;\n return `${shortScheduleId(schedule.id)} every ${schedule.trigger.interval.label} ${timing} ${describeScheduleSource(schedule)} (created by ${schedule.createdBy})`;\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nfunction findOne(\n scheduler: ThreadScheduler,\n threadId: string,\n id: string,\n): { schedule: ThreadSchedule } | ScheduleToolResult {\n const needle = id.toLowerCase();\n const matches = scheduler.list({ threadId }).filter(schedule => schedule.id.toLowerCase().startsWith(needle));\n if (matches.length === 1) return { schedule: matches[0]! };\n return {\n content: matches.length === 0 ? `No schedule \"${id}\" on this thread.` : `\"${id}\" matches several schedules.`,\n isError: true,\n };\n}\n\nexport function createScheduleTools({ scheduler, fileOptions }: ScheduleToolsOptions) {\n const scheduleCreateTool = createTool({\n id: SCHEDULE_TOOL_IDS.create,\n description: `Schedule a recurring prompt on this thread. Each fire arrives as a new user turn labelled \"schedule\".\n\nPass exactly one source: \"prompt\" (text sent each fire), \"promptFile\" (a file re-read and sent as the prompt each fire), or \"script\" (run each fire; its output is sent, followed by \"extraPrompt\" if given). Schedules live only until Mastra Code exits.`,\n inputSchema: z\n .object({\n trigger: triggerSchema,\n prompt: z.string().trim().min(1).optional().describe('Prompt text to send on every fire.'),\n promptFile: z.string().trim().min(1).optional().describe('Path to a file to re-read and send on every fire.'),\n script: z.string().trim().min(1).optional().describe('Path to a script to run on every fire.'),\n extraPrompt: z.string().trim().min(1).optional().describe('Text sent after the script output.'),\n })\n .refine(input => [input.prompt, input.promptFile, input.script].filter(Boolean).length === 1, {\n message: 'Provide exactly one of \"prompt\", \"promptFile\", or \"script\".',\n })\n .refine(input => !input.extraPrompt || input.script, {\n message: '\"extraPrompt\" only applies with \"script\".',\n }),\n outputSchema: resultSchema,\n execute: async (input, context): Promise<ScheduleToolResult> => {\n const target = threadOf(context);\n if (!target) return NO_THREAD;\n let schedule: ThreadSchedule;\n if (input.prompt) {\n schedule = scheduler.create({ trigger: input.trigger, prompt: input.prompt, createdBy: 'agent' }, target);\n } else {\n const token = (input.script ?? input.promptFile)!;\n const file = resolveFile(token, input.script ? 'script' : 'prompt', fileOptions());\n if (!file) return { content: `File not found: ${token}`, isError: true };\n if (file.mode === 'script') {\n try {\n resolveScriptCommand(file.path);\n } catch (error) {\n return {\n content: `Can't run ${token}: ${error instanceof Error ? error.message : String(error)}`,\n isError: true,\n };\n }\n }\n schedule = scheduler.create(\n {\n trigger: input.trigger,\n file,\n ...(input.extraPrompt ? { extraPrompt: input.extraPrompt } : {}),\n createdBy: 'agent',\n },\n target,\n );\n }\n return { content: `Created schedule ${formatSchedule(schedule)}` };\n },\n });\n\n const scheduleListTool = createTool({\n id: SCHEDULE_TOOL_IDS.list,\n description: 'List the recurring prompt schedules on this thread, including ones the user created with /schedules.',\n inputSchema: z.object({}),\n outputSchema: resultSchema,\n execute: async (_input, context): Promise<ScheduleToolResult> => {\n const target = threadOf(context);\n if (!target) return NO_THREAD;\n const schedules = scheduler.list({ threadId: target.threadId });\n if (schedules.length === 0) return { content: 'No schedules on this thread.' };\n return {\n content: [`Schedules on this thread (${schedules.length}):`, ...schedules.map(formatSchedule)].join('\\n'),\n };\n },\n });\n\n const scheduleUpdateTool = createTool({\n id: SCHEDULE_TOOL_IDS.update,\n description: 'Pause or delete a schedule on this thread. Use schedule_resume to resume a paused one.',\n inputSchema: z.object({\n id: idSchema,\n action: z.enum(['pause', 'delete']),\n }),\n outputSchema: resultSchema,\n execute: async ({ id, action }, context): Promise<ScheduleToolResult> => {\n const target = threadOf(context);\n if (!target) return NO_THREAD;\n const found = findOne(scheduler, target.threadId, id);\n if (!('schedule' in found)) return found;\n scheduler[action](found.schedule.id);\n const verb = action === 'pause' ? 'Paused' : 'Deleted';\n return { content: `${verb} schedule ${shortScheduleId(found.schedule.id)}.` };\n },\n });\n\n // Separate from schedule_update: resuming lets the timer run the schedule's\n // script again, so it needs the same approval as creating or running one.\n const scheduleResumeTool = createTool({\n id: SCHEDULE_TOOL_IDS.resume,\n description: 'Resume a paused schedule on this thread. It fires again from the next clock boundary.',\n inputSchema: z.object({ id: idSchema }),\n outputSchema: resultSchema,\n execute: async ({ id }, context): Promise<ScheduleToolResult> => {\n const target = threadOf(context);\n if (!target) return NO_THREAD;\n const found = findOne(scheduler, target.threadId, id);\n if (!('schedule' in found)) return found;\n scheduler.resume(found.schedule.id);\n return { content: `Resumed schedule ${shortScheduleId(found.schedule.id)}.` };\n },\n });\n\n const scheduleRunTool = createTool({\n id: SCHEDULE_TOOL_IDS.run,\n description:\n 'Fire a schedule on this thread once now, even if it is paused, without changing its cadence. Its prompt arrives as the next user turn.',\n inputSchema: z.object({ id: idSchema }),\n outputSchema: resultSchema,\n execute: async ({ id }, context): Promise<ScheduleToolResult> => {\n const target = threadOf(context);\n if (!target) return NO_THREAD;\n const found = findOne(scheduler, target.threadId, id);\n if (!('schedule' in found)) return found;\n const short = shortScheduleId(found.schedule.id);\n const result = await scheduler.run(found.schedule.id);\n switch (result.status) {\n case 'fired':\n return { content: `Triggered schedule ${short}; its prompt arrives as the next turn.` };\n case 'busy':\n return { content: `Schedule ${short} is already firing; skipped so its prompt isn't sent twice.` };\n case 'not-found':\n return { content: `Schedule ${short} was deleted before it fired.`, isError: true };\n case 'failed':\n return { content: `Schedule ${short} failed to fire: ${errorMessage(result.error)}`, isError: true };\n }\n },\n });\n\n return {\n [SCHEDULE_TOOL_IDS.create]: scheduleCreateTool,\n [SCHEDULE_TOOL_IDS.list]: scheduleListTool,\n [SCHEDULE_TOOL_IDS.update]: scheduleUpdateTool,\n [SCHEDULE_TOOL_IDS.resume]: scheduleResumeTool,\n [SCHEDULE_TOOL_IDS.run]: scheduleRunTool,\n };\n}\n"],"mappings":"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"}
@@ -1,3 +1,24 @@
1
+ /**
2
+ * Sub-invocations launched from a parent chat turn (workflow agent steps,
3
+ * sub-agent tool calls) must run under a fresh isolated Mastra memory scope
4
+ * so they don't:
5
+ *
6
+ * - write their prompts/responses into the parent chat thread's history, or
7
+ * - contend with the parent turn's memory-dependent processors
8
+ * (observational-memory, task-state, working-memory-state).
9
+ *
10
+ * `withEphemeralMemory` copies the caller's request context into a child,
11
+ * replaces its MastraMemory with a fresh thread id and inherited resource id,
12
+ * then passes that isolated child to `fn`. The parent context is never mutated,
13
+ * so concurrent sub-invocations cannot overwrite or restore each other's
14
+ * memory values. Isolation writes the ephemeral ids instead of scrubbing them:
15
+ * inner agent invocations resolve their thread/resource via those reserved
16
+ * keys, and leaving them unset causes downstream storage saves to throw
17
+ * "Thread ID is required".
18
+ *
19
+ * Callers can override the ephemeral thread id (e.g. for tests) via
20
+ * `options.threadId`.
21
+ */
1
22
  import { RequestContext } from '@mastra/core/request-context';
2
23
  interface EphemeralMemoryOptions {
3
24
  threadId?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"ephemeral-memory.d.ts","sourceRoot":"","sources":["../../../src/tools/workflows/ephemeral-memory.ts"],"names":[],"mappings":"AAsBA,OAAO,EAAgD,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAE5G,UAAU,sBAAsB;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAsB,mBAAmB,CAAC,CAAC,EACzC,cAAc,EAAE,cAAc,GAAG,SAAS,EAC1C,EAAE,EAAE,CAAC,cAAc,EAAE,cAAc,GAAG,SAAS,KAAK,OAAO,CAAC,CAAC,CAAC,EAC9D,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,CAAC,CAAC,CA6BZ"}
1
+ {"version":3,"file":"ephemeral-memory.d.ts","sourceRoot":"","sources":["../../../src/tools/workflows/ephemeral-memory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,EAAgD,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAE5G,UAAU,sBAAsB;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAsB,mBAAmB,CAAC,CAAC,EACzC,cAAc,EAAE,cAAc,GAAG,SAAS,EAC1C,EAAE,EAAE,CAAC,cAAc,EAAE,cAAc,GAAG,SAAS,KAAK,OAAO,CAAC,CAAC,CAAC,EAC9D,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,CAAC,CAAC,CA6BZ"}
@@ -1,4 +1,3 @@
1
- import { randomUUID } from "crypto";
2
1
  import { MASTRA_RESOURCE_ID_KEY, MASTRA_THREAD_ID_KEY, RequestContext } from "@mastra/core/request-context";
3
2
  //#region src/tools/workflows/ephemeral-memory.ts
4
3
  /**
@@ -27,7 +26,7 @@ async function withEphemeralMemory(requestContext, fn, options = {}) {
27
26
  const childRequestContext = new RequestContext(requestContext.entries());
28
27
  const mastraMemory = requestContext.get("MastraMemory");
29
28
  const resourceId = requestContext.get(MASTRA_RESOURCE_ID_KEY);
30
- const ephemeralThreadId = options.threadId ?? randomUUID();
29
+ const ephemeralThreadId = options.threadId ?? globalThis.crypto.randomUUID();
31
30
  const parentResourceId = mastraMemory?.resourceId ?? resourceId ?? "";
32
31
  childRequestContext.set("MastraMemory", {
33
32
  thread: { id: ephemeralThreadId },
@@ -1 +1 @@
1
- {"version":3,"file":"ephemeral-memory.js","names":[],"sources":["../../../src/tools/workflows/ephemeral-memory.ts"],"sourcesContent":["/**\n * Sub-invocations launched from a parent chat turn (workflow agent steps,\n * sub-agent tool calls) must run under a fresh isolated Mastra memory scope\n * so they don't:\n *\n * - write their prompts/responses into the parent chat thread's history, or\n * - contend with the parent turn's memory-dependent processors\n * (observational-memory, task-state, working-memory-state).\n *\n * `withEphemeralMemory` copies the caller's request context into a child,\n * replaces its MastraMemory with a fresh thread id and inherited resource id,\n * then passes that isolated child to `fn`. The parent context is never mutated,\n * so concurrent sub-invocations cannot overwrite or restore each other's\n * memory values. Isolation writes the ephemeral ids instead of scrubbing them:\n * inner agent invocations resolve their thread/resource via those reserved\n * keys, and leaving them unset causes downstream storage saves to throw\n * \"Thread ID is required\".\n *\n * Callers can override the ephemeral thread id (e.g. for tests) via\n * `options.threadId`.\n */\nimport { randomUUID } from 'node:crypto';\nimport { MASTRA_RESOURCE_ID_KEY, MASTRA_THREAD_ID_KEY, RequestContext } from '@mastra/core/request-context';\n\ninterface EphemeralMemoryOptions {\n threadId?: string;\n}\n\nexport async function withEphemeralMemory<T>(\n requestContext: RequestContext | undefined,\n fn: (requestContext: RequestContext | undefined) => Promise<T>,\n options: EphemeralMemoryOptions = {},\n): Promise<T> {\n if (!requestContext) return fn(undefined);\n\n const childRequestContext = new RequestContext(requestContext.entries());\n const mastraMemory = requestContext.get('MastraMemory') as\n | { thread?: { id?: string }; resourceId?: string; memoryConfig?: unknown }\n | undefined;\n const resourceId = requestContext.get(MASTRA_RESOURCE_ID_KEY) as string | undefined;\n const ephemeralThreadId = options.threadId ?? randomUUID();\n const parentResourceId = mastraMemory?.resourceId ?? resourceId ?? '';\n\n childRequestContext.set('MastraMemory', {\n thread: { id: ephemeralThreadId },\n resourceId: parentResourceId,\n memoryConfig: undefined,\n });\n // Stamp the reserved thread/resource-key context values with the same\n // ephemeral ids. Inner agent invocations (workflow agent steps, sub-agent\n // tool calls) read these keys to resolve their runtime thread; leaving\n // MASTRA_THREAD_ID_KEY unset causes prepare-memory-step to build a\n // MessageList without a threadId, which storage rejects downstream.\n childRequestContext.set(MASTRA_THREAD_ID_KEY, ephemeralThreadId);\n if (parentResourceId) {\n childRequestContext.set(MASTRA_RESOURCE_ID_KEY, parentResourceId);\n } else {\n childRequestContext.delete(MASTRA_RESOURCE_ID_KEY);\n }\n\n return fn(childRequestContext);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AA4BA,eAAsB,oBACpB,gBACA,IACA,UAAkC,CAAC,GACvB;CACZ,IAAI,CAAC,gBAAgB,OAAO,GAAG,KAAA,CAAS;CAExC,MAAM,sBAAsB,IAAI,eAAe,eAAe,QAAQ,CAAC;CACvE,MAAM,eAAe,eAAe,IAAI,cAAc;CAGtD,MAAM,aAAa,eAAe,IAAI,sBAAsB;CAC5D,MAAM,oBAAoB,QAAQ,YAAY,WAAW;CACzD,MAAM,mBAAmB,cAAc,cAAc,cAAc;CAEnE,oBAAoB,IAAI,gBAAgB;EACtC,QAAQ,EAAE,IAAI,kBAAkB;EAChC,YAAY;EACZ,cAAc,KAAA;CAChB,CAAC;CAMD,oBAAoB,IAAI,sBAAsB,iBAAiB;CAC/D,IAAI,kBACF,oBAAoB,IAAI,wBAAwB,gBAAgB;MAEhE,oBAAoB,OAAO,sBAAsB;CAGnD,OAAO,GAAG,mBAAmB;AAC/B"}
1
+ {"version":3,"file":"ephemeral-memory.js","names":[],"sources":["../../../src/tools/workflows/ephemeral-memory.ts"],"sourcesContent":["/**\n * Sub-invocations launched from a parent chat turn (workflow agent steps,\n * sub-agent tool calls) must run under a fresh isolated Mastra memory scope\n * so they don't:\n *\n * - write their prompts/responses into the parent chat thread's history, or\n * - contend with the parent turn's memory-dependent processors\n * (observational-memory, task-state, working-memory-state).\n *\n * `withEphemeralMemory` copies the caller's request context into a child,\n * replaces its MastraMemory with a fresh thread id and inherited resource id,\n * then passes that isolated child to `fn`. The parent context is never mutated,\n * so concurrent sub-invocations cannot overwrite or restore each other's\n * memory values. Isolation writes the ephemeral ids instead of scrubbing them:\n * inner agent invocations resolve their thread/resource via those reserved\n * keys, and leaving them unset causes downstream storage saves to throw\n * \"Thread ID is required\".\n *\n * Callers can override the ephemeral thread id (e.g. for tests) via\n * `options.threadId`.\n */\nimport { MASTRA_RESOURCE_ID_KEY, MASTRA_THREAD_ID_KEY, RequestContext } from '@mastra/core/request-context';\n\ninterface EphemeralMemoryOptions {\n threadId?: string;\n}\n\nexport async function withEphemeralMemory<T>(\n requestContext: RequestContext | undefined,\n fn: (requestContext: RequestContext | undefined) => Promise<T>,\n options: EphemeralMemoryOptions = {},\n): Promise<T> {\n if (!requestContext) return fn(undefined);\n\n const childRequestContext = new RequestContext(requestContext.entries());\n const mastraMemory = requestContext.get('MastraMemory') as\n | { thread?: { id?: string }; resourceId?: string; memoryConfig?: unknown }\n | undefined;\n const resourceId = requestContext.get(MASTRA_RESOURCE_ID_KEY) as string | undefined;\n const ephemeralThreadId = options.threadId ?? globalThis.crypto.randomUUID();\n const parentResourceId = mastraMemory?.resourceId ?? resourceId ?? '';\n\n childRequestContext.set('MastraMemory', {\n thread: { id: ephemeralThreadId },\n resourceId: parentResourceId,\n memoryConfig: undefined,\n });\n // Stamp the reserved thread/resource-key context values with the same\n // ephemeral ids. Inner agent invocations (workflow agent steps, sub-agent\n // tool calls) read these keys to resolve their runtime thread; leaving\n // MASTRA_THREAD_ID_KEY unset causes prepare-memory-step to build a\n // MessageList without a threadId, which storage rejects downstream.\n childRequestContext.set(MASTRA_THREAD_ID_KEY, ephemeralThreadId);\n if (parentResourceId) {\n childRequestContext.set(MASTRA_RESOURCE_ID_KEY, parentResourceId);\n } else {\n childRequestContext.delete(MASTRA_RESOURCE_ID_KEY);\n }\n\n return fn(childRequestContext);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AA2BA,eAAsB,oBACpB,gBACA,IACA,UAAkC,CAAC,GACvB;CACZ,IAAI,CAAC,gBAAgB,OAAO,GAAG,KAAA,CAAS;CAExC,MAAM,sBAAsB,IAAI,eAAe,eAAe,QAAQ,CAAC;CACvE,MAAM,eAAe,eAAe,IAAI,cAAc;CAGtD,MAAM,aAAa,eAAe,IAAI,sBAAsB;CAC5D,MAAM,oBAAoB,QAAQ,YAAY,WAAW,OAAO,WAAW;CAC3E,MAAM,mBAAmB,cAAc,cAAc,cAAc;CAEnE,oBAAoB,IAAI,gBAAgB;EACtC,QAAQ,EAAE,IAAI,kBAAkB;EAChC,YAAY;EACZ,cAAc,KAAA;CAChB,CAAC;CAMD,oBAAoB,IAAI,sBAAsB,iBAAiB;CAC/D,IAAI,kBACF,oBAAoB,IAAI,wBAAwB,gBAAgB;MAEhE,oBAAoB,OAAO,sBAAsB;CAGnD,OAAO,GAAG,mBAAmB;AAC/B"}
@@ -0,0 +1,33 @@
1
+ import type { ListScoresResponse, SaveScorePayload, ScoreRowData } from '@mastra/core/evals';
2
+ import { ScoresStorage } from '@mastra/core/storage';
3
+ import type { StoragePagination } from '@mastra/core/storage';
4
+ /**
5
+ * A scores domain that accepts writes and keeps nothing.
6
+ *
7
+ * mastracode's `outcome` and `efficiency` scorers persist every result through
8
+ * the scores domain (`validateAndSaveScore` → `getStore('scores')`), but nothing
9
+ * in mastracode reads scores back. Writing them to libsql grew mastra.db without
10
+ * bound, and an in-memory store would grow the heap for the life of the process
11
+ * instead (each payload carries the system prompt, messages, input and output).
12
+ * Disabling the domain is not an option: core throws
13
+ * MASTRA_SCORES_STORAGE_NOT_AVAILABLE on every scorer run when it is missing.
14
+ */
15
+ export declare class DiscardingScoresStorage extends ScoresStorage {
16
+ getScoreById(): Promise<ScoreRowData | null>;
17
+ saveScore(score: SaveScorePayload): Promise<{
18
+ score: ScoreRowData;
19
+ }>;
20
+ listScoresByScorerId({ pagination }: {
21
+ pagination: StoragePagination;
22
+ }): Promise<ListScoresResponse>;
23
+ listScoresByRunId({ pagination }: {
24
+ pagination: StoragePagination;
25
+ }): Promise<ListScoresResponse>;
26
+ listScoresByEntityId({ pagination }: {
27
+ pagination: StoragePagination;
28
+ }): Promise<ListScoresResponse>;
29
+ listScoresBySpan({ pagination }: {
30
+ pagination: StoragePagination;
31
+ }): Promise<ListScoresResponse>;
32
+ }
33
+ //# sourceMappingURL=discarding-scores-storage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discarding-scores-storage.d.ts","sourceRoot":"","sources":["../../src/utils/discarding-scores-storage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAC7F,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAE9D;;;;;;;;;;GAUG;AACH,qBAAa,uBAAwB,SAAQ,aAAa;IAClD,YAAY,IAAI,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAI5C,SAAS,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,YAAY,CAAA;KAAE,CAAC;IAKpE,oBAAoB,CAAC,EAAE,UAAU,EAAE,EAAE;QAAE,UAAU,EAAE,iBAAiB,CAAA;KAAE,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAIpG,iBAAiB,CAAC,EAAE,UAAU,EAAE,EAAE;QAAE,UAAU,EAAE,iBAAiB,CAAA;KAAE,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAIjG,oBAAoB,CAAC,EAAE,UAAU,EAAE,EAAE;QAAE,UAAU,EAAE,iBAAiB,CAAA;KAAE,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAIpG,gBAAgB,CAAC,EAAE,UAAU,EAAE,EAAE;QAAE,UAAU,EAAE,iBAAiB,CAAA;KAAE,GAAG,OAAO,CAAC,kBAAkB,CAAC;CAGvG"}
@@ -0,0 +1,54 @@
1
+ import { ScoresStorage } from "@mastra/core/storage";
2
+ //#region src/utils/discarding-scores-storage.ts
3
+ /**
4
+ * A scores domain that accepts writes and keeps nothing.
5
+ *
6
+ * mastracode's `outcome` and `efficiency` scorers persist every result through
7
+ * the scores domain (`validateAndSaveScore` → `getStore('scores')`), but nothing
8
+ * in mastracode reads scores back. Writing them to libsql grew mastra.db without
9
+ * bound, and an in-memory store would grow the heap for the life of the process
10
+ * instead (each payload carries the system prompt, messages, input and output).
11
+ * Disabling the domain is not an option: core throws
12
+ * MASTRA_SCORES_STORAGE_NOT_AVAILABLE on every scorer run when it is missing.
13
+ */
14
+ var DiscardingScoresStorage = class extends ScoresStorage {
15
+ async getScoreById() {
16
+ return null;
17
+ }
18
+ async saveScore(score) {
19
+ const now = /* @__PURE__ */ new Date();
20
+ return { score: {
21
+ ...score,
22
+ id: score.id ?? crypto.randomUUID(),
23
+ createdAt: now,
24
+ updatedAt: now
25
+ } };
26
+ }
27
+ async listScoresByScorerId({ pagination }) {
28
+ return empty(pagination);
29
+ }
30
+ async listScoresByRunId({ pagination }) {
31
+ return empty(pagination);
32
+ }
33
+ async listScoresByEntityId({ pagination }) {
34
+ return empty(pagination);
35
+ }
36
+ async listScoresBySpan({ pagination }) {
37
+ return empty(pagination);
38
+ }
39
+ };
40
+ function empty(pagination) {
41
+ return {
42
+ pagination: {
43
+ total: 0,
44
+ page: pagination.page,
45
+ perPage: pagination.perPage,
46
+ hasMore: false
47
+ },
48
+ scores: []
49
+ };
50
+ }
51
+ //#endregion
52
+ export { DiscardingScoresStorage };
53
+
54
+ //# sourceMappingURL=discarding-scores-storage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discarding-scores-storage.js","names":[],"sources":["../../src/utils/discarding-scores-storage.ts"],"sourcesContent":["import type { ListScoresResponse, SaveScorePayload, ScoreRowData } from '@mastra/core/evals';\nimport { ScoresStorage } from '@mastra/core/storage';\nimport type { StoragePagination } from '@mastra/core/storage';\n\n/**\n * A scores domain that accepts writes and keeps nothing.\n *\n * mastracode's `outcome` and `efficiency` scorers persist every result through\n * the scores domain (`validateAndSaveScore` → `getStore('scores')`), but nothing\n * in mastracode reads scores back. Writing them to libsql grew mastra.db without\n * bound, and an in-memory store would grow the heap for the life of the process\n * instead (each payload carries the system prompt, messages, input and output).\n * Disabling the domain is not an option: core throws\n * MASTRA_SCORES_STORAGE_NOT_AVAILABLE on every scorer run when it is missing.\n */\nexport class DiscardingScoresStorage extends ScoresStorage {\n async getScoreById(): Promise<ScoreRowData | null> {\n return null;\n }\n\n async saveScore(score: SaveScorePayload): Promise<{ score: ScoreRowData }> {\n const now = new Date();\n return { score: { ...score, id: score.id ?? crypto.randomUUID(), createdAt: now, updatedAt: now } as ScoreRowData };\n }\n\n async listScoresByScorerId({ pagination }: { pagination: StoragePagination }): Promise<ListScoresResponse> {\n return empty(pagination);\n }\n\n async listScoresByRunId({ pagination }: { pagination: StoragePagination }): Promise<ListScoresResponse> {\n return empty(pagination);\n }\n\n async listScoresByEntityId({ pagination }: { pagination: StoragePagination }): Promise<ListScoresResponse> {\n return empty(pagination);\n }\n\n async listScoresBySpan({ pagination }: { pagination: StoragePagination }): Promise<ListScoresResponse> {\n return empty(pagination);\n }\n}\n\nfunction empty(pagination: StoragePagination): ListScoresResponse {\n return { pagination: { total: 0, page: pagination.page, perPage: pagination.perPage, hasMore: false }, scores: [] };\n}\n"],"mappings":";;;;;;;;;;;;;AAeA,IAAa,0BAAb,cAA6C,cAAc;CACzD,MAAM,eAA6C;EACjD,OAAO;CACT;CAEA,MAAM,UAAU,OAA2D;EACzE,MAAM,sBAAM,IAAI,KAAK;EACrB,OAAO,EAAE,OAAO;GAAE,GAAG;GAAO,IAAI,MAAM,MAAM,OAAO,WAAW;GAAG,WAAW;GAAK,WAAW;EAAI,EAAkB;CACpH;CAEA,MAAM,qBAAqB,EAAE,cAA8E;EACzG,OAAO,MAAM,UAAU;CACzB;CAEA,MAAM,kBAAkB,EAAE,cAA8E;EACtG,OAAO,MAAM,UAAU;CACzB;CAEA,MAAM,qBAAqB,EAAE,cAA8E;EACzG,OAAO,MAAM,UAAU;CACzB;CAEA,MAAM,iBAAiB,EAAE,cAA8E;EACrG,OAAO,MAAM,UAAU;CACzB;AACF;AAEA,SAAS,MAAM,YAAmD;CAChE,OAAO;EAAE,YAAY;GAAE,OAAO;GAAG,MAAM,WAAW;GAAM,SAAS,WAAW;GAAS,SAAS;EAAM;EAAG,QAAQ,CAAC;CAAE;AACpH"}
@@ -0,0 +1,42 @@
1
+ export declare class MaintenanceLockError extends Error {
2
+ readonly ownerPids: number[];
3
+ constructor(message: string, ownerPids: number[]);
4
+ }
5
+ export declare function getMaintenanceLockPath(): string;
6
+ /** Owner of a lock whose pid file is still being written (PID not known yet). */
7
+ export declare const UNKNOWN_OWNER = -1;
8
+ /**
9
+ * Creating a pid file (open, then write) is not atomic, so an empty or
10
+ * unparseable file may belong to a process that is mid-write. Only treat it as
11
+ * stale once it is older than this.
12
+ */
13
+ export declare const MALFORMED_PID_FILE_GRACE_MS = 5000;
14
+ /**
15
+ * PID holding the maintenance lock, `UNKNOWN_OWNER` while its pid file is still
16
+ * being written, or null. Stale locks are removed.
17
+ */
18
+ export declare function getMaintenanceLockOwner(): number | null;
19
+ /** PIDs of other live registered sessions. Stale registrations are removed. */
20
+ export declare function getLiveSessionPids(): number[];
21
+ /** Test-only: drop every registration held by this process and forget lock ownership. */
22
+ export declare function resetSessionRegistrationsForTesting(): void;
23
+ /** Register one running session in this process. Pair with exactly one unregisterSession(). */
24
+ export declare function registerSession(): void;
25
+ /** Release one registration made by registerSession(). */
26
+ export declare function unregisterSession(): void;
27
+ /**
28
+ * Register this session, then wait for any running maintenance to finish.
29
+ * Waits indefinitely by default: a vacuum on a multi-GB database can take
30
+ * minutes. With `timeoutMs`, throws after that long naming the holder.
31
+ */
32
+ export declare function registerSessionAndWaitForMaintenance({ timeoutMs, pollMs, onWait, }?: {
33
+ timeoutMs?: number;
34
+ pollMs?: number;
35
+ onWait?: (ownerPid: number) => void;
36
+ }): Promise<void>;
37
+ /**
38
+ * Acquire the maintenance lock, then refuse if any mastracode session is live.
39
+ * Returns a release function.
40
+ */
41
+ export declare function acquireMaintenanceLock(): () => void;
42
+ //# sourceMappingURL=maintenance-lock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"maintenance-lock.d.ts","sourceRoot":"","sources":["../../src/utils/maintenance-lock.ts"],"names":[],"mappings":"AAiBA,qBAAa,oBAAqB,SAAQ,KAAK;aAG3B,SAAS,EAAE,MAAM,EAAE;gBADnC,OAAO,EAAE,MAAM,EACC,SAAS,EAAE,MAAM,EAAE;CAKtC;AAcD,wBAAgB,sBAAsB,IAAI,MAAM,CAE/C;AAED,iFAAiF;AACjF,eAAO,MAAM,aAAa,KAAK,CAAC;AAEhC;;;;GAIG;AACH,eAAO,MAAM,2BAA2B,OAAQ,CAAC;AAuCjD;;;GAGG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,GAAG,IAAI,CAgBvD;AAED,+EAA+E;AAC/E,wBAAgB,kBAAkB,IAAI,MAAM,EAAE,CAmB7C;AAOD,yFAAyF;AACzF,wBAAgB,mCAAmC,IAAI,IAAI,CAG1D;AAYD,+FAA+F;AAC/F,wBAAgB,eAAe,IAAI,IAAI,CAStC;AAED,0DAA0D;AAC1D,wBAAgB,iBAAiB,IAAI,IAAI,CAIxC;AAED;;;;GAIG;AACH,wBAAsB,oCAAoC,CAAC,EACzD,SAAoB,EACpB,MAAY,EACZ,MAAM,GACP,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAA;CAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAqBnG;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,IAAI,CA0CnD"}