@mastra/libsql 1.24.0-alpha.1 → 1.24.0-alpha.3

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.
@@ -3,7 +3,7 @@ name: mastra-libsql
3
3
  description: Documentation for @mastra/libsql. Use when working with @mastra/libsql APIs, configuration, or implementation.
4
4
  metadata:
5
5
  package: "@mastra/libsql"
6
- version: "1.24.0-alpha.1"
6
+ version: "1.24.0-alpha.3"
7
7
  ---
8
8
 
9
9
  ## When to use
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.24.0-alpha.1",
2
+ "version": "1.24.0-alpha.3",
3
3
  "package": "@mastra/libsql",
4
4
  "exports": {},
5
5
  "modules": {}
@@ -120,12 +120,14 @@ The function can be asynchronous. For decisions that depend on the tool name and
120
120
 
121
121
  ```typescript
122
122
  import { Classifier } from '@mastra/core/classifier'
123
- import { model } from '../models/evaluation-model'
123
+ import { createTypeSafeAi } from '@ai-sdk/typesafe-ai'
124
124
  import { agent } from './agent'
125
125
 
126
126
  const approvalClassifier = new Classifier({
127
127
  id: 'tool-approval-classifier',
128
- model,
128
+ model: createTypeSafeAi({ apiKey: process.env.TYPESAFE_AI_API_KEY }).evaluationModel(
129
+ 'jev-latest',
130
+ ),
129
131
  questions: {
130
132
  requiresApproval: {
131
133
  type: 'boolean',
@@ -35,7 +35,10 @@ The orchestration worker requires a PubSub backend that supports pull mode (e.g.
35
35
 
36
36
  ### Scheduler worker
37
37
 
38
- Polls storage for due cron schedules and publishes `workflow.start` events. It's a producer only, meaning it creates work for the orchestration worker to pick up.
38
+ Polls storage for due cron schedules and publishes a `workflow.start` event for each fire. It's a producer only, meaning it creates work for the orchestration worker to pick up:
39
+
40
+ - **Split processes**: Scheduled workflows run on the evented engine, and the orchestration worker runs each fire step by step.
41
+ - **In-process mode**: Scheduled workflows run on the default engine. The orchestration worker in the same process runs each fire in-process, the same way a direct `run.start()` does.
39
42
 
40
43
  The scheduler reads declarative `schedule` fields from your workflow definitions automatically. See [Scheduled workflows](https://mastra.ai/docs/workflows/scheduled-workflows) for how to declare schedules.
41
44
 
@@ -132,6 +135,8 @@ You can also pass a worker name to the CLI. The command sets `MASTRA_WORKERS` in
132
135
  mastra worker start orchestration
133
136
  ```
134
137
 
138
+ Set `MASTRA_WORKERS` on every process in a split deployment, including `false` on the API process. Any value switches workflows that declare `schedule` to the evented engine, and every process must run those workflows on the same engine. See [Scheduled workflows](https://mastra.ai/docs/workflows/scheduled-workflows). `mastra worker start` without a worker name doesn't set `MASTRA_WORKERS`, so pass a name or set the variable in the process environment.
139
+
135
140
  ## Network architecture
136
141
 
137
142
  Workers are internal infrastructure. They're not exposed to end users and don't need their own subdomain or public URL, including an inbound HTTP route.
@@ -142,7 +147,7 @@ In a split deployment:
142
147
  - **Workers connect outbound only**: They pull events from the distributed PubSub backend and read/write to the shared storage database. They don't accept inbound traffic from clients.
143
148
  - **The orchestration worker calls the API internally**: It sends step execution requests to the API over the container network using `MASTRA_STEP_EXECUTION_URL`. This is internal service-to-service communication, not a public endpoint.
144
149
 
145
- All three worker types (orchestration, scheduler, background task) sit behind the API on a private network. They share access to the PubSub backend and storage database but never receive traffic directly from clients. HTTP routes for worker-related features run on the API server rather than the worker process. One example is token minting for a voice integration.
150
+ All three worker types (orchestration, scheduler, background task) sit behind the API on a private network. They share access to the PubSub backend and storage database but never receive traffic directly from clients. HTTP routes for worker-related features run on the API server rather than the worker process. One example is creating a token for a voice integration.
146
151
 
147
152
  ## Deploy split workers
148
153
 
@@ -202,7 +202,7 @@ Each delegation creates a fresh `threadId` and a deterministic `resourceId` for
202
202
 
203
203
  > **Note:** Title generation (`generateTitle`) is a top-level thread concern and **isn't** applied to inherited subagent threads. Because each delegation creates an ephemeral thread that no one sees, running title generation for it would waste an LLM call per delegation. To generate titles for a subagent's own threads, give that subagent its own memory configuration.
204
204
 
205
- The supervisor forwards its conversation context to the subagent so it has enough background to complete the task. Only the delegation prompt and the subagent's response are saved; the full parent conversation isn't stored. You can control which messages reach the subagent with the [`messageFilter`](https://mastra.ai/docs/subagents) callback.
205
+ The supervisor forwards its conversation context to the subagent so it has enough background to complete the task. Only the delegation prompt and the subagent's response are saved. The full parent conversation isn't stored. You can control which messages reach the subagent with the [`messageFilter`](https://mastra.ai/docs/subagents) callback.
206
206
 
207
207
  > **Note:** Subagent resource IDs are always suffixed with the agent name (`{parentResourceId}-{agentName}`). Different subagents under the same supervisor never share a resource ID through delegation.
208
208
 
@@ -202,7 +202,7 @@ async function retentionTick() {
202
202
  }
203
203
  ```
204
204
 
205
- You can also cancel a long-running prune with an `AbortSignal`: the loop stops between batches and returns partial results with `done: false`, so the next run resumes cleanly.
205
+ You can also cancel a long-running prune with an `AbortSignal`: the loop stops between batches and returns partial results with `done: false`. The next run resumes cleanly.
206
206
 
207
207
  ## ClickHouse native TTL
208
208
 
package/dist/index.cjs CHANGED
@@ -424,9 +424,14 @@ function handleLogicalOperator(key, value, parentPath) {
424
424
  }
425
425
  const values = [];
426
426
  const joinOperator = key === "$or" || key === "$nor" ? "OR" : "AND";
427
- const joined = (Array.isArray(value) ? value.map((f) => {
428
- return (!!f ? Object.entries(f) : []).map(([k, v]) => buildCondition$1(k, v, key));
429
- }) : [buildCondition$1(key, value, parentPath)]).flat().map((c) => {
427
+ const joined = (Array.isArray(value) ? value.flatMap((f) => {
428
+ const branch = (!!f ? Object.entries(f) : []).map(([k, v]) => buildCondition$1(k, v, key));
429
+ if (branch.length <= 1) return branch;
430
+ return [{
431
+ sql: `(${branch.map((c) => c.sql).join(" AND ")})`,
432
+ values: branch.flatMap((c) => c.values)
433
+ }];
434
+ }) : [buildCondition$1(key, value, parentPath)]).map((c) => {
430
435
  values.push(...c.values);
431
436
  return c.sql;
432
437
  }).join(` ${joinOperator} `);
@@ -11227,6 +11232,7 @@ var SchedulesLibSQL = class SchedulesLibSQL extends _mastra_core_storage.Schedul
11227
11232
  });
11228
11233
  }
11229
11234
  async init() {
11235
+ await this.#migrateLegacyTriggersTable();
11230
11236
  await this.#db.createTable({
11231
11237
  tableName: _mastra_core_storage.TABLE_SCHEDULES,
11232
11238
  schema: _mastra_core_storage.TABLE_SCHEMAS[_mastra_core_storage.TABLE_SCHEDULES]
@@ -11235,6 +11241,15 @@ var SchedulesLibSQL = class SchedulesLibSQL extends _mastra_core_storage.Schedul
11235
11241
  tableName: _mastra_core_storage.TABLE_SCHEDULE_TRIGGERS,
11236
11242
  schema: _mastra_core_storage.TABLE_SCHEMAS[_mastra_core_storage.TABLE_SCHEDULE_TRIGGERS]
11237
11243
  });
11244
+ try {
11245
+ await this.#db.alterTable({
11246
+ tableName: _mastra_core_storage.TABLE_SCHEDULES,
11247
+ schema: _mastra_core_storage.TABLE_SCHEMAS[_mastra_core_storage.TABLE_SCHEDULES],
11248
+ ifNotExists: ["owner_type", "owner_id"]
11249
+ });
11250
+ } catch (error) {
11251
+ if (!(await this.#db.hasColumn(_mastra_core_storage.TABLE_SCHEDULES, "owner_type") && await this.#db.hasColumn(_mastra_core_storage.TABLE_SCHEDULES, "owner_id"))) throw error;
11252
+ }
11238
11253
  await this.#client.batch([{
11239
11254
  sql: `CREATE INDEX IF NOT EXISTS idx_schedules_status_next_fire ON "${_mastra_core_storage.TABLE_SCHEDULES}" ("status", "next_fire_at")`,
11240
11255
  args: []
@@ -11243,6 +11258,42 @@ var SchedulesLibSQL = class SchedulesLibSQL extends _mastra_core_storage.Schedul
11243
11258
  args: []
11244
11259
  }], "write");
11245
11260
  }
11261
+ /**
11262
+ * Trigger tables created before the ownership/audit schema change are keyed
11263
+ * by `run_id` (NOT NULL) and store `status` instead of `outcome`. SQLite
11264
+ * cannot change a primary key or rename-and-retype in place, so the table is
11265
+ * rebuilt in the current shape inside one write transaction. Legacy run ids
11266
+ * are unique, so they become the new row ids.
11267
+ */
11268
+ async #migrateLegacyTriggersTable() {
11269
+ const isLegacy = async () => await this.#db.hasColumn(_mastra_core_storage.TABLE_SCHEDULE_TRIGGERS, "status") && !await this.#db.hasColumn(_mastra_core_storage.TABLE_SCHEDULE_TRIGGERS, "outcome");
11270
+ if (!await isLegacy()) return;
11271
+ const shadow = `${_mastra_core_storage.TABLE_SCHEDULE_TRIGGERS}__legacy_rebuild`;
11272
+ try {
11273
+ await this.#client.batch([
11274
+ `DROP TABLE IF EXISTS "${shadow}"`,
11275
+ `CREATE TABLE "${shadow}" (
11276
+ "id" TEXT NOT NULL PRIMARY KEY,
11277
+ "schedule_id" TEXT NOT NULL,
11278
+ "run_id" TEXT,
11279
+ "scheduled_fire_at" INTEGER NOT NULL,
11280
+ "actual_fire_at" INTEGER NOT NULL,
11281
+ "outcome" TEXT NOT NULL,
11282
+ "error" TEXT,
11283
+ "trigger_kind" TEXT NOT NULL,
11284
+ "parent_trigger_id" TEXT,
11285
+ "metadata" TEXT
11286
+ )`,
11287
+ `INSERT INTO "${shadow}" ("id", "schedule_id", "run_id", "scheduled_fire_at", "actual_fire_at", "outcome", "error", "trigger_kind")
11288
+ SELECT "run_id", "schedule_id", "run_id", "scheduled_fire_at", "actual_fire_at", "status", "error", 'schedule-fire'
11289
+ FROM "${_mastra_core_storage.TABLE_SCHEDULE_TRIGGERS}"`,
11290
+ `DROP TABLE "${_mastra_core_storage.TABLE_SCHEDULE_TRIGGERS}"`,
11291
+ `ALTER TABLE "${shadow}" RENAME TO "${_mastra_core_storage.TABLE_SCHEDULE_TRIGGERS}"`
11292
+ ], "write");
11293
+ } catch (error) {
11294
+ if (await isLegacy()) throw error;
11295
+ }
11296
+ }
11246
11297
  async dangerouslyClearAll() {
11247
11298
  await this.#db.deleteData({ tableName: _mastra_core_storage.TABLE_SCHEDULE_TRIGGERS });
11248
11299
  await this.#db.deleteData({ tableName: _mastra_core_storage.TABLE_SCHEDULES });