@deepagents/text2sql 0.6.0 → 0.8.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.
Files changed (50) hide show
  1. package/dist/index.d.ts +1 -0
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +1121 -453
  4. package/dist/index.js.map +4 -4
  5. package/dist/lib/adapters/mysql/column-stats.mysql.grounding.d.ts +14 -0
  6. package/dist/lib/adapters/mysql/column-stats.mysql.grounding.d.ts.map +1 -0
  7. package/dist/lib/adapters/mysql/column-values.mysql.grounding.d.ts +22 -0
  8. package/dist/lib/adapters/mysql/column-values.mysql.grounding.d.ts.map +1 -0
  9. package/dist/lib/adapters/mysql/constraint.mysql.grounding.d.ts +13 -0
  10. package/dist/lib/adapters/mysql/constraint.mysql.grounding.d.ts.map +1 -0
  11. package/dist/lib/adapters/mysql/index.d.ts +44 -0
  12. package/dist/lib/adapters/mysql/index.d.ts.map +1 -0
  13. package/dist/lib/adapters/mysql/index.js +1597 -0
  14. package/dist/lib/adapters/mysql/index.js.map +7 -0
  15. package/dist/lib/adapters/mysql/indexes.mysql.grounding.d.ts +13 -0
  16. package/dist/lib/adapters/mysql/indexes.mysql.grounding.d.ts.map +1 -0
  17. package/dist/lib/adapters/mysql/info.mysql.grounding.d.ts +13 -0
  18. package/dist/lib/adapters/mysql/info.mysql.grounding.d.ts.map +1 -0
  19. package/dist/lib/adapters/mysql/mysql.d.ts +33 -0
  20. package/dist/lib/adapters/mysql/mysql.d.ts.map +1 -0
  21. package/dist/lib/adapters/mysql/row-count.mysql.grounding.d.ts +13 -0
  22. package/dist/lib/adapters/mysql/row-count.mysql.grounding.d.ts.map +1 -0
  23. package/dist/lib/adapters/mysql/table.mysql.grounding.d.ts +21 -0
  24. package/dist/lib/adapters/mysql/table.mysql.grounding.d.ts.map +1 -0
  25. package/dist/lib/adapters/mysql/view.mysql.grounding.d.ts +18 -0
  26. package/dist/lib/adapters/mysql/view.mysql.grounding.d.ts.map +1 -0
  27. package/dist/lib/agents/bi.agent.d.ts +14 -0
  28. package/dist/lib/agents/bi.agent.d.ts.map +1 -0
  29. package/dist/lib/agents/chat1.agent.d.ts.map +1 -1
  30. package/dist/lib/agents/chat2.agent.d.ts.map +1 -1
  31. package/dist/lib/agents/developer.agent.d.ts +31 -0
  32. package/dist/lib/agents/developer.agent.d.ts.map +1 -0
  33. package/dist/lib/agents/question.agent.d.ts +1 -1
  34. package/dist/lib/agents/question.agent.d.ts.map +1 -1
  35. package/dist/lib/agents/sql.agent.d.ts +14 -32
  36. package/dist/lib/agents/sql.agent.d.ts.map +1 -1
  37. package/dist/lib/agents/text2sql.agent.d.ts.map +1 -1
  38. package/dist/lib/checkpoint.d.ts.map +1 -1
  39. package/dist/lib/sql.d.ts +42 -0
  40. package/dist/lib/sql.d.ts.map +1 -1
  41. package/dist/lib/synthesis/extractors/sql-extractor.d.ts.map +1 -1
  42. package/dist/lib/synthesis/index.js +267 -164
  43. package/dist/lib/synthesis/index.js.map +3 -3
  44. package/dist/lib/synthesis/synthesizers/breadth-evolver.d.ts.map +1 -1
  45. package/dist/lib/synthesis/synthesizers/depth-evolver.d.ts.map +1 -1
  46. package/dist/lib/synthesis/synthesizers/schema-synthesizer.d.ts.map +1 -1
  47. package/dist/lib/synthesis/synthesizers/styles.d.ts +2 -2
  48. package/dist/lib/synthesis/synthesizers/styles.d.ts.map +1 -1
  49. package/dist/lib/teach/teachings.d.ts.map +1 -1
  50. package/package.json +9 -3
package/dist/index.js CHANGED
@@ -149,64 +149,58 @@ function getTablesWithRelated(allTables, relationships, filter) {
149
149
  return Array.from(result);
150
150
  }
151
151
 
152
- // packages/text2sql/src/lib/agents/suggestions.agents.ts
152
+ // packages/text2sql/src/lib/agents/developer.agent.ts
153
+ import { groq as groq3 } from "@ai-sdk/groq";
154
+ import { tool } from "ai";
155
+ import dedent2 from "dedent";
156
+ import z3 from "zod";
157
+ import { agent as agent3, generate as generate2, toState } from "@deepagents/agent";
158
+ import { scratchpad_tool } from "@deepagents/toolbox";
159
+
160
+ // packages/text2sql/src/lib/agents/explainer.agent.ts
153
161
  import { groq } from "@ai-sdk/groq";
154
162
  import dedent from "dedent";
155
163
  import z from "zod";
156
- import { agent, thirdPersonPrompt } from "@deepagents/agent";
157
- var suggestionsAgent = agent({
158
- name: "text2sql-suggestions",
164
+ import { agent } from "@deepagents/agent";
165
+ var explainerAgent = agent({
166
+ name: "explainer",
159
167
  model: groq("openai/gpt-oss-20b"),
160
- output: z.object({
161
- suggestions: z.array(
162
- z.object({
163
- question: z.string().describe("A complex, high-impact business question."),
164
- sql: z.string().describe("The SQL statement needed to answer the question."),
165
- businessValue: z.string().describe("Why the question matters to stakeholders.")
166
- })
167
- ).min(1).max(5).describe("A set of up to two advanced question + SQL pairs.")
168
- }),
169
- prompt: (state) => {
170
- return dedent`
171
- ${thirdPersonPrompt()}
172
-
173
- <identity>
174
- You are a senior analytics strategist who proposes ambitious business questions
175
- and drafts the SQL needed to answer them. You specialize in identifying ideas
176
- that combine multiple tables, apply segmentation or time analysis, and surface
177
- metrics that drive executive decisions.
178
- </identity>
179
-
180
-
181
- <instructions>
182
- - Recommend one or two UNIQUE questions that go beyond simple counts or listings.
183
- - Favor questions that require joins, aggregates, time comparisons, cohort analysis,
184
- or window functions.
185
- - For each question, explain the business reason stakeholders care about it.
186
- - Provide the complete SQL query that could answer the question in the given schema.
187
- - Keep result sets scoped with LIMIT clauses (max 50 rows) when returning raw rows.
188
- - Ensure table/column names match the provided schema exactly.
189
- - Use columns marked [LowCardinality: ...] to identify meaningful categorical filters or segmentations.
190
- - Leverage table [rows / size] hints to determine whether to aggregate (large tables) or inspect detailed data (tiny tables).
191
- - Reference PK/Indexed annotations and the Indexes list to recommend queries that use efficient join/filter paths.
192
- - Column annotations may expose ranges/null percentages—use them to suggest realistic thresholds or quality checks.
193
- - Consult <relationship_examples> to anchor your recommendations in the actual join paths between tables.
194
- - Output only information grounded in the schema/context provided.
195
- </instructions>
168
+ prompt: (state) => dedent`
169
+ You are an expert SQL tutor.
170
+ Explain the following SQL query in plain English to a non-technical user.
171
+ Focus on the intent and logic, not the syntax.
196
172
 
197
- <response-format>
198
- Return valid JSON that satisfies the defined output schema.
199
- </response-format>
200
- `;
201
- }
173
+ <sql>
174
+ ${state?.sql}
175
+ </sql>
176
+ `,
177
+ output: z.object({
178
+ explanation: z.string().describe("The explanation of the SQL query.")
179
+ })
202
180
  });
203
181
 
204
- // packages/text2sql/src/lib/agents/text2sql.agent.ts
182
+ // packages/text2sql/src/lib/agents/sql.agent.ts
205
183
  import { groq as groq2 } from "@ai-sdk/groq";
206
- import { tool } from "ai";
184
+ import {
185
+ APICallError,
186
+ JSONParseError,
187
+ NoContentGeneratedError,
188
+ NoObjectGeneratedError,
189
+ NoOutputGeneratedError,
190
+ TypeValidationError,
191
+ defaultSettingsMiddleware,
192
+ wrapLanguageModel
193
+ } from "ai";
194
+ import { Console } from "node:console";
195
+ import { createWriteStream } from "node:fs";
196
+ import pRetry from "p-retry";
207
197
  import z2 from "zod";
208
- import { agent as agent2, toState } from "@deepagents/agent";
209
- import { scratchpad_tool } from "@deepagents/toolbox";
198
+ import {
199
+ agent as agent2,
200
+ generate,
201
+ toOutput,
202
+ user
203
+ } from "@deepagents/agent";
210
204
 
211
205
  // packages/text2sql/src/lib/teach/xml.ts
212
206
  function wrapBlock(tag, children) {
@@ -581,6 +575,384 @@ function toTeachables(generated) {
581
575
  });
582
576
  }
583
577
 
578
+ // packages/text2sql/src/lib/agents/sql.agent.ts
579
+ var logger = new Console({
580
+ stdout: createWriteStream("./sql-agent.log", { flags: "a" }),
581
+ stderr: createWriteStream("./sql-agent-error.log", { flags: "a" }),
582
+ inspectOptions: { depth: null }
583
+ });
584
+ var RETRY_TEMPERATURES = [0, 0.2, 0.3];
585
+ var sqlQueryAgent = agent2({
586
+ name: "text2sql",
587
+ model: groq2("openai/gpt-oss-20b"),
588
+ logging: process.env.AGENT_LOGGING === "true",
589
+ output: z2.union([
590
+ z2.object({
591
+ sql: z2.string().describe("The SQL query that answers the question"),
592
+ reasoning: z2.string().optional().describe("The reasoning steps taken to generate the SQL")
593
+ }),
594
+ z2.object({
595
+ error: z2.string().describe(
596
+ "Error message explaining why the question cannot be answered with the given schema"
597
+ )
598
+ })
599
+ ]),
600
+ prompt: (state) => {
601
+ return `
602
+ ${state?.teachings || ""}
603
+ ${state?.introspection || ""}
604
+ `;
605
+ }
606
+ });
607
+ function extractSql(output) {
608
+ const match = output.match(/```sql\n?([\s\S]*?)```/);
609
+ return match ? match[1].trim() : output.trim();
610
+ }
611
+ var marker = Symbol("SQLValidationError");
612
+ var SQLValidationError = class _SQLValidationError extends Error {
613
+ [marker];
614
+ constructor(message) {
615
+ super(message);
616
+ this.name = "SQLValidationError";
617
+ this[marker] = true;
618
+ }
619
+ static isInstance(error) {
620
+ return error instanceof _SQLValidationError && error[marker] === true;
621
+ }
622
+ };
623
+ var UnanswerableSQLError = class _UnanswerableSQLError extends Error {
624
+ constructor(message) {
625
+ super(message);
626
+ this.name = "UnanswerableSQLError";
627
+ }
628
+ static isInstance(error) {
629
+ return error instanceof _UnanswerableSQLError;
630
+ }
631
+ };
632
+ async function toSql(options) {
633
+ const { maxRetries = 3 } = options;
634
+ return withRetry(
635
+ async (attemptNumber, errors, attempts) => {
636
+ const agentInstance = sqlQueryAgent.clone({
637
+ model: wrapLanguageModel({
638
+ model: options.model ?? sqlQueryAgent.model,
639
+ middleware: defaultSettingsMiddleware({
640
+ settings: {
641
+ temperature: RETRY_TEMPERATURES[attemptNumber - 1] ?? 0.3,
642
+ topP: 1
643
+ }
644
+ })
645
+ })
646
+ });
647
+ const messages = errors.length ? [
648
+ user(options.input),
649
+ user(
650
+ `<validation_error>Your previous SQL query had the following error: ${errors.at(-1)?.message}. Please fix the query.</validation_error>`
651
+ )
652
+ ] : [user(options.input)];
653
+ const output = await toOutput(
654
+ generate(agentInstance, messages, {
655
+ introspection: options.introspection,
656
+ teachings: toInstructions(
657
+ "instructions",
658
+ persona({
659
+ name: "Freya",
660
+ role: "You are an expert SQL query generator. You translate natural language questions into precise, efficient SQL queries based on the provided database schema."
661
+ }),
662
+ ...options.instructions
663
+ )
664
+ })
665
+ );
666
+ if ("error" in output) {
667
+ throw new UnanswerableSQLError(output.error);
668
+ }
669
+ const sql = extractSql(output.sql);
670
+ const validationError = await options.adapter.validate(sql);
671
+ if (validationError) {
672
+ throw new SQLValidationError(validationError);
673
+ }
674
+ return {
675
+ attempts,
676
+ sql,
677
+ errors: errors.length ? errors.map(formatErrorMessage) : void 0
678
+ };
679
+ },
680
+ { retries: maxRetries - 1 }
681
+ );
682
+ }
683
+ function formatErrorMessage(error) {
684
+ if (APICallError.isInstance(error)) {
685
+ if (error.message.startsWith("Failed to validate JSON")) {
686
+ return `Schema validation failed: ${error.message}`;
687
+ }
688
+ return error.message;
689
+ }
690
+ if (SQLValidationError.isInstance(error)) {
691
+ return `SQL Validation Error: ${error.message}`;
692
+ }
693
+ return error.message;
694
+ }
695
+ async function withRetry(computation, options = { retries: 3 }) {
696
+ const errors = [];
697
+ let attempts = 0;
698
+ return pRetry(
699
+ (attemptNumber) => {
700
+ return computation(attemptNumber, errors, ++attempts);
701
+ },
702
+ {
703
+ retries: options.retries,
704
+ shouldRetry: (context2) => {
705
+ if (UnanswerableSQLError.isInstance(context2.error)) {
706
+ return false;
707
+ }
708
+ if (SQLValidationError.isInstance(context2.error)) {
709
+ return true;
710
+ }
711
+ console.log({
712
+ NoObjectGeneratedError: NoObjectGeneratedError.isInstance(
713
+ context2.error
714
+ ),
715
+ NoOutputGeneratedError: NoOutputGeneratedError.isInstance(
716
+ context2.error
717
+ ),
718
+ APICallError: APICallError.isInstance(context2.error),
719
+ JSONParseError: JSONParseError.isInstance(context2.error),
720
+ TypeValidationError: TypeValidationError.isInstance(context2.error),
721
+ NoContentGeneratedError: NoContentGeneratedError.isInstance(
722
+ context2.error
723
+ )
724
+ });
725
+ return APICallError.isInstance(context2.error) || JSONParseError.isInstance(context2.error) || TypeValidationError.isInstance(context2.error) || NoObjectGeneratedError.isInstance(context2.error) || NoOutputGeneratedError.isInstance(context2.error) || NoContentGeneratedError.isInstance(context2.error);
726
+ },
727
+ onFailedAttempt(context2) {
728
+ logger.error(`toSQL`, context2.error);
729
+ console.log(
730
+ `Attempt ${context2.attemptNumber} failed. There are ${context2.retriesLeft} retries left.`
731
+ );
732
+ errors.push(context2.error);
733
+ }
734
+ }
735
+ );
736
+ }
737
+
738
+ // packages/text2sql/src/lib/agents/developer.agent.ts
739
+ var tools = {
740
+ /**
741
+ * Generate SQL from natural language question.
742
+ * Uses the toSql function with retry logic and validation.
743
+ */
744
+ generate_sql: tool({
745
+ description: dedent2`
746
+ Generate a validated SQL query from a natural language question.
747
+ The query is automatically validated against the database schema.
748
+ Use this when the user asks a question that requires data retrieval.
749
+
750
+ Returns the SQL query along with generation metadata (attempts, any errors encountered).
751
+ `,
752
+ inputSchema: z3.object({
753
+ question: z3.string().min(1).describe("The natural language question to convert to SQL")
754
+ }),
755
+ execute: async ({ question }, options) => {
756
+ const state = toState(options);
757
+ try {
758
+ const result = await toSql({
759
+ input: question,
760
+ adapter: state.adapter,
761
+ introspection: state.introspection,
762
+ instructions: state.instructions
763
+ });
764
+ return {
765
+ success: true,
766
+ sql: result.sql,
767
+ attempts: result.attempts,
768
+ errors: result.errors
769
+ };
770
+ } catch (error) {
771
+ return {
772
+ success: false,
773
+ error: error instanceof Error ? error.message : String(error)
774
+ };
775
+ }
776
+ }
777
+ }),
778
+ /**
779
+ * Get plain-English explanation of a SQL query.
780
+ */
781
+ explain_sql: tool({
782
+ description: dedent2`
783
+ Get a plain-English explanation of a SQL query.
784
+ Use this to help the user understand what a query does.
785
+
786
+ The explanation focuses on intent and logic, not syntax.
787
+ `,
788
+ inputSchema: z3.object({
789
+ sql: z3.string().min(1).describe("The SQL query to explain")
790
+ }),
791
+ execute: async ({ sql }) => {
792
+ const { experimental_output } = await generate2(explainerAgent, [], {
793
+ sql
794
+ });
795
+ return { explanation: experimental_output.explanation };
796
+ }
797
+ }),
798
+ /**
799
+ * Show database schema introspection.
800
+ */
801
+ show_schema: tool({
802
+ description: dedent2`
803
+ Display the database schema introspection.
804
+ Use this when the user wants to see available tables, columns, or relationships.
805
+
806
+ Optionally filter by table name to reduce output.
807
+ `,
808
+ inputSchema: z3.object({
809
+ table: z3.string().optional().describe(
810
+ "Optional: filter to show only a specific table. If omitted, shows full schema."
811
+ )
812
+ }),
813
+ execute: async ({ table }, options) => {
814
+ const state = toState(options);
815
+ if (!table) {
816
+ return { schema: state.introspection };
817
+ }
818
+ const lines = state.introspection.split("\n");
819
+ const tableLines = [];
820
+ let inTable = false;
821
+ let depth = 0;
822
+ for (const line of lines) {
823
+ const lowerLine = line.toLowerCase();
824
+ if (lowerLine.includes(`name="${table.toLowerCase()}"`) || lowerLine.includes(`table="${table.toLowerCase()}"`)) {
825
+ inTable = true;
826
+ depth = 1;
827
+ tableLines.push(line);
828
+ continue;
829
+ }
830
+ if (inTable) {
831
+ tableLines.push(line);
832
+ if (line.includes("</")) {
833
+ depth--;
834
+ }
835
+ if (line.includes("<") && !line.includes("</") && !line.includes("/>")) {
836
+ depth++;
837
+ }
838
+ if (depth <= 0) {
839
+ break;
840
+ }
841
+ }
842
+ }
843
+ if (tableLines.length === 0) {
844
+ return {
845
+ schema: `Table "${table}" not found in schema. Use show_schema without a table filter to see all available tables.`
846
+ };
847
+ }
848
+ return { schema: tableLines.join("\n") };
849
+ }
850
+ }),
851
+ /**
852
+ * Developer scratchpad for notes and reasoning.
853
+ */
854
+ scratchpad: scratchpad_tool
855
+ };
856
+ var developerAgent = agent3({
857
+ model: groq3("gpt-oss-20b"),
858
+ tools,
859
+ name: "developer_agent",
860
+ prompt: (state) => {
861
+ return dedent2`
862
+ You are an expert SQL developer assistant helping power users build and refine queries.
863
+
864
+ ## Your Capabilities
865
+
866
+ You have access to the following tools:
867
+
868
+ 1. **generate_sql**: Convert natural language questions to validated SQL queries
869
+ - Automatically validates against the database schema
870
+ - Returns generation metadata (attempts, errors if any)
871
+
872
+ 2. **explain_sql**: Get a plain-English explanation of any SQL query
873
+ - Helps users understand complex queries
874
+ - Focuses on intent and logic, not syntax
875
+
876
+ 3. **show_schema**: Display database schema information
877
+ - Can show full schema or filter by table name
878
+ - Use to explore available tables and columns
879
+
880
+ 4. **scratchpad**: Record your reasoning and notes
881
+
882
+ ## Guidelines
883
+
884
+ - Be transparent: show the SQL you generate before explaining it
885
+ - Be precise: provide exact column names and table references
886
+ - Be helpful: suggest refinements and alternatives when appropriate
887
+ - Support both natural language questions AND raw SQL input
888
+ - When validating user SQL, explain any errors clearly
889
+ - Use show_schema proactively when you need to verify table/column names
890
+
891
+ ${state?.teachings || ""}
892
+ ${state?.introspection || ""}
893
+ `;
894
+ }
895
+ });
896
+
897
+ // packages/text2sql/src/lib/agents/suggestions.agents.ts
898
+ import { groq as groq4 } from "@ai-sdk/groq";
899
+ import dedent3 from "dedent";
900
+ import z4 from "zod";
901
+ import { agent as agent4, thirdPersonPrompt } from "@deepagents/agent";
902
+ var suggestionsAgent = agent4({
903
+ name: "text2sql-suggestions",
904
+ model: groq4("openai/gpt-oss-20b"),
905
+ output: z4.object({
906
+ suggestions: z4.array(
907
+ z4.object({
908
+ question: z4.string().describe("A complex, high-impact business question."),
909
+ sql: z4.string().describe("The SQL statement needed to answer the question."),
910
+ businessValue: z4.string().describe("Why the question matters to stakeholders.")
911
+ })
912
+ ).min(1).max(5).describe("A set of up to two advanced question + SQL pairs.")
913
+ }),
914
+ prompt: (state) => {
915
+ return dedent3`
916
+ ${thirdPersonPrompt()}
917
+
918
+ <identity>
919
+ You are a senior analytics strategist who proposes ambitious business questions
920
+ and drafts the SQL needed to answer them. You specialize in identifying ideas
921
+ that combine multiple tables, apply segmentation or time analysis, and surface
922
+ metrics that drive executive decisions.
923
+ </identity>
924
+
925
+
926
+ <instructions>
927
+ - Recommend one or two UNIQUE questions that go beyond simple counts or listings.
928
+ - Favor questions that require joins, aggregates, time comparisons, cohort analysis,
929
+ or window functions.
930
+ - For each question, explain the business reason stakeholders care about it.
931
+ - Provide the complete SQL query that could answer the question in the given schema.
932
+ - Keep result sets scoped with LIMIT clauses (max 50 rows) when returning raw rows.
933
+ - Ensure table/column names match the provided schema exactly.
934
+ - Use columns marked [LowCardinality: ...] to identify meaningful categorical filters or segmentations.
935
+ - Leverage table [rows / size] hints to determine whether to aggregate (large tables) or inspect detailed data (tiny tables).
936
+ - Reference PK/Indexed annotations and the Indexes list to recommend queries that use efficient join/filter paths.
937
+ - Column annotations may expose ranges/null percentages—use them to suggest realistic thresholds or quality checks.
938
+ - Consult <relationship_examples> to anchor your recommendations in the actual join paths between tables.
939
+ - Output only information grounded in the schema/context provided.
940
+ </instructions>
941
+
942
+ <response-format>
943
+ Return valid JSON that satisfies the defined output schema.
944
+ </response-format>
945
+ `;
946
+ }
947
+ });
948
+
949
+ // packages/text2sql/src/lib/agents/text2sql.agent.ts
950
+ import { groq as groq5 } from "@ai-sdk/groq";
951
+ import { tool as tool2 } from "ai";
952
+ import z5 from "zod";
953
+ import { agent as agent5, toState as toState2 } from "@deepagents/agent";
954
+ import { scratchpad_tool as scratchpad_tool2 } from "@deepagents/toolbox";
955
+
584
956
  // packages/text2sql/src/lib/memory/memory.prompt.ts
585
957
  var memory_prompt_default = toInstructions(
586
958
  "memory_guidelines",
@@ -710,14 +1082,14 @@ var memory_prompt_default = toInstructions(
710
1082
  );
711
1083
 
712
1084
  // packages/text2sql/src/lib/agents/text2sql.agent.ts
713
- var tools = {
714
- validate_query: tool({
1085
+ var tools2 = {
1086
+ validate_query: tool2({
715
1087
  description: `Validate SQL query syntax before execution. Use this to check if your SQL is valid before running db_query. This helps catch errors early and allows you to correct the query if needed.`,
716
- inputSchema: z2.object({
717
- sql: z2.string().describe("The SQL query to validate.")
1088
+ inputSchema: z5.object({
1089
+ sql: z5.string().describe("The SQL query to validate.")
718
1090
  }),
719
1091
  execute: async ({ sql }, options) => {
720
- const state = toState(options);
1092
+ const state = toState2(options);
721
1093
  const result = await state.adapter.validate(sql);
722
1094
  if (typeof result === "string") {
723
1095
  return `Validation Error: ${result}`;
@@ -725,22 +1097,22 @@ var tools = {
725
1097
  return "Query is valid.";
726
1098
  }
727
1099
  }),
728
- get_sample_rows: tool({
1100
+ get_sample_rows: tool2({
729
1101
  description: `Sample rows from a table to understand data formatting, codes, and value patterns. Use BEFORE writing queries when:
730
1102
  - Column types in schema don't reveal format (e.g., "status" could be 'active'/'inactive' or 1/0)
731
1103
  - Date/time formats are unclear (ISO, Unix timestamp, locale-specific)
732
1104
  - You need to understand lookup table codes or enum values
733
1105
  - Column names are ambiguous (e.g., "type", "category", "code")`,
734
- inputSchema: z2.object({
735
- tableName: z2.string().describe("The name of the table to sample."),
736
- columns: z2.array(z2.string()).optional().describe(
1106
+ inputSchema: z5.object({
1107
+ tableName: z5.string().describe("The name of the table to sample."),
1108
+ columns: z5.array(z5.string()).optional().describe(
737
1109
  "Specific columns to sample. If omitted, samples all columns."
738
1110
  ),
739
- limit: z2.number().min(1).max(10).default(3).optional().describe("Number of rows to sample (1-10, default 3).")
1111
+ limit: z5.number().min(1).max(10).default(3).optional().describe("Number of rows to sample (1-10, default 3).")
740
1112
  }),
741
1113
  execute: ({ tableName, columns, limit = 3 }, options) => {
742
1114
  const safeLimit = Math.min(Math.max(1, limit), 10);
743
- const state = toState(options);
1115
+ const state = toState2(options);
744
1116
  const sql = state.adapter.buildSampleRowsQuery(
745
1117
  tableName,
746
1118
  columns,
@@ -749,13 +1121,13 @@ var tools = {
749
1121
  return state.adapter.execute(sql);
750
1122
  }
751
1123
  }),
752
- db_query: tool({
1124
+ db_query: tool2({
753
1125
  description: `Internal tool to fetch data from the store's database. Write a SQL query to retrieve the information needed to answer the user's question. The results will be returned as data that you can then present to the user in natural language.`,
754
- inputSchema: z2.object({
755
- reasoning: z2.string().describe(
1126
+ inputSchema: z5.object({
1127
+ reasoning: z5.string().describe(
756
1128
  "Your reasoning for why this SQL query is relevant to the user request."
757
1129
  ),
758
- sql: z2.string().min(1, { message: "SQL query cannot be empty." }).refine(
1130
+ sql: z5.string().min(1, { message: "SQL query cannot be empty." }).refine(
759
1131
  (sql) => sql.trim().toUpperCase().startsWith("SELECT") || sql.trim().toUpperCase().startsWith("WITH"),
760
1132
  {
761
1133
  message: "Only read-only SELECT or WITH queries are allowed."
@@ -763,11 +1135,11 @@ var tools = {
763
1135
  ).describe("The SQL query to execute against the database.")
764
1136
  }),
765
1137
  execute: ({ sql }, options) => {
766
- const state = toState(options);
1138
+ const state = toState2(options);
767
1139
  return state.adapter.execute(sql);
768
1140
  }
769
1141
  }),
770
- scratchpad: scratchpad_tool
1142
+ scratchpad: scratchpad_tool2
771
1143
  };
772
1144
  var userMemoryTypes = [
773
1145
  "identity",
@@ -776,61 +1148,61 @@ var userMemoryTypes = [
776
1148
  "context",
777
1149
  "correction"
778
1150
  ];
779
- var userMemorySchema = z2.discriminatedUnion("type", [
780
- z2.object({
781
- type: z2.literal("identity"),
782
- description: z2.string().describe("The user's identity: role or/and name")
1151
+ var userMemorySchema = z5.discriminatedUnion("type", [
1152
+ z5.object({
1153
+ type: z5.literal("identity"),
1154
+ description: z5.string().describe("The user's identity: role or/and name")
783
1155
  }),
784
- z2.object({
785
- type: z2.literal("alias"),
786
- term: z2.string().describe("The term the user uses"),
787
- meaning: z2.string().describe("What the user means by this term")
1156
+ z5.object({
1157
+ type: z5.literal("alias"),
1158
+ term: z5.string().describe("The term the user uses"),
1159
+ meaning: z5.string().describe("What the user means by this term")
788
1160
  }),
789
- z2.object({
790
- type: z2.literal("preference"),
791
- aspect: z2.string().describe("What aspect of output this preference applies to"),
792
- value: z2.string().describe("The user's preference")
1161
+ z5.object({
1162
+ type: z5.literal("preference"),
1163
+ aspect: z5.string().describe("What aspect of output this preference applies to"),
1164
+ value: z5.string().describe("The user's preference")
793
1165
  }),
794
- z2.object({
795
- type: z2.literal("context"),
796
- description: z2.string().describe("What the user is currently working on")
1166
+ z5.object({
1167
+ type: z5.literal("context"),
1168
+ description: z5.string().describe("What the user is currently working on")
797
1169
  }),
798
- z2.object({
799
- type: z2.literal("correction"),
800
- subject: z2.string().describe("What was misunderstood"),
801
- clarification: z2.string().describe("The correct understanding")
1170
+ z5.object({
1171
+ type: z5.literal("correction"),
1172
+ subject: z5.string().describe("What was misunderstood"),
1173
+ clarification: z5.string().describe("The correct understanding")
802
1174
  })
803
1175
  ]);
804
1176
  var memoryTools = {
805
- remember_memory: tool({
1177
+ remember_memory: tool2({
806
1178
  description: "Store something about the user for future conversations. Use silently when user shares facts, preferences, vocabulary, corrections, or context.",
807
- inputSchema: z2.object({ memory: userMemorySchema }),
1179
+ inputSchema: z5.object({ memory: userMemorySchema }),
808
1180
  execute: async ({ memory }, options) => {
809
- const state = toState(
1181
+ const state = toState2(
810
1182
  options
811
1183
  );
812
1184
  await state.memory.remember(state.userId, memory);
813
1185
  return "Remembered.";
814
1186
  }
815
1187
  }),
816
- forget_memory: tool({
1188
+ forget_memory: tool2({
817
1189
  description: "Forget a specific memory. Use when user asks to remove something.",
818
- inputSchema: z2.object({
819
- id: z2.string().describe("The ID of the teachable to forget")
1190
+ inputSchema: z5.object({
1191
+ id: z5.string().describe("The ID of the teachable to forget")
820
1192
  }),
821
1193
  execute: async ({ id }, options) => {
822
- const state = toState(options);
1194
+ const state = toState2(options);
823
1195
  await state.memory.forget(id);
824
1196
  return "Forgotten.";
825
1197
  }
826
1198
  }),
827
- recall_memory: tool({
1199
+ recall_memory: tool2({
828
1200
  description: "List stored memories for the current user. Use when user asks what you remember about them or wants to see their stored preferences.",
829
- inputSchema: z2.object({
830
- type: z2.enum(userMemoryTypes).optional().catch(void 0).describe("Optional: filter by memory type")
1201
+ inputSchema: z5.object({
1202
+ type: z5.enum(userMemoryTypes).optional().catch(void 0).describe("Optional: filter by memory type")
831
1203
  }),
832
1204
  execute: async ({ type }, options) => {
833
- const state = toState(
1205
+ const state = toState2(
834
1206
  options
835
1207
  );
836
1208
  const memories = await state.memory.recall(state.userId, type);
@@ -845,30 +1217,117 @@ var memoryTools = {
845
1217
  }));
846
1218
  }
847
1219
  }),
848
- update_memory: tool({
1220
+ update_memory: tool2({
849
1221
  description: "Update an existing memory. Use when user wants to modify something you previously stored.",
850
- inputSchema: z2.object({
1222
+ inputSchema: z5.object({
851
1223
  memory: userMemorySchema,
852
- id: z2.string().describe("The ID of the memory to update")
1224
+ id: z5.string().describe("The ID of the memory to update")
853
1225
  }),
854
1226
  execute: async ({ id, memory }, options) => {
855
- const state = toState(options);
1227
+ const state = toState2(options);
856
1228
  await state.memory.update(id, memory);
857
1229
  return "Updated.";
858
1230
  }
859
1231
  })
860
1232
  };
861
- var t_a_g = agent2({
862
- model: groq2("openai/gpt-oss-20b"),
863
- tools,
1233
+ var chainOfThoughtPrompt = `
1234
+ ## Query Reasoning Process
1235
+
1236
+ Let's think step by step before writing SQL:
1237
+
1238
+ 1. **Schema Link**: Which tables and columns are relevant? Verify they exist in the schema.
1239
+ 2. **Join Path**: If multiple tables, what relationships connect them?
1240
+ 3. **Filters**: What WHERE conditions are needed?
1241
+ 4. **Aggregation**: Is COUNT, SUM, AVG, GROUP BY, or HAVING required?
1242
+ 5. **Output**: What columns to SELECT and any ORDER BY or LIMIT?
1243
+ 6. **Verify**: Do all referenced tables and columns exist in the schema above?
1244
+
1245
+ For simple queries, steps 2-4 may not apply\u2014skip them.
1246
+
1247
+ For complex queries requiring multiple data points, decompose into sub-questions:
1248
+ - Break the question into simpler parts (Q1, Q2, ...)
1249
+ - Determine if each part needs a subquery or CTE
1250
+ - Combine the parts into the final query
1251
+
1252
+ Keep reasoning brief. Verbose explanations cause errors.
1253
+ `;
1254
+ var fewShotExamples = `
1255
+ ## Examples
1256
+
1257
+ ### Example 1: Simple Filter
1258
+ Question: "How many records in table_a have column_x equal to 'value'?"
1259
+ Reasoning:
1260
+ - Schema Link: table_a, column_x
1261
+ - Filters: column_x = 'value'
1262
+ - Aggregation: COUNT(*)
1263
+ SQL: SELECT COUNT(*) FROM table_a WHERE column_x = 'value'
1264
+
1265
+ ### Example 2: JOIN Query
1266
+ Question: "Show column_y from table_b for each record in table_a where column_x is 'value'"
1267
+ Reasoning:
1268
+ - Schema Link: table_a (column_x, id), table_b (column_y, fk_a)
1269
+ - Join Path: table_a.id \u2192 table_b.fk_a
1270
+ - Filters: column_x = 'value'
1271
+ - Output: column_y from table_b
1272
+ SQL: SELECT b.column_y FROM table_a a JOIN table_b b ON b.fk_a = a.id WHERE a.column_x = 'value'
1273
+
1274
+ ### Example 3: Aggregation with GROUP BY
1275
+ Question: "What is the total of column_y grouped by column_x?"
1276
+ Reasoning:
1277
+ - Schema Link: table_a (column_x, column_y)
1278
+ - Aggregation: SUM(column_y), GROUP BY column_x
1279
+ - Output: column_x, sum
1280
+ SQL: SELECT column_x, SUM(column_y) as total FROM table_a GROUP BY column_x
1281
+
1282
+ ### Example 4: Complex Aggregation
1283
+ Question: "Which values of column_x have more than 10 records, sorted by count descending?"
1284
+ Reasoning:
1285
+ - Schema Link: table_a (column_x)
1286
+ - Aggregation: COUNT(*), GROUP BY column_x, HAVING > 10
1287
+ - Output: column_x, count, ORDER BY count DESC
1288
+ SQL: SELECT column_x, COUNT(*) as cnt FROM table_a GROUP BY column_x HAVING COUNT(*) > 10 ORDER BY cnt DESC
1289
+
1290
+ ### Example 5: Subquery (Decomposition)
1291
+ Question: "Show records from table_a where column_y is above average"
1292
+ Reasoning:
1293
+ - Decompose:
1294
+ - Q1: What is the average of column_y?
1295
+ - Q2: Which records have column_y above that value?
1296
+ - Schema Link: table_a (column_y)
1297
+ - Filters: column_y > (result of Q1)
1298
+ - Output: all columns from matching records
1299
+ - Verify: table_a and column_y exist \u2713
1300
+ SQL: SELECT * FROM table_a WHERE column_y > (SELECT AVG(column_y) FROM table_a)
1301
+
1302
+ ### Example 6: Complex Multi-Join (Decomposition)
1303
+ Question: "Find the top 3 categories by total sales amount for orders placed last month"
1304
+ Reasoning:
1305
+ - Decompose:
1306
+ - Q1: Which orders were placed last month?
1307
+ - Q2: What is the total sales per category for those orders?
1308
+ - Q3: Which 3 categories have the highest totals?
1309
+ - Schema Link: orders (order_date, id), order_items (order_id, amount, product_id), products (id, category_id), categories (id, name)
1310
+ - Join Path: orders \u2192 order_items \u2192 products \u2192 categories
1311
+ - Filters: order_date within last month
1312
+ - Aggregation: SUM(amount), GROUP BY category
1313
+ - Output: category name, total, ORDER BY total DESC, LIMIT 3
1314
+ - Verify: all tables and columns exist \u2713
1315
+ SQL: SELECT c.name, SUM(oi.amount) as total FROM orders o JOIN order_items oi ON oi.order_id = o.id JOIN products p ON p.id = oi.product_id JOIN categories c ON c.id = p.category_id WHERE o.order_date >= DATE('now', '-1 month') GROUP BY c.id, c.name ORDER BY total DESC LIMIT 3
1316
+ `;
1317
+ var t_a_g = agent5({
1318
+ model: groq5("openai/gpt-oss-20b"),
1319
+ tools: tools2,
864
1320
  name: "text2sql",
865
1321
  prompt: (state) => {
866
1322
  const hasMemory = !!state?.memory;
867
1323
  return `
868
-
869
1324
  ${state?.teachings || ""}
870
1325
  ${state?.introspection || ""}
871
1326
 
1327
+ ${chainOfThoughtPrompt}
1328
+
1329
+ ${fewShotExamples}
1330
+
872
1331
  ${hasMemory ? memory_prompt_default : ""}
873
1332
  `;
874
1333
  }
@@ -939,9 +1398,7 @@ var Checkpoint = class _Checkpoint {
939
1398
  * @param step - Unique identifier for this checkpoint point
940
1399
  */
941
1400
  point(step) {
942
- if (!this.points[step]) {
943
- this.points[step] = { committed: false, entries: [] };
944
- }
1401
+ this.points[step] ??= { committed: false, entries: [] };
945
1402
  return new Point(this.points[step], () => this.save());
946
1403
  }
947
1404
  /**
@@ -1279,156 +1736,338 @@ import {
1279
1736
  } from "ai";
1280
1737
  import { v7 as v72 } from "uuid";
1281
1738
  import {
1282
- generate as generate4,
1739
+ generate as generate5,
1283
1740
  stream,
1284
1741
  user as user4
1285
1742
  } from "@deepagents/agent";
1286
1743
 
1287
- // packages/text2sql/src/lib/agents/chat1.agent.ts
1288
- import { groq as groq4 } from "@ai-sdk/groq";
1289
- import { tool as tool2 } from "ai";
1290
- import z4 from "zod";
1291
- import { agent as agent4, toState as toState2 } from "@deepagents/agent";
1292
- import { scratchpad_tool as scratchpad_tool2 } from "@deepagents/toolbox";
1744
+ // packages/text2sql/src/lib/agents/bi.agent.ts
1745
+ import { groq as groq6 } from "@ai-sdk/groq";
1746
+ import { tool as tool3 } from "ai";
1747
+ import dedent4 from "dedent";
1748
+ import z6 from "zod";
1749
+ import { agent as agent6, toState as toState3 } from "@deepagents/agent";
1750
+ import { scratchpad_tool as scratchpad_tool3 } from "@deepagents/toolbox";
1751
+ var tools3 = {
1752
+ /**
1753
+ * Validate SQL query syntax without executing.
1754
+ * Use this to verify queries are correct before embedding in dashboard components.
1755
+ */
1756
+ validate_query: tool3({
1757
+ description: dedent4`
1758
+ Validate SQL query syntax before embedding in dashboard components.
1759
+ Use this to verify your queries are syntactically correct and reference valid tables/columns.
1293
1760
 
1294
- // packages/text2sql/src/lib/agents/sql.agent.ts
1295
- import { groq as groq3 } from "@ai-sdk/groq";
1296
- import { defaultSettingsMiddleware, wrapLanguageModel } from "ai";
1297
- import z3 from "zod";
1298
- import { agent as agent3, generate, user } from "@deepagents/agent";
1299
- var RETRY_TEMPERATURES = [0, 0.2, 0.3];
1300
- var sqlQueryAgent = agent3({
1301
- name: "text2sql",
1302
- model: groq3("openai/gpt-oss-20b"),
1303
- logging: process.env.AGENT_LOGGING === "true",
1304
- output: z3.union([
1305
- z3.object({
1306
- sql: z3.string().describe("The SQL query that answers the question"),
1307
- reasoning: z3.string().optional().describe("The reasoning steps taken to generate the SQL")
1761
+ This tool does NOT execute the query or return data.
1762
+ Only SELECT or WITH statements are allowed.
1763
+ `,
1764
+ inputSchema: z6.object({
1765
+ reasoning: z6.string().describe(
1766
+ "Why this query helps understand the data for dashboard design."
1767
+ ),
1768
+ sql: z6.string().min(1, { message: "SQL query cannot be empty." }).refine(
1769
+ (sql) => sql.trim().toUpperCase().startsWith("SELECT") || sql.trim().toUpperCase().startsWith("WITH"),
1770
+ {
1771
+ message: "Only read-only SELECT or WITH queries are allowed."
1772
+ }
1773
+ ).describe("The SQL query to validate.")
1308
1774
  }),
1309
- z3.object({
1310
- error: z3.string().describe(
1311
- "Error message explaining why the question cannot be answered with the given schema"
1312
- )
1313
- })
1314
- ]),
1315
- prompt: (state) => {
1316
- return `
1317
- ${state?.teachings || ""}
1318
- ${state?.introspection || ""}
1319
- `;
1320
- }
1321
- });
1322
- function extractSql(output) {
1323
- const match = output.match(/```sql\n?([\s\S]*?)```/);
1324
- return match ? match[1].trim() : output.trim();
1325
- }
1326
- async function generateSql(params) {
1327
- const {
1328
- input,
1329
- model,
1330
- temperature,
1331
- introspection,
1332
- instructions,
1333
- previousError
1334
- } = params;
1335
- const agentInstance = sqlQueryAgent.clone({
1336
- model: wrapLanguageModel({
1337
- model,
1338
- middleware: defaultSettingsMiddleware({
1339
- settings: { temperature, topP: 1 }
1340
- })
1341
- })
1342
- });
1343
- const messages = previousError ? [
1344
- user(input),
1345
- user(
1346
- `<validation_error>Your previous SQL query had the following error: ${previousError}. Please fix the query.</validation_error>`
1347
- )
1348
- ] : [user(input)];
1349
- try {
1350
- const { experimental_output: output } = await generate(
1351
- agentInstance,
1352
- messages,
1353
- {
1354
- teachings: toInstructions(
1355
- "instructions",
1356
- persona({
1357
- name: "Freya",
1358
- role: "You are an expert SQL query generator. You translate natural language questions into precise, efficient SQL queries based on the provided database schema."
1359
- }),
1360
- ...instructions
1361
- ),
1362
- introspection
1775
+ execute: async ({ sql }, options) => {
1776
+ const state = toState3(options);
1777
+ const result = await state.adapter.validate(sql);
1778
+ if (typeof result === "string") {
1779
+ return { valid: false, error: result };
1363
1780
  }
1364
- );
1365
- if ("error" in output) {
1366
- return { success: false, error: output.error, isUnanswerable: true };
1367
- }
1368
- return { success: true, sql: extractSql(output.sql) };
1369
- } catch (error) {
1370
- if (error instanceof Error && (error.message.includes("Failed to validate JSON") || error.message.includes("response did not match schema"))) {
1371
- return {
1372
- success: false,
1373
- error: `Schema validation failed: ${error.message}`
1374
- };
1781
+ return { valid: true };
1375
1782
  }
1376
- throw error;
1377
- }
1378
- }
1379
- var sqlGenerators = {
1380
- generateSql
1783
+ }),
1784
+ /**
1785
+ * Record insights and reasoning during schema analysis and dashboard design.
1786
+ */
1787
+ scratchpad: scratchpad_tool3
1381
1788
  };
1382
- async function generateAndValidate(options, temperature, previousError) {
1383
- const result = await sqlGenerators.generateSql({
1384
- input: options.input,
1385
- model: options.model ?? sqlQueryAgent.model,
1386
- temperature,
1387
- introspection: options.introspection,
1388
- instructions: options.instructions,
1389
- previousError
1390
- });
1391
- if (!result.success) {
1392
- return {
1393
- ok: false,
1394
- error: result.error,
1395
- isUnanswerable: result.isUnanswerable
1396
- };
1397
- }
1398
- const validationError = await options.adapter.validate(result.sql);
1399
- if (validationError) {
1400
- return { ok: false, error: validationError };
1401
- }
1402
- return { ok: true, sql: result.sql };
1403
- }
1404
- async function toSql(options) {
1405
- const { maxRetries = 3 } = options;
1406
- const errors = [];
1407
- for (let attempt = 1; attempt <= maxRetries; attempt++) {
1408
- const temperature = RETRY_TEMPERATURES[attempt - 1] ?? 0.3;
1409
- const result = await generateAndValidate(
1410
- options,
1411
- temperature,
1412
- errors.at(-1)
1413
- );
1414
- if (result.ok) {
1415
- return {
1416
- sql: result.sql,
1417
- attempts: attempt,
1418
- errors: errors.length ? errors : void 0
1419
- };
1420
- }
1421
- if (result.isUnanswerable) {
1422
- return { sql: "", attempts: attempt, errors: [result.error] };
1423
- }
1424
- errors.push(result.error);
1789
+ var COMPONENTS_DOC = dedent4`
1790
+ ## Available Components
1791
+
1792
+ You output markdown with embedded HTML custom elements. Use kebab-case tags with closing tags.
1793
+
1794
+ ### Chart Components
1795
+
1796
+ #### Area Charts
1797
+ | Component | Required Props | Optional Props | Use Case |
1798
+ |-----------|----------------|----------------|----------|
1799
+ | \`<area-chart>\` | \`title\`, \`sql\` | \`x-key\`, \`y-key\`, \`variant\` | Cumulative values, trends with volume |
1800
+
1801
+ **Variants** (use \`variant\` prop):
1802
+ - \`default\` - Basic area with smooth curves
1803
+ - \`linear\` - Sharp-edged lines showing precise changes
1804
+ - \`step\` - Step-based segments for discrete data
1805
+ - \`stacked\` - Multiple series stacked on top of each other
1806
+ - \`stacked-expand\` - Normalized to 100% showing percentage contribution
1807
+ - \`gradient\` - Filled with gradient for visual depth
1808
+
1809
+ #### Bar Charts
1810
+ | Component | Required Props | Optional Props | Use Case |
1811
+ |-----------|----------------|----------------|----------|
1812
+ | \`<bar-chart>\` | \`title\`, \`sql\` | \`x-key\`, \`y-key\`, \`variant\`, \`orientation\` | Categorical comparisons, grouped data |
1813
+
1814
+ **Variants** (use \`variant\` prop):
1815
+ - \`default\` - Basic vertical bars
1816
+ - \`multiple\` - Multiple series side by side
1817
+ - \`stacked\` - Multiple series stacked
1818
+ - \`labeled\` - With value labels on bars
1819
+ - \`negative\` - Supports positive/negative values with conditional coloring
1820
+ - \`mixed\` - Different colors per category
1821
+
1822
+ **Orientation** (use \`orientation\` prop):
1823
+ - \`vertical\` (default) - Vertical bars
1824
+ - \`horizontal\` - Horizontal bars (good for long category names)
1825
+
1826
+ #### Line Charts
1827
+ | Component | Required Props | Optional Props | Use Case |
1828
+ |-----------|----------------|----------------|----------|
1829
+ | \`<line-chart>\` | \`title\`, \`sql\` | \`x-key\`, \`y-key\`, \`variant\` | Trends over time, continuous data |
1830
+
1831
+ **Variants** (use \`variant\` prop):
1832
+ - \`default\` - Smooth curved lines
1833
+ - \`linear\` - Straight lines between points
1834
+ - \`step\` - Step-based transitions
1835
+ - \`dots\` - Lines with visible data point markers
1836
+ - \`multiple\` - Multiple series for comparisons (A/B testing, etc.)
1837
+ - \`interactive\` - With metric switching capability
1838
+ - \`labeled\` - With value labels at each point
1839
+
1840
+ #### Pie & Donut Charts
1841
+ | Component | Required Props | Optional Props | Use Case |
1842
+ |-----------|----------------|----------------|----------|
1843
+ | \`<pie-chart>\` | \`title\`, \`sql\` | \`label-key\`, \`value-key\`, \`variant\` | Part-to-whole relationships, distributions |
1844
+ | \`<donut-chart>\` | \`title\`, \`sql\` | \`label-key\`, \`value-key\`, \`variant\` | Same as pie but with center space for text/KPI |
1845
+
1846
+ **Variants** (use \`variant\` prop):
1847
+ - \`default\` - Basic pie/donut
1848
+ - \`labeled\` - With labels on segments
1849
+ - \`legend\` - With external legend
1850
+ - \`interactive\` - With hover highlighting and selection
1851
+ - \`stacked\` - Multiple concentric rings for comparison
1852
+
1853
+ #### Radar Charts
1854
+ | Component | Required Props | Optional Props | Use Case |
1855
+ |-----------|----------------|----------------|----------|
1856
+ | \`<radar-chart>\` | \`title\`, \`sql\` | \`label-key\`, \`value-key\`, \`variant\` | Multi-dimensional comparisons, skill assessments |
1857
+
1858
+ **Variants** (use \`variant\` prop):
1859
+ - \`default\` - Basic radar with polygon grid
1860
+ - \`dots\` - With visible data point markers
1861
+ - \`filled\` - With filled area
1862
+ - \`multiple\` - Multiple series overlapping
1863
+ - \`circle\` - Circular grid instead of polygon
1864
+ - \`legend\` - With integrated legend
1865
+
1866
+ #### Radial Charts
1867
+ | Component | Required Props | Optional Props | Use Case |
1868
+ |-----------|----------------|----------------|----------|
1869
+ | \`<radial-chart>\` | \`title\`, \`sql\` | \`value-key\`, \`variant\` | Progress indicators, gauges, circular metrics |
1870
+
1871
+ **Variants** (use \`variant\` prop):
1872
+ - \`default\` - Basic radial bars from center outward
1873
+ - \`text\` - With centered value/caption text
1874
+ - \`shape\` - Gauge-style arc (not full circle)
1875
+ - \`stacked\` - Concentric arcs for multiple metrics
1876
+ - \`grid\` - With background grid rings
1877
+
1878
+ #### KPI Component
1879
+ | Component | Required Props | Optional Props | Use Case |
1880
+ |-----------|----------------|----------------|----------|
1881
+ | \`<kpi>\` | \`title\`, \`sql\` | \`variant\`, \`format\`, \`trend-sql\`, \`target\`, \`icon\`, \`description\`, \`color\` | Rich metric displays with trends, progress, sparklines |
1882
+
1883
+ **Variants** (use \`variant\` prop):
1884
+ - \`default\` - Simple value card
1885
+ - \`trend\` - Value with change indicator (↑12.5% or ↓3.2%)
1886
+ - \`comparison\` - Value with previous period value shown
1887
+ - \`progress\` - Value with horizontal progress bar toward target
1888
+ - \`ring\` - Value with circular progress gauge toward target
1889
+ - \`sparkline\` - Value with mini area chart showing recent trend
1890
+
1891
+ **Props Reference**:
1892
+ - \`title\` (required) - Display label
1893
+ - \`sql\` (required) - Query returning \`{ value: number }\`
1894
+ - \`variant\` - Display style (see above)
1895
+ - \`format\` - Value format: \`currency\`, \`percent\`, \`number\`, \`compact\`, \`duration\`
1896
+ - \`trend-sql\` - Query for trend data:
1897
+ - For \`trend\`/\`comparison\`: returns \`{ change: number }\` or \`{ previous: number }\`
1898
+ - For \`sparkline\`: returns time-series \`[{ date, value }]\`
1899
+ - \`target\` - Target value for \`progress\`/\`ring\` variants
1900
+ - \`icon\` - Icon identifier: \`dollar\`, \`users\`, \`cart\`, \`chart\`, \`percent\`, \`clock\`
1901
+ - \`description\` - Subtitle/context text
1902
+ - \`color\` - Accent color: \`positive\` (green), \`negative\` (red), \`neutral\`, \`primary\`
1903
+
1904
+ #### Data Table
1905
+ | Component | Required Props | Optional Props | Use Case |
1906
+ |-----------|----------------|----------------|----------|
1907
+ | \`<data-table>\` | \`title\`, \`sql\` | \`columns\` | Detailed data, lists, rankings |
1908
+
1909
+ ### Layout Components
1910
+ | Component | Props | Description |
1911
+ |-----------|-------|-------------|
1912
+ | \`<row>\` | \`gap?\` | Horizontal flex container (small, medium, or large) |
1913
+ | \`<column>\` | \`span\` (1-12) | Column within row, 12-column grid |
1914
+ | \`<grid>\` | \`cols\`, \`gap?\` | CSS Grid container |
1915
+
1916
+ ### Chart Selection Guide
1917
+ - **Time series / Trends with volume**: Use \`<area-chart>\` (shows magnitude over time)
1918
+ - **Time series / Precise trends**: Use \`<line-chart>\` (clean trend lines)
1919
+ - **Categories / Comparisons**: Use \`<bar-chart>\`
1920
+ - **Part-to-whole / Proportions**: Use \`<pie-chart>\` or \`<donut-chart>\`
1921
+ - **Multi-dimensional comparisons**: Use \`<radar-chart>\` (e.g., comparing skills, features)
1922
+ - **Progress / Gauges**: Use \`<radial-chart>\` (circular progress indicators)
1923
+ - **Detailed data / Rankings**: Use \`<data-table>\`
1924
+ - **Single metrics**: Use \`<kpi>\` with appropriate variant:
1925
+ - Simple value → \`default\`
1926
+ - Value with change indicator → \`trend\`
1927
+ - Value vs previous period → \`comparison\`
1928
+ - Value toward goal → \`progress\` or \`ring\`
1929
+ - Value with recent history → \`sparkline\`
1930
+
1931
+ ### Example Output
1932
+ \`\`\`markdown
1933
+ ## Sales Dashboard
1934
+
1935
+ <row>
1936
+ <column span="3">
1937
+ <kpi
1938
+ title="Total Revenue"
1939
+ sql="SELECT SUM(amount) as value FROM orders"
1940
+ trend-sql="SELECT ((SUM(CASE WHEN created_at >= NOW() - INTERVAL '30 days' THEN amount END) - SUM(CASE WHEN created_at >= NOW() - INTERVAL '60 days' AND created_at < NOW() - INTERVAL '30 days' THEN amount END)) / NULLIF(SUM(CASE WHEN created_at >= NOW() - INTERVAL '60 days' AND created_at < NOW() - INTERVAL '30 days' THEN amount END), 0) * 100) as change FROM orders"
1941
+ variant="trend"
1942
+ format="currency"
1943
+ icon="dollar">
1944
+ </kpi>
1945
+ </column>
1946
+ <column span="3">
1947
+ <kpi
1948
+ title="Orders Today"
1949
+ sql="SELECT COUNT(*) as value FROM orders WHERE DATE(created_at) = CURRENT_DATE"
1950
+ trend-sql="SELECT DATE(created_at) as date, COUNT(*) as value FROM orders WHERE created_at >= NOW() - INTERVAL '7 days' GROUP BY 1 ORDER BY 1"
1951
+ variant="sparkline"
1952
+ icon="cart">
1953
+ </kpi>
1954
+ </column>
1955
+ <column span="3">
1956
+ <kpi
1957
+ title="Sales Target"
1958
+ sql="SELECT SUM(amount) as value FROM orders WHERE EXTRACT(QUARTER FROM created_at) = EXTRACT(QUARTER FROM NOW())"
1959
+ target="100000"
1960
+ variant="progress"
1961
+ format="currency"
1962
+ description="Q4 2024 Goal">
1963
+ </kpi>
1964
+ </column>
1965
+ <column span="3">
1966
+ <kpi
1967
+ title="Conversion Rate"
1968
+ sql="SELECT (COUNT(DISTINCT buyer_id)::float / COUNT(DISTINCT visitor_id) * 100) as value FROM sessions"
1969
+ variant="ring"
1970
+ target="100"
1971
+ format="percent"
1972
+ color="primary">
1973
+ </kpi>
1974
+ </column>
1975
+ </row>
1976
+
1977
+ <row>
1978
+ <column span="8">
1979
+ <area-chart
1980
+ title="Revenue Over Time"
1981
+ sql="SELECT DATE_TRUNC('month', created_at) as month, SUM(amount) as revenue FROM orders GROUP BY 1 ORDER BY 1"
1982
+ x-key="month"
1983
+ y-key="revenue"
1984
+ variant="gradient">
1985
+ </area-chart>
1986
+ </column>
1987
+ <column span="4">
1988
+ <donut-chart
1989
+ title="Revenue by Category"
1990
+ sql="SELECT category, SUM(amount) as revenue FROM orders GROUP BY category"
1991
+ label-key="category"
1992
+ value-key="revenue"
1993
+ variant="interactive">
1994
+ </donut-chart>
1995
+ </column>
1996
+ </row>
1997
+
1998
+ <row>
1999
+ <column span="6">
2000
+ <bar-chart
2001
+ title="Monthly Comparison"
2002
+ sql="SELECT DATE_TRUNC('month', created_at) as month, SUM(CASE WHEN EXTRACT(YEAR FROM created_at) = 2024 THEN amount END) as this_year, SUM(CASE WHEN EXTRACT(YEAR FROM created_at) = 2023 THEN amount END) as last_year FROM orders GROUP BY 1"
2003
+ variant="multiple"
2004
+ x-key="month">
2005
+ </bar-chart>
2006
+ </column>
2007
+ <column span="6">
2008
+ <radar-chart
2009
+ title="Product Performance"
2010
+ sql="SELECT metric, score FROM product_metrics WHERE product_id = 1"
2011
+ label-key="metric"
2012
+ value-key="score"
2013
+ variant="filled">
2014
+ </radar-chart>
2015
+ </column>
2016
+ </row>
2017
+
2018
+ <data-table
2019
+ title="Top 10 Products"
2020
+ sql="SELECT name, SUM(quantity) as sold, SUM(amount) as revenue FROM order_items GROUP BY name ORDER BY revenue DESC LIMIT 10">
2021
+ </data-table>
2022
+ \`\`\`
2023
+ `;
2024
+ var biAgent = agent6({
2025
+ model: groq6("gpt-oss-20b"),
2026
+ tools: tools3,
2027
+ name: "bi_agent",
2028
+ prompt: (state) => {
2029
+ return dedent4`
2030
+ You are an expert BI analyst that creates dashboard specifications using HTML custom elements.
2031
+
2032
+ ${COMPONENTS_DOC}
2033
+
2034
+ ## Your Workflow
2035
+
2036
+ 1. **PLAN**: Analyze the request and schema to determine what metrics/visualizations to create
2037
+ 2. **VALIDATE**: Use \`validate_query\` to verify SQL syntax is correct before embedding
2038
+ 3. **OUTPUT**: Generate the dashboard using layout and chart components
2039
+
2040
+ ## Critical Rules
2041
+
2042
+ - **Design from schema**: Use the provided schema introspection to understand available tables, columns, and relationships
2043
+ - **Validate all queries**: Use \`validate_query\` to ensure SQL is syntactically correct before embedding in components
2044
+ - **Use kebab-case HTML tags** with closing tags (e.g., \`<bar-chart></bar-chart>\`)
2045
+ - Use \`scratchpad\` to record schema analysis insights and design decisions
2046
+ - Choose chart types based on column types (dates → line/area, categories → bar/pie, numbers → KPI)
2047
+ - Use layout components (row, column, grid) to organize the dashboard
2048
+ - Include a text introduction explaining what the dashboard shows
2049
+
2050
+ ## SQL Rules
2051
+
2052
+ - Only SELECT or WITH statements
2053
+ - Use proper date/time functions for the database
2054
+ - Include appropriate GROUP BY, ORDER BY clauses
2055
+ - Use aliases for calculated columns
2056
+
2057
+ ${state?.teachings || ""}
2058
+ ${state?.introspection || ""}
2059
+ `;
1425
2060
  }
1426
- return { sql: "", attempts: maxRetries, errors };
1427
- }
2061
+ });
1428
2062
 
1429
2063
  // packages/text2sql/src/lib/agents/chat1.agent.ts
1430
- var tools2 = {
1431
- query_database: tool2({
2064
+ import { groq as groq7 } from "@ai-sdk/groq";
2065
+ import { tool as tool4 } from "ai";
2066
+ import z7 from "zod";
2067
+ import { agent as agent7, toState as toState4 } from "@deepagents/agent";
2068
+ import { scratchpad_tool as scratchpad_tool4 } from "@deepagents/toolbox";
2069
+ var tools4 = {
2070
+ query_database: tool4({
1432
2071
  description: `Query the database to answer a question. Provide your question in natural language and this tool will:
1433
2072
  1. Generate the appropriate SQL query
1434
2073
  2. Validate the SQL syntax
@@ -1436,16 +2075,16 @@ var tools2 = {
1436
2075
  4. Return the results
1437
2076
 
1438
2077
  Use this tool when you need to retrieve data to answer the user's question.`,
1439
- inputSchema: z4.object({
1440
- question: z4.string().min(1).describe(
2078
+ inputSchema: z7.object({
2079
+ question: z7.string().min(1).describe(
1441
2080
  "The question to answer, expressed in natural language. Be specific about what data you need."
1442
2081
  ),
1443
- reasoning: z4.string().optional().describe(
2082
+ reasoning: z7.string().optional().describe(
1444
2083
  "Your reasoning for why this query is needed to answer the user."
1445
2084
  )
1446
2085
  }),
1447
2086
  execute: async ({ question }, options) => {
1448
- const state = toState2(options);
2087
+ const state = toState4(options);
1449
2088
  try {
1450
2089
  const sqlResult = await toSql({
1451
2090
  input: question,
@@ -1456,16 +2095,14 @@ Use this tool when you need to retrieve data to answer the user's question.`,
1456
2095
  if (!sqlResult.sql) {
1457
2096
  return {
1458
2097
  success: false,
1459
- error: sqlResult.errors?.join("; ") || "Failed to generate SQL",
1460
- attempts: sqlResult.attempts
2098
+ error: sqlResult.errors?.join("; ") || "Failed to generate SQL"
1461
2099
  };
1462
2100
  }
1463
2101
  const data = await state.adapter.execute(sqlResult.sql);
1464
2102
  return {
1465
2103
  success: true,
1466
2104
  sql: sqlResult.sql,
1467
- data,
1468
- attempts: sqlResult.attempts
2105
+ data
1469
2106
  };
1470
2107
  } catch (error) {
1471
2108
  return {
@@ -1475,12 +2112,12 @@ Use this tool when you need to retrieve data to answer the user's question.`,
1475
2112
  }
1476
2113
  }
1477
2114
  }),
1478
- scratchpad: scratchpad_tool2
2115
+ scratchpad: scratchpad_tool4
1479
2116
  };
1480
- var chat1Agent = agent4({
2117
+ var chat1Agent = agent7({
1481
2118
  name: "chat1-combined",
1482
- model: groq4("openai/gpt-oss-20b"),
1483
- tools: tools2,
2119
+ model: groq7("openai/gpt-oss-20b"),
2120
+ tools: tools4,
1484
2121
  prompt: (state) => {
1485
2122
  return `
1486
2123
  ${state?.teachings || ""}
@@ -1490,13 +2127,13 @@ ${state?.introspection || ""}
1490
2127
  });
1491
2128
 
1492
2129
  // packages/text2sql/src/lib/agents/chat2.agent.ts
1493
- import { groq as groq5 } from "@ai-sdk/groq";
1494
- import { tool as tool3 } from "ai";
1495
- import z5 from "zod";
1496
- import { agent as agent5, toState as toState3 } from "@deepagents/agent";
1497
- import { scratchpad_tool as scratchpad_tool3 } from "@deepagents/toolbox";
1498
- var tools3 = {
1499
- generate_sql: tool3({
2130
+ import { groq as groq8 } from "@ai-sdk/groq";
2131
+ import { tool as tool5 } from "ai";
2132
+ import z8 from "zod";
2133
+ import { agent as agent8, toState as toState5 } from "@deepagents/agent";
2134
+ import { scratchpad_tool as scratchpad_tool5 } from "@deepagents/toolbox";
2135
+ var tools5 = {
2136
+ generate_sql: tool5({
1500
2137
  description: `Generate a SQL query from a natural language question. This tool will:
1501
2138
  1. Translate your question into SQL
1502
2139
  2. Validate the SQL syntax
@@ -1507,14 +2144,14 @@ Use this BEFORE execute_sql to see what query will be run. You can then:
1507
2144
  - Explain the approach to the user
1508
2145
  - Decide if the SQL looks correct
1509
2146
  - Refine your question and regenerate if needed`,
1510
- inputSchema: z5.object({
1511
- question: z5.string().min(1).describe(
2147
+ inputSchema: z8.object({
2148
+ question: z8.string().min(1).describe(
1512
2149
  "The question to translate into SQL. Be specific about what data you need."
1513
2150
  ),
1514
- reasoning: z5.string().optional().describe("Your reasoning for why this data is needed.")
2151
+ reasoning: z8.string().optional().describe("Your reasoning for why this data is needed.")
1515
2152
  }),
1516
2153
  execute: async ({ question }, options) => {
1517
- const state = toState3(options);
2154
+ const state = toState5(options);
1518
2155
  try {
1519
2156
  const sqlResult = await toSql({
1520
2157
  input: question,
@@ -1526,14 +2163,12 @@ Use this BEFORE execute_sql to see what query will be run. You can then:
1526
2163
  return {
1527
2164
  success: false,
1528
2165
  error: sqlResult.errors?.join("; ") || "Failed to generate SQL",
1529
- attempts: sqlResult.attempts,
1530
2166
  validationErrors: sqlResult.errors
1531
2167
  };
1532
2168
  }
1533
2169
  return {
1534
2170
  success: true,
1535
2171
  sql: sqlResult.sql,
1536
- attempts: sqlResult.attempts,
1537
2172
  validationErrors: sqlResult.errors
1538
2173
  };
1539
2174
  } catch (error) {
@@ -1544,21 +2179,21 @@ Use this BEFORE execute_sql to see what query will be run. You can then:
1544
2179
  }
1545
2180
  }
1546
2181
  }),
1547
- execute_sql: tool3({
2182
+ execute_sql: tool5({
1548
2183
  description: `Execute a SQL query and return the results. Use this AFTER generate_sql to run the query.
1549
2184
 
1550
2185
  Only SELECT and WITH (CTE) queries are allowed - no data modification.`,
1551
- inputSchema: z5.object({
1552
- sql: z5.string().min(1).refine(
2186
+ inputSchema: z8.object({
2187
+ sql: z8.string().min(1).refine(
1553
2188
  (sql) => sql.trim().toUpperCase().startsWith("SELECT") || sql.trim().toUpperCase().startsWith("WITH"),
1554
2189
  {
1555
2190
  message: "Only read-only SELECT or WITH queries are allowed."
1556
2191
  }
1557
2192
  ).describe("The SQL query to execute (must be SELECT or WITH)."),
1558
- reasoning: z5.string().optional().describe("Brief explanation of what this query retrieves.")
2193
+ reasoning: z8.string().optional().describe("Brief explanation of what this query retrieves.")
1559
2194
  }),
1560
2195
  execute: async ({ sql }, options) => {
1561
- const state = toState3(options);
2196
+ const state = toState5(options);
1562
2197
  try {
1563
2198
  const data = await state.adapter.execute(sql);
1564
2199
  return {
@@ -1574,12 +2209,12 @@ Only SELECT and WITH (CTE) queries are allowed - no data modification.`,
1574
2209
  }
1575
2210
  }
1576
2211
  }),
1577
- scratchpad: scratchpad_tool3
2212
+ scratchpad: scratchpad_tool5
1578
2213
  };
1579
- var chat2Agent = agent5({
2214
+ var chat2Agent = agent8({
1580
2215
  name: "chat2-with-peek",
1581
- model: groq5("openai/gpt-oss-20b"),
1582
- tools: tools3,
2216
+ model: groq8("openai/gpt-oss-20b"),
2217
+ tools: tools5,
1583
2218
  prompt: (state) => {
1584
2219
  return `
1585
2220
  ${state?.teachings || ""}
@@ -1597,34 +2232,34 @@ If the generated SQL doesn't look right, you can refine your question and regene
1597
2232
  });
1598
2233
 
1599
2234
  // packages/text2sql/src/lib/agents/chat3.agent.ts
1600
- import { groq as groq6 } from "@ai-sdk/groq";
1601
- import { defaultSettingsMiddleware as defaultSettingsMiddleware2, tool as tool4, wrapLanguageModel as wrapLanguageModel2 } from "ai";
1602
- import z6 from "zod";
1603
- import { agent as agent6, generate as generate2, toState as toState4, user as user2 } from "@deepagents/agent";
1604
- import { scratchpad_tool as scratchpad_tool4 } from "@deepagents/toolbox";
1605
- var collaborativeSqlOutputSchema = z6.discriminatedUnion("status", [
1606
- z6.object({
1607
- status: z6.literal("success"),
1608
- sql: z6.string().describe("The generated SQL query"),
1609
- confidence: z6.enum(["high", "medium", "low"]).describe("Confidence level in this SQL being correct"),
1610
- assumptions: z6.array(z6.string()).optional().describe("Assumptions made during SQL generation"),
1611
- reasoning: z6.string().optional().describe("Brief explanation of the query approach")
2235
+ import { groq as groq9 } from "@ai-sdk/groq";
2236
+ import { defaultSettingsMiddleware as defaultSettingsMiddleware2, tool as tool6, wrapLanguageModel as wrapLanguageModel2 } from "ai";
2237
+ import z9 from "zod";
2238
+ import { agent as agent9, generate as generate3, toState as toState6, user as user2 } from "@deepagents/agent";
2239
+ import { scratchpad_tool as scratchpad_tool6 } from "@deepagents/toolbox";
2240
+ var collaborativeSqlOutputSchema = z9.discriminatedUnion("status", [
2241
+ z9.object({
2242
+ status: z9.literal("success"),
2243
+ sql: z9.string().describe("The generated SQL query"),
2244
+ confidence: z9.enum(["high", "medium", "low"]).describe("Confidence level in this SQL being correct"),
2245
+ assumptions: z9.array(z9.string()).optional().describe("Assumptions made during SQL generation"),
2246
+ reasoning: z9.string().optional().describe("Brief explanation of the query approach")
1612
2247
  }),
1613
- z6.object({
1614
- status: z6.literal("clarification_needed"),
1615
- question: z6.string().describe("Question to clarify the request"),
1616
- context: z6.string().optional().describe("Why this clarification is needed"),
1617
- options: z6.array(z6.string()).optional().describe("Possible options if applicable")
2248
+ z9.object({
2249
+ status: z9.literal("clarification_needed"),
2250
+ question: z9.string().describe("Question to clarify the request"),
2251
+ context: z9.string().optional().describe("Why this clarification is needed"),
2252
+ options: z9.array(z9.string()).optional().describe("Possible options if applicable")
1618
2253
  }),
1619
- z6.object({
1620
- status: z6.literal("unanswerable"),
1621
- reason: z6.string().describe("Why this question cannot be answered"),
1622
- suggestions: z6.array(z6.string()).optional().describe("Alternative questions that could be answered")
2254
+ z9.object({
2255
+ status: z9.literal("unanswerable"),
2256
+ reason: z9.string().describe("Why this question cannot be answered"),
2257
+ suggestions: z9.array(z9.string()).optional().describe("Alternative questions that could be answered")
1623
2258
  })
1624
2259
  ]);
1625
- var collaborativeSqlAgent = agent6({
2260
+ var collaborativeSqlAgent = agent9({
1626
2261
  name: "collaborative-sql",
1627
- model: groq6("openai/gpt-oss-20b"),
2262
+ model: groq9("openai/gpt-oss-20b"),
1628
2263
  output: collaborativeSqlOutputSchema,
1629
2264
  prompt: (state) => {
1630
2265
  return `
@@ -1658,8 +2293,8 @@ Prefer asking for clarification over making low-confidence guesses.
1658
2293
  `;
1659
2294
  }
1660
2295
  });
1661
- var tools4 = {
1662
- consult_sql_agent: tool4({
2296
+ var tools6 = {
2297
+ consult_sql_agent: tool6({
1663
2298
  description: `Consult the SQL specialist agent to generate a query. The SQL agent may:
1664
2299
  - Return a SQL query with confidence level and assumptions
1665
2300
  - Ask for clarification if the question is ambiguous
@@ -1669,15 +2304,15 @@ Based on the response:
1669
2304
  - If clarification is needed, you can provide context or ask the user
1670
2305
  - If assumptions were made, verify them with the user for important queries
1671
2306
  - If unanswerable, relay the suggestions to the user`,
1672
- inputSchema: z6.object({
1673
- question: z6.string().min(1).describe("The question to translate into SQL."),
1674
- context: z6.string().optional().describe("Additional context from the conversation that might help."),
1675
- previousClarification: z6.string().optional().describe(
2307
+ inputSchema: z9.object({
2308
+ question: z9.string().min(1).describe("The question to translate into SQL."),
2309
+ context: z9.string().optional().describe("Additional context from the conversation that might help."),
2310
+ previousClarification: z9.string().optional().describe(
1676
2311
  "Answer to a previous clarification question from the SQL agent."
1677
2312
  )
1678
2313
  }),
1679
2314
  execute: async ({ question, context: context2, previousClarification }, options) => {
1680
- const state = toState4(options);
2315
+ const state = toState6(options);
1681
2316
  try {
1682
2317
  let fullQuestion = question;
1683
2318
  if (context2) {
@@ -1698,7 +2333,7 @@ Clarification provided: ${previousClarification}`;
1698
2333
  })
1699
2334
  })
1700
2335
  });
1701
- const { experimental_output: output } = await generate2(
2336
+ const { experimental_output: output } = await generate3(
1702
2337
  agentInstance,
1703
2338
  [user2(fullQuestion)],
1704
2339
  state
@@ -1747,11 +2382,11 @@ Clarification provided: ${previousClarification}`;
1747
2382
  }
1748
2383
  }
1749
2384
  }),
1750
- execute_sql: tool4({
2385
+ execute_sql: tool6({
1751
2386
  description: `Execute a SQL query directly. Use this when you have SQL that you want to run
1752
2387
  (e.g., after receiving SQL from consult_sql_agent or for follow-up queries).`,
1753
- inputSchema: z6.object({
1754
- sql: z6.string().min(1).refine(
2388
+ inputSchema: z9.object({
2389
+ sql: z9.string().min(1).refine(
1755
2390
  (sql) => sql.trim().toUpperCase().startsWith("SELECT") || sql.trim().toUpperCase().startsWith("WITH"),
1756
2391
  {
1757
2392
  message: "Only read-only SELECT or WITH queries are allowed."
@@ -1759,7 +2394,7 @@ Clarification provided: ${previousClarification}`;
1759
2394
  ).describe("The SQL query to execute.")
1760
2395
  }),
1761
2396
  execute: async ({ sql }, options) => {
1762
- const state = toState4(options);
2397
+ const state = toState6(options);
1763
2398
  try {
1764
2399
  const validationError = await state.adapter.validate(sql);
1765
2400
  if (validationError) {
@@ -1782,12 +2417,12 @@ Clarification provided: ${previousClarification}`;
1782
2417
  }
1783
2418
  }
1784
2419
  }),
1785
- scratchpad: scratchpad_tool4
2420
+ scratchpad: scratchpad_tool6
1786
2421
  };
1787
- var chat3Agent = agent6({
2422
+ var chat3Agent = agent9({
1788
2423
  name: "chat3-collaborative",
1789
- model: groq6("openai/gpt-oss-20b"),
1790
- tools: tools4,
2424
+ model: groq9("openai/gpt-oss-20b"),
2425
+ tools: tools6,
1791
2426
  prompt: (state) => {
1792
2427
  return `
1793
2428
  ${state?.teachings || ""}
@@ -1807,39 +2442,39 @@ For clarification requests, try to answer from conversation context first before
1807
2442
  });
1808
2443
 
1809
2444
  // packages/text2sql/src/lib/agents/chat4.agent.ts
1810
- import { groq as groq7 } from "@ai-sdk/groq";
1811
- import { defaultSettingsMiddleware as defaultSettingsMiddleware3, tool as tool5, wrapLanguageModel as wrapLanguageModel3 } from "ai";
1812
- import z7 from "zod";
1813
- import { agent as agent7, generate as generate3, toState as toState5, user as user3 } from "@deepagents/agent";
1814
- import { scratchpad_tool as scratchpad_tool5 } from "@deepagents/toolbox";
1815
- var questionDecompositionSchema = z7.object({
1816
- originalQuestion: z7.string().describe("The original question being decomposed"),
1817
- breakdown: z7.array(z7.string()).min(1).describe(
2445
+ import { groq as groq10 } from "@ai-sdk/groq";
2446
+ import { defaultSettingsMiddleware as defaultSettingsMiddleware3, tool as tool7, wrapLanguageModel as wrapLanguageModel3 } from "ai";
2447
+ import z10 from "zod";
2448
+ import { agent as agent10, generate as generate4, toState as toState7, user as user3 } from "@deepagents/agent";
2449
+ import { scratchpad_tool as scratchpad_tool7 } from "@deepagents/toolbox";
2450
+ var questionDecompositionSchema = z10.object({
2451
+ originalQuestion: z10.string().describe("The original question being decomposed"),
2452
+ breakdown: z10.array(z10.string()).min(1).describe(
1818
2453
  "Semantic breakdown of the question into its component parts. Each part describes an aspect of what is being asked, NOT how to implement it."
1819
2454
  ),
1820
- entities: z7.array(z7.string()).optional().describe(
2455
+ entities: z10.array(z10.string()).optional().describe(
1821
2456
  "Key entities/concepts mentioned (e.g., customers, orders, products)"
1822
2457
  ),
1823
- filters: z7.array(z7.string()).optional().describe(
2458
+ filters: z10.array(z10.string()).optional().describe(
1824
2459
  'Filtering criteria mentioned (e.g., "last quarter", "above $100")'
1825
2460
  ),
1826
- aggregation: z7.string().optional().describe(
2461
+ aggregation: z10.string().optional().describe(
1827
2462
  'Type of aggregation if any (e.g., "count", "sum", "average", "top N")'
1828
2463
  ),
1829
- ambiguities: z7.array(z7.string()).optional().describe("Any ambiguous parts that might need clarification")
2464
+ ambiguities: z10.array(z10.string()).optional().describe("Any ambiguous parts that might need clarification")
1830
2465
  });
1831
- var decompositionSqlOutputSchema = z7.union([
1832
- z7.object({
1833
- sql: z7.string().describe("The SQL query that answers the decomposed question"),
1834
- reasoning: z7.string().optional().describe("How each breakdown component was addressed")
2466
+ var decompositionSqlOutputSchema = z10.union([
2467
+ z10.object({
2468
+ sql: z10.string().describe("The SQL query that answers the decomposed question"),
2469
+ reasoning: z10.string().optional().describe("How each breakdown component was addressed")
1835
2470
  }),
1836
- z7.object({
1837
- error: z7.string().describe("Error message if the question cannot be answered")
2471
+ z10.object({
2472
+ error: z10.string().describe("Error message if the question cannot be answered")
1838
2473
  })
1839
2474
  ]);
1840
- var decompositionSqlAgent = agent7({
2475
+ var decompositionSqlAgent = agent10({
1841
2476
  name: "decomposition-sql",
1842
- model: groq7("openai/gpt-oss-20b"),
2477
+ model: groq10("openai/gpt-oss-20b"),
1843
2478
  output: decompositionSqlOutputSchema,
1844
2479
  prompt: (state) => {
1845
2480
  return `
@@ -1866,8 +2501,8 @@ If there are ambiguities, make reasonable assumptions and note them in your reas
1866
2501
  }
1867
2502
  });
1868
2503
  var RETRY_TEMPERATURES2 = [0, 0.2, 0.3];
1869
- var tools5 = {
1870
- query_with_decomposition: tool5({
2504
+ var tools7 = {
2505
+ query_with_decomposition: tool7({
1871
2506
  description: `Query the database using question decomposition. This tool:
1872
2507
  1. Breaks down your question into semantic components (entities, filters, aggregations)
1873
2508
  2. Passes the decomposition to the SQL specialist
@@ -1875,22 +2510,22 @@ var tools5 = {
1875
2510
  4. Executes and returns results
1876
2511
 
1877
2512
  This approach helps ensure all aspects of the question are addressed in the query.`,
1878
- inputSchema: z7.object({
1879
- question: z7.string().min(1).describe("The question to answer."),
1880
- breakdown: z7.array(z7.string()).min(1).describe(
2513
+ inputSchema: z10.object({
2514
+ question: z10.string().min(1).describe("The question to answer."),
2515
+ breakdown: z10.array(z10.string()).min(1).describe(
1881
2516
  'Break down the question into its semantic parts. Each part should describe an ASPECT of what is being asked, not instructions. Example for "top customers by revenue last month": ["customers who made purchases", "revenue from those purchases", "time period: last month", "ranking: top by total revenue"]'
1882
2517
  ),
1883
- entities: z7.array(z7.string()).optional().describe(
2518
+ entities: z10.array(z10.string()).optional().describe(
1884
2519
  'Key entities mentioned (e.g., ["customers", "orders", "products"])'
1885
2520
  ),
1886
- filters: z7.array(z7.string()).optional().describe('Filter criteria (e.g., ["last month", "status = active"])'),
1887
- aggregation: z7.string().optional().describe(
2521
+ filters: z10.array(z10.string()).optional().describe('Filter criteria (e.g., ["last month", "status = active"])'),
2522
+ aggregation: z10.string().optional().describe(
1888
2523
  'Aggregation type if any (e.g., "sum revenue", "count orders", "top 10")'
1889
2524
  ),
1890
- ambiguities: z7.array(z7.string()).optional().describe("Note any ambiguous parts you identified")
2525
+ ambiguities: z10.array(z10.string()).optional().describe("Note any ambiguous parts you identified")
1891
2526
  }),
1892
2527
  execute: async ({ question, breakdown, entities, filters, aggregation, ambiguities }, options) => {
1893
- const state = toState5(options);
2528
+ const state = toState7(options);
1894
2529
  const decomposition = {
1895
2530
  originalQuestion: question,
1896
2531
  breakdown,
@@ -1915,7 +2550,7 @@ This approach helps ensure all aspects of the question are addressed in the quer
1915
2550
  const prompt = lastError ? `${decomposedPrompt}
1916
2551
 
1917
2552
  Previous attempt failed with: ${lastError}. Please fix the query.` : decomposedPrompt;
1918
- const { experimental_output: output } = await generate3(
2553
+ const { experimental_output: output } = await generate4(
1919
2554
  agentInstance,
1920
2555
  [user3(prompt)],
1921
2556
  state
@@ -1962,10 +2597,10 @@ Previous attempt failed with: ${lastError}. Please fix the query.` : decomposedP
1962
2597
  }
1963
2598
  }
1964
2599
  }),
1965
- execute_sql: tool5({
2600
+ execute_sql: tool7({
1966
2601
  description: `Execute a SQL query directly. Use for follow-up queries or when you already have SQL.`,
1967
- inputSchema: z7.object({
1968
- sql: z7.string().min(1).refine(
2602
+ inputSchema: z10.object({
2603
+ sql: z10.string().min(1).refine(
1969
2604
  (sql) => sql.trim().toUpperCase().startsWith("SELECT") || sql.trim().toUpperCase().startsWith("WITH"),
1970
2605
  {
1971
2606
  message: "Only read-only SELECT or WITH queries are allowed."
@@ -1973,7 +2608,7 @@ Previous attempt failed with: ${lastError}. Please fix the query.` : decomposedP
1973
2608
  ).describe("The SQL query to execute.")
1974
2609
  }),
1975
2610
  execute: async ({ sql }, options) => {
1976
- const state = toState5(options);
2611
+ const state = toState7(options);
1977
2612
  try {
1978
2613
  const validationError = await state.adapter.validate(sql);
1979
2614
  if (validationError) {
@@ -1996,7 +2631,7 @@ Previous attempt failed with: ${lastError}. Please fix the query.` : decomposedP
1996
2631
  }
1997
2632
  }
1998
2633
  }),
1999
- scratchpad: scratchpad_tool5
2634
+ scratchpad: scratchpad_tool7
2000
2635
  };
2001
2636
  function formatDecomposition(decomposition) {
2002
2637
  const parts = [
@@ -2027,10 +2662,10 @@ function formatDecomposition(decomposition) {
2027
2662
  );
2028
2663
  return parts.join("\n");
2029
2664
  }
2030
- var chat4Agent = agent7({
2665
+ var chat4Agent = agent10({
2031
2666
  name: "chat4-decomposition",
2032
- model: groq7("openai/gpt-oss-20b"),
2033
- tools: tools5,
2667
+ model: groq10("openai/gpt-oss-20b"),
2668
+ tools: tools7,
2034
2669
  prompt: (state) => {
2035
2670
  return `
2036
2671
  ${state?.teachings || ""}
@@ -2056,28 +2691,6 @@ Break the question into its semantic aspects, and let the SQL specialist figure
2056
2691
  }
2057
2692
  });
2058
2693
 
2059
- // packages/text2sql/src/lib/agents/explainer.agent.ts
2060
- import { groq as groq8 } from "@ai-sdk/groq";
2061
- import dedent2 from "dedent";
2062
- import z8 from "zod";
2063
- import { agent as agent8 } from "@deepagents/agent";
2064
- var explainerAgent = agent8({
2065
- name: "explainer",
2066
- model: groq8("openai/gpt-oss-20b"),
2067
- prompt: (state) => dedent2`
2068
- You are an expert SQL tutor.
2069
- Explain the following SQL query in plain English to a non-technical user.
2070
- Focus on the intent and logic, not the syntax.
2071
-
2072
- <sql>
2073
- ${state?.sql}
2074
- </sql>
2075
- `,
2076
- output: z8.object({
2077
- explanation: z8.string().describe("The explanation of the SQL query.")
2078
- })
2079
- });
2080
-
2081
2694
  // packages/text2sql/src/lib/synthesis/types.ts
2082
2695
  async function toPairs(producer) {
2083
2696
  const pairs = [];
@@ -2139,7 +2752,8 @@ function guidelines(options = {}) {
2139
2752
  ),
2140
2753
  // Style and readability
2141
2754
  styleGuide({
2142
- prefer: "Use meaningful aliases for tables and columns to improve readability."
2755
+ prefer: 'For table aliases, use the full table name (e.g., "FROM users AS users", "JOIN order_items AS order_items"). For column aliases, use descriptive names that reflect the data (e.g., "COUNT(*) AS total_orders").',
2756
+ never: "Use abbreviated table aliases (u, oi, ca) or generic positional aliases (t1, t2, a, b)."
2143
2757
  }),
2144
2758
  styleGuide({
2145
2759
  prefer: "Summaries should be concise, business-friendly, highlight key comparisons, and add a short helpful follow-up when useful."
@@ -2151,7 +2765,7 @@ function guidelines(options = {}) {
2151
2765
  action: "Validate syntax and schema references before returning."
2152
2766
  }),
2153
2767
  guardrail({
2154
- rule: "Only generate SELECT statements (read-only queries).",
2768
+ rule: "Only generate SELECT/WITH statements (read-only queries).",
2155
2769
  reason: "Prevents accidental data modification.",
2156
2770
  action: "Never generate INSERT, UPDATE, DELETE, DROP, or other DDL/DML statements."
2157
2771
  }),
@@ -2239,7 +2853,7 @@ var Text2Sql = class {
2239
2853
  };
2240
2854
  }
2241
2855
  async explain(sql) {
2242
- const { experimental_output } = await generate4(
2856
+ const { experimental_output } = await generate5(
2243
2857
  explainerAgent,
2244
2858
  [user4("Explain this SQL.")],
2245
2859
  { sql }
@@ -2260,7 +2874,7 @@ var Text2Sql = class {
2260
2874
  instruct(...dataset) {
2261
2875
  this.#config.instructions.push(...dataset);
2262
2876
  }
2263
- async inspect(agent9) {
2877
+ async inspect(agent11) {
2264
2878
  const [grounding] = await Promise.all([this.index()]);
2265
2879
  const renderToolNames = Object.keys(this.#config.tools ?? {}).filter(
2266
2880
  (name) => name.startsWith("render_")
@@ -2280,14 +2894,14 @@ var Text2Sql = class {
2280
2894
  })
2281
2895
  ] : []
2282
2896
  ];
2283
- const tools6 = Object.keys({
2284
- ...agent9.handoff.tools,
2897
+ const tools8 = Object.keys({
2898
+ ...agent11.handoff.tools,
2285
2899
  ...this.#config.memory ? memoryTools : {},
2286
2900
  ...this.#config.tools
2287
2901
  });
2288
2902
  return {
2289
- tools: tools6,
2290
- prompt: agent9.instructions({
2903
+ tools: tools8,
2904
+ prompt: agent11.instructions({
2291
2905
  introspection: grounding,
2292
2906
  teachings: toInstructions("instructions", ...allInstructions)
2293
2907
  })
@@ -2401,46 +3015,12 @@ var Text2Sql = class {
2401
3015
  userId: params.userId
2402
3016
  }
2403
3017
  );
2404
- return result.toUIMessageStream({
2405
- onError: (error) => {
2406
- if (NoSuchToolError.isInstance(error)) {
2407
- return "The model tried to call a unknown tool.";
2408
- } else if (InvalidToolInputError.isInstance(error)) {
2409
- return "The model called a tool with invalid arguments.";
2410
- } else if (ToolCallRepairError.isInstance(error)) {
2411
- return "The model tried to call a tool with invalid arguments, but it was repaired.";
2412
- } else {
2413
- return "An unknown error occurred.";
2414
- }
2415
- },
2416
- sendStart: true,
2417
- sendFinish: true,
2418
- sendReasoning: true,
2419
- sendSources: true,
2420
- originalMessages: originalMessage,
2421
- generateMessageId: generateId,
2422
- onFinish: async ({ responseMessage, isContinuation }) => {
2423
- const userMessage = messages.at(-1);
2424
- if (!isContinuation && userMessage) {
2425
- console.log(
2426
- "Saving user message to history:",
2427
- JSON.stringify(userMessage)
2428
- );
2429
- await this.#config.history.addMessage({
2430
- id: v72(),
2431
- chatId: params.chatId,
2432
- role: userMessage.role,
2433
- content: userMessage
2434
- });
2435
- }
2436
- await this.#config.history.addMessage({
2437
- id: v72(),
2438
- chatId: params.chatId,
2439
- role: responseMessage.role,
2440
- content: responseMessage
2441
- });
2442
- }
2443
- });
3018
+ return this.#createUIMessageStream(
3019
+ result,
3020
+ messages,
3021
+ params,
3022
+ originalMessage
3023
+ );
2444
3024
  }
2445
3025
  /**
2446
3026
  * Chat1 - Combined tool, no peek.
@@ -2484,7 +3064,7 @@ var Text2Sql = class {
2484
3064
  chat1Agent.clone({
2485
3065
  model: this.#config.model,
2486
3066
  tools: {
2487
- ...tools2,
3067
+ ...tools4,
2488
3068
  ...this.#config.memory ? memoryTools : {},
2489
3069
  ...this.#config.tools
2490
3070
  }
@@ -2493,11 +3073,6 @@ var Text2Sql = class {
2493
3073
  {
2494
3074
  teachings: toInstructions(
2495
3075
  "instructions",
2496
- persona({
2497
- name: "Freya",
2498
- role: "You are an expert SQL query generator, answering business questions with accurate queries.",
2499
- tone: "Your tone should be concise and business-friendly."
2500
- }),
2501
3076
  ...instructions,
2502
3077
  teachable("user_profile", ...userTeachables)
2503
3078
  ),
@@ -2555,7 +3130,7 @@ var Text2Sql = class {
2555
3130
  chat2Agent.clone({
2556
3131
  model: this.#config.model,
2557
3132
  tools: {
2558
- ...tools3,
3133
+ ...tools5,
2559
3134
  ...this.#config.memory ? memoryTools : {},
2560
3135
  ...this.#config.tools
2561
3136
  }
@@ -2564,11 +3139,6 @@ var Text2Sql = class {
2564
3139
  {
2565
3140
  teachings: toInstructions(
2566
3141
  "instructions",
2567
- persona({
2568
- name: "Freya",
2569
- role: "You are an expert SQL query generator, answering business questions with accurate queries.",
2570
- tone: "Your tone should be concise and business-friendly."
2571
- }),
2572
3142
  ...instructions,
2573
3143
  teachable("user_profile", ...userTeachables)
2574
3144
  ),
@@ -2625,7 +3195,7 @@ var Text2Sql = class {
2625
3195
  chat3Agent.clone({
2626
3196
  model: this.#config.model,
2627
3197
  tools: {
2628
- ...tools4,
3198
+ ...tools6,
2629
3199
  ...this.#config.memory ? memoryTools : {},
2630
3200
  ...this.#config.tools
2631
3201
  }
@@ -2634,11 +3204,6 @@ var Text2Sql = class {
2634
3204
  {
2635
3205
  teachings: toInstructions(
2636
3206
  "instructions",
2637
- persona({
2638
- name: "Freya",
2639
- role: "You are an expert SQL query generator, answering business questions with accurate queries.",
2640
- tone: "Your tone should be concise and business-friendly."
2641
- }),
2642
3207
  ...instructions,
2643
3208
  teachable("user_profile", ...userTeachables)
2644
3209
  ),
@@ -2698,7 +3263,7 @@ var Text2Sql = class {
2698
3263
  chat4Agent.clone({
2699
3264
  model: this.#config.model,
2700
3265
  tools: {
2701
- ...tools5,
3266
+ ...tools7,
2702
3267
  ...this.#config.memory ? memoryTools : {},
2703
3268
  ...this.#config.tools
2704
3269
  }
@@ -2707,11 +3272,6 @@ var Text2Sql = class {
2707
3272
  {
2708
3273
  teachings: toInstructions(
2709
3274
  "instructions",
2710
- persona({
2711
- name: "Freya",
2712
- role: "You are an expert SQL query generator, answering business questions with accurate queries.",
2713
- tone: "Your tone should be concise and business-friendly."
2714
- }),
2715
3275
  ...instructions,
2716
3276
  teachable("user_profile", ...userTeachables)
2717
3277
  ),
@@ -2729,10 +3289,117 @@ var Text2Sql = class {
2729
3289
  originalMessage
2730
3290
  );
2731
3291
  }
3292
+ /**
3293
+ * Business intelligence focused chat agent.
3294
+ *
3295
+ * Creates dashboards using MDX components with embedded SQL queries.
3296
+ * The agent explores data, validates SQL, and outputs markdown with
3297
+ * JSX chart components that the frontend renders via MDX.
3298
+ *
3299
+ * @example
3300
+ * ```typescript
3301
+ * const result = await text2sql.bi(
3302
+ * [user("Show me a sales dashboard for last 30 days")],
3303
+ * { chatId: 'dashboard-1', userId: 'user-1' }
3304
+ * );
3305
+ * // Result contains markdown with <BarChart sql="..." />, <KPI sql="..." />, etc.
3306
+ * ```
3307
+ */
3308
+ async bi(messages, params) {
3309
+ const [introspection, userTeachables] = await Promise.all([
3310
+ this.index({ onProgress: console.log }),
3311
+ this.#config.memory ? this.#config.memory.toTeachables(params.userId) : []
3312
+ ]);
3313
+ const chat = await this.#config.history.upsertChat({
3314
+ id: params.chatId,
3315
+ userId: params.userId,
3316
+ title: "Chat " + params.chatId
3317
+ });
3318
+ const originalMessages = [
3319
+ ...chat.messages.map((it) => it.content),
3320
+ ...messages
3321
+ ];
3322
+ const result = stream(
3323
+ biAgent.clone({
3324
+ model: this.#config.model
3325
+ }),
3326
+ originalMessages,
3327
+ {
3328
+ teachings: toInstructions(
3329
+ "instructions",
3330
+ ...this.#config.instructions,
3331
+ teachable("user_profile", ...userTeachables)
3332
+ ),
3333
+ adapter: this.#config.adapter,
3334
+ introspection
3335
+ }
3336
+ );
3337
+ return this.#createUIMessageStream(
3338
+ result,
3339
+ messages,
3340
+ params,
3341
+ originalMessages
3342
+ );
3343
+ }
3344
+ /**
3345
+ * Developer-focused conversational interface for SQL generation.
3346
+ *
3347
+ * Provides power-user tools for query building without execution:
3348
+ * - generate_sql: Convert natural language to validated SQL
3349
+ * - validate_sql: Check SQL syntax
3350
+ * - explain_sql: Get plain-English explanations
3351
+ * - show_schema: Explore database schema on demand
3352
+ *
3353
+ * @example
3354
+ * ```typescript
3355
+ * const result = await text2sql.developer(
3356
+ * [user("Generate a query to find top customers by revenue")],
3357
+ * { chatId: 'dev-session-1', userId: 'dev-1' }
3358
+ * );
3359
+ * // Agent responds with SQL, can validate, explain, or refine iteratively
3360
+ * ```
3361
+ */
3362
+ async developer(messages, params) {
3363
+ const [introspection, userTeachables] = await Promise.all([
3364
+ this.index({ onProgress: console.log }),
3365
+ this.#config.memory ? this.#config.memory.toTeachables(params.userId) : []
3366
+ ]);
3367
+ const chat = await this.#config.history.upsertChat({
3368
+ id: params.chatId,
3369
+ userId: params.userId,
3370
+ title: "Chat " + params.chatId
3371
+ });
3372
+ const originalMessages = [
3373
+ ...chat.messages.map((it) => it.content),
3374
+ ...messages
3375
+ ];
3376
+ const result = stream(
3377
+ developerAgent.clone({
3378
+ model: this.#config.model
3379
+ }),
3380
+ originalMessages,
3381
+ {
3382
+ teachings: toInstructions(
3383
+ "instructions",
3384
+ ...this.#config.instructions,
3385
+ teachable("user_profile", ...userTeachables)
3386
+ ),
3387
+ adapter: this.#config.adapter,
3388
+ introspection,
3389
+ instructions: this.#config.instructions
3390
+ }
3391
+ );
3392
+ return this.#createUIMessageStream(
3393
+ result,
3394
+ messages,
3395
+ params,
3396
+ originalMessages
3397
+ );
3398
+ }
2732
3399
  /**
2733
3400
  * Helper to create UI message stream with common error handling and persistence.
2734
3401
  */
2735
- #createUIMessageStream(result, messages, params, originalMessage) {
3402
+ #createUIMessageStream(result, messages, params, originalMessages) {
2736
3403
  return result.toUIMessageStream({
2737
3404
  onError: (error) => {
2738
3405
  if (NoSuchToolError.isInstance(error)) {
@@ -2749,7 +3416,7 @@ var Text2Sql = class {
2749
3416
  sendFinish: true,
2750
3417
  sendReasoning: true,
2751
3418
  sendSources: true,
2752
- originalMessages: originalMessage,
3419
+ originalMessages,
2753
3420
  generateMessageId: generateId,
2754
3421
  onFinish: async ({ responseMessage, isContinuation }) => {
2755
3422
  const userMessage = messages.at(-1);
@@ -2789,6 +3456,7 @@ export {
2789
3456
  TeachablesStore,
2790
3457
  Text2Sql,
2791
3458
  applyTablesFilter,
3459
+ developerAgent,
2792
3460
  filterRelationshipsByTables,
2793
3461
  filterTablesByName,
2794
3462
  getTablesWithRelated,