@mastra/pg 0.3.1-alpha.3 → 0.3.1-alpha.5

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/dist/index.js CHANGED
@@ -1408,70 +1408,231 @@ var PostgresStore = class extends MastraStorage {
1408
1408
  throw error;
1409
1409
  }
1410
1410
  }
1411
+ async hasColumn(table, column) {
1412
+ const schema = this.schema || "public";
1413
+ const result = await this.db.oneOrNone(
1414
+ `SELECT 1 FROM information_schema.columns WHERE table_schema = $1 AND table_name = $2 AND (column_name = $3 OR column_name = $4)`,
1415
+ [schema, table, column, column.toLowerCase()]
1416
+ );
1417
+ return !!result;
1418
+ }
1419
+ parseWorkflowRun(row) {
1420
+ let parsedSnapshot = row.snapshot;
1421
+ if (typeof parsedSnapshot === "string") {
1422
+ try {
1423
+ parsedSnapshot = JSON.parse(row.snapshot);
1424
+ } catch (e) {
1425
+ console.warn(`Failed to parse snapshot for workflow ${row.workflow_name}: ${e}`);
1426
+ }
1427
+ }
1428
+ return {
1429
+ workflowName: row.workflow_name,
1430
+ runId: row.run_id,
1431
+ snapshot: parsedSnapshot,
1432
+ createdAt: row.createdAt,
1433
+ updatedAt: row.updatedAt,
1434
+ resourceId: row.resourceId
1435
+ };
1436
+ }
1411
1437
  async getWorkflowRuns({
1412
1438
  workflowName,
1413
1439
  fromDate,
1414
1440
  toDate,
1415
1441
  limit,
1416
- offset
1442
+ offset,
1443
+ resourceId
1417
1444
  } = {}) {
1418
- const conditions = [];
1419
- const values = [];
1420
- let paramIndex = 1;
1421
- if (workflowName) {
1422
- conditions.push(`workflow_name = $${paramIndex}`);
1423
- values.push(workflowName);
1424
- paramIndex++;
1425
- }
1426
- if (fromDate) {
1427
- conditions.push(`"createdAt" >= $${paramIndex}`);
1428
- values.push(fromDate);
1429
- paramIndex++;
1430
- }
1431
- if (toDate) {
1432
- conditions.push(`"createdAt" <= $${paramIndex}`);
1433
- values.push(toDate);
1434
- paramIndex++;
1435
- }
1436
- const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
1437
- let total = 0;
1438
- if (limit !== void 0 && offset !== void 0) {
1439
- const countResult = await this.db.one(
1440
- `SELECT COUNT(*) as count FROM ${this.getTableName(TABLE_WORKFLOW_SNAPSHOT)} ${whereClause}`,
1441
- values
1442
- );
1443
- total = Number(countResult.count);
1444
- }
1445
- const query = `
1445
+ try {
1446
+ const conditions = [];
1447
+ const values = [];
1448
+ let paramIndex = 1;
1449
+ if (workflowName) {
1450
+ conditions.push(`workflow_name = $${paramIndex}`);
1451
+ values.push(workflowName);
1452
+ paramIndex++;
1453
+ }
1454
+ if (resourceId) {
1455
+ const hasResourceId = await this.hasColumn(TABLE_WORKFLOW_SNAPSHOT, "resourceId");
1456
+ if (hasResourceId) {
1457
+ conditions.push(`"resourceId" = $${paramIndex}`);
1458
+ values.push(resourceId);
1459
+ paramIndex++;
1460
+ } else {
1461
+ console.warn(`[${TABLE_WORKFLOW_SNAPSHOT}] resourceId column not found. Skipping resourceId filter.`);
1462
+ }
1463
+ }
1464
+ if (fromDate) {
1465
+ conditions.push(`"createdAt" >= $${paramIndex}`);
1466
+ values.push(fromDate);
1467
+ paramIndex++;
1468
+ }
1469
+ if (toDate) {
1470
+ conditions.push(`"createdAt" <= $${paramIndex}`);
1471
+ values.push(toDate);
1472
+ paramIndex++;
1473
+ }
1474
+ const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
1475
+ let total = 0;
1476
+ if (limit !== void 0 && offset !== void 0) {
1477
+ const countResult = await this.db.one(
1478
+ `SELECT COUNT(*) as count FROM ${this.getTableName(TABLE_WORKFLOW_SNAPSHOT)} ${whereClause}`,
1479
+ values
1480
+ );
1481
+ total = Number(countResult.count);
1482
+ }
1483
+ const query = `
1446
1484
  SELECT * FROM ${this.getTableName(TABLE_WORKFLOW_SNAPSHOT)}
1447
1485
  ${whereClause}
1448
1486
  ORDER BY "createdAt" DESC
1449
1487
  ${limit !== void 0 && offset !== void 0 ? ` LIMIT $${paramIndex} OFFSET $${paramIndex + 1}` : ""}
1450
1488
  `;
1451
- const queryValues = limit !== void 0 && offset !== void 0 ? [...values, limit, offset] : values;
1452
- const result = await this.db.manyOrNone(query, queryValues);
1453
- const runs = (result || []).map((row) => {
1454
- let parsedSnapshot = row.snapshot;
1455
- if (typeof parsedSnapshot === "string") {
1456
- try {
1457
- parsedSnapshot = JSON.parse(row.snapshot);
1458
- } catch (e) {
1459
- console.warn(`Failed to parse snapshot for workflow ${row.workflow_name}: ${e}`);
1460
- }
1489
+ const queryValues = limit !== void 0 && offset !== void 0 ? [...values, limit, offset] : values;
1490
+ const result = await this.db.manyOrNone(query, queryValues);
1491
+ const runs = (result || []).map((row) => {
1492
+ return this.parseWorkflowRun(row);
1493
+ });
1494
+ return { runs, total: total || runs.length };
1495
+ } catch (error) {
1496
+ console.error("Error getting workflow runs:", error);
1497
+ throw error;
1498
+ }
1499
+ }
1500
+ async getWorkflowRunById({
1501
+ runId,
1502
+ workflowName
1503
+ }) {
1504
+ try {
1505
+ const conditions = [];
1506
+ const values = [];
1507
+ let paramIndex = 1;
1508
+ if (runId) {
1509
+ conditions.push(`run_id = $${paramIndex}`);
1510
+ values.push(runId);
1511
+ paramIndex++;
1461
1512
  }
1462
- return {
1463
- workflowName: row.workflow_name,
1464
- runId: row.run_id,
1465
- snapshot: parsedSnapshot,
1466
- createdAt: row.createdAt,
1467
- updatedAt: row.updatedAt
1468
- };
1469
- });
1470
- return { runs, total: total || runs.length };
1513
+ if (workflowName) {
1514
+ conditions.push(`workflow_name = $${paramIndex}`);
1515
+ values.push(workflowName);
1516
+ paramIndex++;
1517
+ }
1518
+ const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
1519
+ const query = `
1520
+ SELECT * FROM ${this.getTableName(TABLE_WORKFLOW_SNAPSHOT)}
1521
+ ${whereClause}
1522
+ `;
1523
+ const queryValues = values;
1524
+ const result = await this.db.oneOrNone(query, queryValues);
1525
+ if (!result) {
1526
+ return null;
1527
+ }
1528
+ return this.parseWorkflowRun(result);
1529
+ } catch (error) {
1530
+ console.error("Error getting workflow run by ID:", error);
1531
+ throw error;
1532
+ }
1471
1533
  }
1472
1534
  async close() {
1473
1535
  this.pgp.end();
1474
1536
  }
1475
1537
  };
1476
1538
 
1477
- export { PgVector, PostgresStore };
1539
+ // src/vector/prompt.ts
1540
+ var PGVECTOR_PROMPT = `When querying PG Vector, you can ONLY use the operators listed below. Any other operators will be rejected.
1541
+ Important: Don't explain how to construct the filter - use the specified operators and fields to search the content and return relevant results.
1542
+ If a user tries to give an explicit operator that is not supported, reject the filter entirely and let them know that the operator is not supported.
1543
+
1544
+ Basic Comparison Operators:
1545
+ - $eq: Exact match (default when using field: value)
1546
+ Example: { "category": "electronics" }
1547
+ - $ne: Not equal
1548
+ Example: { "category": { "$ne": "electronics" } }
1549
+ - $gt: Greater than
1550
+ Example: { "price": { "$gt": 100 } }
1551
+ - $gte: Greater than or equal
1552
+ Example: { "price": { "$gte": 100 } }
1553
+ - $lt: Less than
1554
+ Example: { "price": { "$lt": 100 } }
1555
+ - $lte: Less than or equal
1556
+ Example: { "price": { "$lte": 100 } }
1557
+
1558
+ Array Operators:
1559
+ - $in: Match any value in array
1560
+ Example: { "category": { "$in": ["electronics", "books"] } }
1561
+ - $nin: Does not match any value in array
1562
+ Example: { "category": { "$nin": ["electronics", "books"] } }
1563
+ - $all: Match all values in array
1564
+ Example: { "tags": { "$all": ["premium", "sale"] } }
1565
+ - $elemMatch: Match array elements that meet all specified conditions
1566
+ Example: { "items": { "$elemMatch": { "price": { "$gt": 100 } } } }
1567
+ - $contains: Check if array contains value
1568
+ Example: { "tags": { "$contains": "premium" } }
1569
+
1570
+ Logical Operators:
1571
+ - $and: Logical AND (implicit when using multiple conditions)
1572
+ Example: { "$and": [{ "price": { "$gt": 100 } }, { "category": "electronics" }] }
1573
+ - $or: Logical OR
1574
+ Example: { "$or": [{ "price": { "$lt": 50 } }, { "category": "books" }] }
1575
+ - $not: Logical NOT
1576
+ Example: { "$not": { "category": "electronics" } }
1577
+ - $nor: Logical NOR
1578
+ Example: { "$nor": [{ "price": { "$lt": 50 } }, { "category": "books" }] }
1579
+
1580
+ Element Operators:
1581
+ - $exists: Check if field exists
1582
+ Example: { "rating": { "$exists": true } }
1583
+
1584
+ Special Operators:
1585
+ - $size: Array length check
1586
+ Example: { "tags": { "$size": 2 } }
1587
+
1588
+ Restrictions:
1589
+ - Regex patterns are not supported
1590
+ - Direct RegExp patterns will throw an error
1591
+ - Nested fields are supported using dot notation
1592
+ - Multiple conditions on the same field are supported with both implicit and explicit $and
1593
+ - Array operations work on array fields only
1594
+ - Basic operators handle array values as JSON strings
1595
+ - Empty arrays in conditions are handled gracefully
1596
+ - Only logical operators ($and, $or, $not, $nor) can be used at the top level
1597
+ - All other operators must be used within a field condition
1598
+ Valid: { "field": { "$gt": 100 } }
1599
+ Valid: { "$and": [...] }
1600
+ Invalid: { "$gt": 100 }
1601
+ Invalid: { "$contains": "value" }
1602
+ - Logical operators must contain field conditions, not direct operators
1603
+ Valid: { "$and": [{ "field": { "$gt": 100 } }] }
1604
+ Invalid: { "$and": [{ "$gt": 100 }] }
1605
+ - $not operator:
1606
+ - Must be an object
1607
+ - Cannot be empty
1608
+ - Can be used at field level or top level
1609
+ - Valid: { "$not": { "field": "value" } }
1610
+ - Valid: { "field": { "$not": { "$eq": "value" } } }
1611
+ - Other logical operators ($and, $or, $nor):
1612
+ - Can only be used at top level or nested within other logical operators
1613
+ - Can not be used on a field level, or be nested inside a field
1614
+ - Can not be used inside an operator
1615
+ - Valid: { "$and": [{ "field": { "$gt": 100 } }] }
1616
+ - Valid: { "$or": [{ "$and": [{ "field": { "$gt": 100 } }] }] }
1617
+ - Invalid: { "field": { "$and": [{ "$gt": 100 }] } }
1618
+ - Invalid: { "field": { "$or": [{ "$gt": 100 }] } }
1619
+ - Invalid: { "field": { "$gt": { "$and": [{...}] } } }
1620
+ - $elemMatch requires an object with conditions
1621
+ Valid: { "array": { "$elemMatch": { "field": "value" } } }
1622
+ Invalid: { "array": { "$elemMatch": "value" } }
1623
+
1624
+ Example Complex Query:
1625
+ {
1626
+ "$and": [
1627
+ { "category": { "$in": ["electronics", "computers"] } },
1628
+ { "price": { "$gte": 100, "$lte": 1000 } },
1629
+ { "tags": { "$all": ["premium"] } },
1630
+ { "rating": { "$exists": true, "$gt": 4 } },
1631
+ { "$or": [
1632
+ { "stock": { "$gt": 0 } },
1633
+ { "preorder": true }
1634
+ ]}
1635
+ ]
1636
+ }`;
1637
+
1638
+ export { PGVECTOR_PROMPT, PgVector, PostgresStore };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mastra/pg",
3
- "version": "0.3.1-alpha.3",
3
+ "version": "0.3.1-alpha.5",
4
4
  "description": "Postgres provider for Mastra - includes both vector and db storage capabilities",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -24,16 +24,16 @@
24
24
  "pg": "^8.13.3",
25
25
  "pg-promise": "^11.11.0",
26
26
  "xxhash-wasm": "^1.1.0",
27
- "@mastra/core": "^0.9.1-alpha.3"
27
+ "@mastra/core": "^0.9.1-alpha.5"
28
28
  },
29
29
  "devDependencies": {
30
- "@microsoft/api-extractor": "^7.52.1",
30
+ "@microsoft/api-extractor": "^7.52.5",
31
31
  "@types/node": "^20.17.27",
32
32
  "@types/pg": "^8.11.11",
33
33
  "eslint": "^9.23.0",
34
34
  "tsup": "^8.4.0",
35
35
  "typescript": "^5.8.2",
36
- "vitest": "^3.0.9",
36
+ "vitest": "^3.1.2",
37
37
  "@internal/lint": "0.0.2"
38
38
  },
39
39
  "scripts": {
package/src/index.ts CHANGED
@@ -1,2 +1,3 @@
1
1
  export * from './vector';
2
2
  export * from './storage';
3
+ export { PGVECTOR_PROMPT } from './vector/prompt';