@mastra/libsql 1.9.1 → 1.10.0-alpha.1
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/CHANGELOG.md +28 -0
- package/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/index.cjs +269 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +270 -3
- package/dist/index.js.map +1 -1
- package/dist/storage/domains/schedules/index.d.ts +19 -0
- package/dist/storage/domains/schedules/index.d.ts.map +1 -0
- package/dist/storage/index.d.ts +2 -1
- package/dist/storage/index.d.ts.map +1 -1
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
# @mastra/libsql
|
|
2
2
|
|
|
3
|
+
## 1.10.0-alpha.1
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Extend the schedules storage schema to support owned schedules and richer trigger audit. This is a breaking schema change to `mastra_schedules` and `mastra_schedule_triggers`; scheduled workflows are still in alpha so no compat shim is provided. ([#16166](https://github.com/mastra-ai/mastra/pull/16166))
|
|
8
|
+
- `Schedule` gains optional `ownerType` / `ownerId` so a schedule row can be attributed to an owning subsystem (e.g. an agent that owns a heartbeat schedule). Workflow schedules leave both fields unset.
|
|
9
|
+
- `ScheduleTrigger.status` is renamed to `outcome` and the type is widened to `ScheduleTriggerOutcome` so future outcome values can be added without another rename.
|
|
10
|
+
- `ScheduleTrigger` gains a stable `id` primary key and new `triggerKind`, `parentTriggerId`, and `metadata` fields. `triggerKind` distinguishes `schedule-fire` rows from later `queue-drain` rows (used by upcoming heartbeat work); `parentTriggerId` links related rows; `metadata` carries outcome-specific context.
|
|
11
|
+
- The libsql, pg, and mongodb adapters all add the new columns/indexes. Their `@mastra/core` peer dependency is tightened to `>=1.32.0-0 <2.0.0-0` so installing a new storage adapter against an older core (or vice-versa) surfaces a peer-dependency warning at install time instead of silently writing/reading the wrong field.
|
|
12
|
+
- Scheduler producer, server schemas/handler, and client SDK types are updated to use the new fields. The `triggers` response on `GET /api/schedules/:id/triggers` now returns `outcome` instead of `status`.
|
|
13
|
+
- The bundled Studio (Mastra CLI) is updated to read `outcome` so the schedule detail page keeps polling and rendering publish-failure rows correctly.
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- Updated dependencies [[`ca28c23`](https://github.com/mastra-ai/mastra/commit/ca28c232a2f18801a6cf20fe053479237b4d4fb0)]:
|
|
18
|
+
- @mastra/core@1.32.0-alpha.3
|
|
19
|
+
|
|
20
|
+
## 1.10.0-alpha.0
|
|
21
|
+
|
|
22
|
+
### Minor Changes
|
|
23
|
+
|
|
24
|
+
- Added the `schedules` storage domain so LibSQL-backed Mastra apps can use scheduled workflows. Creates `mastra_schedules` and `mastra_schedule_triggers` tables on init. ([#15830](https://github.com/mastra-ai/mastra/pull/15830))
|
|
25
|
+
|
|
26
|
+
### Patch Changes
|
|
27
|
+
|
|
28
|
+
- Updated dependencies [[`c05c9a1`](https://github.com/mastra-ai/mastra/commit/c05c9a13230988cef6d438a62f37760f31927bc7), [`e24aacb`](https://github.com/mastra-ai/mastra/commit/e24aacba07bd66f5d95b636dc24016fca26b52cf), [`c721164`](https://github.com/mastra-ai/mastra/commit/c7211643f7ac861f83b19a3757cc921487fc9d75), [`1b55954`](https://github.com/mastra-ai/mastra/commit/1b559541c1e08a10e49d01ffc51a634dfc37a286), [`5adc55e`](https://github.com/mastra-ai/mastra/commit/5adc55e63407be8ee977914957d68bcc2a075ceb), [`70017d7`](https://github.com/mastra-ai/mastra/commit/70017d72ab741b5d7040e2a15c251a317782e39e), [`e4942bc`](https://github.com/mastra-ai/mastra/commit/e4942bc7fdc903572f7d84f26d5e15f9d39c763d)]:
|
|
29
|
+
- @mastra/core@1.32.0-alpha.1
|
|
30
|
+
|
|
3
31
|
## 1.9.1
|
|
4
32
|
|
|
5
33
|
### Patch Changes
|
package/dist/docs/SKILL.md
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -8896,6 +8896,271 @@ var PromptBlocksLibSQL = class extends storage.PromptBlocksStorage {
|
|
|
8896
8896
|
};
|
|
8897
8897
|
}
|
|
8898
8898
|
};
|
|
8899
|
+
function parseJson2(val) {
|
|
8900
|
+
if (val == null) return void 0;
|
|
8901
|
+
if (typeof val === "string") {
|
|
8902
|
+
try {
|
|
8903
|
+
return JSON.parse(val);
|
|
8904
|
+
} catch {
|
|
8905
|
+
return val;
|
|
8906
|
+
}
|
|
8907
|
+
}
|
|
8908
|
+
return val;
|
|
8909
|
+
}
|
|
8910
|
+
function toNumber(val) {
|
|
8911
|
+
if (typeof val === "bigint") return Number(val);
|
|
8912
|
+
return Number(val);
|
|
8913
|
+
}
|
|
8914
|
+
function rowToSchedule(row) {
|
|
8915
|
+
const target = parseJson2(row.target);
|
|
8916
|
+
if (!target) {
|
|
8917
|
+
throw new Error(`Schedule row ${row.id} has invalid target`);
|
|
8918
|
+
}
|
|
8919
|
+
const schedule = {
|
|
8920
|
+
id: String(row.id),
|
|
8921
|
+
target,
|
|
8922
|
+
cron: String(row.cron),
|
|
8923
|
+
status: String(row.status),
|
|
8924
|
+
nextFireAt: toNumber(row.next_fire_at),
|
|
8925
|
+
createdAt: toNumber(row.created_at),
|
|
8926
|
+
updatedAt: toNumber(row.updated_at)
|
|
8927
|
+
};
|
|
8928
|
+
if (row.timezone != null) schedule.timezone = String(row.timezone);
|
|
8929
|
+
if (row.last_fire_at != null) schedule.lastFireAt = toNumber(row.last_fire_at);
|
|
8930
|
+
if (row.last_run_id != null) schedule.lastRunId = String(row.last_run_id);
|
|
8931
|
+
const metadata = parseJson2(row.metadata);
|
|
8932
|
+
if (metadata !== void 0) schedule.metadata = metadata;
|
|
8933
|
+
if (row.owner_type != null) schedule.ownerType = String(row.owner_type);
|
|
8934
|
+
if (row.owner_id != null) schedule.ownerId = String(row.owner_id);
|
|
8935
|
+
return schedule;
|
|
8936
|
+
}
|
|
8937
|
+
function rowToTrigger(row) {
|
|
8938
|
+
const trigger = {
|
|
8939
|
+
id: row.id != null ? String(row.id) : void 0,
|
|
8940
|
+
scheduleId: String(row.schedule_id),
|
|
8941
|
+
runId: row.run_id != null ? String(row.run_id) : null,
|
|
8942
|
+
scheduledFireAt: toNumber(row.scheduled_fire_at),
|
|
8943
|
+
actualFireAt: toNumber(row.actual_fire_at),
|
|
8944
|
+
outcome: String(row.outcome),
|
|
8945
|
+
triggerKind: row.trigger_kind != null ? String(row.trigger_kind) : "schedule-fire"
|
|
8946
|
+
};
|
|
8947
|
+
if (row.error != null) trigger.error = String(row.error);
|
|
8948
|
+
if (row.parent_trigger_id != null) trigger.parentTriggerId = String(row.parent_trigger_id);
|
|
8949
|
+
const metadata = parseJson2(row.metadata);
|
|
8950
|
+
if (metadata !== void 0) trigger.metadata = metadata;
|
|
8951
|
+
return trigger;
|
|
8952
|
+
}
|
|
8953
|
+
var SchedulesLibSQL = class extends storage.SchedulesStorage {
|
|
8954
|
+
#db;
|
|
8955
|
+
#client;
|
|
8956
|
+
constructor(config) {
|
|
8957
|
+
super();
|
|
8958
|
+
const client = resolveClient(config);
|
|
8959
|
+
this.#client = client;
|
|
8960
|
+
this.#db = new LibSQLDB({ client, maxRetries: config.maxRetries, initialBackoffMs: config.initialBackoffMs });
|
|
8961
|
+
}
|
|
8962
|
+
async init() {
|
|
8963
|
+
await this.#db.createTable({
|
|
8964
|
+
tableName: storage.TABLE_SCHEDULES,
|
|
8965
|
+
schema: storage.TABLE_SCHEMAS[storage.TABLE_SCHEDULES]
|
|
8966
|
+
});
|
|
8967
|
+
await this.#db.createTable({
|
|
8968
|
+
tableName: storage.TABLE_SCHEDULE_TRIGGERS,
|
|
8969
|
+
schema: storage.TABLE_SCHEMAS[storage.TABLE_SCHEDULE_TRIGGERS]
|
|
8970
|
+
});
|
|
8971
|
+
}
|
|
8972
|
+
async dangerouslyClearAll() {
|
|
8973
|
+
await this.#db.deleteData({ tableName: storage.TABLE_SCHEDULE_TRIGGERS });
|
|
8974
|
+
await this.#db.deleteData({ tableName: storage.TABLE_SCHEDULES });
|
|
8975
|
+
}
|
|
8976
|
+
async createSchedule(schedule) {
|
|
8977
|
+
const existing = await this.getSchedule(schedule.id);
|
|
8978
|
+
if (existing) {
|
|
8979
|
+
throw new Error(`Schedule with id "${schedule.id}" already exists`);
|
|
8980
|
+
}
|
|
8981
|
+
await this.#db.insert({
|
|
8982
|
+
tableName: storage.TABLE_SCHEDULES,
|
|
8983
|
+
record: {
|
|
8984
|
+
id: schedule.id,
|
|
8985
|
+
target: schedule.target,
|
|
8986
|
+
cron: schedule.cron,
|
|
8987
|
+
timezone: schedule.timezone ?? null,
|
|
8988
|
+
status: schedule.status,
|
|
8989
|
+
next_fire_at: schedule.nextFireAt,
|
|
8990
|
+
last_fire_at: schedule.lastFireAt ?? null,
|
|
8991
|
+
last_run_id: schedule.lastRunId ?? null,
|
|
8992
|
+
created_at: schedule.createdAt,
|
|
8993
|
+
updated_at: schedule.updatedAt,
|
|
8994
|
+
metadata: schedule.metadata ?? null,
|
|
8995
|
+
owner_type: schedule.ownerType ?? null,
|
|
8996
|
+
owner_id: schedule.ownerId ?? null
|
|
8997
|
+
}
|
|
8998
|
+
});
|
|
8999
|
+
return schedule;
|
|
9000
|
+
}
|
|
9001
|
+
async getSchedule(id) {
|
|
9002
|
+
const result = await this.#client.execute({
|
|
9003
|
+
sql: `SELECT ${buildSelectColumns(storage.TABLE_SCHEDULES)} FROM ${storage.TABLE_SCHEDULES} WHERE id = ?`,
|
|
9004
|
+
args: [id]
|
|
9005
|
+
});
|
|
9006
|
+
const row = result.rows[0];
|
|
9007
|
+
return row ? rowToSchedule(row) : null;
|
|
9008
|
+
}
|
|
9009
|
+
async listSchedules(filter) {
|
|
9010
|
+
const conditions = [];
|
|
9011
|
+
const params = [];
|
|
9012
|
+
if (filter?.status) {
|
|
9013
|
+
conditions.push("status = ?");
|
|
9014
|
+
params.push(filter.status);
|
|
9015
|
+
}
|
|
9016
|
+
if (filter?.workflowId) {
|
|
9017
|
+
conditions.push("json_extract(target, '$.workflowId') = ?");
|
|
9018
|
+
params.push(filter.workflowId);
|
|
9019
|
+
}
|
|
9020
|
+
if (filter?.ownerType !== void 0) {
|
|
9021
|
+
if (filter.ownerType === null) {
|
|
9022
|
+
conditions.push("owner_type IS NULL");
|
|
9023
|
+
} else {
|
|
9024
|
+
conditions.push("owner_type = ?");
|
|
9025
|
+
params.push(filter.ownerType);
|
|
9026
|
+
}
|
|
9027
|
+
}
|
|
9028
|
+
if (filter?.ownerId !== void 0) {
|
|
9029
|
+
if (filter.ownerId === null) {
|
|
9030
|
+
conditions.push("owner_id IS NULL");
|
|
9031
|
+
} else {
|
|
9032
|
+
conditions.push("owner_id = ?");
|
|
9033
|
+
params.push(filter.ownerId);
|
|
9034
|
+
}
|
|
9035
|
+
}
|
|
9036
|
+
const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
9037
|
+
const result = await this.#client.execute({
|
|
9038
|
+
sql: `SELECT ${buildSelectColumns(storage.TABLE_SCHEDULES)} FROM ${storage.TABLE_SCHEDULES} ${where} ORDER BY created_at ASC`,
|
|
9039
|
+
args: params
|
|
9040
|
+
});
|
|
9041
|
+
return result.rows.map((r) => rowToSchedule(r));
|
|
9042
|
+
}
|
|
9043
|
+
async listDueSchedules(now, limit) {
|
|
9044
|
+
const cap = limit ?? 100;
|
|
9045
|
+
const result = await this.#client.execute({
|
|
9046
|
+
sql: `SELECT ${buildSelectColumns(storage.TABLE_SCHEDULES)} FROM ${storage.TABLE_SCHEDULES}
|
|
9047
|
+
WHERE status = ? AND next_fire_at <= ?
|
|
9048
|
+
ORDER BY next_fire_at ASC
|
|
9049
|
+
LIMIT ?`,
|
|
9050
|
+
args: ["active", now, cap]
|
|
9051
|
+
});
|
|
9052
|
+
return result.rows.map((r) => rowToSchedule(r));
|
|
9053
|
+
}
|
|
9054
|
+
async updateSchedule(id, patch) {
|
|
9055
|
+
const setClauses = [];
|
|
9056
|
+
const params = [];
|
|
9057
|
+
if ("cron" in patch && patch.cron !== void 0) {
|
|
9058
|
+
setClauses.push("cron = ?");
|
|
9059
|
+
params.push(patch.cron);
|
|
9060
|
+
}
|
|
9061
|
+
if ("timezone" in patch) {
|
|
9062
|
+
setClauses.push("timezone = ?");
|
|
9063
|
+
params.push(patch.timezone ?? null);
|
|
9064
|
+
}
|
|
9065
|
+
if ("status" in patch && patch.status !== void 0) {
|
|
9066
|
+
setClauses.push("status = ?");
|
|
9067
|
+
params.push(patch.status);
|
|
9068
|
+
}
|
|
9069
|
+
if ("nextFireAt" in patch && patch.nextFireAt !== void 0) {
|
|
9070
|
+
setClauses.push("next_fire_at = ?");
|
|
9071
|
+
params.push(patch.nextFireAt);
|
|
9072
|
+
}
|
|
9073
|
+
if ("target" in patch && patch.target !== void 0) {
|
|
9074
|
+
setClauses.push("target = jsonb(?)");
|
|
9075
|
+
params.push(JSON.stringify(patch.target));
|
|
9076
|
+
}
|
|
9077
|
+
if ("metadata" in patch) {
|
|
9078
|
+
setClauses.push("metadata = jsonb(?)");
|
|
9079
|
+
params.push(patch.metadata != null ? JSON.stringify(patch.metadata) : null);
|
|
9080
|
+
}
|
|
9081
|
+
if ("ownerType" in patch) {
|
|
9082
|
+
setClauses.push("owner_type = ?");
|
|
9083
|
+
params.push(patch.ownerType ?? null);
|
|
9084
|
+
}
|
|
9085
|
+
if ("ownerId" in patch) {
|
|
9086
|
+
setClauses.push("owner_id = ?");
|
|
9087
|
+
params.push(patch.ownerId ?? null);
|
|
9088
|
+
}
|
|
9089
|
+
setClauses.push("updated_at = ?");
|
|
9090
|
+
params.push(Date.now());
|
|
9091
|
+
params.push(id);
|
|
9092
|
+
if (setClauses.length === 1) {
|
|
9093
|
+
const existing = await this.getSchedule(id);
|
|
9094
|
+
if (!existing) throw new Error(`Schedule ${id} not found`);
|
|
9095
|
+
return existing;
|
|
9096
|
+
}
|
|
9097
|
+
await this.#client.execute({
|
|
9098
|
+
sql: `UPDATE ${storage.TABLE_SCHEDULES} SET ${setClauses.join(", ")} WHERE id = ?`,
|
|
9099
|
+
args: params
|
|
9100
|
+
});
|
|
9101
|
+
const updated = await this.getSchedule(id);
|
|
9102
|
+
if (!updated) throw new Error(`Schedule ${id} not found`);
|
|
9103
|
+
return updated;
|
|
9104
|
+
}
|
|
9105
|
+
async updateScheduleNextFire(id, expectedNextFireAt, newNextFireAt, lastFireAt, lastRunId) {
|
|
9106
|
+
const result = await this.#client.execute({
|
|
9107
|
+
sql: `UPDATE ${storage.TABLE_SCHEDULES}
|
|
9108
|
+
SET next_fire_at = ?, last_fire_at = ?, last_run_id = ?, updated_at = ?
|
|
9109
|
+
WHERE id = ? AND next_fire_at = ? AND status = ?`,
|
|
9110
|
+
args: [newNextFireAt, lastFireAt, lastRunId, Date.now(), id, expectedNextFireAt, "active"]
|
|
9111
|
+
});
|
|
9112
|
+
return (result.rowsAffected ?? 0) > 0;
|
|
9113
|
+
}
|
|
9114
|
+
async deleteSchedule(id) {
|
|
9115
|
+
await this.#client.execute({
|
|
9116
|
+
sql: `DELETE FROM ${storage.TABLE_SCHEDULE_TRIGGERS} WHERE schedule_id = ?`,
|
|
9117
|
+
args: [id]
|
|
9118
|
+
});
|
|
9119
|
+
await this.#client.execute({
|
|
9120
|
+
sql: `DELETE FROM ${storage.TABLE_SCHEDULES} WHERE id = ?`,
|
|
9121
|
+
args: [id]
|
|
9122
|
+
});
|
|
9123
|
+
}
|
|
9124
|
+
async recordTrigger(trigger) {
|
|
9125
|
+
const id = trigger.id ?? crypto.randomUUID();
|
|
9126
|
+
await this.#db.insert({
|
|
9127
|
+
tableName: storage.TABLE_SCHEDULE_TRIGGERS,
|
|
9128
|
+
record: {
|
|
9129
|
+
id,
|
|
9130
|
+
schedule_id: trigger.scheduleId,
|
|
9131
|
+
run_id: trigger.runId,
|
|
9132
|
+
scheduled_fire_at: trigger.scheduledFireAt,
|
|
9133
|
+
actual_fire_at: trigger.actualFireAt,
|
|
9134
|
+
outcome: trigger.outcome,
|
|
9135
|
+
error: trigger.error ?? null,
|
|
9136
|
+
trigger_kind: trigger.triggerKind ?? "schedule-fire",
|
|
9137
|
+
parent_trigger_id: trigger.parentTriggerId ?? null,
|
|
9138
|
+
metadata: trigger.metadata ?? null
|
|
9139
|
+
}
|
|
9140
|
+
});
|
|
9141
|
+
}
|
|
9142
|
+
async listTriggers(scheduleId, opts) {
|
|
9143
|
+
const conditions = ["schedule_id = ?"];
|
|
9144
|
+
const params = [scheduleId];
|
|
9145
|
+
if (opts?.fromActualFireAt != null) {
|
|
9146
|
+
conditions.push("actual_fire_at >= ?");
|
|
9147
|
+
params.push(opts.fromActualFireAt);
|
|
9148
|
+
}
|
|
9149
|
+
if (opts?.toActualFireAt != null) {
|
|
9150
|
+
conditions.push("actual_fire_at < ?");
|
|
9151
|
+
params.push(opts.toActualFireAt);
|
|
9152
|
+
}
|
|
9153
|
+
const limitClause = opts?.limit != null ? `LIMIT ${Math.floor(opts.limit)}` : "";
|
|
9154
|
+
const result = await this.#client.execute({
|
|
9155
|
+
sql: `SELECT ${buildSelectColumns(storage.TABLE_SCHEDULE_TRIGGERS)} FROM ${storage.TABLE_SCHEDULE_TRIGGERS}
|
|
9156
|
+
WHERE ${conditions.join(" AND ")}
|
|
9157
|
+
ORDER BY actual_fire_at DESC
|
|
9158
|
+
${limitClause}`,
|
|
9159
|
+
args: params
|
|
9160
|
+
});
|
|
9161
|
+
return result.rows.map((r) => rowToTrigger(r));
|
|
9162
|
+
}
|
|
9163
|
+
};
|
|
8899
9164
|
var ScorerDefinitionsLibSQL = class extends storage.ScorerDefinitionsStorage {
|
|
8900
9165
|
#db;
|
|
8901
9166
|
#client;
|
|
@@ -11127,6 +11392,7 @@ var LibSQLStore = class extends storage.MastraCompositeStore {
|
|
|
11127
11392
|
const skills = new SkillsLibSQL(domainConfig);
|
|
11128
11393
|
const blobs = new BlobsLibSQL(domainConfig);
|
|
11129
11394
|
const backgroundTasks = new BackgroundTasksLibSQL(domainConfig);
|
|
11395
|
+
const schedules = new SchedulesLibSQL(domainConfig);
|
|
11130
11396
|
this.stores = {
|
|
11131
11397
|
scores,
|
|
11132
11398
|
workflows,
|
|
@@ -11143,7 +11409,8 @@ var LibSQLStore = class extends storage.MastraCompositeStore {
|
|
|
11143
11409
|
workspaces,
|
|
11144
11410
|
skills,
|
|
11145
11411
|
blobs,
|
|
11146
|
-
backgroundTasks
|
|
11412
|
+
backgroundTasks,
|
|
11413
|
+
schedules
|
|
11147
11414
|
};
|
|
11148
11415
|
}
|
|
11149
11416
|
};
|
|
@@ -11262,6 +11529,7 @@ exports.MCPServersLibSQL = MCPServersLibSQL;
|
|
|
11262
11529
|
exports.MemoryLibSQL = MemoryLibSQL;
|
|
11263
11530
|
exports.ObservabilityLibSQL = ObservabilityLibSQL;
|
|
11264
11531
|
exports.PromptBlocksLibSQL = PromptBlocksLibSQL;
|
|
11532
|
+
exports.SchedulesLibSQL = SchedulesLibSQL;
|
|
11265
11533
|
exports.ScorerDefinitionsLibSQL = ScorerDefinitionsLibSQL;
|
|
11266
11534
|
exports.ScoresLibSQL = ScoresLibSQL;
|
|
11267
11535
|
exports.SkillsLibSQL = SkillsLibSQL;
|