@deepagents/text2sql 0.18.0 → 0.20.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.
@@ -714,6 +714,32 @@ var LastQueryExtractor = class extends BaseContextualExtractor {
714
714
  // packages/text2sql/src/lib/synthesis/synthesizers/schema-synthesizer.ts
715
715
  import pLimit from "p-limit";
716
716
 
717
+ // packages/text2sql/src/lib/agents/exceptions.ts
718
+ var sqlValidationMarker = Symbol("SQLValidationError");
719
+ var unanswerableSqlMarker = Symbol("UnanswerableSQLError");
720
+ var SQLValidationError = class _SQLValidationError extends Error {
721
+ [sqlValidationMarker];
722
+ constructor(message) {
723
+ super(message);
724
+ this.name = "SQLValidationError";
725
+ this[sqlValidationMarker] = true;
726
+ }
727
+ static isInstance(error) {
728
+ return error instanceof _SQLValidationError && error[sqlValidationMarker] === true;
729
+ }
730
+ };
731
+ var UnanswerableSQLError = class _UnanswerableSQLError extends Error {
732
+ [unanswerableSqlMarker];
733
+ constructor(message) {
734
+ super(message);
735
+ this.name = "UnanswerableSQLError";
736
+ this[unanswerableSqlMarker] = true;
737
+ }
738
+ static isInstance(error) {
739
+ return error instanceof _UnanswerableSQLError && error[unanswerableSqlMarker] === true;
740
+ }
741
+ };
742
+
717
743
  // packages/text2sql/src/lib/agents/question.agent.ts
718
744
  import { groq as groq4 } from "@ai-sdk/groq";
719
745
  import dedent4 from "dedent";
@@ -838,42 +864,120 @@ import {
838
864
  defaultSettingsMiddleware,
839
865
  wrapLanguageModel
840
866
  } from "ai";
867
+ import dedent5 from "dedent";
841
868
  import pRetry from "p-retry";
842
869
  import z5 from "zod";
843
870
  import "@deepagents/agent";
844
871
  import {
845
872
  ContextEngine as ContextEngine5,
846
873
  InMemoryContextStore as InMemoryContextStore5,
874
+ fragment as fragment5,
847
875
  persona as persona5,
876
+ policy,
848
877
  structuredOutput as structuredOutput5,
849
878
  user as user5
850
879
  } from "@deepagents/context";
851
880
  var RETRY_TEMPERATURES = [0, 0.2, 0.3];
881
+ var SQL_AGENT_ROLE = "Expert SQL query generator.";
882
+ var SQL_AGENT_OBJECTIVE = "Generate precise SQL grounded in provided schema.";
883
+ var SQL_AGENT_POLICIES = [
884
+ fragment5(
885
+ "schema_mapping",
886
+ policy({
887
+ rule: "Translate natural language into precise SQL grounded in available schema entities."
888
+ })
889
+ // policy({
890
+ // rule: 'Before returning an error, perform a schema-grounded self-check: identify core intent, draft best-effort SQL, then verify it uses only existing tables/columns.',
891
+ // }),
892
+ // policy({
893
+ // rule: 'Return unanswerable only if that self-check confirms no valid SQL can express the required intent without inventing schema elements.',
894
+ // }),
895
+ // policy({
896
+ // rule: 'Prefer a best-effort valid SQL query when entities can be reasonably inferred from table or column names.',
897
+ // }),
898
+ // policy({
899
+ // rule: 'Use lexical normalization (singular/plural, paraphrases, role synonyms, and minor wording differences) to align question terms with schema names.',
900
+ // }),
901
+ // policy({
902
+ // rule: 'Decompose noun phrases into core entity and qualifiers, and map the core entity first.',
903
+ // }),
904
+ // policy({
905
+ // rule: 'Do not require every descriptive word to map to a separate schema field when the core entity match is unambiguous.',
906
+ // }),
907
+ // policy({
908
+ // rule: 'For phrases like "X of Y", treat Y as contextual (non-blocking) when Y has no mapped schema field and the question does not ask to filter/group/select by Y explicitly.',
909
+ // }),
910
+ // policy({
911
+ // rule: 'Treat unmatched qualifiers as blockers only when they are restrictive constraints (specific values, comparisons, or conditions that change row eligibility).',
912
+ // }),
913
+ // hint('Preserve schema spelling exactly, including typos in column names.'),
914
+ )
915
+ // fragment(
916
+ // 'unanswerable_gate',
917
+ // workflow({
918
+ // task: 'Unanswerable decision',
919
+ // steps: [
920
+ // 'Identify the core intent (metric/projection and required filters).',
921
+ // 'Attempt schema-grounded mapping for the core intent before considering error.',
922
+ // 'If a valid SELECT can answer the core intent without inventing schema entities, return SQL.',
923
+ // 'Return unanswerable only when required information cannot be mapped to any available table or column.',
924
+ // ],
925
+ // }),
926
+ // policy({
927
+ // rule: 'Do not reject a question as unanswerable when requested information can be derived by filtering, joining, grouping, counting, set operations, or sorting on available columns.',
928
+ // }),
929
+ // ),
930
+ // fragment(
931
+ // 'query_shape_preferences',
932
+ // hint(
933
+ // 'Prefer explicit INNER JOINs over LEFT JOINs unless the question requires unmatched rows.',
934
+ // ),
935
+ // hint(
936
+ // 'Prefer direct joins over dropping join constraints or using weaker alternatives.',
937
+ // ),
938
+ // hint('Use DISTINCT only when uniqueness is explicitly requested.'),
939
+ // hint(
940
+ // 'For superlatives over grouped entities (most/least/highest/lowest by group), prefer GROUP BY with ORDER BY aggregate and LIMIT 1.',
941
+ // ),
942
+ // hint(
943
+ // 'For average/count conditions per entity, prefer GROUP BY with HAVING aggregate predicates over row-level WHERE predicates.',
944
+ // ),
945
+ // hint(
946
+ // 'For "both" conditions across two criteria, prefer INTERSECT when selecting shared values.',
947
+ // ),
948
+ // hint(
949
+ // 'For "A or B" retrieval across criteria, prefer UNION when combining two qualifying sets.',
950
+ // ),
951
+ // hint(
952
+ // 'For "never" constraints against related records, prefer NOT IN or EXCEPT against the disqualifying set.',
953
+ // ),
954
+ // hint(
955
+ // 'Use equality predicates for exact values unless the question asks for pattern matching.',
956
+ // ),
957
+ // hint(
958
+ // 'Keep numeric literals unquoted when they are purely numeric tokens in the question.',
959
+ // ),
960
+ // ),
961
+ // fragment(
962
+ // 'sql_minimality',
963
+ // guardrail({
964
+ // rule: 'Never hallucinate tables or columns.',
965
+ // reason: 'Schema fidelity is required.',
966
+ // action: 'Use only available schema entities.',
967
+ // }),
968
+ // guardrail({
969
+ // rule: 'Prefer the minimal query over transformed expressions.',
970
+ // reason:
971
+ // 'Unnecessary transformations reduce correctness and add avoidable complexity.',
972
+ // action:
973
+ // 'Do not add date parsing, substring extraction, derived projections, or extra selected columns unless explicitly requested or required by schema mismatch.',
974
+ // }),
975
+ // ),
976
+ ];
852
977
  function extractSql(output) {
853
978
  const match = output.match(/```sql\n?([\s\S]*?)```/);
854
979
  return match ? match[1].trim() : output.trim();
855
980
  }
856
- var marker = Symbol("SQLValidationError");
857
- var SQLValidationError = class _SQLValidationError extends Error {
858
- [marker];
859
- constructor(message) {
860
- super(message);
861
- this.name = "SQLValidationError";
862
- this[marker] = true;
863
- }
864
- static isInstance(error) {
865
- return error instanceof _SQLValidationError && error[marker] === true;
866
- }
867
- };
868
- var UnanswerableSQLError = class _UnanswerableSQLError extends Error {
869
- constructor(message) {
870
- super(message);
871
- this.name = "UnanswerableSQLError";
872
- }
873
- static isInstance(error) {
874
- return error instanceof _UnanswerableSQLError;
875
- }
876
- };
877
981
  async function toSql(options) {
878
982
  const { maxRetries = 3 } = options;
879
983
  return withRetry(
@@ -886,21 +990,38 @@ async function toSql(options) {
886
990
  context.set(
887
991
  persona5({
888
992
  name: "Freya",
889
- role: "You are an expert SQL query generator. You translate natural language questions into precise, efficient SQL queries based on the provided database schema.",
890
- objective: "Translate natural language questions into precise, efficient SQL queries"
993
+ role: SQL_AGENT_ROLE,
994
+ objective: SQL_AGENT_OBJECTIVE
995
+ // role: `You are a data science expert that provides well-reasoned and detailed responses.`,
996
+ // objective: `Your task is to understand the schema and generate a valid SQL query to answer the question. You first think about the reasoning process as an internal monologue and then provide the user with the answer.`,
891
997
  }),
892
- ...options.instructions,
893
- ...options.schemaFragments
998
+ ...SQL_AGENT_POLICIES,
999
+ ...options.fragments
894
1000
  );
895
1001
  if (errors.length) {
1002
+ const lastError = errors.at(-1);
896
1003
  context.set(
897
- user5(options.input),
898
- user5(
899
- `<validation_error>Your previous SQL query had the following error: ${errors.at(-1)?.message}. Please fix the query.</validation_error>`
1004
+ user5(dedent5`
1005
+ Answer the following question with the SQL code. Use the piece of evidence and base your answer on the database schema.
1006
+ Given the question, the evidence and the database schema, return the SQL script that addresses the question.
1007
+
1008
+ Question: ${options.input}
1009
+ `),
1010
+ UnanswerableSQLError.isInstance(lastError) ? user5(
1011
+ `<retry_instruction>Your previous response marked the task as unanswerable. Re-evaluate using best-effort schema mapping. If the core intent is answerable with existing tables/columns, return SQL. Return error only when required core intent cannot be mapped without inventing schema elements.</retry_instruction>`
1012
+ ) : user5(
1013
+ `<validation_error>Your previous SQL query had the following error: ${lastError?.message}. Please fix the query.</validation_error>`
900
1014
  )
901
1015
  );
902
1016
  } else {
903
- context.set(user5(options.input));
1017
+ context.set(
1018
+ user5(dedent5`
1019
+ Answer the following question with the SQL code. Use the piece of evidence and base your answer on the database schema.
1020
+ Given the question, the evidence and the database schema, return the SQL script that addresses the question.
1021
+
1022
+ Question: ${options.input}
1023
+ `)
1024
+ );
904
1025
  }
905
1026
  const temperature = RETRY_TEMPERATURES[attemptNumber - 1] ?? RETRY_TEMPERATURES[RETRY_TEMPERATURES.length - 1];
906
1027
  const baseModel = options.model ?? groq5("openai/gpt-oss-20b");
@@ -926,19 +1047,45 @@ async function toSql(options) {
926
1047
  })
927
1048
  });
928
1049
  const { result: output } = await sqlOutput.generate();
1050
+ const finalizeSql = async (rawSql) => {
1051
+ const sql = options.adapter.format(extractSql(rawSql));
1052
+ const validationError = await options.adapter.validate(sql);
1053
+ if (validationError) {
1054
+ throw new SQLValidationError(validationError);
1055
+ }
1056
+ return {
1057
+ attempts,
1058
+ sql,
1059
+ errors: errors.length ? errors.map(formatErrorMessage) : void 0
1060
+ };
1061
+ };
929
1062
  if ("error" in output) {
930
- throw new UnanswerableSQLError(output.error);
931
- }
932
- const sql = options.adapter.format(extractSql(output.sql));
933
- const validationError = await options.adapter.validate(sql);
934
- if (validationError) {
935
- throw new SQLValidationError(validationError);
1063
+ context.set(
1064
+ user5(
1065
+ "<best_effort_fallback>Do not return unanswerable. Produce the best valid SQL query that answers the core intent using only available schema entities.</best_effort_fallback>"
1066
+ )
1067
+ );
1068
+ const forcedSqlOutput = structuredOutput5({
1069
+ model,
1070
+ context,
1071
+ schema: z5.object({
1072
+ sql: z5.string().describe(
1073
+ "Best-effort SQL query that answers the core intent using only available schema entities."
1074
+ ),
1075
+ reasoning: z5.string().describe("Reasoning steps for best-effort schema mapping.")
1076
+ })
1077
+ });
1078
+ try {
1079
+ const forced = await forcedSqlOutput.generate();
1080
+ return await finalizeSql(forced.sql);
1081
+ } catch (error) {
1082
+ if (SQLValidationError.isInstance(error) || APICallError.isInstance(error) || JSONParseError.isInstance(error) || TypeValidationError.isInstance(error) || NoObjectGeneratedError.isInstance(error) || NoOutputGeneratedError.isInstance(error) || NoContentGeneratedError.isInstance(error)) {
1083
+ throw error;
1084
+ }
1085
+ throw new UnanswerableSQLError(output.error);
1086
+ }
936
1087
  }
937
- return {
938
- attempts,
939
- sql,
940
- errors: errors.length ? errors.map(formatErrorMessage) : void 0
941
- };
1088
+ return await finalizeSql(output.sql);
942
1089
  },
943
1090
  { retries: maxRetries - 1 }
944
1091
  );
@@ -1001,9 +1148,6 @@ async function withRetry(computation, options = { retries: 3 }) {
1001
1148
  return APICallError.isInstance(context.error) || JSONParseError.isInstance(context.error) || TypeValidationError.isInstance(context.error) || NoObjectGeneratedError.isInstance(context.error) || NoOutputGeneratedError.isInstance(context.error) || NoContentGeneratedError.isInstance(context.error);
1002
1149
  },
1003
1150
  onFailedAttempt(context) {
1004
- console.log(
1005
- `Attempt ${context.attemptNumber} failed. There are ${context.retriesLeft} retries left.`
1006
- );
1007
1151
  errors.push(context.error);
1008
1152
  }
1009
1153
  }
@@ -1076,9 +1220,7 @@ Generate ${this.options.count} questions at ${complexity} complexity.` : void 0;
1076
1220
  return await toSql({
1077
1221
  input: question,
1078
1222
  adapter: this.adapter,
1079
- schemaFragments: [],
1080
- // Placeholder - needs to pass actual fragments
1081
- instructions: this.options.teachings ?? [],
1223
+ fragments: this.options.teachings ?? [],
1082
1224
  model: this.options.model
1083
1225
  });
1084
1226
  } catch (error) {
@@ -1107,14 +1249,14 @@ Generate ${this.options.count} questions at ${complexity} complexity.` : void 0;
1107
1249
 
1108
1250
  // packages/text2sql/src/lib/synthesis/synthesizers/breadth-evolver.ts
1109
1251
  import { groq as groq6 } from "@ai-sdk/groq";
1110
- import dedent5 from "dedent";
1252
+ import dedent6 from "dedent";
1111
1253
  import pLimit2 from "p-limit";
1112
1254
  import z6 from "zod";
1113
1255
  import "@deepagents/agent";
1114
1256
  import {
1115
1257
  ContextEngine as ContextEngine6,
1116
1258
  InMemoryContextStore as InMemoryContextStore6,
1117
- fragment as fragment5,
1259
+ fragment as fragment6,
1118
1260
  guardrail as guardrail2,
1119
1261
  persona as personaFragment,
1120
1262
  structuredOutput as structuredOutput6,
@@ -1166,7 +1308,7 @@ async function paraphraseQuestion(params) {
1166
1308
  chatId: `paraphraser-${crypto.randomUUID()}`,
1167
1309
  userId: "system"
1168
1310
  });
1169
- const personaInstruction = params.persona ? dedent5`
1311
+ const personaInstruction = params.persona ? dedent6`
1170
1312
  <persona role="${params.persona.role}">
1171
1313
  ${params.persona.perspective}
1172
1314
 
@@ -1174,7 +1316,7 @@ async function paraphraseQuestion(params) {
1174
1316
  Use their vocabulary, priorities, and framing style.
1175
1317
  </persona>
1176
1318
  ` : "";
1177
- const styleInstruction = params.persona?.styles && params.persona.styles.length > 0 ? dedent5`
1319
+ const styleInstruction = params.persona?.styles && params.persona.styles.length > 0 ? dedent6`
1178
1320
  <communication_styles>
1179
1321
  Generate paraphrases using these communication styles: ${params.persona.styles.join(", ")}
1180
1322
 
@@ -1190,17 +1332,17 @@ async function paraphraseQuestion(params) {
1190
1332
  role: "You are a linguistic expert specializing in paraphrasing database questions. Your task is to generate alternative phrasings of questions that preserve the exact same semantic meaning - they must all produce the identical SQL query.",
1191
1333
  objective: "Generate paraphrased versions of questions that preserve exact semantic meaning and produce identical SQL"
1192
1334
  }),
1193
- fragment5("original_question", params.question),
1194
- fragment5(
1335
+ fragment6("original_question", params.question),
1336
+ fragment6(
1195
1337
  "reference_sql",
1196
1338
  params.sql,
1197
1339
  "This SQL shows what the question is really asking - all paraphrases must ask for exactly this"
1198
1340
  ),
1199
- ...personaInstruction ? [fragment5("persona", personaInstruction)] : [],
1200
- ...styleInstruction ? [fragment5("communication_styles", styleInstruction)] : [],
1201
- fragment5(
1341
+ ...personaInstruction ? [fragment6("persona", personaInstruction)] : [],
1342
+ ...styleInstruction ? [fragment6("communication_styles", styleInstruction)] : [],
1343
+ fragment6(
1202
1344
  "task",
1203
- dedent5`
1345
+ dedent6`
1204
1346
  Generate exactly ${params.count} paraphrased versions of the original question.
1205
1347
 
1206
1348
  Requirements:
@@ -1277,7 +1419,7 @@ var BreadthEvolver = class extends PairProducer {
1277
1419
  // packages/text2sql/src/lib/synthesis/synthesizers/depth-evolver.ts
1278
1420
  import { groq as groq7 } from "@ai-sdk/groq";
1279
1421
  import { NoObjectGeneratedError as NoObjectGeneratedError2, NoOutputGeneratedError as NoOutputGeneratedError2 } from "ai";
1280
- import dedent6 from "dedent";
1422
+ import dedent7 from "dedent";
1281
1423
  import pLimit3 from "p-limit";
1282
1424
  import pRetry2 from "p-retry";
1283
1425
  import z7 from "zod";
@@ -1285,14 +1427,14 @@ import "@deepagents/agent";
1285
1427
  import {
1286
1428
  ContextEngine as ContextEngine7,
1287
1429
  InMemoryContextStore as InMemoryContextStore7,
1288
- fragment as fragment6,
1430
+ fragment as fragment7,
1289
1431
  guardrail as guardrail3,
1290
1432
  persona as persona6,
1291
1433
  structuredOutput as structuredOutput7,
1292
1434
  user as user7
1293
1435
  } from "@deepagents/context";
1294
1436
  var techniqueInstructions = {
1295
- "add-aggregation": dedent6`
1437
+ "add-aggregation": dedent7`
1296
1438
  Add aggregation requirements to the question.
1297
1439
  Transform it to require GROUP BY, COUNT, SUM, AVG, MIN, MAX, or similar operations.
1298
1440
  Examples:
@@ -1300,7 +1442,7 @@ var techniqueInstructions = {
1300
1442
  - "List products" → "What is the average price per category?"
1301
1443
  - "Get employees" → "How many employees are in each department?"
1302
1444
  `,
1303
- "add-filter": dedent6`
1445
+ "add-filter": dedent7`
1304
1446
  Add filtering conditions to the question.
1305
1447
  Transform it to require WHERE clauses with specific conditions.
1306
1448
  Examples:
@@ -1308,7 +1450,7 @@ var techniqueInstructions = {
1308
1450
  - "List customers" → "List customers who have made more than 5 purchases"
1309
1451
  - "Get products" → "Get products with price above $100"
1310
1452
  `,
1311
- "add-join": dedent6`
1453
+ "add-join": dedent7`
1312
1454
  Add requirements that need data from related tables.
1313
1455
  Transform it to require JOIN operations between multiple tables.
1314
1456
  Examples:
@@ -1316,7 +1458,7 @@ var techniqueInstructions = {
1316
1458
  - "List products" → "List products with their supplier information"
1317
1459
  - "Get employees" → "Get employees with their department and manager names"
1318
1460
  `,
1319
- "add-reasoning": dedent6`
1461
+ "add-reasoning": dedent7`
1320
1462
  Add multi-step reasoning requirements.
1321
1463
  Transform it to require logical deduction, comparisons, or derived calculations.
1322
1464
  Examples:
@@ -1324,7 +1466,7 @@ var techniqueInstructions = {
1324
1466
  - "List products" → "Which products are underperforming compared to their category average?"
1325
1467
  - "Get revenue" → "Which month had the highest growth compared to the previous month?"
1326
1468
  `,
1327
- hypothetical: dedent6`
1469
+ hypothetical: dedent7`
1328
1470
  Add a hypothetical or speculative scenario.
1329
1471
  Transform it to require applying calculations or projections.
1330
1472
  Examples:
@@ -1348,21 +1490,21 @@ async function evolveQuestion(params) {
1348
1490
  role: "You are an expert at evolving simple database questions into more complex ones. Your task is to take a basic question and transform it into a more sophisticated version that requires advanced SQL techniques to answer.",
1349
1491
  objective: "Transform simple questions into complex versions requiring advanced SQL techniques"
1350
1492
  }),
1351
- fragment6("original_question", params.question),
1352
- fragment6(
1493
+ fragment7("original_question", params.question),
1494
+ fragment7(
1353
1495
  "original_sql",
1354
1496
  params.sql,
1355
1497
  "(This shows what the original question required)"
1356
1498
  ),
1357
- fragment6("database_schema", params.schema),
1358
- fragment6(
1499
+ fragment7("database_schema", params.schema),
1500
+ fragment7(
1359
1501
  "technique",
1360
1502
  { name: params.technique },
1361
1503
  params.techniqueInstruction
1362
1504
  ),
1363
- fragment6(
1505
+ fragment7(
1364
1506
  "task",
1365
- dedent6`
1507
+ dedent7`
1366
1508
  Evolve the original question using the "${params.technique}" technique.
1367
1509
 
1368
1510
  Requirements:
@@ -1455,9 +1597,7 @@ var DepthEvolver = class extends PairProducer {
1455
1597
  const sqlResult = await toSql({
1456
1598
  input: evolvedQuestion,
1457
1599
  adapter: this.adapter,
1458
- schemaFragments: [],
1459
- // Placeholder - needs to pass actual fragments
1460
- instructions: [],
1600
+ fragments: [],
1461
1601
  model: this.options?.model
1462
1602
  });
1463
1603
  return {
@@ -1507,14 +1647,14 @@ async function withRetry2(computation) {
1507
1647
 
1508
1648
  // packages/text2sql/src/lib/synthesis/synthesizers/persona-generator.ts
1509
1649
  import { groq as groq8 } from "@ai-sdk/groq";
1510
- import dedent7 from "dedent";
1650
+ import dedent8 from "dedent";
1511
1651
  import z8 from "zod";
1512
1652
  import "@deepagents/agent";
1513
1653
  import {
1514
1654
  ContextEngine as ContextEngine8,
1515
1655
  InMemoryContextStore as InMemoryContextStore8,
1516
1656
  XmlRenderer,
1517
- fragment as fragment7,
1657
+ fragment as fragment8,
1518
1658
  guardrail as guardrail4,
1519
1659
  persona as personaFragment2,
1520
1660
  structuredOutput as structuredOutput8,
@@ -1547,10 +1687,10 @@ async function generatePersonas(schemaFragments, options) {
1547
1687
  role: "You are an expert at understanding database schemas and inferring who would use them.",
1548
1688
  objective: "Generate realistic personas representing users who would query this database"
1549
1689
  }),
1550
- fragment7("database_schema", schema),
1551
- fragment7(
1690
+ fragment8("database_schema", schema),
1691
+ fragment8(
1552
1692
  "task",
1553
- dedent7`
1693
+ dedent8`
1554
1694
  Analyze the database schema and generate realistic personas representing
1555
1695
  the different types of users who would query this database.
1556
1696
 
@@ -1581,9 +1721,9 @@ async function generatePersonas(schemaFragments, options) {
1581
1721
  - Styles should match how this persona would naturally communicate
1582
1722
  `
1583
1723
  ),
1584
- fragment7(
1724
+ fragment8(
1585
1725
  "example",
1586
- dedent7`
1726
+ dedent8`
1587
1727
  For an e-commerce schema with orders, customers, products tables:
1588
1728
 
1589
1729
  {
@@ -1626,7 +1766,7 @@ import { XmlRenderer as XmlRenderer2 } from "@deepagents/context";
1626
1766
 
1627
1767
  // packages/text2sql/src/lib/agents/teachables.agent.ts
1628
1768
  import { groq as groq9 } from "@ai-sdk/groq";
1629
- import dedent8 from "dedent";
1769
+ import dedent9 from "dedent";
1630
1770
  import z9 from "zod";
1631
1771
  import "@deepagents/agent";
1632
1772
  import {
@@ -1636,7 +1776,7 @@ import {
1636
1776
  clarification,
1637
1777
  example,
1638
1778
  explain,
1639
- fragment as fragment8,
1779
+ fragment as fragment9,
1640
1780
  guardrail as guardrail5,
1641
1781
  hint,
1642
1782
  persona as persona7,
@@ -1710,11 +1850,11 @@ async function toTeachings(input, options) {
1710
1850
  role: 'You design "fragments" for a Text2SQL system. Fragments become structured XML instructions.',
1711
1851
  objective: "Choose only high-impact items that improve accuracy, safety, or clarity for this database"
1712
1852
  }),
1713
- fragment8("database_schema", input.schema),
1714
- ...input.context ? [fragment8("additional_context", input.context)] : [],
1715
- fragment8(
1853
+ fragment9("database_schema", input.schema),
1854
+ ...input.context ? [fragment9("additional_context", input.context)] : [],
1855
+ fragment9(
1716
1856
  "output_structure",
1717
- dedent8`
1857
+ dedent9`
1718
1858
  Output a JSON object with these optional arrays (include only relevant ones):
1719
1859
  - terms: [{ name: string, definition: string }] - Domain terminology
1720
1860
  - hints: [{ text: string }] - Helpful SQL generation hints
@@ -1728,9 +1868,9 @@ async function toTeachings(input, options) {
1728
1868
  - analogies: [{ concepts: string[], relationship: string, insight?: string, therefore?: string, pitfall?: string }]
1729
1869
  `
1730
1870
  ),
1731
- fragment8(
1871
+ fragment9(
1732
1872
  "task",
1733
- dedent8`
1873
+ dedent9`
1734
1874
  1. Analyze the schema to infer domain, relationships, and sensitive columns.
1735
1875
  2. Generate 3-10 fragments total across all categories, prioritizing:
1736
1876
  - guardrails for PII columns (email, ssn, phone, etc)