@mastra/code-sdk 1.8.4-alpha.6 → 1.9.0-alpha.10
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.
- package/README.md +190 -0
- package/dist/acp/agent.d.ts +30 -17
- package/dist/acp/agent.d.ts.map +1 -1
- package/dist/acp/agent.js +294 -103
- package/dist/acp/agent.js.map +1 -1
- package/dist/acp/errors.d.ts +3 -0
- package/dist/acp/errors.d.ts.map +1 -0
- package/dist/acp/errors.js +14 -0
- package/dist/acp/errors.js.map +1 -0
- package/dist/acp/event-mapper.d.ts +6 -1
- package/dist/acp/event-mapper.d.ts.map +1 -1
- package/dist/acp/event-mapper.js +116 -56
- package/dist/acp/event-mapper.js.map +1 -1
- package/dist/acp/index.d.ts +1 -4
- package/dist/acp/index.d.ts.map +1 -1
- package/dist/acp/index.js +6 -48
- package/dist/acp/index.js.map +1 -1
- package/dist/acp/runtime.d.ts +5 -0
- package/dist/acp/runtime.d.ts.map +1 -0
- package/dist/acp/runtime.js +80 -0
- package/dist/acp/runtime.js.map +1 -0
- package/dist/acp/server.d.ts +3 -6
- package/dist/acp/server.d.ts.map +1 -1
- package/dist/acp/server.js +22 -19
- package/dist/acp/server.js.map +1 -1
- package/dist/acp/skills.d.ts +6 -0
- package/dist/acp/skills.d.ts.map +1 -0
- package/dist/acp/skills.js +33 -0
- package/dist/acp/skills.js.map +1 -0
- package/dist/agents/model.js +1 -1
- package/dist/agents/prompts/agent-instructions.js +2 -2
- package/dist/agents/tools.d.ts +1 -1
- package/dist/agents/tools.d.ts.map +1 -1
- package/dist/agents/tools.js +2 -1
- package/dist/agents/tools.js.map +1 -1
- package/dist/agents/workspace.js +1 -1
- package/dist/analytics.js +2 -2
- package/dist/auth/providers/kimi-coding.js +1 -1
- package/dist/auth/storage.js +2 -2
- package/dist/clipboard/index.js +2 -2
- package/dist/headless/run-mc.d.ts.map +1 -1
- package/dist/headless/run-mc.js +14 -0
- package/dist/headless/run-mc.js.map +1 -1
- package/dist/hooks/config.js +1 -1
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +75 -8
- package/dist/index.js.map +1 -1
- package/dist/lsp/server.js +1 -1
- package/dist/lsp/workspace.js +1 -1
- package/dist/mcp/config.js +1 -1
- package/dist/mcp/manager.d.ts.map +1 -1
- package/dist/mcp/manager.js +2 -1
- package/dist/mcp/manager.js.map +1 -1
- package/dist/mcp/state.js +1 -1
- package/dist/mcp/types.d.ts +2 -0
- package/dist/mcp/types.d.ts.map +1 -1
- package/dist/onboarding/settings.d.ts +2 -0
- package/dist/onboarding/settings.d.ts.map +1 -1
- package/dist/onboarding/settings.js +6 -4
- package/dist/onboarding/settings.js.map +1 -1
- package/dist/permissions.d.ts.map +1 -1
- package/dist/permissions.js +6 -1
- package/dist/permissions.js.map +1 -1
- package/dist/plugins/dependencies.js +1 -1
- package/dist/plugins/install.js +1 -1
- package/dist/plugins/loader.js +3 -3
- package/dist/plugins/manager.js +1 -1
- package/dist/plugins/manifest.js +1 -1
- package/dist/plugins/package-link.js +1 -1
- package/dist/plugins/paths.js +1 -1
- package/dist/plugins/registry.js +1 -1
- package/dist/plugins/scaffold.js +1 -1
- package/dist/process-memory-diagnostics.js +3 -3
- package/dist/providers/amazon-bedrock-gateway.js +1 -1
- package/dist/providers/openai-codex.js +1 -1
- package/dist/schedules/index.d.ts +10 -0
- package/dist/schedules/index.d.ts.map +1 -0
- package/dist/schedules/index.js +6 -0
- package/dist/schedules/interval.d.ts +49 -0
- package/dist/schedules/interval.d.ts.map +1 -0
- package/dist/schedules/interval.js +215 -0
- package/dist/schedules/interval.js.map +1 -0
- package/dist/schedules/prompt.d.ts +36 -0
- package/dist/schedules/prompt.d.ts.map +1 -0
- package/dist/schedules/prompt.js +39 -0
- package/dist/schedules/prompt.js.map +1 -0
- package/dist/schedules/run-script.d.ts +8 -0
- package/dist/schedules/run-script.d.ts.map +1 -0
- package/dist/schedules/run-script.js +83 -0
- package/dist/schedules/run-script.js.map +1 -0
- package/dist/schedules/scheduler.d.ts +101 -0
- package/dist/schedules/scheduler.d.ts.map +1 -0
- package/dist/schedules/scheduler.js +169 -0
- package/dist/schedules/scheduler.js.map +1 -0
- package/dist/schedules/tools.d.ts +57 -0
- package/dist/schedules/tools.d.ts.map +1 -0
- package/dist/schedules/tools.js +220 -0
- package/dist/schedules/tools.js.map +1 -0
- package/dist/schema.js +1 -1
- package/dist/tools/request-sandbox-access.js +5 -4
- package/dist/tools/request-sandbox-access.js.map +1 -1
- package/dist/utils/debug-log.js +1 -1
- package/dist/utils/discarding-scores-storage.d.ts +33 -0
- package/dist/utils/discarding-scores-storage.d.ts.map +1 -0
- package/dist/utils/discarding-scores-storage.js +54 -0
- package/dist/utils/discarding-scores-storage.js.map +1 -0
- package/dist/utils/maintenance-lock.d.ts +42 -0
- package/dist/utils/maintenance-lock.d.ts.map +1 -0
- package/dist/utils/maintenance-lock.js +199 -0
- package/dist/utils/maintenance-lock.js.map +1 -0
- package/dist/utils/project.js +3 -3
- package/dist/utils/prune-cli.d.ts +24 -0
- package/dist/utils/prune-cli.d.ts.map +1 -0
- package/dist/utils/prune-cli.js +125 -0
- package/dist/utils/prune-cli.js.map +1 -0
- package/dist/utils/signals-pubsub.js +1 -1
- package/dist/utils/slash-command-loader.js +1 -1
- package/dist/utils/slash-command-processor.js +1 -1
- package/dist/utils/storage-maintenance.d.ts.map +1 -1
- package/dist/utils/storage-maintenance.js +34 -4
- package/dist/utils/storage-maintenance.js.map +1 -1
- package/dist/utils/thread-lock.js +1 -1
- package/dist/utils/update-check.js +2 -2
- package/dist/workflows/register-primitives.js +1 -1
- package/package.json +22 -12
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scheduler.d.ts","sourceRoot":"","sources":["../../src/schedules/scheduler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { nextFireTime, validateInterval } from "./interval.js";
|
|
2
|
+
import { randomUUID } from "crypto";
|
|
3
|
+
//#region src/schedules/scheduler.ts
|
|
4
|
+
/**
|
|
5
|
+
* Process-local scheduler behind `/schedules`.
|
|
6
|
+
*
|
|
7
|
+
* Schedules live only in this process: timers fire them and they die with it.
|
|
8
|
+
* Nothing is written to shared storage, so other Mastra Code processes on the
|
|
9
|
+
* same database never see — or fire — this session's schedules.
|
|
10
|
+
*/
|
|
11
|
+
/** `source` attribute on fired signals; the TUI labels these turns `schedule`. */
|
|
12
|
+
const SCHEDULE_SIGNAL_SOURCE = "schedule";
|
|
13
|
+
/** How late a timer may run before its fire counts as missed (sleep, stalled event loop). */
|
|
14
|
+
const LATE_FIRE_GRACE_MS = 6e4;
|
|
15
|
+
var ThreadScheduler = class {
|
|
16
|
+
#entries = /* @__PURE__ */ new Map();
|
|
17
|
+
#options;
|
|
18
|
+
constructor(options) {
|
|
19
|
+
this.#options = options;
|
|
20
|
+
}
|
|
21
|
+
#now() {
|
|
22
|
+
return this.#options.now?.() ?? Date.now();
|
|
23
|
+
}
|
|
24
|
+
/** Throws when the interval is not a supported wall-clock cadence (see `validateInterval`) or the prompt is empty. */
|
|
25
|
+
create(spec, target) {
|
|
26
|
+
const { interval } = spec.trigger;
|
|
27
|
+
const check = validateInterval(interval);
|
|
28
|
+
if ("error" in check) throw new Error(`Invalid schedule interval: ${check.error}${check.suggestion ? ` Try ${check.suggestion}.` : ""}`);
|
|
29
|
+
if ("prompt" in spec && !spec.prompt.trim()) throw new Error("Schedule prompt is empty.");
|
|
30
|
+
const now = this.#now();
|
|
31
|
+
const schedule = {
|
|
32
|
+
id: randomUUID(),
|
|
33
|
+
threadId: target.threadId,
|
|
34
|
+
resourceId: target.resourceId,
|
|
35
|
+
trigger: {
|
|
36
|
+
kind: "every",
|
|
37
|
+
interval: { ...interval }
|
|
38
|
+
},
|
|
39
|
+
..."file" in spec ? {
|
|
40
|
+
file: { ...spec.file },
|
|
41
|
+
...spec.extraPrompt ? { extraPrompt: spec.extraPrompt } : {}
|
|
42
|
+
} : { prompt: spec.prompt },
|
|
43
|
+
createdBy: spec.createdBy ?? "user",
|
|
44
|
+
status: "active",
|
|
45
|
+
nextFireAt: nextFireTime(interval.ms, now),
|
|
46
|
+
createdAt: now
|
|
47
|
+
};
|
|
48
|
+
const entry = {
|
|
49
|
+
schedule,
|
|
50
|
+
inFlight: 0
|
|
51
|
+
};
|
|
52
|
+
this.#entries.set(schedule.id, entry);
|
|
53
|
+
this.#arm(entry);
|
|
54
|
+
return { ...schedule };
|
|
55
|
+
}
|
|
56
|
+
list(filter = {}) {
|
|
57
|
+
return [...this.#entries.values()].map((entry) => ({ ...entry.schedule })).filter((schedule) => !filter.threadId || schedule.threadId === filter.threadId).sort((a, b) => a.createdAt - b.createdAt);
|
|
58
|
+
}
|
|
59
|
+
delete(id) {
|
|
60
|
+
const entry = this.#entries.get(id);
|
|
61
|
+
if (!entry) return false;
|
|
62
|
+
clearTimeout(entry.timer);
|
|
63
|
+
this.#entries.delete(id);
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
pause(id) {
|
|
67
|
+
const entry = this.#entries.get(id);
|
|
68
|
+
if (!entry) return false;
|
|
69
|
+
clearTimeout(entry.timer);
|
|
70
|
+
entry.timer = void 0;
|
|
71
|
+
entry.schedule.status = "paused";
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
resume(id) {
|
|
75
|
+
const entry = this.#entries.get(id);
|
|
76
|
+
if (!entry) return false;
|
|
77
|
+
if (entry.schedule.status === "active") return true;
|
|
78
|
+
entry.schedule.status = "active";
|
|
79
|
+
entry.schedule.nextFireAt = nextFireTime(entry.schedule.trigger.interval.ms, this.#now());
|
|
80
|
+
this.#arm(entry);
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
/** Whether a fire of this schedule (timer or manual) is still assembling or delivering. */
|
|
84
|
+
isFiring(id) {
|
|
85
|
+
return (this.#entries.get(id)?.inFlight ?? 0) > 0;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Fire once now, outside the cadence. Returns `busy` without firing when a
|
|
89
|
+
* fire of this schedule is still running (a slow script, say), so the same
|
|
90
|
+
* script never runs twice at once. Resolves once the fire finished; a fire
|
|
91
|
+
* that never reached the agent resolves `failed` instead of calling `onError`.
|
|
92
|
+
*/
|
|
93
|
+
async run(id) {
|
|
94
|
+
const entry = this.#entries.get(id);
|
|
95
|
+
if (!entry) return { status: "not-found" };
|
|
96
|
+
if (entry.inFlight > 0) return { status: "busy" };
|
|
97
|
+
const result = await this.#fire(entry);
|
|
98
|
+
if (result.kind === "failed") return {
|
|
99
|
+
status: "failed",
|
|
100
|
+
error: result.error
|
|
101
|
+
};
|
|
102
|
+
return result.kind === "delivered" ? { status: "fired" } : { status: "not-found" };
|
|
103
|
+
}
|
|
104
|
+
/** Drop every schedule and timer (process shutdown). */
|
|
105
|
+
stop() {
|
|
106
|
+
for (const entry of this.#entries.values()) clearTimeout(entry.timer);
|
|
107
|
+
this.#entries.clear();
|
|
108
|
+
}
|
|
109
|
+
#arm(entry) {
|
|
110
|
+
clearTimeout(entry.timer);
|
|
111
|
+
const scheduledAt = entry.schedule.nextFireAt;
|
|
112
|
+
entry.timer = setTimeout(() => {
|
|
113
|
+
if (this.#entries.get(entry.schedule.id) !== entry || entry.schedule.status !== "active") return;
|
|
114
|
+
const now = this.#now();
|
|
115
|
+
entry.schedule.nextFireAt = nextFireTime(entry.schedule.trigger.interval.ms, Math.max(now, scheduledAt));
|
|
116
|
+
this.#arm(entry);
|
|
117
|
+
if (now - scheduledAt > 6e4) return;
|
|
118
|
+
if (entry.inFlight === 0) this.#fire(entry).then((result) => {
|
|
119
|
+
if (result.kind === "failed") this.#options.onError?.(result.error, { ...entry.schedule });
|
|
120
|
+
});
|
|
121
|
+
}, Math.max(0, scheduledAt - this.#now()));
|
|
122
|
+
entry.timer.unref?.();
|
|
123
|
+
}
|
|
124
|
+
async #fire(entry) {
|
|
125
|
+
const schedule = { ...entry.schedule };
|
|
126
|
+
entry.inFlight++;
|
|
127
|
+
try {
|
|
128
|
+
const assembled = await this.#options.assemblePrompt(schedule);
|
|
129
|
+
if (this.#entries.get(schedule.id) !== entry) return { kind: "deleted" };
|
|
130
|
+
await this.#options.deliver(schedule, assembled);
|
|
131
|
+
return { kind: "delivered" };
|
|
132
|
+
} catch (error) {
|
|
133
|
+
return {
|
|
134
|
+
kind: "failed",
|
|
135
|
+
error
|
|
136
|
+
};
|
|
137
|
+
} finally {
|
|
138
|
+
entry.inFlight--;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
function shortScheduleId(id) {
|
|
143
|
+
return id.slice(0, 8);
|
|
144
|
+
}
|
|
145
|
+
/** One-line human summary of what a schedule sends: `run ./check.sh + "extra"`, `read notes.md`, `"prompt"`. */
|
|
146
|
+
function describeScheduleSource(schedule) {
|
|
147
|
+
if (!schedule.file) return `"${schedule.prompt ?? ""}"`;
|
|
148
|
+
const verb = schedule.file.mode === "script" ? "run" : "read";
|
|
149
|
+
const extra = schedule.extraPrompt ? ` + "${schedule.extraPrompt}"` : "";
|
|
150
|
+
return `${verb} ${schedule.file.displayPath}${extra}`;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Attributes on a fired schedule signal. They carry everything the transcript
|
|
154
|
+
* header needs, so reloaded history renders without the process-local entry.
|
|
155
|
+
*/
|
|
156
|
+
function scheduleSignalAttributes(schedule, assembled = {}) {
|
|
157
|
+
return {
|
|
158
|
+
source: SCHEDULE_SIGNAL_SOURCE,
|
|
159
|
+
scheduleId: schedule.id,
|
|
160
|
+
scheduleCadence: schedule.trigger.interval.label,
|
|
161
|
+
scheduleSource: describeScheduleSource(schedule),
|
|
162
|
+
scheduleCreatedBy: schedule.createdBy,
|
|
163
|
+
...assembled.outcome ? { scheduleOutcome: assembled.outcome } : {}
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
//#endregion
|
|
167
|
+
export { LATE_FIRE_GRACE_MS, SCHEDULE_SIGNAL_SOURCE, ThreadScheduler, describeScheduleSource, scheduleSignalAttributes, shortScheduleId };
|
|
168
|
+
|
|
169
|
+
//# sourceMappingURL=scheduler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scheduler.js","names":["#options","#now","#entries","#arm","#fire"],"sources":["../../src/schedules/scheduler.ts"],"sourcesContent":["/**\n * Process-local scheduler behind `/schedules`.\n *\n * Schedules live only in this process: timers fire them and they die with it.\n * Nothing is written to shared storage, so other Mastra Code processes on the\n * same database never see — or fire — this session's schedules.\n */\nimport { randomUUID } from 'node:crypto';\nimport { nextFireTime, validateInterval } from './interval.js';\nimport type { ParsedInterval } from './interval.js';\nimport type { AssembledPrompt } from './prompt.js';\n\n/** `source` attribute on fired signals; the TUI labels these turns `schedule`. */\nexport const SCHEDULE_SIGNAL_SOURCE = 'schedule';\n\n/** When a schedule fires. Only recurring `every` triggers exist today. */\nexport type ScheduleTrigger = { kind: 'every'; interval: ParsedInterval };\n\n/** A file a schedule runs as a script, or re-reads and sends as the prompt, on every fire. */\nexport type ScheduleFile = { path: string; displayPath: string; mode: 'script' | 'prompt' };\n\n/** What to send on each fire: `prompt` text, or a `file` (plus `extraPrompt` appended after it). */\nexport type ThreadScheduleSource = { prompt: string } | { file: ScheduleFile; extraPrompt?: string };\n\nexport type ThreadScheduleSpec = ThreadScheduleSource & {\n trigger: ScheduleTrigger;\n /** Who is creating it: the user via `/schedules`, or the agent via its schedule tools. Defaults to `user`. */\n createdBy?: 'user' | 'agent';\n};\n\nexport type ThreadSchedule = {\n id: string;\n threadId: string;\n resourceId: string;\n trigger: ScheduleTrigger;\n prompt?: string;\n file?: ScheduleFile;\n extraPrompt?: string;\n createdBy: 'user' | 'agent';\n status: 'active' | 'paused';\n /** Next boundary this schedule fires at; only meaningful while active. */\n nextFireAt: number;\n createdAt: number;\n};\n\nexport type ThreadSchedulerOptions = {\n /** Build the prompt for one fire (runs scripts / reads files). */\n assemblePrompt: (schedule: ThreadSchedule) => Promise<AssembledPrompt>;\n /** Hand the prompt to the agent for the schedule's thread. */\n deliver: (schedule: ThreadSchedule, assembled: AssembledPrompt) => Promise<void>;\n /** A fire failed before reaching the agent. */\n onError?: (error: unknown, schedule: ThreadSchedule) => void;\n now?: () => number;\n};\n\n/** How late a timer may run before its fire counts as missed (sleep, stalled event loop). */\nexport const LATE_FIRE_GRACE_MS = 60_000;\n\n/**\n * Outcome of a manual `run()`. `failed` means nothing reached the agent: the\n * prompt could not be built or the agent refused it.\n */\nexport type ScheduleRunResult =\n | { status: 'fired' }\n | { status: 'failed'; error: unknown }\n | { status: 'busy' }\n | { status: 'not-found' };\n\ntype FireOutcome = { kind: 'delivered' } | { kind: 'deleted' } | { kind: 'failed'; error: unknown };\n\ntype Entry = { schedule: ThreadSchedule; timer?: ReturnType<typeof setTimeout>; inFlight: number };\n\nexport class ThreadScheduler {\n #entries = new Map<string, Entry>();\n #options: ThreadSchedulerOptions;\n\n constructor(options: ThreadSchedulerOptions) {\n this.#options = options;\n }\n\n #now(): number {\n return this.#options.now?.() ?? Date.now();\n }\n\n /** Throws when the interval is not a supported wall-clock cadence (see `validateInterval`) or the prompt is empty. */\n create(spec: ThreadScheduleSpec, target: { threadId: string; resourceId: string }): ThreadSchedule {\n const { interval } = spec.trigger;\n const check = validateInterval(interval);\n if ('error' in check) {\n throw new Error(\n `Invalid schedule interval: ${check.error}${check.suggestion ? ` Try ${check.suggestion}.` : ''}`,\n );\n }\n if ('prompt' in spec && !spec.prompt.trim()) throw new Error('Schedule prompt is empty.');\n const now = this.#now();\n const schedule: ThreadSchedule = {\n id: randomUUID(),\n threadId: target.threadId,\n resourceId: target.resourceId,\n trigger: { kind: 'every', interval: { ...interval } },\n ...('file' in spec\n ? { file: { ...spec.file }, ...(spec.extraPrompt ? { extraPrompt: spec.extraPrompt } : {}) }\n : { prompt: spec.prompt }),\n createdBy: spec.createdBy ?? 'user',\n status: 'active',\n nextFireAt: nextFireTime(interval.ms, now),\n createdAt: now,\n };\n const entry: Entry = { schedule, inFlight: 0 };\n this.#entries.set(schedule.id, entry);\n this.#arm(entry);\n return { ...schedule };\n }\n\n list(filter: { threadId?: string } = {}): ThreadSchedule[] {\n return [...this.#entries.values()]\n .map(entry => ({ ...entry.schedule }))\n .filter(schedule => !filter.threadId || schedule.threadId === filter.threadId)\n .sort((a, b) => a.createdAt - b.createdAt);\n }\n\n delete(id: string): boolean {\n const entry = this.#entries.get(id);\n if (!entry) return false;\n clearTimeout(entry.timer);\n this.#entries.delete(id);\n return true;\n }\n\n pause(id: string): boolean {\n const entry = this.#entries.get(id);\n if (!entry) return false;\n clearTimeout(entry.timer);\n entry.timer = undefined;\n entry.schedule.status = 'paused';\n return true;\n }\n\n resume(id: string): boolean {\n const entry = this.#entries.get(id);\n if (!entry) return false;\n if (entry.schedule.status === 'active') return true;\n entry.schedule.status = 'active';\n entry.schedule.nextFireAt = nextFireTime(entry.schedule.trigger.interval.ms, this.#now());\n this.#arm(entry);\n return true;\n }\n\n /** Whether a fire of this schedule (timer or manual) is still assembling or delivering. */\n isFiring(id: string): boolean {\n return (this.#entries.get(id)?.inFlight ?? 0) > 0;\n }\n\n /**\n * Fire once now, outside the cadence. Returns `busy` without firing when a\n * fire of this schedule is still running (a slow script, say), so the same\n * script never runs twice at once. Resolves once the fire finished; a fire\n * that never reached the agent resolves `failed` instead of calling `onError`.\n */\n async run(id: string): Promise<ScheduleRunResult> {\n const entry = this.#entries.get(id);\n if (!entry) return { status: 'not-found' };\n if (entry.inFlight > 0) return { status: 'busy' };\n const result = await this.#fire(entry);\n if (result.kind === 'failed') return { status: 'failed', error: result.error };\n return result.kind === 'delivered' ? { status: 'fired' } : { status: 'not-found' };\n }\n\n /** Drop every schedule and timer (process shutdown). */\n stop(): void {\n for (const entry of this.#entries.values()) clearTimeout(entry.timer);\n this.#entries.clear();\n }\n\n #arm(entry: Entry): void {\n clearTimeout(entry.timer);\n const scheduledAt = entry.schedule.nextFireAt;\n entry.timer = setTimeout(\n () => {\n if (this.#entries.get(entry.schedule.id) !== entry || entry.schedule.status !== 'active') return;\n // Timers can fire a hair early; step from the later of now and the\n // intended boundary so the same boundary is never fired twice.\n const now = this.#now();\n entry.schedule.nextFireAt = nextFireTime(entry.schedule.trigger.interval.ms, Math.max(now, scheduledAt));\n this.#arm(entry);\n // A timer that ran long after its boundary (machine asleep) is a missed fire, not a late one.\n if (now - scheduledAt > LATE_FIRE_GRACE_MS) return;\n // A slow script can outlast a short interval; don't stack fires.\n if (entry.inFlight === 0) {\n void this.#fire(entry).then(result => {\n if (result.kind === 'failed') this.#options.onError?.(result.error, { ...entry.schedule });\n });\n }\n },\n Math.max(0, scheduledAt - this.#now()),\n );\n entry.timer.unref?.();\n }\n\n async #fire(entry: Entry): Promise<FireOutcome> {\n const schedule = { ...entry.schedule };\n entry.inFlight++;\n try {\n const assembled = await this.#options.assemblePrompt(schedule);\n // Deleted while its prompt was being built: drop the fire quietly.\n if (this.#entries.get(schedule.id) !== entry) return { kind: 'deleted' };\n await this.#options.deliver(schedule, assembled);\n return { kind: 'delivered' };\n } catch (error) {\n return { kind: 'failed', error };\n } finally {\n entry.inFlight--;\n }\n }\n}\n\nexport function shortScheduleId(id: string): string {\n return id.slice(0, 8);\n}\n\n/** One-line human summary of what a schedule sends: `run ./check.sh + \"extra\"`, `read notes.md`, `\"prompt\"`. */\nexport function describeScheduleSource(schedule: Pick<ThreadSchedule, 'prompt' | 'file' | 'extraPrompt'>): string {\n if (!schedule.file) return `\"${schedule.prompt ?? ''}\"`;\n const verb = schedule.file.mode === 'script' ? 'run' : 'read';\n const extra = schedule.extraPrompt ? ` + \"${schedule.extraPrompt}\"` : '';\n return `${verb} ${schedule.file.displayPath}${extra}`;\n}\n\n/**\n * Attributes on a fired schedule signal. They carry everything the transcript\n * header needs, so reloaded history renders without the process-local entry.\n */\nexport function scheduleSignalAttributes(\n schedule: ThreadSchedule,\n assembled: Pick<AssembledPrompt, 'outcome'> = {},\n): Record<string, string> {\n return {\n source: SCHEDULE_SIGNAL_SOURCE,\n scheduleId: schedule.id,\n scheduleCadence: schedule.trigger.interval.label,\n scheduleSource: describeScheduleSource(schedule),\n scheduleCreatedBy: schedule.createdBy,\n ...(assembled.outcome ? { scheduleOutcome: assembled.outcome } : {}),\n };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { ThreadScheduler } from './scheduler.js';
|
|
2
|
+
export declare const SCHEDULE_TOOL_IDS: {
|
|
3
|
+
readonly create: "schedule_create";
|
|
4
|
+
readonly list: "schedule_list";
|
|
5
|
+
readonly update: "schedule_update";
|
|
6
|
+
readonly resume: "schedule_resume";
|
|
7
|
+
readonly run: "schedule_run";
|
|
8
|
+
};
|
|
9
|
+
export type ScheduleFileOptions = {
|
|
10
|
+
/** Directory relative paths resolve against (the project root). */
|
|
11
|
+
cwd: string;
|
|
12
|
+
homeDir?: string;
|
|
13
|
+
fileExists: (absPath: string) => boolean;
|
|
14
|
+
};
|
|
15
|
+
export type ScheduleToolsOptions = {
|
|
16
|
+
scheduler: ThreadScheduler;
|
|
17
|
+
fileOptions: () => ScheduleFileOptions;
|
|
18
|
+
};
|
|
19
|
+
export declare function createScheduleTools({ scheduler, fileOptions }: ScheduleToolsOptions): {
|
|
20
|
+
schedule_create: import("@mastra/core/tools").Tool<{
|
|
21
|
+
trigger: {
|
|
22
|
+
kind: "every";
|
|
23
|
+
interval: import("./interval.js").ParsedInterval;
|
|
24
|
+
};
|
|
25
|
+
prompt?: string | undefined;
|
|
26
|
+
promptFile?: string | undefined;
|
|
27
|
+
script?: string | undefined;
|
|
28
|
+
extraPrompt?: string | undefined;
|
|
29
|
+
}, {
|
|
30
|
+
content: string;
|
|
31
|
+
isError?: boolean | undefined;
|
|
32
|
+
}, unknown, unknown, import("@mastra/core/tools").ToolExecutionContext<unknown, unknown, unknown>, "schedule_create", unknown>;
|
|
33
|
+
schedule_list: import("@mastra/core/tools").Tool<Record<string, never>, {
|
|
34
|
+
content: string;
|
|
35
|
+
isError?: boolean | undefined;
|
|
36
|
+
}, unknown, unknown, import("@mastra/core/tools").ToolExecutionContext<unknown, unknown, unknown>, "schedule_list", unknown>;
|
|
37
|
+
schedule_update: import("@mastra/core/tools").Tool<{
|
|
38
|
+
id: string;
|
|
39
|
+
action: "pause" | "delete";
|
|
40
|
+
}, {
|
|
41
|
+
content: string;
|
|
42
|
+
isError?: boolean | undefined;
|
|
43
|
+
}, unknown, unknown, import("@mastra/core/tools").ToolExecutionContext<unknown, unknown, unknown>, "schedule_update", unknown>;
|
|
44
|
+
schedule_resume: import("@mastra/core/tools").Tool<{
|
|
45
|
+
id: string;
|
|
46
|
+
}, {
|
|
47
|
+
content: string;
|
|
48
|
+
isError?: boolean | undefined;
|
|
49
|
+
}, unknown, unknown, import("@mastra/core/tools").ToolExecutionContext<unknown, unknown, unknown>, "schedule_resume", unknown>;
|
|
50
|
+
schedule_run: import("@mastra/core/tools").Tool<{
|
|
51
|
+
id: string;
|
|
52
|
+
}, {
|
|
53
|
+
content: string;
|
|
54
|
+
isError?: boolean | undefined;
|
|
55
|
+
}, unknown, unknown, import("@mastra/core/tools").ToolExecutionContext<unknown, unknown, unknown>, "schedule_run", unknown>;
|
|
56
|
+
};
|
|
57
|
+
//# sourceMappingURL=tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../src/schedules/tools.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAgC,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEpF,eAAO,MAAM,iBAAiB;;;;;;CAMpB,CAAC;AAEX,MAAM,MAAM,mBAAmB,GAAG;IAChC,mEAAmE;IACnE,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC;CAC1C,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,SAAS,EAAE,eAAe,CAAC;IAC3B,WAAW,EAAE,MAAM,mBAAmB,CAAC;CACxC,CAAC;AAiFF,wBAAgB,mBAAmB,CAAC,EAAE,SAAS,EAAE,WAAW,EAAE,EAAE,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4InF"}
|
|
@@ -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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"}
|
package/dist/schema.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { DEFAULT_CONFIG_DIR, DEFAULT_OM_MODEL_ID } from "./constants.js";
|
|
2
1
|
import { THINKING_LEVEL_VALUES } from "./thinking.js";
|
|
2
|
+
import { DEFAULT_CONFIG_DIR, DEFAULT_OM_MODEL_ID } from "./constants.js";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
//#region src/schema.ts
|
|
5
5
|
const stateSchema = z.object({
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { getAllowedPathsFromContext, isPathAllowed } from "./utils.js";
|
|
2
|
-
import * as os$1 from "os";
|
|
3
2
|
import * as path$1 from "path";
|
|
3
|
+
import * as os$1 from "os";
|
|
4
|
+
import { LocalFilesystem } from "@mastra/core/workspace";
|
|
4
5
|
import { createTool } from "@mastra/core/tools";
|
|
5
6
|
import { z } from "zod";
|
|
6
|
-
import { LocalFilesystem } from "@mastra/core/workspace";
|
|
7
7
|
//#region src/tools/request-sandbox-access.ts
|
|
8
8
|
/**
|
|
9
9
|
* request_access tool — requests permission to access a directory outside the project root.
|
|
@@ -30,9 +30,10 @@ const requestSandboxAccessTool = createTool({
|
|
|
30
30
|
execute: async ({ path: requestedPath, reason }, context) => {
|
|
31
31
|
try {
|
|
32
32
|
const agentControllerCtx = context?.requestContext?.get("controller");
|
|
33
|
+
const projectRoot = agentControllerCtx?.getState()?.projectPath ?? process.cwd();
|
|
33
34
|
const expanded = expandTilde(requestedPath);
|
|
34
|
-
const absolutePath = path$1.isAbsolute(expanded) ? expanded : path$1.resolve(
|
|
35
|
-
if (isPathAllowed(absolutePath,
|
|
35
|
+
const absolutePath = path$1.isAbsolute(expanded) ? expanded : path$1.resolve(projectRoot, expanded);
|
|
36
|
+
if (isPathAllowed(absolutePath, projectRoot, getAllowedPathsFromContext(context))) return {
|
|
36
37
|
content: `Access already granted: "${absolutePath}" is within the project root or allowed paths.`,
|
|
37
38
|
isError: false
|
|
38
39
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request-sandbox-access.js","names":["os","path"],"sources":["../../src/tools/request-sandbox-access.ts"],"sourcesContent":["/**\n * request_access tool — requests permission to access a directory outside the project root.\n * The user can approve or deny the request via TUI dialog.\n */\n\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport type { AgentControllerRequestContext } from '@mastra/core/agent-controller';\nimport { createTool } from '@mastra/core/tools';\nimport { LocalFilesystem } from '@mastra/core/workspace';\nimport { z } from 'zod';\nimport type { MastraCodeState } from '../schema.js';\nimport { isPathAllowed, getAllowedPathsFromContext } from './utils.js';\n\nfunction expandTilde(p: string): string {\n if (p === '~') return os.homedir();\n if (p.startsWith('~/') || p.startsWith('~\\\\')) return path.join(os.homedir(), p.slice(2));\n return p;\n}\n\ntype RequestSandboxAccessInput = {\n path: string;\n reason: string;\n};\n\nconst requestSandboxAccessInputSchema = z.object({\n path: z.string().min(1).describe('The absolute path to the directory you need access to.'),\n reason: z.string().min(1).describe('Brief explanation of why you need access to this directory.'),\n});\n\nexport const requestSandboxAccessTool = createTool({\n id: 'request_access',\n description: `Request permission to access a directory outside the current project. Use this when you need to read or write files in a directory that is not within the project root. The user will be prompted to approve or deny the request.`,\n inputSchema: requestSandboxAccessInputSchema,\n suspendSchema: z.object({\n kind: z.literal('sandbox_access_request'),\n path: z.string(),\n reason: z.string(),\n }),\n resumeSchema: z.union([z.string(), z.array(z.string())]),\n execute: async ({ path: requestedPath, reason }: RequestSandboxAccessInput, context: any) => {\n try {\n const agentControllerCtx = context?.requestContext?.get('controller') as\n | AgentControllerRequestContext<MastraCodeState>\n | undefined;\n\n // Resolve to absolute path (expand ~ first since Node path APIs don't handle it)\n const expanded = expandTilde(requestedPath);\n const absolutePath = path.isAbsolute(expanded) ? expanded : path.resolve(
|
|
1
|
+
{"version":3,"file":"request-sandbox-access.js","names":["os","path"],"sources":["../../src/tools/request-sandbox-access.ts"],"sourcesContent":["/**\n * request_access tool — requests permission to access a directory outside the project root.\n * The user can approve or deny the request via TUI dialog.\n */\n\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport type { AgentControllerRequestContext } from '@mastra/core/agent-controller';\nimport { createTool } from '@mastra/core/tools';\nimport { LocalFilesystem } from '@mastra/core/workspace';\nimport { z } from 'zod';\nimport type { MastraCodeState } from '../schema.js';\nimport { isPathAllowed, getAllowedPathsFromContext } from './utils.js';\n\nfunction expandTilde(p: string): string {\n if (p === '~') return os.homedir();\n if (p.startsWith('~/') || p.startsWith('~\\\\')) return path.join(os.homedir(), p.slice(2));\n return p;\n}\n\ntype RequestSandboxAccessInput = {\n path: string;\n reason: string;\n};\n\nconst requestSandboxAccessInputSchema = z.object({\n path: z.string().min(1).describe('The absolute path to the directory you need access to.'),\n reason: z.string().min(1).describe('Brief explanation of why you need access to this directory.'),\n});\n\nexport const requestSandboxAccessTool = createTool({\n id: 'request_access',\n description: `Request permission to access a directory outside the current project. Use this when you need to read or write files in a directory that is not within the project root. The user will be prompted to approve or deny the request.`,\n inputSchema: requestSandboxAccessInputSchema,\n suspendSchema: z.object({\n kind: z.literal('sandbox_access_request'),\n path: z.string(),\n reason: z.string(),\n }),\n resumeSchema: z.union([z.string(), z.array(z.string())]),\n execute: async ({ path: requestedPath, reason }: RequestSandboxAccessInput, context: any) => {\n try {\n const agentControllerCtx = context?.requestContext?.get('controller') as\n | AgentControllerRequestContext<MastraCodeState>\n | undefined;\n\n // Resolve to absolute path (expand ~ first since Node path APIs don't handle it)\n const projectRoot = agentControllerCtx?.getState()?.projectPath ?? process.cwd();\n const expanded = expandTilde(requestedPath);\n const absolutePath = path.isAbsolute(expanded) ? expanded : path.resolve(projectRoot, expanded);\n\n // Check if already allowed\n const allowedPaths = getAllowedPathsFromContext(context);\n if (isPathAllowed(absolutePath, projectRoot, allowedPaths)) {\n return {\n content: `Access already granted: \"${absolutePath}\" is within the project root or allowed paths.`,\n isError: false,\n };\n }\n\n const suspend = context?.agent?.suspend ?? context?.suspend;\n const resumeData = context?.agent?.resumeData ?? context?.resumeData;\n\n // First pass: pause via the native tool-suspension primitive so the host can\n // prompt the user. The suspend payload carries the request details; the host\n // resumes with the user's answer as resume data.\n if (resumeData === undefined) {\n if (!suspend) {\n return {\n content: `Cannot request sandbox access: interactive context not available. The user should manually run /sandbox add ${absolutePath}`,\n isError: true,\n };\n }\n await suspend({ kind: 'sandbox_access_request', path: absolutePath, reason });\n return;\n }\n\n const answerText = Array.isArray(resumeData) ? resumeData.join(', ') : String(resumeData);\n const approved = answerText.toLowerCase().startsWith('y') || answerText.toLowerCase() === 'approve';\n if (approved) {\n // Persist to controller state first (and await it) so the value is\n // committed before the next tool call re-derives the workspace's\n // allowed paths from state. The workspace factory rebuilds the\n // filesystem allowlist from `sandboxAllowedPaths` on every call\n // (getDynamicWorkspace), so an unawaited setState would let that\n // rebuild clobber the in-turn widen below before the grant lands.\n const controllerState = agentControllerCtx?.getState();\n const currentAllowed = (controllerState?.sandboxAllowedPaths as string[] | undefined) ?? [];\n const nextAllowed = currentAllowed.includes(absolutePath) ? currentAllowed : [...currentAllowed, absolutePath];\n if (!currentAllowed.includes(absolutePath)) {\n await agentControllerCtx?.setState({\n sandboxAllowedPaths: nextAllowed,\n });\n }\n\n // Also update the live workspace filesystem immediately so tools in\n // the same turn (e.g. `view`) can access the path without waiting for\n // a fresh workspace build. The resolved workspace is carried on the\n // controller request context — the tool-execution context does not expose\n // it — so read the filesystem from there.\n const fs = agentControllerCtx?.workspace?.filesystem ?? context?.workspace?.filesystem;\n if (fs instanceof LocalFilesystem) {\n fs.setAllowedPaths((prev: readonly string[]) => [...prev, absolutePath]);\n }\n\n return {\n content: `Access granted: \"${absolutePath}\" has been added to allowed paths. You can now access files in this directory.`,\n isError: false,\n };\n } else {\n return {\n content: `Access denied: The user declined access to \"${absolutePath}\".`,\n isError: false,\n };\n }\n } catch (error) {\n const msg = error instanceof Error ? error.message : 'Unknown error';\n return {\n content: `Failed to request sandbox access: ${msg}`,\n isError: true,\n };\n }\n },\n} as any);\n"],"mappings":";;;;;;;;;;;AAcA,SAAS,YAAY,GAAmB;CACtC,IAAI,MAAM,KAAK,OAAOA,KAAG,QAAQ;CACjC,IAAI,EAAE,WAAW,IAAI,KAAK,EAAE,WAAW,KAAK,GAAG,OAAOC,OAAK,KAAKD,KAAG,QAAQ,GAAG,EAAE,MAAM,CAAC,CAAC;CACxF,OAAO;AACT;AAYA,MAAa,2BAA2B,WAAW;CACjD,IAAI;CACJ,aAAa;CACb,aARsC,EAAE,OAAO;EAC/C,MAAM,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,wDAAwD;EACzF,QAAQ,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,6DAA6D;CAClG,CAKe;CACb,eAAe,EAAE,OAAO;EACtB,MAAM,EAAE,QAAQ,wBAAwB;EACxC,MAAM,EAAE,OAAO;EACf,QAAQ,EAAE,OAAO;CACnB,CAAC;CACD,cAAc,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACvD,SAAS,OAAO,EAAE,MAAM,eAAe,UAAqC,YAAiB;EAC3F,IAAI;GACF,MAAM,qBAAqB,SAAS,gBAAgB,IAAI,YAAY;GAKpE,MAAM,cAAc,oBAAoB,SAAS,CAAC,EAAE,eAAe,QAAQ,IAAI;GAC/E,MAAM,WAAW,YAAY,aAAa;GAC1C,MAAM,eAAeC,OAAK,WAAW,QAAQ,IAAI,WAAWA,OAAK,QAAQ,aAAa,QAAQ;GAI9F,IAAI,cAAc,cAAc,aADX,2BAA2B,OACQ,CAAC,GACvD,OAAO;IACL,SAAS,4BAA4B,aAAa;IAClD,SAAS;GACX;GAGF,MAAM,UAAU,SAAS,OAAO,WAAW,SAAS;GACpD,MAAM,aAAa,SAAS,OAAO,cAAc,SAAS;GAK1D,IAAI,eAAe,KAAA,GAAW;IAC5B,IAAI,CAAC,SACH,OAAO;KACL,SAAS,+GAA+G;KACxH,SAAS;IACX;IAEF,MAAM,QAAQ;KAAE,MAAM;KAA0B,MAAM;KAAc;IAAO,CAAC;IAC5E;GACF;GAEA,MAAM,aAAa,MAAM,QAAQ,UAAU,IAAI,WAAW,KAAK,IAAI,IAAI,OAAO,UAAU;GAExF,IADiB,WAAW,YAAY,CAAC,CAAC,WAAW,GAAG,KAAK,WAAW,YAAY,MAAM,WAC5E;IAQZ,MAAM,kBADkB,oBAAoB,SAAS,EAAA,EACZ,uBAAgD,CAAC;IAC1F,MAAM,cAAc,eAAe,SAAS,YAAY,IAAI,iBAAiB,CAAC,GAAG,gBAAgB,YAAY;IAC7G,IAAI,CAAC,eAAe,SAAS,YAAY,GACvC,MAAM,oBAAoB,SAAS,EACjC,qBAAqB,YACvB,CAAC;IAQH,MAAM,KAAK,oBAAoB,WAAW,cAAc,SAAS,WAAW;IAC5E,IAAI,cAAc,iBAChB,GAAG,iBAAiB,SAA4B,CAAC,GAAG,MAAM,YAAY,CAAC;IAGzE,OAAO;KACL,SAAS,oBAAoB,aAAa;KAC1C,SAAS;IACX;GACF,OACE,OAAO;IACL,SAAS,+CAA+C,aAAa;IACrE,SAAS;GACX;EAEJ,SAAS,OAAO;GAEd,OAAO;IACL,SAAS,qCAFC,iBAAiB,QAAQ,MAAM,UAAU;IAGnD,SAAS;GACX;EACF;CACF;AACF,CAAQ"}
|
package/dist/utils/debug-log.js
CHANGED
|
@@ -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"}
|