diff --git a/frontend/src/pages/WorkspaceSettings/AgentConfig/SQLConnectorSelection/DBConnection.jsx b/frontend/src/pages/WorkspaceSettings/AgentConfig/SQLConnectorSelection/DBConnection.jsx
new file mode 100644
index 00000000000..7a58da45401
--- /dev/null
+++ b/frontend/src/pages/WorkspaceSettings/AgentConfig/SQLConnectorSelection/DBConnection.jsx
@@ -0,0 +1,47 @@
+import PostgreSQLLogo from "./icons/postgresql.png";
+import MySQLLogo from "./icons/mysql.png";
+import MSSQLLogo from "./icons/mssql.png";
+import { X } from "@phosphor-icons/react";
+
+export const DB_LOGOS = {
+ postgresql: PostgreSQLLogo,
+ mysql: MySQLLogo,
+ "sql-server": MSSQLLogo,
+};
+
+export default function DBConnection({ connection, onRemove }) {
+ const { database_id, engine } = connection;
+ function removeConfirmation() {
+ if (
+ !window.confirm(
+ `Delete ${database_id} from the list of available SQL connections? This cannot be undone.`
+ )
+ ) {
+ return false;
+ }
+ onRemove(database_id);
+ }
+
+ return (
+
+

+
+
+
{database_id}
+
{engine}
+
+
+
+
+ );
+}
diff --git a/frontend/src/pages/WorkspaceSettings/AgentConfig/SQLConnectorSelection/NewConnectionModal.jsx b/frontend/src/pages/WorkspaceSettings/AgentConfig/SQLConnectorSelection/NewConnectionModal.jsx
new file mode 100644
index 00000000000..e76b27cceda
--- /dev/null
+++ b/frontend/src/pages/WorkspaceSettings/AgentConfig/SQLConnectorSelection/NewConnectionModal.jsx
@@ -0,0 +1,271 @@
+import { useState } from "react";
+import { createPortal } from "react-dom";
+import ModalWrapper from "@/components/ModalWrapper";
+import { WarningOctagon, X } from "@phosphor-icons/react";
+import { DB_LOGOS } from "./DBConnection";
+
+function assembleConnectionString({
+ engine,
+ username = "",
+ password = "",
+ host = "",
+ port = "",
+ database = "",
+}) {
+ if ([username, password, host, database].every((i) => !!i) === false)
+ return `Please fill out all the fields above.`;
+ switch (engine) {
+ case "postgresql":
+ return `postgres://${username}:${password}@${host}:${port}/${database}`;
+ case "mysql":
+ return `mysql://${username}:${password}@${host}:${port}/${database}`;
+ case "sql-server":
+ return `mssql://${username}:${password}@${host}:${port}/${database}`;
+ default:
+ return null;
+ }
+}
+
+const DEFAULT_ENGINE = "postgresql";
+const DEFAULT_CONFIG = {
+ username: null,
+ password: null,
+ host: null,
+ port: null,
+ database: null,
+};
+
+export default function NewSQLConnection({ isOpen, closeModal, onSubmit }) {
+ const [engine, setEngine] = useState(DEFAULT_ENGINE);
+ const [config, setConfig] = useState(DEFAULT_CONFIG);
+ if (!isOpen) return null;
+
+ function handleClose() {
+ setEngine(DEFAULT_ENGINE);
+ setConfig(DEFAULT_CONFIG);
+ closeModal();
+ }
+
+ function onFormChange() {
+ const form = new FormData(document.getElementById("sql-connection-form"));
+ setConfig({
+ username: form.get("username").trim(),
+ password: form.get("password"),
+ host: form.get("host").trim(),
+ port: form.get("port").trim(),
+ database: form.get("database").trim(),
+ });
+ }
+
+ async function handleUpdate(e) {
+ e.preventDefault();
+ e.stopPropagation();
+ const form = new FormData(e.target);
+ onSubmit({
+ engine,
+ database_id: form.get("name"),
+ connectionString: assembleConnectionString({ engine, ...config }),
+ });
+ handleClose();
+ return false;
+ }
+
+ // Cannot do nested forms, it will cause all sorts of issues, so we portal this out
+ // to the parent container form so we don't have nested forms.
+ return createPortal(
+
+
+
+
+
+ New SQL Connection
+
+
+
+
+
+
+
+ ,
+ document.getElementById("workspace-agent-settings-container")
+ );
+}
+
+function DBEngine({ provider, active, onClick }) {
+ return (
+
+ );
+}
diff --git a/frontend/src/pages/WorkspaceSettings/AgentConfig/SQLConnectorSelection/icons/mssql.png b/frontend/src/pages/WorkspaceSettings/AgentConfig/SQLConnectorSelection/icons/mssql.png
new file mode 100644
index 00000000000..7bd58a9a3ea
Binary files /dev/null and b/frontend/src/pages/WorkspaceSettings/AgentConfig/SQLConnectorSelection/icons/mssql.png differ
diff --git a/frontend/src/pages/WorkspaceSettings/AgentConfig/SQLConnectorSelection/icons/mysql.png b/frontend/src/pages/WorkspaceSettings/AgentConfig/SQLConnectorSelection/icons/mysql.png
new file mode 100644
index 00000000000..5a440811548
Binary files /dev/null and b/frontend/src/pages/WorkspaceSettings/AgentConfig/SQLConnectorSelection/icons/mysql.png differ
diff --git a/frontend/src/pages/WorkspaceSettings/AgentConfig/SQLConnectorSelection/icons/postgresql.png b/frontend/src/pages/WorkspaceSettings/AgentConfig/SQLConnectorSelection/icons/postgresql.png
new file mode 100644
index 00000000000..67918df7a77
Binary files /dev/null and b/frontend/src/pages/WorkspaceSettings/AgentConfig/SQLConnectorSelection/icons/postgresql.png differ
diff --git a/frontend/src/pages/WorkspaceSettings/AgentConfig/SQLConnectorSelection/index.jsx b/frontend/src/pages/WorkspaceSettings/AgentConfig/SQLConnectorSelection/index.jsx
new file mode 100644
index 00000000000..9feb4b8bb6c
--- /dev/null
+++ b/frontend/src/pages/WorkspaceSettings/AgentConfig/SQLConnectorSelection/index.jsx
@@ -0,0 +1,109 @@
+import React, { useState } from "react";
+import DBConnection from "./DBConnection";
+import { Plus } from "@phosphor-icons/react";
+import NewSQLConnection from "./NewConnectionModal";
+import { useModal } from "@/hooks/useModal";
+
+export default function AgentSQLConnectorSelection({
+ skill,
+ settings,
+ toggleSkill,
+ enabled = false,
+}) {
+ const { isOpen, openModal, closeModal } = useModal();
+ const [connections, setConnections] = useState(
+ settings?.preferences?.agent_sql_connections || []
+ );
+
+ return (
+ <>
+
+
+
+
+
+
+
+ Enable your agent to be able to leverage SQL to answer you questions
+ by connecting to various SQL database providers.
+
+
+ {enabled && (
+ <>
+
+
conn.action !== "remove")
+ )}
+ />
+
+
+ Your database connections
+
+
+ {connections
+ .filter((connection) => connection.action !== "remove")
+ .map((connection) => (
+
{
+ setConnections((prev) =>
+ prev.map((conn) => {
+ if (conn.database_id === databaseId)
+ return { ...conn, action: "remove" };
+ return conn;
+ })
+ );
+ }}
+ />
+ ))}
+
+
+
+ >
+ )}
+
+
+ setConnections((prev) => [...prev, { action: "add", ...newDb }])
+ }
+ />
+ >
+ );
+}
diff --git a/frontend/src/pages/WorkspaceSettings/AgentConfig/index.jsx b/frontend/src/pages/WorkspaceSettings/AgentConfig/index.jsx
index c96cc12469b..02065251a66 100644
--- a/frontend/src/pages/WorkspaceSettings/AgentConfig/index.jsx
+++ b/frontend/src/pages/WorkspaceSettings/AgentConfig/index.jsx
@@ -5,6 +5,7 @@ import { castToType } from "@/utils/types";
import { useEffect, useRef, useState } from "react";
import AgentLLMSelection from "./AgentLLMSelection";
import AgentWebSearchSelection from "./WebSearchSelection";
+import AgentSQLConnectorSelection from "./SQLConnectorSelection";
import GenericSkill from "./GenericSkill";
import Admin from "@/models/admin";
import * as Skeleton from "react-loading-skeleton";
@@ -205,6 +206,12 @@ function AvailableAgentSkills({ skills, settings, toggleAgentSkill }) {
toggleSkill={toggleAgentSkill}
enabled={skills.includes("web-browsing")}
/>
+
);
diff --git a/server/endpoints/admin.js b/server/endpoints/admin.js
index 2ef611f6a19..959e023ff14 100644
--- a/server/endpoints/admin.js
+++ b/server/endpoints/admin.js
@@ -350,6 +350,8 @@ function adminEndpoints(app) {
agent_search_provider:
(await SystemSettings.get({ label: "agent_search_provider" }))
?.value || null,
+ agent_sql_connections:
+ await SystemSettings.brief.agent_sql_connections(),
default_agent_skills:
safeJsonParse(
(await SystemSettings.get({ label: "default_agent_skills" }))
diff --git a/server/models/systemSettings.js b/server/models/systemSettings.js
index 248ca8cd79b..7b4f21eebe7 100644
--- a/server/models/systemSettings.js
+++ b/server/models/systemSettings.js
@@ -2,8 +2,10 @@ process.env.NODE_ENV === "development"
? require("dotenv").config({ path: `.env.${process.env.NODE_ENV}` })
: require("dotenv").config();
-const { isValidUrl } = require("../utils/http");
+const { default: slugify } = require("slugify");
+const { isValidUrl, safeJsonParse } = require("../utils/http");
const prisma = require("../utils/prisma");
+const { v4 } = require("uuid");
function isNullOrNaN(value) {
if (value === null) return true;
@@ -24,6 +26,7 @@ const SystemSettings = {
"text_splitter_chunk_overlap",
"agent_search_provider",
"default_agent_skills",
+ "agent_sql_connections",
],
validations: {
footer_data: (updates) => {
@@ -65,6 +68,7 @@ const SystemSettings = {
},
agent_search_provider: (update) => {
try {
+ if (update === "none") return null;
if (!["google-search-engine", "serper-dot-dev"].includes(update))
throw new Error("Invalid SERP provider.");
return String(update);
@@ -85,6 +89,22 @@ const SystemSettings = {
return JSON.stringify([]);
}
},
+ agent_sql_connections: async (updates) => {
+ const existingConnections = safeJsonParse(
+ (await SystemSettings.get({ label: "agent_sql_connections" }))?.value,
+ []
+ );
+ try {
+ const updatedConnections = mergeConnections(
+ existingConnections,
+ safeJsonParse(updates, [])
+ );
+ return JSON.stringify(updatedConnections);
+ } catch (e) {
+ console.error(`Failed to merge connections`);
+ return JSON.stringify(existingConnections ?? []);
+ }
+ },
},
currentSettings: async function () {
const { hasVectorCachedFiles } = require("../utils/files");
@@ -204,22 +224,30 @@ const SystemSettings = {
// that takes no user input for the keys being modified.
_updateSettings: async function (updates = {}) {
try {
- const updatePromises = Object.keys(updates).map((key) => {
- const validatedValue = this.validations.hasOwnProperty(key)
- ? this.validations[key](updates[key])
- : updates[key];
-
- return prisma.system_settings.upsert({
- where: { label: key },
- update: {
- value: validatedValue === null ? null : String(validatedValue),
- },
- create: {
- label: key,
- value: validatedValue === null ? null : String(validatedValue),
- },
- });
- });
+ const updatePromises = [];
+ for (const key of Object.keys(updates)) {
+ let validatedValue = updates[key];
+ if (this.validations.hasOwnProperty(key)) {
+ if (this.validations[key].constructor.name === "AsyncFunction") {
+ validatedValue = await this.validations[key](updates[key]);
+ } else {
+ validatedValue = this.validations[key](updates[key]);
+ }
+ }
+
+ updatePromises.push(
+ prisma.system_settings.upsert({
+ where: { label: key },
+ update: {
+ value: validatedValue === null ? null : String(validatedValue),
+ },
+ create: {
+ label: key,
+ value: validatedValue === null ? null : String(validatedValue),
+ },
+ })
+ );
+ }
await Promise.all(updatePromises);
return { success: true, error: null };
@@ -392,6 +420,58 @@ const SystemSettings = {
CohereModelPref: process.env.COHERE_MODEL_PREF,
};
},
+
+ // For special retrieval of a key setting that does not expose any credential information
+ brief: {
+ agent_sql_connections: async function () {
+ const setting = await SystemSettings.get({
+ label: "agent_sql_connections",
+ });
+ if (!setting) return [];
+ return safeJsonParse(setting.value, []).map((dbConfig) => {
+ const { connectionString, ...rest } = dbConfig;
+ return rest;
+ });
+ },
+ },
};
+function mergeConnections(existingConnections = [], updates = []) {
+ let updatedConnections = [...existingConnections];
+ const existingDbIds = existingConnections.map((conn) => conn.database_id);
+
+ // First remove all 'action:remove' candidates from existing connections.
+ const toRemove = updates
+ .filter((conn) => conn.action === "remove")
+ .map((conn) => conn.database_id);
+ updatedConnections = updatedConnections.filter(
+ (conn) => !toRemove.includes(conn.database_id)
+ );
+
+ // Next add all 'action:add' candidates into the updatedConnections; We DO NOT validate the connection strings.
+ // but we do validate their database_id is unique.
+ updates
+ .filter((conn) => conn.action === "add")
+ .forEach((update) => {
+ if (!update.connectionString) return; // invalid connection string
+
+ // Remap name to be unique to entire set.
+ if (existingDbIds.includes(update.database_id)) {
+ update.database_id = slugify(
+ `${update.database_id}-${v4().slice(0, 4)}`
+ );
+ } else {
+ update.database_id = slugify(update.database_id);
+ }
+
+ updatedConnections.push({
+ engine: update.engine,
+ database_id: update.database_id,
+ connectionString: update.connectionString,
+ });
+ });
+
+ return updatedConnections;
+}
+
module.exports.SystemSettings = SystemSettings;
diff --git a/server/package.json b/server/package.json
index 73b947c461e..4f9954700e0 100644
--- a/server/package.json
+++ b/server/package.json
@@ -58,11 +58,14 @@
"langchain": "0.1.36",
"mime": "^3.0.0",
"moment": "^2.29.4",
+ "mssql": "^10.0.2",
"multer": "^1.4.5-lts.1",
+ "mysql2": "^3.9.7",
"node-html-markdown": "^1.3.0",
"node-llama-cpp": "^2.8.0",
"ollama": "^0.5.0",
"openai": "4.38.5",
+ "pg": "^8.11.5",
"pinecone-client": "^1.1.0",
"pluralize": "^8.0.0",
"posthog-node": "^3.1.1",
@@ -72,6 +75,7 @@
"sqlite3": "^5.1.6",
"swagger-autogen": "^2.23.5",
"swagger-ui-express": "^5.0.0",
+ "url-pattern": "^1.0.3",
"uuid": "^9.0.0",
"uuid-apikey": "^1.5.3",
"vectordb": "0.4.11",
diff --git a/server/utils/agents/aibitat/index.js b/server/utils/agents/aibitat/index.js
index f21c4aa4511..fa490edb297 100644
--- a/server/utils/agents/aibitat/index.js
+++ b/server/utils/agents/aibitat/index.js
@@ -498,6 +498,17 @@ Only return the role.
return availableNodes[Math.floor(Math.random() * availableNodes.length)];
}
+ /**
+ *
+ * @param {string} pluginName this name of the plugin being called
+ * @returns string of the plugin to be called compensating for children denoted by # in the string.
+ * eg: sql-agent:list-database-connections
+ */
+ #parseFunctionName(pluginName = "") {
+ if (!pluginName.includes("#")) return pluginName;
+ return pluginName.split("#")[1];
+ }
+
/**
* Check if the chat has reached the maximum number of rounds.
*/
@@ -550,7 +561,7 @@ ${this.getHistory({ to: route.to })
// get the functions that the node can call
const functions = fromConfig.functions
- ?.map((name) => this.functions.get(name))
+ ?.map((name) => this.functions.get(this.#parseFunctionName(name)))
.filter((a) => !!a);
const provider = this.getProviderForConfig({
diff --git a/server/utils/agents/aibitat/plugins/index.js b/server/utils/agents/aibitat/plugins/index.js
index d9ff544e2e8..9a7ee7a059f 100644
--- a/server/utils/agents/aibitat/plugins/index.js
+++ b/server/utils/agents/aibitat/plugins/index.js
@@ -6,6 +6,7 @@ const { saveFileInBrowser } = require("./save-file-browser.js");
const { chatHistory } = require("./chat-history.js");
const { memory } = require("./memory.js");
const { rechart } = require("./rechart.js");
+const { sqlAgent } = require("./sql-agent/index.js");
module.exports = {
webScraping,
@@ -16,6 +17,7 @@ module.exports = {
chatHistory,
memory,
rechart,
+ sqlAgent,
// Plugin name aliases so they can be pulled by slug as well.
[webScraping.name]: webScraping,
@@ -26,4 +28,5 @@ module.exports = {
[chatHistory.name]: chatHistory,
[memory.name]: memory,
[rechart.name]: rechart,
+ [sqlAgent.name]: sqlAgent,
};
diff --git a/server/utils/agents/aibitat/plugins/sql-agent/SQLConnectors/MSSQL.js b/server/utils/agents/aibitat/plugins/sql-agent/SQLConnectors/MSSQL.js
new file mode 100644
index 00000000000..ed75aa7aa71
--- /dev/null
+++ b/server/utils/agents/aibitat/plugins/sql-agent/SQLConnectors/MSSQL.js
@@ -0,0 +1,89 @@
+const mssql = require("mssql");
+const UrlPattern = require("url-pattern");
+
+class MSSQLConnector {
+ #connected = false;
+ database_id = "";
+ connectionConfig = {
+ user: null,
+ password: null,
+ database: null,
+ server: null,
+ port: null,
+ pool: {
+ max: 10,
+ min: 0,
+ idleTimeoutMillis: 30000,
+ },
+ options: {
+ encrypt: false,
+ trustServerCertificate: true,
+ },
+ };
+
+ constructor(
+ config = {
+ // we will force into RFC-3986 from DB
+ // eg: mssql://user:password@server:port/database?{...opts}
+ connectionString: null, // we will force into RFC-3986
+ }
+ ) {
+ this.connectionString = config.connectionString;
+ this._client = null;
+ this.#parseDatabase();
+ }
+
+ #parseDatabase() {
+ const connectionPattern = new UrlPattern(
+ "mssql\\://:username\\::password@*\\::port/:database*"
+ );
+ const match = connectionPattern.match(this.connectionString);
+ this.database_id = match?.database;
+ this.connectionConfig = {
+ ...this.connectionConfig,
+ user: match?.username,
+ password: match?.password,
+ database: match?.database,
+ server: match?._[0],
+ port: match?.port ? Number(match.port) : null,
+ };
+ }
+
+ async connect() {
+ this._client = await mssql.connect(this.connectionConfig);
+ this.#connected = true;
+ return this._client;
+ }
+
+ /**
+ *
+ * @param {string} queryString the SQL query to be run
+ * @returns {import(".").QueryResult}
+ */
+ async runQuery(queryString = "") {
+ const result = { rows: [], count: 0, error: null };
+ try {
+ if (!this.#connected) await this.connect();
+
+ const query = await this._client.query(queryString);
+ result.rows = query.recordset;
+ result.count = query.rowsAffected.reduce((sum, a) => sum + a, 0);
+ } catch (err) {
+ console.log(this.constructor.name, err);
+ result.error = err.message;
+ } finally {
+ await this._client.close();
+ this.#connected = false;
+ }
+ return result;
+ }
+
+ getTablesSql() {
+ return `SELECT name FROM sysobjects WHERE xtype='U';`;
+ }
+ getTableSchemaSql(table_name) {
+ return `SELECT COLUMN_NAME,COLUMN_DEFAULT,IS_NULLABLE,DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='${table_name}'`;
+ }
+}
+
+module.exports.MSSQLConnector = MSSQLConnector;
diff --git a/server/utils/agents/aibitat/plugins/sql-agent/SQLConnectors/MySQL.js b/server/utils/agents/aibitat/plugins/sql-agent/SQLConnectors/MySQL.js
new file mode 100644
index 00000000000..d9982ab318e
--- /dev/null
+++ b/server/utils/agents/aibitat/plugins/sql-agent/SQLConnectors/MySQL.js
@@ -0,0 +1,59 @@
+const mysql = require("mysql2/promise");
+const UrlPattern = require("url-pattern");
+
+class MySQLConnector {
+ #connected = false;
+ database_id = "";
+ constructor(
+ config = {
+ connectionString: null,
+ }
+ ) {
+ this.connectionString = config.connectionString;
+ this._client = null;
+ this.database_id = this.#parseDatabase();
+ }
+
+ #parseDatabase() {
+ const connectionPattern = new UrlPattern("mysql\\://*@*/:database*");
+ const match = connectionPattern.match(this.connectionString);
+ return match?.database;
+ }
+
+ async connect() {
+ this._client = await mysql.createConnection({ uri: this.connectionString });
+ this.#connected = true;
+ return this._client;
+ }
+
+ /**
+ *
+ * @param {string} queryString the SQL query to be run
+ * @returns {import(".").QueryResult}
+ */
+ async runQuery(queryString = "") {
+ const result = { rows: [], count: 0, error: null };
+ try {
+ if (!this.#connected) await this.connect();
+ const [query] = await this._client.query(queryString);
+ result.rows = query;
+ result.count = query?.length;
+ } catch (err) {
+ console.log(this.constructor.name, err);
+ result.error = err.message;
+ } finally {
+ await this._client.end();
+ this.#connected = false;
+ }
+ return result;
+ }
+
+ getTablesSql() {
+ return `SELECT table_name FROM information_schema.tables WHERE table_schema = '${this.database_id}'`;
+ }
+ getTableSchemaSql(table_name) {
+ return `SHOW COLUMNS FROM ${this.database_id}.${table_name};`;
+ }
+}
+
+module.exports.MySQLConnector = MySQLConnector;
diff --git a/server/utils/agents/aibitat/plugins/sql-agent/SQLConnectors/Postgresql.js b/server/utils/agents/aibitat/plugins/sql-agent/SQLConnectors/Postgresql.js
new file mode 100644
index 00000000000..463fea51018
--- /dev/null
+++ b/server/utils/agents/aibitat/plugins/sql-agent/SQLConnectors/Postgresql.js
@@ -0,0 +1,52 @@
+const pgSql = require("pg");
+
+class PostgresSQLConnector {
+ #connected = false;
+ constructor(
+ config = {
+ connectionString: null,
+ }
+ ) {
+ this.connectionString = config.connectionString;
+ this._client = new pgSql.Client({
+ connectionString: this.connectionString,
+ });
+ }
+
+ async connect() {
+ await this._client.connect();
+ this.#connected = true;
+ return this._client;
+ }
+
+ /**
+ *
+ * @param {string} queryString the SQL query to be run
+ * @returns {import(".").QueryResult}
+ */
+ async runQuery(queryString = "") {
+ const result = { rows: [], count: 0, error: null };
+ try {
+ if (!this.#connected) await this.connect();
+ const query = await this._client.query(queryString);
+ result.rows = query.rows;
+ result.count = query.rowCount;
+ } catch (err) {
+ console.log(this.constructor.name, err);
+ result.error = err.message;
+ } finally {
+ await this._client.end();
+ this.#connected = false;
+ }
+ return result;
+ }
+
+ getTablesSql() {
+ return `SELECT * FROM pg_catalog.pg_tables WHERE schemaname = 'public'`;
+ }
+ getTableSchemaSql(table_name) {
+ return ` select column_name, data_type, character_maximum_length, column_default, is_nullable from INFORMATION_SCHEMA.COLUMNS where table_name = '${table_name}'`;
+ }
+}
+
+module.exports.PostgresSQLConnector = PostgresSQLConnector;
diff --git a/server/utils/agents/aibitat/plugins/sql-agent/SQLConnectors/index.js b/server/utils/agents/aibitat/plugins/sql-agent/SQLConnectors/index.js
new file mode 100644
index 00000000000..9cf1e1ff4d7
--- /dev/null
+++ b/server/utils/agents/aibitat/plugins/sql-agent/SQLConnectors/index.js
@@ -0,0 +1,60 @@
+const { SystemSettings } = require("../../../../../../models/systemSettings");
+const { safeJsonParse } = require("../../../../../http");
+
+/**
+ * @typedef {('postgresql'|'mysql'|'sql-server')} SQLEngine
+ */
+
+/**
+ * @typedef {Object} QueryResult
+ * @property {[number]} rows - The query result rows
+ * @property {number} count - Number of rows the query returned/changed
+ * @property {string|null} error - Error string if there was an issue
+ */
+
+/**
+ * A valid database SQL connection object
+ * @typedef {Object} SQLConnection
+ * @property {string} database_id - Unique identifier of the database connection
+ * @property {SQLEngine} engine - Engine used by connection
+ * @property {string} connectionString - RFC connection string for db
+ */
+
+/**
+ * @param {SQLEngine} identifier
+ * @param {object} connectionConfig
+ * @returns Database Connection Engine Class for SQLAgent or throws error
+ */
+function getDBClient(identifier = "", connectionConfig = {}) {
+ switch (identifier) {
+ case "mysql":
+ const { MySQLConnector } = require("./MySQL");
+ return new MySQLConnector(connectionConfig);
+ case "postgresql":
+ const { PostgresSQLConnector } = require("./Postgresql");
+ return new PostgresSQLConnector(connectionConfig);
+ case "sql-server":
+ const { MSSQLConnector } = require("./MSSQL");
+ return new MSSQLConnector(connectionConfig);
+ default:
+ throw new Error(
+ `There is no supported database connector for ${identifier}`
+ );
+ }
+}
+
+/**
+ * Lists all of the known database connection that can be used by the agent.
+ * @returns {Promise<[SQLConnection]>}
+ */
+async function listSQLConnections() {
+ return safeJsonParse(
+ (await SystemSettings.get({ label: "agent_sql_connections" }))?.value,
+ []
+ );
+}
+
+module.exports = {
+ getDBClient,
+ listSQLConnections,
+};
diff --git a/server/utils/agents/aibitat/plugins/sql-agent/get-table-schema.js b/server/utils/agents/aibitat/plugins/sql-agent/get-table-schema.js
new file mode 100644
index 00000000000..2f66d119d7d
--- /dev/null
+++ b/server/utils/agents/aibitat/plugins/sql-agent/get-table-schema.js
@@ -0,0 +1,98 @@
+module.exports.SqlAgentGetTableSchema = {
+ name: "sql-get-table-schema",
+ plugin: function () {
+ const {
+ listSQLConnections,
+ getDBClient,
+ } = require("./SQLConnectors/index.js");
+
+ return {
+ name: "sql-get-table-schema",
+ setup(aibitat) {
+ aibitat.function({
+ super: aibitat,
+ name: this.name,
+ description:
+ "Gets the table schema in SQL for a given `table` and `database_id`",
+ examples: [
+ {
+ prompt: "What does the customers table in access-logs look like?",
+ call: JSON.stringify({
+ database_id: "access-logs",
+ table_name: "customers",
+ }),
+ },
+ {
+ prompt:
+ "Get me the full name of a company in records-main, the table should be call comps",
+ call: JSON.stringify({
+ database_id: "records-main",
+ table_name: "comps",
+ }),
+ },
+ ],
+ parameters: {
+ $schema: "http://json-schema.org/draft-07/schema#",
+ type: "object",
+ properties: {
+ database_id: {
+ type: "string",
+ description:
+ "The database identifier for which we will connect to to query the table schema. This is a required field.",
+ },
+ table_name: {
+ type: "string",
+ description:
+ "The database identifier for the table name we want the schema for. This is a required field.",
+ },
+ },
+ additionalProperties: false,
+ },
+ required: ["database_id", "table_name"],
+ handler: async function ({ database_id = "", table_name = "" }) {
+ this.super.handlerProps.log(`Using the sql-get-table-schema tool.`);
+ try {
+ const databaseConfig = (await listSQLConnections()).find(
+ (db) => db.database_id === database_id
+ );
+ if (!databaseConfig) {
+ this.super.handlerProps.log(
+ `sql-get-table-schema to find config!.`,
+ database_id
+ );
+ return `No database connection for ${database_id} was found!`;
+ }
+
+ const db = getDBClient(databaseConfig.engine, databaseConfig);
+ this.super.introspect(
+ `${this.caller}: Querying the table schema for ${table_name} in the ${databaseConfig.database_id} database.`
+ );
+ this.super.introspect(
+ `Running SQL: ${db.getTableSchemaSql(table_name)}`
+ );
+ const result = await db.runQuery(
+ db.getTableSchemaSql(table_name)
+ );
+
+ if (result.error) {
+ this.super.handlerProps.log(
+ `sql-get-table-schema tool reported error`,
+ result.error
+ );
+ this.super.introspect(`Error: ${result.error}`);
+ return `There was an error running the query: ${result.error}`;
+ }
+
+ return JSON.stringify(result);
+ } catch (e) {
+ this.super.handlerProps.log(
+ `sql-get-table-schema raised an error. ${e.message}`
+ );
+ return e.message;
+ }
+ },
+ });
+ },
+ };
+ },
+};
diff --git a/server/utils/agents/aibitat/plugins/sql-agent/index.js b/server/utils/agents/aibitat/plugins/sql-agent/index.js
new file mode 100644
index 00000000000..b7c1ed7d387
--- /dev/null
+++ b/server/utils/agents/aibitat/plugins/sql-agent/index.js
@@ -0,0 +1,21 @@
+const { SqlAgentGetTableSchema } = require("./get-table-schema");
+const { SqlAgentListDatabase } = require("./list-database");
+const { SqlAgentListTables } = require("./list-table");
+const { SqlAgentQuery } = require("./query");
+
+const sqlAgent = {
+ name: "sql-agent",
+ startupConfig: {
+ params: {},
+ },
+ plugin: [
+ SqlAgentListDatabase,
+ SqlAgentListTables,
+ SqlAgentGetTableSchema,
+ SqlAgentQuery,
+ ],
+};
+
+module.exports = {
+ sqlAgent,
+};
diff --git a/server/utils/agents/aibitat/plugins/sql-agent/list-database.js b/server/utils/agents/aibitat/plugins/sql-agent/list-database.js
new file mode 100644
index 00000000000..20e67c281d4
--- /dev/null
+++ b/server/utils/agents/aibitat/plugins/sql-agent/list-database.js
@@ -0,0 +1,49 @@
+module.exports.SqlAgentListDatabase = {
+ name: "sql-list-databases",
+ plugin: function () {
+ const { listSQLConnections } = require("./SQLConnectors");
+ return {
+ name: "sql-list-databases",
+ setup(aibitat) {
+ aibitat.function({
+ super: aibitat,
+ name: this.name,
+ description:
+ "List all available databases via `list_databases` you currently have access to. Returns a unique string identifier `database_id` that can be used for future calls.",
+ examples: [
+ {
+ prompt: "What databases can you access?",
+ call: JSON.stringify({}),
+ },
+ {
+ prompt: "What databases can you tell me about?",
+ call: JSON.stringify({}),
+ },
+ {
+ prompt: "Is there a database named erp-logs you can access?",
+ call: JSON.stringify({}),
+ },
+ ],
+ parameters: {
+ $schema: "http://json-schema.org/draft-07/schema#",
+ type: "object",
+ properties: {},
+ additionalProperties: false,
+ },
+ handler: async function () {
+ this.super.handlerProps.log(`Using the sql-list-databases tool.`);
+ this.super.introspect(
+ `${this.caller}: Checking what are the available databases.`
+ );
+
+ const connections = (await listSQLConnections()).map((conn) => {
+ const { connectionString, ...rest } = conn;
+ return rest;
+ });
+ return JSON.stringify(connections);
+ },
+ });
+ },
+ };
+ },
+};
diff --git a/server/utils/agents/aibitat/plugins/sql-agent/list-table.js b/server/utils/agents/aibitat/plugins/sql-agent/list-table.js
new file mode 100644
index 00000000000..d186bf01e0d
--- /dev/null
+++ b/server/utils/agents/aibitat/plugins/sql-agent/list-table.js
@@ -0,0 +1,85 @@
+module.exports.SqlAgentListTables = {
+ name: "sql-list-tables",
+ plugin: function () {
+ const {
+ listSQLConnections,
+ getDBClient,
+ } = require("./SQLConnectors/index.js");
+
+ return {
+ name: "sql-list-tables",
+ setup(aibitat) {
+ aibitat.function({
+ super: aibitat,
+ name: this.name,
+ description:
+ "List all available tables in a database via its `database_id`.",
+ examples: [
+ {
+ prompt: "What tables are there in the `access-logs` database?",
+ call: JSON.stringify({ database_id: "access-logs" }),
+ },
+ {
+ prompt:
+ "What information can you access in the customer_accts postgres db?",
+ call: JSON.stringify({ database_id: "customer_accts" }),
+ },
+ {
+ prompt: "Can you tell me what is in the primary-logs db?",
+ call: JSON.stringify({ database_id: "primary-logs" }),
+ },
+ ],
+ parameters: {
+ $schema: "http://json-schema.org/draft-07/schema#",
+ type: "object",
+ properties: {
+ database_id: {
+ type: "string",
+ description:
+ "The database identifier for which we will list all tables for. This is a required parameter",
+ },
+ },
+ additionalProperties: false,
+ },
+ required: ["database_id"],
+ handler: async function ({ database_id = "" }) {
+ try {
+ this.super.handlerProps.log(`Using the sql-list-tables tool.`);
+ const databaseConfig = (await listSQLConnections()).find(
+ (db) => db.database_id === database_id
+ );
+ if (!databaseConfig) {
+ this.super.handlerProps.log(
+ `sql-list-tables failed to find config!.`,
+ database_id
+ );
+ return `No database connection for ${database_id} was found!`;
+ }
+
+ const db = getDBClient(databaseConfig.engine, databaseConfig);
+ this.super.introspect(
+ `${this.caller}: Checking what are the available tables in the ${databaseConfig.database_id} database.`
+ );
+
+ this.super.introspect(`Running SQL: ${db.getTablesSql()}`);
+ const result = await db.runQuery(db.getTablesSql(database_id));
+ if (result.error) {
+ this.super.handlerProps.log(
+ `sql-list-tables tool reported error`,
+ result.error
+ );
+ this.super.introspect(`Error: ${result.error}`);
+ return `There was an error running the query: ${result.error}`;
+ }
+
+ return JSON.stringify(result);
+ } catch (e) {
+ console.error(e);
+ return e.message;
+ }
+ },
+ });
+ },
+ };
+ },
+};
diff --git a/server/utils/agents/aibitat/plugins/sql-agent/query.js b/server/utils/agents/aibitat/plugins/sql-agent/query.js
new file mode 100644
index 00000000000..fca1aeb0368
--- /dev/null
+++ b/server/utils/agents/aibitat/plugins/sql-agent/query.js
@@ -0,0 +1,101 @@
+module.exports.SqlAgentQuery = {
+ name: "sql-query",
+ plugin: function () {
+ const {
+ getDBClient,
+ listSQLConnections,
+ } = require("./SQLConnectors/index.js");
+
+ return {
+ name: "sql-query",
+ setup(aibitat) {
+ aibitat.function({
+ super: aibitat,
+ name: this.name,
+ description:
+ "Run a read-only SQL query on a `database_id` which will return up rows of data related to the query. The query must only be SELECT statements which do not modify the table data. There should be a reasonable LIMIT on the return quantity to prevent long-running or queries which crash the db.",
+ examples: [
+ {
+ prompt: "How many customers are in dvd-rentals?",
+ call: JSON.stringify({
+ database_id: "dvd-rentals",
+ sql_query: "SELECT * FROM customers",
+ }),
+ },
+ {
+ prompt: "Can you tell me the total volume of sales last month?",
+ call: JSON.stringify({
+ database_id: "sales-db",
+ sql_query:
+ "SELECT SUM(sale_amount) AS total_sales FROM sales WHERE sale_date >= DATEADD(month, -1, DATEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE()), 1)) AND sale_date < DATEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE()), 1)",
+ }),
+ },
+ {
+ prompt:
+ "Do we have anyone in the staff table for our production db named 'sam'? ",
+ call: JSON.stringify({
+ database_id: "production",
+ sql_query:
+ "SElECT * FROM staff WHERE first_name='sam%' OR last_name='sam%'",
+ }),
+ },
+ ],
+ parameters: {
+ $schema: "http://json-schema.org/draft-07/schema#",
+ type: "object",
+ properties: {
+ database_id: {
+ type: "string",
+ description:
+ "The database identifier for which we will connect to to query the table schema. This is required to run the SQL query.",
+ },
+ sql_query: {
+ type: "string",
+ description:
+ "The raw SQL query to run. Should be a query which does not modify the table and will return results.",
+ },
+ },
+ additionalProperties: false,
+ },
+ required: ["database_id", "table_name"],
+ handler: async function ({ database_id = "", sql_query = "" }) {
+ this.super.handlerProps.log(`Using the sql-query tool.`);
+ try {
+ const databaseConfig = (await listSQLConnections()).find(
+ (db) => db.database_id === database_id
+ );
+ if (!databaseConfig) {
+ this.super.handlerProps.log(
+ `sql-query failed to find config!.`,
+ database_id
+ );
+ return `No database connection for ${database_id} was found!`;
+ }
+
+ this.super.introspect(
+ `${this.caller}: Im going to run a query on the ${database_id} to get an answer.`
+ );
+ const db = getDBClient(databaseConfig.engine, databaseConfig);
+
+ this.super.introspect(`Running SQL: ${sql_query}`);
+ const result = await db.runQuery(sql_query);
+ if (result.error) {
+ this.super.handlerProps.log(
+ `sql-query tool reported error`,
+ result.error
+ );
+ this.super.introspect(`Error: ${result.error}`);
+ return `There was an error running the query: ${result.error}`;
+ }
+
+ return JSON.stringify(result);
+ } catch (e) {
+ console.error(e);
+ return e.message;
+ }
+ },
+ });
+ },
+ };
+ },
+};
diff --git a/server/utils/agents/aibitat/plugins/websocket.js b/server/utils/agents/aibitat/plugins/websocket.js
index b6154984d28..f5c73b33b78 100644
--- a/server/utils/agents/aibitat/plugins/websocket.js
+++ b/server/utils/agents/aibitat/plugins/websocket.js
@@ -49,7 +49,7 @@ const websocket = {
setup(aibitat) {
aibitat.onError(async (error) => {
if (!!error?.message) {
- console.error(chalk.red(` error: ${error.message}`));
+ console.error(chalk.red(` error: ${error.message}`), error);
aibitat.introspect(
`Error encountered while running: ${error.message}`
);
diff --git a/server/utils/agents/aibitat/providers/anthropic.js b/server/utils/agents/aibitat/providers/anthropic.js
index 307731ba7a4..b69b14d6c2e 100644
--- a/server/utils/agents/aibitat/providers/anthropic.js
+++ b/server/utils/agents/aibitat/providers/anthropic.js
@@ -3,7 +3,7 @@ const { RetryError } = require("../error.js");
const Provider = require("./ai-provider.js");
/**
- * The provider for the Anthropic API.
+ * The agent provider for the Anthropic API.
* By default, the model is set to 'claude-2'.
*/
class AnthropicProvider extends Provider {
diff --git a/server/utils/agents/aibitat/providers/azure.js b/server/utils/agents/aibitat/providers/azure.js
index cdcf7618bfd..0ecc398f1b9 100644
--- a/server/utils/agents/aibitat/providers/azure.js
+++ b/server/utils/agents/aibitat/providers/azure.js
@@ -4,7 +4,7 @@ const InheritMultiple = require("./helpers/classes.js");
const UnTooled = require("./helpers/untooled.js");
/**
- * The provider for the Azure OpenAI API.
+ * The agent provider for the Azure OpenAI API.
*/
class AzureOpenAiProvider extends InheritMultiple([Provider, UnTooled]) {
model;
@@ -84,6 +84,11 @@ class AzureOpenAiProvider extends InheritMultiple([Provider, UnTooled]) {
);
completion = response.choices[0].message;
}
+
+ // The UnTooled class inherited Deduplicator is mostly useful to prevent the agent
+ // from calling the exact same function over and over in a loop within a single chat exchange
+ // _but_ we should enable it to call previously used tools in a new chat interaction.
+ this.deduplicator.reset("runs");
return { result: completion.content, cost: 0 };
} catch (error) {
throw error;
diff --git a/server/utils/agents/aibitat/providers/genericOpenAi.js b/server/utils/agents/aibitat/providers/genericOpenAi.js
index e41476d2a66..a1b2db3ea57 100644
--- a/server/utils/agents/aibitat/providers/genericOpenAi.js
+++ b/server/utils/agents/aibitat/providers/genericOpenAi.js
@@ -4,7 +4,7 @@ const InheritMultiple = require("./helpers/classes.js");
const UnTooled = require("./helpers/untooled.js");
/**
- * The provider for the Generic OpenAI provider.
+ * The agent provider for the Generic OpenAI provider.
* Since we cannot promise the generic provider even supports tool calling
* which is nearly 100% likely it does not, we can just wrap it in untooled
* which often is far better anyway.
@@ -94,6 +94,10 @@ class GenericOpenAiProvider extends InheritMultiple([Provider, UnTooled]) {
completion = response.choices[0].message;
}
+ // The UnTooled class inherited Deduplicator is mostly useful to prevent the agent
+ // from calling the exact same function over and over in a loop within a single chat exchange
+ // _but_ we should enable it to call previously used tools in a new chat interaction.
+ this.deduplicator.reset("runs");
return {
result: completion.content,
cost: 0,
diff --git a/server/utils/agents/aibitat/providers/groq.js b/server/utils/agents/aibitat/providers/groq.js
index 720d8743734..01f69f7c110 100644
--- a/server/utils/agents/aibitat/providers/groq.js
+++ b/server/utils/agents/aibitat/providers/groq.js
@@ -3,7 +3,7 @@ const Provider = require("./ai-provider.js");
const { RetryError } = require("../error.js");
/**
- * The provider for the Groq provider.
+ * The agent provider for the Groq provider.
* Using OpenAI tool calling with groq really sucks right now
* its just fast and bad. We should probably migrate this to Untooled to improve
* coherence.
diff --git a/server/utils/agents/aibitat/providers/koboldcpp.js b/server/utils/agents/aibitat/providers/koboldcpp.js
index 77088263cf2..2dd12784587 100644
--- a/server/utils/agents/aibitat/providers/koboldcpp.js
+++ b/server/utils/agents/aibitat/providers/koboldcpp.js
@@ -4,7 +4,7 @@ const InheritMultiple = require("./helpers/classes.js");
const UnTooled = require("./helpers/untooled.js");
/**
- * The provider for the KoboldCPP provider.
+ * The agent provider for the KoboldCPP provider.
*/
class KoboldCPPProvider extends InheritMultiple([Provider, UnTooled]) {
model;
@@ -89,6 +89,10 @@ class KoboldCPPProvider extends InheritMultiple([Provider, UnTooled]) {
completion = response.choices[0].message;
}
+ // The UnTooled class inherited Deduplicator is mostly useful to prevent the agent
+ // from calling the exact same function over and over in a loop within a single chat exchange
+ // _but_ we should enable it to call previously used tools in a new chat interaction.
+ this.deduplicator.reset("runs");
return {
result: completion.content,
cost: 0,
diff --git a/server/utils/agents/aibitat/providers/lmstudio.js b/server/utils/agents/aibitat/providers/lmstudio.js
index f5c4a2e82c8..258f2e29114 100644
--- a/server/utils/agents/aibitat/providers/lmstudio.js
+++ b/server/utils/agents/aibitat/providers/lmstudio.js
@@ -4,7 +4,7 @@ const InheritMultiple = require("./helpers/classes.js");
const UnTooled = require("./helpers/untooled.js");
/**
- * The provider for the LMStudio provider.
+ * The agent provider for the LMStudio.
*/
class LMStudioProvider extends InheritMultiple([Provider, UnTooled]) {
model;
@@ -89,6 +89,10 @@ class LMStudioProvider extends InheritMultiple([Provider, UnTooled]) {
completion = response.choices[0].message;
}
+ // The UnTooled class inherited Deduplicator is mostly useful to prevent the agent
+ // from calling the exact same function over and over in a loop within a single chat exchange
+ // _but_ we should enable it to call previously used tools in a new chat interaction.
+ this.deduplicator.reset("runs");
return {
result: completion.content,
cost: 0,
diff --git a/server/utils/agents/aibitat/providers/localai.js b/server/utils/agents/aibitat/providers/localai.js
index 161172c2154..bd0c3b5246d 100644
--- a/server/utils/agents/aibitat/providers/localai.js
+++ b/server/utils/agents/aibitat/providers/localai.js
@@ -4,7 +4,7 @@ const InheritMultiple = require("./helpers/classes.js");
const UnTooled = require("./helpers/untooled.js");
/**
- * The provider for the LocalAI provider.
+ * The agent provider for the LocalAI provider.
*/
class LocalAiProvider extends InheritMultiple([Provider, UnTooled]) {
model;
@@ -93,6 +93,10 @@ class LocalAiProvider extends InheritMultiple([Provider, UnTooled]) {
completion = response.choices[0].message;
}
+ // The UnTooled class inherited Deduplicator is mostly useful to prevent the agent
+ // from calling the exact same function over and over in a loop within a single chat exchange
+ // _but_ we should enable it to call previously used tools in a new chat interaction.
+ this.deduplicator.reset("runs");
return { result: completion.content, cost: 0 };
} catch (error) {
throw error;
diff --git a/server/utils/agents/aibitat/providers/mistral.js b/server/utils/agents/aibitat/providers/mistral.js
index cdc2a5e75fa..aa2c1c6ec44 100644
--- a/server/utils/agents/aibitat/providers/mistral.js
+++ b/server/utils/agents/aibitat/providers/mistral.js
@@ -4,7 +4,7 @@ const InheritMultiple = require("./helpers/classes.js");
const UnTooled = require("./helpers/untooled.js");
/**
- * The provider for the Mistral provider.
+ * The agent provider for the Mistral provider.
* Mistral limits what models can call tools and even when using those
* the model names change and dont match docs. When you do have the right model
* it still fails and is not truly OpenAI compatible so its easier to just wrap
@@ -93,6 +93,10 @@ class MistralProvider extends InheritMultiple([Provider, UnTooled]) {
completion = response.choices[0].message;
}
+ // The UnTooled class inherited Deduplicator is mostly useful to prevent the agent
+ // from calling the exact same function over and over in a loop within a single chat exchange
+ // _but_ we should enable it to call previously used tools in a new chat interaction.
+ this.deduplicator.reset("runs");
return {
result: completion.content,
cost: 0,
diff --git a/server/utils/agents/aibitat/providers/ollama.js b/server/utils/agents/aibitat/providers/ollama.js
index d52d80caa08..5cb529e51b3 100644
--- a/server/utils/agents/aibitat/providers/ollama.js
+++ b/server/utils/agents/aibitat/providers/ollama.js
@@ -4,7 +4,7 @@ const UnTooled = require("./helpers/untooled.js");
const { Ollama } = require("ollama");
/**
- * The provider for the Ollama provider.
+ * The agent provider for the Ollama provider.
*/
class OllamaProvider extends InheritMultiple([Provider, UnTooled]) {
model;
@@ -83,6 +83,10 @@ class OllamaProvider extends InheritMultiple([Provider, UnTooled]) {
completion = response.message;
}
+ // The UnTooled class inherited Deduplicator is mostly useful to prevent the agent
+ // from calling the exact same function over and over in a loop within a single chat exchange
+ // _but_ we should enable it to call previously used tools in a new chat interaction.
+ this.deduplicator.reset("runs");
return {
result: completion.content,
cost: 0,
diff --git a/server/utils/agents/aibitat/providers/openai.js b/server/utils/agents/aibitat/providers/openai.js
index 3fcc46ca5b8..2866a7592b4 100644
--- a/server/utils/agents/aibitat/providers/openai.js
+++ b/server/utils/agents/aibitat/providers/openai.js
@@ -3,7 +3,7 @@ const Provider = require("./ai-provider.js");
const { RetryError } = require("../error.js");
/**
- * The provider for the OpenAI API.
+ * The agent provider for the OpenAI API.
* By default, the model is set to 'gpt-3.5-turbo'.
*/
class OpenAIProvider extends Provider {
diff --git a/server/utils/agents/aibitat/providers/openrouter.js b/server/utils/agents/aibitat/providers/openrouter.js
index 81297ae28a2..50c0868ddee 100644
--- a/server/utils/agents/aibitat/providers/openrouter.js
+++ b/server/utils/agents/aibitat/providers/openrouter.js
@@ -4,7 +4,7 @@ const InheritMultiple = require("./helpers/classes.js");
const UnTooled = require("./helpers/untooled.js");
/**
- * The provider for the OpenRouter provider.
+ * The agent provider for the OpenRouter provider.
*/
class OpenRouterProvider extends InheritMultiple([Provider, UnTooled]) {
model;
@@ -93,6 +93,10 @@ class OpenRouterProvider extends InheritMultiple([Provider, UnTooled]) {
completion = response.choices[0].message;
}
+ // The UnTooled class inherited Deduplicator is mostly useful to prevent the agent
+ // from calling the exact same function over and over in a loop within a single chat exchange
+ // _but_ we should enable it to call previously used tools in a new chat interaction.
+ this.deduplicator.reset("runs");
return {
result: completion.content,
cost: 0,
diff --git a/server/utils/agents/aibitat/providers/perplexity.js b/server/utils/agents/aibitat/providers/perplexity.js
index 29970fd064f..07220695088 100644
--- a/server/utils/agents/aibitat/providers/perplexity.js
+++ b/server/utils/agents/aibitat/providers/perplexity.js
@@ -4,7 +4,7 @@ const InheritMultiple = require("./helpers/classes.js");
const UnTooled = require("./helpers/untooled.js");
/**
- * The provider for the Perplexity provider.
+ * The agent provider for the Perplexity provider.
*/
class PerplexityProvider extends InheritMultiple([Provider, UnTooled]) {
model;
@@ -89,6 +89,10 @@ class PerplexityProvider extends InheritMultiple([Provider, UnTooled]) {
completion = response.choices[0].message;
}
+ // The UnTooled class inherited Deduplicator is mostly useful to prevent the agent
+ // from calling the exact same function over and over in a loop within a single chat exchange
+ // _but_ we should enable it to call previously used tools in a new chat interaction.
+ this.deduplicator.reset("runs");
return {
result: completion.content,
cost: 0,
diff --git a/server/utils/agents/aibitat/providers/textgenwebui.js b/server/utils/agents/aibitat/providers/textgenwebui.js
index d1e424255a4..7ef1cf4c6e6 100644
--- a/server/utils/agents/aibitat/providers/textgenwebui.js
+++ b/server/utils/agents/aibitat/providers/textgenwebui.js
@@ -4,7 +4,7 @@ const InheritMultiple = require("./helpers/classes.js");
const UnTooled = require("./helpers/untooled.js");
/**
- * The provider for the Oobabooga provider.
+ * The agent provider for the Oobabooga provider.
*/
class TextWebGenUiProvider extends InheritMultiple([Provider, UnTooled]) {
model;
@@ -88,6 +88,10 @@ class TextWebGenUiProvider extends InheritMultiple([Provider, UnTooled]) {
completion = response.choices[0].message;
}
+ // The UnTooled class inherited Deduplicator is mostly useful to prevent the agent
+ // from calling the exact same function over and over in a loop within a single chat exchange
+ // _but_ we should enable it to call previously used tools in a new chat interaction.
+ this.deduplicator.reset("runs");
return {
result: completion.content,
cost: 0,
diff --git a/server/utils/agents/aibitat/providers/togetherai.js b/server/utils/agents/aibitat/providers/togetherai.js
index 4ea5e11c2ef..78cbb512c68 100644
--- a/server/utils/agents/aibitat/providers/togetherai.js
+++ b/server/utils/agents/aibitat/providers/togetherai.js
@@ -4,7 +4,7 @@ const InheritMultiple = require("./helpers/classes.js");
const UnTooled = require("./helpers/untooled.js");
/**
- * The provider for the TogetherAI provider.
+ * The agent provider for the TogetherAI provider.
*/
class TogetherAIProvider extends InheritMultiple([Provider, UnTooled]) {
model;
@@ -89,6 +89,10 @@ class TogetherAIProvider extends InheritMultiple([Provider, UnTooled]) {
completion = response.choices[0].message;
}
+ // The UnTooled class inherited Deduplicator is mostly useful to prevent the agent
+ // from calling the exact same function over and over in a loop within a single chat exchange
+ // _but_ we should enable it to call previously used tools in a new chat interaction.
+ this.deduplicator.reset("runs");
return {
result: completion.content,
cost: 0,
diff --git a/server/utils/agents/aibitat/utils/dedupe.js b/server/utils/agents/aibitat/utils/dedupe.js
index 8c4d582d0c5..321f69299a9 100644
--- a/server/utils/agents/aibitat/utils/dedupe.js
+++ b/server/utils/agents/aibitat/utils/dedupe.js
@@ -38,6 +38,25 @@ class Deduplicator {
return this.#hashes.hasOwnProperty(newSig);
}
+ /**
+ * Resets the object property for this instance of the Deduplicator class
+ * @param {('runs'|'cooldowns'|'uniques')} type - The type of prop to reset
+ */
+ reset(type = "runs") {
+ switch (type) {
+ case "runs":
+ this.#hashes = {};
+ break;
+ case "cooldowns":
+ this.#cooldowns = {};
+ break;
+ case "uniques":
+ this.#uniques = {};
+ break;
+ }
+ return;
+ }
+
startCooldown(
key,
parameters = {
diff --git a/server/utils/agents/defaults.js b/server/utils/agents/defaults.js
index 4e12b90621c..796a7bbcb17 100644
--- a/server/utils/agents/defaults.js
+++ b/server/utils/agents/defaults.js
@@ -25,8 +25,22 @@ const WORKSPACE_AGENT = {
const _setting = (
await SystemSettings.get({ label: "default_agent_skills" })
)?.value;
+
safeJsonParse(_setting, []).forEach((skillName) => {
if (!AgentPlugins.hasOwnProperty(skillName)) return;
+
+ // This is a plugin module with many sub-children plugins who
+ // need to be named via `${parent}#${child}` naming convention
+ if (Array.isArray(AgentPlugins[skillName].plugin)) {
+ for (const subPlugin of AgentPlugins[skillName].plugin) {
+ defaultFunctions.push(
+ `${AgentPlugins[skillName].name}#${subPlugin.name}`
+ );
+ }
+ return;
+ }
+
+ // This is normal single-stage plugin
defaultFunctions.push(AgentPlugins[skillName].name);
});
diff --git a/server/utils/agents/index.js b/server/utils/agents/index.js
index 08ce5558ec0..cf6f312d0ea 100644
--- a/server/utils/agents/index.js
+++ b/server/utils/agents/index.js
@@ -197,33 +197,71 @@ class AgentHandler {
this.invocation = invocation ?? null;
}
- #attachPlugins(args) {
- for (const name of this.#funcsToLoad) {
- if (!AgentPlugins.hasOwnProperty(name)) {
+ #parseCallOptions(args, config = {}, pluginName) {
+ const callOpts = {};
+ for (const [param, definition] of Object.entries(config)) {
+ if (
+ definition.required &&
+ (!args.hasOwnProperty(param) || args[param] === null)
+ ) {
this.log(
- `${name} is not a valid plugin. Skipping inclusion to agent cluster.`
+ `'${param}' required parameter for '${pluginName}' plugin is missing. Plugin may not function or crash agent.`
);
continue;
}
+ callOpts[param] = args.hasOwnProperty(param)
+ ? args[param]
+ : definition.default || null;
+ }
+ return callOpts;
+ }
- const callOpts = {};
- for (const [param, definition] of Object.entries(
- AgentPlugins[name].startupConfig.params
- )) {
- if (
- definition.required &&
- (!args.hasOwnProperty(param) || args[param] === null)
- ) {
+ #attachPlugins(args) {
+ for (const name of this.#funcsToLoad) {
+ // Load child plugin
+ if (name.includes("#")) {
+ const [parent, childPluginName] = name.split("#");
+ if (!AgentPlugins.hasOwnProperty(parent)) {
+ this.log(
+ `${parent} is not a valid plugin. Skipping inclusion to agent cluster.`
+ );
+ continue;
+ }
+
+ const childPlugin = AgentPlugins[parent].plugin.find(
+ (child) => child.name === childPluginName
+ );
+ if (!childPlugin) {
this.log(
- `'${param}' required parameter for '${name}' plugin is missing. Plugin may not function or crash agent.`
+ `${parent} does not have child plugin named ${childPluginName}. Skipping inclusion to agent cluster.`
);
continue;
}
- callOpts[param] = args.hasOwnProperty(param)
- ? args[param]
- : definition.default || null;
+
+ const callOpts = this.#parseCallOptions(
+ args,
+ childPlugin?.startupConfig?.params,
+ name
+ );
+ this.aibitat.use(childPlugin.plugin(callOpts));
+ this.log(
+ `Attached ${parent}:${childPluginName} plugin to Agent cluster`
+ );
+ continue;
+ }
+
+ // Load single-stage plugin.
+ if (!AgentPlugins.hasOwnProperty(name)) {
+ this.log(
+ `${name} is not a valid plugin. Skipping inclusion to agent cluster.`
+ );
+ continue;
}
+ const callOpts = this.#parseCallOptions(
+ args,
+ AgentPlugins[name].startupConfig.params
+ );
const AIbitatPlugin = AgentPlugins[name];
this.aibitat.use(AIbitatPlugin.plugin(callOpts));
this.log(`Attached ${name} plugin to Agent cluster`);
diff --git a/server/yarn.lock b/server/yarn.lock
index 9e4f184d5f0..d274e574f3c 100644
--- a/server/yarn.lock
+++ b/server/yarn.lock
@@ -82,6 +82,13 @@
"@azure/core-util" "^1.0.0"
tslib "^2.6.2"
+"@azure/abort-controller@^1.0.0":
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/@azure/abort-controller/-/abort-controller-1.1.0.tgz#788ee78457a55af8a1ad342acb182383d2119249"
+ integrity sha512-TrRLIoSQVzfAJX9H1JeFjzAoDGcoK1IYX1UImfceTZpsyYfWr09Ss1aHW1y5TrrR3iq6RZLBwJ3E24uwPhwahw==
+ dependencies:
+ tslib "^2.2.0"
+
"@azure/abort-controller@^2.0.0":
version "2.1.2"
resolved "https://registry.yarnpkg.com/@azure/abort-controller/-/abort-controller-2.1.2.tgz#42fe0ccab23841d9905812c58f1082d27784566d"
@@ -89,7 +96,7 @@
dependencies:
tslib "^2.6.2"
-"@azure/core-auth@^1.3.0", "@azure/core-auth@^1.4.0":
+"@azure/core-auth@^1.3.0", "@azure/core-auth@^1.4.0", "@azure/core-auth@^1.5.0":
version "1.7.2"
resolved "https://registry.yarnpkg.com/@azure/core-auth/-/core-auth-1.7.2.tgz#558b7cb7dd12b00beec07ae5df5907d74df1ebd9"
integrity sha512-Igm/S3fDYmnMq1uKS38Ae1/m37B3zigdlZw+kocwEhh5GjyKjPrXKO2J6rzpC1wAxrNil/jX9BJRqBshyjnF3g==
@@ -98,6 +105,59 @@
"@azure/core-util" "^1.1.0"
tslib "^2.6.2"
+"@azure/core-client@^1.3.0", "@azure/core-client@^1.4.0", "@azure/core-client@^1.5.0":
+ version "1.9.2"
+ resolved "https://registry.yarnpkg.com/@azure/core-client/-/core-client-1.9.2.tgz#6fc69cee2816883ab6c5cdd653ee4f2ff9774f74"
+ integrity sha512-kRdry/rav3fUKHl/aDLd/pDLcB+4pOFwPPTVEExuMyaI5r+JBbMWqRbCY1pn5BniDaU3lRxO9eaQ1AmSMehl/w==
+ dependencies:
+ "@azure/abort-controller" "^2.0.0"
+ "@azure/core-auth" "^1.4.0"
+ "@azure/core-rest-pipeline" "^1.9.1"
+ "@azure/core-tracing" "^1.0.0"
+ "@azure/core-util" "^1.6.1"
+ "@azure/logger" "^1.0.0"
+ tslib "^2.6.2"
+
+"@azure/core-http-compat@^2.0.1":
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/@azure/core-http-compat/-/core-http-compat-2.1.2.tgz#d1585ada24ba750dc161d816169b33b35f762f0d"
+ integrity sha512-5MnV1yqzZwgNLLjlizsU3QqOeQChkIXw781Fwh1xdAqJR5AA32IUaq6xv1BICJvfbHoa+JYcaij2HFkhLbNTJQ==
+ dependencies:
+ "@azure/abort-controller" "^2.0.0"
+ "@azure/core-client" "^1.3.0"
+ "@azure/core-rest-pipeline" "^1.3.0"
+
+"@azure/core-lro@^2.2.0":
+ version "2.7.2"
+ resolved "https://registry.yarnpkg.com/@azure/core-lro/-/core-lro-2.7.2.tgz#787105027a20e45c77651a98b01a4d3b01b75a08"
+ integrity sha512-0YIpccoX8m/k00O7mDDMdJpbr6mf1yWo2dfmxt5A8XVZVVMz2SSKaEbMCeJRvgQ0IaSlqhjT47p4hVIRRy90xw==
+ dependencies:
+ "@azure/abort-controller" "^2.0.0"
+ "@azure/core-util" "^1.2.0"
+ "@azure/logger" "^1.0.0"
+ tslib "^2.6.2"
+
+"@azure/core-paging@^1.1.1":
+ version "1.6.2"
+ resolved "https://registry.yarnpkg.com/@azure/core-paging/-/core-paging-1.6.2.tgz#40d3860dc2df7f291d66350b2cfd9171526433e7"
+ integrity sha512-YKWi9YuCU04B55h25cnOYZHxXYtEvQEbKST5vqRga7hWY9ydd3FZHdeQF8pyh+acWZvppw13M/LMGx0LABUVMA==
+ dependencies:
+ tslib "^2.6.2"
+
+"@azure/core-rest-pipeline@^1.1.0", "@azure/core-rest-pipeline@^1.3.0", "@azure/core-rest-pipeline@^1.8.1", "@azure/core-rest-pipeline@^1.9.1":
+ version "1.16.0"
+ resolved "https://registry.yarnpkg.com/@azure/core-rest-pipeline/-/core-rest-pipeline-1.16.0.tgz#631172e2fe0346cf4410d1c8e01ad98d849738e2"
+ integrity sha512-CeuTvsXxCUmEuxH5g/aceuSl6w2EugvNHKAtKKVdiX915EjJJxAwfzNNWZreNnbxHZ2fi0zaM6wwS23x2JVqSQ==
+ dependencies:
+ "@azure/abort-controller" "^2.0.0"
+ "@azure/core-auth" "^1.4.0"
+ "@azure/core-tracing" "^1.0.1"
+ "@azure/core-util" "^1.9.0"
+ "@azure/logger" "^1.0.0"
+ http-proxy-agent "^7.0.0"
+ https-proxy-agent "^7.0.0"
+ tslib "^2.6.2"
+
"@azure/core-rest-pipeline@^1.13.0", "@azure/core-rest-pipeline@^1.5.0":
version "1.15.2"
resolved "https://registry.yarnpkg.com/@azure/core-rest-pipeline/-/core-rest-pipeline-1.15.2.tgz#421729bbd8cd5f9f50b403e79941f27ac1bdc302"
@@ -119,14 +179,14 @@
dependencies:
tslib "^2.6.2"
-"@azure/core-tracing@^1.0.1":
+"@azure/core-tracing@^1.0.0", "@azure/core-tracing@^1.0.1":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@azure/core-tracing/-/core-tracing-1.1.2.tgz#065dab4e093fb61899988a1cdbc827d9ad90b4ee"
integrity sha512-dawW9ifvWAWmUm9/h+/UQ2jrdvjCJ7VJEuCJ6XVNudzcOwm53BFZH4Q845vjfgoUAM8ZxokvVNxNxAITc502YA==
dependencies:
tslib "^2.6.2"
-"@azure/core-util@^1.0.0", "@azure/core-util@^1.1.0", "@azure/core-util@^1.3.0", "@azure/core-util@^1.4.0":
+"@azure/core-util@^1.0.0", "@azure/core-util@^1.1.0", "@azure/core-util@^1.2.0", "@azure/core-util@^1.3.0", "@azure/core-util@^1.4.0", "@azure/core-util@^1.6.1", "@azure/core-util@^1.9.0":
version "1.9.0"
resolved "https://registry.yarnpkg.com/@azure/core-util/-/core-util-1.9.0.tgz#469afd7e6452d5388b189f90d33f7756b0b210d1"
integrity sha512-AfalUQ1ZppaKuxPPMsFEUdX6GZPB3d9paR9d/TTL7Ow2De8cJaC7ibi7kWVlFAVPCYo31OcnGymc0R89DX8Oaw==
@@ -134,6 +194,43 @@
"@azure/abort-controller" "^2.0.0"
tslib "^2.6.2"
+"@azure/identity@^3.4.1":
+ version "3.4.2"
+ resolved "https://registry.yarnpkg.com/@azure/identity/-/identity-3.4.2.tgz#6b01724c9caac7cadab6b63c76584345bda8e2de"
+ integrity sha512-0q5DL4uyR0EZ4RXQKD8MadGH6zTIcloUoS/RVbCpNpej4pwte0xpqYxk8K97Py2RiuUvI7F4GXpoT4046VfufA==
+ dependencies:
+ "@azure/abort-controller" "^1.0.0"
+ "@azure/core-auth" "^1.5.0"
+ "@azure/core-client" "^1.4.0"
+ "@azure/core-rest-pipeline" "^1.1.0"
+ "@azure/core-tracing" "^1.0.0"
+ "@azure/core-util" "^1.6.1"
+ "@azure/logger" "^1.0.0"
+ "@azure/msal-browser" "^3.5.0"
+ "@azure/msal-node" "^2.5.1"
+ events "^3.0.0"
+ jws "^4.0.0"
+ open "^8.0.0"
+ stoppable "^1.1.0"
+ tslib "^2.2.0"
+
+"@azure/keyvault-keys@^4.4.0":
+ version "4.8.0"
+ resolved "https://registry.yarnpkg.com/@azure/keyvault-keys/-/keyvault-keys-4.8.0.tgz#1513b3a187bb3a9a372b5980c593962fb793b2ad"
+ integrity sha512-jkuYxgkw0aaRfk40OQhFqDIupqblIOIlYESWB6DKCVDxQet1pyv86Tfk9M+5uFM0+mCs6+MUHU+Hxh3joiUn4Q==
+ dependencies:
+ "@azure/abort-controller" "^1.0.0"
+ "@azure/core-auth" "^1.3.0"
+ "@azure/core-client" "^1.5.0"
+ "@azure/core-http-compat" "^2.0.1"
+ "@azure/core-lro" "^2.2.0"
+ "@azure/core-paging" "^1.1.1"
+ "@azure/core-rest-pipeline" "^1.8.1"
+ "@azure/core-tracing" "^1.0.0"
+ "@azure/core-util" "^1.0.0"
+ "@azure/logger" "^1.0.0"
+ tslib "^2.2.0"
+
"@azure/logger@^1.0.0", "@azure/logger@^1.0.3":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@azure/logger/-/logger-1.1.2.tgz#3f4b876cefad328dc14aff8b850d63b611e249dc"
@@ -141,6 +238,27 @@
dependencies:
tslib "^2.6.2"
+"@azure/msal-browser@^3.5.0":
+ version "3.14.0"
+ resolved "https://registry.yarnpkg.com/@azure/msal-browser/-/msal-browser-3.14.0.tgz#1cb5cab438a9943212aa50c403d11f775c787b21"
+ integrity sha512-Un85LhOoecJ3HDTS3Uv3UWnXC9/43ZSO+Kc+anSqpZvcEt58SiO/3DuVCAe1A3I5UIBYJNMgTmZPGXQ0MVYrwA==
+ dependencies:
+ "@azure/msal-common" "14.10.0"
+
+"@azure/msal-common@14.10.0":
+ version "14.10.0"
+ resolved "https://registry.yarnpkg.com/@azure/msal-common/-/msal-common-14.10.0.tgz#215449726717b53d549953db77562cad6cb8421c"
+ integrity sha512-Zk6DPDz7e1wPgLoLgAp0349Yay9RvcjPM5We/ehuenDNsz/t9QEFI7tRoHpp/e47I4p20XE3FiDlhKwAo3utDA==
+
+"@azure/msal-node@^2.5.1":
+ version "2.8.1"
+ resolved "https://registry.yarnpkg.com/@azure/msal-node/-/msal-node-2.8.1.tgz#aded28d37eea2e7278c9bd44f2016647390f239c"
+ integrity sha512-VcZZM+5VvCWRBTOF7SxMKaxrz+EXjntx2u5AQe7QE06e6FuPJElGBrImgNgCh5QmFaNCfVFO+3qNR7UoFD/Gfw==
+ dependencies:
+ "@azure/msal-common" "14.10.0"
+ jsonwebtoken "^9.0.0"
+ uuid "^8.3.0"
+
"@azure/openai@1.0.0-beta.10":
version "1.0.0-beta.10"
resolved "https://registry.yarnpkg.com/@azure/openai/-/openai-1.0.0-beta.10.tgz#13bcf5c5bc34dd27e33dc6aab5db3dc97dd4545b"
@@ -427,6 +545,11 @@
resolved "https://registry.yarnpkg.com/@inquirer/type/-/type-1.3.1.tgz#afb95ff78f44fff7e8a00e17d5820db6add2a076"
integrity sha512-Pe3PFccjPVJV1vtlfVvm9OnlbxqdnP5QcscFEFEnK5quChf1ufZtM0r8mR5ToWHMxZOh0s8o/qp9ANGRTo/DAw==
+"@js-joda/core@^5.5.3":
+ version "5.6.2"
+ resolved "https://registry.yarnpkg.com/@js-joda/core/-/core-5.6.2.tgz#1885d10daa404cea2bd55575f910ab3bbe6c33d7"
+ integrity sha512-ow4R+7C24xeTjiMTTZ4k6lvxj7MRBqvqLCQjThQff3RjOmIMokMP20LNYVFhGafJtUx/Xo2Qp4qU8eNoTVH0SA==
+
"@js-sdsl/ordered-map@^4.4.2":
version "4.4.2"
resolved "https://registry.yarnpkg.com/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz#9299f82874bab9e4c7f9c48d865becbfe8d6907c"
@@ -954,6 +1077,11 @@
resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.29.6.tgz#4cd8372f9247372edd5fc5af44f67e2032c46e2f"
integrity sha512-aX5IFYWlMa7tQ8xZr3b2gtVReCvg7f3LEhjir/JAjX2bJCMVJA5tIPv30wTD4KDfcwMd7DDYY3hFDeGmOgtrZQ==
+"@tediousjs/connection-string@^0.5.0":
+ version "0.5.0"
+ resolved "https://registry.yarnpkg.com/@tediousjs/connection-string/-/connection-string-0.5.0.tgz#9b3d858c040aac6bdf5584bf45370cef5b6522b4"
+ integrity sha512-7qSgZbincDDDFyRweCIEvZULFAw5iz/DeunhvuxpL31nfntX3P4Yd4HkHBRg9H8CdqY1e5WFN1PZIz/REL9MVQ==
+
"@tootallnate/once@1":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82"
@@ -1030,6 +1158,14 @@
resolved "https://registry.yarnpkg.com/@types/pad-left/-/pad-left-2.1.1.tgz#17d906fc75804e1cc722da73623f1d978f16a137"
integrity sha512-Xd22WCRBydkGSApl5Bw0PhAOHKSVjNL3E3AwzKaps96IMraPqy5BvZIsBVK6JLwdybUzjHnuWVwpDd0JjTfHXA==
+"@types/readable-stream@^4.0.0":
+ version "4.0.14"
+ resolved "https://registry.yarnpkg.com/@types/readable-stream/-/readable-stream-4.0.14.tgz#5a76a00e1e3dd6ff921ea2b3fac7485c5a492c19"
+ integrity sha512-xZn/AuUbCMShGsqH/ehZtGDwQtbx00M9rZ2ENLe4tOjFZ/JFeWMhEZkk2fEe1jAUqqEAURIkFJ7Az/go8mM1/w==
+ dependencies:
+ "@types/node" "*"
+ safe-buffer "~5.1.1"
+
"@types/retry@0.12.0":
version "0.12.0"
resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.0.tgz#2b35eccfcee7d38cd72ad99232fbd58bffb3c84d"
@@ -1539,6 +1675,16 @@ bl@^5.0.0:
inherits "^2.0.4"
readable-stream "^3.4.0"
+bl@^6.0.3:
+ version "6.0.12"
+ resolved "https://registry.yarnpkg.com/bl/-/bl-6.0.12.tgz#77c35b96e13aeff028496c798b75389ddee9c7f8"
+ integrity sha512-EnEYHilP93oaOa2MnmNEjAcovPS3JlQZOyzGXi3EyEpPhm9qWvdDp7BmAVEVusGzp8LlwQK56Av+OkDoRjzE0w==
+ dependencies:
+ "@types/readable-stream" "^4.0.0"
+ buffer "^6.0.3"
+ inherits "^2.0.4"
+ readable-stream "^4.2.0"
+
body-parser@1.20.2, body-parser@^1.20.2:
version "1.20.2"
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.2.tgz#6feb0e21c4724d06de7ff38da36dad4f57a747fd"
@@ -1931,6 +2077,11 @@ commander@^10.0.1:
resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06"
integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==
+commander@^11.0.0:
+ version "11.1.0"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-11.1.0.tgz#62fdce76006a68e5c1ab3314dc92e800eb83d906"
+ integrity sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==
+
commander@^8.0.0:
version "8.3.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66"
@@ -2147,6 +2298,11 @@ define-data-property@^1.0.1, define-data-property@^1.1.4:
es-errors "^1.3.0"
gopd "^1.0.1"
+define-lazy-prop@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f"
+ integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==
+
define-properties@^1.2.0, define-properties@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c"
@@ -2166,6 +2322,11 @@ delegates@^1.0.0:
resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==
+denque@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/denque/-/denque-2.1.0.tgz#e93e1a6569fb5e66f16a3c2a2964617d349d6ab1"
+ integrity sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==
+
depd@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df"
@@ -2383,6 +2544,20 @@ es-abstract@^1.22.1, es-abstract@^1.22.3, es-abstract@^1.23.0, es-abstract@^1.23
unbox-primitive "^1.0.2"
which-typed-array "^1.1.15"
+es-aggregate-error@^1.0.9:
+ version "1.0.13"
+ resolved "https://registry.yarnpkg.com/es-aggregate-error/-/es-aggregate-error-1.0.13.tgz#7f28b77c9d8d09bbcd3a466e4be9fe02fa985201"
+ integrity sha512-KkzhUUuD2CUMqEc8JEqsXEMDHzDPE8RCjZeUBitsnB1eNcAJWQPiciKsMXe3Yytj4Flw1XLl46Qcf9OxvZha7A==
+ dependencies:
+ define-data-property "^1.1.4"
+ define-properties "^1.2.1"
+ es-abstract "^1.23.2"
+ es-errors "^1.3.0"
+ function-bind "^1.1.2"
+ globalthis "^1.0.3"
+ has-property-descriptors "^1.0.2"
+ set-function-name "^2.0.2"
+
es-define-property@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845"
@@ -2622,6 +2797,11 @@ eventemitter3@^4.0.4:
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f"
integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==
+events@^3.0.0, events@^3.3.0:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400"
+ integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==
+
execa@^5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd"
@@ -3028,6 +3208,13 @@ gcp-metadata@^5.3.0:
gaxios "^5.0.0"
json-bigint "^1.0.0"
+generate-function@^2.3.1:
+ version "2.3.1"
+ resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.3.1.tgz#f069617690c10c868e73b8465746764f97c3479f"
+ integrity sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==
+ dependencies:
+ is-property "^1.0.2"
+
generic-pool@^3.9.0:
version "3.9.0"
resolved "https://registry.yarnpkg.com/generic-pool/-/generic-pool-3.9.0.tgz#36f4a678e963f4fdb8707eab050823abc4e8f5e4"
@@ -3353,7 +3540,7 @@ iconv-lite@0.4.24, iconv-lite@^0.4.24:
dependencies:
safer-buffer ">= 2.1.2 < 3"
-iconv-lite@^0.6.2:
+iconv-lite@^0.6.2, iconv-lite@^0.6.3:
version "0.6.3"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501"
integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==
@@ -3516,6 +3703,11 @@ is-date-object@^1.0.1, is-date-object@^1.0.5:
dependencies:
has-tostringtag "^1.0.0"
+is-docker@^2.0.0, is-docker@^2.1.1:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa"
+ integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==
+
is-extglob@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
@@ -3584,6 +3776,11 @@ is-path-inside@^3.0.3:
resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283"
integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==
+is-property@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84"
+ integrity sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==
+
is-regex@^1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958"
@@ -3655,6 +3852,13 @@ is-weakset@^2.0.3:
call-bind "^1.0.7"
get-intrinsic "^1.2.4"
+is-wsl@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271"
+ integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==
+ dependencies:
+ is-docker "^2.0.0"
+
isarray@^2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723"
@@ -3715,6 +3919,11 @@ js-base64@3.7.2:
resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-3.7.2.tgz#816d11d81a8aff241603d19ce5761e13e41d7745"
integrity sha512-NnRs6dsyqUXejqk/yv2aiXlAvOs56sLkX6nUdeaNezI5LFFLlsZjOThmwnrcwh5ZZRwZlCMnVAY3CvhIhoVEKQ==
+js-md4@^0.3.2:
+ version "0.3.2"
+ resolved "https://registry.yarnpkg.com/js-md4/-/js-md4-0.3.2.tgz#cd3b3dc045b0c404556c81ddb5756c23e59d7cf5"
+ integrity sha512-/GDnfQYsltsjRswQhN9fhv3EMw2sCpUdrdxyWDOUK7eyD++r3gRhzgiQgc/x4MAv2i1iuQ4lxO5mvqM3vj4bwA==
+
js-tiktoken@^1.0.11, js-tiktoken@^1.0.7, js-tiktoken@^1.0.8:
version "1.0.11"
resolved "https://registry.yarnpkg.com/js-tiktoken/-/js-tiktoken-1.0.11.tgz#d7d707b849f703841112660d9d55169424a35344"
@@ -3734,6 +3943,11 @@ js-yaml@^4.1.0:
dependencies:
argparse "^2.0.1"
+jsbi@^4.3.0:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/jsbi/-/jsbi-4.3.0.tgz#b54ee074fb6fcbc00619559305c8f7e912b04741"
+ integrity sha512-SnZNcinB4RIcnEyZqFPdGPVgrg2AcnykiBy0sHVJQKHYeaLUvi3Exj+iaPpLnFVkDPZIV4U0yvgC9/R4uEAZ9g==
+
jsbn@1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-1.1.0.tgz#b01307cb29b618a1ed26ec79e911f803c4da0040"
@@ -3811,7 +4025,7 @@ jsonwebtoken@^8.5.1:
ms "^2.1.1"
semver "^5.6.0"
-jsonwebtoken@^9.0.2:
+jsonwebtoken@^9.0.0, jsonwebtoken@^9.0.2:
version "9.0.2"
resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz#65ff91f4abef1784697d40952bb1998c504caaf3"
integrity sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==
@@ -4050,7 +4264,7 @@ long@^4.0.0:
resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28"
integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==
-long@^5.0.0:
+long@^5.0.0, long@^5.2.1:
version "5.2.3"
resolved "https://registry.yarnpkg.com/long/-/long-5.2.3.tgz#a3ba97f3877cf1d778eccbcb048525ebb77499e1"
integrity sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==
@@ -4074,6 +4288,16 @@ lru-cache@^6.0.0:
dependencies:
yallist "^4.0.0"
+lru-cache@^7.14.1:
+ version "7.18.3"
+ resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.18.3.tgz#f793896e0fd0e954a59dfdd82f0773808df6aa89"
+ integrity sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==
+
+lru-cache@^8.0.0:
+ version "8.0.5"
+ resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-8.0.5.tgz#983fe337f3e176667f8e567cfcce7cb064ea214e"
+ integrity sha512-MhWWlVnuab1RG5/zMRRcVGXZLCXrZTgfwMikgzCegsPnG62yDQo5JnqKkrK4jO5iKqDAZGItAqN5CtKBCBWRUA==
+
lru-cache@^9.1.2:
version "9.1.2"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-9.1.2.tgz#255fdbc14b75589d6d0e73644ca167a8db506835"
@@ -4327,6 +4551,18 @@ ms@2.1.3, ms@^2.0.0, ms@^2.1.1:
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
+mssql@^10.0.2:
+ version "10.0.2"
+ resolved "https://registry.yarnpkg.com/mssql/-/mssql-10.0.2.tgz#99f9113a05b8ee32c84704fddc3780554cd89a60"
+ integrity sha512-GrQ6gzv2xA7ndOvONyZ++4RZsNkr8qDiIpvuFn2pR3TPiSk/cKdmvOrDU3jWgon7EPj7CPgmDiMh7Hgtft2xLg==
+ dependencies:
+ "@tediousjs/connection-string" "^0.5.0"
+ commander "^11.0.0"
+ debug "^4.3.3"
+ rfdc "^1.3.0"
+ tarn "^3.0.2"
+ tedious "^16.4.0"
+
multer@^1.4.5-lts.1:
version "1.4.5-lts.1"
resolved "https://registry.yarnpkg.com/multer/-/multer-1.4.5-lts.1.tgz#803e24ad1984f58edffbc79f56e305aec5cfd1ac"
@@ -4350,11 +4586,37 @@ mute-stream@^1.0.0:
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-1.0.0.tgz#e31bd9fe62f0aed23520aa4324ea6671531e013e"
integrity sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==
+mysql2@^3.9.7:
+ version "3.9.7"
+ resolved "https://registry.yarnpkg.com/mysql2/-/mysql2-3.9.7.tgz#843755daf65b5ef08afe545fe14b8fb62824741a"
+ integrity sha512-KnJT8vYRcNAZv73uf9zpXqNbvBG7DJrs+1nACsjZP1HMJ1TgXEy8wnNilXAn/5i57JizXKtrUtwDB7HxT9DDpw==
+ dependencies:
+ denque "^2.1.0"
+ generate-function "^2.3.1"
+ iconv-lite "^0.6.3"
+ long "^5.2.1"
+ lru-cache "^8.0.0"
+ named-placeholders "^1.1.3"
+ seq-queue "^0.0.5"
+ sqlstring "^2.3.2"
+
+named-placeholders@^1.1.3:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/named-placeholders/-/named-placeholders-1.1.3.tgz#df595799a36654da55dda6152ba7a137ad1d9351"
+ integrity sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w==
+ dependencies:
+ lru-cache "^7.14.1"
+
napi-build-utils@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-1.0.2.tgz#b1fddc0b2c46e380a0b7a76f984dd47c41a13806"
integrity sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==
+native-duplexpair@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/native-duplexpair/-/native-duplexpair-1.0.0.tgz#7899078e64bf3c8a3d732601b3d40ff05db58fa0"
+ integrity sha512-E7QQoM+3jvNtlmyfqRZ0/U75VFgCls+fSkbml2MpgWkWyz3ox8Y58gNhfuziuQYGNNQAbFZJQck55LHCnCK6CA==
+
natural-compare@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
@@ -4372,6 +4634,11 @@ node-abi@^3.3.0:
dependencies:
semver "^7.3.5"
+node-abort-controller@^3.1.1:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/node-abort-controller/-/node-abort-controller-3.1.1.tgz#a94377e964a9a37ac3976d848cb5c765833b8548"
+ integrity sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==
+
node-addon-api@^5.0.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-5.1.0.tgz#49da1ca055e109a23d537e9de43c09cca21eb762"
@@ -4685,6 +4952,15 @@ onnxruntime-web@1.14.0:
onnxruntime-common "~1.14.0"
platform "^1.3.6"
+open@^8.0.0:
+ version "8.4.2"
+ resolved "https://registry.yarnpkg.com/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9"
+ integrity sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==
+ dependencies:
+ define-lazy-prop "^2.0.0"
+ is-docker "^2.1.1"
+ is-wsl "^2.2.0"
+
openai@4.38.5:
version "4.38.5"
resolved "https://registry.yarnpkg.com/openai/-/openai-4.38.5.tgz#87de78eed9f7e63331fb6b1307d8c9dd986b39d0"
@@ -4848,6 +5124,62 @@ pend@~1.2.0:
resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50"
integrity sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==
+pg-cloudflare@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz#e6d5833015b170e23ae819e8c5d7eaedb472ca98"
+ integrity sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==
+
+pg-connection-string@^2.6.4:
+ version "2.6.4"
+ resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.6.4.tgz#f543862adfa49fa4e14bc8a8892d2a84d754246d"
+ integrity sha512-v+Z7W/0EO707aNMaAEfiGnGL9sxxumwLl2fJvCQtMn9Fxsg+lPpPkdcyBSv/KFgpGdYkMfn+EI1Or2EHjpgLCA==
+
+pg-int8@1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/pg-int8/-/pg-int8-1.0.1.tgz#943bd463bf5b71b4170115f80f8efc9a0c0eb78c"
+ integrity sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==
+
+pg-pool@^3.6.2:
+ version "3.6.2"
+ resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-3.6.2.tgz#3a592370b8ae3f02a7c8130d245bc02fa2c5f3f2"
+ integrity sha512-Htjbg8BlwXqSBQ9V8Vjtc+vzf/6fVUuak/3/XXKA9oxZprwW3IMDQTGHP+KDmVL7rtd+R1QjbnCFPuTHm3G4hg==
+
+pg-protocol@^1.6.1:
+ version "1.6.1"
+ resolved "https://registry.yarnpkg.com/pg-protocol/-/pg-protocol-1.6.1.tgz#21333e6d83b01faaebfe7a33a7ad6bfd9ed38cb3"
+ integrity sha512-jPIlvgoD63hrEuihvIg+tJhoGjUsLPn6poJY9N5CnlPd91c2T18T/9zBtLxZSb1EhYxBRoZJtzScCaWlYLtktg==
+
+pg-types@^2.1.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/pg-types/-/pg-types-2.2.0.tgz#2d0250d636454f7cfa3b6ae0382fdfa8063254a3"
+ integrity sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==
+ dependencies:
+ pg-int8 "1.0.1"
+ postgres-array "~2.0.0"
+ postgres-bytea "~1.0.0"
+ postgres-date "~1.0.4"
+ postgres-interval "^1.1.0"
+
+pg@^8.11.5:
+ version "8.11.5"
+ resolved "https://registry.yarnpkg.com/pg/-/pg-8.11.5.tgz#e722b0a5f1ed92931c31758ebec3ddf878dd4128"
+ integrity sha512-jqgNHSKL5cbDjFlHyYsCXmQDrfIX/3RsNwYqpd4N0Kt8niLuNoRNH+aazv6cOd43gPh9Y4DjQCtb+X0MH0Hvnw==
+ dependencies:
+ pg-connection-string "^2.6.4"
+ pg-pool "^3.6.2"
+ pg-protocol "^1.6.1"
+ pg-types "^2.1.0"
+ pgpass "1.x"
+ optionalDependencies:
+ pg-cloudflare "^1.1.1"
+
+pgpass@1.x:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/pgpass/-/pgpass-1.0.5.tgz#9b873e4a564bb10fa7a7dbd55312728d422a223d"
+ integrity sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==
+ dependencies:
+ split2 "^4.1.0"
+
picomatch@^2.0.4, picomatch@^2.2.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
@@ -4882,6 +5214,28 @@ possible-typed-array-names@^1.0.0:
resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz#89bb63c6fada2c3e90adc4a647beeeb39cc7bf8f"
integrity sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==
+postgres-array@~2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/postgres-array/-/postgres-array-2.0.0.tgz#48f8fce054fbc69671999329b8834b772652d82e"
+ integrity sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==
+
+postgres-bytea@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/postgres-bytea/-/postgres-bytea-1.0.0.tgz#027b533c0aa890e26d172d47cf9ccecc521acd35"
+ integrity sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==
+
+postgres-date@~1.0.4:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/postgres-date/-/postgres-date-1.0.7.tgz#51bc086006005e5061c591cee727f2531bf641a8"
+ integrity sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==
+
+postgres-interval@^1.1.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/postgres-interval/-/postgres-interval-1.2.0.tgz#b460c82cb1587507788819a06aa0fffdb3544695"
+ integrity sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==
+ dependencies:
+ xtend "^4.0.0"
+
posthog-node@^3.1.1:
version "3.6.3"
resolved "https://registry.yarnpkg.com/posthog-node/-/posthog-node-3.6.3.tgz#4d3a2a4385e01c4d9e91d01dbde104e60285853d"
@@ -4937,6 +5291,11 @@ process-nextick-args@~2.0.0:
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
+process@^0.11.10:
+ version "0.11.10"
+ resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
+ integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==
+
promise-inflight@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3"
@@ -5110,6 +5469,17 @@ readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0:
string_decoder "^1.1.1"
util-deprecate "^1.0.1"
+readable-stream@^4.2.0:
+ version "4.5.2"
+ resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-4.5.2.tgz#9e7fc4c45099baeed934bff6eb97ba6cf2729e09"
+ integrity sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==
+ dependencies:
+ abort-controller "^3.0.0"
+ buffer "^6.0.3"
+ events "^3.3.0"
+ process "^0.11.10"
+ string_decoder "^1.3.0"
+
readdir-glob@^1.1.2:
version "1.1.3"
resolved "https://registry.yarnpkg.com/readdir-glob/-/readdir-glob-1.1.3.tgz#c3d831f51f5e7bfa62fa2ffbe4b508c640f09584"
@@ -5199,6 +5569,11 @@ reusify@^1.0.4:
resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
+rfdc@^1.3.0:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.1.tgz#2b6d4df52dffe8bb346992a10ea9451f24373a8f"
+ integrity sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==
+
rimraf@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
@@ -5298,6 +5673,11 @@ send@0.18.0:
range-parser "~1.2.1"
statuses "2.0.1"
+seq-queue@^0.0.5:
+ version "0.0.5"
+ resolved "https://registry.yarnpkg.com/seq-queue/-/seq-queue-0.0.5.tgz#d56812e1c017a6e4e7c3e3a37a1da6d78dd3c93e"
+ integrity sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==
+
serve-static@1.15.0:
version "1.15.0"
resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540"
@@ -5450,7 +5830,12 @@ socks@^2.6.2:
ip-address "^9.0.5"
smart-buffer "^4.2.0"
-sprintf-js@^1.1.3:
+split2@^4.1.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/split2/-/split2-4.2.0.tgz#c9c5920904d148bab0b9f67145f245a86aadbfa4"
+ integrity sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==
+
+sprintf-js@^1.1.2, sprintf-js@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.3.tgz#4914b903a2f8b685d17fdf78a70e917e872e444a"
integrity sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==
@@ -5472,6 +5857,11 @@ sqlite@^4.2.1:
resolved "https://registry.yarnpkg.com/sqlite/-/sqlite-4.2.1.tgz#d4eedfd1ad702f79110792375f4241a90c75c828"
integrity sha512-Tll0Ndvnwkuv5Hn6WIbh26rZiYQORuH1t5m/or9LUpSmDmmyFG89G9fKrSeugMPxwmEIXoVxqTun4LbizTs4uw==
+sqlstring@^2.3.2:
+ version "2.3.3"
+ resolved "https://registry.yarnpkg.com/sqlstring/-/sqlstring-2.3.3.tgz#2ddc21f03bce2c387ed60680e739922c65751d0c"
+ integrity sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==
+
ssri@^8.0.0, ssri@^8.0.1:
version "8.0.1"
resolved "https://registry.yarnpkg.com/ssri/-/ssri-8.0.1.tgz#638e4e439e2ffbd2cd289776d5ca457c4f51a2af"
@@ -5496,6 +5886,11 @@ stdin-discarder@^0.1.0:
dependencies:
bl "^5.0.0"
+stoppable@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/stoppable/-/stoppable-1.1.0.tgz#32da568e83ea488b08e4d7ea2c3bcc9d75015d5b"
+ integrity sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==
+
stream-read-all@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/stream-read-all/-/stream-read-all-3.0.1.tgz#60762ae45e61d93ba0978cda7f3913790052ad96"
@@ -5585,7 +5980,7 @@ string.prototype.trimstart@^1.0.8:
define-properties "^1.2.1"
es-object-atoms "^1.0.0"
-string_decoder@^1.1.1:
+string_decoder@^1.1.1, string_decoder@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e"
integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==
@@ -5748,6 +6143,28 @@ tar@^6.0.2, tar@^6.1.11, tar@^6.1.2, tar@^6.2.0:
mkdirp "^1.0.3"
yallist "^4.0.0"
+tarn@^3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/tarn/-/tarn-3.0.2.tgz#73b6140fbb881b71559c4f8bfde3d9a4b3d27693"
+ integrity sha512-51LAVKUSZSVfI05vjPESNc5vwqqZpbXCsU+/+wxlOrUjk2SnFTt97v9ZgQrD4YmxYW1Px6w2KjaDitCfkvgxMQ==
+
+tedious@^16.4.0:
+ version "16.7.1"
+ resolved "https://registry.yarnpkg.com/tedious/-/tedious-16.7.1.tgz#1190f30fd99a413f1dc9250dee4835cf0788b650"
+ integrity sha512-NmedZS0NJiTv3CoYnf1FtjxIDUgVYzEmavrc8q2WHRb+lP4deI9BpQfmNnBZZaWusDbP5FVFZCcvzb3xOlNVlQ==
+ dependencies:
+ "@azure/identity" "^3.4.1"
+ "@azure/keyvault-keys" "^4.4.0"
+ "@js-joda/core" "^5.5.3"
+ bl "^6.0.3"
+ es-aggregate-error "^1.0.9"
+ iconv-lite "^0.6.3"
+ js-md4 "^0.3.2"
+ jsbi "^4.3.0"
+ native-duplexpair "^1.0.0"
+ node-abort-controller "^3.1.1"
+ sprintf-js "^1.1.2"
+
text-hex@1.0.x:
version "1.0.0"
resolved "https://registry.yarnpkg.com/text-hex/-/text-hex-1.0.0.tgz#69dc9c1b17446ee79a92bf5b884bb4b9127506f5"
@@ -5794,7 +6211,7 @@ triple-beam@^1.3.0:
resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.4.1.tgz#6fde70271dc6e5d73ca0c3b24e2d92afb7441984"
integrity sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==
-tslib@^2.4.0, tslib@^2.5.3, tslib@^2.6.2:
+tslib@^2.2.0, tslib@^2.4.0, tslib@^2.5.3, tslib@^2.6.2:
version "2.6.2"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae"
integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==
@@ -5966,6 +6383,11 @@ url-join@4.0.1, url-join@^4.0.1:
resolved "https://registry.yarnpkg.com/url-join/-/url-join-4.0.1.tgz#b642e21a2646808ffa178c4c5fda39844e12cde7"
integrity sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==
+url-pattern@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/url-pattern/-/url-pattern-1.0.3.tgz#0409292471b24f23c50d65a47931793d2b5acfc1"
+ integrity sha512-uQcEj/2puA4aq1R3A2+VNVBgaWYR24FdWjl7VNW83rnWftlhyzOZ/tBjezRiC2UkIzuxC8Top3IekN3vUf1WxA==
+
url-template@^2.0.8:
version "2.0.8"
resolved "https://registry.yarnpkg.com/url-template/-/url-template-2.0.8.tgz#fc565a3cccbff7730c775f5641f9555791439f21"
@@ -5991,7 +6413,7 @@ uuid-apikey@^1.5.3:
encode32 "^1.1.0"
uuid "^8.3.1"
-uuid@^8.3.1:
+uuid@^8.3.0, uuid@^8.3.1:
version "8.3.2"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==