@mastra/libsql 1.3.0-alpha.1 → 1.4.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 +101 -0
- package/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/docs/references/guides-agent-frameworks-ai-sdk.md +6 -2
- package/dist/index.cjs +1972 -175
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1971 -177
- package/dist/index.js.map +1 -1
- package/dist/storage/db/index.d.ts +2 -1
- package/dist/storage/db/index.d.ts.map +1 -1
- package/dist/storage/domains/agents/index.d.ts.map +1 -1
- package/dist/storage/domains/datasets/index.d.ts +43 -0
- package/dist/storage/domains/datasets/index.d.ts.map +1 -0
- package/dist/storage/domains/experiments/index.d.ts +29 -0
- package/dist/storage/domains/experiments/index.d.ts.map +1 -0
- package/dist/storage/domains/mcp-clients/index.d.ts +26 -0
- package/dist/storage/domains/mcp-clients/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 +6 -6
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, 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
|
|
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';
|
|
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';
|
|
@@ -1690,17 +1690,30 @@ var LibSQLDB = class extends MastraBase {
|
|
|
1690
1690
|
*/
|
|
1691
1691
|
async createTable({
|
|
1692
1692
|
tableName,
|
|
1693
|
-
schema
|
|
1693
|
+
schema,
|
|
1694
|
+
compositePrimaryKey
|
|
1694
1695
|
}) {
|
|
1695
1696
|
try {
|
|
1696
1697
|
const parsedTableName = parseSqlIdentifier(tableName, "table name");
|
|
1698
|
+
if (compositePrimaryKey) {
|
|
1699
|
+
for (const col of compositePrimaryKey) {
|
|
1700
|
+
if (!(col in schema)) {
|
|
1701
|
+
throw new Error(`compositePrimaryKey column "${col}" does not exist in schema for table "${tableName}"`);
|
|
1702
|
+
}
|
|
1703
|
+
}
|
|
1704
|
+
}
|
|
1705
|
+
const compositePKSet = compositePrimaryKey ? new Set(compositePrimaryKey) : null;
|
|
1697
1706
|
const columnDefinitions = Object.entries(schema).map(([colName, colDef]) => {
|
|
1698
1707
|
const type = this.getSqlType(colDef.type);
|
|
1699
1708
|
const nullable = colDef.nullable === false ? "NOT NULL" : "";
|
|
1700
|
-
const primaryKey = colDef.primaryKey ? "PRIMARY KEY" : "";
|
|
1709
|
+
const primaryKey = colDef.primaryKey && !compositePKSet?.has(colName) ? "PRIMARY KEY" : "";
|
|
1701
1710
|
return `"${colName}" ${type} ${nullable} ${primaryKey}`.trim();
|
|
1702
1711
|
});
|
|
1703
1712
|
const tableConstraints = [];
|
|
1713
|
+
if (compositePrimaryKey) {
|
|
1714
|
+
const pkCols = compositePrimaryKey.map((c) => `"${c}"`).join(", ");
|
|
1715
|
+
tableConstraints.push(`PRIMARY KEY (${pkCols})`);
|
|
1716
|
+
}
|
|
1704
1717
|
if (tableName === TABLE_WORKFLOW_SNAPSHOT) {
|
|
1705
1718
|
tableConstraints.push("UNIQUE (workflow_name, run_id)");
|
|
1706
1719
|
}
|
|
@@ -2053,7 +2066,9 @@ var SNAPSHOT_FIELDS = [
|
|
|
2053
2066
|
"inputProcessors",
|
|
2054
2067
|
"outputProcessors",
|
|
2055
2068
|
"memory",
|
|
2056
|
-
"scorers"
|
|
2069
|
+
"scorers",
|
|
2070
|
+
"mcpClients",
|
|
2071
|
+
"requestContextSchema"
|
|
2057
2072
|
];
|
|
2058
2073
|
var AgentsLibSQL = class extends AgentsStorage {
|
|
2059
2074
|
#db;
|
|
@@ -2483,33 +2498,1858 @@ var AgentsLibSQL = class extends AgentsStorage {
|
|
|
2483
2498
|
const total = await this.#db.selectTotalCount({ tableName: TABLE_AGENTS });
|
|
2484
2499
|
if (total === 0) {
|
|
2485
2500
|
return {
|
|
2486
|
-
agents: [],
|
|
2501
|
+
agents: [],
|
|
2502
|
+
total: 0,
|
|
2503
|
+
page,
|
|
2504
|
+
perPage: perPageForResponse,
|
|
2505
|
+
hasMore: false
|
|
2506
|
+
};
|
|
2507
|
+
}
|
|
2508
|
+
const limitValue = perPageInput === false ? total : perPage;
|
|
2509
|
+
const rows = await this.#db.selectMany({
|
|
2510
|
+
tableName: TABLE_AGENTS,
|
|
2511
|
+
orderBy: `"${field}" ${direction}`,
|
|
2512
|
+
limit: limitValue,
|
|
2513
|
+
offset
|
|
2514
|
+
});
|
|
2515
|
+
const agents = rows.map((row) => this.parseRow(row));
|
|
2516
|
+
return {
|
|
2517
|
+
agents,
|
|
2518
|
+
total,
|
|
2519
|
+
page,
|
|
2520
|
+
perPage: perPageForResponse,
|
|
2521
|
+
hasMore: perPageInput === false ? false : offset + perPage < total
|
|
2522
|
+
};
|
|
2523
|
+
} catch (error) {
|
|
2524
|
+
if (error instanceof MastraError) throw error;
|
|
2525
|
+
throw new MastraError(
|
|
2526
|
+
{
|
|
2527
|
+
id: createStorageErrorId("LIBSQL", "LIST_AGENTS", "FAILED"),
|
|
2528
|
+
domain: ErrorDomain.STORAGE,
|
|
2529
|
+
category: ErrorCategory.THIRD_PARTY
|
|
2530
|
+
},
|
|
2531
|
+
error
|
|
2532
|
+
);
|
|
2533
|
+
}
|
|
2534
|
+
}
|
|
2535
|
+
// ==========================================================================
|
|
2536
|
+
// Agent Version Methods
|
|
2537
|
+
// ==========================================================================
|
|
2538
|
+
async createVersion(input) {
|
|
2539
|
+
try {
|
|
2540
|
+
const now = /* @__PURE__ */ new Date();
|
|
2541
|
+
await this.#db.insert({
|
|
2542
|
+
tableName: TABLE_AGENT_VERSIONS,
|
|
2543
|
+
record: {
|
|
2544
|
+
id: input.id,
|
|
2545
|
+
agentId: input.agentId,
|
|
2546
|
+
versionNumber: input.versionNumber,
|
|
2547
|
+
name: input.name ?? null,
|
|
2548
|
+
description: input.description ?? null,
|
|
2549
|
+
instructions: this.serializeInstructions(input.instructions),
|
|
2550
|
+
model: input.model,
|
|
2551
|
+
tools: input.tools ?? null,
|
|
2552
|
+
defaultOptions: input.defaultOptions ?? null,
|
|
2553
|
+
workflows: input.workflows ?? null,
|
|
2554
|
+
agents: input.agents ?? null,
|
|
2555
|
+
integrationTools: input.integrationTools ?? null,
|
|
2556
|
+
inputProcessors: input.inputProcessors ?? null,
|
|
2557
|
+
outputProcessors: input.outputProcessors ?? null,
|
|
2558
|
+
memory: input.memory ?? null,
|
|
2559
|
+
scorers: input.scorers ?? null,
|
|
2560
|
+
mcpClients: input.mcpClients ?? null,
|
|
2561
|
+
requestContextSchema: input.requestContextSchema ?? null,
|
|
2562
|
+
changedFields: input.changedFields ?? null,
|
|
2563
|
+
changeMessage: input.changeMessage ?? null,
|
|
2564
|
+
createdAt: now
|
|
2565
|
+
}
|
|
2566
|
+
});
|
|
2567
|
+
return {
|
|
2568
|
+
...input,
|
|
2569
|
+
createdAt: now
|
|
2570
|
+
};
|
|
2571
|
+
} catch (error) {
|
|
2572
|
+
if (error instanceof MastraError) throw error;
|
|
2573
|
+
throw new MastraError(
|
|
2574
|
+
{
|
|
2575
|
+
id: createStorageErrorId("LIBSQL", "CREATE_VERSION", "FAILED"),
|
|
2576
|
+
domain: ErrorDomain.STORAGE,
|
|
2577
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
2578
|
+
details: { versionId: input.id, agentId: input.agentId }
|
|
2579
|
+
},
|
|
2580
|
+
error
|
|
2581
|
+
);
|
|
2582
|
+
}
|
|
2583
|
+
}
|
|
2584
|
+
async getVersion(id) {
|
|
2585
|
+
try {
|
|
2586
|
+
const result = await this.#db.select({
|
|
2587
|
+
tableName: TABLE_AGENT_VERSIONS,
|
|
2588
|
+
keys: { id }
|
|
2589
|
+
});
|
|
2590
|
+
if (!result) {
|
|
2591
|
+
return null;
|
|
2592
|
+
}
|
|
2593
|
+
return this.parseVersionRow(result);
|
|
2594
|
+
} catch (error) {
|
|
2595
|
+
if (error instanceof MastraError) throw error;
|
|
2596
|
+
throw new MastraError(
|
|
2597
|
+
{
|
|
2598
|
+
id: createStorageErrorId("LIBSQL", "GET_VERSION", "FAILED"),
|
|
2599
|
+
domain: ErrorDomain.STORAGE,
|
|
2600
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
2601
|
+
details: { versionId: id }
|
|
2602
|
+
},
|
|
2603
|
+
error
|
|
2604
|
+
);
|
|
2605
|
+
}
|
|
2606
|
+
}
|
|
2607
|
+
async getVersionByNumber(agentId, versionNumber) {
|
|
2608
|
+
try {
|
|
2609
|
+
const rows = await this.#db.selectMany({
|
|
2610
|
+
tableName: TABLE_AGENT_VERSIONS,
|
|
2611
|
+
whereClause: {
|
|
2612
|
+
sql: "WHERE agentId = ? AND versionNumber = ?",
|
|
2613
|
+
args: [agentId, versionNumber]
|
|
2614
|
+
},
|
|
2615
|
+
limit: 1
|
|
2616
|
+
});
|
|
2617
|
+
if (!rows || rows.length === 0) {
|
|
2618
|
+
return null;
|
|
2619
|
+
}
|
|
2620
|
+
return this.parseVersionRow(rows[0]);
|
|
2621
|
+
} catch (error) {
|
|
2622
|
+
if (error instanceof MastraError) throw error;
|
|
2623
|
+
throw new MastraError(
|
|
2624
|
+
{
|
|
2625
|
+
id: createStorageErrorId("LIBSQL", "GET_VERSION_BY_NUMBER", "FAILED"),
|
|
2626
|
+
domain: ErrorDomain.STORAGE,
|
|
2627
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
2628
|
+
details: { agentId, versionNumber }
|
|
2629
|
+
},
|
|
2630
|
+
error
|
|
2631
|
+
);
|
|
2632
|
+
}
|
|
2633
|
+
}
|
|
2634
|
+
async getLatestVersion(agentId) {
|
|
2635
|
+
try {
|
|
2636
|
+
const rows = await this.#db.selectMany({
|
|
2637
|
+
tableName: TABLE_AGENT_VERSIONS,
|
|
2638
|
+
whereClause: {
|
|
2639
|
+
sql: "WHERE agentId = ?",
|
|
2640
|
+
args: [agentId]
|
|
2641
|
+
},
|
|
2642
|
+
orderBy: "versionNumber DESC",
|
|
2643
|
+
limit: 1
|
|
2644
|
+
});
|
|
2645
|
+
if (!rows || rows.length === 0) {
|
|
2646
|
+
return null;
|
|
2647
|
+
}
|
|
2648
|
+
return this.parseVersionRow(rows[0]);
|
|
2649
|
+
} catch (error) {
|
|
2650
|
+
if (error instanceof MastraError) throw error;
|
|
2651
|
+
throw new MastraError(
|
|
2652
|
+
{
|
|
2653
|
+
id: createStorageErrorId("LIBSQL", "GET_LATEST_VERSION", "FAILED"),
|
|
2654
|
+
domain: ErrorDomain.STORAGE,
|
|
2655
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
2656
|
+
details: { agentId }
|
|
2657
|
+
},
|
|
2658
|
+
error
|
|
2659
|
+
);
|
|
2660
|
+
}
|
|
2661
|
+
}
|
|
2662
|
+
async listVersions(input) {
|
|
2663
|
+
const { agentId, page = 0, perPage: perPageInput, orderBy } = input;
|
|
2664
|
+
if (page < 0) {
|
|
2665
|
+
throw new MastraError(
|
|
2666
|
+
{
|
|
2667
|
+
id: createStorageErrorId("LIBSQL", "LIST_VERSIONS", "INVALID_PAGE"),
|
|
2668
|
+
domain: ErrorDomain.STORAGE,
|
|
2669
|
+
category: ErrorCategory.USER,
|
|
2670
|
+
details: { page }
|
|
2671
|
+
},
|
|
2672
|
+
new Error("page must be >= 0")
|
|
2673
|
+
);
|
|
2674
|
+
}
|
|
2675
|
+
const perPage = normalizePerPage(perPageInput, 20);
|
|
2676
|
+
const { offset, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
|
|
2677
|
+
try {
|
|
2678
|
+
const { field, direction } = this.parseVersionOrderBy(orderBy);
|
|
2679
|
+
const total = await this.#db.selectTotalCount({
|
|
2680
|
+
tableName: TABLE_AGENT_VERSIONS,
|
|
2681
|
+
whereClause: {
|
|
2682
|
+
sql: "WHERE agentId = ?",
|
|
2683
|
+
args: [agentId]
|
|
2684
|
+
}
|
|
2685
|
+
});
|
|
2686
|
+
if (total === 0) {
|
|
2687
|
+
return {
|
|
2688
|
+
versions: [],
|
|
2689
|
+
total: 0,
|
|
2690
|
+
page,
|
|
2691
|
+
perPage: perPageForResponse,
|
|
2692
|
+
hasMore: false
|
|
2693
|
+
};
|
|
2694
|
+
}
|
|
2695
|
+
const limitValue = perPageInput === false ? total : perPage;
|
|
2696
|
+
const rows = await this.#db.selectMany({
|
|
2697
|
+
tableName: TABLE_AGENT_VERSIONS,
|
|
2698
|
+
whereClause: {
|
|
2699
|
+
sql: "WHERE agentId = ?",
|
|
2700
|
+
args: [agentId]
|
|
2701
|
+
},
|
|
2702
|
+
orderBy: `"${field}" ${direction}`,
|
|
2703
|
+
limit: limitValue,
|
|
2704
|
+
offset
|
|
2705
|
+
});
|
|
2706
|
+
const versions = rows.map((row) => this.parseVersionRow(row));
|
|
2707
|
+
return {
|
|
2708
|
+
versions,
|
|
2709
|
+
total,
|
|
2710
|
+
page,
|
|
2711
|
+
perPage: perPageForResponse,
|
|
2712
|
+
hasMore: perPageInput === false ? false : offset + perPage < total
|
|
2713
|
+
};
|
|
2714
|
+
} catch (error) {
|
|
2715
|
+
if (error instanceof MastraError) throw error;
|
|
2716
|
+
throw new MastraError(
|
|
2717
|
+
{
|
|
2718
|
+
id: createStorageErrorId("LIBSQL", "LIST_VERSIONS", "FAILED"),
|
|
2719
|
+
domain: ErrorDomain.STORAGE,
|
|
2720
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
2721
|
+
details: { agentId }
|
|
2722
|
+
},
|
|
2723
|
+
error
|
|
2724
|
+
);
|
|
2725
|
+
}
|
|
2726
|
+
}
|
|
2727
|
+
async deleteVersion(id) {
|
|
2728
|
+
try {
|
|
2729
|
+
await this.#db.delete({
|
|
2730
|
+
tableName: TABLE_AGENT_VERSIONS,
|
|
2731
|
+
keys: { id }
|
|
2732
|
+
});
|
|
2733
|
+
} catch (error) {
|
|
2734
|
+
if (error instanceof MastraError) throw error;
|
|
2735
|
+
throw new MastraError(
|
|
2736
|
+
{
|
|
2737
|
+
id: createStorageErrorId("LIBSQL", "DELETE_VERSION", "FAILED"),
|
|
2738
|
+
domain: ErrorDomain.STORAGE,
|
|
2739
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
2740
|
+
details: { versionId: id }
|
|
2741
|
+
},
|
|
2742
|
+
error
|
|
2743
|
+
);
|
|
2744
|
+
}
|
|
2745
|
+
}
|
|
2746
|
+
async deleteVersionsByParentId(entityId) {
|
|
2747
|
+
try {
|
|
2748
|
+
const versions = await this.#db.selectMany({
|
|
2749
|
+
tableName: TABLE_AGENT_VERSIONS,
|
|
2750
|
+
whereClause: {
|
|
2751
|
+
sql: "WHERE agentId = ?",
|
|
2752
|
+
args: [entityId]
|
|
2753
|
+
}
|
|
2754
|
+
});
|
|
2755
|
+
for (const version of versions) {
|
|
2756
|
+
await this.#db.delete({
|
|
2757
|
+
tableName: TABLE_AGENT_VERSIONS,
|
|
2758
|
+
keys: { id: version.id }
|
|
2759
|
+
});
|
|
2760
|
+
}
|
|
2761
|
+
} catch (error) {
|
|
2762
|
+
if (error instanceof MastraError) throw error;
|
|
2763
|
+
throw new MastraError(
|
|
2764
|
+
{
|
|
2765
|
+
id: createStorageErrorId("LIBSQL", "DELETE_VERSIONS_BY_AGENT_ID", "FAILED"),
|
|
2766
|
+
domain: ErrorDomain.STORAGE,
|
|
2767
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
2768
|
+
details: { agentId: entityId }
|
|
2769
|
+
},
|
|
2770
|
+
error
|
|
2771
|
+
);
|
|
2772
|
+
}
|
|
2773
|
+
}
|
|
2774
|
+
async countVersions(agentId) {
|
|
2775
|
+
try {
|
|
2776
|
+
const count = await this.#db.selectTotalCount({
|
|
2777
|
+
tableName: TABLE_AGENT_VERSIONS,
|
|
2778
|
+
whereClause: {
|
|
2779
|
+
sql: "WHERE agentId = ?",
|
|
2780
|
+
args: [agentId]
|
|
2781
|
+
}
|
|
2782
|
+
});
|
|
2783
|
+
return count;
|
|
2784
|
+
} catch (error) {
|
|
2785
|
+
if (error instanceof MastraError) throw error;
|
|
2786
|
+
throw new MastraError(
|
|
2787
|
+
{
|
|
2788
|
+
id: createStorageErrorId("LIBSQL", "COUNT_VERSIONS", "FAILED"),
|
|
2789
|
+
domain: ErrorDomain.STORAGE,
|
|
2790
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
2791
|
+
details: { agentId }
|
|
2792
|
+
},
|
|
2793
|
+
error
|
|
2794
|
+
);
|
|
2795
|
+
}
|
|
2796
|
+
}
|
|
2797
|
+
// ==========================================================================
|
|
2798
|
+
// Private Helper Methods
|
|
2799
|
+
// ==========================================================================
|
|
2800
|
+
serializeInstructions(instructions) {
|
|
2801
|
+
return Array.isArray(instructions) ? JSON.stringify(instructions) : instructions;
|
|
2802
|
+
}
|
|
2803
|
+
deserializeInstructions(raw) {
|
|
2804
|
+
if (!raw) return raw;
|
|
2805
|
+
try {
|
|
2806
|
+
const parsed = JSON.parse(raw);
|
|
2807
|
+
if (Array.isArray(parsed)) return parsed;
|
|
2808
|
+
} catch {
|
|
2809
|
+
}
|
|
2810
|
+
return raw;
|
|
2811
|
+
}
|
|
2812
|
+
parseVersionRow(row) {
|
|
2813
|
+
return {
|
|
2814
|
+
id: row.id,
|
|
2815
|
+
agentId: row.agentId,
|
|
2816
|
+
versionNumber: row.versionNumber,
|
|
2817
|
+
name: row.name,
|
|
2818
|
+
description: row.description,
|
|
2819
|
+
instructions: this.deserializeInstructions(row.instructions),
|
|
2820
|
+
model: this.parseJson(row.model, "model"),
|
|
2821
|
+
tools: this.parseJson(row.tools, "tools"),
|
|
2822
|
+
defaultOptions: this.parseJson(row.defaultOptions, "defaultOptions"),
|
|
2823
|
+
workflows: this.parseJson(row.workflows, "workflows"),
|
|
2824
|
+
agents: this.parseJson(row.agents, "agents"),
|
|
2825
|
+
integrationTools: this.parseJson(row.integrationTools, "integrationTools"),
|
|
2826
|
+
inputProcessors: this.parseJson(row.inputProcessors, "inputProcessors"),
|
|
2827
|
+
outputProcessors: this.parseJson(row.outputProcessors, "outputProcessors"),
|
|
2828
|
+
memory: this.parseJson(row.memory, "memory"),
|
|
2829
|
+
scorers: this.parseJson(row.scorers, "scorers"),
|
|
2830
|
+
mcpClients: this.parseJson(row.mcpClients, "mcpClients"),
|
|
2831
|
+
requestContextSchema: this.parseJson(row.requestContextSchema, "requestContextSchema"),
|
|
2832
|
+
changedFields: this.parseJson(row.changedFields, "changedFields"),
|
|
2833
|
+
changeMessage: row.changeMessage,
|
|
2834
|
+
createdAt: new Date(row.createdAt)
|
|
2835
|
+
};
|
|
2836
|
+
}
|
|
2837
|
+
};
|
|
2838
|
+
function jsonbArg(value) {
|
|
2839
|
+
return value === void 0 || value === null ? null : JSON.stringify(value);
|
|
2840
|
+
}
|
|
2841
|
+
var DatasetsLibSQL = class extends DatasetsStorage {
|
|
2842
|
+
#db;
|
|
2843
|
+
#client;
|
|
2844
|
+
constructor(config) {
|
|
2845
|
+
super();
|
|
2846
|
+
const client = resolveClient(config);
|
|
2847
|
+
this.#client = client;
|
|
2848
|
+
this.#db = new LibSQLDB({ client, maxRetries: config.maxRetries, initialBackoffMs: config.initialBackoffMs });
|
|
2849
|
+
}
|
|
2850
|
+
async init() {
|
|
2851
|
+
await this.#db.createTable({ tableName: TABLE_DATASETS, schema: DATASETS_SCHEMA });
|
|
2852
|
+
await this.#db.createTable({ tableName: TABLE_DATASET_ITEMS, schema: DATASET_ITEMS_SCHEMA });
|
|
2853
|
+
await this.#db.createTable({ tableName: TABLE_DATASET_VERSIONS, schema: DATASET_VERSIONS_SCHEMA });
|
|
2854
|
+
await this.#client.execute({
|
|
2855
|
+
sql: `CREATE INDEX IF NOT EXISTS idx_dataset_items_dataset_validto ON "${TABLE_DATASET_ITEMS}" ("datasetId", "validTo")`,
|
|
2856
|
+
args: []
|
|
2857
|
+
});
|
|
2858
|
+
await this.#client.execute({
|
|
2859
|
+
sql: `CREATE INDEX IF NOT EXISTS idx_dataset_items_dataset_version ON "${TABLE_DATASET_ITEMS}" ("datasetId", "datasetVersion")`,
|
|
2860
|
+
args: []
|
|
2861
|
+
});
|
|
2862
|
+
await this.#client.execute({
|
|
2863
|
+
sql: `CREATE INDEX IF NOT EXISTS idx_dataset_items_dataset_validto_deleted ON "${TABLE_DATASET_ITEMS}" ("datasetId", "validTo", "isDeleted")`,
|
|
2864
|
+
args: []
|
|
2865
|
+
});
|
|
2866
|
+
await this.#client.execute({
|
|
2867
|
+
sql: `CREATE INDEX IF NOT EXISTS idx_dataset_versions_dataset_version ON "${TABLE_DATASET_VERSIONS}" ("datasetId", "version")`,
|
|
2868
|
+
args: []
|
|
2869
|
+
});
|
|
2870
|
+
await this.#client.execute({
|
|
2871
|
+
sql: `CREATE UNIQUE INDEX IF NOT EXISTS idx_dataset_versions_dataset_version_unique ON "${TABLE_DATASET_VERSIONS}" ("datasetId", "version")`,
|
|
2872
|
+
args: []
|
|
2873
|
+
});
|
|
2874
|
+
}
|
|
2875
|
+
async dangerouslyClearAll() {
|
|
2876
|
+
await this.#db.deleteData({ tableName: TABLE_DATASET_VERSIONS });
|
|
2877
|
+
await this.#db.deleteData({ tableName: TABLE_DATASET_ITEMS });
|
|
2878
|
+
await this.#db.deleteData({ tableName: TABLE_DATASETS });
|
|
2879
|
+
}
|
|
2880
|
+
// --- Row transformers ---
|
|
2881
|
+
transformDatasetRow(row) {
|
|
2882
|
+
return {
|
|
2883
|
+
id: row.id,
|
|
2884
|
+
name: row.name,
|
|
2885
|
+
description: row.description,
|
|
2886
|
+
metadata: row.metadata ? safelyParseJSON(row.metadata) : void 0,
|
|
2887
|
+
inputSchema: row.inputSchema ? safelyParseJSON(row.inputSchema) : void 0,
|
|
2888
|
+
groundTruthSchema: row.groundTruthSchema ? safelyParseJSON(row.groundTruthSchema) : void 0,
|
|
2889
|
+
version: row.version,
|
|
2890
|
+
createdAt: ensureDate(row.createdAt),
|
|
2891
|
+
updatedAt: ensureDate(row.updatedAt)
|
|
2892
|
+
};
|
|
2893
|
+
}
|
|
2894
|
+
transformItemRow(row) {
|
|
2895
|
+
return {
|
|
2896
|
+
id: row.id,
|
|
2897
|
+
datasetId: row.datasetId,
|
|
2898
|
+
datasetVersion: row.datasetVersion,
|
|
2899
|
+
input: safelyParseJSON(row.input),
|
|
2900
|
+
groundTruth: row.groundTruth ? safelyParseJSON(row.groundTruth) : void 0,
|
|
2901
|
+
metadata: row.metadata ? safelyParseJSON(row.metadata) : void 0,
|
|
2902
|
+
createdAt: ensureDate(row.createdAt),
|
|
2903
|
+
updatedAt: ensureDate(row.updatedAt)
|
|
2904
|
+
};
|
|
2905
|
+
}
|
|
2906
|
+
transformItemRowFull(row) {
|
|
2907
|
+
return {
|
|
2908
|
+
id: row.id,
|
|
2909
|
+
datasetId: row.datasetId,
|
|
2910
|
+
datasetVersion: row.datasetVersion,
|
|
2911
|
+
validTo: row.validTo,
|
|
2912
|
+
isDeleted: Boolean(row.isDeleted),
|
|
2913
|
+
input: safelyParseJSON(row.input),
|
|
2914
|
+
groundTruth: row.groundTruth ? safelyParseJSON(row.groundTruth) : void 0,
|
|
2915
|
+
metadata: row.metadata ? safelyParseJSON(row.metadata) : void 0,
|
|
2916
|
+
createdAt: ensureDate(row.createdAt),
|
|
2917
|
+
updatedAt: ensureDate(row.updatedAt)
|
|
2918
|
+
};
|
|
2919
|
+
}
|
|
2920
|
+
transformDatasetVersionRow(row) {
|
|
2921
|
+
return {
|
|
2922
|
+
id: row.id,
|
|
2923
|
+
datasetId: row.datasetId,
|
|
2924
|
+
version: row.version,
|
|
2925
|
+
createdAt: ensureDate(row.createdAt)
|
|
2926
|
+
};
|
|
2927
|
+
}
|
|
2928
|
+
// --- Dataset CRUD ---
|
|
2929
|
+
async createDataset(input) {
|
|
2930
|
+
try {
|
|
2931
|
+
const id = crypto.randomUUID();
|
|
2932
|
+
const now = /* @__PURE__ */ new Date();
|
|
2933
|
+
const nowIso = now.toISOString();
|
|
2934
|
+
await this.#db.insert({
|
|
2935
|
+
tableName: TABLE_DATASETS,
|
|
2936
|
+
record: {
|
|
2937
|
+
id,
|
|
2938
|
+
name: input.name,
|
|
2939
|
+
description: input.description ?? null,
|
|
2940
|
+
metadata: input.metadata,
|
|
2941
|
+
inputSchema: input.inputSchema ?? null,
|
|
2942
|
+
groundTruthSchema: input.groundTruthSchema ?? null,
|
|
2943
|
+
version: 0,
|
|
2944
|
+
createdAt: nowIso,
|
|
2945
|
+
updatedAt: nowIso
|
|
2946
|
+
}
|
|
2947
|
+
});
|
|
2948
|
+
return {
|
|
2949
|
+
id,
|
|
2950
|
+
name: input.name,
|
|
2951
|
+
description: input.description,
|
|
2952
|
+
metadata: input.metadata,
|
|
2953
|
+
inputSchema: input.inputSchema,
|
|
2954
|
+
groundTruthSchema: input.groundTruthSchema,
|
|
2955
|
+
version: 0,
|
|
2956
|
+
createdAt: now,
|
|
2957
|
+
updatedAt: now
|
|
2958
|
+
};
|
|
2959
|
+
} catch (error) {
|
|
2960
|
+
throw new MastraError(
|
|
2961
|
+
{
|
|
2962
|
+
id: createStorageErrorId("LIBSQL", "CREATE_DATASET", "FAILED"),
|
|
2963
|
+
domain: ErrorDomain.STORAGE,
|
|
2964
|
+
category: ErrorCategory.THIRD_PARTY
|
|
2965
|
+
},
|
|
2966
|
+
error
|
|
2967
|
+
);
|
|
2968
|
+
}
|
|
2969
|
+
}
|
|
2970
|
+
async getDatasetById({ id }) {
|
|
2971
|
+
try {
|
|
2972
|
+
const result = await this.#client.execute({
|
|
2973
|
+
sql: `SELECT ${buildSelectColumns(TABLE_DATASETS)} FROM ${TABLE_DATASETS} WHERE id = ?`,
|
|
2974
|
+
args: [id]
|
|
2975
|
+
});
|
|
2976
|
+
return result.rows?.[0] ? this.transformDatasetRow(result.rows[0]) : null;
|
|
2977
|
+
} catch (error) {
|
|
2978
|
+
throw new MastraError(
|
|
2979
|
+
{
|
|
2980
|
+
id: createStorageErrorId("LIBSQL", "GET_DATASET", "FAILED"),
|
|
2981
|
+
domain: ErrorDomain.STORAGE,
|
|
2982
|
+
category: ErrorCategory.THIRD_PARTY
|
|
2983
|
+
},
|
|
2984
|
+
error
|
|
2985
|
+
);
|
|
2986
|
+
}
|
|
2987
|
+
}
|
|
2988
|
+
async _doUpdateDataset(args) {
|
|
2989
|
+
try {
|
|
2990
|
+
const existing = await this.getDatasetById({ id: args.id });
|
|
2991
|
+
if (!existing) {
|
|
2992
|
+
throw new MastraError({
|
|
2993
|
+
id: createStorageErrorId("LIBSQL", "UPDATE_DATASET", "NOT_FOUND"),
|
|
2994
|
+
domain: ErrorDomain.STORAGE,
|
|
2995
|
+
category: ErrorCategory.USER,
|
|
2996
|
+
details: { datasetId: args.id }
|
|
2997
|
+
});
|
|
2998
|
+
}
|
|
2999
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
3000
|
+
const updates = ["updatedAt = ?"];
|
|
3001
|
+
const values = [now];
|
|
3002
|
+
if (args.name !== void 0) {
|
|
3003
|
+
updates.push("name = ?");
|
|
3004
|
+
values.push(args.name);
|
|
3005
|
+
}
|
|
3006
|
+
if (args.description !== void 0) {
|
|
3007
|
+
updates.push("description = ?");
|
|
3008
|
+
values.push(args.description);
|
|
3009
|
+
}
|
|
3010
|
+
if (args.metadata !== void 0) {
|
|
3011
|
+
updates.push("metadata = ?");
|
|
3012
|
+
values.push(JSON.stringify(args.metadata));
|
|
3013
|
+
}
|
|
3014
|
+
if (args.inputSchema !== void 0) {
|
|
3015
|
+
updates.push("inputSchema = ?");
|
|
3016
|
+
values.push(args.inputSchema === null ? null : JSON.stringify(args.inputSchema));
|
|
3017
|
+
}
|
|
3018
|
+
if (args.groundTruthSchema !== void 0) {
|
|
3019
|
+
updates.push("groundTruthSchema = ?");
|
|
3020
|
+
values.push(args.groundTruthSchema === null ? null : JSON.stringify(args.groundTruthSchema));
|
|
3021
|
+
}
|
|
3022
|
+
values.push(args.id);
|
|
3023
|
+
await this.#client.execute({
|
|
3024
|
+
sql: `UPDATE ${TABLE_DATASETS} SET ${updates.join(", ")} WHERE id = ?`,
|
|
3025
|
+
args: values
|
|
3026
|
+
});
|
|
3027
|
+
return {
|
|
3028
|
+
...existing,
|
|
3029
|
+
name: args.name ?? existing.name,
|
|
3030
|
+
description: args.description ?? existing.description,
|
|
3031
|
+
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,
|
|
3034
|
+
updatedAt: new Date(now)
|
|
3035
|
+
};
|
|
3036
|
+
} catch (error) {
|
|
3037
|
+
if (error instanceof MastraError) throw error;
|
|
3038
|
+
throw new MastraError(
|
|
3039
|
+
{
|
|
3040
|
+
id: createStorageErrorId("LIBSQL", "UPDATE_DATASET", "FAILED"),
|
|
3041
|
+
domain: ErrorDomain.STORAGE,
|
|
3042
|
+
category: ErrorCategory.THIRD_PARTY
|
|
3043
|
+
},
|
|
3044
|
+
error
|
|
3045
|
+
);
|
|
3046
|
+
}
|
|
3047
|
+
}
|
|
3048
|
+
async deleteDataset({ id }) {
|
|
3049
|
+
try {
|
|
3050
|
+
try {
|
|
3051
|
+
await this.#client.execute({
|
|
3052
|
+
sql: `DELETE FROM ${TABLE_EXPERIMENT_RESULTS} WHERE experimentId IN (SELECT id FROM ${TABLE_EXPERIMENTS} WHERE datasetId = ?)`,
|
|
3053
|
+
args: [id]
|
|
3054
|
+
});
|
|
3055
|
+
} catch {
|
|
3056
|
+
}
|
|
3057
|
+
try {
|
|
3058
|
+
await this.#client.execute({
|
|
3059
|
+
sql: `UPDATE ${TABLE_EXPERIMENTS} SET datasetId = NULL, datasetVersion = NULL WHERE datasetId = ?`,
|
|
3060
|
+
args: [id]
|
|
3061
|
+
});
|
|
3062
|
+
} catch {
|
|
3063
|
+
}
|
|
3064
|
+
await this.#client.batch(
|
|
3065
|
+
[
|
|
3066
|
+
{ sql: `DELETE FROM ${TABLE_DATASET_VERSIONS} WHERE datasetId = ?`, args: [id] },
|
|
3067
|
+
{ sql: `DELETE FROM ${TABLE_DATASET_ITEMS} WHERE datasetId = ?`, args: [id] },
|
|
3068
|
+
{ sql: `DELETE FROM ${TABLE_DATASETS} WHERE id = ?`, args: [id] }
|
|
3069
|
+
],
|
|
3070
|
+
"write"
|
|
3071
|
+
);
|
|
3072
|
+
} catch (error) {
|
|
3073
|
+
throw new MastraError(
|
|
3074
|
+
{
|
|
3075
|
+
id: createStorageErrorId("LIBSQL", "DELETE_DATASET", "FAILED"),
|
|
3076
|
+
domain: ErrorDomain.STORAGE,
|
|
3077
|
+
category: ErrorCategory.THIRD_PARTY
|
|
3078
|
+
},
|
|
3079
|
+
error
|
|
3080
|
+
);
|
|
3081
|
+
}
|
|
3082
|
+
}
|
|
3083
|
+
async listDatasets(args) {
|
|
3084
|
+
try {
|
|
3085
|
+
const { page, perPage: perPageInput } = args.pagination;
|
|
3086
|
+
const countResult = await this.#client.execute({
|
|
3087
|
+
sql: `SELECT COUNT(*) as count FROM ${TABLE_DATASETS}`,
|
|
3088
|
+
args: []
|
|
3089
|
+
});
|
|
3090
|
+
const total = Number(countResult.rows?.[0]?.count ?? 0);
|
|
3091
|
+
if (total === 0) {
|
|
3092
|
+
return {
|
|
3093
|
+
datasets: [],
|
|
3094
|
+
pagination: { total: 0, page, perPage: perPageInput, hasMore: false }
|
|
3095
|
+
};
|
|
3096
|
+
}
|
|
3097
|
+
const perPage = normalizePerPage(perPageInput, 100);
|
|
3098
|
+
const { offset: start, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
|
|
3099
|
+
const limitValue = perPageInput === false ? total : perPage;
|
|
3100
|
+
const end = perPageInput === false ? total : start + perPage;
|
|
3101
|
+
const result = await this.#client.execute({
|
|
3102
|
+
sql: `SELECT ${buildSelectColumns(TABLE_DATASETS)} FROM ${TABLE_DATASETS} ORDER BY createdAt DESC LIMIT ? OFFSET ?`,
|
|
3103
|
+
args: [limitValue, start]
|
|
3104
|
+
});
|
|
3105
|
+
return {
|
|
3106
|
+
datasets: result.rows?.map((row) => this.transformDatasetRow(row)) ?? [],
|
|
3107
|
+
pagination: {
|
|
3108
|
+
total,
|
|
3109
|
+
page,
|
|
3110
|
+
perPage: perPageForResponse,
|
|
3111
|
+
hasMore: end < total
|
|
3112
|
+
}
|
|
3113
|
+
};
|
|
3114
|
+
} catch (error) {
|
|
3115
|
+
throw new MastraError(
|
|
3116
|
+
{
|
|
3117
|
+
id: createStorageErrorId("LIBSQL", "LIST_DATASETS", "FAILED"),
|
|
3118
|
+
domain: ErrorDomain.STORAGE,
|
|
3119
|
+
category: ErrorCategory.THIRD_PARTY
|
|
3120
|
+
},
|
|
3121
|
+
error
|
|
3122
|
+
);
|
|
3123
|
+
}
|
|
3124
|
+
}
|
|
3125
|
+
// --- SCD-2 item mutations ---
|
|
3126
|
+
async _doAddItem(args) {
|
|
3127
|
+
try {
|
|
3128
|
+
const id = crypto.randomUUID();
|
|
3129
|
+
const versionId = crypto.randomUUID();
|
|
3130
|
+
const now = /* @__PURE__ */ new Date();
|
|
3131
|
+
const nowIso = now.toISOString();
|
|
3132
|
+
const results = await this.#client.batch(
|
|
3133
|
+
[
|
|
3134
|
+
{
|
|
3135
|
+
sql: `UPDATE ${TABLE_DATASETS} SET version = version + 1 WHERE id = ? RETURNING version`,
|
|
3136
|
+
args: [args.datasetId]
|
|
3137
|
+
},
|
|
3138
|
+
{
|
|
3139
|
+
sql: `INSERT INTO ${TABLE_DATASET_ITEMS} (id, datasetId, datasetVersion, validTo, isDeleted, input, groundTruth, metadata, createdAt, updatedAt) VALUES (?, ?, (SELECT version FROM ${TABLE_DATASETS} WHERE id = ?), NULL, 0, jsonb(?), jsonb(?), jsonb(?), ?, ?)`,
|
|
3140
|
+
args: [
|
|
3141
|
+
id,
|
|
3142
|
+
args.datasetId,
|
|
3143
|
+
args.datasetId,
|
|
3144
|
+
jsonbArg(args.input),
|
|
3145
|
+
jsonbArg(args.groundTruth),
|
|
3146
|
+
jsonbArg(args.metadata),
|
|
3147
|
+
nowIso,
|
|
3148
|
+
nowIso
|
|
3149
|
+
]
|
|
3150
|
+
},
|
|
3151
|
+
{
|
|
3152
|
+
sql: `INSERT INTO ${TABLE_DATASET_VERSIONS} (id, datasetId, version, createdAt) VALUES (?, ?, (SELECT version FROM ${TABLE_DATASETS} WHERE id = ?), ?)`,
|
|
3153
|
+
args: [versionId, args.datasetId, args.datasetId, nowIso]
|
|
3154
|
+
}
|
|
3155
|
+
],
|
|
3156
|
+
"write"
|
|
3157
|
+
);
|
|
3158
|
+
const newVersion = Number(results[0].rows[0].version);
|
|
3159
|
+
return {
|
|
3160
|
+
id,
|
|
3161
|
+
datasetId: args.datasetId,
|
|
3162
|
+
datasetVersion: newVersion,
|
|
3163
|
+
input: args.input,
|
|
3164
|
+
groundTruth: args.groundTruth,
|
|
3165
|
+
metadata: args.metadata,
|
|
3166
|
+
createdAt: now,
|
|
3167
|
+
updatedAt: now
|
|
3168
|
+
};
|
|
3169
|
+
} catch (error) {
|
|
3170
|
+
if (error instanceof MastraError) throw error;
|
|
3171
|
+
throw new MastraError(
|
|
3172
|
+
{
|
|
3173
|
+
id: createStorageErrorId("LIBSQL", "ADD_ITEM", "FAILED"),
|
|
3174
|
+
domain: ErrorDomain.STORAGE,
|
|
3175
|
+
category: ErrorCategory.THIRD_PARTY
|
|
3176
|
+
},
|
|
3177
|
+
error
|
|
3178
|
+
);
|
|
3179
|
+
}
|
|
3180
|
+
}
|
|
3181
|
+
async _doUpdateItem(args) {
|
|
3182
|
+
try {
|
|
3183
|
+
const existing = await this.getItemById({ id: args.id });
|
|
3184
|
+
if (!existing) {
|
|
3185
|
+
throw new MastraError({
|
|
3186
|
+
id: createStorageErrorId("LIBSQL", "UPDATE_ITEM", "NOT_FOUND"),
|
|
3187
|
+
domain: ErrorDomain.STORAGE,
|
|
3188
|
+
category: ErrorCategory.USER,
|
|
3189
|
+
details: { itemId: args.id }
|
|
3190
|
+
});
|
|
3191
|
+
}
|
|
3192
|
+
if (existing.datasetId !== args.datasetId) {
|
|
3193
|
+
throw new MastraError({
|
|
3194
|
+
id: createStorageErrorId("LIBSQL", "UPDATE_ITEM", "DATASET_MISMATCH"),
|
|
3195
|
+
domain: ErrorDomain.STORAGE,
|
|
3196
|
+
category: ErrorCategory.USER,
|
|
3197
|
+
details: { itemId: args.id, expectedDatasetId: args.datasetId, actualDatasetId: existing.datasetId }
|
|
3198
|
+
});
|
|
3199
|
+
}
|
|
3200
|
+
const versionId = crypto.randomUUID();
|
|
3201
|
+
const now = /* @__PURE__ */ new Date();
|
|
3202
|
+
const nowIso = now.toISOString();
|
|
3203
|
+
const mergedInput = args.input ?? existing.input;
|
|
3204
|
+
const mergedGroundTruth = args.groundTruth ?? existing.groundTruth;
|
|
3205
|
+
const mergedMetadata = args.metadata ?? existing.metadata;
|
|
3206
|
+
const results = await this.#client.batch(
|
|
3207
|
+
[
|
|
3208
|
+
{
|
|
3209
|
+
sql: `UPDATE ${TABLE_DATASETS} SET version = version + 1 WHERE id = ? RETURNING version`,
|
|
3210
|
+
args: [args.datasetId]
|
|
3211
|
+
},
|
|
3212
|
+
{
|
|
3213
|
+
sql: `UPDATE ${TABLE_DATASET_ITEMS} SET validTo = (SELECT version FROM ${TABLE_DATASETS} WHERE id = ?) WHERE id = ? AND validTo IS NULL AND isDeleted = 0`,
|
|
3214
|
+
args: [args.datasetId, args.id]
|
|
3215
|
+
},
|
|
3216
|
+
{
|
|
3217
|
+
sql: `INSERT INTO ${TABLE_DATASET_ITEMS} (id, datasetId, datasetVersion, validTo, isDeleted, input, groundTruth, metadata, createdAt, updatedAt) VALUES (?, ?, (SELECT version FROM ${TABLE_DATASETS} WHERE id = ?), NULL, 0, jsonb(?), jsonb(?), jsonb(?), ?, ?)`,
|
|
3218
|
+
args: [
|
|
3219
|
+
args.id,
|
|
3220
|
+
args.datasetId,
|
|
3221
|
+
args.datasetId,
|
|
3222
|
+
jsonbArg(mergedInput),
|
|
3223
|
+
jsonbArg(mergedGroundTruth),
|
|
3224
|
+
jsonbArg(mergedMetadata),
|
|
3225
|
+
existing.createdAt.toISOString(),
|
|
3226
|
+
nowIso
|
|
3227
|
+
]
|
|
3228
|
+
},
|
|
3229
|
+
{
|
|
3230
|
+
sql: `INSERT INTO ${TABLE_DATASET_VERSIONS} (id, datasetId, version, createdAt) VALUES (?, ?, (SELECT version FROM ${TABLE_DATASETS} WHERE id = ?), ?)`,
|
|
3231
|
+
args: [versionId, args.datasetId, args.datasetId, nowIso]
|
|
3232
|
+
}
|
|
3233
|
+
],
|
|
3234
|
+
"write"
|
|
3235
|
+
);
|
|
3236
|
+
const newVersion = Number(results[0].rows[0].version);
|
|
3237
|
+
return {
|
|
3238
|
+
...existing,
|
|
3239
|
+
datasetVersion: newVersion,
|
|
3240
|
+
input: mergedInput,
|
|
3241
|
+
groundTruth: mergedGroundTruth,
|
|
3242
|
+
metadata: mergedMetadata,
|
|
3243
|
+
updatedAt: now
|
|
3244
|
+
};
|
|
3245
|
+
} catch (error) {
|
|
3246
|
+
if (error instanceof MastraError) throw error;
|
|
3247
|
+
throw new MastraError(
|
|
3248
|
+
{
|
|
3249
|
+
id: createStorageErrorId("LIBSQL", "UPDATE_ITEM", "FAILED"),
|
|
3250
|
+
domain: ErrorDomain.STORAGE,
|
|
3251
|
+
category: ErrorCategory.THIRD_PARTY
|
|
3252
|
+
},
|
|
3253
|
+
error
|
|
3254
|
+
);
|
|
3255
|
+
}
|
|
3256
|
+
}
|
|
3257
|
+
async _doDeleteItem({ id, datasetId }) {
|
|
3258
|
+
try {
|
|
3259
|
+
const existing = await this.getItemById({ id });
|
|
3260
|
+
if (!existing) return;
|
|
3261
|
+
if (existing.datasetId !== datasetId) {
|
|
3262
|
+
throw new MastraError({
|
|
3263
|
+
id: createStorageErrorId("LIBSQL", "DELETE_ITEM", "DATASET_MISMATCH"),
|
|
3264
|
+
domain: ErrorDomain.STORAGE,
|
|
3265
|
+
category: ErrorCategory.USER,
|
|
3266
|
+
details: { itemId: id, expectedDatasetId: datasetId, actualDatasetId: existing.datasetId }
|
|
3267
|
+
});
|
|
3268
|
+
}
|
|
3269
|
+
const versionId = crypto.randomUUID();
|
|
3270
|
+
const nowIso = (/* @__PURE__ */ new Date()).toISOString();
|
|
3271
|
+
await this.#client.batch(
|
|
3272
|
+
[
|
|
3273
|
+
{
|
|
3274
|
+
sql: `UPDATE ${TABLE_DATASETS} SET version = version + 1 WHERE id = ? RETURNING version`,
|
|
3275
|
+
args: [datasetId]
|
|
3276
|
+
},
|
|
3277
|
+
{
|
|
3278
|
+
sql: `UPDATE ${TABLE_DATASET_ITEMS} SET validTo = (SELECT version FROM ${TABLE_DATASETS} WHERE id = ?) WHERE id = ? AND validTo IS NULL AND isDeleted = 0`,
|
|
3279
|
+
args: [datasetId, id]
|
|
3280
|
+
},
|
|
3281
|
+
{
|
|
3282
|
+
sql: `INSERT INTO ${TABLE_DATASET_ITEMS} (id, datasetId, datasetVersion, validTo, isDeleted, input, groundTruth, metadata, createdAt, updatedAt) VALUES (?, ?, (SELECT version FROM ${TABLE_DATASETS} WHERE id = ?), NULL, 1, jsonb(?), jsonb(?), jsonb(?), ?, ?)`,
|
|
3283
|
+
args: [
|
|
3284
|
+
id,
|
|
3285
|
+
datasetId,
|
|
3286
|
+
datasetId,
|
|
3287
|
+
jsonbArg(existing.input),
|
|
3288
|
+
jsonbArg(existing.groundTruth),
|
|
3289
|
+
jsonbArg(existing.metadata),
|
|
3290
|
+
existing.createdAt.toISOString(),
|
|
3291
|
+
nowIso
|
|
3292
|
+
]
|
|
3293
|
+
},
|
|
3294
|
+
{
|
|
3295
|
+
sql: `INSERT INTO ${TABLE_DATASET_VERSIONS} (id, datasetId, version, createdAt) VALUES (?, ?, (SELECT version FROM ${TABLE_DATASETS} WHERE id = ?), ?)`,
|
|
3296
|
+
args: [versionId, datasetId, datasetId, nowIso]
|
|
3297
|
+
}
|
|
3298
|
+
],
|
|
3299
|
+
"write"
|
|
3300
|
+
);
|
|
3301
|
+
} catch (error) {
|
|
3302
|
+
if (error instanceof MastraError) throw error;
|
|
3303
|
+
throw new MastraError(
|
|
3304
|
+
{
|
|
3305
|
+
id: createStorageErrorId("LIBSQL", "DELETE_ITEM", "FAILED"),
|
|
3306
|
+
domain: ErrorDomain.STORAGE,
|
|
3307
|
+
category: ErrorCategory.THIRD_PARTY
|
|
3308
|
+
},
|
|
3309
|
+
error
|
|
3310
|
+
);
|
|
3311
|
+
}
|
|
3312
|
+
}
|
|
3313
|
+
// --- SCD-2 queries ---
|
|
3314
|
+
async getItemById(args) {
|
|
3315
|
+
try {
|
|
3316
|
+
let result;
|
|
3317
|
+
if (args.datasetVersion !== void 0) {
|
|
3318
|
+
result = await this.#client.execute({
|
|
3319
|
+
sql: `SELECT ${buildSelectColumns(TABLE_DATASET_ITEMS)} FROM ${TABLE_DATASET_ITEMS} WHERE id = ? AND datasetVersion = ? AND isDeleted = 0`,
|
|
3320
|
+
args: [args.id, args.datasetVersion]
|
|
3321
|
+
});
|
|
3322
|
+
} else {
|
|
3323
|
+
result = await this.#client.execute({
|
|
3324
|
+
sql: `SELECT ${buildSelectColumns(TABLE_DATASET_ITEMS)} FROM ${TABLE_DATASET_ITEMS} WHERE id = ? AND validTo IS NULL AND isDeleted = 0`,
|
|
3325
|
+
args: [args.id]
|
|
3326
|
+
});
|
|
3327
|
+
}
|
|
3328
|
+
return result.rows?.[0] ? this.transformItemRow(result.rows[0]) : null;
|
|
3329
|
+
} catch (error) {
|
|
3330
|
+
throw new MastraError(
|
|
3331
|
+
{
|
|
3332
|
+
id: createStorageErrorId("LIBSQL", "GET_ITEM", "FAILED"),
|
|
3333
|
+
domain: ErrorDomain.STORAGE,
|
|
3334
|
+
category: ErrorCategory.THIRD_PARTY
|
|
3335
|
+
},
|
|
3336
|
+
error
|
|
3337
|
+
);
|
|
3338
|
+
}
|
|
3339
|
+
}
|
|
3340
|
+
async getItemsByVersion({ datasetId, version }) {
|
|
3341
|
+
try {
|
|
3342
|
+
const result = await this.#client.execute({
|
|
3343
|
+
sql: `SELECT ${buildSelectColumns(TABLE_DATASET_ITEMS)} FROM ${TABLE_DATASET_ITEMS} WHERE datasetId = ? AND datasetVersion <= ? AND (validTo IS NULL OR validTo > ?) AND isDeleted = 0 ORDER BY createdAt DESC`,
|
|
3344
|
+
args: [datasetId, version, version]
|
|
3345
|
+
});
|
|
3346
|
+
return result.rows?.map((row) => this.transformItemRow(row)) ?? [];
|
|
3347
|
+
} catch (error) {
|
|
3348
|
+
throw new MastraError(
|
|
3349
|
+
{
|
|
3350
|
+
id: createStorageErrorId("LIBSQL", "GET_ITEMS_BY_VERSION", "FAILED"),
|
|
3351
|
+
domain: ErrorDomain.STORAGE,
|
|
3352
|
+
category: ErrorCategory.THIRD_PARTY
|
|
3353
|
+
},
|
|
3354
|
+
error
|
|
3355
|
+
);
|
|
3356
|
+
}
|
|
3357
|
+
}
|
|
3358
|
+
async getItemHistory(itemId) {
|
|
3359
|
+
try {
|
|
3360
|
+
const result = await this.#client.execute({
|
|
3361
|
+
sql: `SELECT ${buildSelectColumns(TABLE_DATASET_ITEMS)} FROM ${TABLE_DATASET_ITEMS} WHERE id = ? ORDER BY datasetVersion DESC`,
|
|
3362
|
+
args: [itemId]
|
|
3363
|
+
});
|
|
3364
|
+
return result.rows?.map((row) => this.transformItemRowFull(row)) ?? [];
|
|
3365
|
+
} catch (error) {
|
|
3366
|
+
throw new MastraError(
|
|
3367
|
+
{
|
|
3368
|
+
id: createStorageErrorId("LIBSQL", "GET_ITEM_HISTORY", "FAILED"),
|
|
3369
|
+
domain: ErrorDomain.STORAGE,
|
|
3370
|
+
category: ErrorCategory.THIRD_PARTY
|
|
3371
|
+
},
|
|
3372
|
+
error
|
|
3373
|
+
);
|
|
3374
|
+
}
|
|
3375
|
+
}
|
|
3376
|
+
async listItems(args) {
|
|
3377
|
+
try {
|
|
3378
|
+
const { page, perPage: perPageInput } = args.pagination;
|
|
3379
|
+
if (args.version !== void 0) {
|
|
3380
|
+
const conditions2 = [
|
|
3381
|
+
"datasetId = ?",
|
|
3382
|
+
"datasetVersion <= ?",
|
|
3383
|
+
"(validTo IS NULL OR validTo > ?)",
|
|
3384
|
+
"isDeleted = 0"
|
|
3385
|
+
];
|
|
3386
|
+
const queryParams2 = [args.datasetId, args.version, args.version];
|
|
3387
|
+
if (args.search) {
|
|
3388
|
+
conditions2.push(`(LOWER(json(input)) LIKE ? OR LOWER(COALESCE(json(groundTruth), '')) LIKE ?)`);
|
|
3389
|
+
const searchPattern = `%${args.search.toLowerCase()}%`;
|
|
3390
|
+
queryParams2.push(searchPattern, searchPattern);
|
|
3391
|
+
}
|
|
3392
|
+
const whereClause2 = `WHERE ${conditions2.join(" AND ")}`;
|
|
3393
|
+
const countResult2 = await this.#client.execute({
|
|
3394
|
+
sql: `SELECT COUNT(*) as count FROM ${TABLE_DATASET_ITEMS} ${whereClause2}`,
|
|
3395
|
+
args: queryParams2
|
|
3396
|
+
});
|
|
3397
|
+
const total2 = Number(countResult2.rows?.[0]?.count ?? 0);
|
|
3398
|
+
if (total2 === 0) {
|
|
3399
|
+
return {
|
|
3400
|
+
items: [],
|
|
3401
|
+
pagination: { total: 0, page, perPage: perPageInput, hasMore: false }
|
|
3402
|
+
};
|
|
3403
|
+
}
|
|
3404
|
+
const perPage2 = normalizePerPage(perPageInput, 100);
|
|
3405
|
+
const { offset: start2, perPage: perPageForResponse2 } = calculatePagination(page, perPageInput, perPage2);
|
|
3406
|
+
const limitValue2 = perPageInput === false ? total2 : perPage2;
|
|
3407
|
+
const end2 = perPageInput === false ? total2 : start2 + perPage2;
|
|
3408
|
+
const result2 = await this.#client.execute({
|
|
3409
|
+
sql: `SELECT ${buildSelectColumns(TABLE_DATASET_ITEMS)} FROM ${TABLE_DATASET_ITEMS} ${whereClause2} ORDER BY createdAt DESC LIMIT ? OFFSET ?`,
|
|
3410
|
+
args: [...queryParams2, limitValue2, start2]
|
|
3411
|
+
});
|
|
3412
|
+
return {
|
|
3413
|
+
items: result2.rows?.map((row) => this.transformItemRow(row)) ?? [],
|
|
3414
|
+
pagination: {
|
|
3415
|
+
total: total2,
|
|
3416
|
+
page,
|
|
3417
|
+
perPage: perPageForResponse2,
|
|
3418
|
+
hasMore: end2 < total2
|
|
3419
|
+
}
|
|
3420
|
+
};
|
|
3421
|
+
}
|
|
3422
|
+
const conditions = ["datasetId = ?", "validTo IS NULL", "isDeleted = 0"];
|
|
3423
|
+
const queryParams = [args.datasetId];
|
|
3424
|
+
if (args.search) {
|
|
3425
|
+
conditions.push(`(LOWER(json(input)) LIKE ? OR LOWER(COALESCE(json(groundTruth), '')) LIKE ?)`);
|
|
3426
|
+
const searchPattern = `%${args.search.toLowerCase()}%`;
|
|
3427
|
+
queryParams.push(searchPattern, searchPattern);
|
|
3428
|
+
}
|
|
3429
|
+
const whereClause = `WHERE ${conditions.join(" AND ")}`;
|
|
3430
|
+
const countResult = await this.#client.execute({
|
|
3431
|
+
sql: `SELECT COUNT(*) as count FROM ${TABLE_DATASET_ITEMS} ${whereClause}`,
|
|
3432
|
+
args: queryParams
|
|
3433
|
+
});
|
|
3434
|
+
const total = Number(countResult.rows?.[0]?.count ?? 0);
|
|
3435
|
+
if (total === 0) {
|
|
3436
|
+
return {
|
|
3437
|
+
items: [],
|
|
3438
|
+
pagination: { total: 0, page, perPage: perPageInput, hasMore: false }
|
|
3439
|
+
};
|
|
3440
|
+
}
|
|
3441
|
+
const perPage = normalizePerPage(perPageInput, 100);
|
|
3442
|
+
const { offset: start, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
|
|
3443
|
+
const limitValue = perPageInput === false ? total : perPage;
|
|
3444
|
+
const end = perPageInput === false ? total : start + perPage;
|
|
3445
|
+
const result = await this.#client.execute({
|
|
3446
|
+
sql: `SELECT ${buildSelectColumns(TABLE_DATASET_ITEMS)} FROM ${TABLE_DATASET_ITEMS} ${whereClause} ORDER BY createdAt DESC LIMIT ? OFFSET ?`,
|
|
3447
|
+
args: [...queryParams, limitValue, start]
|
|
3448
|
+
});
|
|
3449
|
+
return {
|
|
3450
|
+
items: result.rows?.map((row) => this.transformItemRow(row)) ?? [],
|
|
3451
|
+
pagination: {
|
|
3452
|
+
total,
|
|
3453
|
+
page,
|
|
3454
|
+
perPage: perPageForResponse,
|
|
3455
|
+
hasMore: end < total
|
|
3456
|
+
}
|
|
3457
|
+
};
|
|
3458
|
+
} catch (error) {
|
|
3459
|
+
throw new MastraError(
|
|
3460
|
+
{
|
|
3461
|
+
id: createStorageErrorId("LIBSQL", "LIST_ITEMS", "FAILED"),
|
|
3462
|
+
domain: ErrorDomain.STORAGE,
|
|
3463
|
+
category: ErrorCategory.THIRD_PARTY
|
|
3464
|
+
},
|
|
3465
|
+
error
|
|
3466
|
+
);
|
|
3467
|
+
}
|
|
3468
|
+
}
|
|
3469
|
+
// --- Dataset version methods ---
|
|
3470
|
+
async createDatasetVersion(datasetId, version) {
|
|
3471
|
+
try {
|
|
3472
|
+
const id = crypto.randomUUID();
|
|
3473
|
+
const now = /* @__PURE__ */ new Date();
|
|
3474
|
+
const nowIso = now.toISOString();
|
|
3475
|
+
await this.#db.insert({
|
|
3476
|
+
tableName: TABLE_DATASET_VERSIONS,
|
|
3477
|
+
record: {
|
|
3478
|
+
id,
|
|
3479
|
+
datasetId,
|
|
3480
|
+
version,
|
|
3481
|
+
createdAt: nowIso
|
|
3482
|
+
}
|
|
3483
|
+
});
|
|
3484
|
+
return {
|
|
3485
|
+
id,
|
|
3486
|
+
datasetId,
|
|
3487
|
+
version,
|
|
3488
|
+
createdAt: now
|
|
3489
|
+
};
|
|
3490
|
+
} catch (error) {
|
|
3491
|
+
throw new MastraError(
|
|
3492
|
+
{
|
|
3493
|
+
id: createStorageErrorId("LIBSQL", "CREATE_DATASET_VERSION", "FAILED"),
|
|
3494
|
+
domain: ErrorDomain.STORAGE,
|
|
3495
|
+
category: ErrorCategory.THIRD_PARTY
|
|
3496
|
+
},
|
|
3497
|
+
error
|
|
3498
|
+
);
|
|
3499
|
+
}
|
|
3500
|
+
}
|
|
3501
|
+
async listDatasetVersions(input) {
|
|
3502
|
+
try {
|
|
3503
|
+
const { page, perPage: perPageInput } = input.pagination;
|
|
3504
|
+
const countResult = await this.#client.execute({
|
|
3505
|
+
sql: `SELECT COUNT(*) as count FROM ${TABLE_DATASET_VERSIONS} WHERE datasetId = ?`,
|
|
3506
|
+
args: [input.datasetId]
|
|
3507
|
+
});
|
|
3508
|
+
const total = Number(countResult.rows?.[0]?.count ?? 0);
|
|
3509
|
+
if (total === 0) {
|
|
3510
|
+
return {
|
|
3511
|
+
versions: [],
|
|
3512
|
+
pagination: { total: 0, page, perPage: perPageInput, hasMore: false }
|
|
3513
|
+
};
|
|
3514
|
+
}
|
|
3515
|
+
const perPage = normalizePerPage(perPageInput, 100);
|
|
3516
|
+
const { offset: start, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
|
|
3517
|
+
const limitValue = perPageInput === false ? total : perPage;
|
|
3518
|
+
const end = perPageInput === false ? total : start + perPage;
|
|
3519
|
+
const result = await this.#client.execute({
|
|
3520
|
+
sql: `SELECT ${buildSelectColumns(TABLE_DATASET_VERSIONS)} FROM ${TABLE_DATASET_VERSIONS} WHERE datasetId = ? ORDER BY version DESC LIMIT ? OFFSET ?`,
|
|
3521
|
+
args: [input.datasetId, limitValue, start]
|
|
3522
|
+
});
|
|
3523
|
+
return {
|
|
3524
|
+
versions: result.rows?.map((row) => this.transformDatasetVersionRow(row)) ?? [],
|
|
3525
|
+
pagination: {
|
|
3526
|
+
total,
|
|
3527
|
+
page,
|
|
3528
|
+
perPage: perPageForResponse,
|
|
3529
|
+
hasMore: end < total
|
|
3530
|
+
}
|
|
3531
|
+
};
|
|
3532
|
+
} catch (error) {
|
|
3533
|
+
throw new MastraError(
|
|
3534
|
+
{
|
|
3535
|
+
id: createStorageErrorId("LIBSQL", "LIST_DATASET_VERSIONS", "FAILED"),
|
|
3536
|
+
domain: ErrorDomain.STORAGE,
|
|
3537
|
+
category: ErrorCategory.THIRD_PARTY
|
|
3538
|
+
},
|
|
3539
|
+
error
|
|
3540
|
+
);
|
|
3541
|
+
}
|
|
3542
|
+
}
|
|
3543
|
+
// --- Bulk operations (SCD-2 internally) ---
|
|
3544
|
+
async _doBatchInsertItems(input) {
|
|
3545
|
+
try {
|
|
3546
|
+
const dataset = await this.getDatasetById({ id: input.datasetId });
|
|
3547
|
+
if (!dataset) {
|
|
3548
|
+
throw new MastraError({
|
|
3549
|
+
id: createStorageErrorId("LIBSQL", "BULK_ADD_ITEMS", "DATASET_NOT_FOUND"),
|
|
3550
|
+
domain: ErrorDomain.STORAGE,
|
|
3551
|
+
category: ErrorCategory.USER,
|
|
3552
|
+
details: { datasetId: input.datasetId }
|
|
3553
|
+
});
|
|
3554
|
+
}
|
|
3555
|
+
const now = /* @__PURE__ */ new Date();
|
|
3556
|
+
const nowIso = now.toISOString();
|
|
3557
|
+
const versionId = crypto.randomUUID();
|
|
3558
|
+
const statements = [
|
|
3559
|
+
{
|
|
3560
|
+
sql: `UPDATE ${TABLE_DATASETS} SET version = version + 1 WHERE id = ? RETURNING version`,
|
|
3561
|
+
args: [input.datasetId]
|
|
3562
|
+
}
|
|
3563
|
+
];
|
|
3564
|
+
const items = [];
|
|
3565
|
+
for (const itemInput of input.items) {
|
|
3566
|
+
const id = crypto.randomUUID();
|
|
3567
|
+
items.push({ id, input: itemInput });
|
|
3568
|
+
statements.push({
|
|
3569
|
+
sql: `INSERT INTO ${TABLE_DATASET_ITEMS} (id, datasetId, datasetVersion, validTo, isDeleted, input, groundTruth, metadata, createdAt, updatedAt) VALUES (?, ?, (SELECT version FROM ${TABLE_DATASETS} WHERE id = ?), NULL, 0, jsonb(?), jsonb(?), jsonb(?), ?, ?)`,
|
|
3570
|
+
args: [
|
|
3571
|
+
id,
|
|
3572
|
+
input.datasetId,
|
|
3573
|
+
input.datasetId,
|
|
3574
|
+
jsonbArg(itemInput.input),
|
|
3575
|
+
jsonbArg(itemInput.groundTruth),
|
|
3576
|
+
jsonbArg(itemInput.metadata),
|
|
3577
|
+
nowIso,
|
|
3578
|
+
nowIso
|
|
3579
|
+
]
|
|
3580
|
+
});
|
|
3581
|
+
}
|
|
3582
|
+
statements.push({
|
|
3583
|
+
sql: `INSERT INTO ${TABLE_DATASET_VERSIONS} (id, datasetId, version, createdAt) VALUES (?, ?, (SELECT version FROM ${TABLE_DATASETS} WHERE id = ?), ?)`,
|
|
3584
|
+
args: [versionId, input.datasetId, input.datasetId, nowIso]
|
|
3585
|
+
});
|
|
3586
|
+
const results = await this.#client.batch(statements, "write");
|
|
3587
|
+
const newVersion = Number(results[0].rows[0].version);
|
|
3588
|
+
return items.map(({ id, input: itemInput }) => ({
|
|
3589
|
+
id,
|
|
3590
|
+
datasetId: input.datasetId,
|
|
3591
|
+
datasetVersion: newVersion,
|
|
3592
|
+
input: itemInput.input,
|
|
3593
|
+
groundTruth: itemInput.groundTruth,
|
|
3594
|
+
metadata: itemInput.metadata,
|
|
3595
|
+
createdAt: now,
|
|
3596
|
+
updatedAt: now
|
|
3597
|
+
}));
|
|
3598
|
+
} catch (error) {
|
|
3599
|
+
if (error instanceof MastraError) throw error;
|
|
3600
|
+
throw new MastraError(
|
|
3601
|
+
{
|
|
3602
|
+
id: createStorageErrorId("LIBSQL", "BULK_ADD_ITEMS", "FAILED"),
|
|
3603
|
+
domain: ErrorDomain.STORAGE,
|
|
3604
|
+
category: ErrorCategory.THIRD_PARTY
|
|
3605
|
+
},
|
|
3606
|
+
error
|
|
3607
|
+
);
|
|
3608
|
+
}
|
|
3609
|
+
}
|
|
3610
|
+
async _doBatchDeleteItems(input) {
|
|
3611
|
+
try {
|
|
3612
|
+
const dataset = await this.getDatasetById({ id: input.datasetId });
|
|
3613
|
+
if (!dataset) {
|
|
3614
|
+
throw new MastraError({
|
|
3615
|
+
id: createStorageErrorId("LIBSQL", "BULK_DELETE_ITEMS", "DATASET_NOT_FOUND"),
|
|
3616
|
+
domain: ErrorDomain.STORAGE,
|
|
3617
|
+
category: ErrorCategory.USER,
|
|
3618
|
+
details: { datasetId: input.datasetId }
|
|
3619
|
+
});
|
|
3620
|
+
}
|
|
3621
|
+
const currentItems = [];
|
|
3622
|
+
for (const itemId of input.itemIds) {
|
|
3623
|
+
const item = await this.getItemById({ id: itemId });
|
|
3624
|
+
if (item && item.datasetId === input.datasetId) {
|
|
3625
|
+
currentItems.push(item);
|
|
3626
|
+
}
|
|
3627
|
+
}
|
|
3628
|
+
if (currentItems.length === 0) return;
|
|
3629
|
+
const nowIso = (/* @__PURE__ */ new Date()).toISOString();
|
|
3630
|
+
const versionId = crypto.randomUUID();
|
|
3631
|
+
const statements = [
|
|
3632
|
+
{
|
|
3633
|
+
sql: `UPDATE ${TABLE_DATASETS} SET version = version + 1 WHERE id = ? RETURNING version`,
|
|
3634
|
+
args: [input.datasetId]
|
|
3635
|
+
}
|
|
3636
|
+
];
|
|
3637
|
+
for (const item of currentItems) {
|
|
3638
|
+
statements.push({
|
|
3639
|
+
sql: `UPDATE ${TABLE_DATASET_ITEMS} SET validTo = (SELECT version FROM ${TABLE_DATASETS} WHERE id = ?) WHERE id = ? AND validTo IS NULL AND isDeleted = 0`,
|
|
3640
|
+
args: [input.datasetId, item.id]
|
|
3641
|
+
});
|
|
3642
|
+
statements.push({
|
|
3643
|
+
sql: `INSERT INTO ${TABLE_DATASET_ITEMS} (id, datasetId, datasetVersion, validTo, isDeleted, input, groundTruth, metadata, createdAt, updatedAt) VALUES (?, ?, (SELECT version FROM ${TABLE_DATASETS} WHERE id = ?), NULL, 1, jsonb(?), jsonb(?), jsonb(?), ?, ?)`,
|
|
3644
|
+
args: [
|
|
3645
|
+
item.id,
|
|
3646
|
+
input.datasetId,
|
|
3647
|
+
input.datasetId,
|
|
3648
|
+
jsonbArg(item.input),
|
|
3649
|
+
jsonbArg(item.groundTruth),
|
|
3650
|
+
jsonbArg(item.metadata),
|
|
3651
|
+
item.createdAt.toISOString(),
|
|
3652
|
+
nowIso
|
|
3653
|
+
]
|
|
3654
|
+
});
|
|
3655
|
+
}
|
|
3656
|
+
statements.push({
|
|
3657
|
+
sql: `INSERT INTO ${TABLE_DATASET_VERSIONS} (id, datasetId, version, createdAt) VALUES (?, ?, (SELECT version FROM ${TABLE_DATASETS} WHERE id = ?), ?)`,
|
|
3658
|
+
args: [versionId, input.datasetId, input.datasetId, nowIso]
|
|
3659
|
+
});
|
|
3660
|
+
await this.#client.batch(statements, "write");
|
|
3661
|
+
} catch (error) {
|
|
3662
|
+
if (error instanceof MastraError) throw error;
|
|
3663
|
+
throw new MastraError(
|
|
3664
|
+
{
|
|
3665
|
+
id: createStorageErrorId("LIBSQL", "BULK_DELETE_ITEMS", "FAILED"),
|
|
3666
|
+
domain: ErrorDomain.STORAGE,
|
|
3667
|
+
category: ErrorCategory.THIRD_PARTY
|
|
3668
|
+
},
|
|
3669
|
+
error
|
|
3670
|
+
);
|
|
3671
|
+
}
|
|
3672
|
+
}
|
|
3673
|
+
};
|
|
3674
|
+
var ExperimentsLibSQL = class extends ExperimentsStorage {
|
|
3675
|
+
#db;
|
|
3676
|
+
#client;
|
|
3677
|
+
constructor(config) {
|
|
3678
|
+
super();
|
|
3679
|
+
const client = resolveClient(config);
|
|
3680
|
+
this.#client = client;
|
|
3681
|
+
this.#db = new LibSQLDB({ client, maxRetries: config.maxRetries, initialBackoffMs: config.initialBackoffMs });
|
|
3682
|
+
}
|
|
3683
|
+
async init() {
|
|
3684
|
+
await this.#db.createTable({ tableName: TABLE_EXPERIMENTS, schema: EXPERIMENTS_SCHEMA });
|
|
3685
|
+
await this.#db.createTable({
|
|
3686
|
+
tableName: TABLE_EXPERIMENT_RESULTS,
|
|
3687
|
+
schema: EXPERIMENT_RESULTS_SCHEMA
|
|
3688
|
+
});
|
|
3689
|
+
await this.#client.execute({
|
|
3690
|
+
sql: `CREATE INDEX IF NOT EXISTS idx_experiments_datasetid ON "${TABLE_EXPERIMENTS}" ("datasetId")`,
|
|
3691
|
+
args: []
|
|
3692
|
+
});
|
|
3693
|
+
await this.#client.execute({
|
|
3694
|
+
sql: `CREATE INDEX IF NOT EXISTS idx_experiment_results_experimentid ON "${TABLE_EXPERIMENT_RESULTS}" ("experimentId")`,
|
|
3695
|
+
args: []
|
|
3696
|
+
});
|
|
3697
|
+
await this.#client.execute({
|
|
3698
|
+
sql: `CREATE UNIQUE INDEX IF NOT EXISTS idx_experiment_results_exp_item ON "${TABLE_EXPERIMENT_RESULTS}" ("experimentId", "itemId")`,
|
|
3699
|
+
args: []
|
|
3700
|
+
});
|
|
3701
|
+
}
|
|
3702
|
+
async dangerouslyClearAll() {
|
|
3703
|
+
await this.#db.deleteData({ tableName: TABLE_EXPERIMENT_RESULTS });
|
|
3704
|
+
await this.#db.deleteData({ tableName: TABLE_EXPERIMENTS });
|
|
3705
|
+
}
|
|
3706
|
+
// Helper to transform row to Experiment
|
|
3707
|
+
transformExperimentRow(row) {
|
|
3708
|
+
return {
|
|
3709
|
+
id: row.id,
|
|
3710
|
+
datasetId: row.datasetId ?? null,
|
|
3711
|
+
datasetVersion: row.datasetVersion != null ? row.datasetVersion : null,
|
|
3712
|
+
targetType: row.targetType,
|
|
3713
|
+
targetId: row.targetId,
|
|
3714
|
+
name: row.name ?? void 0,
|
|
3715
|
+
description: row.description ?? void 0,
|
|
3716
|
+
metadata: row.metadata ? safelyParseJSON(row.metadata) : void 0,
|
|
3717
|
+
status: row.status,
|
|
3718
|
+
totalItems: row.totalItems,
|
|
3719
|
+
succeededCount: row.succeededCount,
|
|
3720
|
+
failedCount: row.failedCount,
|
|
3721
|
+
skippedCount: row.skippedCount ?? 0,
|
|
3722
|
+
startedAt: row.startedAt ? ensureDate(row.startedAt) : null,
|
|
3723
|
+
completedAt: row.completedAt ? ensureDate(row.completedAt) : null,
|
|
3724
|
+
createdAt: ensureDate(row.createdAt),
|
|
3725
|
+
updatedAt: ensureDate(row.updatedAt)
|
|
3726
|
+
};
|
|
3727
|
+
}
|
|
3728
|
+
// Helper to transform row to ExperimentResult
|
|
3729
|
+
transformExperimentResultRow(row) {
|
|
3730
|
+
return {
|
|
3731
|
+
id: row.id,
|
|
3732
|
+
experimentId: row.experimentId,
|
|
3733
|
+
itemId: row.itemId,
|
|
3734
|
+
itemDatasetVersion: row.itemDatasetVersion != null ? row.itemDatasetVersion : null,
|
|
3735
|
+
input: safelyParseJSON(row.input),
|
|
3736
|
+
output: row.output ? safelyParseJSON(row.output) : null,
|
|
3737
|
+
groundTruth: row.groundTruth ? safelyParseJSON(row.groundTruth) : null,
|
|
3738
|
+
error: row.error ? safelyParseJSON(row.error) : null,
|
|
3739
|
+
startedAt: ensureDate(row.startedAt),
|
|
3740
|
+
completedAt: ensureDate(row.completedAt),
|
|
3741
|
+
retryCount: row.retryCount,
|
|
3742
|
+
traceId: row.traceId ?? null,
|
|
3743
|
+
createdAt: ensureDate(row.createdAt)
|
|
3744
|
+
};
|
|
3745
|
+
}
|
|
3746
|
+
// Experiment lifecycle
|
|
3747
|
+
async createExperiment(input) {
|
|
3748
|
+
try {
|
|
3749
|
+
const id = input.id ?? crypto.randomUUID();
|
|
3750
|
+
const now = /* @__PURE__ */ new Date();
|
|
3751
|
+
const nowIso = now.toISOString();
|
|
3752
|
+
await this.#db.insert({
|
|
3753
|
+
tableName: TABLE_EXPERIMENTS,
|
|
3754
|
+
record: {
|
|
3755
|
+
id,
|
|
3756
|
+
datasetId: input.datasetId ?? null,
|
|
3757
|
+
datasetVersion: input.datasetVersion ?? null,
|
|
3758
|
+
targetType: input.targetType,
|
|
3759
|
+
targetId: input.targetId,
|
|
3760
|
+
name: input.name ?? null,
|
|
3761
|
+
description: input.description ?? null,
|
|
3762
|
+
metadata: input.metadata ?? null,
|
|
3763
|
+
status: "pending",
|
|
3764
|
+
totalItems: input.totalItems,
|
|
3765
|
+
succeededCount: 0,
|
|
3766
|
+
failedCount: 0,
|
|
3767
|
+
skippedCount: 0,
|
|
3768
|
+
startedAt: null,
|
|
3769
|
+
completedAt: null,
|
|
3770
|
+
createdAt: nowIso,
|
|
3771
|
+
updatedAt: nowIso
|
|
3772
|
+
}
|
|
3773
|
+
});
|
|
3774
|
+
return {
|
|
3775
|
+
id,
|
|
3776
|
+
datasetId: input.datasetId,
|
|
3777
|
+
datasetVersion: input.datasetVersion,
|
|
3778
|
+
targetType: input.targetType,
|
|
3779
|
+
targetId: input.targetId,
|
|
3780
|
+
name: input.name,
|
|
3781
|
+
description: input.description,
|
|
3782
|
+
metadata: input.metadata,
|
|
3783
|
+
status: "pending",
|
|
3784
|
+
totalItems: input.totalItems,
|
|
3785
|
+
succeededCount: 0,
|
|
3786
|
+
failedCount: 0,
|
|
3787
|
+
skippedCount: 0,
|
|
3788
|
+
startedAt: null,
|
|
3789
|
+
completedAt: null,
|
|
3790
|
+
createdAt: now,
|
|
3791
|
+
updatedAt: now
|
|
3792
|
+
};
|
|
3793
|
+
} catch (error) {
|
|
3794
|
+
throw new MastraError(
|
|
3795
|
+
{
|
|
3796
|
+
id: createStorageErrorId("LIBSQL", "CREATE_EXPERIMENT", "FAILED"),
|
|
3797
|
+
domain: ErrorDomain.STORAGE,
|
|
3798
|
+
category: ErrorCategory.THIRD_PARTY
|
|
3799
|
+
},
|
|
3800
|
+
error
|
|
3801
|
+
);
|
|
3802
|
+
}
|
|
3803
|
+
}
|
|
3804
|
+
async updateExperiment(input) {
|
|
3805
|
+
try {
|
|
3806
|
+
const existing = await this.getExperimentById({ id: input.id });
|
|
3807
|
+
if (!existing) {
|
|
3808
|
+
throw new MastraError({
|
|
3809
|
+
id: createStorageErrorId("LIBSQL", "UPDATE_EXPERIMENT", "NOT_FOUND"),
|
|
3810
|
+
domain: ErrorDomain.STORAGE,
|
|
3811
|
+
category: ErrorCategory.USER,
|
|
3812
|
+
details: { experimentId: input.id }
|
|
3813
|
+
});
|
|
3814
|
+
}
|
|
3815
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
3816
|
+
const updates = ["updatedAt = ?"];
|
|
3817
|
+
const values = [now];
|
|
3818
|
+
if (input.status !== void 0) {
|
|
3819
|
+
updates.push("status = ?");
|
|
3820
|
+
values.push(input.status);
|
|
3821
|
+
}
|
|
3822
|
+
if (input.succeededCount !== void 0) {
|
|
3823
|
+
updates.push("succeededCount = ?");
|
|
3824
|
+
values.push(input.succeededCount);
|
|
3825
|
+
}
|
|
3826
|
+
if (input.failedCount !== void 0) {
|
|
3827
|
+
updates.push("failedCount = ?");
|
|
3828
|
+
values.push(input.failedCount);
|
|
3829
|
+
}
|
|
3830
|
+
if (input.startedAt !== void 0) {
|
|
3831
|
+
updates.push("startedAt = ?");
|
|
3832
|
+
values.push(input.startedAt?.toISOString() ?? null);
|
|
3833
|
+
}
|
|
3834
|
+
if (input.completedAt !== void 0) {
|
|
3835
|
+
updates.push("completedAt = ?");
|
|
3836
|
+
values.push(input.completedAt?.toISOString() ?? null);
|
|
3837
|
+
}
|
|
3838
|
+
if (input.skippedCount !== void 0) {
|
|
3839
|
+
updates.push("skippedCount = ?");
|
|
3840
|
+
values.push(input.skippedCount);
|
|
3841
|
+
}
|
|
3842
|
+
if (input.name !== void 0) {
|
|
3843
|
+
updates.push("name = ?");
|
|
3844
|
+
values.push(input.name);
|
|
3845
|
+
}
|
|
3846
|
+
if (input.description !== void 0) {
|
|
3847
|
+
updates.push("description = ?");
|
|
3848
|
+
values.push(input.description);
|
|
3849
|
+
}
|
|
3850
|
+
if (input.metadata !== void 0) {
|
|
3851
|
+
updates.push("metadata = ?");
|
|
3852
|
+
values.push(JSON.stringify(input.metadata));
|
|
3853
|
+
}
|
|
3854
|
+
values.push(input.id);
|
|
3855
|
+
await this.#client.execute({
|
|
3856
|
+
sql: `UPDATE ${TABLE_EXPERIMENTS} SET ${updates.join(", ")} WHERE id = ?`,
|
|
3857
|
+
args: values
|
|
3858
|
+
});
|
|
3859
|
+
const updated = await this.getExperimentById({ id: input.id });
|
|
3860
|
+
return updated;
|
|
3861
|
+
} catch (error) {
|
|
3862
|
+
if (error instanceof MastraError) throw error;
|
|
3863
|
+
throw new MastraError(
|
|
3864
|
+
{
|
|
3865
|
+
id: createStorageErrorId("LIBSQL", "UPDATE_EXPERIMENT", "FAILED"),
|
|
3866
|
+
domain: ErrorDomain.STORAGE,
|
|
3867
|
+
category: ErrorCategory.THIRD_PARTY
|
|
3868
|
+
},
|
|
3869
|
+
error
|
|
3870
|
+
);
|
|
3871
|
+
}
|
|
3872
|
+
}
|
|
3873
|
+
async getExperimentById(args) {
|
|
3874
|
+
try {
|
|
3875
|
+
const result = await this.#client.execute({
|
|
3876
|
+
sql: `SELECT ${buildSelectColumns(TABLE_EXPERIMENTS)} FROM ${TABLE_EXPERIMENTS} WHERE id = ?`,
|
|
3877
|
+
args: [args.id]
|
|
3878
|
+
});
|
|
3879
|
+
return result.rows?.[0] ? this.transformExperimentRow(result.rows[0]) : null;
|
|
3880
|
+
} catch (error) {
|
|
3881
|
+
throw new MastraError(
|
|
3882
|
+
{
|
|
3883
|
+
id: createStorageErrorId("LIBSQL", "GET_EXPERIMENT", "FAILED"),
|
|
3884
|
+
domain: ErrorDomain.STORAGE,
|
|
3885
|
+
category: ErrorCategory.THIRD_PARTY
|
|
3886
|
+
},
|
|
3887
|
+
error
|
|
3888
|
+
);
|
|
3889
|
+
}
|
|
3890
|
+
}
|
|
3891
|
+
async listExperiments(args) {
|
|
3892
|
+
try {
|
|
3893
|
+
const { page, perPage: perPageInput } = args.pagination;
|
|
3894
|
+
const conditions = [];
|
|
3895
|
+
const queryParams = [];
|
|
3896
|
+
if (args.datasetId) {
|
|
3897
|
+
conditions.push("datasetId = ?");
|
|
3898
|
+
queryParams.push(args.datasetId);
|
|
3899
|
+
}
|
|
3900
|
+
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
3901
|
+
const countResult = await this.#client.execute({
|
|
3902
|
+
sql: `SELECT COUNT(*) as count FROM ${TABLE_EXPERIMENTS} ${whereClause}`,
|
|
3903
|
+
args: queryParams
|
|
3904
|
+
});
|
|
3905
|
+
const total = Number(countResult.rows?.[0]?.count ?? 0);
|
|
3906
|
+
if (total === 0) {
|
|
3907
|
+
return {
|
|
3908
|
+
experiments: [],
|
|
3909
|
+
pagination: { total: 0, page, perPage: perPageInput, hasMore: false }
|
|
3910
|
+
};
|
|
3911
|
+
}
|
|
3912
|
+
const perPage = normalizePerPage(perPageInput, 100);
|
|
3913
|
+
const { offset: start, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
|
|
3914
|
+
const limitValue = perPageInput === false ? total : perPage;
|
|
3915
|
+
const end = perPageInput === false ? total : start + perPage;
|
|
3916
|
+
const result = await this.#client.execute({
|
|
3917
|
+
sql: `SELECT ${buildSelectColumns(TABLE_EXPERIMENTS)} FROM ${TABLE_EXPERIMENTS} ${whereClause} ORDER BY createdAt DESC LIMIT ? OFFSET ?`,
|
|
3918
|
+
args: [...queryParams, limitValue, start]
|
|
3919
|
+
});
|
|
3920
|
+
return {
|
|
3921
|
+
experiments: result.rows?.map((row) => this.transformExperimentRow(row)) ?? [],
|
|
3922
|
+
pagination: {
|
|
3923
|
+
total,
|
|
3924
|
+
page,
|
|
3925
|
+
perPage: perPageForResponse,
|
|
3926
|
+
hasMore: end < total
|
|
3927
|
+
}
|
|
3928
|
+
};
|
|
3929
|
+
} catch (error) {
|
|
3930
|
+
throw new MastraError(
|
|
3931
|
+
{
|
|
3932
|
+
id: createStorageErrorId("LIBSQL", "LIST_EXPERIMENTS", "FAILED"),
|
|
3933
|
+
domain: ErrorDomain.STORAGE,
|
|
3934
|
+
category: ErrorCategory.THIRD_PARTY
|
|
3935
|
+
},
|
|
3936
|
+
error
|
|
3937
|
+
);
|
|
3938
|
+
}
|
|
3939
|
+
}
|
|
3940
|
+
async deleteExperiment(args) {
|
|
3941
|
+
try {
|
|
3942
|
+
await this.#client.execute({
|
|
3943
|
+
sql: `DELETE FROM ${TABLE_EXPERIMENT_RESULTS} WHERE experimentId = ?`,
|
|
3944
|
+
args: [args.id]
|
|
3945
|
+
});
|
|
3946
|
+
await this.#client.execute({
|
|
3947
|
+
sql: `DELETE FROM ${TABLE_EXPERIMENTS} WHERE id = ?`,
|
|
3948
|
+
args: [args.id]
|
|
3949
|
+
});
|
|
3950
|
+
} catch (error) {
|
|
3951
|
+
throw new MastraError(
|
|
3952
|
+
{
|
|
3953
|
+
id: createStorageErrorId("LIBSQL", "DELETE_EXPERIMENT", "FAILED"),
|
|
3954
|
+
domain: ErrorDomain.STORAGE,
|
|
3955
|
+
category: ErrorCategory.THIRD_PARTY
|
|
3956
|
+
},
|
|
3957
|
+
error
|
|
3958
|
+
);
|
|
3959
|
+
}
|
|
3960
|
+
}
|
|
3961
|
+
// Results (per-item)
|
|
3962
|
+
async addExperimentResult(input) {
|
|
3963
|
+
try {
|
|
3964
|
+
const id = input.id ?? crypto.randomUUID();
|
|
3965
|
+
const now = /* @__PURE__ */ new Date();
|
|
3966
|
+
const nowIso = now.toISOString();
|
|
3967
|
+
await this.#db.insert({
|
|
3968
|
+
tableName: TABLE_EXPERIMENT_RESULTS,
|
|
3969
|
+
record: {
|
|
3970
|
+
id,
|
|
3971
|
+
experimentId: input.experimentId,
|
|
3972
|
+
itemId: input.itemId,
|
|
3973
|
+
itemDatasetVersion: input.itemDatasetVersion ?? null,
|
|
3974
|
+
input: input.input,
|
|
3975
|
+
output: input.output,
|
|
3976
|
+
groundTruth: input.groundTruth,
|
|
3977
|
+
error: input.error ?? null,
|
|
3978
|
+
startedAt: input.startedAt.toISOString(),
|
|
3979
|
+
completedAt: input.completedAt.toISOString(),
|
|
3980
|
+
retryCount: input.retryCount,
|
|
3981
|
+
traceId: input.traceId ?? null,
|
|
3982
|
+
createdAt: nowIso
|
|
3983
|
+
}
|
|
3984
|
+
});
|
|
3985
|
+
return {
|
|
3986
|
+
id,
|
|
3987
|
+
experimentId: input.experimentId,
|
|
3988
|
+
itemId: input.itemId,
|
|
3989
|
+
itemDatasetVersion: input.itemDatasetVersion,
|
|
3990
|
+
input: input.input,
|
|
3991
|
+
output: input.output,
|
|
3992
|
+
groundTruth: input.groundTruth,
|
|
3993
|
+
error: input.error,
|
|
3994
|
+
startedAt: input.startedAt,
|
|
3995
|
+
completedAt: input.completedAt,
|
|
3996
|
+
retryCount: input.retryCount,
|
|
3997
|
+
traceId: input.traceId ?? null,
|
|
3998
|
+
createdAt: now
|
|
3999
|
+
};
|
|
4000
|
+
} catch (error) {
|
|
4001
|
+
throw new MastraError(
|
|
4002
|
+
{
|
|
4003
|
+
id: createStorageErrorId("LIBSQL", "ADD_EXPERIMENT_RESULT", "FAILED"),
|
|
4004
|
+
domain: ErrorDomain.STORAGE,
|
|
4005
|
+
category: ErrorCategory.THIRD_PARTY
|
|
4006
|
+
},
|
|
4007
|
+
error
|
|
4008
|
+
);
|
|
4009
|
+
}
|
|
4010
|
+
}
|
|
4011
|
+
async getExperimentResultById(args) {
|
|
4012
|
+
try {
|
|
4013
|
+
const result = await this.#client.execute({
|
|
4014
|
+
sql: `SELECT ${buildSelectColumns(TABLE_EXPERIMENT_RESULTS)} FROM ${TABLE_EXPERIMENT_RESULTS} WHERE id = ?`,
|
|
4015
|
+
args: [args.id]
|
|
4016
|
+
});
|
|
4017
|
+
return result.rows?.[0] ? this.transformExperimentResultRow(result.rows[0]) : null;
|
|
4018
|
+
} catch (error) {
|
|
4019
|
+
throw new MastraError(
|
|
4020
|
+
{
|
|
4021
|
+
id: createStorageErrorId("LIBSQL", "GET_EXPERIMENT_RESULT", "FAILED"),
|
|
4022
|
+
domain: ErrorDomain.STORAGE,
|
|
4023
|
+
category: ErrorCategory.THIRD_PARTY
|
|
4024
|
+
},
|
|
4025
|
+
error
|
|
4026
|
+
);
|
|
4027
|
+
}
|
|
4028
|
+
}
|
|
4029
|
+
async listExperimentResults(args) {
|
|
4030
|
+
try {
|
|
4031
|
+
const { page, perPage: perPageInput } = args.pagination;
|
|
4032
|
+
const conditions = ["experimentId = ?"];
|
|
4033
|
+
const queryParams = [args.experimentId];
|
|
4034
|
+
const whereClause = `WHERE ${conditions.join(" AND ")}`;
|
|
4035
|
+
const countResult = await this.#client.execute({
|
|
4036
|
+
sql: `SELECT COUNT(*) as count FROM ${TABLE_EXPERIMENT_RESULTS} ${whereClause}`,
|
|
4037
|
+
args: queryParams
|
|
4038
|
+
});
|
|
4039
|
+
const total = Number(countResult.rows?.[0]?.count ?? 0);
|
|
4040
|
+
if (total === 0) {
|
|
4041
|
+
return {
|
|
4042
|
+
results: [],
|
|
4043
|
+
pagination: { total: 0, page, perPage: perPageInput, hasMore: false }
|
|
4044
|
+
};
|
|
4045
|
+
}
|
|
4046
|
+
const perPage = normalizePerPage(perPageInput, 100);
|
|
4047
|
+
const { offset: start, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
|
|
4048
|
+
const limitValue = perPageInput === false ? total : perPage;
|
|
4049
|
+
const end = perPageInput === false ? total : start + perPage;
|
|
4050
|
+
const result = await this.#client.execute({
|
|
4051
|
+
sql: `SELECT ${buildSelectColumns(TABLE_EXPERIMENT_RESULTS)} FROM ${TABLE_EXPERIMENT_RESULTS} ${whereClause} ORDER BY startedAt ASC LIMIT ? OFFSET ?`,
|
|
4052
|
+
args: [...queryParams, limitValue, start]
|
|
4053
|
+
});
|
|
4054
|
+
return {
|
|
4055
|
+
results: result.rows?.map((row) => this.transformExperimentResultRow(row)) ?? [],
|
|
4056
|
+
pagination: {
|
|
4057
|
+
total,
|
|
4058
|
+
page,
|
|
4059
|
+
perPage: perPageForResponse,
|
|
4060
|
+
hasMore: end < total
|
|
4061
|
+
}
|
|
4062
|
+
};
|
|
4063
|
+
} catch (error) {
|
|
4064
|
+
throw new MastraError(
|
|
4065
|
+
{
|
|
4066
|
+
id: createStorageErrorId("LIBSQL", "LIST_EXPERIMENT_RESULTS", "FAILED"),
|
|
4067
|
+
domain: ErrorDomain.STORAGE,
|
|
4068
|
+
category: ErrorCategory.THIRD_PARTY
|
|
4069
|
+
},
|
|
4070
|
+
error
|
|
4071
|
+
);
|
|
4072
|
+
}
|
|
4073
|
+
}
|
|
4074
|
+
async deleteExperimentResults(args) {
|
|
4075
|
+
try {
|
|
4076
|
+
await this.#client.execute({
|
|
4077
|
+
sql: `DELETE FROM ${TABLE_EXPERIMENT_RESULTS} WHERE experimentId = ?`,
|
|
4078
|
+
args: [args.experimentId]
|
|
4079
|
+
});
|
|
4080
|
+
} catch (error) {
|
|
4081
|
+
throw new MastraError(
|
|
4082
|
+
{
|
|
4083
|
+
id: createStorageErrorId("LIBSQL", "DELETE_EXPERIMENT_RESULTS", "FAILED"),
|
|
4084
|
+
domain: ErrorDomain.STORAGE,
|
|
4085
|
+
category: ErrorCategory.THIRD_PARTY
|
|
4086
|
+
},
|
|
4087
|
+
error
|
|
4088
|
+
);
|
|
4089
|
+
}
|
|
4090
|
+
}
|
|
4091
|
+
};
|
|
4092
|
+
var SNAPSHOT_FIELDS2 = ["name", "description", "servers"];
|
|
4093
|
+
var MCPClientsLibSQL = class extends MCPClientsStorage {
|
|
4094
|
+
#db;
|
|
4095
|
+
#client;
|
|
4096
|
+
constructor(config) {
|
|
4097
|
+
super();
|
|
4098
|
+
const client = resolveClient(config);
|
|
4099
|
+
this.#client = client;
|
|
4100
|
+
this.#db = new LibSQLDB({ client, maxRetries: config.maxRetries, initialBackoffMs: config.initialBackoffMs });
|
|
4101
|
+
}
|
|
4102
|
+
async init() {
|
|
4103
|
+
await this.#db.createTable({ tableName: TABLE_MCP_CLIENTS, schema: MCP_CLIENTS_SCHEMA });
|
|
4104
|
+
await this.#db.createTable({
|
|
4105
|
+
tableName: TABLE_MCP_CLIENT_VERSIONS,
|
|
4106
|
+
schema: MCP_CLIENT_VERSIONS_SCHEMA
|
|
4107
|
+
});
|
|
4108
|
+
await this.#client.execute(
|
|
4109
|
+
`CREATE UNIQUE INDEX IF NOT EXISTS idx_mcp_client_versions_client_version ON "${TABLE_MCP_CLIENT_VERSIONS}" ("mcpClientId", "versionNumber")`
|
|
4110
|
+
);
|
|
4111
|
+
}
|
|
4112
|
+
async dangerouslyClearAll() {
|
|
4113
|
+
await this.#db.deleteData({ tableName: TABLE_MCP_CLIENTS });
|
|
4114
|
+
await this.#db.deleteData({ tableName: TABLE_MCP_CLIENT_VERSIONS });
|
|
4115
|
+
}
|
|
4116
|
+
// ==========================================================================
|
|
4117
|
+
// MCP Client CRUD
|
|
4118
|
+
// ==========================================================================
|
|
4119
|
+
async getById(id) {
|
|
4120
|
+
try {
|
|
4121
|
+
const result = await this.#client.execute({
|
|
4122
|
+
sql: `SELECT ${buildSelectColumns(TABLE_MCP_CLIENTS)} FROM "${TABLE_MCP_CLIENTS}" WHERE id = ?`,
|
|
4123
|
+
args: [id]
|
|
4124
|
+
});
|
|
4125
|
+
const row = result.rows?.[0];
|
|
4126
|
+
return row ? this.#parseMCPClientRow(row) : null;
|
|
4127
|
+
} catch (error) {
|
|
4128
|
+
if (error instanceof MastraError) throw error;
|
|
4129
|
+
throw new MastraError(
|
|
4130
|
+
{
|
|
4131
|
+
id: createStorageErrorId("LIBSQL", "GET_MCP_CLIENT", "FAILED"),
|
|
4132
|
+
domain: ErrorDomain.STORAGE,
|
|
4133
|
+
category: ErrorCategory.THIRD_PARTY
|
|
4134
|
+
},
|
|
4135
|
+
error
|
|
4136
|
+
);
|
|
4137
|
+
}
|
|
4138
|
+
}
|
|
4139
|
+
async create(input) {
|
|
4140
|
+
const { mcpClient } = input;
|
|
4141
|
+
try {
|
|
4142
|
+
const now = /* @__PURE__ */ new Date();
|
|
4143
|
+
await this.#db.insert({
|
|
4144
|
+
tableName: TABLE_MCP_CLIENTS,
|
|
4145
|
+
record: {
|
|
4146
|
+
id: mcpClient.id,
|
|
4147
|
+
status: "draft",
|
|
4148
|
+
activeVersionId: null,
|
|
4149
|
+
authorId: mcpClient.authorId ?? null,
|
|
4150
|
+
metadata: mcpClient.metadata ?? null,
|
|
4151
|
+
createdAt: now.toISOString(),
|
|
4152
|
+
updatedAt: now.toISOString()
|
|
4153
|
+
}
|
|
4154
|
+
});
|
|
4155
|
+
const { id: _id, authorId: _authorId, metadata: _metadata, ...snapshotConfig } = mcpClient;
|
|
4156
|
+
const versionId = crypto.randomUUID();
|
|
4157
|
+
try {
|
|
4158
|
+
await this.createVersion({
|
|
4159
|
+
id: versionId,
|
|
4160
|
+
mcpClientId: mcpClient.id,
|
|
4161
|
+
versionNumber: 1,
|
|
4162
|
+
...snapshotConfig,
|
|
4163
|
+
changedFields: Object.keys(snapshotConfig),
|
|
4164
|
+
changeMessage: "Initial version"
|
|
4165
|
+
});
|
|
4166
|
+
} catch (versionError) {
|
|
4167
|
+
await this.#db.delete({ tableName: TABLE_MCP_CLIENTS, keys: { id: mcpClient.id } });
|
|
4168
|
+
throw versionError;
|
|
4169
|
+
}
|
|
4170
|
+
return {
|
|
4171
|
+
id: mcpClient.id,
|
|
4172
|
+
status: "draft",
|
|
4173
|
+
activeVersionId: void 0,
|
|
4174
|
+
authorId: mcpClient.authorId,
|
|
4175
|
+
metadata: mcpClient.metadata,
|
|
4176
|
+
createdAt: now,
|
|
4177
|
+
updatedAt: now
|
|
4178
|
+
};
|
|
4179
|
+
} catch (error) {
|
|
4180
|
+
if (error instanceof MastraError) throw error;
|
|
4181
|
+
throw new MastraError(
|
|
4182
|
+
{
|
|
4183
|
+
id: createStorageErrorId("LIBSQL", "CREATE_MCP_CLIENT", "FAILED"),
|
|
4184
|
+
domain: ErrorDomain.STORAGE,
|
|
4185
|
+
category: ErrorCategory.THIRD_PARTY
|
|
4186
|
+
},
|
|
4187
|
+
error
|
|
4188
|
+
);
|
|
4189
|
+
}
|
|
4190
|
+
}
|
|
4191
|
+
async update(input) {
|
|
4192
|
+
const { id, ...updates } = input;
|
|
4193
|
+
try {
|
|
4194
|
+
const existing = await this.getById(id);
|
|
4195
|
+
if (!existing) {
|
|
4196
|
+
throw new Error(`MCP client with id ${id} not found`);
|
|
4197
|
+
}
|
|
4198
|
+
const { authorId, activeVersionId, metadata, status, ...configFields } = updates;
|
|
4199
|
+
const configFieldNames = SNAPSHOT_FIELDS2;
|
|
4200
|
+
const hasConfigUpdate = configFieldNames.some((field) => field in configFields);
|
|
4201
|
+
const updateData = {
|
|
4202
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
4203
|
+
};
|
|
4204
|
+
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
|
+
}
|
|
4211
|
+
if (status !== void 0) updateData.status = status;
|
|
4212
|
+
if (metadata !== void 0) {
|
|
4213
|
+
updateData.metadata = { ...existing.metadata, ...metadata };
|
|
4214
|
+
}
|
|
4215
|
+
await this.#db.update({
|
|
4216
|
+
tableName: TABLE_MCP_CLIENTS,
|
|
4217
|
+
keys: { id },
|
|
4218
|
+
data: updateData
|
|
4219
|
+
});
|
|
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
|
+
const updated = await this.getById(id);
|
|
4251
|
+
if (!updated) {
|
|
4252
|
+
throw new MastraError({
|
|
4253
|
+
id: createStorageErrorId("LIBSQL", "UPDATE_MCP_CLIENT", "NOT_FOUND_AFTER_UPDATE"),
|
|
4254
|
+
domain: ErrorDomain.STORAGE,
|
|
4255
|
+
category: ErrorCategory.SYSTEM,
|
|
4256
|
+
text: `MCP client ${id} not found after update`,
|
|
4257
|
+
details: { id }
|
|
4258
|
+
});
|
|
4259
|
+
}
|
|
4260
|
+
return updated;
|
|
4261
|
+
} catch (error) {
|
|
4262
|
+
if (error instanceof MastraError) throw error;
|
|
4263
|
+
throw new MastraError(
|
|
4264
|
+
{
|
|
4265
|
+
id: createStorageErrorId("LIBSQL", "UPDATE_MCP_CLIENT", "FAILED"),
|
|
4266
|
+
domain: ErrorDomain.STORAGE,
|
|
4267
|
+
category: ErrorCategory.THIRD_PARTY
|
|
4268
|
+
},
|
|
4269
|
+
error
|
|
4270
|
+
);
|
|
4271
|
+
}
|
|
4272
|
+
}
|
|
4273
|
+
async delete(id) {
|
|
4274
|
+
try {
|
|
4275
|
+
await this.deleteVersionsByParentId(id);
|
|
4276
|
+
await this.#client.execute({
|
|
4277
|
+
sql: `DELETE FROM "${TABLE_MCP_CLIENTS}" WHERE "id" = ?`,
|
|
4278
|
+
args: [id]
|
|
4279
|
+
});
|
|
4280
|
+
} catch (error) {
|
|
4281
|
+
if (error instanceof MastraError) throw error;
|
|
4282
|
+
throw new MastraError(
|
|
4283
|
+
{
|
|
4284
|
+
id: createStorageErrorId("LIBSQL", "DELETE_MCP_CLIENT", "FAILED"),
|
|
4285
|
+
domain: ErrorDomain.STORAGE,
|
|
4286
|
+
category: ErrorCategory.THIRD_PARTY
|
|
4287
|
+
},
|
|
4288
|
+
error
|
|
4289
|
+
);
|
|
4290
|
+
}
|
|
4291
|
+
}
|
|
4292
|
+
async list(args) {
|
|
4293
|
+
try {
|
|
4294
|
+
const { page = 0, perPage: perPageInput, orderBy, authorId, metadata } = args || {};
|
|
4295
|
+
const { field, direction } = this.parseOrderBy(orderBy);
|
|
4296
|
+
const conditions = [];
|
|
4297
|
+
const queryParams = [];
|
|
4298
|
+
if (authorId !== void 0) {
|
|
4299
|
+
conditions.push("authorId = ?");
|
|
4300
|
+
queryParams.push(authorId);
|
|
4301
|
+
}
|
|
4302
|
+
if (metadata && Object.keys(metadata).length > 0) {
|
|
4303
|
+
for (const [key, value] of Object.entries(metadata)) {
|
|
4304
|
+
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(key)) {
|
|
4305
|
+
throw new MastraError({
|
|
4306
|
+
id: createStorageErrorId("LIBSQL", "LIST_MCP_CLIENTS", "INVALID_METADATA_KEY"),
|
|
4307
|
+
domain: ErrorDomain.STORAGE,
|
|
4308
|
+
category: ErrorCategory.USER,
|
|
4309
|
+
text: `Invalid metadata key: ${key}. Keys must be alphanumeric with underscores.`,
|
|
4310
|
+
details: { key }
|
|
4311
|
+
});
|
|
4312
|
+
}
|
|
4313
|
+
conditions.push(`json_extract(metadata, '$.${key}') = ?`);
|
|
4314
|
+
queryParams.push(typeof value === "string" ? value : JSON.stringify(value));
|
|
4315
|
+
}
|
|
4316
|
+
}
|
|
4317
|
+
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
4318
|
+
const countResult = await this.#client.execute({
|
|
4319
|
+
sql: `SELECT COUNT(*) as count FROM "${TABLE_MCP_CLIENTS}" ${whereClause}`,
|
|
4320
|
+
args: queryParams
|
|
4321
|
+
});
|
|
4322
|
+
const total = Number(countResult.rows?.[0]?.count ?? 0);
|
|
4323
|
+
if (total === 0) {
|
|
4324
|
+
return {
|
|
4325
|
+
mcpClients: [],
|
|
2487
4326
|
total: 0,
|
|
2488
4327
|
page,
|
|
2489
|
-
perPage:
|
|
4328
|
+
perPage: perPageInput ?? 100,
|
|
2490
4329
|
hasMore: false
|
|
2491
4330
|
};
|
|
2492
4331
|
}
|
|
4332
|
+
const perPage = normalizePerPage(perPageInput, 100);
|
|
4333
|
+
const { offset: start, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
|
|
2493
4334
|
const limitValue = perPageInput === false ? total : perPage;
|
|
2494
|
-
const
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
offset
|
|
4335
|
+
const end = perPageInput === false ? total : start + perPage;
|
|
4336
|
+
const result = await this.#client.execute({
|
|
4337
|
+
sql: `SELECT ${buildSelectColumns(TABLE_MCP_CLIENTS)} FROM "${TABLE_MCP_CLIENTS}" ${whereClause} ORDER BY ${field} ${direction} LIMIT ? OFFSET ?`,
|
|
4338
|
+
args: [...queryParams, limitValue, start]
|
|
2499
4339
|
});
|
|
2500
|
-
const
|
|
4340
|
+
const mcpClients = result.rows?.map((row) => this.#parseMCPClientRow(row)) ?? [];
|
|
2501
4341
|
return {
|
|
2502
|
-
|
|
4342
|
+
mcpClients,
|
|
2503
4343
|
total,
|
|
2504
4344
|
page,
|
|
2505
4345
|
perPage: perPageForResponse,
|
|
2506
|
-
hasMore:
|
|
4346
|
+
hasMore: end < total
|
|
2507
4347
|
};
|
|
2508
4348
|
} catch (error) {
|
|
2509
4349
|
if (error instanceof MastraError) throw error;
|
|
2510
4350
|
throw new MastraError(
|
|
2511
4351
|
{
|
|
2512
|
-
id: createStorageErrorId("LIBSQL", "
|
|
4352
|
+
id: createStorageErrorId("LIBSQL", "LIST_MCP_CLIENTS", "FAILED"),
|
|
2513
4353
|
domain: ErrorDomain.STORAGE,
|
|
2514
4354
|
category: ErrorCategory.THIRD_PARTY
|
|
2515
4355
|
},
|
|
@@ -2518,33 +4358,23 @@ var AgentsLibSQL = class extends AgentsStorage {
|
|
|
2518
4358
|
}
|
|
2519
4359
|
}
|
|
2520
4360
|
// ==========================================================================
|
|
2521
|
-
//
|
|
4361
|
+
// MCP Client Version Methods
|
|
2522
4362
|
// ==========================================================================
|
|
2523
4363
|
async createVersion(input) {
|
|
2524
4364
|
try {
|
|
2525
4365
|
const now = /* @__PURE__ */ new Date();
|
|
2526
4366
|
await this.#db.insert({
|
|
2527
|
-
tableName:
|
|
4367
|
+
tableName: TABLE_MCP_CLIENT_VERSIONS,
|
|
2528
4368
|
record: {
|
|
2529
4369
|
id: input.id,
|
|
2530
|
-
|
|
4370
|
+
mcpClientId: input.mcpClientId,
|
|
2531
4371
|
versionNumber: input.versionNumber,
|
|
2532
|
-
name: input.name
|
|
4372
|
+
name: input.name,
|
|
2533
4373
|
description: input.description ?? null,
|
|
2534
|
-
|
|
2535
|
-
model: input.model,
|
|
2536
|
-
tools: input.tools ?? null,
|
|
2537
|
-
defaultOptions: input.defaultOptions ?? null,
|
|
2538
|
-
workflows: input.workflows ?? null,
|
|
2539
|
-
agents: input.agents ?? null,
|
|
2540
|
-
integrationTools: input.integrationTools ?? null,
|
|
2541
|
-
inputProcessors: input.inputProcessors ?? null,
|
|
2542
|
-
outputProcessors: input.outputProcessors ?? null,
|
|
2543
|
-
memory: input.memory ?? null,
|
|
2544
|
-
scorers: input.scorers ?? null,
|
|
4374
|
+
servers: input.servers ?? null,
|
|
2545
4375
|
changedFields: input.changedFields ?? null,
|
|
2546
4376
|
changeMessage: input.changeMessage ?? null,
|
|
2547
|
-
createdAt: now
|
|
4377
|
+
createdAt: now.toISOString()
|
|
2548
4378
|
}
|
|
2549
4379
|
});
|
|
2550
4380
|
return {
|
|
@@ -2555,10 +4385,9 @@ var AgentsLibSQL = class extends AgentsStorage {
|
|
|
2555
4385
|
if (error instanceof MastraError) throw error;
|
|
2556
4386
|
throw new MastraError(
|
|
2557
4387
|
{
|
|
2558
|
-
id: createStorageErrorId("LIBSQL", "
|
|
4388
|
+
id: createStorageErrorId("LIBSQL", "CREATE_MCP_CLIENT_VERSION", "FAILED"),
|
|
2559
4389
|
domain: ErrorDomain.STORAGE,
|
|
2560
|
-
category: ErrorCategory.THIRD_PARTY
|
|
2561
|
-
details: { versionId: input.id, agentId: input.agentId }
|
|
4390
|
+
category: ErrorCategory.THIRD_PARTY
|
|
2562
4391
|
},
|
|
2563
4392
|
error
|
|
2564
4393
|
);
|
|
@@ -2566,142 +4395,105 @@ var AgentsLibSQL = class extends AgentsStorage {
|
|
|
2566
4395
|
}
|
|
2567
4396
|
async getVersion(id) {
|
|
2568
4397
|
try {
|
|
2569
|
-
const result = await this.#
|
|
2570
|
-
|
|
2571
|
-
|
|
4398
|
+
const result = await this.#client.execute({
|
|
4399
|
+
sql: `SELECT ${buildSelectColumns(TABLE_MCP_CLIENT_VERSIONS)} FROM "${TABLE_MCP_CLIENT_VERSIONS}" WHERE id = ?`,
|
|
4400
|
+
args: [id]
|
|
2572
4401
|
});
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
}
|
|
2576
|
-
return this.parseVersionRow(result);
|
|
4402
|
+
const row = result.rows?.[0];
|
|
4403
|
+
return row ? this.#parseVersionRow(row) : null;
|
|
2577
4404
|
} catch (error) {
|
|
2578
4405
|
if (error instanceof MastraError) throw error;
|
|
2579
4406
|
throw new MastraError(
|
|
2580
4407
|
{
|
|
2581
|
-
id: createStorageErrorId("LIBSQL", "
|
|
4408
|
+
id: createStorageErrorId("LIBSQL", "GET_MCP_CLIENT_VERSION", "FAILED"),
|
|
2582
4409
|
domain: ErrorDomain.STORAGE,
|
|
2583
|
-
category: ErrorCategory.THIRD_PARTY
|
|
2584
|
-
details: { versionId: id }
|
|
4410
|
+
category: ErrorCategory.THIRD_PARTY
|
|
2585
4411
|
},
|
|
2586
4412
|
error
|
|
2587
4413
|
);
|
|
2588
4414
|
}
|
|
2589
4415
|
}
|
|
2590
|
-
async getVersionByNumber(
|
|
4416
|
+
async getVersionByNumber(mcpClientId, versionNumber) {
|
|
2591
4417
|
try {
|
|
2592
|
-
const
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
sql: "WHERE agentId = ? AND versionNumber = ?",
|
|
2596
|
-
args: [agentId, versionNumber]
|
|
2597
|
-
},
|
|
2598
|
-
limit: 1
|
|
4418
|
+
const result = await this.#client.execute({
|
|
4419
|
+
sql: `SELECT ${buildSelectColumns(TABLE_MCP_CLIENT_VERSIONS)} FROM "${TABLE_MCP_CLIENT_VERSIONS}" WHERE mcpClientId = ? AND versionNumber = ?`,
|
|
4420
|
+
args: [mcpClientId, versionNumber]
|
|
2599
4421
|
});
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
}
|
|
2603
|
-
return this.parseVersionRow(rows[0]);
|
|
4422
|
+
const row = result.rows?.[0];
|
|
4423
|
+
return row ? this.#parseVersionRow(row) : null;
|
|
2604
4424
|
} catch (error) {
|
|
2605
4425
|
if (error instanceof MastraError) throw error;
|
|
2606
4426
|
throw new MastraError(
|
|
2607
4427
|
{
|
|
2608
|
-
id: createStorageErrorId("LIBSQL", "
|
|
4428
|
+
id: createStorageErrorId("LIBSQL", "GET_MCP_CLIENT_VERSION_BY_NUMBER", "FAILED"),
|
|
2609
4429
|
domain: ErrorDomain.STORAGE,
|
|
2610
|
-
category: ErrorCategory.THIRD_PARTY
|
|
2611
|
-
details: { agentId, versionNumber }
|
|
4430
|
+
category: ErrorCategory.THIRD_PARTY
|
|
2612
4431
|
},
|
|
2613
4432
|
error
|
|
2614
4433
|
);
|
|
2615
4434
|
}
|
|
2616
4435
|
}
|
|
2617
|
-
async getLatestVersion(
|
|
4436
|
+
async getLatestVersion(mcpClientId) {
|
|
2618
4437
|
try {
|
|
2619
|
-
const
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
sql: "WHERE agentId = ?",
|
|
2623
|
-
args: [agentId]
|
|
2624
|
-
},
|
|
2625
|
-
orderBy: "versionNumber DESC",
|
|
2626
|
-
limit: 1
|
|
4438
|
+
const result = await this.#client.execute({
|
|
4439
|
+
sql: `SELECT ${buildSelectColumns(TABLE_MCP_CLIENT_VERSIONS)} FROM "${TABLE_MCP_CLIENT_VERSIONS}" WHERE mcpClientId = ? ORDER BY versionNumber DESC LIMIT 1`,
|
|
4440
|
+
args: [mcpClientId]
|
|
2627
4441
|
});
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
}
|
|
2631
|
-
return this.parseVersionRow(rows[0]);
|
|
4442
|
+
const row = result.rows?.[0];
|
|
4443
|
+
return row ? this.#parseVersionRow(row) : null;
|
|
2632
4444
|
} catch (error) {
|
|
2633
4445
|
if (error instanceof MastraError) throw error;
|
|
2634
4446
|
throw new MastraError(
|
|
2635
4447
|
{
|
|
2636
|
-
id: createStorageErrorId("LIBSQL", "
|
|
4448
|
+
id: createStorageErrorId("LIBSQL", "GET_LATEST_MCP_CLIENT_VERSION", "FAILED"),
|
|
2637
4449
|
domain: ErrorDomain.STORAGE,
|
|
2638
|
-
category: ErrorCategory.THIRD_PARTY
|
|
2639
|
-
details: { agentId }
|
|
4450
|
+
category: ErrorCategory.THIRD_PARTY
|
|
2640
4451
|
},
|
|
2641
4452
|
error
|
|
2642
4453
|
);
|
|
2643
4454
|
}
|
|
2644
4455
|
}
|
|
2645
4456
|
async listVersions(input) {
|
|
2646
|
-
const { agentId, page = 0, perPage: perPageInput, orderBy } = input;
|
|
2647
|
-
if (page < 0) {
|
|
2648
|
-
throw new MastraError(
|
|
2649
|
-
{
|
|
2650
|
-
id: createStorageErrorId("LIBSQL", "LIST_VERSIONS", "INVALID_PAGE"),
|
|
2651
|
-
domain: ErrorDomain.STORAGE,
|
|
2652
|
-
category: ErrorCategory.USER,
|
|
2653
|
-
details: { page }
|
|
2654
|
-
},
|
|
2655
|
-
new Error("page must be >= 0")
|
|
2656
|
-
);
|
|
2657
|
-
}
|
|
2658
|
-
const perPage = normalizePerPage(perPageInput, 20);
|
|
2659
|
-
const { offset, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
|
|
2660
4457
|
try {
|
|
4458
|
+
const { mcpClientId, page = 0, perPage: perPageInput, orderBy } = input;
|
|
2661
4459
|
const { field, direction } = this.parseVersionOrderBy(orderBy);
|
|
2662
|
-
const
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
sql: "WHERE agentId = ?",
|
|
2666
|
-
args: [agentId]
|
|
2667
|
-
}
|
|
4460
|
+
const countResult = await this.#client.execute({
|
|
4461
|
+
sql: `SELECT COUNT(*) as count FROM "${TABLE_MCP_CLIENT_VERSIONS}" WHERE mcpClientId = ?`,
|
|
4462
|
+
args: [mcpClientId]
|
|
2668
4463
|
});
|
|
4464
|
+
const total = Number(countResult.rows?.[0]?.count ?? 0);
|
|
2669
4465
|
if (total === 0) {
|
|
2670
4466
|
return {
|
|
2671
4467
|
versions: [],
|
|
2672
4468
|
total: 0,
|
|
2673
4469
|
page,
|
|
2674
|
-
perPage:
|
|
4470
|
+
perPage: perPageInput ?? 20,
|
|
2675
4471
|
hasMore: false
|
|
2676
4472
|
};
|
|
2677
4473
|
}
|
|
4474
|
+
const perPage = normalizePerPage(perPageInput, 20);
|
|
4475
|
+
const { offset: start, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
|
|
2678
4476
|
const limitValue = perPageInput === false ? total : perPage;
|
|
2679
|
-
const
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
args: [agentId]
|
|
2684
|
-
},
|
|
2685
|
-
orderBy: `"${field}" ${direction}`,
|
|
2686
|
-
limit: limitValue,
|
|
2687
|
-
offset
|
|
4477
|
+
const end = perPageInput === false ? total : start + perPage;
|
|
4478
|
+
const result = await this.#client.execute({
|
|
4479
|
+
sql: `SELECT ${buildSelectColumns(TABLE_MCP_CLIENT_VERSIONS)} FROM "${TABLE_MCP_CLIENT_VERSIONS}" WHERE mcpClientId = ? ORDER BY ${field} ${direction} LIMIT ? OFFSET ?`,
|
|
4480
|
+
args: [mcpClientId, limitValue, start]
|
|
2688
4481
|
});
|
|
2689
|
-
const versions = rows
|
|
4482
|
+
const versions = result.rows?.map((row) => this.#parseVersionRow(row)) ?? [];
|
|
2690
4483
|
return {
|
|
2691
4484
|
versions,
|
|
2692
4485
|
total,
|
|
2693
4486
|
page,
|
|
2694
4487
|
perPage: perPageForResponse,
|
|
2695
|
-
hasMore:
|
|
4488
|
+
hasMore: end < total
|
|
2696
4489
|
};
|
|
2697
4490
|
} catch (error) {
|
|
2698
4491
|
if (error instanceof MastraError) throw error;
|
|
2699
4492
|
throw new MastraError(
|
|
2700
4493
|
{
|
|
2701
|
-
id: createStorageErrorId("LIBSQL", "
|
|
4494
|
+
id: createStorageErrorId("LIBSQL", "LIST_MCP_CLIENT_VERSIONS", "FAILED"),
|
|
2702
4495
|
domain: ErrorDomain.STORAGE,
|
|
2703
|
-
category: ErrorCategory.THIRD_PARTY
|
|
2704
|
-
details: { agentId }
|
|
4496
|
+
category: ErrorCategory.THIRD_PARTY
|
|
2705
4497
|
},
|
|
2706
4498
|
error
|
|
2707
4499
|
);
|
|
@@ -2709,18 +4501,17 @@ var AgentsLibSQL = class extends AgentsStorage {
|
|
|
2709
4501
|
}
|
|
2710
4502
|
async deleteVersion(id) {
|
|
2711
4503
|
try {
|
|
2712
|
-
await this.#
|
|
2713
|
-
|
|
2714
|
-
|
|
4504
|
+
await this.#client.execute({
|
|
4505
|
+
sql: `DELETE FROM "${TABLE_MCP_CLIENT_VERSIONS}" WHERE "id" = ?`,
|
|
4506
|
+
args: [id]
|
|
2715
4507
|
});
|
|
2716
4508
|
} catch (error) {
|
|
2717
4509
|
if (error instanceof MastraError) throw error;
|
|
2718
4510
|
throw new MastraError(
|
|
2719
4511
|
{
|
|
2720
|
-
id: createStorageErrorId("LIBSQL", "
|
|
4512
|
+
id: createStorageErrorId("LIBSQL", "DELETE_MCP_CLIENT_VERSION", "FAILED"),
|
|
2721
4513
|
domain: ErrorDomain.STORAGE,
|
|
2722
|
-
category: ErrorCategory.THIRD_PARTY
|
|
2723
|
-
details: { versionId: id }
|
|
4514
|
+
category: ErrorCategory.THIRD_PARTY
|
|
2724
4515
|
},
|
|
2725
4516
|
error
|
|
2726
4517
|
);
|
|
@@ -2728,90 +4519,87 @@ var AgentsLibSQL = class extends AgentsStorage {
|
|
|
2728
4519
|
}
|
|
2729
4520
|
async deleteVersionsByParentId(entityId) {
|
|
2730
4521
|
try {
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
sql: "WHERE agentId = ?",
|
|
2735
|
-
args: [entityId]
|
|
2736
|
-
}
|
|
4522
|
+
await this.#client.execute({
|
|
4523
|
+
sql: `DELETE FROM "${TABLE_MCP_CLIENT_VERSIONS}" WHERE "mcpClientId" = ?`,
|
|
4524
|
+
args: [entityId]
|
|
2737
4525
|
});
|
|
2738
|
-
for (const version of versions) {
|
|
2739
|
-
await this.#db.delete({
|
|
2740
|
-
tableName: TABLE_AGENT_VERSIONS,
|
|
2741
|
-
keys: { id: version.id }
|
|
2742
|
-
});
|
|
2743
|
-
}
|
|
2744
4526
|
} catch (error) {
|
|
2745
4527
|
if (error instanceof MastraError) throw error;
|
|
2746
4528
|
throw new MastraError(
|
|
2747
4529
|
{
|
|
2748
|
-
id: createStorageErrorId("LIBSQL", "
|
|
4530
|
+
id: createStorageErrorId("LIBSQL", "DELETE_MCP_CLIENT_VERSIONS_BY_CLIENT", "FAILED"),
|
|
2749
4531
|
domain: ErrorDomain.STORAGE,
|
|
2750
|
-
category: ErrorCategory.THIRD_PARTY
|
|
2751
|
-
details: { agentId: entityId }
|
|
4532
|
+
category: ErrorCategory.THIRD_PARTY
|
|
2752
4533
|
},
|
|
2753
4534
|
error
|
|
2754
4535
|
);
|
|
2755
4536
|
}
|
|
2756
4537
|
}
|
|
2757
|
-
async countVersions(
|
|
4538
|
+
async countVersions(mcpClientId) {
|
|
2758
4539
|
try {
|
|
2759
|
-
const
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
sql: "WHERE agentId = ?",
|
|
2763
|
-
args: [agentId]
|
|
2764
|
-
}
|
|
4540
|
+
const result = await this.#client.execute({
|
|
4541
|
+
sql: `SELECT COUNT(*) as count FROM "${TABLE_MCP_CLIENT_VERSIONS}" WHERE mcpClientId = ?`,
|
|
4542
|
+
args: [mcpClientId]
|
|
2765
4543
|
});
|
|
2766
|
-
return count;
|
|
4544
|
+
return Number(result.rows?.[0]?.count ?? 0);
|
|
2767
4545
|
} catch (error) {
|
|
2768
4546
|
if (error instanceof MastraError) throw error;
|
|
2769
4547
|
throw new MastraError(
|
|
2770
4548
|
{
|
|
2771
|
-
id: createStorageErrorId("LIBSQL", "
|
|
4549
|
+
id: createStorageErrorId("LIBSQL", "COUNT_MCP_CLIENT_VERSIONS", "FAILED"),
|
|
2772
4550
|
domain: ErrorDomain.STORAGE,
|
|
2773
|
-
category: ErrorCategory.THIRD_PARTY
|
|
2774
|
-
details: { agentId }
|
|
4551
|
+
category: ErrorCategory.THIRD_PARTY
|
|
2775
4552
|
},
|
|
2776
4553
|
error
|
|
2777
4554
|
);
|
|
2778
4555
|
}
|
|
2779
4556
|
}
|
|
2780
4557
|
// ==========================================================================
|
|
2781
|
-
// Private
|
|
4558
|
+
// Private Helpers
|
|
2782
4559
|
// ==========================================================================
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
4560
|
+
#parseMCPClientRow(row) {
|
|
4561
|
+
const safeParseJSON = (val) => {
|
|
4562
|
+
if (val === null || val === void 0) return void 0;
|
|
4563
|
+
if (typeof val === "string") {
|
|
4564
|
+
try {
|
|
4565
|
+
return JSON.parse(val);
|
|
4566
|
+
} catch {
|
|
4567
|
+
return val;
|
|
4568
|
+
}
|
|
4569
|
+
}
|
|
4570
|
+
return val;
|
|
4571
|
+
};
|
|
4572
|
+
return {
|
|
4573
|
+
id: row.id,
|
|
4574
|
+
status: row.status ?? "draft",
|
|
4575
|
+
activeVersionId: row.activeVersionId ?? void 0,
|
|
4576
|
+
authorId: row.authorId ?? void 0,
|
|
4577
|
+
metadata: safeParseJSON(row.metadata),
|
|
4578
|
+
createdAt: new Date(row.createdAt),
|
|
4579
|
+
updatedAt: new Date(row.updatedAt)
|
|
4580
|
+
};
|
|
2794
4581
|
}
|
|
2795
|
-
parseVersionRow(row) {
|
|
4582
|
+
#parseVersionRow(row) {
|
|
4583
|
+
const safeParseJSON = (val) => {
|
|
4584
|
+
if (val === null || val === void 0) return void 0;
|
|
4585
|
+
if (typeof val === "string") {
|
|
4586
|
+
try {
|
|
4587
|
+
return JSON.parse(val);
|
|
4588
|
+
} catch {
|
|
4589
|
+
return val;
|
|
4590
|
+
}
|
|
4591
|
+
}
|
|
4592
|
+
return val;
|
|
4593
|
+
};
|
|
2796
4594
|
return {
|
|
2797
4595
|
id: row.id,
|
|
2798
|
-
|
|
2799
|
-
versionNumber: row.versionNumber,
|
|
4596
|
+
mcpClientId: row.mcpClientId,
|
|
4597
|
+
versionNumber: Number(row.versionNumber),
|
|
2800
4598
|
name: row.name,
|
|
2801
|
-
description: row.description,
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
defaultOptions: this.parseJson(row.defaultOptions, "defaultOptions"),
|
|
2806
|
-
workflows: this.parseJson(row.workflows, "workflows"),
|
|
2807
|
-
agents: this.parseJson(row.agents, "agents"),
|
|
2808
|
-
integrationTools: this.parseJson(row.integrationTools, "integrationTools"),
|
|
2809
|
-
inputProcessors: this.parseJson(row.inputProcessors, "inputProcessors"),
|
|
2810
|
-
outputProcessors: this.parseJson(row.outputProcessors, "outputProcessors"),
|
|
2811
|
-
memory: this.parseJson(row.memory, "memory"),
|
|
2812
|
-
scorers: this.parseJson(row.scorers, "scorers"),
|
|
2813
|
-
changedFields: this.parseJson(row.changedFields, "changedFields"),
|
|
2814
|
-
changeMessage: row.changeMessage,
|
|
4599
|
+
description: row.description ?? void 0,
|
|
4600
|
+
servers: safeParseJSON(row.servers),
|
|
4601
|
+
changedFields: safeParseJSON(row.changedFields),
|
|
4602
|
+
changeMessage: row.changeMessage ?? void 0,
|
|
2815
4603
|
createdAt: new Date(row.createdAt)
|
|
2816
4604
|
};
|
|
2817
4605
|
}
|
|
@@ -5142,7 +6930,7 @@ var ObservabilityLibSQL = class extends ObservabilityStorage {
|
|
|
5142
6930
|
}
|
|
5143
6931
|
}
|
|
5144
6932
|
};
|
|
5145
|
-
var
|
|
6933
|
+
var SNAPSHOT_FIELDS3 = ["name", "description", "content", "rules"];
|
|
5146
6934
|
var PromptBlocksLibSQL = class extends PromptBlocksStorage {
|
|
5147
6935
|
#db;
|
|
5148
6936
|
#client;
|
|
@@ -5241,7 +7029,7 @@ var PromptBlocksLibSQL = class extends PromptBlocksStorage {
|
|
|
5241
7029
|
throw new Error(`Prompt block with id ${id} not found`);
|
|
5242
7030
|
}
|
|
5243
7031
|
const { authorId, activeVersionId, metadata, status, ...configFields } = updates;
|
|
5244
|
-
const configFieldNames =
|
|
7032
|
+
const configFieldNames = SNAPSHOT_FIELDS3;
|
|
5245
7033
|
const hasConfigUpdate = configFieldNames.some((field) => field in configFields);
|
|
5246
7034
|
const updateData = {
|
|
5247
7035
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -5649,7 +7437,7 @@ var PromptBlocksLibSQL = class extends PromptBlocksStorage {
|
|
|
5649
7437
|
};
|
|
5650
7438
|
}
|
|
5651
7439
|
};
|
|
5652
|
-
var
|
|
7440
|
+
var SNAPSHOT_FIELDS4 = [
|
|
5653
7441
|
"name",
|
|
5654
7442
|
"description",
|
|
5655
7443
|
"type",
|
|
@@ -5760,7 +7548,7 @@ var ScorerDefinitionsLibSQL = class extends ScorerDefinitionsStorage {
|
|
|
5760
7548
|
throw new Error(`Scorer definition with id ${id} not found`);
|
|
5761
7549
|
}
|
|
5762
7550
|
const { authorId, activeVersionId, metadata, status, ...configFields } = updates;
|
|
5763
|
-
const configFieldNames =
|
|
7551
|
+
const configFieldNames = SNAPSHOT_FIELDS4;
|
|
5764
7552
|
const hasConfigUpdate = configFieldNames.some((field) => field in configFields);
|
|
5765
7553
|
const updateData = {
|
|
5766
7554
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -6828,16 +8616,22 @@ var LibSQLStore = class extends MastraCompositeStore {
|
|
|
6828
8616
|
const memory = new MemoryLibSQL(domainConfig);
|
|
6829
8617
|
const observability = new ObservabilityLibSQL(domainConfig);
|
|
6830
8618
|
const agents = new AgentsLibSQL(domainConfig);
|
|
8619
|
+
const datasets = new DatasetsLibSQL(domainConfig);
|
|
8620
|
+
const experiments = new ExperimentsLibSQL(domainConfig);
|
|
6831
8621
|
const promptBlocks = new PromptBlocksLibSQL(domainConfig);
|
|
6832
8622
|
const scorerDefinitions = new ScorerDefinitionsLibSQL(domainConfig);
|
|
8623
|
+
const mcpClients = new MCPClientsLibSQL(domainConfig);
|
|
6833
8624
|
this.stores = {
|
|
6834
8625
|
scores,
|
|
6835
8626
|
workflows,
|
|
6836
8627
|
memory,
|
|
6837
8628
|
observability,
|
|
6838
8629
|
agents,
|
|
8630
|
+
datasets,
|
|
8631
|
+
experiments,
|
|
6839
8632
|
promptBlocks,
|
|
6840
|
-
scorerDefinitions
|
|
8633
|
+
scorerDefinitions,
|
|
8634
|
+
mcpClients
|
|
6841
8635
|
};
|
|
6842
8636
|
}
|
|
6843
8637
|
};
|
|
@@ -6941,6 +8735,6 @@ Example Complex Query:
|
|
|
6941
8735
|
]
|
|
6942
8736
|
}`;
|
|
6943
8737
|
|
|
6944
|
-
export { AgentsLibSQL, LibSQLStore as DefaultStorage, LIBSQL_PROMPT, LibSQLStore, LibSQLVector, MemoryLibSQL, ObservabilityLibSQL, PromptBlocksLibSQL, ScorerDefinitionsLibSQL, ScoresLibSQL, WorkflowsLibSQL };
|
|
8738
|
+
export { AgentsLibSQL, DatasetsLibSQL, LibSQLStore as DefaultStorage, ExperimentsLibSQL, LIBSQL_PROMPT, LibSQLStore, LibSQLVector, MCPClientsLibSQL, MemoryLibSQL, ObservabilityLibSQL, PromptBlocksLibSQL, ScorerDefinitionsLibSQL, ScoresLibSQL, WorkflowsLibSQL };
|
|
6945
8739
|
//# sourceMappingURL=index.js.map
|
|
6946
8740
|
//# sourceMappingURL=index.js.map
|