@mastra/libsql 1.10.1-alpha.3 → 1.11.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 +59 -0
- package/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/index.cjs +433 -25
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +434 -27
- package/dist/index.js.map +1 -1
- package/dist/storage/db/utils.d.ts +5 -0
- 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/favorites/index.d.ts +17 -0
- package/dist/storage/domains/favorites/index.d.ts.map +1 -0
- package/dist/storage/domains/skills/index.d.ts.map +1 -1
- package/dist/storage/domains/workspaces/index.d.ts.map +1 -1
- package/dist/storage/index.d.ts +2 -1
- package/dist/storage/index.d.ts.map +1 -1
- package/package.json +6 -6
package/dist/index.cjs
CHANGED
|
@@ -1211,6 +1211,15 @@ function buildSelectColumns(tableName) {
|
|
|
1211
1211
|
return colDef?.type === "jsonb" ? `json("${parsedCol}") as "${parsedCol}"` : `"${parsedCol}"`;
|
|
1212
1212
|
}).join(", ");
|
|
1213
1213
|
}
|
|
1214
|
+
function buildSelectColumnsWithAlias(tableName, alias) {
|
|
1215
|
+
const parsedAlias = utils.parseSqlIdentifier(alias, "table alias");
|
|
1216
|
+
const schema = storage.TABLE_SCHEMAS[tableName];
|
|
1217
|
+
return Object.keys(schema).map((col) => {
|
|
1218
|
+
const colDef = schema[col];
|
|
1219
|
+
const parsedCol = utils.parseSqlIdentifier(col, "column name");
|
|
1220
|
+
return colDef?.type === "jsonb" ? `json(${parsedAlias}."${parsedCol}") as "${parsedCol}"` : `${parsedAlias}."${parsedCol}"`;
|
|
1221
|
+
}).join(", ");
|
|
1222
|
+
}
|
|
1214
1223
|
function isLockError(error) {
|
|
1215
1224
|
return error.code === "SQLITE_BUSY" || error.code === "SQLITE_LOCKED" || error.message?.toLowerCase().includes("database is locked") || error.message?.toLowerCase().includes("database table is locked") || error.message?.toLowerCase().includes("table is locked") || error.constructor.name === "SqliteError" && error.message?.toLowerCase().includes("locked");
|
|
1216
1225
|
}
|
|
@@ -2261,12 +2270,12 @@ var AgentsLibSQL = class extends storage.AgentsStorage {
|
|
|
2261
2270
|
await this.#db.alterTable({
|
|
2262
2271
|
tableName: storage.TABLE_AGENTS,
|
|
2263
2272
|
schema: storage.AGENTS_SCHEMA,
|
|
2264
|
-
ifNotExists: ["status", "authorId"]
|
|
2273
|
+
ifNotExists: ["status", "authorId", "visibility", "favoriteCount"]
|
|
2265
2274
|
});
|
|
2266
2275
|
await this.#db.alterTable({
|
|
2267
2276
|
tableName: storage.TABLE_AGENT_VERSIONS,
|
|
2268
2277
|
schema: storage.AGENT_VERSIONS_SCHEMA,
|
|
2269
|
-
ifNotExists: ["mcpClients", "requestContextSchema", "workspace", "skills", "skillsFormat"]
|
|
2278
|
+
ifNotExists: ["mcpClients", "requestContextSchema", "workspace", "skills", "skillsFormat", "browser"]
|
|
2270
2279
|
});
|
|
2271
2280
|
await this.#migrateToolsToJsonbFormat();
|
|
2272
2281
|
await this.#cleanupStaleDrafts();
|
|
@@ -2357,14 +2366,23 @@ var AgentsLibSQL = class extends storage.AgentsStorage {
|
|
|
2357
2366
|
});
|
|
2358
2367
|
}
|
|
2359
2368
|
/**
|
|
2360
|
-
* Removes stale draft agent records that have no
|
|
2369
|
+
* Removes stale draft agent records that have no versions at all.
|
|
2361
2370
|
* These are left behind when createAgent partially fails (inserts thin record
|
|
2362
2371
|
* but fails to create the version due to schema mismatch).
|
|
2372
|
+
*
|
|
2373
|
+
* A legitimate draft (never published) will have rows in the versions table,
|
|
2374
|
+
* so we must only delete records with zero associated versions.
|
|
2363
2375
|
*/
|
|
2364
2376
|
async #cleanupStaleDrafts() {
|
|
2365
2377
|
try {
|
|
2366
2378
|
await this.#client.execute({
|
|
2367
|
-
sql: `DELETE FROM "${storage.TABLE_AGENTS}"
|
|
2379
|
+
sql: `DELETE FROM "${storage.TABLE_AGENTS}"
|
|
2380
|
+
WHERE status = 'draft'
|
|
2381
|
+
AND activeVersionId IS NULL
|
|
2382
|
+
AND NOT EXISTS (
|
|
2383
|
+
SELECT 1 FROM "${storage.TABLE_AGENT_VERSIONS}"
|
|
2384
|
+
WHERE "${storage.TABLE_AGENT_VERSIONS}".agentId = "${storage.TABLE_AGENTS}".id
|
|
2385
|
+
)`
|
|
2368
2386
|
});
|
|
2369
2387
|
} catch {
|
|
2370
2388
|
}
|
|
@@ -2459,7 +2477,9 @@ var AgentsLibSQL = class extends storage.AgentsStorage {
|
|
|
2459
2477
|
status: row.status,
|
|
2460
2478
|
activeVersionId: row.activeVersionId,
|
|
2461
2479
|
authorId: row.authorId,
|
|
2480
|
+
visibility: row.visibility ?? void 0,
|
|
2462
2481
|
metadata: this.parseJson(row.metadata, "metadata"),
|
|
2482
|
+
favoriteCount: row.favoriteCount === null || row.favoriteCount === void 0 ? 0 : Number(row.favoriteCount),
|
|
2463
2483
|
createdAt: new Date(row.createdAt),
|
|
2464
2484
|
updatedAt: new Date(row.updatedAt)
|
|
2465
2485
|
};
|
|
@@ -2488,6 +2508,7 @@ var AgentsLibSQL = class extends storage.AgentsStorage {
|
|
|
2488
2508
|
const { agent } = input;
|
|
2489
2509
|
try {
|
|
2490
2510
|
const now = /* @__PURE__ */ new Date();
|
|
2511
|
+
const visibility = agent.visibility ?? (agent.authorId ? "private" : null);
|
|
2491
2512
|
await this.#db.insert({
|
|
2492
2513
|
tableName: storage.TABLE_AGENTS,
|
|
2493
2514
|
record: {
|
|
@@ -2495,12 +2516,14 @@ var AgentsLibSQL = class extends storage.AgentsStorage {
|
|
|
2495
2516
|
status: "draft",
|
|
2496
2517
|
activeVersionId: null,
|
|
2497
2518
|
authorId: agent.authorId ?? null,
|
|
2519
|
+
visibility,
|
|
2498
2520
|
metadata: agent.metadata ?? null,
|
|
2521
|
+
favoriteCount: 0,
|
|
2499
2522
|
createdAt: now,
|
|
2500
2523
|
updatedAt: now
|
|
2501
2524
|
}
|
|
2502
2525
|
});
|
|
2503
|
-
const { id: _id, authorId: _authorId, metadata: _metadata, ...snapshotConfig } = agent;
|
|
2526
|
+
const { id: _id, authorId: _authorId, visibility: _visibility, metadata: _metadata, ...snapshotConfig } = agent;
|
|
2504
2527
|
const versionId = crypto.randomUUID();
|
|
2505
2528
|
await this.createVersion({
|
|
2506
2529
|
id: versionId,
|
|
@@ -2549,13 +2572,14 @@ var AgentsLibSQL = class extends storage.AgentsStorage {
|
|
|
2549
2572
|
details: { agentId: id }
|
|
2550
2573
|
});
|
|
2551
2574
|
}
|
|
2552
|
-
const { authorId, activeVersionId, metadata, status } = updates;
|
|
2575
|
+
const { authorId, activeVersionId, metadata, status, visibility } = updates;
|
|
2553
2576
|
const updateData = {
|
|
2554
2577
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
2555
2578
|
};
|
|
2556
2579
|
if (authorId !== void 0) updateData.authorId = authorId;
|
|
2557
2580
|
if (activeVersionId !== void 0) updateData.activeVersionId = activeVersionId;
|
|
2558
2581
|
if (status !== void 0) updateData.status = status;
|
|
2582
|
+
if (visibility !== void 0) updateData.visibility = visibility;
|
|
2559
2583
|
if (metadata !== void 0) {
|
|
2560
2584
|
updateData.metadata = { ...existing.metadata, ...metadata };
|
|
2561
2585
|
}
|
|
@@ -2611,7 +2635,18 @@ var AgentsLibSQL = class extends storage.AgentsStorage {
|
|
|
2611
2635
|
}
|
|
2612
2636
|
}
|
|
2613
2637
|
async list(args) {
|
|
2614
|
-
const {
|
|
2638
|
+
const {
|
|
2639
|
+
page = 0,
|
|
2640
|
+
perPage: perPageInput,
|
|
2641
|
+
orderBy,
|
|
2642
|
+
authorId,
|
|
2643
|
+
metadata,
|
|
2644
|
+
status,
|
|
2645
|
+
visibility,
|
|
2646
|
+
entityIds,
|
|
2647
|
+
pinFavoritedFor,
|
|
2648
|
+
favoritedOnly
|
|
2649
|
+
} = args || {};
|
|
2615
2650
|
const { field, direction } = this.parseOrderBy(orderBy);
|
|
2616
2651
|
if (page < 0) {
|
|
2617
2652
|
throw new error.MastraError(
|
|
@@ -2627,16 +2662,29 @@ var AgentsLibSQL = class extends storage.AgentsStorage {
|
|
|
2627
2662
|
const perPage = storage.normalizePerPage(perPageInput, 100);
|
|
2628
2663
|
const { offset, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
|
|
2629
2664
|
try {
|
|
2665
|
+
if (entityIds && entityIds.length === 0) {
|
|
2666
|
+
return {
|
|
2667
|
+
agents: [],
|
|
2668
|
+
total: 0,
|
|
2669
|
+
page,
|
|
2670
|
+
perPage: perPageForResponse,
|
|
2671
|
+
hasMore: false
|
|
2672
|
+
};
|
|
2673
|
+
}
|
|
2630
2674
|
const conditions = [];
|
|
2631
2675
|
const queryParams = [];
|
|
2632
2676
|
if (status) {
|
|
2633
|
-
conditions.push("status = ?");
|
|
2677
|
+
conditions.push("a.status = ?");
|
|
2634
2678
|
queryParams.push(status);
|
|
2635
2679
|
}
|
|
2636
2680
|
if (authorId !== void 0) {
|
|
2637
|
-
conditions.push("authorId = ?");
|
|
2681
|
+
conditions.push("a.authorId = ?");
|
|
2638
2682
|
queryParams.push(authorId);
|
|
2639
2683
|
}
|
|
2684
|
+
if (visibility !== void 0) {
|
|
2685
|
+
conditions.push("a.visibility = ?");
|
|
2686
|
+
queryParams.push(visibility);
|
|
2687
|
+
}
|
|
2640
2688
|
if (metadata && Object.keys(metadata).length > 0) {
|
|
2641
2689
|
for (const [key, value] of Object.entries(metadata)) {
|
|
2642
2690
|
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(key)) {
|
|
@@ -2648,14 +2696,32 @@ var AgentsLibSQL = class extends storage.AgentsStorage {
|
|
|
2648
2696
|
details: { key }
|
|
2649
2697
|
});
|
|
2650
2698
|
}
|
|
2651
|
-
conditions.push(`json_extract(metadata, '$.${key}') = ?`);
|
|
2699
|
+
conditions.push(`json_extract(a.metadata, '$.${key}') = ?`);
|
|
2652
2700
|
queryParams.push(typeof value === "string" ? value : JSON.stringify(value));
|
|
2653
2701
|
}
|
|
2654
2702
|
}
|
|
2703
|
+
if (entityIds && entityIds.length > 0) {
|
|
2704
|
+
const placeholders = entityIds.map(() => "?").join(", ");
|
|
2705
|
+
conditions.push(`a.id IN (${placeholders})`);
|
|
2706
|
+
queryParams.push(...entityIds);
|
|
2707
|
+
}
|
|
2708
|
+
const joinUserId = pinFavoritedFor;
|
|
2709
|
+
const useJoin = Boolean(joinUserId);
|
|
2710
|
+
let joinClause = "";
|
|
2711
|
+
const joinParams = [];
|
|
2712
|
+
if (useJoin && joinUserId) {
|
|
2713
|
+
joinClause = `LEFT JOIN "${storage.TABLE_FAVORITES}" s ON s."entityType" = 'agent' AND s."entityId" = a.id AND s."userId" = ?`;
|
|
2714
|
+
joinParams.push(joinUserId);
|
|
2715
|
+
if (favoritedOnly) {
|
|
2716
|
+
conditions.push('s."userId" IS NOT NULL');
|
|
2717
|
+
}
|
|
2718
|
+
} else if (favoritedOnly) {
|
|
2719
|
+
conditions.push("1=0");
|
|
2720
|
+
}
|
|
2655
2721
|
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
2656
2722
|
const countResult = await this.#client.execute({
|
|
2657
|
-
sql: `SELECT COUNT(*) as count FROM "${storage.TABLE_AGENTS}" ${whereClause}`,
|
|
2658
|
-
args: queryParams
|
|
2723
|
+
sql: `SELECT COUNT(*) as count FROM "${storage.TABLE_AGENTS}" a ${joinClause} ${whereClause}`,
|
|
2724
|
+
args: [...joinParams, ...queryParams]
|
|
2659
2725
|
});
|
|
2660
2726
|
const total = Number(countResult.rows?.[0]?.count ?? 0);
|
|
2661
2727
|
if (total === 0) {
|
|
@@ -2667,10 +2733,18 @@ var AgentsLibSQL = class extends storage.AgentsStorage {
|
|
|
2667
2733
|
hasMore: false
|
|
2668
2734
|
};
|
|
2669
2735
|
}
|
|
2736
|
+
const orderByParts = [];
|
|
2737
|
+
if (useJoin && joinUserId) {
|
|
2738
|
+
orderByParts.push(`(s."userId" IS NOT NULL) DESC`);
|
|
2739
|
+
}
|
|
2740
|
+
orderByParts.push(`a."${field}" ${direction}`);
|
|
2741
|
+
orderByParts.push(`a."id" ASC`);
|
|
2742
|
+
const orderByClause = `ORDER BY ${orderByParts.join(", ")}`;
|
|
2670
2743
|
const limitValue = perPageInput === false ? total : perPage;
|
|
2744
|
+
const selectCols = buildSelectColumnsWithAlias(storage.TABLE_AGENTS, "a");
|
|
2671
2745
|
const result = await this.#client.execute({
|
|
2672
|
-
sql: `SELECT ${
|
|
2673
|
-
args: [...queryParams, limitValue, offset]
|
|
2746
|
+
sql: `SELECT ${selectCols} FROM "${storage.TABLE_AGENTS}" a ${joinClause} ${whereClause} ${orderByClause} LIMIT ? OFFSET ?`,
|
|
2747
|
+
args: [...joinParams, ...queryParams, limitValue, offset]
|
|
2674
2748
|
});
|
|
2675
2749
|
const rows = result.rows ?? [];
|
|
2676
2750
|
const agents = rows.map((row) => this.parseRow(row));
|
|
@@ -2723,6 +2797,7 @@ var AgentsLibSQL = class extends storage.AgentsStorage {
|
|
|
2723
2797
|
workspace: input.workspace ?? null,
|
|
2724
2798
|
skills: input.skills ?? null,
|
|
2725
2799
|
skillsFormat: input.skillsFormat ?? null,
|
|
2800
|
+
browser: input.browser ?? null,
|
|
2726
2801
|
changedFields: input.changedFields ?? null,
|
|
2727
2802
|
changeMessage: input.changeMessage ?? null,
|
|
2728
2803
|
createdAt: now
|
|
@@ -2996,6 +3071,7 @@ var AgentsLibSQL = class extends storage.AgentsStorage {
|
|
|
2996
3071
|
workspace: this.parseJson(row.workspace, "workspace"),
|
|
2997
3072
|
skills: this.parseJson(row.skills, "skills"),
|
|
2998
3073
|
skillsFormat: row.skillsFormat,
|
|
3074
|
+
browser: this.parseJson(row.browser, "browser"),
|
|
2999
3075
|
changedFields: this.parseJson(row.changedFields, "changedFields"),
|
|
3000
3076
|
changeMessage: row.changeMessage,
|
|
3001
3077
|
createdAt: new Date(row.createdAt)
|
|
@@ -4977,6 +5053,255 @@ var ExperimentsLibSQL = class extends storage.ExperimentsStorage {
|
|
|
4977
5053
|
}
|
|
4978
5054
|
}
|
|
4979
5055
|
};
|
|
5056
|
+
var ENTITY_TABLE = {
|
|
5057
|
+
agent: storage.TABLE_AGENTS,
|
|
5058
|
+
skill: storage.TABLE_SKILLS
|
|
5059
|
+
};
|
|
5060
|
+
var FavoritesLibSQL = class extends storage.FavoritesStorage {
|
|
5061
|
+
#db;
|
|
5062
|
+
#client;
|
|
5063
|
+
constructor(config) {
|
|
5064
|
+
super();
|
|
5065
|
+
const client = resolveClient(config);
|
|
5066
|
+
this.#client = client;
|
|
5067
|
+
this.#db = new LibSQLDB({ client, maxRetries: config.maxRetries, initialBackoffMs: config.initialBackoffMs });
|
|
5068
|
+
}
|
|
5069
|
+
async init() {
|
|
5070
|
+
await this.#db.createTable({
|
|
5071
|
+
tableName: storage.TABLE_FAVORITES,
|
|
5072
|
+
schema: storage.FAVORITES_SCHEMA,
|
|
5073
|
+
compositePrimaryKey: ["userId", "entityType", "entityId"]
|
|
5074
|
+
});
|
|
5075
|
+
await this.#client.execute(
|
|
5076
|
+
`CREATE INDEX IF NOT EXISTS idx_favorites_entity ON "${storage.TABLE_FAVORITES}" ("entityType", "entityId")`
|
|
5077
|
+
);
|
|
5078
|
+
}
|
|
5079
|
+
async dangerouslyClearAll() {
|
|
5080
|
+
const tx = await this.#client.transaction("write");
|
|
5081
|
+
try {
|
|
5082
|
+
await tx.execute(`DELETE FROM "${storage.TABLE_FAVORITES}"`);
|
|
5083
|
+
await tx.execute(`UPDATE "${storage.TABLE_AGENTS}" SET "favoriteCount" = 0 WHERE "favoriteCount" > 0`);
|
|
5084
|
+
await tx.execute(`UPDATE "${storage.TABLE_SKILLS}" SET "favoriteCount" = 0 WHERE "favoriteCount" > 0`);
|
|
5085
|
+
await tx.commit();
|
|
5086
|
+
} catch (error) {
|
|
5087
|
+
if (!tx.closed) {
|
|
5088
|
+
await tx.rollback();
|
|
5089
|
+
}
|
|
5090
|
+
throw error;
|
|
5091
|
+
}
|
|
5092
|
+
}
|
|
5093
|
+
async favorite(input) {
|
|
5094
|
+
const { userId, entityType, entityId } = input;
|
|
5095
|
+
const entityTable = ENTITY_TABLE[entityType];
|
|
5096
|
+
try {
|
|
5097
|
+
const tx = await this.#client.transaction("write");
|
|
5098
|
+
try {
|
|
5099
|
+
const entityRow = await tx.execute({
|
|
5100
|
+
sql: `SELECT "favoriteCount" FROM "${entityTable}" WHERE id = ?`,
|
|
5101
|
+
args: [entityId]
|
|
5102
|
+
});
|
|
5103
|
+
if (!entityRow.rows?.[0]) {
|
|
5104
|
+
throw new error.MastraError({
|
|
5105
|
+
id: storage.createStorageErrorId("LIBSQL", "FAVORITE", "ENTITY_NOT_FOUND"),
|
|
5106
|
+
domain: error.ErrorDomain.STORAGE,
|
|
5107
|
+
category: error.ErrorCategory.USER,
|
|
5108
|
+
text: `${entityType} ${entityId} not found`,
|
|
5109
|
+
details: { entityType, entityId }
|
|
5110
|
+
});
|
|
5111
|
+
}
|
|
5112
|
+
const inserted = await tx.execute({
|
|
5113
|
+
sql: `INSERT OR IGNORE INTO "${storage.TABLE_FAVORITES}" ("userId", "entityType", "entityId", "createdAt") VALUES (?, ?, ?, ?)`,
|
|
5114
|
+
args: [userId, entityType, entityId, (/* @__PURE__ */ new Date()).toISOString()]
|
|
5115
|
+
});
|
|
5116
|
+
if ((inserted.rowsAffected ?? 0) > 0) {
|
|
5117
|
+
await tx.execute({
|
|
5118
|
+
sql: `UPDATE "${entityTable}" SET "favoriteCount" = COALESCE("favoriteCount", 0) + 1 WHERE id = ?`,
|
|
5119
|
+
args: [entityId]
|
|
5120
|
+
});
|
|
5121
|
+
}
|
|
5122
|
+
const after = await tx.execute({
|
|
5123
|
+
sql: `SELECT "favoriteCount" FROM "${entityTable}" WHERE id = ?`,
|
|
5124
|
+
args: [entityId]
|
|
5125
|
+
});
|
|
5126
|
+
const favoriteCount = Number(after.rows?.[0]?.favoriteCount ?? 0);
|
|
5127
|
+
await tx.commit();
|
|
5128
|
+
return { favorited: true, favoriteCount };
|
|
5129
|
+
} catch (error) {
|
|
5130
|
+
if (!tx.closed) {
|
|
5131
|
+
await tx.rollback();
|
|
5132
|
+
}
|
|
5133
|
+
throw error;
|
|
5134
|
+
}
|
|
5135
|
+
} catch (error$1) {
|
|
5136
|
+
if (error$1 instanceof error.MastraError) throw error$1;
|
|
5137
|
+
throw new error.MastraError(
|
|
5138
|
+
{
|
|
5139
|
+
id: storage.createStorageErrorId("LIBSQL", "FAVORITE", "FAILED"),
|
|
5140
|
+
domain: error.ErrorDomain.STORAGE,
|
|
5141
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
5142
|
+
details: { entityType, entityId }
|
|
5143
|
+
},
|
|
5144
|
+
error$1
|
|
5145
|
+
);
|
|
5146
|
+
}
|
|
5147
|
+
}
|
|
5148
|
+
async unfavorite(input) {
|
|
5149
|
+
const { userId, entityType, entityId } = input;
|
|
5150
|
+
const entityTable = ENTITY_TABLE[entityType];
|
|
5151
|
+
try {
|
|
5152
|
+
const tx = await this.#client.transaction("write");
|
|
5153
|
+
try {
|
|
5154
|
+
const entityRow = await tx.execute({
|
|
5155
|
+
sql: `SELECT "favoriteCount" FROM "${entityTable}" WHERE id = ?`,
|
|
5156
|
+
args: [entityId]
|
|
5157
|
+
});
|
|
5158
|
+
if (!entityRow.rows?.[0]) {
|
|
5159
|
+
throw new error.MastraError({
|
|
5160
|
+
id: storage.createStorageErrorId("LIBSQL", "UNFAVORITE", "ENTITY_NOT_FOUND"),
|
|
5161
|
+
domain: error.ErrorDomain.STORAGE,
|
|
5162
|
+
category: error.ErrorCategory.USER,
|
|
5163
|
+
text: `${entityType} ${entityId} not found`,
|
|
5164
|
+
details: { entityType, entityId }
|
|
5165
|
+
});
|
|
5166
|
+
}
|
|
5167
|
+
const deleted = await tx.execute({
|
|
5168
|
+
sql: `DELETE FROM "${storage.TABLE_FAVORITES}" WHERE "userId" = ? AND "entityType" = ? AND "entityId" = ?`,
|
|
5169
|
+
args: [userId, entityType, entityId]
|
|
5170
|
+
});
|
|
5171
|
+
if ((deleted.rowsAffected ?? 0) > 0) {
|
|
5172
|
+
await tx.execute({
|
|
5173
|
+
sql: `UPDATE "${entityTable}" SET "favoriteCount" = MAX(COALESCE("favoriteCount", 0) - 1, 0) WHERE id = ?`,
|
|
5174
|
+
args: [entityId]
|
|
5175
|
+
});
|
|
5176
|
+
}
|
|
5177
|
+
const after = await tx.execute({
|
|
5178
|
+
sql: `SELECT "favoriteCount" FROM "${entityTable}" WHERE id = ?`,
|
|
5179
|
+
args: [entityId]
|
|
5180
|
+
});
|
|
5181
|
+
const favoriteCount = Number(after.rows?.[0]?.favoriteCount ?? 0);
|
|
5182
|
+
await tx.commit();
|
|
5183
|
+
return { favorited: false, favoriteCount };
|
|
5184
|
+
} catch (error) {
|
|
5185
|
+
if (!tx.closed) {
|
|
5186
|
+
await tx.rollback();
|
|
5187
|
+
}
|
|
5188
|
+
throw error;
|
|
5189
|
+
}
|
|
5190
|
+
} catch (error$1) {
|
|
5191
|
+
if (error$1 instanceof error.MastraError) throw error$1;
|
|
5192
|
+
throw new error.MastraError(
|
|
5193
|
+
{
|
|
5194
|
+
id: storage.createStorageErrorId("LIBSQL", "UNFAVORITE", "FAILED"),
|
|
5195
|
+
domain: error.ErrorDomain.STORAGE,
|
|
5196
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
5197
|
+
details: { entityType, entityId }
|
|
5198
|
+
},
|
|
5199
|
+
error$1
|
|
5200
|
+
);
|
|
5201
|
+
}
|
|
5202
|
+
}
|
|
5203
|
+
async isFavorited(input) {
|
|
5204
|
+
try {
|
|
5205
|
+
const result = await this.#client.execute({
|
|
5206
|
+
sql: `SELECT 1 FROM "${storage.TABLE_FAVORITES}" WHERE "userId" = ? AND "entityType" = ? AND "entityId" = ? LIMIT 1`,
|
|
5207
|
+
args: [input.userId, input.entityType, input.entityId]
|
|
5208
|
+
});
|
|
5209
|
+
return (result.rows?.length ?? 0) > 0;
|
|
5210
|
+
} catch (error$1) {
|
|
5211
|
+
if (error$1 instanceof error.MastraError) throw error$1;
|
|
5212
|
+
throw new error.MastraError(
|
|
5213
|
+
{
|
|
5214
|
+
id: storage.createStorageErrorId("LIBSQL", "IS_FAVORITED", "FAILED"),
|
|
5215
|
+
domain: error.ErrorDomain.STORAGE,
|
|
5216
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
5217
|
+
},
|
|
5218
|
+
error$1
|
|
5219
|
+
);
|
|
5220
|
+
}
|
|
5221
|
+
}
|
|
5222
|
+
async isFavoritedBatch(input) {
|
|
5223
|
+
const { userId, entityType, entityIds } = input;
|
|
5224
|
+
if (entityIds.length === 0) {
|
|
5225
|
+
return /* @__PURE__ */ new Set();
|
|
5226
|
+
}
|
|
5227
|
+
try {
|
|
5228
|
+
const placeholders = entityIds.map(() => "?").join(", ");
|
|
5229
|
+
const args = [userId, entityType, ...entityIds];
|
|
5230
|
+
const result = await this.#client.execute({
|
|
5231
|
+
sql: `SELECT "entityId" FROM "${storage.TABLE_FAVORITES}" WHERE "userId" = ? AND "entityType" = ? AND "entityId" IN (${placeholders})`,
|
|
5232
|
+
args
|
|
5233
|
+
});
|
|
5234
|
+
const set = /* @__PURE__ */ new Set();
|
|
5235
|
+
for (const row of result.rows ?? []) {
|
|
5236
|
+
set.add(row.entityId);
|
|
5237
|
+
}
|
|
5238
|
+
return set;
|
|
5239
|
+
} catch (error$1) {
|
|
5240
|
+
if (error$1 instanceof error.MastraError) throw error$1;
|
|
5241
|
+
throw new error.MastraError(
|
|
5242
|
+
{
|
|
5243
|
+
id: storage.createStorageErrorId("LIBSQL", "IS_FAVORITED_BATCH", "FAILED"),
|
|
5244
|
+
domain: error.ErrorDomain.STORAGE,
|
|
5245
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
5246
|
+
},
|
|
5247
|
+
error$1
|
|
5248
|
+
);
|
|
5249
|
+
}
|
|
5250
|
+
}
|
|
5251
|
+
async listFavoritedIds(input) {
|
|
5252
|
+
try {
|
|
5253
|
+
const result = await this.#client.execute({
|
|
5254
|
+
sql: `SELECT "entityId" FROM "${storage.TABLE_FAVORITES}" WHERE "userId" = ? AND "entityType" = ? ORDER BY "createdAt" DESC, "entityId" ASC`,
|
|
5255
|
+
args: [input.userId, input.entityType]
|
|
5256
|
+
});
|
|
5257
|
+
return (result.rows ?? []).map((row) => row.entityId);
|
|
5258
|
+
} catch (error$1) {
|
|
5259
|
+
if (error$1 instanceof error.MastraError) throw error$1;
|
|
5260
|
+
throw new error.MastraError(
|
|
5261
|
+
{
|
|
5262
|
+
id: storage.createStorageErrorId("LIBSQL", "LIST_FAVORITED_IDS", "FAILED"),
|
|
5263
|
+
domain: error.ErrorDomain.STORAGE,
|
|
5264
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
5265
|
+
},
|
|
5266
|
+
error$1
|
|
5267
|
+
);
|
|
5268
|
+
}
|
|
5269
|
+
}
|
|
5270
|
+
async deleteFavoritesForEntity(input) {
|
|
5271
|
+
const entityTable = ENTITY_TABLE[input.entityType];
|
|
5272
|
+
try {
|
|
5273
|
+
const tx = await this.#client.transaction("write");
|
|
5274
|
+
try {
|
|
5275
|
+
const result = await tx.execute({
|
|
5276
|
+
sql: `DELETE FROM "${storage.TABLE_FAVORITES}" WHERE "entityType" = ? AND "entityId" = ?`,
|
|
5277
|
+
args: [input.entityType, input.entityId]
|
|
5278
|
+
});
|
|
5279
|
+
await tx.execute({
|
|
5280
|
+
sql: `UPDATE "${entityTable}" SET "favoriteCount" = 0 WHERE id = ?`,
|
|
5281
|
+
args: [input.entityId]
|
|
5282
|
+
});
|
|
5283
|
+
await tx.commit();
|
|
5284
|
+
return Number(result.rowsAffected ?? 0);
|
|
5285
|
+
} catch (txError) {
|
|
5286
|
+
if (!tx.closed) {
|
|
5287
|
+
await tx.rollback();
|
|
5288
|
+
}
|
|
5289
|
+
throw txError;
|
|
5290
|
+
}
|
|
5291
|
+
} catch (error$1) {
|
|
5292
|
+
if (error$1 instanceof error.MastraError) throw error$1;
|
|
5293
|
+
throw new error.MastraError(
|
|
5294
|
+
{
|
|
5295
|
+
id: storage.createStorageErrorId("LIBSQL", "DELETE_FAVORITES_FOR_ENTITY", "FAILED"),
|
|
5296
|
+
domain: error.ErrorDomain.STORAGE,
|
|
5297
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
5298
|
+
details: { entityType: input.entityType, entityId: input.entityId }
|
|
5299
|
+
},
|
|
5300
|
+
error$1
|
|
5301
|
+
);
|
|
5302
|
+
}
|
|
5303
|
+
}
|
|
5304
|
+
};
|
|
4980
5305
|
var MCPClientsLibSQL = class extends storage.MCPClientsStorage {
|
|
4981
5306
|
#db;
|
|
4982
5307
|
#client;
|
|
@@ -10048,6 +10373,7 @@ var SNAPSHOT_FIELDS = [
|
|
|
10048
10373
|
"references",
|
|
10049
10374
|
"scripts",
|
|
10050
10375
|
"assets",
|
|
10376
|
+
"files",
|
|
10051
10377
|
"metadata",
|
|
10052
10378
|
"tree"
|
|
10053
10379
|
];
|
|
@@ -10066,6 +10392,16 @@ var SkillsLibSQL = class extends storage.SkillsStorage {
|
|
|
10066
10392
|
tableName: storage.TABLE_SKILL_VERSIONS,
|
|
10067
10393
|
schema: storage.SKILL_VERSIONS_SCHEMA
|
|
10068
10394
|
});
|
|
10395
|
+
await this.#db.alterTable({
|
|
10396
|
+
tableName: storage.TABLE_SKILLS,
|
|
10397
|
+
schema: storage.SKILLS_SCHEMA,
|
|
10398
|
+
ifNotExists: ["visibility", "favoriteCount"]
|
|
10399
|
+
});
|
|
10400
|
+
await this.#db.alterTable({
|
|
10401
|
+
tableName: storage.TABLE_SKILL_VERSIONS,
|
|
10402
|
+
schema: storage.SKILL_VERSIONS_SCHEMA,
|
|
10403
|
+
ifNotExists: ["files"]
|
|
10404
|
+
});
|
|
10069
10405
|
await this.#client.execute(
|
|
10070
10406
|
`CREATE UNIQUE INDEX IF NOT EXISTS idx_skill_versions_skill_version ON "${storage.TABLE_SKILL_VERSIONS}" ("skillId", "versionNumber")`
|
|
10071
10407
|
);
|
|
@@ -10101,6 +10437,7 @@ var SkillsLibSQL = class extends storage.SkillsStorage {
|
|
|
10101
10437
|
const { skill } = input;
|
|
10102
10438
|
try {
|
|
10103
10439
|
const now = /* @__PURE__ */ new Date();
|
|
10440
|
+
const visibility = skill.visibility ?? (skill.authorId ? "private" : void 0);
|
|
10104
10441
|
await this.#db.insert({
|
|
10105
10442
|
tableName: storage.TABLE_SKILLS,
|
|
10106
10443
|
record: {
|
|
@@ -10108,11 +10445,13 @@ var SkillsLibSQL = class extends storage.SkillsStorage {
|
|
|
10108
10445
|
status: "draft",
|
|
10109
10446
|
activeVersionId: null,
|
|
10110
10447
|
authorId: skill.authorId ?? null,
|
|
10448
|
+
visibility: visibility ?? null,
|
|
10449
|
+
favoriteCount: 0,
|
|
10111
10450
|
createdAt: now.toISOString(),
|
|
10112
10451
|
updatedAt: now.toISOString()
|
|
10113
10452
|
}
|
|
10114
10453
|
});
|
|
10115
|
-
const { id: _id, authorId: _authorId, ...snapshotConfig } = skill;
|
|
10454
|
+
const { id: _id, authorId: _authorId, visibility: _visibility, ...snapshotConfig } = skill;
|
|
10116
10455
|
const versionId = crypto.randomUUID();
|
|
10117
10456
|
try {
|
|
10118
10457
|
await this.createVersion({
|
|
@@ -10160,13 +10499,18 @@ var SkillsLibSQL = class extends storage.SkillsStorage {
|
|
|
10160
10499
|
details: { skillId: id }
|
|
10161
10500
|
});
|
|
10162
10501
|
}
|
|
10163
|
-
const { authorId, activeVersionId, status, ...
|
|
10502
|
+
const { authorId, visibility, activeVersionId, status, ...rawConfigFields } = updates;
|
|
10503
|
+
const configFields = {};
|
|
10504
|
+
for (const [key, value] of Object.entries(rawConfigFields)) {
|
|
10505
|
+
if (value !== void 0) configFields[key] = value;
|
|
10506
|
+
}
|
|
10164
10507
|
const configFieldNames = SNAPSHOT_FIELDS;
|
|
10165
10508
|
const hasConfigUpdate = configFieldNames.some((field) => field in configFields);
|
|
10166
10509
|
const updateData = {
|
|
10167
10510
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
10168
10511
|
};
|
|
10169
10512
|
if (authorId !== void 0) updateData.authorId = authorId;
|
|
10513
|
+
if (visibility !== void 0) updateData.visibility = visibility;
|
|
10170
10514
|
if (activeVersionId !== void 0) {
|
|
10171
10515
|
updateData.activeVersionId = activeVersionId;
|
|
10172
10516
|
if (status === void 0) {
|
|
@@ -10259,18 +10603,63 @@ var SkillsLibSQL = class extends storage.SkillsStorage {
|
|
|
10259
10603
|
}
|
|
10260
10604
|
async list(args) {
|
|
10261
10605
|
try {
|
|
10262
|
-
const {
|
|
10606
|
+
const {
|
|
10607
|
+
page = 0,
|
|
10608
|
+
perPage: perPageInput,
|
|
10609
|
+
orderBy,
|
|
10610
|
+
authorId,
|
|
10611
|
+
visibility,
|
|
10612
|
+
status,
|
|
10613
|
+
entityIds,
|
|
10614
|
+
pinFavoritedFor,
|
|
10615
|
+
favoritedOnly
|
|
10616
|
+
} = args || {};
|
|
10263
10617
|
const { field, direction } = this.parseOrderBy(orderBy);
|
|
10618
|
+
if (entityIds && entityIds.length === 0) {
|
|
10619
|
+
return {
|
|
10620
|
+
skills: [],
|
|
10621
|
+
total: 0,
|
|
10622
|
+
page,
|
|
10623
|
+
perPage: perPageInput ?? 100,
|
|
10624
|
+
hasMore: false
|
|
10625
|
+
};
|
|
10626
|
+
}
|
|
10264
10627
|
const conditions = [];
|
|
10265
10628
|
const queryParams = [];
|
|
10266
10629
|
if (authorId !== void 0) {
|
|
10267
|
-
conditions.push("authorId = ?");
|
|
10630
|
+
conditions.push("s_e.authorId = ?");
|
|
10268
10631
|
queryParams.push(authorId);
|
|
10269
10632
|
}
|
|
10633
|
+
if (visibility !== void 0) {
|
|
10634
|
+
conditions.push("s_e.visibility = ?");
|
|
10635
|
+
queryParams.push(visibility);
|
|
10636
|
+
}
|
|
10637
|
+
if (status !== void 0) {
|
|
10638
|
+
conditions.push("s_e.status = ?");
|
|
10639
|
+
queryParams.push(status);
|
|
10640
|
+
}
|
|
10641
|
+
if (entityIds && entityIds.length > 0) {
|
|
10642
|
+
const placeholders = entityIds.map(() => "?").join(", ");
|
|
10643
|
+
conditions.push(`s_e.id IN (${placeholders})`);
|
|
10644
|
+
queryParams.push(...entityIds);
|
|
10645
|
+
}
|
|
10646
|
+
const joinUserId = pinFavoritedFor;
|
|
10647
|
+
const useJoin = Boolean(joinUserId);
|
|
10648
|
+
let joinClause = "";
|
|
10649
|
+
const joinParams = [];
|
|
10650
|
+
if (useJoin && joinUserId) {
|
|
10651
|
+
joinClause = `LEFT JOIN "${storage.TABLE_FAVORITES}" st ON st."entityType" = 'skill' AND st."entityId" = s_e.id AND st."userId" = ?`;
|
|
10652
|
+
joinParams.push(joinUserId);
|
|
10653
|
+
if (favoritedOnly) {
|
|
10654
|
+
conditions.push('st."userId" IS NOT NULL');
|
|
10655
|
+
}
|
|
10656
|
+
} else if (favoritedOnly) {
|
|
10657
|
+
conditions.push("1=0");
|
|
10658
|
+
}
|
|
10270
10659
|
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
10271
10660
|
const countResult = await this.#client.execute({
|
|
10272
|
-
sql: `SELECT COUNT(*) as count FROM "${storage.TABLE_SKILLS}" ${whereClause}`,
|
|
10273
|
-
args: queryParams
|
|
10661
|
+
sql: `SELECT COUNT(*) as count FROM "${storage.TABLE_SKILLS}" s_e ${joinClause} ${whereClause}`,
|
|
10662
|
+
args: [...joinParams, ...queryParams]
|
|
10274
10663
|
});
|
|
10275
10664
|
const total = Number(countResult.rows?.[0]?.count ?? 0);
|
|
10276
10665
|
if (total === 0) {
|
|
@@ -10286,9 +10675,17 @@ var SkillsLibSQL = class extends storage.SkillsStorage {
|
|
|
10286
10675
|
const { offset: start, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
|
|
10287
10676
|
const limitValue = perPageInput === false ? total : perPage;
|
|
10288
10677
|
const end = perPageInput === false ? total : start + perPage;
|
|
10678
|
+
const orderByParts = [];
|
|
10679
|
+
if (useJoin && joinUserId) {
|
|
10680
|
+
orderByParts.push(`(st."userId" IS NOT NULL) DESC`);
|
|
10681
|
+
}
|
|
10682
|
+
orderByParts.push(`s_e."${field}" ${direction}`);
|
|
10683
|
+
orderByParts.push(`s_e."id" ASC`);
|
|
10684
|
+
const orderByClause = `ORDER BY ${orderByParts.join(", ")}`;
|
|
10685
|
+
const selectCols = buildSelectColumnsWithAlias(storage.TABLE_SKILLS, "s_e");
|
|
10289
10686
|
const result = await this.#client.execute({
|
|
10290
|
-
sql: `SELECT ${
|
|
10291
|
-
args: [...queryParams, limitValue, start]
|
|
10687
|
+
sql: `SELECT ${selectCols} FROM "${storage.TABLE_SKILLS}" s_e ${joinClause} ${whereClause} ${orderByClause} LIMIT ? OFFSET ?`,
|
|
10688
|
+
args: [...joinParams, ...queryParams, limitValue, start]
|
|
10292
10689
|
});
|
|
10293
10690
|
const skills = result.rows?.map((row) => this.#parseSkillRow(row)) ?? [];
|
|
10294
10691
|
return {
|
|
@@ -10320,9 +10717,9 @@ var SkillsLibSQL = class extends storage.SkillsStorage {
|
|
|
10320
10717
|
sql: `INSERT INTO "${storage.TABLE_SKILL_VERSIONS}" (
|
|
10321
10718
|
id, "skillId", "versionNumber",
|
|
10322
10719
|
name, description, instructions, license, compatibility,
|
|
10323
|
-
source, "references", scripts, assets, metadata, tree,
|
|
10720
|
+
source, "references", scripts, assets, files, metadata, tree,
|
|
10324
10721
|
"changedFields", "changeMessage", "createdAt"
|
|
10325
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
10722
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
10326
10723
|
args: [
|
|
10327
10724
|
input.id,
|
|
10328
10725
|
input.skillId,
|
|
@@ -10336,6 +10733,7 @@ var SkillsLibSQL = class extends storage.SkillsStorage {
|
|
|
10336
10733
|
input.references ? JSON.stringify(input.references) : null,
|
|
10337
10734
|
input.scripts ? JSON.stringify(input.scripts) : null,
|
|
10338
10735
|
input.assets ? JSON.stringify(input.assets) : null,
|
|
10736
|
+
input.files ? JSON.stringify(input.files) : null,
|
|
10339
10737
|
input.metadata ? JSON.stringify(input.metadata) : null,
|
|
10340
10738
|
input.tree ? JSON.stringify(input.tree) : null,
|
|
10341
10739
|
input.changedFields ? JSON.stringify(input.changedFields) : null,
|
|
@@ -10529,6 +10927,8 @@ var SkillsLibSQL = class extends storage.SkillsStorage {
|
|
|
10529
10927
|
status: row.status ?? "draft",
|
|
10530
10928
|
activeVersionId: row.activeVersionId ?? void 0,
|
|
10531
10929
|
authorId: row.authorId ?? void 0,
|
|
10930
|
+
visibility: row.visibility ?? void 0,
|
|
10931
|
+
favoriteCount: row.favoriteCount === null || row.favoriteCount === void 0 ? 0 : Number(row.favoriteCount),
|
|
10532
10932
|
createdAt: new Date(row.createdAt),
|
|
10533
10933
|
updatedAt: new Date(row.updatedAt)
|
|
10534
10934
|
};
|
|
@@ -10558,6 +10958,7 @@ var SkillsLibSQL = class extends storage.SkillsStorage {
|
|
|
10558
10958
|
references: safeParseJSON(row.references),
|
|
10559
10959
|
scripts: safeParseJSON(row.scripts),
|
|
10560
10960
|
assets: safeParseJSON(row.assets),
|
|
10961
|
+
files: safeParseJSON(row.files),
|
|
10561
10962
|
metadata: safeParseJSON(row.metadata),
|
|
10562
10963
|
tree: safeParseJSON(row.tree),
|
|
10563
10964
|
changedFields: safeParseJSON(row.changedFields),
|
|
@@ -11009,7 +11410,11 @@ var WorkspacesLibSQL = class extends storage.WorkspacesStorage {
|
|
|
11009
11410
|
details: { workspaceId: id }
|
|
11010
11411
|
});
|
|
11011
11412
|
}
|
|
11012
|
-
const { authorId, activeVersionId, metadata, status, ...
|
|
11413
|
+
const { authorId, activeVersionId, metadata, status, ...rawConfigFields } = updates;
|
|
11414
|
+
const configFields = {};
|
|
11415
|
+
for (const [key, value] of Object.entries(rawConfigFields)) {
|
|
11416
|
+
if (value !== void 0) configFields[key] = value;
|
|
11417
|
+
}
|
|
11013
11418
|
const configFieldNames = SNAPSHOT_FIELDS2;
|
|
11014
11419
|
const hasConfigUpdate = configFieldNames.some((field) => field in configFields);
|
|
11015
11420
|
const updateData = {
|
|
@@ -11494,6 +11899,7 @@ var LibSQLStore = class extends storage.MastraCompositeStore {
|
|
|
11494
11899
|
const mcpServers = new MCPServersLibSQL(domainConfig);
|
|
11495
11900
|
const workspaces = new WorkspacesLibSQL(domainConfig);
|
|
11496
11901
|
const skills = new SkillsLibSQL(domainConfig);
|
|
11902
|
+
const favorites = new FavoritesLibSQL(domainConfig);
|
|
11497
11903
|
const blobs = new BlobsLibSQL(domainConfig);
|
|
11498
11904
|
const backgroundTasks = new BackgroundTasksLibSQL(domainConfig);
|
|
11499
11905
|
const schedules = new SchedulesLibSQL(domainConfig);
|
|
@@ -11512,6 +11918,7 @@ var LibSQLStore = class extends storage.MastraCompositeStore {
|
|
|
11512
11918
|
mcpServers,
|
|
11513
11919
|
workspaces,
|
|
11514
11920
|
skills,
|
|
11921
|
+
favorites,
|
|
11515
11922
|
blobs,
|
|
11516
11923
|
backgroundTasks,
|
|
11517
11924
|
schedules
|
|
@@ -11682,6 +12089,7 @@ exports.ChannelsLibSQL = ChannelsLibSQL;
|
|
|
11682
12089
|
exports.DatasetsLibSQL = DatasetsLibSQL;
|
|
11683
12090
|
exports.DefaultStorage = LibSQLStore;
|
|
11684
12091
|
exports.ExperimentsLibSQL = ExperimentsLibSQL;
|
|
12092
|
+
exports.FavoritesLibSQL = FavoritesLibSQL;
|
|
11685
12093
|
exports.LIBSQL_PROMPT = LIBSQL_PROMPT;
|
|
11686
12094
|
exports.LibSQLStore = LibSQLStore;
|
|
11687
12095
|
exports.LibSQLVector = LibSQLVector;
|