sql-ai-harness 0.0.0-stage → 0.1.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 (117) hide show
  1. package/.env.example +31 -0
  2. package/LICENSE +15 -0
  3. package/README.md +201 -2
  4. package/dist/ai/factory.d.ts +4 -0
  5. package/dist/ai/factory.d.ts.map +1 -0
  6. package/dist/ai/factory.js +48 -0
  7. package/dist/ai/factory.js.map +1 -0
  8. package/dist/ai/provider.d.ts +13 -0
  9. package/dist/ai/provider.d.ts.map +1 -0
  10. package/dist/ai/provider.js +2 -0
  11. package/dist/ai/provider.js.map +1 -0
  12. package/dist/ai/sdk-provider.d.ts +13 -0
  13. package/dist/ai/sdk-provider.d.ts.map +1 -0
  14. package/dist/ai/sdk-provider.js +29 -0
  15. package/dist/ai/sdk-provider.js.map +1 -0
  16. package/dist/cli-observer.d.ts +5 -0
  17. package/dist/cli-observer.d.ts.map +1 -0
  18. package/dist/cli-observer.js +79 -0
  19. package/dist/cli-observer.js.map +1 -0
  20. package/dist/cli.d.ts +3 -0
  21. package/dist/cli.d.ts.map +1 -0
  22. package/dist/cli.js +101 -0
  23. package/dist/cli.js.map +1 -0
  24. package/dist/commands/init.d.ts +2 -0
  25. package/dist/commands/init.d.ts.map +1 -0
  26. package/dist/commands/init.js +232 -0
  27. package/dist/commands/init.js.map +1 -0
  28. package/dist/config/config.d.ts +39 -0
  29. package/dist/config/config.d.ts.map +1 -0
  30. package/dist/config/config.js +84 -0
  31. package/dist/config/config.js.map +1 -0
  32. package/dist/context/db-context.d.ts +12 -0
  33. package/dist/context/db-context.d.ts.map +1 -0
  34. package/dist/context/db-context.js +29 -0
  35. package/dist/context/db-context.js.map +1 -0
  36. package/dist/core/agent/agent.d.ts +32 -0
  37. package/dist/core/agent/agent.d.ts.map +1 -0
  38. package/dist/core/agent/agent.js +323 -0
  39. package/dist/core/agent/agent.js.map +1 -0
  40. package/dist/core/agent/index.d.ts +4 -0
  41. package/dist/core/agent/index.d.ts.map +1 -0
  42. package/dist/core/agent/index.js +2 -0
  43. package/dist/core/agent/index.js.map +1 -0
  44. package/dist/core/agent/observability.d.ts +19 -0
  45. package/dist/core/agent/observability.d.ts.map +1 -0
  46. package/dist/core/agent/observability.js +4 -0
  47. package/dist/core/agent/observability.js.map +1 -0
  48. package/dist/core/tools/describe-table.d.ts +6 -0
  49. package/dist/core/tools/describe-table.d.ts.map +1 -0
  50. package/dist/core/tools/describe-table.js +25 -0
  51. package/dist/core/tools/describe-table.js.map +1 -0
  52. package/dist/core/tools/describe-tables.d.ts +6 -0
  53. package/dist/core/tools/describe-tables.d.ts.map +1 -0
  54. package/dist/core/tools/describe-tables.js +22 -0
  55. package/dist/core/tools/describe-tables.js.map +1 -0
  56. package/dist/core/tools/execute-query.d.ts +6 -0
  57. package/dist/core/tools/execute-query.d.ts.map +1 -0
  58. package/dist/core/tools/execute-query.js +31 -0
  59. package/dist/core/tools/execute-query.js.map +1 -0
  60. package/dist/core/tools/explain-query.d.ts +10 -0
  61. package/dist/core/tools/explain-query.d.ts.map +1 -0
  62. package/dist/core/tools/explain-query.js +34 -0
  63. package/dist/core/tools/explain-query.js.map +1 -0
  64. package/dist/core/tools/get-relationships.d.ts +6 -0
  65. package/dist/core/tools/get-relationships.d.ts.map +1 -0
  66. package/dist/core/tools/get-relationships.js +23 -0
  67. package/dist/core/tools/get-relationships.js.map +1 -0
  68. package/dist/core/tools/index.d.ts +9 -0
  69. package/dist/core/tools/index.d.ts.map +1 -0
  70. package/dist/core/tools/index.js +8 -0
  71. package/dist/core/tools/index.js.map +1 -0
  72. package/dist/core/tools/list-tables.d.ts +3 -0
  73. package/dist/core/tools/list-tables.d.ts.map +1 -0
  74. package/dist/core/tools/list-tables.js +18 -0
  75. package/dist/core/tools/list-tables.js.map +1 -0
  76. package/dist/core/tools/registry.d.ts +11 -0
  77. package/dist/core/tools/registry.d.ts.map +1 -0
  78. package/dist/core/tools/registry.js +48 -0
  79. package/dist/core/tools/registry.js.map +1 -0
  80. package/dist/core/types/index.d.ts +94 -0
  81. package/dist/core/types/index.d.ts.map +1 -0
  82. package/dist/core/types/index.js +6 -0
  83. package/dist/core/types/index.js.map +1 -0
  84. package/dist/database/adapter.d.ts +3 -0
  85. package/dist/database/adapter.d.ts.map +1 -0
  86. package/dist/database/adapter.js +2 -0
  87. package/dist/database/adapter.js.map +1 -0
  88. package/dist/database/index.d.ts +4 -0
  89. package/dist/database/index.d.ts.map +1 -0
  90. package/dist/database/index.js +2 -0
  91. package/dist/database/index.js.map +1 -0
  92. package/dist/database/mysql/adapter.d.ts +21 -0
  93. package/dist/database/mysql/adapter.d.ts.map +1 -0
  94. package/dist/database/mysql/adapter.js +140 -0
  95. package/dist/database/mysql/adapter.js.map +1 -0
  96. package/dist/index.d.ts +19 -0
  97. package/dist/index.d.ts.map +1 -0
  98. package/dist/index.js +13 -0
  99. package/dist/index.js.map +1 -0
  100. package/dist/safety/limits.d.ts +7 -0
  101. package/dist/safety/limits.d.ts.map +1 -0
  102. package/dist/safety/limits.js +15 -0
  103. package/dist/safety/limits.js.map +1 -0
  104. package/dist/safety/policy.d.ts +8 -0
  105. package/dist/safety/policy.d.ts.map +1 -0
  106. package/dist/safety/policy.js +11 -0
  107. package/dist/safety/policy.js.map +1 -0
  108. package/dist/safety/sql-validator.d.ts +15 -0
  109. package/dist/safety/sql-validator.d.ts.map +1 -0
  110. package/dist/safety/sql-validator.js +31 -0
  111. package/dist/safety/sql-validator.js.map +1 -0
  112. package/dist/schema/cache.d.ts +24 -0
  113. package/dist/schema/cache.d.ts.map +1 -0
  114. package/dist/schema/cache.js +56 -0
  115. package/dist/schema/cache.js.map +1 -0
  116. package/package.json +75 -3
  117. package/sql-ai.example.md +32 -0
@@ -0,0 +1,232 @@
1
+ import { createInterface } from 'node:readline/promises';
2
+ import { stdin, stdout } from 'node:process';
3
+ import { readFile, writeFile, access, chmod } from 'node:fs/promises';
4
+ import { constants } from 'node:fs';
5
+ import { resolve } from 'node:path';
6
+ import { MySqlAdapter } from '../database/mysql/adapter.js';
7
+ const PROVIDERS = [
8
+ { value: 'openrouter', label: 'OpenRouter', model: '' },
9
+ { value: 'google', label: 'Google Gemini', model: '' },
10
+ { value: 'groq', label: 'Groq', model: '' },
11
+ { value: 'cerebras', label: 'Cerebras', model: '' },
12
+ { value: 'ollama', label: 'Ollama (local)', model: 'qwen2.5:7b' },
13
+ ];
14
+ function required(value, label) {
15
+ const clean = value.trim();
16
+ if (!clean)
17
+ throw new Error(`${label} is required.`);
18
+ return clean;
19
+ }
20
+ async function askSecret(question) {
21
+ if (!stdin.isTTY || typeof stdin.setRawMode !== 'function') {
22
+ const rl = createInterface({ input: stdin, output: stdout });
23
+ try {
24
+ return await rl.question(`${question}: `);
25
+ }
26
+ finally {
27
+ rl.close();
28
+ }
29
+ }
30
+ stdout.write(`${question}: `);
31
+ stdin.setRawMode(true);
32
+ stdin.resume();
33
+ stdin.setEncoding('utf8');
34
+ return new Promise((resolvePromise, reject) => {
35
+ let value = '';
36
+ const cleanup = () => {
37
+ stdin.setRawMode(false);
38
+ stdin.pause();
39
+ stdin.removeListener('data', onData);
40
+ };
41
+ const onData = (chunk) => {
42
+ for (const char of chunk) {
43
+ if (char === '\u0003') {
44
+ cleanup();
45
+ stdout.write('\n');
46
+ reject(new Error('Setup cancelled.'));
47
+ return;
48
+ }
49
+ if (char === '\r' || char === '\n') {
50
+ cleanup();
51
+ stdout.write('\n');
52
+ resolvePromise(value);
53
+ return;
54
+ }
55
+ if (char === '\u007f' || char === '\b')
56
+ value = value.slice(0, -1);
57
+ else if (char >= ' ')
58
+ value += char;
59
+ }
60
+ };
61
+ stdin.on('data', onData);
62
+ });
63
+ }
64
+ async function askChoice(rl, question, options) {
65
+ stdout.write(`\n${question}\n`);
66
+ options.forEach((option, index) => stdout.write(` ${index + 1}. ${option.label}\n`));
67
+ while (true) {
68
+ const answer = (await rl.question(`Choose 1-${options.length} [1]: `)).trim() || '1';
69
+ const index = Number(answer) - 1;
70
+ if (Number.isInteger(index) && options[index])
71
+ return options[index].value;
72
+ stdout.write(`Enter a number from 1 to ${options.length}.\n`);
73
+ }
74
+ }
75
+ async function askValue(rl, label, defaultValue) {
76
+ const answer = (await rl.question(`${label} [${defaultValue}]: `)).trim();
77
+ return answer || defaultValue;
78
+ }
79
+ function dotenvValue(value) {
80
+ return value === '' ? '' : JSON.stringify(value);
81
+ }
82
+ async function saveEnvFile(path, values) {
83
+ let existing = '';
84
+ try {
85
+ existing = await readFile(path, 'utf8');
86
+ }
87
+ catch (error) {
88
+ if (error.code !== 'ENOENT')
89
+ throw error;
90
+ }
91
+ const lines = existing.split(/\r?\n/);
92
+ const output = [];
93
+ const written = new Set();
94
+ for (const line of lines) {
95
+ const match = line.match(/^\s*(?:export\s+)?([A-Z][A-Z0-9_]*)\s*=/);
96
+ const key = match?.[1];
97
+ if (key && Object.hasOwn(values, key)) {
98
+ if (!written.has(key))
99
+ output.push(`${key}=${dotenvValue(values[key])}`);
100
+ written.add(key);
101
+ }
102
+ else {
103
+ output.push(line);
104
+ }
105
+ }
106
+ const additions = Object.entries(values)
107
+ .filter(([key]) => !written.has(key))
108
+ .map(([key, value]) => `${key}=${dotenvValue(value)}`);
109
+ const merged = [...output.filter((line, index, all) => line !== '' || index < all.length - 1), ...additions].join('\n').replace(/\n*$/, '\n');
110
+ await writeFile(path, merged, { encoding: 'utf8', mode: 0o600 });
111
+ await chmod(path, 0o600);
112
+ }
113
+ export async function runInit(args = []) {
114
+ if (!stdin.isTTY || !stdout.isTTY) {
115
+ throw new Error('The init command requires an interactive terminal. Configure environment variables for non-interactive use.');
116
+ }
117
+ const force = args.includes('--force');
118
+ const envPath = resolve(process.cwd(), '.env');
119
+ try {
120
+ await access(envPath, constants.F_OK);
121
+ if (!force) {
122
+ const check = createInterface({ input: stdin, output: stdout });
123
+ const answer = (await check.question('A .env file already exists. Continue and add harness settings? (y/N): ')).trim().toLowerCase();
124
+ check.close();
125
+ if (answer !== 'y' && answer !== 'yes')
126
+ throw new Error('Setup cancelled. Existing .env file was not changed. Use --force to update harness settings.');
127
+ }
128
+ }
129
+ catch (error) {
130
+ if (error.code !== 'ENOENT')
131
+ throw error;
132
+ }
133
+ let rl = createInterface({ input: stdin, output: stdout });
134
+ const values = {
135
+ DB_DRIVER: 'mysql',
136
+ DB_HOST: '127.0.0.1',
137
+ DB_PORT: '3306',
138
+ DB_NAME: '',
139
+ DB_USER: '',
140
+ DB_PASSWORD: '',
141
+ AI_PROVIDER: 'openrouter',
142
+ AI_MODEL: '',
143
+ OPENROUTER_API_KEY: '',
144
+ GROQ_API_KEY: '',
145
+ GOOGLE_GENERATIVE_AI_API_KEY: '',
146
+ CEREBRAS_API_KEY: '',
147
+ OLLAMA_BASE_URL: 'http://localhost:11434/v1',
148
+ AI_SITE_NAME: 'SQL AI Harness',
149
+ SQL_MAX_ROWS: '500',
150
+ SQL_QUERY_TIMEOUT_MS: '10000',
151
+ SQL_MAX_RESULT_BYTES: '1048576',
152
+ AGENT_MAX_STEPS: '8',
153
+ SCHEMA_CACHE_TTL_MS: '300000',
154
+ };
155
+ try {
156
+ stdout.write('\nSQL AI Harness — Setup\n\nDatabase\n');
157
+ values.DB_HOST = await askValue(rl, 'MySQL/MariaDB host', '127.0.0.1');
158
+ values.DB_PORT = await askValue(rl, 'Port', '3306');
159
+ if (!/^\d+$/.test(values.DB_PORT) || Number(values.DB_PORT) < 1 || Number(values.DB_PORT) > 65535) {
160
+ throw new Error('Database port must be a number between 1 and 65535.');
161
+ }
162
+ values.DB_NAME = required(await askValue(rl, 'Database name', ''), 'Database name');
163
+ values.DB_USER = required(await askValue(rl, 'Database username', ''), 'Database username');
164
+ rl.close();
165
+ values.DB_PASSWORD = await askSecret('Database password');
166
+ rl = createInterface({ input: stdin, output: stdout });
167
+ const provider = await askChoice(rl, 'AI provider', PROVIDERS.map(({ value, label }) => ({ value, label })));
168
+ values.AI_PROVIDER = provider;
169
+ const providerInfo = PROVIDERS.find((item) => item.value === provider);
170
+ values.AI_MODEL = required(await rl.question('Model ID (enter the exact model identifier supported by this provider): '), 'Model ID');
171
+ if (provider !== 'ollama') {
172
+ const keyNames = {
173
+ openrouter: 'OPENROUTER_API_KEY',
174
+ google: 'GOOGLE_GENERATIVE_AI_API_KEY',
175
+ groq: 'GROQ_API_KEY',
176
+ cerebras: 'CEREBRAS_API_KEY',
177
+ };
178
+ rl.close();
179
+ values[keyNames[provider]] = required(await askSecret(`${providerInfo.label} API key`), 'API key');
180
+ rl = createInterface({ input: stdin, output: stdout });
181
+ }
182
+ else {
183
+ values.OLLAMA_BASE_URL = await askValue(rl, 'Ollama OpenAI-compatible base URL', 'http://localhost:11434/v1');
184
+ try {
185
+ new URL(values.OLLAMA_BASE_URL);
186
+ }
187
+ catch {
188
+ throw new Error('Ollama base URL must be a valid URL.');
189
+ }
190
+ }
191
+ values.AGENT_MAX_STEPS = await askValue(rl, 'Maximum agent steps', '8');
192
+ values.SQL_MAX_ROWS = await askValue(rl, 'Maximum rows returned', '500');
193
+ values.SCHEMA_CACHE_TTL_MS = String(Number(await askValue(rl, 'Schema cache TTL in minutes', '5')) * 60_000);
194
+ if (!/^\d+$/.test(values.AGENT_MAX_STEPS) || Number(values.AGENT_MAX_STEPS) < 1 || Number(values.AGENT_MAX_STEPS) > 20) {
195
+ throw new Error('Maximum agent steps must be between 1 and 20.');
196
+ }
197
+ if (!/^\d+$/.test(values.SQL_MAX_ROWS) || Number(values.SQL_MAX_ROWS) < 1) {
198
+ throw new Error('Maximum rows returned must be a positive integer.');
199
+ }
200
+ if (!/^\d+$/.test(values.SCHEMA_CACHE_TTL_MS) || Number(values.SCHEMA_CACHE_TTL_MS) < 60_000) {
201
+ throw new Error('Schema cache TTL must be at least 1 minute.');
202
+ }
203
+ stdout.write('\nTesting MySQL/MariaDB connection...\n');
204
+ const database = new MySqlAdapter({
205
+ host: values.DB_HOST, port: Number(values.DB_PORT), database: values.DB_NAME,
206
+ user: values.DB_USER, password: values.DB_PASSWORD,
207
+ });
208
+ try {
209
+ const tables = await database.listTables();
210
+ stdout.write(`✓ Database connection successful (${tables.length} tables discovered).\n`);
211
+ }
212
+ finally {
213
+ await database.close();
214
+ }
215
+ // Keep only the selected provider's secret key in the generated configuration.
216
+ const selectedKey = provider === 'ollama' ? undefined : {
217
+ openrouter: 'OPENROUTER_API_KEY', google: 'GOOGLE_GENERATIVE_AI_API_KEY',
218
+ groq: 'GROQ_API_KEY', cerebras: 'CEREBRAS_API_KEY',
219
+ }[provider];
220
+ for (const key of ['OPENROUTER_API_KEY', 'GROQ_API_KEY', 'GOOGLE_GENERATIVE_AI_API_KEY', 'CEREBRAS_API_KEY']) {
221
+ if (key !== selectedKey)
222
+ delete values[key];
223
+ }
224
+ await saveEnvFile(envPath, values);
225
+ stdout.write(`\n✓ Configuration saved to ${envPath}\n`);
226
+ stdout.write(' Keep .env out of version control; it contains credentials.\n\nSetup complete. Try:\n sql-ai-harness ask "How many records are in the database?"\n\n');
227
+ }
228
+ finally {
229
+ rl.close();
230
+ }
231
+ }
232
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ import 'dotenv/config';
2
+ import { z } from 'zod';
3
+ import type { SqlSafetyPolicy } from '../core/types/index.js';
4
+ declare const providerSchema: z.ZodEnum<{
5
+ cerebras: "cerebras";
6
+ google: "google";
7
+ groq: "groq";
8
+ ollama: "ollama";
9
+ openrouter: "openrouter";
10
+ }>;
11
+ export type AiProviderName = z.infer<typeof providerSchema>;
12
+ export interface AppConfig {
13
+ ai: {
14
+ provider: AiProviderName;
15
+ apiKey?: string;
16
+ model: string;
17
+ baseUrl?: string;
18
+ siteUrl?: string;
19
+ siteName: string;
20
+ };
21
+ database: {
22
+ driver: 'mysql' | 'postgres' | 'sqlite';
23
+ host: string;
24
+ port: number;
25
+ name: string;
26
+ user: string;
27
+ password: string;
28
+ };
29
+ safety: SqlSafetyPolicy;
30
+ agent: {
31
+ maxSteps: number;
32
+ };
33
+ schema: {
34
+ cacheTtlMs: number;
35
+ };
36
+ }
37
+ export declare function loadConfig(env?: NodeJS.ProcessEnv): AppConfig;
38
+ export {};
39
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/config/config.ts"],"names":[],"mappings":"AACA,OAAO,eAAe,CAAC;AACvB,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAE9D,QAAA,MAAM,cAAc;;;;;;EAMlB,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAiC5D,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE;QACF,QAAQ,EAAE,cAAc,CAAC;QACzB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,QAAQ,EAAE;QACR,MAAM,EAAE,OAAO,GAAG,UAAU,GAAG,QAAQ,CAAC;QACxC,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,MAAM,EAAE,eAAe,CAAC;IACxB,KAAK,EAAE;QACL,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,MAAM,EAAE;QACN,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;CACH;AAED,wBAAgB,UAAU,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,SAAS,CA0D1E"}
@@ -0,0 +1,84 @@
1
+ import 'dotenv/config';
2
+ import { z } from 'zod';
3
+ const providerSchema = z.enum([
4
+ 'openrouter',
5
+ 'groq',
6
+ 'google',
7
+ 'cerebras',
8
+ 'ollama',
9
+ ]);
10
+ const envSchema = z.object({
11
+ AI_PROVIDER: providerSchema.default('openrouter'),
12
+ AI_MODEL: z.string().min(1, 'AI_MODEL is required'),
13
+ OPENROUTER_API_KEY: z.string().optional(),
14
+ GROQ_API_KEY: z.string().optional(),
15
+ GOOGLE_GENERATIVE_AI_API_KEY: z.string().optional(),
16
+ CEREBRAS_API_KEY: z.string().optional(),
17
+ OLLAMA_BASE_URL: z.string().url().default('http://localhost:11434/v1'),
18
+ AI_SITE_URL: z.preprocess((value) => value === '' ? undefined : value, z.string().url().optional()),
19
+ AI_SITE_NAME: z.string().default('SQL AI Harness'),
20
+ DB_DRIVER: z.enum(['mysql', 'postgres', 'sqlite']).default('mysql'),
21
+ DB_HOST: z.string().default('127.0.0.1'),
22
+ DB_PORT: z.coerce.number().int().positive().default(3306),
23
+ DB_NAME: z.string().default(''),
24
+ DB_USER: z.string().default(''),
25
+ DB_PASSWORD: z.string().default(''),
26
+ SQL_MAX_ROWS: z.coerce.number().int().positive().default(500),
27
+ SQL_QUERY_TIMEOUT_MS: z.coerce.number().int().positive().default(10_000),
28
+ SQL_MAX_RESULT_BYTES: z.coerce.number().int().positive().default(1_048_576),
29
+ AGENT_MAX_STEPS: z.coerce.number().int().min(1).max(20).default(8),
30
+ SCHEMA_CACHE_TTL_MS: z.coerce.number().int().positive().default(300_000),
31
+ });
32
+ export function loadConfig(env = process.env) {
33
+ const parsed = envSchema.parse(env);
34
+ const apiKeys = {
35
+ openrouter: parsed.OPENROUTER_API_KEY,
36
+ groq: parsed.GROQ_API_KEY,
37
+ google: parsed.GOOGLE_GENERATIVE_AI_API_KEY,
38
+ cerebras: parsed.CEREBRAS_API_KEY,
39
+ ollama: undefined,
40
+ };
41
+ const apiKey = apiKeys[parsed.AI_PROVIDER];
42
+ if (parsed.AI_PROVIDER !== 'ollama' && !apiKey?.trim()) {
43
+ const envNames = {
44
+ openrouter: 'OPENROUTER_API_KEY',
45
+ groq: 'GROQ_API_KEY',
46
+ google: 'GOOGLE_GENERATIVE_AI_API_KEY',
47
+ cerebras: 'CEREBRAS_API_KEY',
48
+ };
49
+ throw new Error(`${envNames[parsed.AI_PROVIDER]} is required when AI_PROVIDER=${parsed.AI_PROVIDER}`);
50
+ }
51
+ return {
52
+ ai: {
53
+ provider: parsed.AI_PROVIDER,
54
+ apiKey,
55
+ model: parsed.AI_MODEL,
56
+ baseUrl: parsed.AI_PROVIDER === 'ollama'
57
+ ? parsed.OLLAMA_BASE_URL
58
+ : undefined,
59
+ siteUrl: parsed.AI_SITE_URL,
60
+ siteName: parsed.AI_SITE_NAME,
61
+ },
62
+ database: {
63
+ driver: parsed.DB_DRIVER,
64
+ host: parsed.DB_HOST,
65
+ port: parsed.DB_PORT,
66
+ name: parsed.DB_NAME,
67
+ user: parsed.DB_USER,
68
+ password: parsed.DB_PASSWORD,
69
+ },
70
+ agent: {
71
+ maxSteps: parsed.AGENT_MAX_STEPS,
72
+ },
73
+ schema: {
74
+ cacheTtlMs: parsed.SCHEMA_CACHE_TTL_MS,
75
+ },
76
+ safety: {
77
+ readOnly: true,
78
+ maxRows: parsed.SQL_MAX_ROWS,
79
+ queryTimeoutMs: parsed.SQL_QUERY_TIMEOUT_MS,
80
+ maxResultBytes: parsed.SQL_MAX_RESULT_BYTES,
81
+ },
82
+ };
83
+ }
84
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/config/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { DatabaseContext } from '../core/types/index.js';
2
+ export declare const DEFAULT_DATABASE_CONTEXT_FILE = "sql-ai.md";
3
+ export interface DatabaseContextLoaderOptions {
4
+ cwd?: string;
5
+ fileName?: string;
6
+ }
7
+ /**
8
+ * Loads optional, user-authored business/domain context for the connected database.
9
+ * Missing context is normal and never prevents the harness from running.
10
+ */
11
+ export declare function loadDatabaseContext(options?: DatabaseContextLoaderOptions): Promise<DatabaseContext>;
12
+ //# sourceMappingURL=db-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db-context.d.ts","sourceRoot":"","sources":["../../src/context/db-context.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAE9D,eAAO,MAAM,6BAA6B,cAAc,CAAC;AAEzD,MAAM,WAAW,4BAA4B;IAC3C,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,GAAE,4BAAiC,GACzC,OAAO,CAAC,eAAe,CAAC,CAqB1B"}
@@ -0,0 +1,29 @@
1
+ import { access, readFile } from 'node:fs/promises';
2
+ import { constants } from 'node:fs';
3
+ import { resolve } from 'node:path';
4
+ export const DEFAULT_DATABASE_CONTEXT_FILE = 'sql-ai.md';
5
+ /**
6
+ * Loads optional, user-authored business/domain context for the connected database.
7
+ * Missing context is normal and never prevents the harness from running.
8
+ */
9
+ export async function loadDatabaseContext(options = {}) {
10
+ const cwd = options.cwd ?? process.cwd();
11
+ const fileName = options.fileName ?? DEFAULT_DATABASE_CONTEXT_FILE;
12
+ const path = resolve(cwd, fileName);
13
+ try {
14
+ await access(path, constants.R_OK);
15
+ const content = (await readFile(path, 'utf8')).trim();
16
+ if (!content)
17
+ return {};
18
+ return { content, source: path };
19
+ }
20
+ catch (error) {
21
+ const code = error && typeof error === 'object' && 'code' in error
22
+ ? error.code
23
+ : undefined;
24
+ if (code === 'ENOENT')
25
+ return {};
26
+ throw error;
27
+ }
28
+ }
29
+ //# sourceMappingURL=db-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db-context.js","sourceRoot":"","sources":["../../src/context/db-context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,MAAM,CAAC,MAAM,6BAA6B,GAAG,WAAW,CAAC;AAOzD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,OAAO,GAAiC,EAAE;IAE1C,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IACzC,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,6BAA6B,CAAC;IACnE,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IAEpC,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC;QACnC,MAAM,OAAO,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAEtD,IAAI,CAAC,OAAO;YAAE,OAAO,EAAE,CAAC;QAExB,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IACnC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,GAAG,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,IAAI,KAAK;YAChE,CAAC,CAAE,KAA2B,CAAC,IAAI;YACnC,CAAC,CAAC,SAAS,CAAC;QAEd,IAAI,IAAI,KAAK,QAAQ;YAAE,OAAO,EAAE,CAAC;QAEjC,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -0,0 +1,32 @@
1
+ import type { AiProvider } from "../../ai/provider.js";
2
+ import type { DatabaseContext, ToolContext } from "../types/index.js";
3
+ import { type AgentObserver } from "./observability.js";
4
+ export type ResponseMode = "natural" | "technical" | "debug";
5
+ export interface AgentOptions {
6
+ maxSteps?: number;
7
+ databaseContext?: DatabaseContext;
8
+ responseMode?: ResponseMode;
9
+ temperature?: number;
10
+ observer?: AgentObserver;
11
+ }
12
+ export interface AgentResult {
13
+ text: string;
14
+ steps: number;
15
+ toolCalls: number;
16
+ raw?: unknown;
17
+ }
18
+ /**
19
+ * Application-level agent. Provider-specific model calls stay behind AiProvider;
20
+ * database access stays behind ToolContext and the tool registry.
21
+ */
22
+ export declare class Agent {
23
+ private readonly provider;
24
+ private readonly context;
25
+ private readonly options;
26
+ constructor(provider: AiProvider, context: ToolContext, options?: AgentOptions);
27
+ ask(question: string): Promise<AgentResult>;
28
+ private responseInstructions;
29
+ private buildTools;
30
+ private discoverRelationships;
31
+ }
32
+ //# sourceMappingURL=agent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../../src/core/agent/agent.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,KAAK,EACV,eAAe,EAEf,WAAW,EACZ,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAqB,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAoC3E,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,WAAW,GAAG,OAAO,CAAC;AAE7D,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,YAAY,CAAC,EAAE,YAAY,CAAC;IAE5B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,aAAa,CAAC;CAC1B;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAsED;;;GAGG;AACH,qBAAa,KAAK;IAEd,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAH1B,YACmB,QAAQ,EAAE,UAAU,EACpB,OAAO,EAAE,WAAW,EACpB,OAAO,GAAE,YAAiB,EACzC;IAEE,GAAG,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAqEhD;IAED,OAAO,CAAC,oBAAoB;IAyB5B,OAAO,CAAC,UAAU;YAkHJ,qBAAqB;CAmDpC"}