sandal-db 1.0.4 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +2 -0
  2. package/dist/cli.js +70 -13
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # SANDAL: Safe Agentic Natural-language Database Access Layer
2
2
 
3
+ ![SANDAL](image.png)
4
+
3
5
  SANDAL is an agentic command-line interface that enables software engineers, data analysts, and site reliability engineers to query, inspect, and manage databases using natural language. Powered by LangGraph and multi-provider language models, SANDAL translates natural language prompts into parameterized database queries, displays execution previews and impact estimations, and enforces multi-layered guardrails before executing any mutating statements.
4
6
 
5
7
  ---
package/dist/cli.js CHANGED
@@ -1220,33 +1220,90 @@ function createDatabaseAdapter(url) {
1220
1220
  import { ChatGoogleGenerativeAI } from "@langchain/google-genai";
1221
1221
  import { ChatOpenAI } from "@langchain/openai";
1222
1222
  import { ChatAnthropic } from "@langchain/anthropic";
1223
- function createChatModel(options) {
1224
- const { provider, model, apiKey, temperature = 0 } = options;
1223
+ function isReasoningOrFixedTempModel(provider, model) {
1224
+ const normalized = model.toLowerCase().replace(/^models\//, "").trim();
1225
1225
  switch (provider) {
1226
1226
  case "google":
1227
- return new ChatGoogleGenerativeAI({
1227
+ return normalized.includes("thinking") || normalized.includes("reasoning") || /^gemini-([3-9]|\d{2,}|2\.[5-9])/i.test(normalized);
1228
+ case "openai":
1229
+ return /^o[1-9]/i.test(normalized) || normalized.includes("reasoning") || normalized.includes("thinking");
1230
+ case "anthropic":
1231
+ return normalized.includes("thinking") || normalized.includes("reasoning");
1232
+ default:
1233
+ return false;
1234
+ }
1235
+ }
1236
+ function resolveTemperature(provider, model, requestedTemperature) {
1237
+ if (isReasoningOrFixedTempModel(provider, model)) {
1238
+ return void 0;
1239
+ }
1240
+ return requestedTemperature ?? 0;
1241
+ }
1242
+ function attachTemperatureFallback(model) {
1243
+ const originalInvoke = model.invoke.bind(model);
1244
+ model.invoke = (async (input3, options) => {
1245
+ try {
1246
+ return await originalInvoke(input3, options);
1247
+ } catch (err) {
1248
+ const errMsg = err?.message || String(err);
1249
+ const isTempError = errMsg.toLowerCase().includes("temperature") && (errMsg.toLowerCase().includes("unsupported") || errMsg.toLowerCase().includes("does not support") || errMsg.toLowerCase().includes("not support"));
1250
+ if (isTempError) {
1251
+ model.temperature = void 0;
1252
+ if (model.client?.generationConfig) {
1253
+ delete model.client.generationConfig.temperature;
1254
+ }
1255
+ return await originalInvoke(input3, options);
1256
+ }
1257
+ throw err;
1258
+ }
1259
+ });
1260
+ return model;
1261
+ }
1262
+ function createChatModel(options) {
1263
+ const { provider, model, apiKey, temperature: requestedTemp } = options;
1264
+ const temperature = resolveTemperature(provider, model, requestedTemp);
1265
+ let chatModel;
1266
+ switch (provider) {
1267
+ case "google": {
1268
+ const config = {
1228
1269
  model,
1229
1270
  apiKey,
1230
- temperature,
1231
1271
  maxRetries: 2
1232
- });
1233
- case "openai":
1234
- return new ChatOpenAI({
1272
+ };
1273
+ if (temperature !== void 0) {
1274
+ config.temperature = temperature;
1275
+ }
1276
+ chatModel = new ChatGoogleGenerativeAI(config);
1277
+ break;
1278
+ }
1279
+ case "openai": {
1280
+ const config = {
1235
1281
  modelName: model,
1236
1282
  apiKey,
1237
- temperature,
1238
1283
  maxRetries: 2
1239
- });
1240
- case "anthropic":
1241
- return new ChatAnthropic({
1284
+ };
1285
+ if (temperature !== void 0) {
1286
+ config.temperature = temperature;
1287
+ }
1288
+ chatModel = new ChatOpenAI(config);
1289
+ break;
1290
+ }
1291
+ case "anthropic": {
1292
+ const config = {
1242
1293
  modelName: model,
1243
1294
  anthropicApiKey: apiKey,
1244
- temperature,
1245
1295
  maxRetries: 2
1246
- });
1296
+ };
1297
+ if (temperature !== void 0) {
1298
+ config.temperature = temperature;
1299
+ }
1300
+ chatModel = new ChatAnthropic(config);
1301
+ break;
1302
+ }
1247
1303
  default:
1248
1304
  throw new Error(`Unsupported LLM provider: ${provider}`);
1249
1305
  }
1306
+ return attachTemperatureFallback(chatModel);
1250
1307
  }
1251
1308
 
1252
1309
  // src/repl.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sandal-db",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "description": "SANDAL - Safe Agentic Natural-language Database Access Layer. Production-grade agentic database assistant CLI using LangGraph and LLMs (Google Gemini, OpenAI, Anthropic)",
5
5
  "type": "module",
6
6
  "bin": {