@agentforge/tools 0.16.40 → 0.16.42

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
@@ -6034,156 +6034,7 @@ async function withTransaction(manager, operation, options) {
6034
6034
  // src/data/relational/schema/validation.ts
6035
6035
  var VALID_TABLE_FILTER_PATTERN = /^[a-zA-Z_][a-zA-Z0-9_]*(\.[a-zA-Z_][a-zA-Z0-9_]*)?$/;
6036
6036
 
6037
- // src/data/relational/schema/schema-inspector.ts
6038
- var logger13 = createLogger("agentforge:tools:data:relational:schema-inspector");
6039
- var DEFAULT_CACHE_TTL_MS = 6e4;
6040
- var schemaCache = /* @__PURE__ */ new Map();
6041
- var POSTGRES_TABLES_QUERY = `
6042
- SELECT
6043
- table_schema AS schema_name,
6044
- table_name
6045
- FROM information_schema.tables
6046
- WHERE table_type = 'BASE TABLE'
6047
- AND table_schema NOT IN ('pg_catalog', 'information_schema')
6048
- ORDER BY table_schema, table_name
6049
- `;
6050
- var POSTGRES_COLUMNS_QUERY = `
6051
- SELECT
6052
- table_schema AS schema_name,
6053
- table_name,
6054
- column_name,
6055
- data_type,
6056
- is_nullable,
6057
- column_default
6058
- FROM information_schema.columns
6059
- WHERE table_schema NOT IN ('pg_catalog', 'information_schema')
6060
- ORDER BY table_schema, table_name, ordinal_position
6061
- `;
6062
- var POSTGRES_PRIMARY_KEYS_QUERY = `
6063
- SELECT
6064
- kcu.table_schema AS schema_name,
6065
- kcu.table_name,
6066
- kcu.column_name,
6067
- kcu.ordinal_position AS key_position
6068
- FROM information_schema.table_constraints tc
6069
- JOIN information_schema.key_column_usage kcu
6070
- ON tc.constraint_name = kcu.constraint_name
6071
- AND tc.table_schema = kcu.table_schema
6072
- AND tc.table_name = kcu.table_name
6073
- WHERE tc.constraint_type = 'PRIMARY KEY'
6074
- ORDER BY kcu.table_schema, kcu.table_name, kcu.ordinal_position
6075
- `;
6076
- var POSTGRES_FOREIGN_KEYS_QUERY = `
6077
- SELECT
6078
- tc.table_schema AS schema_name,
6079
- tc.table_name,
6080
- tc.constraint_name,
6081
- kcu.column_name,
6082
- ccu.table_schema AS referenced_schema_name,
6083
- ccu.table_name AS referenced_table_name,
6084
- ccu.column_name AS referenced_column_name
6085
- FROM information_schema.table_constraints tc
6086
- JOIN information_schema.key_column_usage kcu
6087
- ON tc.constraint_name = kcu.constraint_name
6088
- AND tc.table_schema = kcu.table_schema
6089
- JOIN information_schema.constraint_column_usage ccu
6090
- ON ccu.constraint_name = tc.constraint_name
6091
- AND ccu.table_schema = tc.table_schema
6092
- WHERE tc.constraint_type = 'FOREIGN KEY'
6093
- ORDER BY tc.table_schema, tc.table_name, tc.constraint_name, kcu.ordinal_position
6094
- `;
6095
- var POSTGRES_INDEXES_QUERY = `
6096
- SELECT
6097
- ns.nspname AS schema_name,
6098
- tbl.relname AS table_name,
6099
- idx.relname AS index_name,
6100
- ix.indisunique AS is_unique,
6101
- att.attname AS column_name,
6102
- ord.ordinality AS column_position
6103
- FROM pg_class tbl
6104
- JOIN pg_namespace ns
6105
- ON ns.oid = tbl.relnamespace
6106
- JOIN pg_index ix
6107
- ON ix.indrelid = tbl.oid
6108
- JOIN pg_class idx
6109
- ON idx.oid = ix.indexrelid
6110
- JOIN LATERAL unnest(ix.indkey) WITH ORDINALITY AS ord(attnum, ordinality)
6111
- ON true
6112
- JOIN pg_attribute att
6113
- ON att.attrelid = tbl.oid
6114
- AND att.attnum = ord.attnum
6115
- WHERE tbl.relkind = 'r'
6116
- AND ns.nspname NOT IN ('pg_catalog', 'information_schema')
6117
- AND ix.indisprimary = false
6118
- ORDER BY ns.nspname, tbl.relname, idx.relname, ord.ordinality
6119
- `;
6120
- var MYSQL_TABLES_QUERY = `
6121
- SELECT
6122
- table_schema AS schema_name,
6123
- table_name AS table_name
6124
- FROM information_schema.tables
6125
- WHERE table_type = 'BASE TABLE'
6126
- AND table_schema = DATABASE()
6127
- ORDER BY table_name
6128
- `;
6129
- var MYSQL_COLUMNS_QUERY = `
6130
- SELECT
6131
- table_schema AS schema_name,
6132
- table_name AS table_name,
6133
- column_name AS column_name,
6134
- column_type AS data_type,
6135
- is_nullable AS is_nullable,
6136
- column_default AS column_default
6137
- FROM information_schema.columns
6138
- WHERE table_schema = DATABASE()
6139
- ORDER BY table_name, ordinal_position
6140
- `;
6141
- var MYSQL_PRIMARY_KEYS_QUERY = `
6142
- SELECT
6143
- table_schema AS schema_name,
6144
- table_name AS table_name,
6145
- column_name AS column_name,
6146
- ordinal_position AS key_position
6147
- FROM information_schema.key_column_usage
6148
- WHERE table_schema = DATABASE()
6149
- AND constraint_name = 'PRIMARY'
6150
- ORDER BY table_name, ordinal_position
6151
- `;
6152
- var MYSQL_FOREIGN_KEYS_QUERY = `
6153
- SELECT
6154
- table_schema AS schema_name,
6155
- table_name AS table_name,
6156
- constraint_name AS constraint_name,
6157
- column_name AS column_name,
6158
- referenced_table_schema AS referenced_schema_name,
6159
- referenced_table_name AS referenced_table_name,
6160
- referenced_column_name AS referenced_column_name
6161
- FROM information_schema.key_column_usage
6162
- WHERE table_schema = DATABASE()
6163
- AND referenced_table_name IS NOT NULL
6164
- ORDER BY table_name, constraint_name, ordinal_position
6165
- `;
6166
- var MYSQL_INDEXES_QUERY = `
6167
- SELECT
6168
- table_schema AS schema_name,
6169
- table_name AS table_name,
6170
- index_name AS index_name,
6171
- non_unique AS non_unique,
6172
- column_name AS column_name,
6173
- seq_in_index AS seq_in_index
6174
- FROM information_schema.statistics
6175
- WHERE table_schema = DATABASE()
6176
- AND index_name <> 'PRIMARY'
6177
- ORDER BY table_name, index_name, seq_in_index
6178
- `;
6179
- var SQLITE_TABLES_QUERY = `
6180
- SELECT
6181
- name AS table_name
6182
- FROM sqlite_master
6183
- WHERE type = 'table'
6184
- AND name NOT LIKE 'sqlite_%'
6185
- ORDER BY name
6186
- `;
6037
+ // src/data/relational/schema/schema-inspector-shared.ts
6187
6038
  function normalizeFilterName(value) {
6188
6039
  return value.trim().toLowerCase();
6189
6040
  }
@@ -6279,14 +6130,391 @@ function escapeSqliteStringLiteral(value) {
6279
6130
  function sortColumnsByPosition(columnsByPosition) {
6280
6131
  return columnsByPosition.sort((a, b) => a.position - b.position).map((entry) => entry.column);
6281
6132
  }
6133
+ function createTableMap(refs) {
6134
+ const tableMap2 = /* @__PURE__ */ new Map();
6135
+ for (const ref of refs) {
6136
+ const key = buildTableKey(ref.tableName, ref.schemaName);
6137
+ tableMap2.set(key, {
6138
+ name: ref.tableName,
6139
+ schema: ref.schemaName,
6140
+ columns: [],
6141
+ primaryKey: [],
6142
+ foreignKeys: [],
6143
+ indexes: []
6144
+ });
6145
+ }
6146
+ return tableMap2;
6147
+ }
6148
+ function getTableFromRow(tableMap2, row, tableField, schemaField) {
6149
+ const tableName = toStringValue(row[tableField]);
6150
+ const schemaName = toOptionalStringValue(row[schemaField]) ;
6151
+ const key = buildTableKey(tableName, schemaName);
6152
+ return tableMap2.get(key);
6153
+ }
6154
+ function createColumnSchema(row, fields) {
6155
+ return {
6156
+ name: toStringValue(row[fields?.name ?? "column_name"]),
6157
+ type: toStringValue(row[fields?.type ?? "data_type"]),
6158
+ isNullable: toBooleanValue(row[fields?.nullable ?? "is_nullable"]),
6159
+ defaultValue: row[fields?.defaultValue ?? "column_default"] ?? null,
6160
+ isPrimaryKey: fields?.primaryKey ?? false
6161
+ };
6162
+ }
6163
+ function applyPrimaryKeyColumn(table, columnName) {
6164
+ table.primaryKey.push(columnName);
6165
+ const column = table.columns.find((entry) => entry.name === columnName);
6166
+ if (column) {
6167
+ column.isPrimaryKey = true;
6168
+ }
6169
+ }
6170
+ function applyIndexRows(tableMap2, rows, tableField, schemaField, config) {
6171
+ const grouped = /* @__PURE__ */ new Map();
6172
+ for (const row of rows) {
6173
+ const table = getTableFromRow(tableMap2, row, tableField, schemaField);
6174
+ if (!table) {
6175
+ continue;
6176
+ }
6177
+ const indexName = toStringValue(row[config.indexNameField]);
6178
+ if (!indexName) {
6179
+ continue;
6180
+ }
6181
+ const groupKey = `${table.schema ?? ""}.${table.name}.${indexName}`;
6182
+ const entry = grouped.get(groupKey) ?? {
6183
+ table,
6184
+ indexName,
6185
+ isUnique: config.uniqueResolver(row),
6186
+ columnsByPosition: []
6187
+ };
6188
+ entry.columnsByPosition.push({
6189
+ position: toNumberValue(row[config.positionField]),
6190
+ column: toStringValue(row[config.columnField])
6191
+ });
6192
+ grouped.set(groupKey, entry);
6193
+ }
6194
+ for (const entry of grouped.values()) {
6195
+ const index = {
6196
+ name: entry.indexName,
6197
+ isUnique: entry.isUnique,
6198
+ columns: sortColumnsByPosition(entry.columnsByPosition)
6199
+ };
6200
+ entry.table.indexes.push(index);
6201
+ }
6202
+ }
6203
+
6204
+ // src/data/relational/schema/schema-inspector-mysql.ts
6205
+ var MYSQL_TABLES_QUERY = `
6206
+ SELECT
6207
+ table_schema AS schema_name,
6208
+ table_name AS table_name
6209
+ FROM information_schema.tables
6210
+ WHERE table_type = 'BASE TABLE'
6211
+ AND table_schema = DATABASE()
6212
+ ORDER BY table_name
6213
+ `;
6214
+ var MYSQL_COLUMNS_QUERY = `
6215
+ SELECT
6216
+ table_schema AS schema_name,
6217
+ table_name AS table_name,
6218
+ column_name AS column_name,
6219
+ column_type AS data_type,
6220
+ is_nullable AS is_nullable,
6221
+ column_default AS column_default
6222
+ FROM information_schema.columns
6223
+ WHERE table_schema = DATABASE()
6224
+ ORDER BY table_name, ordinal_position
6225
+ `;
6226
+ var MYSQL_PRIMARY_KEYS_QUERY = `
6227
+ SELECT
6228
+ table_schema AS schema_name,
6229
+ table_name AS table_name,
6230
+ column_name AS column_name,
6231
+ ordinal_position AS key_position
6232
+ FROM information_schema.key_column_usage
6233
+ WHERE table_schema = DATABASE()
6234
+ AND constraint_name = 'PRIMARY'
6235
+ ORDER BY table_name, ordinal_position
6236
+ `;
6237
+ var MYSQL_FOREIGN_KEYS_QUERY = `
6238
+ SELECT
6239
+ table_schema AS schema_name,
6240
+ table_name AS table_name,
6241
+ constraint_name AS constraint_name,
6242
+ column_name AS column_name,
6243
+ referenced_table_schema AS referenced_schema_name,
6244
+ referenced_table_name AS referenced_table_name,
6245
+ referenced_column_name AS referenced_column_name
6246
+ FROM information_schema.key_column_usage
6247
+ WHERE table_schema = DATABASE()
6248
+ AND referenced_table_name IS NOT NULL
6249
+ ORDER BY table_name, constraint_name, ordinal_position
6250
+ `;
6251
+ var MYSQL_INDEXES_QUERY = `
6252
+ SELECT
6253
+ table_schema AS schema_name,
6254
+ table_name AS table_name,
6255
+ index_name AS index_name,
6256
+ non_unique AS non_unique,
6257
+ column_name AS column_name,
6258
+ seq_in_index AS seq_in_index
6259
+ FROM information_schema.statistics
6260
+ WHERE table_schema = DATABASE()
6261
+ AND index_name <> 'PRIMARY'
6262
+ ORDER BY table_name, index_name, seq_in_index
6263
+ `;
6264
+ async function inspectMySQL(runQueryRows) {
6265
+ const tableRows = await runQueryRows(MYSQL_TABLES_QUERY);
6266
+ const tableMap2 = createTableMap(
6267
+ tableRows.map((row) => ({
6268
+ schemaName: toOptionalStringValue(row.schema_name),
6269
+ tableName: toStringValue(row.table_name)
6270
+ }))
6271
+ );
6272
+ const columnsRows = await runQueryRows(MYSQL_COLUMNS_QUERY);
6273
+ for (const row of columnsRows) {
6274
+ const table = getTableFromRow(tableMap2, row, "table_name", "schema_name");
6275
+ if (!table) {
6276
+ continue;
6277
+ }
6278
+ table.columns.push(createColumnSchema(row));
6279
+ }
6280
+ const primaryKeyRows = await runQueryRows(MYSQL_PRIMARY_KEYS_QUERY);
6281
+ for (const row of primaryKeyRows) {
6282
+ const table = getTableFromRow(tableMap2, row, "table_name", "schema_name");
6283
+ if (!table) {
6284
+ continue;
6285
+ }
6286
+ applyPrimaryKeyColumn(table, toStringValue(row.column_name));
6287
+ }
6288
+ const foreignKeyRows = await runQueryRows(MYSQL_FOREIGN_KEYS_QUERY);
6289
+ for (const row of foreignKeyRows) {
6290
+ const table = getTableFromRow(tableMap2, row, "table_name", "schema_name");
6291
+ if (!table) {
6292
+ continue;
6293
+ }
6294
+ const foreignKey = {
6295
+ name: toOptionalStringValue(row.constraint_name),
6296
+ column: toStringValue(row.column_name),
6297
+ referencedSchema: toOptionalStringValue(row.referenced_schema_name),
6298
+ referencedTable: toStringValue(row.referenced_table_name),
6299
+ referencedColumn: toStringValue(row.referenced_column_name)
6300
+ };
6301
+ table.foreignKeys.push(foreignKey);
6302
+ }
6303
+ const indexRows = await runQueryRows(MYSQL_INDEXES_QUERY);
6304
+ applyIndexRows(tableMap2, indexRows, "table_name", "schema_name", {
6305
+ indexNameField: "index_name",
6306
+ columnField: "column_name",
6307
+ positionField: "seq_in_index",
6308
+ uniqueResolver: (row) => !toBooleanValue(row.non_unique)
6309
+ });
6310
+ return Array.from(tableMap2.values());
6311
+ }
6312
+
6313
+ // src/data/relational/schema/schema-inspector-postgresql.ts
6314
+ var POSTGRES_TABLES_QUERY = `
6315
+ SELECT
6316
+ table_schema AS schema_name,
6317
+ table_name
6318
+ FROM information_schema.tables
6319
+ WHERE table_type = 'BASE TABLE'
6320
+ AND table_schema NOT IN ('pg_catalog', 'information_schema')
6321
+ ORDER BY table_schema, table_name
6322
+ `;
6323
+ var POSTGRES_COLUMNS_QUERY = `
6324
+ SELECT
6325
+ table_schema AS schema_name,
6326
+ table_name,
6327
+ column_name,
6328
+ data_type,
6329
+ is_nullable,
6330
+ column_default
6331
+ FROM information_schema.columns
6332
+ WHERE table_schema NOT IN ('pg_catalog', 'information_schema')
6333
+ ORDER BY table_schema, table_name, ordinal_position
6334
+ `;
6335
+ var POSTGRES_PRIMARY_KEYS_QUERY = `
6336
+ SELECT
6337
+ kcu.table_schema AS schema_name,
6338
+ kcu.table_name,
6339
+ kcu.column_name,
6340
+ kcu.ordinal_position AS key_position
6341
+ FROM information_schema.table_constraints tc
6342
+ JOIN information_schema.key_column_usage kcu
6343
+ ON tc.constraint_name = kcu.constraint_name
6344
+ AND tc.table_schema = kcu.table_schema
6345
+ AND tc.table_name = kcu.table_name
6346
+ WHERE tc.constraint_type = 'PRIMARY KEY'
6347
+ ORDER BY kcu.table_schema, kcu.table_name, kcu.ordinal_position
6348
+ `;
6349
+ var POSTGRES_FOREIGN_KEYS_QUERY = `
6350
+ SELECT
6351
+ tc.table_schema AS schema_name,
6352
+ tc.table_name,
6353
+ tc.constraint_name,
6354
+ kcu.column_name,
6355
+ ccu.table_schema AS referenced_schema_name,
6356
+ ccu.table_name AS referenced_table_name,
6357
+ ccu.column_name AS referenced_column_name
6358
+ FROM information_schema.table_constraints tc
6359
+ JOIN information_schema.key_column_usage kcu
6360
+ ON tc.constraint_name = kcu.constraint_name
6361
+ AND tc.table_schema = kcu.table_schema
6362
+ JOIN information_schema.constraint_column_usage ccu
6363
+ ON ccu.constraint_name = tc.constraint_name
6364
+ AND ccu.table_schema = tc.table_schema
6365
+ WHERE tc.constraint_type = 'FOREIGN KEY'
6366
+ ORDER BY tc.table_schema, tc.table_name, tc.constraint_name, kcu.ordinal_position
6367
+ `;
6368
+ var POSTGRES_INDEXES_QUERY = `
6369
+ SELECT
6370
+ ns.nspname AS schema_name,
6371
+ tbl.relname AS table_name,
6372
+ idx.relname AS index_name,
6373
+ ix.indisunique AS is_unique,
6374
+ att.attname AS column_name,
6375
+ ord.ordinality AS column_position
6376
+ FROM pg_class tbl
6377
+ JOIN pg_namespace ns
6378
+ ON ns.oid = tbl.relnamespace
6379
+ JOIN pg_index ix
6380
+ ON ix.indrelid = tbl.oid
6381
+ JOIN pg_class idx
6382
+ ON idx.oid = ix.indexrelid
6383
+ JOIN LATERAL unnest(ix.indkey) WITH ORDINALITY AS ord(attnum, ordinality)
6384
+ ON true
6385
+ JOIN pg_attribute att
6386
+ ON att.attrelid = tbl.oid
6387
+ AND att.attnum = ord.attnum
6388
+ WHERE tbl.relkind = 'r'
6389
+ AND ns.nspname NOT IN ('pg_catalog', 'information_schema')
6390
+ AND ix.indisprimary = false
6391
+ ORDER BY ns.nspname, tbl.relname, idx.relname, ord.ordinality
6392
+ `;
6393
+ async function inspectPostgreSQL(runQueryRows) {
6394
+ const tableRows = await runQueryRows(POSTGRES_TABLES_QUERY);
6395
+ const tableMap2 = createTableMap(
6396
+ tableRows.map((row) => ({
6397
+ schemaName: toOptionalStringValue(row.schema_name),
6398
+ tableName: toStringValue(row.table_name)
6399
+ }))
6400
+ );
6401
+ const columnsRows = await runQueryRows(POSTGRES_COLUMNS_QUERY);
6402
+ for (const row of columnsRows) {
6403
+ const table = getTableFromRow(tableMap2, row, "table_name", "schema_name");
6404
+ if (!table) {
6405
+ continue;
6406
+ }
6407
+ table.columns.push(createColumnSchema(row));
6408
+ }
6409
+ const primaryKeyRows = await runQueryRows(POSTGRES_PRIMARY_KEYS_QUERY);
6410
+ for (const row of primaryKeyRows) {
6411
+ const table = getTableFromRow(tableMap2, row, "table_name", "schema_name");
6412
+ if (!table) {
6413
+ continue;
6414
+ }
6415
+ applyPrimaryKeyColumn(table, toStringValue(row.column_name));
6416
+ }
6417
+ const foreignKeyRows = await runQueryRows(POSTGRES_FOREIGN_KEYS_QUERY);
6418
+ for (const row of foreignKeyRows) {
6419
+ const table = getTableFromRow(tableMap2, row, "table_name", "schema_name");
6420
+ if (!table) {
6421
+ continue;
6422
+ }
6423
+ const foreignKey = {
6424
+ name: toOptionalStringValue(row.constraint_name),
6425
+ column: toStringValue(row.column_name),
6426
+ referencedSchema: toOptionalStringValue(row.referenced_schema_name),
6427
+ referencedTable: toStringValue(row.referenced_table_name),
6428
+ referencedColumn: toStringValue(row.referenced_column_name)
6429
+ };
6430
+ table.foreignKeys.push(foreignKey);
6431
+ }
6432
+ const indexRows = await runQueryRows(POSTGRES_INDEXES_QUERY);
6433
+ applyIndexRows(tableMap2, indexRows, "table_name", "schema_name", {
6434
+ indexNameField: "index_name",
6435
+ columnField: "column_name",
6436
+ positionField: "column_position",
6437
+ uniqueResolver: (row) => toBooleanValue(row.is_unique)
6438
+ });
6439
+ return Array.from(tableMap2.values());
6440
+ }
6441
+
6442
+ // src/data/relational/schema/schema-inspector-sqlite.ts
6443
+ var SQLITE_TABLES_QUERY = `
6444
+ SELECT
6445
+ name AS table_name
6446
+ FROM sqlite_master
6447
+ WHERE type = 'table'
6448
+ AND name NOT LIKE 'sqlite_%'
6449
+ ORDER BY name
6450
+ `;
6451
+ async function inspectSQLite(runQueryRows) {
6452
+ const tableRows = await runQueryRows(SQLITE_TABLES_QUERY);
6453
+ const tableMap2 = createTableMap(
6454
+ tableRows.map((row) => ({
6455
+ tableName: toStringValue(row.table_name)
6456
+ }))
6457
+ );
6458
+ for (const table of tableMap2.values()) {
6459
+ const tableLiteral = escapeSqliteStringLiteral(table.name);
6460
+ const columnRows = await runQueryRows(`PRAGMA table_info('${tableLiteral}')`);
6461
+ const primaryKeyColumns = [];
6462
+ for (const row of columnRows) {
6463
+ const pkPosition = toNumberValue(row.pk);
6464
+ const columnName = toStringValue(row.name);
6465
+ if (pkPosition > 0) {
6466
+ primaryKeyColumns.push({ position: pkPosition, column: columnName });
6467
+ }
6468
+ const column = createColumnSchema(row, {
6469
+ name: "name",
6470
+ type: "type",
6471
+ nullable: "notnull",
6472
+ defaultValue: "dflt_value",
6473
+ primaryKey: pkPosition > 0
6474
+ });
6475
+ column.isNullable = !toBooleanValue(row.notnull);
6476
+ table.columns.push(column);
6477
+ }
6478
+ table.primaryKey = sortColumnsByPosition(primaryKeyColumns);
6479
+ const foreignKeyRows = await runQueryRows(`PRAGMA foreign_key_list('${tableLiteral}')`);
6480
+ for (const row of foreignKeyRows) {
6481
+ const foreignKey = {
6482
+ column: toStringValue(row.from),
6483
+ referencedTable: toStringValue(row.table),
6484
+ referencedColumn: toStringValue(row.to)
6485
+ };
6486
+ table.foreignKeys.push(foreignKey);
6487
+ }
6488
+ const indexListRows = await runQueryRows(`PRAGMA index_list('${tableLiteral}')`);
6489
+ for (const indexRow of indexListRows) {
6490
+ const indexName = toStringValue(indexRow.name);
6491
+ if (!indexName || toStringValue(indexRow.origin) === "pk") {
6492
+ continue;
6493
+ }
6494
+ const indexNameLiteral = escapeSqliteStringLiteral(indexName);
6495
+ const indexInfoRows = await runQueryRows(`PRAGMA index_info('${indexNameLiteral}')`);
6496
+ const indexColumns = sortColumnsByPosition(
6497
+ indexInfoRows.map((row) => ({
6498
+ position: toNumberValue(row.seqno),
6499
+ column: toStringValue(row.name)
6500
+ }))
6501
+ );
6502
+ const index = {
6503
+ name: indexName,
6504
+ isUnique: toBooleanValue(indexRow.unique),
6505
+ columns: indexColumns
6506
+ };
6507
+ table.indexes.push(index);
6508
+ }
6509
+ }
6510
+ return Array.from(tableMap2.values());
6511
+ }
6512
+
6513
+ // src/data/relational/schema/schema-inspector.ts
6514
+ var logger13 = createLogger("agentforge:tools:data:relational:schema-inspector");
6515
+ var DEFAULT_CACHE_TTL_MS = 6e4;
6516
+ var schemaCache = /* @__PURE__ */ new Map();
6282
6517
  var SchemaInspector = class _SchemaInspector {
6283
- /**
6284
- * Create a new SchemaInspector.
6285
- *
6286
- * @param manager - ConnectionManager instance for database access
6287
- * @param vendor - Database vendor ('postgresql' | 'mysql' | 'sqlite')
6288
- * @param config - Optional configuration for cache TTL and cache key
6289
- */
6290
6518
  constructor(manager, vendor, config) {
6291
6519
  this.manager = manager;
6292
6520
  this.vendor = vendor;
@@ -6295,11 +6523,6 @@ var SchemaInspector = class _SchemaInspector {
6295
6523
  }
6296
6524
  cacheTtlMs;
6297
6525
  cacheKey;
6298
- /**
6299
- * Clear cached schema data.
6300
- *
6301
- * @param cacheKey - Specific cache key to clear. If omitted, clears all cached schemas.
6302
- */
6303
6526
  static clearCache(cacheKey) {
6304
6527
  if (cacheKey) {
6305
6528
  schemaCache.delete(cacheKey);
@@ -6307,18 +6530,9 @@ var SchemaInspector = class _SchemaInspector {
6307
6530
  }
6308
6531
  schemaCache.clear();
6309
6532
  }
6310
- /** Invalidate this inspector's cached schema, if any. */
6311
6533
  invalidateCache() {
6312
6534
  _SchemaInspector.clearCache(this.cacheKey);
6313
6535
  }
6314
- /**
6315
- * Inspect the database schema and return structured metadata.
6316
- *
6317
- * Results are cached when a `cacheKey` was provided at construction time.
6318
- *
6319
- * @param options - Optional table filters and cache bypass flag
6320
- * @returns Structured schema with tables, columns, indexes, and foreign keys
6321
- */
6322
6536
  async inspect(options) {
6323
6537
  const tableFilters = validateTableFilters(options?.tables);
6324
6538
  const bypassCache = options?.bypassCache ?? false;
@@ -6339,7 +6553,7 @@ var SchemaInspector = class _SchemaInspector {
6339
6553
  return filterSchemaTables(cloneSchema(schema), tableFilters);
6340
6554
  }
6341
6555
  async inspectFromDatabase() {
6342
- const tables = this.vendor === "postgresql" ? await this.inspectPostgreSQL() : this.vendor === "mysql" ? await this.inspectMySQL() : await this.inspectSQLite();
6556
+ const tables = await this.inspectTables();
6343
6557
  return {
6344
6558
  vendor: this.vendor,
6345
6559
  tables: tables.sort((left, right) => {
@@ -6350,6 +6564,18 @@ var SchemaInspector = class _SchemaInspector {
6350
6564
  generatedAt: (/* @__PURE__ */ new Date()).toISOString()
6351
6565
  };
6352
6566
  }
6567
+ async inspectTables() {
6568
+ switch (this.vendor) {
6569
+ case "postgresql":
6570
+ return inspectPostgreSQL((query) => this.runQueryRows(query));
6571
+ case "mysql":
6572
+ return inspectMySQL((query) => this.runQueryRows(query));
6573
+ case "sqlite":
6574
+ return inspectSQLite((query) => this.runQueryRows(query));
6575
+ default:
6576
+ throw new Error(`Unsupported database vendor: ${String(this.vendor)}`);
6577
+ }
6578
+ }
6353
6579
  async runQueryRows(query) {
6354
6580
  const result = await executeQuery2(this.manager, {
6355
6581
  sql: query,
@@ -6357,240 +6583,6 @@ var SchemaInspector = class _SchemaInspector {
6357
6583
  });
6358
6584
  return result.rows;
6359
6585
  }
6360
- createTableMap(refs) {
6361
- const tableMap2 = /* @__PURE__ */ new Map();
6362
- for (const ref of refs) {
6363
- const key = buildTableKey(ref.tableName, ref.schemaName);
6364
- tableMap2.set(key, {
6365
- name: ref.tableName,
6366
- schema: ref.schemaName,
6367
- columns: [],
6368
- primaryKey: [],
6369
- foreignKeys: [],
6370
- indexes: []
6371
- });
6372
- }
6373
- return tableMap2;
6374
- }
6375
- getTableFromRow(tableMap2, row, tableField, schemaField) {
6376
- const tableName = toStringValue(row[tableField]);
6377
- const schemaName = schemaField ? toOptionalStringValue(row[schemaField]) : void 0;
6378
- const key = buildTableKey(tableName, schemaName);
6379
- return tableMap2.get(key);
6380
- }
6381
- async inspectPostgreSQL() {
6382
- const tableRows = await this.runQueryRows(POSTGRES_TABLES_QUERY);
6383
- const tableMap2 = this.createTableMap(
6384
- tableRows.map((row) => ({
6385
- schemaName: toOptionalStringValue(row.schema_name),
6386
- tableName: toStringValue(row.table_name)
6387
- }))
6388
- );
6389
- const columnsRows = await this.runQueryRows(POSTGRES_COLUMNS_QUERY);
6390
- for (const row of columnsRows) {
6391
- const table = this.getTableFromRow(tableMap2, row, "table_name", "schema_name");
6392
- if (!table) {
6393
- continue;
6394
- }
6395
- const column = {
6396
- name: toStringValue(row.column_name),
6397
- type: toStringValue(row.data_type),
6398
- isNullable: toBooleanValue(row.is_nullable),
6399
- defaultValue: row.column_default ?? null,
6400
- isPrimaryKey: false
6401
- };
6402
- table.columns.push(column);
6403
- }
6404
- const primaryKeyRows = await this.runQueryRows(POSTGRES_PRIMARY_KEYS_QUERY);
6405
- for (const row of primaryKeyRows) {
6406
- const table = this.getTableFromRow(tableMap2, row, "table_name", "schema_name");
6407
- if (!table) {
6408
- continue;
6409
- }
6410
- const columnName = toStringValue(row.column_name);
6411
- table.primaryKey.push(columnName);
6412
- const column = table.columns.find((entry) => entry.name === columnName);
6413
- if (column) {
6414
- column.isPrimaryKey = true;
6415
- }
6416
- }
6417
- const foreignKeyRows = await this.runQueryRows(POSTGRES_FOREIGN_KEYS_QUERY);
6418
- for (const row of foreignKeyRows) {
6419
- const table = this.getTableFromRow(tableMap2, row, "table_name", "schema_name");
6420
- if (!table) {
6421
- continue;
6422
- }
6423
- const foreignKey = {
6424
- name: toOptionalStringValue(row.constraint_name),
6425
- column: toStringValue(row.column_name),
6426
- referencedSchema: toOptionalStringValue(row.referenced_schema_name),
6427
- referencedTable: toStringValue(row.referenced_table_name),
6428
- referencedColumn: toStringValue(row.referenced_column_name)
6429
- };
6430
- table.foreignKeys.push(foreignKey);
6431
- }
6432
- const indexRows = await this.runQueryRows(POSTGRES_INDEXES_QUERY);
6433
- this.applyIndexRows(tableMap2, indexRows, "table_name", "schema_name", {
6434
- indexNameField: "index_name",
6435
- columnField: "column_name",
6436
- positionField: "column_position",
6437
- uniqueResolver: (row) => toBooleanValue(row.is_unique)
6438
- });
6439
- return Array.from(tableMap2.values());
6440
- }
6441
- async inspectMySQL() {
6442
- const tableRows = await this.runQueryRows(MYSQL_TABLES_QUERY);
6443
- const tableMap2 = this.createTableMap(
6444
- tableRows.map((row) => ({
6445
- schemaName: toOptionalStringValue(row.schema_name),
6446
- tableName: toStringValue(row.table_name)
6447
- }))
6448
- );
6449
- const columnsRows = await this.runQueryRows(MYSQL_COLUMNS_QUERY);
6450
- for (const row of columnsRows) {
6451
- const table = this.getTableFromRow(tableMap2, row, "table_name", "schema_name");
6452
- if (!table) {
6453
- continue;
6454
- }
6455
- const column = {
6456
- name: toStringValue(row.column_name),
6457
- type: toStringValue(row.data_type),
6458
- isNullable: toBooleanValue(row.is_nullable),
6459
- defaultValue: row.column_default ?? null,
6460
- isPrimaryKey: false
6461
- };
6462
- table.columns.push(column);
6463
- }
6464
- const primaryKeyRows = await this.runQueryRows(MYSQL_PRIMARY_KEYS_QUERY);
6465
- for (const row of primaryKeyRows) {
6466
- const table = this.getTableFromRow(tableMap2, row, "table_name", "schema_name");
6467
- if (!table) {
6468
- continue;
6469
- }
6470
- const columnName = toStringValue(row.column_name);
6471
- table.primaryKey.push(columnName);
6472
- const column = table.columns.find((entry) => entry.name === columnName);
6473
- if (column) {
6474
- column.isPrimaryKey = true;
6475
- }
6476
- }
6477
- const foreignKeyRows = await this.runQueryRows(MYSQL_FOREIGN_KEYS_QUERY);
6478
- for (const row of foreignKeyRows) {
6479
- const table = this.getTableFromRow(tableMap2, row, "table_name", "schema_name");
6480
- if (!table) {
6481
- continue;
6482
- }
6483
- const foreignKey = {
6484
- name: toOptionalStringValue(row.constraint_name),
6485
- column: toStringValue(row.column_name),
6486
- referencedSchema: toOptionalStringValue(row.referenced_schema_name),
6487
- referencedTable: toStringValue(row.referenced_table_name),
6488
- referencedColumn: toStringValue(row.referenced_column_name)
6489
- };
6490
- table.foreignKeys.push(foreignKey);
6491
- }
6492
- const indexRows = await this.runQueryRows(MYSQL_INDEXES_QUERY);
6493
- this.applyIndexRows(tableMap2, indexRows, "table_name", "schema_name", {
6494
- indexNameField: "index_name",
6495
- columnField: "column_name",
6496
- positionField: "seq_in_index",
6497
- uniqueResolver: (row) => !toBooleanValue(row.non_unique)
6498
- });
6499
- return Array.from(tableMap2.values());
6500
- }
6501
- async inspectSQLite() {
6502
- const tableRows = await this.runQueryRows(SQLITE_TABLES_QUERY);
6503
- const tableMap2 = this.createTableMap(
6504
- tableRows.map((row) => ({
6505
- tableName: toStringValue(row.table_name)
6506
- }))
6507
- );
6508
- for (const table of tableMap2.values()) {
6509
- const tableLiteral = escapeSqliteStringLiteral(table.name);
6510
- const columnRows = await this.runQueryRows(`PRAGMA table_info('${tableLiteral}')`);
6511
- const primaryKeyColumns = [];
6512
- for (const row of columnRows) {
6513
- const pkPosition = toNumberValue(row.pk);
6514
- const columnName = toStringValue(row.name);
6515
- if (pkPosition > 0) {
6516
- primaryKeyColumns.push({ position: pkPosition, column: columnName });
6517
- }
6518
- const column = {
6519
- name: columnName,
6520
- type: toStringValue(row.type),
6521
- isNullable: !toBooleanValue(row.notnull),
6522
- defaultValue: row.dflt_value ?? null,
6523
- isPrimaryKey: pkPosition > 0
6524
- };
6525
- table.columns.push(column);
6526
- }
6527
- table.primaryKey = sortColumnsByPosition(primaryKeyColumns);
6528
- const foreignKeyRows = await this.runQueryRows(`PRAGMA foreign_key_list('${tableLiteral}')`);
6529
- for (const row of foreignKeyRows) {
6530
- const foreignKey = {
6531
- column: toStringValue(row.from),
6532
- referencedTable: toStringValue(row.table),
6533
- referencedColumn: toStringValue(row.to)
6534
- };
6535
- table.foreignKeys.push(foreignKey);
6536
- }
6537
- const indexListRows = await this.runQueryRows(`PRAGMA index_list('${tableLiteral}')`);
6538
- for (const indexRow of indexListRows) {
6539
- const indexName = toStringValue(indexRow.name);
6540
- if (!indexName || toStringValue(indexRow.origin) === "pk") {
6541
- continue;
6542
- }
6543
- const indexNameLiteral = escapeSqliteStringLiteral(indexName);
6544
- const indexInfoRows = await this.runQueryRows(`PRAGMA index_info('${indexNameLiteral}')`);
6545
- const indexColumns = sortColumnsByPosition(
6546
- indexInfoRows.map((row) => ({
6547
- position: toNumberValue(row.seqno),
6548
- column: toStringValue(row.name)
6549
- }))
6550
- );
6551
- const index = {
6552
- name: indexName,
6553
- isUnique: toBooleanValue(indexRow.unique),
6554
- columns: indexColumns
6555
- };
6556
- table.indexes.push(index);
6557
- }
6558
- }
6559
- return Array.from(tableMap2.values());
6560
- }
6561
- applyIndexRows(tableMap2, rows, tableField, schemaField, config) {
6562
- const grouped = /* @__PURE__ */ new Map();
6563
- for (const row of rows) {
6564
- const table = this.getTableFromRow(tableMap2, row, tableField, schemaField);
6565
- if (!table) {
6566
- continue;
6567
- }
6568
- const indexName = toStringValue(row[config.indexNameField]);
6569
- if (!indexName) {
6570
- continue;
6571
- }
6572
- const groupKey = `${table.schema ?? ""}.${table.name}.${indexName}`;
6573
- const entry = grouped.get(groupKey) ?? {
6574
- table,
6575
- indexName,
6576
- isUnique: config.uniqueResolver(row),
6577
- columnsByPosition: []
6578
- };
6579
- entry.columnsByPosition.push({
6580
- position: toNumberValue(row[config.positionField]),
6581
- column: toStringValue(row[config.columnField])
6582
- });
6583
- grouped.set(groupKey, entry);
6584
- }
6585
- for (const entry of grouped.values()) {
6586
- const index = {
6587
- name: entry.indexName,
6588
- isUnique: entry.isUnique,
6589
- columns: sortColumnsByPosition(entry.columnsByPosition)
6590
- };
6591
- entry.table.indexes.push(index);
6592
- }
6593
- }
6594
6586
  };
6595
6587
  var logger14 = createLogger("agentforge:tools:data:relational:schema-validator");
6596
6588
  function validateTableExists(schema, tableName) {