@mastra/libsql 1.4.0 → 1.5.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.
- package/CHANGELOG.md +144 -0
- package/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/index.cjs +1523 -484
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1522 -486
- package/dist/index.js.map +1 -1
- package/dist/storage/db/utils.d.ts.map +1 -1
- package/dist/storage/domains/agents/index.d.ts.map +1 -1
- package/dist/storage/domains/blobs/index.d.ts +17 -0
- package/dist/storage/domains/blobs/index.d.ts.map +1 -0
- package/dist/storage/domains/datasets/index.d.ts.map +1 -1
- package/dist/storage/domains/mcp-clients/index.d.ts.map +1 -1
- package/dist/storage/domains/prompt-blocks/index.d.ts.map +1 -1
- package/dist/storage/domains/scorer-definitions/index.d.ts.map +1 -1
- package/dist/storage/domains/skills/index.d.ts +26 -0
- package/dist/storage/domains/skills/index.d.ts.map +1 -0
- package/dist/storage/domains/workspaces/index.d.ts +26 -0
- package/dist/storage/domains/workspaces/index.d.ts.map +1 -0
- package/dist/storage/index.d.ts +4 -1
- package/dist/storage/index.d.ts.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createClient } from '@libsql/client';
|
|
2
2
|
import { MastraError, ErrorCategory, ErrorDomain } from '@mastra/core/error';
|
|
3
|
-
import { createVectorErrorId, AgentsStorage, AGENTS_SCHEMA, TABLE_AGENTS, AGENT_VERSIONS_SCHEMA, TABLE_AGENT_VERSIONS, createStorageErrorId, normalizePerPage, calculatePagination, DatasetsStorage, DATASETS_SCHEMA, TABLE_DATASETS, DATASET_ITEMS_SCHEMA, TABLE_DATASET_ITEMS, DATASET_VERSIONS_SCHEMA, TABLE_DATASET_VERSIONS, ensureDate, safelyParseJSON, TABLE_EXPERIMENT_RESULTS, TABLE_EXPERIMENTS, ExperimentsStorage, EXPERIMENTS_SCHEMA, EXPERIMENT_RESULTS_SCHEMA, MCPClientsStorage, MCP_CLIENTS_SCHEMA, TABLE_MCP_CLIENTS, MCP_CLIENT_VERSIONS_SCHEMA, TABLE_MCP_CLIENT_VERSIONS, MemoryStorage, TABLE_SCHEMAS, TABLE_THREADS, TABLE_MESSAGES, TABLE_RESOURCES, ObservabilityStorage, SPAN_SCHEMA, TABLE_SPANS, listTracesArgsSchema, toTraceSpans, PromptBlocksStorage, PROMPT_BLOCKS_SCHEMA, TABLE_PROMPT_BLOCKS, PROMPT_BLOCK_VERSIONS_SCHEMA, TABLE_PROMPT_BLOCK_VERSIONS, ScorerDefinitionsStorage, SCORER_DEFINITIONS_SCHEMA, TABLE_SCORER_DEFINITIONS, SCORER_DEFINITION_VERSIONS_SCHEMA, TABLE_SCORER_DEFINITION_VERSIONS, ScoresStorage, SCORERS_SCHEMA, TABLE_SCORERS, transformScoreRow, WorkflowsStorage, TABLE_WORKFLOW_SNAPSHOT, MastraCompositeStore, TraceStatus, getSqlType } from '@mastra/core/storage';
|
|
3
|
+
import { createVectorErrorId, AgentsStorage, AGENTS_SCHEMA, TABLE_AGENTS, AGENT_VERSIONS_SCHEMA, TABLE_AGENT_VERSIONS, createStorageErrorId, normalizePerPage, calculatePagination, BlobStore, TABLE_SKILL_BLOBS, SKILL_BLOBS_SCHEMA, DatasetsStorage, DATASETS_SCHEMA, TABLE_DATASETS, DATASET_ITEMS_SCHEMA, TABLE_DATASET_ITEMS, DATASET_VERSIONS_SCHEMA, TABLE_DATASET_VERSIONS, ensureDate, safelyParseJSON, TABLE_EXPERIMENT_RESULTS, TABLE_EXPERIMENTS, ExperimentsStorage, EXPERIMENTS_SCHEMA, EXPERIMENT_RESULTS_SCHEMA, MCPClientsStorage, MCP_CLIENTS_SCHEMA, TABLE_MCP_CLIENTS, MCP_CLIENT_VERSIONS_SCHEMA, TABLE_MCP_CLIENT_VERSIONS, MemoryStorage, TABLE_SCHEMAS, TABLE_THREADS, TABLE_MESSAGES, TABLE_RESOURCES, ObservabilityStorage, SPAN_SCHEMA, TABLE_SPANS, listTracesArgsSchema, toTraceSpans, PromptBlocksStorage, PROMPT_BLOCKS_SCHEMA, TABLE_PROMPT_BLOCKS, PROMPT_BLOCK_VERSIONS_SCHEMA, TABLE_PROMPT_BLOCK_VERSIONS, ScorerDefinitionsStorage, SCORER_DEFINITIONS_SCHEMA, TABLE_SCORER_DEFINITIONS, SCORER_DEFINITION_VERSIONS_SCHEMA, TABLE_SCORER_DEFINITION_VERSIONS, ScoresStorage, SCORERS_SCHEMA, TABLE_SCORERS, transformScoreRow, SkillsStorage, SKILLS_SCHEMA, TABLE_SKILLS, SKILL_VERSIONS_SCHEMA, TABLE_SKILL_VERSIONS, WorkflowsStorage, TABLE_WORKFLOW_SNAPSHOT, WorkspacesStorage, WORKSPACES_SCHEMA, TABLE_WORKSPACES, WORKSPACE_VERSIONS_SCHEMA, TABLE_WORKSPACE_VERSIONS, MastraCompositeStore, TraceStatus, getSqlType } from '@mastra/core/storage';
|
|
4
4
|
import { parseSqlIdentifier, parseFieldKey } from '@mastra/core/utils';
|
|
5
5
|
import { MastraVector, validateTopK, validateUpsertInput } from '@mastra/core/vector';
|
|
6
6
|
import { BaseFilterTranslator } from '@mastra/core/vector/filter';
|
|
@@ -1092,7 +1092,7 @@ function buildSelectColumns(tableName) {
|
|
|
1092
1092
|
return Object.keys(schema).map((col) => {
|
|
1093
1093
|
const colDef = schema[col];
|
|
1094
1094
|
const parsedCol = parseSqlIdentifier(col, "column name");
|
|
1095
|
-
return colDef?.type === "jsonb" ? `json(${parsedCol}) as ${parsedCol}` : parsedCol
|
|
1095
|
+
return colDef?.type === "jsonb" ? `json("${parsedCol}") as "${parsedCol}"` : `"${parsedCol}"`;
|
|
1096
1096
|
}).join(", ");
|
|
1097
1097
|
}
|
|
1098
1098
|
function isLockError(error) {
|
|
@@ -2053,23 +2053,6 @@ Note: This migration may take some time for large tables.
|
|
|
2053
2053
|
};
|
|
2054
2054
|
|
|
2055
2055
|
// src/storage/domains/agents/index.ts
|
|
2056
|
-
var SNAPSHOT_FIELDS = [
|
|
2057
|
-
"name",
|
|
2058
|
-
"description",
|
|
2059
|
-
"instructions",
|
|
2060
|
-
"model",
|
|
2061
|
-
"tools",
|
|
2062
|
-
"defaultOptions",
|
|
2063
|
-
"workflows",
|
|
2064
|
-
"agents",
|
|
2065
|
-
"integrationTools",
|
|
2066
|
-
"inputProcessors",
|
|
2067
|
-
"outputProcessors",
|
|
2068
|
-
"memory",
|
|
2069
|
-
"scorers",
|
|
2070
|
-
"mcpClients",
|
|
2071
|
-
"requestContextSchema"
|
|
2072
|
-
];
|
|
2073
2056
|
var AgentsLibSQL = class extends AgentsStorage {
|
|
2074
2057
|
#db;
|
|
2075
2058
|
#client;
|
|
@@ -2089,6 +2072,11 @@ var AgentsLibSQL = class extends AgentsStorage {
|
|
|
2089
2072
|
schema: AGENTS_SCHEMA,
|
|
2090
2073
|
ifNotExists: ["status", "authorId"]
|
|
2091
2074
|
});
|
|
2075
|
+
await this.#db.alterTable({
|
|
2076
|
+
tableName: TABLE_AGENT_VERSIONS,
|
|
2077
|
+
schema: AGENT_VERSIONS_SCHEMA,
|
|
2078
|
+
ifNotExists: ["mcpClients", "requestContextSchema", "workspace", "skills", "skillsFormat"]
|
|
2079
|
+
});
|
|
2092
2080
|
await this.#migrateToolsToJsonbFormat();
|
|
2093
2081
|
await this.#cleanupStaleDrafts();
|
|
2094
2082
|
}
|
|
@@ -2360,8 +2348,8 @@ var AgentsLibSQL = class extends AgentsStorage {
|
|
|
2360
2348
|
async update(input) {
|
|
2361
2349
|
const { id, ...updates } = input;
|
|
2362
2350
|
try {
|
|
2363
|
-
const
|
|
2364
|
-
if (!
|
|
2351
|
+
const existing = await this.getById(id);
|
|
2352
|
+
if (!existing) {
|
|
2365
2353
|
throw new MastraError({
|
|
2366
2354
|
id: createStorageErrorId("LIBSQL", "UPDATE_AGENT", "NOT_FOUND"),
|
|
2367
2355
|
domain: ErrorDomain.STORAGE,
|
|
@@ -2370,68 +2358,21 @@ var AgentsLibSQL = class extends AgentsStorage {
|
|
|
2370
2358
|
details: { agentId: id }
|
|
2371
2359
|
});
|
|
2372
2360
|
}
|
|
2373
|
-
const
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
metadata: updates.metadata
|
|
2377
|
-
};
|
|
2378
|
-
const configFields = {};
|
|
2379
|
-
for (const field of SNAPSHOT_FIELDS) {
|
|
2380
|
-
if (updates[field] !== void 0) {
|
|
2381
|
-
configFields[field] = updates[field];
|
|
2382
|
-
}
|
|
2383
|
-
}
|
|
2384
|
-
if (Object.keys(configFields).length > 0) {
|
|
2385
|
-
const latestVersion = await this.getLatestVersion(id);
|
|
2386
|
-
const nextVersionNumber = latestVersion ? latestVersion.versionNumber + 1 : 1;
|
|
2387
|
-
if (!latestVersion) {
|
|
2388
|
-
throw new MastraError({
|
|
2389
|
-
id: createStorageErrorId("LIBSQL", "UPDATE_AGENT", "NO_VERSION"),
|
|
2390
|
-
domain: ErrorDomain.STORAGE,
|
|
2391
|
-
category: ErrorCategory.USER,
|
|
2392
|
-
text: `Cannot update config fields for agent ${id} - no versions exist`,
|
|
2393
|
-
details: { id }
|
|
2394
|
-
});
|
|
2395
|
-
}
|
|
2396
|
-
const latestSnapshot = {};
|
|
2397
|
-
for (const field of SNAPSHOT_FIELDS) {
|
|
2398
|
-
if (latestVersion[field] !== void 0) {
|
|
2399
|
-
latestSnapshot[field] = latestVersion[field];
|
|
2400
|
-
}
|
|
2401
|
-
}
|
|
2402
|
-
const sanitizedConfigFields = Object.fromEntries(
|
|
2403
|
-
Object.entries(configFields).map(([key, value]) => [key, value === null ? void 0 : value])
|
|
2404
|
-
);
|
|
2405
|
-
const versionInput = {
|
|
2406
|
-
id: crypto.randomUUID(),
|
|
2407
|
-
agentId: id,
|
|
2408
|
-
versionNumber: nextVersionNumber,
|
|
2409
|
-
...latestSnapshot,
|
|
2410
|
-
// Start from latest version
|
|
2411
|
-
...sanitizedConfigFields,
|
|
2412
|
-
// Apply updates (null values converted to undefined)
|
|
2413
|
-
changedFields: Object.keys(configFields),
|
|
2414
|
-
changeMessage: `Updated: ${Object.keys(configFields).join(", ")}`
|
|
2415
|
-
};
|
|
2416
|
-
await this.createVersion(versionInput);
|
|
2417
|
-
}
|
|
2418
|
-
const data = {
|
|
2419
|
-
updatedAt: /* @__PURE__ */ new Date()
|
|
2361
|
+
const { authorId, activeVersionId, metadata, status } = updates;
|
|
2362
|
+
const updateData = {
|
|
2363
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
2420
2364
|
};
|
|
2421
|
-
if (
|
|
2422
|
-
if (
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
data.metadata = metadataFields.metadata;
|
|
2427
|
-
}
|
|
2428
|
-
if (Object.keys(data).length > 1) {
|
|
2429
|
-
await this.#db.update({
|
|
2430
|
-
tableName: TABLE_AGENTS,
|
|
2431
|
-
keys: { id },
|
|
2432
|
-
data
|
|
2433
|
-
});
|
|
2365
|
+
if (authorId !== void 0) updateData.authorId = authorId;
|
|
2366
|
+
if (activeVersionId !== void 0) updateData.activeVersionId = activeVersionId;
|
|
2367
|
+
if (status !== void 0) updateData.status = status;
|
|
2368
|
+
if (metadata !== void 0) {
|
|
2369
|
+
updateData.metadata = { ...existing.metadata, ...metadata };
|
|
2434
2370
|
}
|
|
2371
|
+
await this.#db.update({
|
|
2372
|
+
tableName: TABLE_AGENTS,
|
|
2373
|
+
keys: { id },
|
|
2374
|
+
data: updateData
|
|
2375
|
+
});
|
|
2435
2376
|
const updatedAgent = await this.getById(id);
|
|
2436
2377
|
if (!updatedAgent) {
|
|
2437
2378
|
throw new MastraError({
|
|
@@ -2479,7 +2420,7 @@ var AgentsLibSQL = class extends AgentsStorage {
|
|
|
2479
2420
|
}
|
|
2480
2421
|
}
|
|
2481
2422
|
async list(args) {
|
|
2482
|
-
const { page = 0, perPage: perPageInput, orderBy } = args || {};
|
|
2423
|
+
const { page = 0, perPage: perPageInput, orderBy, authorId, metadata, status } = args || {};
|
|
2483
2424
|
const { field, direction } = this.parseOrderBy(orderBy);
|
|
2484
2425
|
if (page < 0) {
|
|
2485
2426
|
throw new MastraError(
|
|
@@ -2495,7 +2436,37 @@ var AgentsLibSQL = class extends AgentsStorage {
|
|
|
2495
2436
|
const perPage = normalizePerPage(perPageInput, 100);
|
|
2496
2437
|
const { offset, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
|
|
2497
2438
|
try {
|
|
2498
|
-
const
|
|
2439
|
+
const conditions = [];
|
|
2440
|
+
const queryParams = [];
|
|
2441
|
+
if (status) {
|
|
2442
|
+
conditions.push("status = ?");
|
|
2443
|
+
queryParams.push(status);
|
|
2444
|
+
}
|
|
2445
|
+
if (authorId !== void 0) {
|
|
2446
|
+
conditions.push("authorId = ?");
|
|
2447
|
+
queryParams.push(authorId);
|
|
2448
|
+
}
|
|
2449
|
+
if (metadata && Object.keys(metadata).length > 0) {
|
|
2450
|
+
for (const [key, value] of Object.entries(metadata)) {
|
|
2451
|
+
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(key)) {
|
|
2452
|
+
throw new MastraError({
|
|
2453
|
+
id: createStorageErrorId("LIBSQL", "LIST_AGENTS", "INVALID_METADATA_KEY"),
|
|
2454
|
+
domain: ErrorDomain.STORAGE,
|
|
2455
|
+
category: ErrorCategory.USER,
|
|
2456
|
+
text: `Invalid metadata key: ${key}. Keys must be alphanumeric with underscores.`,
|
|
2457
|
+
details: { key }
|
|
2458
|
+
});
|
|
2459
|
+
}
|
|
2460
|
+
conditions.push(`json_extract(metadata, '$.${key}') = ?`);
|
|
2461
|
+
queryParams.push(typeof value === "string" ? value : JSON.stringify(value));
|
|
2462
|
+
}
|
|
2463
|
+
}
|
|
2464
|
+
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
2465
|
+
const countResult = await this.#client.execute({
|
|
2466
|
+
sql: `SELECT COUNT(*) as count FROM "${TABLE_AGENTS}" ${whereClause}`,
|
|
2467
|
+
args: queryParams
|
|
2468
|
+
});
|
|
2469
|
+
const total = Number(countResult.rows?.[0]?.count ?? 0);
|
|
2499
2470
|
if (total === 0) {
|
|
2500
2471
|
return {
|
|
2501
2472
|
agents: [],
|
|
@@ -2506,12 +2477,11 @@ var AgentsLibSQL = class extends AgentsStorage {
|
|
|
2506
2477
|
};
|
|
2507
2478
|
}
|
|
2508
2479
|
const limitValue = perPageInput === false ? total : perPage;
|
|
2509
|
-
const
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
limit: limitValue,
|
|
2513
|
-
offset
|
|
2480
|
+
const result = await this.#client.execute({
|
|
2481
|
+
sql: `SELECT ${buildSelectColumns(TABLE_AGENTS)} FROM "${TABLE_AGENTS}" ${whereClause} ORDER BY "${field}" ${direction} LIMIT ? OFFSET ?`,
|
|
2482
|
+
args: [...queryParams, limitValue, offset]
|
|
2514
2483
|
});
|
|
2484
|
+
const rows = result.rows ?? [];
|
|
2515
2485
|
const agents = rows.map((row) => this.parseRow(row));
|
|
2516
2486
|
return {
|
|
2517
2487
|
agents,
|
|
@@ -2559,6 +2529,9 @@ var AgentsLibSQL = class extends AgentsStorage {
|
|
|
2559
2529
|
scorers: input.scorers ?? null,
|
|
2560
2530
|
mcpClients: input.mcpClients ?? null,
|
|
2561
2531
|
requestContextSchema: input.requestContextSchema ?? null,
|
|
2532
|
+
workspace: input.workspace ?? null,
|
|
2533
|
+
skills: input.skills ?? null,
|
|
2534
|
+
skillsFormat: input.skillsFormat ?? null,
|
|
2562
2535
|
changedFields: input.changedFields ?? null,
|
|
2563
2536
|
changeMessage: input.changeMessage ?? null,
|
|
2564
2537
|
createdAt: now
|
|
@@ -2829,12 +2802,101 @@ var AgentsLibSQL = class extends AgentsStorage {
|
|
|
2829
2802
|
scorers: this.parseJson(row.scorers, "scorers"),
|
|
2830
2803
|
mcpClients: this.parseJson(row.mcpClients, "mcpClients"),
|
|
2831
2804
|
requestContextSchema: this.parseJson(row.requestContextSchema, "requestContextSchema"),
|
|
2805
|
+
workspace: this.parseJson(row.workspace, "workspace"),
|
|
2806
|
+
skills: this.parseJson(row.skills, "skills"),
|
|
2807
|
+
skillsFormat: row.skillsFormat,
|
|
2832
2808
|
changedFields: this.parseJson(row.changedFields, "changedFields"),
|
|
2833
2809
|
changeMessage: row.changeMessage,
|
|
2834
2810
|
createdAt: new Date(row.createdAt)
|
|
2835
2811
|
};
|
|
2836
2812
|
}
|
|
2837
2813
|
};
|
|
2814
|
+
var BlobsLibSQL = class extends BlobStore {
|
|
2815
|
+
#db;
|
|
2816
|
+
#client;
|
|
2817
|
+
static MANAGED_TABLES = [TABLE_SKILL_BLOBS];
|
|
2818
|
+
constructor(config) {
|
|
2819
|
+
super();
|
|
2820
|
+
const client = resolveClient(config);
|
|
2821
|
+
this.#client = client;
|
|
2822
|
+
this.#db = new LibSQLDB({ client, maxRetries: config.maxRetries, initialBackoffMs: config.initialBackoffMs });
|
|
2823
|
+
}
|
|
2824
|
+
async init() {
|
|
2825
|
+
await this.#db.createTable({ tableName: TABLE_SKILL_BLOBS, schema: SKILL_BLOBS_SCHEMA });
|
|
2826
|
+
}
|
|
2827
|
+
async put(entry) {
|
|
2828
|
+
const now = entry.createdAt ?? /* @__PURE__ */ new Date();
|
|
2829
|
+
await this.#client.execute({
|
|
2830
|
+
sql: `INSERT OR IGNORE INTO "${TABLE_SKILL_BLOBS}" ("hash", "content", "size", "mimeType", "createdAt") VALUES (?, ?, ?, ?, ?)`,
|
|
2831
|
+
args: [entry.hash, entry.content, entry.size, entry.mimeType ?? null, now.toISOString()]
|
|
2832
|
+
});
|
|
2833
|
+
}
|
|
2834
|
+
async get(hash) {
|
|
2835
|
+
const result = await this.#client.execute({
|
|
2836
|
+
sql: `SELECT ${buildSelectColumns(TABLE_SKILL_BLOBS)} FROM "${TABLE_SKILL_BLOBS}" WHERE "hash" = ?`,
|
|
2837
|
+
args: [hash]
|
|
2838
|
+
});
|
|
2839
|
+
if (!result.rows.length) return null;
|
|
2840
|
+
return this.#parseRow(result.rows[0]);
|
|
2841
|
+
}
|
|
2842
|
+
async has(hash) {
|
|
2843
|
+
const result = await this.#client.execute({
|
|
2844
|
+
sql: `SELECT 1 FROM "${TABLE_SKILL_BLOBS}" WHERE "hash" = ? LIMIT 1`,
|
|
2845
|
+
args: [hash]
|
|
2846
|
+
});
|
|
2847
|
+
return result.rows.length > 0;
|
|
2848
|
+
}
|
|
2849
|
+
async delete(hash) {
|
|
2850
|
+
const result = await this.#client.execute({
|
|
2851
|
+
sql: `DELETE FROM "${TABLE_SKILL_BLOBS}" WHERE "hash" = ?`,
|
|
2852
|
+
args: [hash]
|
|
2853
|
+
});
|
|
2854
|
+
return result.rowsAffected > 0;
|
|
2855
|
+
}
|
|
2856
|
+
async putMany(entries) {
|
|
2857
|
+
if (entries.length === 0) return;
|
|
2858
|
+
await this.#db.batchInsert({
|
|
2859
|
+
tableName: TABLE_SKILL_BLOBS,
|
|
2860
|
+
records: entries.map((entry) => ({
|
|
2861
|
+
hash: entry.hash,
|
|
2862
|
+
content: entry.content,
|
|
2863
|
+
size: entry.size,
|
|
2864
|
+
mimeType: entry.mimeType ?? null,
|
|
2865
|
+
createdAt: (entry.createdAt ?? /* @__PURE__ */ new Date()).toISOString()
|
|
2866
|
+
}))
|
|
2867
|
+
});
|
|
2868
|
+
}
|
|
2869
|
+
async getMany(hashes) {
|
|
2870
|
+
const result = /* @__PURE__ */ new Map();
|
|
2871
|
+
if (hashes.length === 0) return result;
|
|
2872
|
+
const batchSize = 500;
|
|
2873
|
+
for (let i = 0; i < hashes.length; i += batchSize) {
|
|
2874
|
+
const batch = hashes.slice(i, i + batchSize);
|
|
2875
|
+
const placeholders = batch.map(() => "?").join(", ");
|
|
2876
|
+
const queryResult = await this.#client.execute({
|
|
2877
|
+
sql: `SELECT ${buildSelectColumns(TABLE_SKILL_BLOBS)} FROM "${TABLE_SKILL_BLOBS}" WHERE "hash" IN (${placeholders})`,
|
|
2878
|
+
args: batch
|
|
2879
|
+
});
|
|
2880
|
+
for (const row of queryResult.rows) {
|
|
2881
|
+
const entry = this.#parseRow(row);
|
|
2882
|
+
result.set(entry.hash, entry);
|
|
2883
|
+
}
|
|
2884
|
+
}
|
|
2885
|
+
return result;
|
|
2886
|
+
}
|
|
2887
|
+
async dangerouslyClearAll() {
|
|
2888
|
+
await this.#db.deleteData({ tableName: TABLE_SKILL_BLOBS });
|
|
2889
|
+
}
|
|
2890
|
+
#parseRow(row) {
|
|
2891
|
+
return {
|
|
2892
|
+
hash: row.hash,
|
|
2893
|
+
content: row.content,
|
|
2894
|
+
size: Number(row.size),
|
|
2895
|
+
mimeType: row.mimeType || void 0,
|
|
2896
|
+
createdAt: new Date(row.createdAt)
|
|
2897
|
+
};
|
|
2898
|
+
}
|
|
2899
|
+
};
|
|
2838
2900
|
function jsonbArg(value) {
|
|
2839
2901
|
return value === void 0 || value === null ? null : JSON.stringify(value);
|
|
2840
2902
|
}
|
|
@@ -2950,8 +3012,8 @@ var DatasetsLibSQL = class extends DatasetsStorage {
|
|
|
2950
3012
|
name: input.name,
|
|
2951
3013
|
description: input.description,
|
|
2952
3014
|
metadata: input.metadata,
|
|
2953
|
-
inputSchema: input.inputSchema,
|
|
2954
|
-
groundTruthSchema: input.groundTruthSchema,
|
|
3015
|
+
inputSchema: input.inputSchema ?? void 0,
|
|
3016
|
+
groundTruthSchema: input.groundTruthSchema ?? void 0,
|
|
2955
3017
|
version: 0,
|
|
2956
3018
|
createdAt: now,
|
|
2957
3019
|
updatedAt: now
|
|
@@ -3029,8 +3091,8 @@ var DatasetsLibSQL = class extends DatasetsStorage {
|
|
|
3029
3091
|
name: args.name ?? existing.name,
|
|
3030
3092
|
description: args.description ?? existing.description,
|
|
3031
3093
|
metadata: args.metadata ?? existing.metadata,
|
|
3032
|
-
inputSchema: args.inputSchema !== void 0 ? args.inputSchema : existing.inputSchema,
|
|
3033
|
-
groundTruthSchema: args.groundTruthSchema !== void 0 ? args.groundTruthSchema : existing.groundTruthSchema,
|
|
3094
|
+
inputSchema: (args.inputSchema !== void 0 ? args.inputSchema : existing.inputSchema) ?? void 0,
|
|
3095
|
+
groundTruthSchema: (args.groundTruthSchema !== void 0 ? args.groundTruthSchema : existing.groundTruthSchema) ?? void 0,
|
|
3034
3096
|
updatedAt: new Date(now)
|
|
3035
3097
|
};
|
|
3036
3098
|
} catch (error) {
|
|
@@ -4089,7 +4151,6 @@ var ExperimentsLibSQL = class extends ExperimentsStorage {
|
|
|
4089
4151
|
}
|
|
4090
4152
|
}
|
|
4091
4153
|
};
|
|
4092
|
-
var SNAPSHOT_FIELDS2 = ["name", "description", "servers"];
|
|
4093
4154
|
var MCPClientsLibSQL = class extends MCPClientsStorage {
|
|
4094
4155
|
#db;
|
|
4095
4156
|
#client;
|
|
@@ -4195,19 +4256,12 @@ var MCPClientsLibSQL = class extends MCPClientsStorage {
|
|
|
4195
4256
|
if (!existing) {
|
|
4196
4257
|
throw new Error(`MCP client with id ${id} not found`);
|
|
4197
4258
|
}
|
|
4198
|
-
const { authorId, activeVersionId, metadata, status
|
|
4199
|
-
const configFieldNames = SNAPSHOT_FIELDS2;
|
|
4200
|
-
const hasConfigUpdate = configFieldNames.some((field) => field in configFields);
|
|
4259
|
+
const { authorId, activeVersionId, metadata, status } = updates;
|
|
4201
4260
|
const updateData = {
|
|
4202
4261
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
4203
4262
|
};
|
|
4204
4263
|
if (authorId !== void 0) updateData.authorId = authorId;
|
|
4205
|
-
if (activeVersionId !== void 0)
|
|
4206
|
-
updateData.activeVersionId = activeVersionId;
|
|
4207
|
-
if (status === void 0) {
|
|
4208
|
-
updateData.status = "published";
|
|
4209
|
-
}
|
|
4210
|
-
}
|
|
4264
|
+
if (activeVersionId !== void 0) updateData.activeVersionId = activeVersionId;
|
|
4211
4265
|
if (status !== void 0) updateData.status = status;
|
|
4212
4266
|
if (metadata !== void 0) {
|
|
4213
4267
|
updateData.metadata = { ...existing.metadata, ...metadata };
|
|
@@ -4217,36 +4271,6 @@ var MCPClientsLibSQL = class extends MCPClientsStorage {
|
|
|
4217
4271
|
keys: { id },
|
|
4218
4272
|
data: updateData
|
|
4219
4273
|
});
|
|
4220
|
-
if (hasConfigUpdate) {
|
|
4221
|
-
const latestVersion = await this.getLatestVersion(id);
|
|
4222
|
-
if (!latestVersion) {
|
|
4223
|
-
throw new Error(`No versions found for MCP client ${id}`);
|
|
4224
|
-
}
|
|
4225
|
-
const {
|
|
4226
|
-
id: _versionId,
|
|
4227
|
-
mcpClientId: _mcpClientId,
|
|
4228
|
-
versionNumber: _versionNumber,
|
|
4229
|
-
changedFields: _changedFields,
|
|
4230
|
-
changeMessage: _changeMessage,
|
|
4231
|
-
createdAt: _createdAt,
|
|
4232
|
-
...latestConfig
|
|
4233
|
-
} = latestVersion;
|
|
4234
|
-
const newConfig = { ...latestConfig, ...configFields };
|
|
4235
|
-
const changedFields = configFieldNames.filter(
|
|
4236
|
-
(field) => field in configFields && JSON.stringify(configFields[field]) !== JSON.stringify(latestConfig[field])
|
|
4237
|
-
);
|
|
4238
|
-
if (changedFields.length > 0) {
|
|
4239
|
-
const newVersionId = crypto.randomUUID();
|
|
4240
|
-
await this.createVersion({
|
|
4241
|
-
id: newVersionId,
|
|
4242
|
-
mcpClientId: id,
|
|
4243
|
-
versionNumber: latestVersion.versionNumber + 1,
|
|
4244
|
-
...newConfig,
|
|
4245
|
-
changedFields,
|
|
4246
|
-
changeMessage: `Updated ${changedFields.join(", ")}`
|
|
4247
|
-
});
|
|
4248
|
-
}
|
|
4249
|
-
}
|
|
4250
4274
|
const updated = await this.getById(id);
|
|
4251
4275
|
if (!updated) {
|
|
4252
4276
|
throw new MastraError({
|
|
@@ -4291,10 +4315,12 @@ var MCPClientsLibSQL = class extends MCPClientsStorage {
|
|
|
4291
4315
|
}
|
|
4292
4316
|
async list(args) {
|
|
4293
4317
|
try {
|
|
4294
|
-
const { page = 0, perPage: perPageInput, orderBy, authorId, metadata } = args || {};
|
|
4318
|
+
const { page = 0, perPage: perPageInput, orderBy, authorId, metadata, status = "published" } = args || {};
|
|
4295
4319
|
const { field, direction } = this.parseOrderBy(orderBy);
|
|
4296
4320
|
const conditions = [];
|
|
4297
4321
|
const queryParams = [];
|
|
4322
|
+
conditions.push("status = ?");
|
|
4323
|
+
queryParams.push(status);
|
|
4298
4324
|
if (authorId !== void 0) {
|
|
4299
4325
|
conditions.push("authorId = ?");
|
|
4300
4326
|
queryParams.push(authorId);
|
|
@@ -4314,7 +4340,7 @@ var MCPClientsLibSQL = class extends MCPClientsStorage {
|
|
|
4314
4340
|
queryParams.push(typeof value === "string" ? value : JSON.stringify(value));
|
|
4315
4341
|
}
|
|
4316
4342
|
}
|
|
4317
|
-
const whereClause =
|
|
4343
|
+
const whereClause = `WHERE ${conditions.join(" AND ")}`;
|
|
4318
4344
|
const countResult = await this.#client.execute({
|
|
4319
4345
|
sql: `SELECT COUNT(*) as count FROM "${TABLE_MCP_CLIENTS}" ${whereClause}`,
|
|
4320
4346
|
args: queryParams
|
|
@@ -5594,7 +5620,7 @@ var MemoryLibSQL = class extends MemoryStorage {
|
|
|
5594
5620
|
const newThread = {
|
|
5595
5621
|
id: newThreadId,
|
|
5596
5622
|
resourceId: resourceId || sourceThread.resourceId,
|
|
5597
|
-
title: title || (sourceThread.title ? `Clone of ${sourceThread.title}` :
|
|
5623
|
+
title: title || (sourceThread.title ? `Clone of ${sourceThread.title}` : ""),
|
|
5598
5624
|
metadata: {
|
|
5599
5625
|
...metadata,
|
|
5600
5626
|
clone: cloneMetadata
|
|
@@ -5610,7 +5636,7 @@ var MemoryLibSQL = class extends MemoryStorage {
|
|
|
5610
5636
|
args: [
|
|
5611
5637
|
newThread.id,
|
|
5612
5638
|
newThread.resourceId,
|
|
5613
|
-
newThread.title
|
|
5639
|
+
newThread.title ?? "",
|
|
5614
5640
|
JSON.stringify(newThread.metadata),
|
|
5615
5641
|
nowStr,
|
|
5616
5642
|
nowStr
|
|
@@ -6930,7 +6956,6 @@ var ObservabilityLibSQL = class extends ObservabilityStorage {
|
|
|
6930
6956
|
}
|
|
6931
6957
|
}
|
|
6932
6958
|
};
|
|
6933
|
-
var SNAPSHOT_FIELDS3 = ["name", "description", "content", "rules"];
|
|
6934
6959
|
var PromptBlocksLibSQL = class extends PromptBlocksStorage {
|
|
6935
6960
|
#db;
|
|
6936
6961
|
#client;
|
|
@@ -7028,19 +7053,12 @@ var PromptBlocksLibSQL = class extends PromptBlocksStorage {
|
|
|
7028
7053
|
if (!existing) {
|
|
7029
7054
|
throw new Error(`Prompt block with id ${id} not found`);
|
|
7030
7055
|
}
|
|
7031
|
-
const { authorId, activeVersionId, metadata, status
|
|
7032
|
-
const configFieldNames = SNAPSHOT_FIELDS3;
|
|
7033
|
-
const hasConfigUpdate = configFieldNames.some((field) => field in configFields);
|
|
7056
|
+
const { authorId, activeVersionId, metadata, status } = updates;
|
|
7034
7057
|
const updateData = {
|
|
7035
7058
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
7036
7059
|
};
|
|
7037
7060
|
if (authorId !== void 0) updateData.authorId = authorId;
|
|
7038
|
-
if (activeVersionId !== void 0)
|
|
7039
|
-
updateData.activeVersionId = activeVersionId;
|
|
7040
|
-
if (status === void 0) {
|
|
7041
|
-
updateData.status = "published";
|
|
7042
|
-
}
|
|
7043
|
-
}
|
|
7061
|
+
if (activeVersionId !== void 0) updateData.activeVersionId = activeVersionId;
|
|
7044
7062
|
if (status !== void 0) updateData.status = status;
|
|
7045
7063
|
if (metadata !== void 0) {
|
|
7046
7064
|
updateData.metadata = { ...existing.metadata, ...metadata };
|
|
@@ -7050,34 +7068,6 @@ var PromptBlocksLibSQL = class extends PromptBlocksStorage {
|
|
|
7050
7068
|
keys: { id },
|
|
7051
7069
|
data: updateData
|
|
7052
7070
|
});
|
|
7053
|
-
if (hasConfigUpdate) {
|
|
7054
|
-
const latestVersion = await this.getLatestVersion(id);
|
|
7055
|
-
if (!latestVersion) {
|
|
7056
|
-
throw new Error(`No versions found for prompt block ${id}`);
|
|
7057
|
-
}
|
|
7058
|
-
const {
|
|
7059
|
-
id: _versionId,
|
|
7060
|
-
blockId: _blockId,
|
|
7061
|
-
versionNumber: _versionNumber,
|
|
7062
|
-
changedFields: _changedFields,
|
|
7063
|
-
changeMessage: _changeMessage,
|
|
7064
|
-
createdAt: _createdAt,
|
|
7065
|
-
...latestConfig
|
|
7066
|
-
} = latestVersion;
|
|
7067
|
-
const newConfig = { ...latestConfig, ...configFields };
|
|
7068
|
-
const changedFields = configFieldNames.filter(
|
|
7069
|
-
(field) => field in configFields && JSON.stringify(configFields[field]) !== JSON.stringify(latestConfig[field])
|
|
7070
|
-
);
|
|
7071
|
-
const newVersionId = crypto.randomUUID();
|
|
7072
|
-
await this.createVersion({
|
|
7073
|
-
id: newVersionId,
|
|
7074
|
-
blockId: id,
|
|
7075
|
-
versionNumber: latestVersion.versionNumber + 1,
|
|
7076
|
-
...newConfig,
|
|
7077
|
-
changedFields,
|
|
7078
|
-
changeMessage: `Updated ${changedFields.join(", ")}`
|
|
7079
|
-
});
|
|
7080
|
-
}
|
|
7081
7071
|
const updated = await this.getById(id);
|
|
7082
7072
|
if (!updated) {
|
|
7083
7073
|
throw new MastraError({
|
|
@@ -7122,10 +7112,12 @@ var PromptBlocksLibSQL = class extends PromptBlocksStorage {
|
|
|
7122
7112
|
}
|
|
7123
7113
|
async list(args) {
|
|
7124
7114
|
try {
|
|
7125
|
-
const { page = 0, perPage: perPageInput, orderBy, authorId, metadata } = args || {};
|
|
7115
|
+
const { page = 0, perPage: perPageInput, orderBy, authorId, metadata, status = "published" } = args || {};
|
|
7126
7116
|
const { field, direction } = this.parseOrderBy(orderBy);
|
|
7127
7117
|
const conditions = [];
|
|
7128
7118
|
const queryParams = [];
|
|
7119
|
+
conditions.push("status = ?");
|
|
7120
|
+
queryParams.push(status);
|
|
7129
7121
|
if (authorId !== void 0) {
|
|
7130
7122
|
conditions.push("authorId = ?");
|
|
7131
7123
|
queryParams.push(authorId);
|
|
@@ -7145,7 +7137,7 @@ var PromptBlocksLibSQL = class extends PromptBlocksStorage {
|
|
|
7145
7137
|
queryParams.push(typeof value === "string" ? value : JSON.stringify(value));
|
|
7146
7138
|
}
|
|
7147
7139
|
}
|
|
7148
|
-
const whereClause =
|
|
7140
|
+
const whereClause = `WHERE ${conditions.join(" AND ")}`;
|
|
7149
7141
|
const countResult = await this.#client.execute({
|
|
7150
7142
|
sql: `SELECT COUNT(*) as count FROM "${TABLE_PROMPT_BLOCKS}" ${whereClause}`,
|
|
7151
7143
|
args: queryParams
|
|
@@ -7437,16 +7429,6 @@ var PromptBlocksLibSQL = class extends PromptBlocksStorage {
|
|
|
7437
7429
|
};
|
|
7438
7430
|
}
|
|
7439
7431
|
};
|
|
7440
|
-
var SNAPSHOT_FIELDS4 = [
|
|
7441
|
-
"name",
|
|
7442
|
-
"description",
|
|
7443
|
-
"type",
|
|
7444
|
-
"model",
|
|
7445
|
-
"instructions",
|
|
7446
|
-
"scoreRange",
|
|
7447
|
-
"presetConfig",
|
|
7448
|
-
"defaultSampling"
|
|
7449
|
-
];
|
|
7450
7432
|
var ScorerDefinitionsLibSQL = class extends ScorerDefinitionsStorage {
|
|
7451
7433
|
#db;
|
|
7452
7434
|
#client;
|
|
@@ -7547,19 +7529,12 @@ var ScorerDefinitionsLibSQL = class extends ScorerDefinitionsStorage {
|
|
|
7547
7529
|
if (!existing) {
|
|
7548
7530
|
throw new Error(`Scorer definition with id ${id} not found`);
|
|
7549
7531
|
}
|
|
7550
|
-
const { authorId, activeVersionId, metadata, status
|
|
7551
|
-
const configFieldNames = SNAPSHOT_FIELDS4;
|
|
7552
|
-
const hasConfigUpdate = configFieldNames.some((field) => field in configFields);
|
|
7532
|
+
const { authorId, activeVersionId, metadata, status } = updates;
|
|
7553
7533
|
const updateData = {
|
|
7554
7534
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
7555
7535
|
};
|
|
7556
7536
|
if (authorId !== void 0) updateData.authorId = authorId;
|
|
7557
|
-
if (activeVersionId !== void 0)
|
|
7558
|
-
updateData.activeVersionId = activeVersionId;
|
|
7559
|
-
if (status === void 0) {
|
|
7560
|
-
updateData.status = "published";
|
|
7561
|
-
}
|
|
7562
|
-
}
|
|
7537
|
+
if (activeVersionId !== void 0) updateData.activeVersionId = activeVersionId;
|
|
7563
7538
|
if (status !== void 0) updateData.status = status;
|
|
7564
7539
|
if (metadata !== void 0) {
|
|
7565
7540
|
updateData.metadata = { ...existing.metadata, ...metadata };
|
|
@@ -7569,34 +7544,6 @@ var ScorerDefinitionsLibSQL = class extends ScorerDefinitionsStorage {
|
|
|
7569
7544
|
keys: { id },
|
|
7570
7545
|
data: updateData
|
|
7571
7546
|
});
|
|
7572
|
-
if (hasConfigUpdate) {
|
|
7573
|
-
const latestVersion = await this.getLatestVersion(id);
|
|
7574
|
-
if (!latestVersion) {
|
|
7575
|
-
throw new Error(`No versions found for scorer definition ${id}`);
|
|
7576
|
-
}
|
|
7577
|
-
const {
|
|
7578
|
-
id: _versionId,
|
|
7579
|
-
scorerDefinitionId: _scorerDefinitionId,
|
|
7580
|
-
versionNumber: _versionNumber,
|
|
7581
|
-
changedFields: _changedFields,
|
|
7582
|
-
changeMessage: _changeMessage,
|
|
7583
|
-
createdAt: _createdAt,
|
|
7584
|
-
...latestConfig
|
|
7585
|
-
} = latestVersion;
|
|
7586
|
-
const newConfig = { ...latestConfig, ...configFields };
|
|
7587
|
-
const changedFields = configFieldNames.filter(
|
|
7588
|
-
(field) => field in configFields && JSON.stringify(configFields[field]) !== JSON.stringify(latestConfig[field])
|
|
7589
|
-
);
|
|
7590
|
-
const newVersionId = crypto.randomUUID();
|
|
7591
|
-
await this.createVersion({
|
|
7592
|
-
id: newVersionId,
|
|
7593
|
-
scorerDefinitionId: id,
|
|
7594
|
-
versionNumber: latestVersion.versionNumber + 1,
|
|
7595
|
-
...newConfig,
|
|
7596
|
-
changedFields,
|
|
7597
|
-
changeMessage: `Updated ${changedFields.join(", ")}`
|
|
7598
|
-
});
|
|
7599
|
-
}
|
|
7600
7547
|
const updated = await this.getById(id);
|
|
7601
7548
|
if (!updated) {
|
|
7602
7549
|
throw new MastraError({
|
|
@@ -7641,10 +7588,14 @@ var ScorerDefinitionsLibSQL = class extends ScorerDefinitionsStorage {
|
|
|
7641
7588
|
}
|
|
7642
7589
|
async list(args) {
|
|
7643
7590
|
try {
|
|
7644
|
-
const { page = 0, perPage: perPageInput, orderBy, authorId, metadata } = args || {};
|
|
7591
|
+
const { page = 0, perPage: perPageInput, orderBy, authorId, metadata, status } = args || {};
|
|
7645
7592
|
const { field, direction } = this.parseOrderBy(orderBy);
|
|
7646
7593
|
const conditions = [];
|
|
7647
7594
|
const queryParams = [];
|
|
7595
|
+
if (status) {
|
|
7596
|
+
conditions.push("status = ?");
|
|
7597
|
+
queryParams.push(status);
|
|
7598
|
+
}
|
|
7648
7599
|
if (authorId !== void 0) {
|
|
7649
7600
|
conditions.push("authorId = ?");
|
|
7650
7601
|
queryParams.push(authorId);
|
|
@@ -8260,229 +8211,1237 @@ var ScoresLibSQL = class extends ScoresStorage {
|
|
|
8260
8211
|
}
|
|
8261
8212
|
}
|
|
8262
8213
|
};
|
|
8263
|
-
var
|
|
8214
|
+
var SNAPSHOT_FIELDS = [
|
|
8215
|
+
"name",
|
|
8216
|
+
"description",
|
|
8217
|
+
"instructions",
|
|
8218
|
+
"license",
|
|
8219
|
+
"compatibility",
|
|
8220
|
+
"source",
|
|
8221
|
+
"references",
|
|
8222
|
+
"scripts",
|
|
8223
|
+
"assets",
|
|
8224
|
+
"metadata",
|
|
8225
|
+
"tree"
|
|
8226
|
+
];
|
|
8227
|
+
var SkillsLibSQL = class extends SkillsStorage {
|
|
8264
8228
|
#db;
|
|
8265
8229
|
#client;
|
|
8266
|
-
executeWithRetry;
|
|
8267
8230
|
constructor(config) {
|
|
8268
8231
|
super();
|
|
8269
8232
|
const client = resolveClient(config);
|
|
8270
|
-
const maxRetries = config.maxRetries ?? 5;
|
|
8271
|
-
const initialBackoffMs = config.initialBackoffMs ?? 500;
|
|
8272
8233
|
this.#client = client;
|
|
8273
|
-
this.#db = new LibSQLDB({ client, maxRetries, initialBackoffMs });
|
|
8274
|
-
|
|
8275
|
-
|
|
8276
|
-
|
|
8277
|
-
|
|
8234
|
+
this.#db = new LibSQLDB({ client, maxRetries: config.maxRetries, initialBackoffMs: config.initialBackoffMs });
|
|
8235
|
+
}
|
|
8236
|
+
async init() {
|
|
8237
|
+
await this.#db.createTable({ tableName: TABLE_SKILLS, schema: SKILLS_SCHEMA });
|
|
8238
|
+
await this.#db.createTable({
|
|
8239
|
+
tableName: TABLE_SKILL_VERSIONS,
|
|
8240
|
+
schema: SKILL_VERSIONS_SCHEMA
|
|
8278
8241
|
});
|
|
8279
|
-
this.
|
|
8280
|
-
|
|
8242
|
+
await this.#client.execute(
|
|
8243
|
+
`CREATE UNIQUE INDEX IF NOT EXISTS idx_skill_versions_skill_version ON "${TABLE_SKILL_VERSIONS}" ("skillId", "versionNumber")`
|
|
8281
8244
|
);
|
|
8282
8245
|
}
|
|
8283
|
-
|
|
8284
|
-
|
|
8285
|
-
|
|
8286
|
-
try {
|
|
8287
|
-
parsedSnapshot = JSON.parse(row.snapshot);
|
|
8288
|
-
} catch (e) {
|
|
8289
|
-
this.logger.warn(`Failed to parse snapshot for workflow ${row.workflow_name}: ${e}`);
|
|
8290
|
-
}
|
|
8291
|
-
}
|
|
8292
|
-
return {
|
|
8293
|
-
workflowName: row.workflow_name,
|
|
8294
|
-
runId: row.run_id,
|
|
8295
|
-
snapshot: parsedSnapshot,
|
|
8296
|
-
resourceId: row.resourceId,
|
|
8297
|
-
createdAt: new Date(row.createdAt),
|
|
8298
|
-
updatedAt: new Date(row.updatedAt)
|
|
8299
|
-
};
|
|
8246
|
+
async dangerouslyClearAll() {
|
|
8247
|
+
await this.#db.deleteData({ tableName: TABLE_SKILLS });
|
|
8248
|
+
await this.#db.deleteData({ tableName: TABLE_SKILL_VERSIONS });
|
|
8300
8249
|
}
|
|
8301
|
-
|
|
8302
|
-
|
|
8303
|
-
|
|
8304
|
-
|
|
8305
|
-
|
|
8306
|
-
|
|
8307
|
-
|
|
8308
|
-
|
|
8309
|
-
|
|
8310
|
-
|
|
8311
|
-
|
|
8250
|
+
// ==========================================================================
|
|
8251
|
+
// Skill CRUD
|
|
8252
|
+
// ==========================================================================
|
|
8253
|
+
async getById(id) {
|
|
8254
|
+
try {
|
|
8255
|
+
const result = await this.#client.execute({
|
|
8256
|
+
sql: `SELECT ${buildSelectColumns(TABLE_SKILLS)} FROM "${TABLE_SKILLS}" WHERE id = ?`,
|
|
8257
|
+
args: [id]
|
|
8258
|
+
});
|
|
8259
|
+
const row = result.rows?.[0];
|
|
8260
|
+
return row ? this.#parseSkillRow(row) : null;
|
|
8261
|
+
} catch (error) {
|
|
8262
|
+
if (error instanceof MastraError) throw error;
|
|
8263
|
+
throw new MastraError(
|
|
8264
|
+
{
|
|
8265
|
+
id: createStorageErrorId("LIBSQL", "GET_SKILL", "FAILED"),
|
|
8266
|
+
domain: ErrorDomain.STORAGE,
|
|
8267
|
+
category: ErrorCategory.THIRD_PARTY
|
|
8268
|
+
},
|
|
8269
|
+
error
|
|
8270
|
+
);
|
|
8271
|
+
}
|
|
8312
8272
|
}
|
|
8313
|
-
async
|
|
8273
|
+
async create(input) {
|
|
8274
|
+
const { skill } = input;
|
|
8314
8275
|
try {
|
|
8315
|
-
|
|
8316
|
-
this.
|
|
8317
|
-
|
|
8318
|
-
|
|
8319
|
-
|
|
8320
|
-
|
|
8321
|
-
|
|
8322
|
-
|
|
8276
|
+
const now = /* @__PURE__ */ new Date();
|
|
8277
|
+
await this.#db.insert({
|
|
8278
|
+
tableName: TABLE_SKILLS,
|
|
8279
|
+
record: {
|
|
8280
|
+
id: skill.id,
|
|
8281
|
+
status: "draft",
|
|
8282
|
+
activeVersionId: null,
|
|
8283
|
+
authorId: skill.authorId ?? null,
|
|
8284
|
+
createdAt: now.toISOString(),
|
|
8285
|
+
updatedAt: now.toISOString()
|
|
8286
|
+
}
|
|
8287
|
+
});
|
|
8288
|
+
const { id: _id, authorId: _authorId, ...snapshotConfig } = skill;
|
|
8289
|
+
const versionId = crypto.randomUUID();
|
|
8323
8290
|
try {
|
|
8324
|
-
await this
|
|
8325
|
-
|
|
8326
|
-
|
|
8327
|
-
|
|
8291
|
+
await this.createVersion({
|
|
8292
|
+
id: versionId,
|
|
8293
|
+
skillId: skill.id,
|
|
8294
|
+
versionNumber: 1,
|
|
8295
|
+
...snapshotConfig,
|
|
8296
|
+
changedFields: Object.keys(snapshotConfig),
|
|
8297
|
+
changeMessage: "Initial version"
|
|
8298
|
+
});
|
|
8299
|
+
} catch (versionError) {
|
|
8300
|
+
await this.#db.delete({ tableName: TABLE_SKILLS, keys: { id: skill.id } });
|
|
8301
|
+
throw versionError;
|
|
8328
8302
|
}
|
|
8329
|
-
|
|
8330
|
-
|
|
8303
|
+
return {
|
|
8304
|
+
id: skill.id,
|
|
8305
|
+
status: "draft",
|
|
8306
|
+
activeVersionId: void 0,
|
|
8307
|
+
authorId: skill.authorId,
|
|
8308
|
+
createdAt: now,
|
|
8309
|
+
updatedAt: now
|
|
8310
|
+
};
|
|
8311
|
+
} catch (error) {
|
|
8312
|
+
if (error instanceof MastraError) throw error;
|
|
8313
|
+
throw new MastraError(
|
|
8314
|
+
{
|
|
8315
|
+
id: createStorageErrorId("LIBSQL", "CREATE_SKILL", "FAILED"),
|
|
8316
|
+
domain: ErrorDomain.STORAGE,
|
|
8317
|
+
category: ErrorCategory.THIRD_PARTY
|
|
8318
|
+
},
|
|
8319
|
+
error
|
|
8320
|
+
);
|
|
8331
8321
|
}
|
|
8332
8322
|
}
|
|
8333
|
-
async
|
|
8334
|
-
|
|
8335
|
-
|
|
8336
|
-
|
|
8337
|
-
|
|
8338
|
-
|
|
8339
|
-
|
|
8340
|
-
|
|
8341
|
-
|
|
8342
|
-
|
|
8343
|
-
|
|
8344
|
-
sql: `SELECT json(snapshot) as snapshot FROM ${TABLE_WORKFLOW_SNAPSHOT} WHERE workflow_name = ? AND run_id = ?`,
|
|
8345
|
-
args: [workflowName, runId]
|
|
8346
|
-
});
|
|
8347
|
-
let snapshot;
|
|
8348
|
-
if (!existingSnapshotResult.rows?.[0]) {
|
|
8349
|
-
snapshot = {
|
|
8350
|
-
context: {},
|
|
8351
|
-
activePaths: [],
|
|
8352
|
-
timestamp: Date.now(),
|
|
8353
|
-
suspendedPaths: {},
|
|
8354
|
-
activeStepsPath: {},
|
|
8355
|
-
resumeLabels: {},
|
|
8356
|
-
serializedStepGraph: [],
|
|
8357
|
-
status: "pending",
|
|
8358
|
-
value: {},
|
|
8359
|
-
waitingPaths: {},
|
|
8360
|
-
runId,
|
|
8361
|
-
requestContext: {}
|
|
8362
|
-
};
|
|
8363
|
-
} else {
|
|
8364
|
-
const existingSnapshot = existingSnapshotResult.rows[0].snapshot;
|
|
8365
|
-
snapshot = typeof existingSnapshot === "string" ? JSON.parse(existingSnapshot) : existingSnapshot;
|
|
8366
|
-
}
|
|
8367
|
-
snapshot.context[stepId] = result;
|
|
8368
|
-
snapshot.requestContext = { ...snapshot.requestContext, ...requestContext };
|
|
8369
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
8370
|
-
await tx.execute({
|
|
8371
|
-
sql: `INSERT INTO ${TABLE_WORKFLOW_SNAPSHOT} (workflow_name, run_id, snapshot, createdAt, updatedAt)
|
|
8372
|
-
VALUES (?, ?, jsonb(?), ?, ?)
|
|
8373
|
-
ON CONFLICT(workflow_name, run_id)
|
|
8374
|
-
DO UPDATE SET snapshot = excluded.snapshot, updatedAt = excluded.updatedAt`,
|
|
8375
|
-
args: [workflowName, runId, JSON.stringify(snapshot), now, now]
|
|
8323
|
+
async update(input) {
|
|
8324
|
+
const { id, ...updates } = input;
|
|
8325
|
+
try {
|
|
8326
|
+
const existing = await this.getById(id);
|
|
8327
|
+
if (!existing) {
|
|
8328
|
+
throw new MastraError({
|
|
8329
|
+
id: createStorageErrorId("LIBSQL", "UPDATE_SKILL", "NOT_FOUND"),
|
|
8330
|
+
domain: ErrorDomain.STORAGE,
|
|
8331
|
+
category: ErrorCategory.USER,
|
|
8332
|
+
text: `Skill ${id} not found`,
|
|
8333
|
+
details: { skillId: id }
|
|
8376
8334
|
});
|
|
8377
|
-
|
|
8378
|
-
|
|
8379
|
-
|
|
8380
|
-
|
|
8381
|
-
|
|
8335
|
+
}
|
|
8336
|
+
const { authorId, activeVersionId, status, ...configFields } = updates;
|
|
8337
|
+
const configFieldNames = SNAPSHOT_FIELDS;
|
|
8338
|
+
const hasConfigUpdate = configFieldNames.some((field) => field in configFields);
|
|
8339
|
+
const updateData = {
|
|
8340
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
8341
|
+
};
|
|
8342
|
+
if (authorId !== void 0) updateData.authorId = authorId;
|
|
8343
|
+
if (activeVersionId !== void 0) {
|
|
8344
|
+
updateData.activeVersionId = activeVersionId;
|
|
8345
|
+
if (status === void 0) {
|
|
8346
|
+
updateData.status = "published";
|
|
8382
8347
|
}
|
|
8383
|
-
throw error;
|
|
8384
8348
|
}
|
|
8385
|
-
|
|
8386
|
-
|
|
8387
|
-
|
|
8388
|
-
|
|
8389
|
-
|
|
8390
|
-
|
|
8391
|
-
|
|
8392
|
-
|
|
8393
|
-
|
|
8394
|
-
|
|
8395
|
-
|
|
8396
|
-
|
|
8397
|
-
|
|
8398
|
-
|
|
8399
|
-
|
|
8400
|
-
|
|
8401
|
-
return void 0;
|
|
8349
|
+
if (status !== void 0) updateData.status = status;
|
|
8350
|
+
await this.#db.update({
|
|
8351
|
+
tableName: TABLE_SKILLS,
|
|
8352
|
+
keys: { id },
|
|
8353
|
+
data: updateData
|
|
8354
|
+
});
|
|
8355
|
+
if (hasConfigUpdate) {
|
|
8356
|
+
const latestVersion = await this.getLatestVersion(id);
|
|
8357
|
+
if (!latestVersion) {
|
|
8358
|
+
throw new MastraError({
|
|
8359
|
+
id: createStorageErrorId("LIBSQL", "UPDATE_SKILL", "NO_VERSIONS"),
|
|
8360
|
+
domain: ErrorDomain.STORAGE,
|
|
8361
|
+
category: ErrorCategory.USER,
|
|
8362
|
+
text: `No versions found for skill ${id}`,
|
|
8363
|
+
details: { skillId: id }
|
|
8364
|
+
});
|
|
8402
8365
|
}
|
|
8403
|
-
const
|
|
8404
|
-
|
|
8405
|
-
|
|
8406
|
-
|
|
8407
|
-
|
|
8366
|
+
const {
|
|
8367
|
+
id: _versionId,
|
|
8368
|
+
skillId: _skillId,
|
|
8369
|
+
versionNumber: _versionNumber,
|
|
8370
|
+
changedFields: _changedFields,
|
|
8371
|
+
changeMessage: _changeMessage,
|
|
8372
|
+
createdAt: _createdAt,
|
|
8373
|
+
...latestConfig
|
|
8374
|
+
} = latestVersion;
|
|
8375
|
+
const newConfig = { ...latestConfig, ...configFields };
|
|
8376
|
+
const changedFields = configFieldNames.filter(
|
|
8377
|
+
(field) => field in configFields && JSON.stringify(configFields[field]) !== JSON.stringify(latestConfig[field])
|
|
8378
|
+
);
|
|
8379
|
+
if (changedFields.length > 0) {
|
|
8380
|
+
const newVersionId = crypto.randomUUID();
|
|
8381
|
+
await this.createVersion({
|
|
8382
|
+
id: newVersionId,
|
|
8383
|
+
skillId: id,
|
|
8384
|
+
versionNumber: latestVersion.versionNumber + 1,
|
|
8385
|
+
...newConfig,
|
|
8386
|
+
changedFields,
|
|
8387
|
+
changeMessage: `Updated ${changedFields.join(", ")}`
|
|
8388
|
+
});
|
|
8408
8389
|
}
|
|
8409
|
-
|
|
8410
|
-
|
|
8411
|
-
|
|
8412
|
-
|
|
8390
|
+
}
|
|
8391
|
+
const updated = await this.getById(id);
|
|
8392
|
+
if (!updated) {
|
|
8393
|
+
throw new MastraError({
|
|
8394
|
+
id: createStorageErrorId("LIBSQL", "UPDATE_SKILL", "NOT_FOUND_AFTER_UPDATE"),
|
|
8395
|
+
domain: ErrorDomain.STORAGE,
|
|
8396
|
+
category: ErrorCategory.SYSTEM,
|
|
8397
|
+
text: `Skill ${id} not found after update`,
|
|
8398
|
+
details: { id }
|
|
8413
8399
|
});
|
|
8414
|
-
await tx.commit();
|
|
8415
|
-
return updatedSnapshot;
|
|
8416
|
-
} catch (error) {
|
|
8417
|
-
if (!tx.closed) {
|
|
8418
|
-
await tx.rollback();
|
|
8419
|
-
}
|
|
8420
|
-
throw error;
|
|
8421
8400
|
}
|
|
8422
|
-
|
|
8423
|
-
|
|
8424
|
-
|
|
8425
|
-
|
|
8426
|
-
|
|
8427
|
-
|
|
8428
|
-
|
|
8429
|
-
|
|
8430
|
-
|
|
8431
|
-
|
|
8432
|
-
|
|
8433
|
-
|
|
8434
|
-
workflow_name: workflowName,
|
|
8435
|
-
run_id: runId,
|
|
8436
|
-
resourceId,
|
|
8437
|
-
snapshot,
|
|
8438
|
-
createdAt: createdAt ?? now,
|
|
8439
|
-
updatedAt: updatedAt ?? now
|
|
8440
|
-
};
|
|
8441
|
-
this.logger.debug("Persisting workflow snapshot", { workflowName, runId, data });
|
|
8442
|
-
await this.#db.insert({
|
|
8443
|
-
tableName: TABLE_WORKFLOW_SNAPSHOT,
|
|
8444
|
-
record: data
|
|
8445
|
-
});
|
|
8401
|
+
return updated;
|
|
8402
|
+
} catch (error) {
|
|
8403
|
+
if (error instanceof MastraError) throw error;
|
|
8404
|
+
throw new MastraError(
|
|
8405
|
+
{
|
|
8406
|
+
id: createStorageErrorId("LIBSQL", "UPDATE_SKILL", "FAILED"),
|
|
8407
|
+
domain: ErrorDomain.STORAGE,
|
|
8408
|
+
category: ErrorCategory.THIRD_PARTY
|
|
8409
|
+
},
|
|
8410
|
+
error
|
|
8411
|
+
);
|
|
8412
|
+
}
|
|
8446
8413
|
}
|
|
8447
|
-
async
|
|
8448
|
-
|
|
8449
|
-
|
|
8450
|
-
|
|
8451
|
-
|
|
8452
|
-
|
|
8453
|
-
|
|
8454
|
-
|
|
8414
|
+
async delete(id) {
|
|
8415
|
+
try {
|
|
8416
|
+
await this.deleteVersionsByParentId(id);
|
|
8417
|
+
await this.#client.execute({
|
|
8418
|
+
sql: `DELETE FROM "${TABLE_SKILLS}" WHERE "id" = ?`,
|
|
8419
|
+
args: [id]
|
|
8420
|
+
});
|
|
8421
|
+
} catch (error) {
|
|
8422
|
+
if (error instanceof MastraError) throw error;
|
|
8423
|
+
throw new MastraError(
|
|
8424
|
+
{
|
|
8425
|
+
id: createStorageErrorId("LIBSQL", "DELETE_SKILL", "FAILED"),
|
|
8426
|
+
domain: ErrorDomain.STORAGE,
|
|
8427
|
+
category: ErrorCategory.THIRD_PARTY
|
|
8428
|
+
},
|
|
8429
|
+
error
|
|
8430
|
+
);
|
|
8431
|
+
}
|
|
8432
|
+
}
|
|
8433
|
+
async list(args) {
|
|
8434
|
+
try {
|
|
8435
|
+
const { page = 0, perPage: perPageInput, orderBy, authorId } = args || {};
|
|
8436
|
+
const { field, direction } = this.parseOrderBy(orderBy);
|
|
8437
|
+
const conditions = [];
|
|
8438
|
+
const queryParams = [];
|
|
8439
|
+
if (authorId !== void 0) {
|
|
8440
|
+
conditions.push("authorId = ?");
|
|
8441
|
+
queryParams.push(authorId);
|
|
8442
|
+
}
|
|
8443
|
+
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
8444
|
+
const countResult = await this.#client.execute({
|
|
8445
|
+
sql: `SELECT COUNT(*) as count FROM "${TABLE_SKILLS}" ${whereClause}`,
|
|
8446
|
+
args: queryParams
|
|
8447
|
+
});
|
|
8448
|
+
const total = Number(countResult.rows?.[0]?.count ?? 0);
|
|
8449
|
+
if (total === 0) {
|
|
8450
|
+
return {
|
|
8451
|
+
skills: [],
|
|
8452
|
+
total: 0,
|
|
8453
|
+
page,
|
|
8454
|
+
perPage: perPageInput ?? 100,
|
|
8455
|
+
hasMore: false
|
|
8456
|
+
};
|
|
8457
|
+
}
|
|
8458
|
+
const perPage = normalizePerPage(perPageInput, 100);
|
|
8459
|
+
const { offset: start, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
|
|
8460
|
+
const limitValue = perPageInput === false ? total : perPage;
|
|
8461
|
+
const end = perPageInput === false ? total : start + perPage;
|
|
8462
|
+
const result = await this.#client.execute({
|
|
8463
|
+
sql: `SELECT ${buildSelectColumns(TABLE_SKILLS)} FROM "${TABLE_SKILLS}" ${whereClause} ORDER BY ${field} ${direction} LIMIT ? OFFSET ?`,
|
|
8464
|
+
args: [...queryParams, limitValue, start]
|
|
8465
|
+
});
|
|
8466
|
+
const skills = result.rows?.map((row) => this.#parseSkillRow(row)) ?? [];
|
|
8467
|
+
return {
|
|
8468
|
+
skills,
|
|
8469
|
+
total,
|
|
8470
|
+
page,
|
|
8471
|
+
perPage: perPageForResponse,
|
|
8472
|
+
hasMore: end < total
|
|
8473
|
+
};
|
|
8474
|
+
} catch (error) {
|
|
8475
|
+
if (error instanceof MastraError) throw error;
|
|
8476
|
+
throw new MastraError(
|
|
8477
|
+
{
|
|
8478
|
+
id: createStorageErrorId("LIBSQL", "LIST_SKILLS", "FAILED"),
|
|
8479
|
+
domain: ErrorDomain.STORAGE,
|
|
8480
|
+
category: ErrorCategory.THIRD_PARTY
|
|
8481
|
+
},
|
|
8482
|
+
error
|
|
8483
|
+
);
|
|
8484
|
+
}
|
|
8485
|
+
}
|
|
8486
|
+
// ==========================================================================
|
|
8487
|
+
// Skill Version Methods
|
|
8488
|
+
// ==========================================================================
|
|
8489
|
+
async createVersion(input) {
|
|
8490
|
+
try {
|
|
8491
|
+
const now = /* @__PURE__ */ new Date();
|
|
8492
|
+
await this.#client.execute({
|
|
8493
|
+
sql: `INSERT INTO "${TABLE_SKILL_VERSIONS}" (
|
|
8494
|
+
id, "skillId", "versionNumber",
|
|
8495
|
+
name, description, instructions, license, compatibility,
|
|
8496
|
+
source, "references", scripts, assets, metadata, tree,
|
|
8497
|
+
"changedFields", "changeMessage", "createdAt"
|
|
8498
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
8499
|
+
args: [
|
|
8500
|
+
input.id,
|
|
8501
|
+
input.skillId,
|
|
8502
|
+
input.versionNumber,
|
|
8503
|
+
input.name,
|
|
8504
|
+
input.description ?? null,
|
|
8505
|
+
input.instructions ?? null,
|
|
8506
|
+
input.license ?? null,
|
|
8507
|
+
input.compatibility ? JSON.stringify(input.compatibility) : null,
|
|
8508
|
+
input.source ? JSON.stringify(input.source) : null,
|
|
8509
|
+
input.references ? JSON.stringify(input.references) : null,
|
|
8510
|
+
input.scripts ? JSON.stringify(input.scripts) : null,
|
|
8511
|
+
input.assets ? JSON.stringify(input.assets) : null,
|
|
8512
|
+
input.metadata ? JSON.stringify(input.metadata) : null,
|
|
8513
|
+
input.tree ? JSON.stringify(input.tree) : null,
|
|
8514
|
+
input.changedFields ? JSON.stringify(input.changedFields) : null,
|
|
8515
|
+
input.changeMessage ?? null,
|
|
8516
|
+
now.toISOString()
|
|
8517
|
+
]
|
|
8518
|
+
});
|
|
8519
|
+
return {
|
|
8520
|
+
...input,
|
|
8521
|
+
createdAt: now
|
|
8522
|
+
};
|
|
8523
|
+
} catch (error) {
|
|
8524
|
+
if (error instanceof MastraError) throw error;
|
|
8525
|
+
throw new MastraError(
|
|
8526
|
+
{
|
|
8527
|
+
id: createStorageErrorId("LIBSQL", "CREATE_SKILL_VERSION", "FAILED"),
|
|
8528
|
+
domain: ErrorDomain.STORAGE,
|
|
8529
|
+
category: ErrorCategory.THIRD_PARTY
|
|
8530
|
+
},
|
|
8531
|
+
error
|
|
8532
|
+
);
|
|
8533
|
+
}
|
|
8534
|
+
}
|
|
8535
|
+
async getVersion(id) {
|
|
8536
|
+
try {
|
|
8537
|
+
const result = await this.#client.execute({
|
|
8538
|
+
sql: `SELECT ${buildSelectColumns(TABLE_SKILL_VERSIONS)} FROM "${TABLE_SKILL_VERSIONS}" WHERE id = ?`,
|
|
8539
|
+
args: [id]
|
|
8540
|
+
});
|
|
8541
|
+
const row = result.rows?.[0];
|
|
8542
|
+
return row ? this.#parseVersionRow(row) : null;
|
|
8543
|
+
} catch (error) {
|
|
8544
|
+
if (error instanceof MastraError) throw error;
|
|
8545
|
+
throw new MastraError(
|
|
8546
|
+
{
|
|
8547
|
+
id: createStorageErrorId("LIBSQL", "GET_SKILL_VERSION", "FAILED"),
|
|
8548
|
+
domain: ErrorDomain.STORAGE,
|
|
8549
|
+
category: ErrorCategory.THIRD_PARTY
|
|
8550
|
+
},
|
|
8551
|
+
error
|
|
8552
|
+
);
|
|
8553
|
+
}
|
|
8554
|
+
}
|
|
8555
|
+
async getVersionByNumber(skillId, versionNumber) {
|
|
8556
|
+
try {
|
|
8557
|
+
const result = await this.#client.execute({
|
|
8558
|
+
sql: `SELECT ${buildSelectColumns(TABLE_SKILL_VERSIONS)} FROM "${TABLE_SKILL_VERSIONS}" WHERE skillId = ? AND versionNumber = ?`,
|
|
8559
|
+
args: [skillId, versionNumber]
|
|
8560
|
+
});
|
|
8561
|
+
const row = result.rows?.[0];
|
|
8562
|
+
return row ? this.#parseVersionRow(row) : null;
|
|
8563
|
+
} catch (error) {
|
|
8564
|
+
if (error instanceof MastraError) throw error;
|
|
8565
|
+
throw new MastraError(
|
|
8566
|
+
{
|
|
8567
|
+
id: createStorageErrorId("LIBSQL", "GET_SKILL_VERSION_BY_NUMBER", "FAILED"),
|
|
8568
|
+
domain: ErrorDomain.STORAGE,
|
|
8569
|
+
category: ErrorCategory.THIRD_PARTY
|
|
8570
|
+
},
|
|
8571
|
+
error
|
|
8572
|
+
);
|
|
8573
|
+
}
|
|
8574
|
+
}
|
|
8575
|
+
async getLatestVersion(skillId) {
|
|
8576
|
+
try {
|
|
8577
|
+
const result = await this.#client.execute({
|
|
8578
|
+
sql: `SELECT ${buildSelectColumns(TABLE_SKILL_VERSIONS)} FROM "${TABLE_SKILL_VERSIONS}" WHERE skillId = ? ORDER BY versionNumber DESC LIMIT 1`,
|
|
8579
|
+
args: [skillId]
|
|
8580
|
+
});
|
|
8581
|
+
const row = result.rows?.[0];
|
|
8582
|
+
return row ? this.#parseVersionRow(row) : null;
|
|
8583
|
+
} catch (error) {
|
|
8584
|
+
if (error instanceof MastraError) throw error;
|
|
8585
|
+
throw new MastraError(
|
|
8586
|
+
{
|
|
8587
|
+
id: createStorageErrorId("LIBSQL", "GET_LATEST_SKILL_VERSION", "FAILED"),
|
|
8588
|
+
domain: ErrorDomain.STORAGE,
|
|
8589
|
+
category: ErrorCategory.THIRD_PARTY
|
|
8590
|
+
},
|
|
8591
|
+
error
|
|
8592
|
+
);
|
|
8593
|
+
}
|
|
8594
|
+
}
|
|
8595
|
+
async listVersions(input) {
|
|
8596
|
+
try {
|
|
8597
|
+
const { skillId, page = 0, perPage: perPageInput, orderBy } = input;
|
|
8598
|
+
const { field, direction } = this.parseVersionOrderBy(orderBy);
|
|
8599
|
+
const countResult = await this.#client.execute({
|
|
8600
|
+
sql: `SELECT COUNT(*) as count FROM "${TABLE_SKILL_VERSIONS}" WHERE skillId = ?`,
|
|
8601
|
+
args: [skillId]
|
|
8602
|
+
});
|
|
8603
|
+
const total = Number(countResult.rows?.[0]?.count ?? 0);
|
|
8604
|
+
if (total === 0) {
|
|
8605
|
+
return {
|
|
8606
|
+
versions: [],
|
|
8607
|
+
total: 0,
|
|
8608
|
+
page,
|
|
8609
|
+
perPage: perPageInput ?? 20,
|
|
8610
|
+
hasMore: false
|
|
8611
|
+
};
|
|
8612
|
+
}
|
|
8613
|
+
const perPage = normalizePerPage(perPageInput, 20);
|
|
8614
|
+
const { offset: start, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
|
|
8615
|
+
const limitValue = perPageInput === false ? total : perPage;
|
|
8616
|
+
const end = perPageInput === false ? total : start + perPage;
|
|
8617
|
+
const result = await this.#client.execute({
|
|
8618
|
+
sql: `SELECT ${buildSelectColumns(TABLE_SKILL_VERSIONS)} FROM "${TABLE_SKILL_VERSIONS}" WHERE skillId = ? ORDER BY ${field} ${direction} LIMIT ? OFFSET ?`,
|
|
8619
|
+
args: [skillId, limitValue, start]
|
|
8620
|
+
});
|
|
8621
|
+
const versions = result.rows?.map((row) => this.#parseVersionRow(row)) ?? [];
|
|
8622
|
+
return {
|
|
8623
|
+
versions,
|
|
8624
|
+
total,
|
|
8625
|
+
page,
|
|
8626
|
+
perPage: perPageForResponse,
|
|
8627
|
+
hasMore: end < total
|
|
8628
|
+
};
|
|
8629
|
+
} catch (error) {
|
|
8630
|
+
if (error instanceof MastraError) throw error;
|
|
8631
|
+
throw new MastraError(
|
|
8632
|
+
{
|
|
8633
|
+
id: createStorageErrorId("LIBSQL", "LIST_SKILL_VERSIONS", "FAILED"),
|
|
8634
|
+
domain: ErrorDomain.STORAGE,
|
|
8635
|
+
category: ErrorCategory.THIRD_PARTY
|
|
8636
|
+
},
|
|
8637
|
+
error
|
|
8638
|
+
);
|
|
8639
|
+
}
|
|
8640
|
+
}
|
|
8641
|
+
async deleteVersion(id) {
|
|
8642
|
+
try {
|
|
8643
|
+
await this.#client.execute({
|
|
8644
|
+
sql: `DELETE FROM "${TABLE_SKILL_VERSIONS}" WHERE "id" = ?`,
|
|
8645
|
+
args: [id]
|
|
8646
|
+
});
|
|
8647
|
+
} catch (error) {
|
|
8648
|
+
if (error instanceof MastraError) throw error;
|
|
8649
|
+
throw new MastraError(
|
|
8650
|
+
{
|
|
8651
|
+
id: createStorageErrorId("LIBSQL", "DELETE_SKILL_VERSION", "FAILED"),
|
|
8652
|
+
domain: ErrorDomain.STORAGE,
|
|
8653
|
+
category: ErrorCategory.THIRD_PARTY
|
|
8654
|
+
},
|
|
8655
|
+
error
|
|
8656
|
+
);
|
|
8657
|
+
}
|
|
8658
|
+
}
|
|
8659
|
+
async deleteVersionsByParentId(entityId) {
|
|
8660
|
+
try {
|
|
8661
|
+
await this.#client.execute({
|
|
8662
|
+
sql: `DELETE FROM "${TABLE_SKILL_VERSIONS}" WHERE "skillId" = ?`,
|
|
8663
|
+
args: [entityId]
|
|
8664
|
+
});
|
|
8665
|
+
} catch (error) {
|
|
8666
|
+
if (error instanceof MastraError) throw error;
|
|
8667
|
+
throw new MastraError(
|
|
8668
|
+
{
|
|
8669
|
+
id: createStorageErrorId("LIBSQL", "DELETE_SKILL_VERSIONS_BY_SKILL", "FAILED"),
|
|
8670
|
+
domain: ErrorDomain.STORAGE,
|
|
8671
|
+
category: ErrorCategory.THIRD_PARTY
|
|
8672
|
+
},
|
|
8673
|
+
error
|
|
8674
|
+
);
|
|
8675
|
+
}
|
|
8676
|
+
}
|
|
8677
|
+
async countVersions(skillId) {
|
|
8678
|
+
try {
|
|
8679
|
+
const result = await this.#client.execute({
|
|
8680
|
+
sql: `SELECT COUNT(*) as count FROM "${TABLE_SKILL_VERSIONS}" WHERE skillId = ?`,
|
|
8681
|
+
args: [skillId]
|
|
8682
|
+
});
|
|
8683
|
+
return Number(result.rows?.[0]?.count ?? 0);
|
|
8684
|
+
} catch (error) {
|
|
8685
|
+
if (error instanceof MastraError) throw error;
|
|
8686
|
+
throw new MastraError(
|
|
8687
|
+
{
|
|
8688
|
+
id: createStorageErrorId("LIBSQL", "COUNT_SKILL_VERSIONS", "FAILED"),
|
|
8689
|
+
domain: ErrorDomain.STORAGE,
|
|
8690
|
+
category: ErrorCategory.THIRD_PARTY
|
|
8691
|
+
},
|
|
8692
|
+
error
|
|
8693
|
+
);
|
|
8694
|
+
}
|
|
8695
|
+
}
|
|
8696
|
+
// ==========================================================================
|
|
8697
|
+
// Private Helpers
|
|
8698
|
+
// ==========================================================================
|
|
8699
|
+
#parseSkillRow(row) {
|
|
8700
|
+
return {
|
|
8701
|
+
id: row.id,
|
|
8702
|
+
status: row.status ?? "draft",
|
|
8703
|
+
activeVersionId: row.activeVersionId ?? void 0,
|
|
8704
|
+
authorId: row.authorId ?? void 0,
|
|
8705
|
+
createdAt: new Date(row.createdAt),
|
|
8706
|
+
updatedAt: new Date(row.updatedAt)
|
|
8707
|
+
};
|
|
8708
|
+
}
|
|
8709
|
+
#parseVersionRow(row) {
|
|
8710
|
+
const safeParseJSON = (val) => {
|
|
8711
|
+
if (val === null || val === void 0) return void 0;
|
|
8712
|
+
if (typeof val === "string") {
|
|
8713
|
+
try {
|
|
8714
|
+
return JSON.parse(val);
|
|
8715
|
+
} catch {
|
|
8716
|
+
return val;
|
|
8717
|
+
}
|
|
8718
|
+
}
|
|
8719
|
+
return val;
|
|
8720
|
+
};
|
|
8721
|
+
return {
|
|
8722
|
+
id: row.id,
|
|
8723
|
+
skillId: row.skillId,
|
|
8724
|
+
versionNumber: Number(row.versionNumber),
|
|
8725
|
+
name: row.name,
|
|
8726
|
+
description: row.description ?? void 0,
|
|
8727
|
+
instructions: row.instructions ?? void 0,
|
|
8728
|
+
license: row.license ?? void 0,
|
|
8729
|
+
compatibility: safeParseJSON(row.compatibility),
|
|
8730
|
+
source: safeParseJSON(row.source),
|
|
8731
|
+
references: safeParseJSON(row.references),
|
|
8732
|
+
scripts: safeParseJSON(row.scripts),
|
|
8733
|
+
assets: safeParseJSON(row.assets),
|
|
8734
|
+
metadata: safeParseJSON(row.metadata),
|
|
8735
|
+
tree: safeParseJSON(row.tree),
|
|
8736
|
+
changedFields: safeParseJSON(row.changedFields),
|
|
8737
|
+
changeMessage: row.changeMessage ?? void 0,
|
|
8738
|
+
createdAt: new Date(row.createdAt)
|
|
8739
|
+
};
|
|
8740
|
+
}
|
|
8741
|
+
};
|
|
8742
|
+
var WorkflowsLibSQL = class extends WorkflowsStorage {
|
|
8743
|
+
#db;
|
|
8744
|
+
#client;
|
|
8745
|
+
executeWithRetry;
|
|
8746
|
+
constructor(config) {
|
|
8747
|
+
super();
|
|
8748
|
+
const client = resolveClient(config);
|
|
8749
|
+
const maxRetries = config.maxRetries ?? 5;
|
|
8750
|
+
const initialBackoffMs = config.initialBackoffMs ?? 500;
|
|
8751
|
+
this.#client = client;
|
|
8752
|
+
this.#db = new LibSQLDB({ client, maxRetries, initialBackoffMs });
|
|
8753
|
+
this.executeWithRetry = createExecuteWriteOperationWithRetry({
|
|
8754
|
+
logger: this.logger,
|
|
8755
|
+
maxRetries,
|
|
8756
|
+
initialBackoffMs
|
|
8757
|
+
});
|
|
8758
|
+
this.setupPragmaSettings().catch(
|
|
8759
|
+
(err) => this.logger.warn("LibSQL Workflows: Failed to setup PRAGMA settings.", err)
|
|
8760
|
+
);
|
|
8761
|
+
}
|
|
8762
|
+
parseWorkflowRun(row) {
|
|
8763
|
+
let parsedSnapshot = row.snapshot;
|
|
8764
|
+
if (typeof parsedSnapshot === "string") {
|
|
8765
|
+
try {
|
|
8766
|
+
parsedSnapshot = JSON.parse(row.snapshot);
|
|
8767
|
+
} catch (e) {
|
|
8768
|
+
this.logger.warn(`Failed to parse snapshot for workflow ${row.workflow_name}: ${e}`);
|
|
8769
|
+
}
|
|
8770
|
+
}
|
|
8771
|
+
return {
|
|
8772
|
+
workflowName: row.workflow_name,
|
|
8773
|
+
runId: row.run_id,
|
|
8774
|
+
snapshot: parsedSnapshot,
|
|
8775
|
+
resourceId: row.resourceId,
|
|
8776
|
+
createdAt: new Date(row.createdAt),
|
|
8777
|
+
updatedAt: new Date(row.updatedAt)
|
|
8778
|
+
};
|
|
8779
|
+
}
|
|
8780
|
+
async init() {
|
|
8781
|
+
const schema = TABLE_SCHEMAS[TABLE_WORKFLOW_SNAPSHOT];
|
|
8782
|
+
await this.#db.createTable({ tableName: TABLE_WORKFLOW_SNAPSHOT, schema });
|
|
8783
|
+
await this.#db.alterTable({
|
|
8784
|
+
tableName: TABLE_WORKFLOW_SNAPSHOT,
|
|
8785
|
+
schema,
|
|
8786
|
+
ifNotExists: ["resourceId"]
|
|
8787
|
+
});
|
|
8788
|
+
}
|
|
8789
|
+
async dangerouslyClearAll() {
|
|
8790
|
+
await this.#db.deleteData({ tableName: TABLE_WORKFLOW_SNAPSHOT });
|
|
8791
|
+
}
|
|
8792
|
+
async setupPragmaSettings() {
|
|
8793
|
+
try {
|
|
8794
|
+
await this.#client.execute("PRAGMA busy_timeout = 10000;");
|
|
8795
|
+
this.logger.debug("LibSQL Workflows: PRAGMA busy_timeout=10000 set.");
|
|
8796
|
+
try {
|
|
8797
|
+
await this.#client.execute("PRAGMA journal_mode = WAL;");
|
|
8798
|
+
this.logger.debug("LibSQL Workflows: PRAGMA journal_mode=WAL set.");
|
|
8799
|
+
} catch {
|
|
8800
|
+
this.logger.debug("LibSQL Workflows: WAL mode not supported, using default journal mode.");
|
|
8801
|
+
}
|
|
8802
|
+
try {
|
|
8803
|
+
await this.#client.execute("PRAGMA synchronous = NORMAL;");
|
|
8804
|
+
this.logger.debug("LibSQL Workflows: PRAGMA synchronous=NORMAL set.");
|
|
8805
|
+
} catch {
|
|
8806
|
+
this.logger.debug("LibSQL Workflows: Failed to set synchronous mode.");
|
|
8807
|
+
}
|
|
8808
|
+
} catch (err) {
|
|
8809
|
+
this.logger.warn("LibSQL Workflows: Failed to set PRAGMA settings.", err);
|
|
8810
|
+
}
|
|
8811
|
+
}
|
|
8812
|
+
async updateWorkflowResults({
|
|
8813
|
+
workflowName,
|
|
8814
|
+
runId,
|
|
8815
|
+
stepId,
|
|
8816
|
+
result,
|
|
8817
|
+
requestContext
|
|
8818
|
+
}) {
|
|
8819
|
+
return this.executeWithRetry(async () => {
|
|
8820
|
+
const tx = await this.#client.transaction("write");
|
|
8821
|
+
try {
|
|
8822
|
+
const existingSnapshotResult = await tx.execute({
|
|
8823
|
+
sql: `SELECT json(snapshot) as snapshot FROM ${TABLE_WORKFLOW_SNAPSHOT} WHERE workflow_name = ? AND run_id = ?`,
|
|
8824
|
+
args: [workflowName, runId]
|
|
8825
|
+
});
|
|
8826
|
+
let snapshot;
|
|
8827
|
+
if (!existingSnapshotResult.rows?.[0]) {
|
|
8828
|
+
snapshot = {
|
|
8829
|
+
context: {},
|
|
8830
|
+
activePaths: [],
|
|
8831
|
+
timestamp: Date.now(),
|
|
8832
|
+
suspendedPaths: {},
|
|
8833
|
+
activeStepsPath: {},
|
|
8834
|
+
resumeLabels: {},
|
|
8835
|
+
serializedStepGraph: [],
|
|
8836
|
+
status: "pending",
|
|
8837
|
+
value: {},
|
|
8838
|
+
waitingPaths: {},
|
|
8839
|
+
runId,
|
|
8840
|
+
requestContext: {}
|
|
8841
|
+
};
|
|
8842
|
+
} else {
|
|
8843
|
+
const existingSnapshot = existingSnapshotResult.rows[0].snapshot;
|
|
8844
|
+
snapshot = typeof existingSnapshot === "string" ? JSON.parse(existingSnapshot) : existingSnapshot;
|
|
8845
|
+
}
|
|
8846
|
+
snapshot.context[stepId] = result;
|
|
8847
|
+
snapshot.requestContext = { ...snapshot.requestContext, ...requestContext };
|
|
8848
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
8849
|
+
await tx.execute({
|
|
8850
|
+
sql: `INSERT INTO ${TABLE_WORKFLOW_SNAPSHOT} (workflow_name, run_id, snapshot, createdAt, updatedAt)
|
|
8851
|
+
VALUES (?, ?, jsonb(?), ?, ?)
|
|
8852
|
+
ON CONFLICT(workflow_name, run_id)
|
|
8853
|
+
DO UPDATE SET snapshot = excluded.snapshot, updatedAt = excluded.updatedAt`,
|
|
8854
|
+
args: [workflowName, runId, JSON.stringify(snapshot), now, now]
|
|
8855
|
+
});
|
|
8856
|
+
await tx.commit();
|
|
8857
|
+
return snapshot.context;
|
|
8858
|
+
} catch (error) {
|
|
8859
|
+
if (!tx.closed) {
|
|
8860
|
+
await tx.rollback();
|
|
8861
|
+
}
|
|
8862
|
+
throw error;
|
|
8863
|
+
}
|
|
8864
|
+
}, "updateWorkflowResults");
|
|
8865
|
+
}
|
|
8866
|
+
async updateWorkflowState({
|
|
8867
|
+
workflowName,
|
|
8868
|
+
runId,
|
|
8869
|
+
opts
|
|
8870
|
+
}) {
|
|
8871
|
+
return this.executeWithRetry(async () => {
|
|
8872
|
+
const tx = await this.#client.transaction("write");
|
|
8873
|
+
try {
|
|
8874
|
+
const existingSnapshotResult = await tx.execute({
|
|
8875
|
+
sql: `SELECT json(snapshot) as snapshot FROM ${TABLE_WORKFLOW_SNAPSHOT} WHERE workflow_name = ? AND run_id = ?`,
|
|
8876
|
+
args: [workflowName, runId]
|
|
8877
|
+
});
|
|
8878
|
+
if (!existingSnapshotResult.rows?.[0]) {
|
|
8879
|
+
await tx.rollback();
|
|
8880
|
+
return void 0;
|
|
8881
|
+
}
|
|
8882
|
+
const existingSnapshot = existingSnapshotResult.rows[0].snapshot;
|
|
8883
|
+
const snapshot = typeof existingSnapshot === "string" ? JSON.parse(existingSnapshot) : existingSnapshot;
|
|
8884
|
+
if (!snapshot || !snapshot?.context) {
|
|
8885
|
+
await tx.rollback();
|
|
8886
|
+
throw new Error(`Snapshot not found for runId ${runId}`);
|
|
8887
|
+
}
|
|
8888
|
+
const updatedSnapshot = { ...snapshot, ...opts };
|
|
8889
|
+
await tx.execute({
|
|
8890
|
+
sql: `UPDATE ${TABLE_WORKFLOW_SNAPSHOT} SET snapshot = jsonb(?) WHERE workflow_name = ? AND run_id = ?`,
|
|
8891
|
+
args: [JSON.stringify(updatedSnapshot), workflowName, runId]
|
|
8892
|
+
});
|
|
8893
|
+
await tx.commit();
|
|
8894
|
+
return updatedSnapshot;
|
|
8895
|
+
} catch (error) {
|
|
8896
|
+
if (!tx.closed) {
|
|
8897
|
+
await tx.rollback();
|
|
8898
|
+
}
|
|
8899
|
+
throw error;
|
|
8900
|
+
}
|
|
8901
|
+
}, "updateWorkflowState");
|
|
8902
|
+
}
|
|
8903
|
+
async persistWorkflowSnapshot({
|
|
8904
|
+
workflowName,
|
|
8905
|
+
runId,
|
|
8906
|
+
resourceId,
|
|
8907
|
+
snapshot,
|
|
8908
|
+
createdAt,
|
|
8909
|
+
updatedAt
|
|
8910
|
+
}) {
|
|
8911
|
+
const now = /* @__PURE__ */ new Date();
|
|
8912
|
+
const data = {
|
|
8913
|
+
workflow_name: workflowName,
|
|
8914
|
+
run_id: runId,
|
|
8915
|
+
resourceId,
|
|
8916
|
+
snapshot,
|
|
8917
|
+
createdAt: createdAt ?? now,
|
|
8918
|
+
updatedAt: updatedAt ?? now
|
|
8919
|
+
};
|
|
8920
|
+
this.logger.debug("Persisting workflow snapshot", { workflowName, runId, data });
|
|
8921
|
+
await this.#db.insert({
|
|
8922
|
+
tableName: TABLE_WORKFLOW_SNAPSHOT,
|
|
8923
|
+
record: data
|
|
8924
|
+
});
|
|
8925
|
+
}
|
|
8926
|
+
async loadWorkflowSnapshot({
|
|
8927
|
+
workflowName,
|
|
8928
|
+
runId
|
|
8929
|
+
}) {
|
|
8930
|
+
this.logger.debug("Loading workflow snapshot", { workflowName, runId });
|
|
8931
|
+
const d = await this.#db.select({
|
|
8932
|
+
tableName: TABLE_WORKFLOW_SNAPSHOT,
|
|
8933
|
+
keys: { workflow_name: workflowName, run_id: runId }
|
|
8934
|
+
});
|
|
8935
|
+
return d ? d.snapshot : null;
|
|
8936
|
+
}
|
|
8937
|
+
async getWorkflowRunById({
|
|
8938
|
+
runId,
|
|
8939
|
+
workflowName
|
|
8940
|
+
}) {
|
|
8941
|
+
const conditions = [];
|
|
8942
|
+
const args = [];
|
|
8943
|
+
if (runId) {
|
|
8944
|
+
conditions.push("run_id = ?");
|
|
8945
|
+
args.push(runId);
|
|
8946
|
+
}
|
|
8947
|
+
if (workflowName) {
|
|
8948
|
+
conditions.push("workflow_name = ?");
|
|
8949
|
+
args.push(workflowName);
|
|
8950
|
+
}
|
|
8951
|
+
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
8952
|
+
try {
|
|
8953
|
+
const result = await this.#client.execute({
|
|
8954
|
+
sql: `SELECT workflow_name, run_id, resourceId, json(snapshot) as snapshot, createdAt, updatedAt FROM ${TABLE_WORKFLOW_SNAPSHOT} ${whereClause} ORDER BY createdAt DESC LIMIT 1`,
|
|
8955
|
+
args
|
|
8956
|
+
});
|
|
8957
|
+
if (!result.rows?.[0]) {
|
|
8958
|
+
return null;
|
|
8959
|
+
}
|
|
8960
|
+
return this.parseWorkflowRun(result.rows[0]);
|
|
8961
|
+
} catch (error) {
|
|
8962
|
+
throw new MastraError(
|
|
8963
|
+
{
|
|
8964
|
+
id: createStorageErrorId("LIBSQL", "GET_WORKFLOW_RUN_BY_ID", "FAILED"),
|
|
8965
|
+
domain: ErrorDomain.STORAGE,
|
|
8966
|
+
category: ErrorCategory.THIRD_PARTY
|
|
8967
|
+
},
|
|
8968
|
+
error
|
|
8969
|
+
);
|
|
8970
|
+
}
|
|
8971
|
+
}
|
|
8972
|
+
async deleteWorkflowRunById({ runId, workflowName }) {
|
|
8973
|
+
return this.executeWithRetry(async () => {
|
|
8974
|
+
try {
|
|
8975
|
+
await this.#client.execute({
|
|
8976
|
+
sql: `DELETE FROM ${TABLE_WORKFLOW_SNAPSHOT} WHERE workflow_name = ? AND run_id = ?`,
|
|
8977
|
+
args: [workflowName, runId]
|
|
8978
|
+
});
|
|
8979
|
+
} catch (error) {
|
|
8980
|
+
throw new MastraError(
|
|
8981
|
+
{
|
|
8982
|
+
id: createStorageErrorId("LIBSQL", "DELETE_WORKFLOW_RUN_BY_ID", "FAILED"),
|
|
8983
|
+
domain: ErrorDomain.STORAGE,
|
|
8984
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
8985
|
+
details: { runId, workflowName }
|
|
8986
|
+
},
|
|
8987
|
+
error
|
|
8988
|
+
);
|
|
8989
|
+
}
|
|
8990
|
+
}, "deleteWorkflowRunById");
|
|
8991
|
+
}
|
|
8992
|
+
async listWorkflowRuns({
|
|
8993
|
+
workflowName,
|
|
8994
|
+
fromDate,
|
|
8995
|
+
toDate,
|
|
8996
|
+
page,
|
|
8997
|
+
perPage,
|
|
8998
|
+
resourceId,
|
|
8999
|
+
status
|
|
9000
|
+
} = {}) {
|
|
9001
|
+
try {
|
|
9002
|
+
const conditions = [];
|
|
9003
|
+
const args = [];
|
|
9004
|
+
if (workflowName) {
|
|
9005
|
+
conditions.push("workflow_name = ?");
|
|
9006
|
+
args.push(workflowName);
|
|
9007
|
+
}
|
|
9008
|
+
if (status) {
|
|
9009
|
+
conditions.push("json_extract(snapshot, '$.status') = ?");
|
|
9010
|
+
args.push(status);
|
|
9011
|
+
}
|
|
9012
|
+
if (fromDate) {
|
|
9013
|
+
conditions.push("createdAt >= ?");
|
|
9014
|
+
args.push(fromDate.toISOString());
|
|
9015
|
+
}
|
|
9016
|
+
if (toDate) {
|
|
9017
|
+
conditions.push("createdAt <= ?");
|
|
9018
|
+
args.push(toDate.toISOString());
|
|
9019
|
+
}
|
|
9020
|
+
if (resourceId) {
|
|
9021
|
+
const hasResourceId = await this.#db.hasColumn(TABLE_WORKFLOW_SNAPSHOT, "resourceId");
|
|
9022
|
+
if (hasResourceId) {
|
|
9023
|
+
conditions.push("resourceId = ?");
|
|
9024
|
+
args.push(resourceId);
|
|
9025
|
+
} else {
|
|
9026
|
+
this.logger.warn(`[${TABLE_WORKFLOW_SNAPSHOT}] resourceId column not found. Skipping resourceId filter.`);
|
|
9027
|
+
}
|
|
9028
|
+
}
|
|
9029
|
+
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
9030
|
+
let total = 0;
|
|
9031
|
+
const usePagination = typeof perPage === "number" && typeof page === "number";
|
|
9032
|
+
if (usePagination) {
|
|
9033
|
+
const countResult = await this.#client.execute({
|
|
9034
|
+
sql: `SELECT COUNT(*) as count FROM ${TABLE_WORKFLOW_SNAPSHOT} ${whereClause}`,
|
|
9035
|
+
args
|
|
9036
|
+
});
|
|
9037
|
+
total = Number(countResult.rows?.[0]?.count ?? 0);
|
|
9038
|
+
}
|
|
9039
|
+
const normalizedPerPage = usePagination ? normalizePerPage(perPage, Number.MAX_SAFE_INTEGER) : 0;
|
|
9040
|
+
const offset = usePagination ? page * normalizedPerPage : 0;
|
|
9041
|
+
const result = await this.#client.execute({
|
|
9042
|
+
sql: `SELECT workflow_name, run_id, resourceId, json(snapshot) as snapshot, createdAt, updatedAt FROM ${TABLE_WORKFLOW_SNAPSHOT} ${whereClause} ORDER BY createdAt DESC${usePagination ? ` LIMIT ? OFFSET ?` : ""}`,
|
|
9043
|
+
args: usePagination ? [...args, normalizedPerPage, offset] : args
|
|
9044
|
+
});
|
|
9045
|
+
const runs = (result.rows || []).map((row) => this.parseWorkflowRun(row));
|
|
9046
|
+
return { runs, total: total || runs.length };
|
|
9047
|
+
} catch (error) {
|
|
9048
|
+
throw new MastraError(
|
|
9049
|
+
{
|
|
9050
|
+
id: createStorageErrorId("LIBSQL", "LIST_WORKFLOW_RUNS", "FAILED"),
|
|
9051
|
+
domain: ErrorDomain.STORAGE,
|
|
9052
|
+
category: ErrorCategory.THIRD_PARTY
|
|
9053
|
+
},
|
|
9054
|
+
error
|
|
9055
|
+
);
|
|
9056
|
+
}
|
|
9057
|
+
}
|
|
9058
|
+
};
|
|
9059
|
+
var SNAPSHOT_FIELDS2 = [
|
|
9060
|
+
"name",
|
|
9061
|
+
"description",
|
|
9062
|
+
"filesystem",
|
|
9063
|
+
"sandbox",
|
|
9064
|
+
"mounts",
|
|
9065
|
+
"search",
|
|
9066
|
+
"skills",
|
|
9067
|
+
"tools",
|
|
9068
|
+
"autoSync",
|
|
9069
|
+
"operationTimeout"
|
|
9070
|
+
];
|
|
9071
|
+
var WorkspacesLibSQL = class extends WorkspacesStorage {
|
|
9072
|
+
#db;
|
|
9073
|
+
#client;
|
|
9074
|
+
constructor(config) {
|
|
9075
|
+
super();
|
|
9076
|
+
const client = resolveClient(config);
|
|
9077
|
+
this.#client = client;
|
|
9078
|
+
this.#db = new LibSQLDB({ client, maxRetries: config.maxRetries, initialBackoffMs: config.initialBackoffMs });
|
|
9079
|
+
}
|
|
9080
|
+
async init() {
|
|
9081
|
+
await this.#db.createTable({ tableName: TABLE_WORKSPACES, schema: WORKSPACES_SCHEMA });
|
|
9082
|
+
await this.#db.createTable({
|
|
9083
|
+
tableName: TABLE_WORKSPACE_VERSIONS,
|
|
9084
|
+
schema: WORKSPACE_VERSIONS_SCHEMA
|
|
8455
9085
|
});
|
|
8456
|
-
|
|
9086
|
+
await this.#client.execute(
|
|
9087
|
+
`CREATE UNIQUE INDEX IF NOT EXISTS idx_workspace_versions_workspace_version ON "${TABLE_WORKSPACE_VERSIONS}" ("workspaceId", "versionNumber")`
|
|
9088
|
+
);
|
|
9089
|
+
}
|
|
9090
|
+
async dangerouslyClearAll() {
|
|
9091
|
+
await this.#db.deleteData({ tableName: TABLE_WORKSPACES });
|
|
9092
|
+
await this.#db.deleteData({ tableName: TABLE_WORKSPACE_VERSIONS });
|
|
9093
|
+
}
|
|
9094
|
+
// ==========================================================================
|
|
9095
|
+
// Workspace CRUD
|
|
9096
|
+
// ==========================================================================
|
|
9097
|
+
async getById(id) {
|
|
9098
|
+
try {
|
|
9099
|
+
const result = await this.#client.execute({
|
|
9100
|
+
sql: `SELECT ${buildSelectColumns(TABLE_WORKSPACES)} FROM "${TABLE_WORKSPACES}" WHERE id = ?`,
|
|
9101
|
+
args: [id]
|
|
9102
|
+
});
|
|
9103
|
+
const row = result.rows?.[0];
|
|
9104
|
+
return row ? this.#parseWorkspaceRow(row) : null;
|
|
9105
|
+
} catch (error) {
|
|
9106
|
+
if (error instanceof MastraError) throw error;
|
|
9107
|
+
throw new MastraError(
|
|
9108
|
+
{
|
|
9109
|
+
id: createStorageErrorId("LIBSQL", "GET_WORKSPACE", "FAILED"),
|
|
9110
|
+
domain: ErrorDomain.STORAGE,
|
|
9111
|
+
category: ErrorCategory.THIRD_PARTY
|
|
9112
|
+
},
|
|
9113
|
+
error
|
|
9114
|
+
);
|
|
9115
|
+
}
|
|
9116
|
+
}
|
|
9117
|
+
async create(input) {
|
|
9118
|
+
const { workspace } = input;
|
|
9119
|
+
try {
|
|
9120
|
+
const now = /* @__PURE__ */ new Date();
|
|
9121
|
+
await this.#db.insert({
|
|
9122
|
+
tableName: TABLE_WORKSPACES,
|
|
9123
|
+
record: {
|
|
9124
|
+
id: workspace.id,
|
|
9125
|
+
status: "draft",
|
|
9126
|
+
activeVersionId: null,
|
|
9127
|
+
authorId: workspace.authorId ?? null,
|
|
9128
|
+
metadata: workspace.metadata ?? null,
|
|
9129
|
+
createdAt: now.toISOString(),
|
|
9130
|
+
updatedAt: now.toISOString()
|
|
9131
|
+
}
|
|
9132
|
+
});
|
|
9133
|
+
const { id: _id, authorId: _authorId, metadata: _metadata, ...snapshotConfig } = workspace;
|
|
9134
|
+
const versionId = crypto.randomUUID();
|
|
9135
|
+
try {
|
|
9136
|
+
await this.createVersion({
|
|
9137
|
+
id: versionId,
|
|
9138
|
+
workspaceId: workspace.id,
|
|
9139
|
+
versionNumber: 1,
|
|
9140
|
+
...snapshotConfig,
|
|
9141
|
+
changedFields: Object.keys(snapshotConfig),
|
|
9142
|
+
changeMessage: "Initial version"
|
|
9143
|
+
});
|
|
9144
|
+
} catch (versionError) {
|
|
9145
|
+
await this.#db.delete({ tableName: TABLE_WORKSPACES, keys: { id: workspace.id } });
|
|
9146
|
+
throw versionError;
|
|
9147
|
+
}
|
|
9148
|
+
return {
|
|
9149
|
+
id: workspace.id,
|
|
9150
|
+
status: "draft",
|
|
9151
|
+
activeVersionId: void 0,
|
|
9152
|
+
authorId: workspace.authorId,
|
|
9153
|
+
metadata: workspace.metadata,
|
|
9154
|
+
createdAt: now,
|
|
9155
|
+
updatedAt: now
|
|
9156
|
+
};
|
|
9157
|
+
} catch (error) {
|
|
9158
|
+
if (error instanceof MastraError) throw error;
|
|
9159
|
+
throw new MastraError(
|
|
9160
|
+
{
|
|
9161
|
+
id: createStorageErrorId("LIBSQL", "CREATE_WORKSPACE", "FAILED"),
|
|
9162
|
+
domain: ErrorDomain.STORAGE,
|
|
9163
|
+
category: ErrorCategory.THIRD_PARTY
|
|
9164
|
+
},
|
|
9165
|
+
error
|
|
9166
|
+
);
|
|
9167
|
+
}
|
|
9168
|
+
}
|
|
9169
|
+
async update(input) {
|
|
9170
|
+
const { id, ...updates } = input;
|
|
9171
|
+
try {
|
|
9172
|
+
const existing = await this.getById(id);
|
|
9173
|
+
if (!existing) {
|
|
9174
|
+
throw new MastraError({
|
|
9175
|
+
id: createStorageErrorId("LIBSQL", "UPDATE_WORKSPACE", "NOT_FOUND"),
|
|
9176
|
+
domain: ErrorDomain.STORAGE,
|
|
9177
|
+
category: ErrorCategory.USER,
|
|
9178
|
+
text: `Workspace ${id} not found`,
|
|
9179
|
+
details: { workspaceId: id }
|
|
9180
|
+
});
|
|
9181
|
+
}
|
|
9182
|
+
const { authorId, activeVersionId, metadata, status, ...configFields } = updates;
|
|
9183
|
+
const configFieldNames = SNAPSHOT_FIELDS2;
|
|
9184
|
+
const hasConfigUpdate = configFieldNames.some((field) => field in configFields);
|
|
9185
|
+
const updateData = {
|
|
9186
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
9187
|
+
};
|
|
9188
|
+
if (authorId !== void 0) updateData.authorId = authorId;
|
|
9189
|
+
if (activeVersionId !== void 0) {
|
|
9190
|
+
updateData.activeVersionId = activeVersionId;
|
|
9191
|
+
if (status === void 0) {
|
|
9192
|
+
updateData.status = "published";
|
|
9193
|
+
}
|
|
9194
|
+
}
|
|
9195
|
+
if (status !== void 0) updateData.status = status;
|
|
9196
|
+
if (metadata !== void 0) {
|
|
9197
|
+
updateData.metadata = { ...existing.metadata || {}, ...metadata };
|
|
9198
|
+
}
|
|
9199
|
+
await this.#db.update({
|
|
9200
|
+
tableName: TABLE_WORKSPACES,
|
|
9201
|
+
keys: { id },
|
|
9202
|
+
data: updateData
|
|
9203
|
+
});
|
|
9204
|
+
if (hasConfigUpdate) {
|
|
9205
|
+
const latestVersion = await this.getLatestVersion(id);
|
|
9206
|
+
if (!latestVersion) {
|
|
9207
|
+
throw new Error(`No versions found for workspace ${id}`);
|
|
9208
|
+
}
|
|
9209
|
+
const {
|
|
9210
|
+
id: _versionId,
|
|
9211
|
+
workspaceId: _workspaceId,
|
|
9212
|
+
versionNumber: _versionNumber,
|
|
9213
|
+
changedFields: _changedFields,
|
|
9214
|
+
changeMessage: _changeMessage,
|
|
9215
|
+
createdAt: _createdAt,
|
|
9216
|
+
...latestConfig
|
|
9217
|
+
} = latestVersion;
|
|
9218
|
+
const newConfig = { ...latestConfig, ...configFields };
|
|
9219
|
+
const changedFields = configFieldNames.filter(
|
|
9220
|
+
(field) => field in configFields && JSON.stringify(configFields[field]) !== JSON.stringify(latestConfig[field])
|
|
9221
|
+
);
|
|
9222
|
+
if (changedFields.length > 0) {
|
|
9223
|
+
const newVersionId = crypto.randomUUID();
|
|
9224
|
+
await this.createVersion({
|
|
9225
|
+
id: newVersionId,
|
|
9226
|
+
workspaceId: id,
|
|
9227
|
+
versionNumber: latestVersion.versionNumber + 1,
|
|
9228
|
+
...newConfig,
|
|
9229
|
+
changedFields,
|
|
9230
|
+
changeMessage: `Updated ${changedFields.join(", ")}`
|
|
9231
|
+
});
|
|
9232
|
+
}
|
|
9233
|
+
}
|
|
9234
|
+
const updated = await this.getById(id);
|
|
9235
|
+
if (!updated) {
|
|
9236
|
+
throw new MastraError({
|
|
9237
|
+
id: createStorageErrorId("LIBSQL", "UPDATE_WORKSPACE", "NOT_FOUND_AFTER_UPDATE"),
|
|
9238
|
+
domain: ErrorDomain.STORAGE,
|
|
9239
|
+
category: ErrorCategory.SYSTEM,
|
|
9240
|
+
text: `Workspace ${id} not found after update`,
|
|
9241
|
+
details: { id }
|
|
9242
|
+
});
|
|
9243
|
+
}
|
|
9244
|
+
return updated;
|
|
9245
|
+
} catch (error) {
|
|
9246
|
+
if (error instanceof MastraError) throw error;
|
|
9247
|
+
throw new MastraError(
|
|
9248
|
+
{
|
|
9249
|
+
id: createStorageErrorId("LIBSQL", "UPDATE_WORKSPACE", "FAILED"),
|
|
9250
|
+
domain: ErrorDomain.STORAGE,
|
|
9251
|
+
category: ErrorCategory.THIRD_PARTY
|
|
9252
|
+
},
|
|
9253
|
+
error
|
|
9254
|
+
);
|
|
9255
|
+
}
|
|
9256
|
+
}
|
|
9257
|
+
async delete(id) {
|
|
9258
|
+
try {
|
|
9259
|
+
await this.deleteVersionsByParentId(id);
|
|
9260
|
+
await this.#client.execute({
|
|
9261
|
+
sql: `DELETE FROM "${TABLE_WORKSPACES}" WHERE "id" = ?`,
|
|
9262
|
+
args: [id]
|
|
9263
|
+
});
|
|
9264
|
+
} catch (error) {
|
|
9265
|
+
if (error instanceof MastraError) throw error;
|
|
9266
|
+
throw new MastraError(
|
|
9267
|
+
{
|
|
9268
|
+
id: createStorageErrorId("LIBSQL", "DELETE_WORKSPACE", "FAILED"),
|
|
9269
|
+
domain: ErrorDomain.STORAGE,
|
|
9270
|
+
category: ErrorCategory.THIRD_PARTY
|
|
9271
|
+
},
|
|
9272
|
+
error
|
|
9273
|
+
);
|
|
9274
|
+
}
|
|
9275
|
+
}
|
|
9276
|
+
async list(args) {
|
|
9277
|
+
try {
|
|
9278
|
+
const { page = 0, perPage: perPageInput, orderBy, authorId, metadata } = args || {};
|
|
9279
|
+
const { field, direction } = this.parseOrderBy(orderBy);
|
|
9280
|
+
const conditions = [];
|
|
9281
|
+
const queryParams = [];
|
|
9282
|
+
if (authorId !== void 0) {
|
|
9283
|
+
conditions.push("authorId = ?");
|
|
9284
|
+
queryParams.push(authorId);
|
|
9285
|
+
}
|
|
9286
|
+
if (metadata && Object.keys(metadata).length > 0) {
|
|
9287
|
+
for (const [key, value] of Object.entries(metadata)) {
|
|
9288
|
+
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(key)) {
|
|
9289
|
+
throw new MastraError({
|
|
9290
|
+
id: createStorageErrorId("LIBSQL", "LIST_WORKSPACES", "INVALID_METADATA_KEY"),
|
|
9291
|
+
domain: ErrorDomain.STORAGE,
|
|
9292
|
+
category: ErrorCategory.USER,
|
|
9293
|
+
text: `Invalid metadata key: ${key}. Keys must be alphanumeric with underscores.`,
|
|
9294
|
+
details: { key }
|
|
9295
|
+
});
|
|
9296
|
+
}
|
|
9297
|
+
conditions.push(`json_extract(metadata, '$.${key}') = ?`);
|
|
9298
|
+
queryParams.push(typeof value === "string" ? value : JSON.stringify(value));
|
|
9299
|
+
}
|
|
9300
|
+
}
|
|
9301
|
+
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
9302
|
+
const countResult = await this.#client.execute({
|
|
9303
|
+
sql: `SELECT COUNT(*) as count FROM "${TABLE_WORKSPACES}" ${whereClause}`,
|
|
9304
|
+
args: queryParams
|
|
9305
|
+
});
|
|
9306
|
+
const total = Number(countResult.rows?.[0]?.count ?? 0);
|
|
9307
|
+
if (total === 0) {
|
|
9308
|
+
return {
|
|
9309
|
+
workspaces: [],
|
|
9310
|
+
total: 0,
|
|
9311
|
+
page,
|
|
9312
|
+
perPage: perPageInput ?? 100,
|
|
9313
|
+
hasMore: false
|
|
9314
|
+
};
|
|
9315
|
+
}
|
|
9316
|
+
const perPage = normalizePerPage(perPageInput, 100);
|
|
9317
|
+
const { offset: start, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
|
|
9318
|
+
const limitValue = perPageInput === false ? total : perPage;
|
|
9319
|
+
const end = perPageInput === false ? total : start + perPage;
|
|
9320
|
+
const result = await this.#client.execute({
|
|
9321
|
+
sql: `SELECT ${buildSelectColumns(TABLE_WORKSPACES)} FROM "${TABLE_WORKSPACES}" ${whereClause} ORDER BY ${field} ${direction} LIMIT ? OFFSET ?`,
|
|
9322
|
+
args: [...queryParams, limitValue, start]
|
|
9323
|
+
});
|
|
9324
|
+
const workspaces = result.rows?.map((row) => this.#parseWorkspaceRow(row)) ?? [];
|
|
9325
|
+
return {
|
|
9326
|
+
workspaces,
|
|
9327
|
+
total,
|
|
9328
|
+
page,
|
|
9329
|
+
perPage: perPageForResponse,
|
|
9330
|
+
hasMore: end < total
|
|
9331
|
+
};
|
|
9332
|
+
} catch (error) {
|
|
9333
|
+
if (error instanceof MastraError) throw error;
|
|
9334
|
+
throw new MastraError(
|
|
9335
|
+
{
|
|
9336
|
+
id: createStorageErrorId("LIBSQL", "LIST_WORKSPACES", "FAILED"),
|
|
9337
|
+
domain: ErrorDomain.STORAGE,
|
|
9338
|
+
category: ErrorCategory.THIRD_PARTY
|
|
9339
|
+
},
|
|
9340
|
+
error
|
|
9341
|
+
);
|
|
9342
|
+
}
|
|
9343
|
+
}
|
|
9344
|
+
// ==========================================================================
|
|
9345
|
+
// Workspace Version Methods
|
|
9346
|
+
// ==========================================================================
|
|
9347
|
+
async createVersion(input) {
|
|
9348
|
+
try {
|
|
9349
|
+
const now = /* @__PURE__ */ new Date();
|
|
9350
|
+
await this.#client.execute({
|
|
9351
|
+
sql: `INSERT INTO "${TABLE_WORKSPACE_VERSIONS}" (
|
|
9352
|
+
id, "workspaceId", "versionNumber",
|
|
9353
|
+
name, description, filesystem, sandbox, mounts, search, skills, tools,
|
|
9354
|
+
"autoSync", "operationTimeout",
|
|
9355
|
+
"changedFields", "changeMessage", "createdAt"
|
|
9356
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
9357
|
+
args: [
|
|
9358
|
+
input.id,
|
|
9359
|
+
input.workspaceId,
|
|
9360
|
+
input.versionNumber,
|
|
9361
|
+
input.name,
|
|
9362
|
+
input.description ?? null,
|
|
9363
|
+
input.filesystem ? JSON.stringify(input.filesystem) : null,
|
|
9364
|
+
input.sandbox ? JSON.stringify(input.sandbox) : null,
|
|
9365
|
+
input.mounts ? JSON.stringify(input.mounts) : null,
|
|
9366
|
+
input.search ? JSON.stringify(input.search) : null,
|
|
9367
|
+
input.skills ? JSON.stringify(input.skills) : null,
|
|
9368
|
+
input.tools ? JSON.stringify(input.tools) : null,
|
|
9369
|
+
input.autoSync ? 1 : 0,
|
|
9370
|
+
input.operationTimeout ?? null,
|
|
9371
|
+
input.changedFields ? JSON.stringify(input.changedFields) : null,
|
|
9372
|
+
input.changeMessage ?? null,
|
|
9373
|
+
now.toISOString()
|
|
9374
|
+
]
|
|
9375
|
+
});
|
|
9376
|
+
return {
|
|
9377
|
+
...input,
|
|
9378
|
+
createdAt: now
|
|
9379
|
+
};
|
|
9380
|
+
} catch (error) {
|
|
9381
|
+
if (error instanceof MastraError) throw error;
|
|
9382
|
+
throw new MastraError(
|
|
9383
|
+
{
|
|
9384
|
+
id: createStorageErrorId("LIBSQL", "CREATE_WORKSPACE_VERSION", "FAILED"),
|
|
9385
|
+
domain: ErrorDomain.STORAGE,
|
|
9386
|
+
category: ErrorCategory.THIRD_PARTY
|
|
9387
|
+
},
|
|
9388
|
+
error
|
|
9389
|
+
);
|
|
9390
|
+
}
|
|
8457
9391
|
}
|
|
8458
|
-
async
|
|
8459
|
-
|
|
8460
|
-
|
|
8461
|
-
|
|
8462
|
-
|
|
8463
|
-
|
|
8464
|
-
|
|
8465
|
-
|
|
8466
|
-
|
|
9392
|
+
async getVersion(id) {
|
|
9393
|
+
try {
|
|
9394
|
+
const result = await this.#client.execute({
|
|
9395
|
+
sql: `SELECT ${buildSelectColumns(TABLE_WORKSPACE_VERSIONS)} FROM "${TABLE_WORKSPACE_VERSIONS}" WHERE id = ?`,
|
|
9396
|
+
args: [id]
|
|
9397
|
+
});
|
|
9398
|
+
const row = result.rows?.[0];
|
|
9399
|
+
return row ? this.#parseVersionRow(row) : null;
|
|
9400
|
+
} catch (error) {
|
|
9401
|
+
if (error instanceof MastraError) throw error;
|
|
9402
|
+
throw new MastraError(
|
|
9403
|
+
{
|
|
9404
|
+
id: createStorageErrorId("LIBSQL", "GET_WORKSPACE_VERSION", "FAILED"),
|
|
9405
|
+
domain: ErrorDomain.STORAGE,
|
|
9406
|
+
category: ErrorCategory.THIRD_PARTY
|
|
9407
|
+
},
|
|
9408
|
+
error
|
|
9409
|
+
);
|
|
8467
9410
|
}
|
|
8468
|
-
|
|
8469
|
-
|
|
8470
|
-
|
|
9411
|
+
}
|
|
9412
|
+
async getVersionByNumber(workspaceId, versionNumber) {
|
|
9413
|
+
try {
|
|
9414
|
+
const result = await this.#client.execute({
|
|
9415
|
+
sql: `SELECT ${buildSelectColumns(TABLE_WORKSPACE_VERSIONS)} FROM "${TABLE_WORKSPACE_VERSIONS}" WHERE "workspaceId" = ? AND "versionNumber" = ?`,
|
|
9416
|
+
args: [workspaceId, versionNumber]
|
|
9417
|
+
});
|
|
9418
|
+
const row = result.rows?.[0];
|
|
9419
|
+
return row ? this.#parseVersionRow(row) : null;
|
|
9420
|
+
} catch (error) {
|
|
9421
|
+
if (error instanceof MastraError) throw error;
|
|
9422
|
+
throw new MastraError(
|
|
9423
|
+
{
|
|
9424
|
+
id: createStorageErrorId("LIBSQL", "GET_WORKSPACE_VERSION_BY_NUMBER", "FAILED"),
|
|
9425
|
+
domain: ErrorDomain.STORAGE,
|
|
9426
|
+
category: ErrorCategory.THIRD_PARTY
|
|
9427
|
+
},
|
|
9428
|
+
error
|
|
9429
|
+
);
|
|
8471
9430
|
}
|
|
8472
|
-
|
|
9431
|
+
}
|
|
9432
|
+
async getLatestVersion(workspaceId) {
|
|
8473
9433
|
try {
|
|
8474
9434
|
const result = await this.#client.execute({
|
|
8475
|
-
sql: `SELECT
|
|
8476
|
-
args
|
|
9435
|
+
sql: `SELECT ${buildSelectColumns(TABLE_WORKSPACE_VERSIONS)} FROM "${TABLE_WORKSPACE_VERSIONS}" WHERE "workspaceId" = ? ORDER BY "versionNumber" DESC LIMIT 1`,
|
|
9436
|
+
args: [workspaceId]
|
|
8477
9437
|
});
|
|
8478
|
-
|
|
8479
|
-
|
|
8480
|
-
}
|
|
8481
|
-
return this.parseWorkflowRun(result.rows[0]);
|
|
9438
|
+
const row = result.rows?.[0];
|
|
9439
|
+
return row ? this.#parseVersionRow(row) : null;
|
|
8482
9440
|
} catch (error) {
|
|
9441
|
+
if (error instanceof MastraError) throw error;
|
|
8483
9442
|
throw new MastraError(
|
|
8484
9443
|
{
|
|
8485
|
-
id: createStorageErrorId("LIBSQL", "
|
|
9444
|
+
id: createStorageErrorId("LIBSQL", "GET_LATEST_WORKSPACE_VERSION", "FAILED"),
|
|
8486
9445
|
domain: ErrorDomain.STORAGE,
|
|
8487
9446
|
category: ErrorCategory.THIRD_PARTY
|
|
8488
9447
|
},
|
|
@@ -8490,85 +9449,100 @@ var WorkflowsLibSQL = class extends WorkflowsStorage {
|
|
|
8490
9449
|
);
|
|
8491
9450
|
}
|
|
8492
9451
|
}
|
|
8493
|
-
async
|
|
8494
|
-
|
|
8495
|
-
|
|
8496
|
-
|
|
8497
|
-
|
|
8498
|
-
|
|
8499
|
-
|
|
8500
|
-
}
|
|
8501
|
-
|
|
8502
|
-
|
|
8503
|
-
|
|
8504
|
-
|
|
8505
|
-
|
|
8506
|
-
|
|
8507
|
-
|
|
8508
|
-
|
|
8509
|
-
|
|
9452
|
+
async listVersions(input) {
|
|
9453
|
+
try {
|
|
9454
|
+
const { workspaceId, page = 0, perPage: perPageInput, orderBy } = input;
|
|
9455
|
+
const { field, direction } = this.parseVersionOrderBy(orderBy);
|
|
9456
|
+
const countResult = await this.#client.execute({
|
|
9457
|
+
sql: `SELECT COUNT(*) as count FROM "${TABLE_WORKSPACE_VERSIONS}" WHERE "workspaceId" = ?`,
|
|
9458
|
+
args: [workspaceId]
|
|
9459
|
+
});
|
|
9460
|
+
const total = Number(countResult.rows?.[0]?.count ?? 0);
|
|
9461
|
+
if (total === 0) {
|
|
9462
|
+
return {
|
|
9463
|
+
versions: [],
|
|
9464
|
+
total: 0,
|
|
9465
|
+
page,
|
|
9466
|
+
perPage: perPageInput ?? 20,
|
|
9467
|
+
hasMore: false
|
|
9468
|
+
};
|
|
8510
9469
|
}
|
|
8511
|
-
|
|
9470
|
+
const perPage = normalizePerPage(perPageInput, 20);
|
|
9471
|
+
const { offset: start, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
|
|
9472
|
+
const limitValue = perPageInput === false ? total : perPage;
|
|
9473
|
+
const end = perPageInput === false ? total : start + perPage;
|
|
9474
|
+
const result = await this.#client.execute({
|
|
9475
|
+
sql: `SELECT ${buildSelectColumns(TABLE_WORKSPACE_VERSIONS)} FROM "${TABLE_WORKSPACE_VERSIONS}" WHERE "workspaceId" = ? ORDER BY ${field} ${direction} LIMIT ? OFFSET ?`,
|
|
9476
|
+
args: [workspaceId, limitValue, start]
|
|
9477
|
+
});
|
|
9478
|
+
const versions = result.rows?.map((row) => this.#parseVersionRow(row)) ?? [];
|
|
9479
|
+
return {
|
|
9480
|
+
versions,
|
|
9481
|
+
total,
|
|
9482
|
+
page,
|
|
9483
|
+
perPage: perPageForResponse,
|
|
9484
|
+
hasMore: end < total
|
|
9485
|
+
};
|
|
9486
|
+
} catch (error) {
|
|
9487
|
+
if (error instanceof MastraError) throw error;
|
|
9488
|
+
throw new MastraError(
|
|
9489
|
+
{
|
|
9490
|
+
id: createStorageErrorId("LIBSQL", "LIST_WORKSPACE_VERSIONS", "FAILED"),
|
|
9491
|
+
domain: ErrorDomain.STORAGE,
|
|
9492
|
+
category: ErrorCategory.THIRD_PARTY
|
|
9493
|
+
},
|
|
9494
|
+
error
|
|
9495
|
+
);
|
|
9496
|
+
}
|
|
8512
9497
|
}
|
|
8513
|
-
async
|
|
8514
|
-
|
|
8515
|
-
|
|
8516
|
-
|
|
8517
|
-
|
|
8518
|
-
|
|
8519
|
-
|
|
8520
|
-
|
|
8521
|
-
|
|
9498
|
+
async deleteVersion(id) {
|
|
9499
|
+
try {
|
|
9500
|
+
await this.#client.execute({
|
|
9501
|
+
sql: `DELETE FROM "${TABLE_WORKSPACE_VERSIONS}" WHERE "id" = ?`,
|
|
9502
|
+
args: [id]
|
|
9503
|
+
});
|
|
9504
|
+
} catch (error) {
|
|
9505
|
+
if (error instanceof MastraError) throw error;
|
|
9506
|
+
throw new MastraError(
|
|
9507
|
+
{
|
|
9508
|
+
id: createStorageErrorId("LIBSQL", "DELETE_WORKSPACE_VERSION", "FAILED"),
|
|
9509
|
+
domain: ErrorDomain.STORAGE,
|
|
9510
|
+
category: ErrorCategory.THIRD_PARTY
|
|
9511
|
+
},
|
|
9512
|
+
error
|
|
9513
|
+
);
|
|
9514
|
+
}
|
|
9515
|
+
}
|
|
9516
|
+
async deleteVersionsByParentId(entityId) {
|
|
9517
|
+
try {
|
|
9518
|
+
await this.#client.execute({
|
|
9519
|
+
sql: `DELETE FROM "${TABLE_WORKSPACE_VERSIONS}" WHERE "workspaceId" = ?`,
|
|
9520
|
+
args: [entityId]
|
|
9521
|
+
});
|
|
9522
|
+
} catch (error) {
|
|
9523
|
+
if (error instanceof MastraError) throw error;
|
|
9524
|
+
throw new MastraError(
|
|
9525
|
+
{
|
|
9526
|
+
id: createStorageErrorId("LIBSQL", "DELETE_WORKSPACE_VERSIONS_BY_WORKSPACE", "FAILED"),
|
|
9527
|
+
domain: ErrorDomain.STORAGE,
|
|
9528
|
+
category: ErrorCategory.THIRD_PARTY
|
|
9529
|
+
},
|
|
9530
|
+
error
|
|
9531
|
+
);
|
|
9532
|
+
}
|
|
9533
|
+
}
|
|
9534
|
+
async countVersions(workspaceId) {
|
|
8522
9535
|
try {
|
|
8523
|
-
const conditions = [];
|
|
8524
|
-
const args = [];
|
|
8525
|
-
if (workflowName) {
|
|
8526
|
-
conditions.push("workflow_name = ?");
|
|
8527
|
-
args.push(workflowName);
|
|
8528
|
-
}
|
|
8529
|
-
if (status) {
|
|
8530
|
-
conditions.push("json_extract(snapshot, '$.status') = ?");
|
|
8531
|
-
args.push(status);
|
|
8532
|
-
}
|
|
8533
|
-
if (fromDate) {
|
|
8534
|
-
conditions.push("createdAt >= ?");
|
|
8535
|
-
args.push(fromDate.toISOString());
|
|
8536
|
-
}
|
|
8537
|
-
if (toDate) {
|
|
8538
|
-
conditions.push("createdAt <= ?");
|
|
8539
|
-
args.push(toDate.toISOString());
|
|
8540
|
-
}
|
|
8541
|
-
if (resourceId) {
|
|
8542
|
-
const hasResourceId = await this.#db.hasColumn(TABLE_WORKFLOW_SNAPSHOT, "resourceId");
|
|
8543
|
-
if (hasResourceId) {
|
|
8544
|
-
conditions.push("resourceId = ?");
|
|
8545
|
-
args.push(resourceId);
|
|
8546
|
-
} else {
|
|
8547
|
-
this.logger.warn(`[${TABLE_WORKFLOW_SNAPSHOT}] resourceId column not found. Skipping resourceId filter.`);
|
|
8548
|
-
}
|
|
8549
|
-
}
|
|
8550
|
-
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
8551
|
-
let total = 0;
|
|
8552
|
-
const usePagination = typeof perPage === "number" && typeof page === "number";
|
|
8553
|
-
if (usePagination) {
|
|
8554
|
-
const countResult = await this.#client.execute({
|
|
8555
|
-
sql: `SELECT COUNT(*) as count FROM ${TABLE_WORKFLOW_SNAPSHOT} ${whereClause}`,
|
|
8556
|
-
args
|
|
8557
|
-
});
|
|
8558
|
-
total = Number(countResult.rows?.[0]?.count ?? 0);
|
|
8559
|
-
}
|
|
8560
|
-
const normalizedPerPage = usePagination ? normalizePerPage(perPage, Number.MAX_SAFE_INTEGER) : 0;
|
|
8561
|
-
const offset = usePagination ? page * normalizedPerPage : 0;
|
|
8562
9536
|
const result = await this.#client.execute({
|
|
8563
|
-
sql: `SELECT
|
|
8564
|
-
args:
|
|
9537
|
+
sql: `SELECT COUNT(*) as count FROM "${TABLE_WORKSPACE_VERSIONS}" WHERE "workspaceId" = ?`,
|
|
9538
|
+
args: [workspaceId]
|
|
8565
9539
|
});
|
|
8566
|
-
|
|
8567
|
-
return { runs, total: total || runs.length };
|
|
9540
|
+
return Number(result.rows?.[0]?.count ?? 0);
|
|
8568
9541
|
} catch (error) {
|
|
9542
|
+
if (error instanceof MastraError) throw error;
|
|
8569
9543
|
throw new MastraError(
|
|
8570
9544
|
{
|
|
8571
|
-
id: createStorageErrorId("LIBSQL", "
|
|
9545
|
+
id: createStorageErrorId("LIBSQL", "COUNT_WORKSPACE_VERSIONS", "FAILED"),
|
|
8572
9546
|
domain: ErrorDomain.STORAGE,
|
|
8573
9547
|
category: ErrorCategory.THIRD_PARTY
|
|
8574
9548
|
},
|
|
@@ -8576,6 +9550,62 @@ var WorkflowsLibSQL = class extends WorkflowsStorage {
|
|
|
8576
9550
|
);
|
|
8577
9551
|
}
|
|
8578
9552
|
}
|
|
9553
|
+
// ==========================================================================
|
|
9554
|
+
// Private Helpers
|
|
9555
|
+
// ==========================================================================
|
|
9556
|
+
#parseWorkspaceRow(row) {
|
|
9557
|
+
const safeParseJSON = (val) => {
|
|
9558
|
+
if (val === null || val === void 0) return void 0;
|
|
9559
|
+
if (typeof val === "string") {
|
|
9560
|
+
try {
|
|
9561
|
+
return JSON.parse(val);
|
|
9562
|
+
} catch {
|
|
9563
|
+
return val;
|
|
9564
|
+
}
|
|
9565
|
+
}
|
|
9566
|
+
return val;
|
|
9567
|
+
};
|
|
9568
|
+
return {
|
|
9569
|
+
id: row.id,
|
|
9570
|
+
status: row.status ?? "draft",
|
|
9571
|
+
activeVersionId: row.activeVersionId ?? void 0,
|
|
9572
|
+
authorId: row.authorId ?? void 0,
|
|
9573
|
+
metadata: safeParseJSON(row.metadata),
|
|
9574
|
+
createdAt: new Date(row.createdAt),
|
|
9575
|
+
updatedAt: new Date(row.updatedAt)
|
|
9576
|
+
};
|
|
9577
|
+
}
|
|
9578
|
+
#parseVersionRow(row) {
|
|
9579
|
+
const safeParseJSON = (val) => {
|
|
9580
|
+
if (val === null || val === void 0) return void 0;
|
|
9581
|
+
if (typeof val === "string") {
|
|
9582
|
+
try {
|
|
9583
|
+
return JSON.parse(val);
|
|
9584
|
+
} catch {
|
|
9585
|
+
return val;
|
|
9586
|
+
}
|
|
9587
|
+
}
|
|
9588
|
+
return val;
|
|
9589
|
+
};
|
|
9590
|
+
return {
|
|
9591
|
+
id: row.id,
|
|
9592
|
+
workspaceId: row.workspaceId,
|
|
9593
|
+
versionNumber: Number(row.versionNumber),
|
|
9594
|
+
name: row.name,
|
|
9595
|
+
description: row.description ?? void 0,
|
|
9596
|
+
filesystem: safeParseJSON(row.filesystem),
|
|
9597
|
+
sandbox: safeParseJSON(row.sandbox),
|
|
9598
|
+
mounts: safeParseJSON(row.mounts),
|
|
9599
|
+
search: safeParseJSON(row.search),
|
|
9600
|
+
skills: safeParseJSON(row.skills),
|
|
9601
|
+
tools: safeParseJSON(row.tools),
|
|
9602
|
+
autoSync: Boolean(row.autoSync),
|
|
9603
|
+
operationTimeout: row.operationTimeout != null ? Number(row.operationTimeout) : void 0,
|
|
9604
|
+
changedFields: safeParseJSON(row.changedFields),
|
|
9605
|
+
changeMessage: row.changeMessage ?? void 0,
|
|
9606
|
+
createdAt: new Date(row.createdAt)
|
|
9607
|
+
};
|
|
9608
|
+
}
|
|
8579
9609
|
};
|
|
8580
9610
|
|
|
8581
9611
|
// src/storage/index.ts
|
|
@@ -8621,6 +9651,9 @@ var LibSQLStore = class extends MastraCompositeStore {
|
|
|
8621
9651
|
const promptBlocks = new PromptBlocksLibSQL(domainConfig);
|
|
8622
9652
|
const scorerDefinitions = new ScorerDefinitionsLibSQL(domainConfig);
|
|
8623
9653
|
const mcpClients = new MCPClientsLibSQL(domainConfig);
|
|
9654
|
+
const workspaces = new WorkspacesLibSQL(domainConfig);
|
|
9655
|
+
const skills = new SkillsLibSQL(domainConfig);
|
|
9656
|
+
const blobs = new BlobsLibSQL(domainConfig);
|
|
8624
9657
|
this.stores = {
|
|
8625
9658
|
scores,
|
|
8626
9659
|
workflows,
|
|
@@ -8631,7 +9664,10 @@ var LibSQLStore = class extends MastraCompositeStore {
|
|
|
8631
9664
|
experiments,
|
|
8632
9665
|
promptBlocks,
|
|
8633
9666
|
scorerDefinitions,
|
|
8634
|
-
mcpClients
|
|
9667
|
+
mcpClients,
|
|
9668
|
+
workspaces,
|
|
9669
|
+
skills,
|
|
9670
|
+
blobs
|
|
8635
9671
|
};
|
|
8636
9672
|
}
|
|
8637
9673
|
};
|
|
@@ -8735,6 +9771,6 @@ Example Complex Query:
|
|
|
8735
9771
|
]
|
|
8736
9772
|
}`;
|
|
8737
9773
|
|
|
8738
|
-
export { AgentsLibSQL, DatasetsLibSQL, LibSQLStore as DefaultStorage, ExperimentsLibSQL, LIBSQL_PROMPT, LibSQLStore, LibSQLVector, MCPClientsLibSQL, MemoryLibSQL, ObservabilityLibSQL, PromptBlocksLibSQL, ScorerDefinitionsLibSQL, ScoresLibSQL, WorkflowsLibSQL };
|
|
9774
|
+
export { AgentsLibSQL, BlobsLibSQL, DatasetsLibSQL, LibSQLStore as DefaultStorage, ExperimentsLibSQL, LIBSQL_PROMPT, LibSQLStore, LibSQLVector, MCPClientsLibSQL, MemoryLibSQL, ObservabilityLibSQL, PromptBlocksLibSQL, ScorerDefinitionsLibSQL, ScoresLibSQL, SkillsLibSQL, WorkflowsLibSQL, WorkspacesLibSQL };
|
|
8739
9775
|
//# sourceMappingURL=index.js.map
|
|
8740
9776
|
//# sourceMappingURL=index.js.map
|