@databridgeai/toolkit 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,103 @@
1
+ # @databridgeai/toolkit
2
+
3
+ **Schema introspection, playground helpers, and utility functions for DataBridge AI.**
4
+
5
+ This package provides lower-level tools for advanced integrations. Most users should use `@databridgeai/connector` instead.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install @databridgeai/toolkit
11
+ ```
12
+
13
+ ## Schema Introspection
14
+
15
+ Automatically discover your database schema:
16
+
17
+ ### PostgreSQL
18
+
19
+ ```typescript
20
+ import { introspectPostgres } from '@databridgeai/toolkit';
21
+ import { Pool } from 'pg';
22
+
23
+ const pool = new Pool({ connectionString: process.env.DATABASE_URL });
24
+
25
+ const schema = await introspectPostgres(pool, {
26
+ tables: ['users', 'orders', 'products'],
27
+ tenantField: 'organization_id',
28
+ });
29
+
30
+ console.log(schema);
31
+ // {
32
+ // tables: [
33
+ // { name: 'users', columns: [{ name: 'id', type: 'integer' }, ...] },
34
+ // { name: 'orders', columns: [...] },
35
+ // ]
36
+ // }
37
+ ```
38
+
39
+ ### MongoDB
40
+
41
+ ```typescript
42
+ import { introspectMongo } from '@databridgeai/toolkit';
43
+ import { MongoClient } from 'mongodb';
44
+
45
+ const client = new MongoClient(process.env.MONGO_URL!);
46
+ const db = client.db('myapp');
47
+
48
+ const schema = await introspectMongo(db, {
49
+ collections: ['users', 'orders'],
50
+ });
51
+ ```
52
+
53
+ ## Agent (Full Runtime Integration)
54
+
55
+ For direct runtime API integration without the connector:
56
+
57
+ ```typescript
58
+ import { initAgent } from '@databridgeai/toolkit';
59
+
60
+ const agent = initAgent({
61
+ apiKey: process.env.DATABRIDGE_API_KEY!,
62
+ db: pool,
63
+ exposeTables: ['users', 'orders'],
64
+ runtimeUrl: 'https://your-server.vercel.app',
65
+ });
66
+
67
+ await agent.init();
68
+ const result = await agent.chat('Show top customers', userContext);
69
+ ```
70
+
71
+ ## Playground HTML
72
+
73
+ Generate a self-contained chat playground UI:
74
+
75
+ ```typescript
76
+ import { getPlaygroundHTML } from '@databridgeai/toolkit';
77
+
78
+ app.get('/playground', (_req, res) => {
79
+ res.setHeader('Content-Type', 'text/html');
80
+ res.send(getPlaygroundHTML());
81
+ });
82
+ ```
83
+
84
+ ## Exports
85
+
86
+ | Export | Description |
87
+ |--------|------------|
88
+ | `introspectPostgres()` | Discover Postgres table schemas |
89
+ | `introspectMongo()` | Discover MongoDB collection schemas |
90
+ | `initAgent()` | Create an agent with full runtime integration |
91
+ | `getPlaygroundHTML()` | Generate chat playground HTML |
92
+
93
+ ## Related Packages
94
+
95
+ | Package | Purpose |
96
+ |---------|---------|
97
+ | `@databridgeai/connector` | Recommended backend connector |
98
+ | `@databridgeai/react` | React chat widget |
99
+ | `@databridgeai/core` | Shared types & validators |
100
+
101
+ ## License
102
+
103
+ MIT
@@ -0,0 +1,70 @@
1
+ import { Pool } from "pg";
2
+ import { Db } from "mongodb";
3
+ import { UserContext } from "@databridgeai/core";
4
+ export interface AgentConfig {
5
+ /** API key for authenticating with the runtime */
6
+ apiKey: string;
7
+ /** Database connection — Postgres Pool or Mongo Db instance */
8
+ db: Pool | Db;
9
+ /** Tables/collections to expose to the AI agent */
10
+ exposeTables: string[];
11
+ /** Field used for tenant isolation (e.g., "org_id") */
12
+ tenantField?: string;
13
+ /** Runtime server URL (defaults to http://localhost:3100) */
14
+ runtimeUrl?: string;
15
+ }
16
+ export declare class AgentClient {
17
+ private config;
18
+ private projectId;
19
+ private runtimeUrl;
20
+ constructor(config: AgentConfig);
21
+ /**
22
+ * Initialize the agent: introspect DB schema and register with runtime.
23
+ */
24
+ init(): Promise<{
25
+ projectId: string;
26
+ }>;
27
+ /**
28
+ * Send a chat message to the AI agent.
29
+ */
30
+ chat(message: string, userContext: UserContext): Promise<{
31
+ message: string;
32
+ data?: any;
33
+ }>;
34
+ /**
35
+ * Returns an Express-compatible middleware that proxies chat requests.
36
+ * Mount it on your app: app.post('/ai/chat', agent.middleware())
37
+ */
38
+ middleware(): (req: any, res: any) => Promise<void>;
39
+ /**
40
+ * Returns Express middleware to serve the embedded Chat Playground UI.
41
+ * Mount it on your app: app.get('/playground', agent.playgroundUI())
42
+ *
43
+ * This provides a ready-to-use web interface for testing the AI agent.
44
+ */
45
+ playgroundUI(options?: {
46
+ chatEndpoint?: string;
47
+ defaultUserId?: string;
48
+ defaultOrgId?: string;
49
+ defaultRole?: string;
50
+ projectName?: string;
51
+ }): (_req: any, res: any) => void;
52
+ private getDbType;
53
+ private introspectSchema;
54
+ private getConnectionString;
55
+ }
56
+ /**
57
+ * Create and initialize an agent.
58
+ *
59
+ * Usage:
60
+ * ```ts
61
+ * const agent = await initAgent({
62
+ * apiKey: process.env.AGENT_KEY!,
63
+ * db: pool, // pg Pool or mongo Db
64
+ * exposeTables: ["users", "orders"],
65
+ * tenantField: "org_id"
66
+ * });
67
+ * ```
68
+ */
69
+ export declare function initAgent(config: AgentConfig): Promise<AgentClient>;
70
+ //# sourceMappingURL=agent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,IAAI,CAAC;AAC1B,OAAO,EAAe,EAAE,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EAA+B,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAO9E,MAAM,WAAW,WAAW;IAC1B,kDAAkD;IAClD,MAAM,EAAE,MAAM,CAAC;IAEf,+DAA+D;IAC/D,EAAE,EAAE,IAAI,GAAG,EAAE,CAAC;IAEd,mDAAmD;IACnD,YAAY,EAAE,MAAM,EAAE,CAAC;IAEvB,uDAAuD;IACvD,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,6DAA6D;IAC7D,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAID,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,UAAU,CAAS;gBAEf,MAAM,EAAE,WAAW;IAK/B;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IA0C5C;;OAEG;IACG,IAAI,CACR,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,WAAW,GACvB,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,GAAG,CAAA;KAAE,CAAC;IAgC3C;;;OAGG;IACH,UAAU,KACM,KAAK,GAAG,EAAE,KAAK,GAAG;IAyBlC;;;;;OAKG;IACH,YAAY,CAAC,OAAO,CAAC,EAAE;QACrB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,IASS,MAAM,GAAG,EAAE,KAAK,GAAG;IAgB7B,OAAO,CAAC,SAAS;YAaH,gBAAgB;IAgB9B,OAAO,CAAC,mBAAmB;CA+B5B;AAID;;;;;;;;;;;;GAYG;AACH,wBAAsB,SAAS,CAC7B,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC,WAAW,CAAC,CAItB"}
package/dist/agent.js ADDED
@@ -0,0 +1,194 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AgentClient = void 0;
4
+ exports.initAgent = initAgent;
5
+ const pg_1 = require("pg");
6
+ const introspect_postgres_1 = require("./introspect-postgres");
7
+ const introspect_mongo_1 = require("./introspect-mongo");
8
+ const playground_1 = require("./playground");
9
+ // ─── Agent Client ─────────────────────────────────────────
10
+ class AgentClient {
11
+ config;
12
+ projectId = null;
13
+ runtimeUrl;
14
+ constructor(config) {
15
+ this.config = config;
16
+ this.runtimeUrl = config.runtimeUrl || "http://localhost:3100";
17
+ }
18
+ /**
19
+ * Initialize the agent: introspect DB schema and register with runtime.
20
+ */
21
+ async init() {
22
+ console.log("[databridgeai/toolkit] Initializing agent...");
23
+ // 1. Detect DB type and introspect
24
+ const schema = await this.introspectSchema();
25
+ console.log(`[databridgeai/toolkit] Introspected ${schema.tables.length} table(s).`);
26
+ // 2. Detect connection string for runtime to use
27
+ const connectionString = this.getConnectionString();
28
+ // 3. Register with runtime
29
+ const response = await fetch(`${this.runtimeUrl}/register-project`, {
30
+ method: "POST",
31
+ headers: { "Content-Type": "application/json" },
32
+ body: JSON.stringify({
33
+ apiKey: this.config.apiKey,
34
+ dbType: this.getDbType(),
35
+ schema,
36
+ tenantField: this.config.tenantField,
37
+ connectionString,
38
+ }),
39
+ });
40
+ if (!response.ok) {
41
+ const err = await response.json().catch(() => ({}));
42
+ throw new Error(`Failed to register with runtime: ${response.status} ${JSON.stringify(err)}`);
43
+ }
44
+ const result = (await response.json());
45
+ this.projectId = result.projectId;
46
+ console.log(`[databridgeai/toolkit] Registered as project "${this.projectId}".`);
47
+ return result;
48
+ }
49
+ /**
50
+ * Send a chat message to the AI agent.
51
+ */
52
+ async chat(message, userContext) {
53
+ if (!this.projectId) {
54
+ throw new Error("Agent not initialized. Call init() before chat().");
55
+ }
56
+ const body = {
57
+ projectId: this.projectId,
58
+ message,
59
+ userContext,
60
+ };
61
+ const response = await fetch(`${this.runtimeUrl}/chat`, {
62
+ method: "POST",
63
+ headers: {
64
+ "Content-Type": "application/json",
65
+ Authorization: `Bearer ${this.config.apiKey}`,
66
+ },
67
+ body: JSON.stringify(body),
68
+ });
69
+ if (!response.ok) {
70
+ const err = await response.json().catch(() => ({}));
71
+ throw new Error(`Chat request failed: ${response.status} ${JSON.stringify(err)}`);
72
+ }
73
+ return (await response.json());
74
+ }
75
+ /**
76
+ * Returns an Express-compatible middleware that proxies chat requests.
77
+ * Mount it on your app: app.post('/ai/chat', agent.middleware())
78
+ */
79
+ middleware() {
80
+ return async (req, res) => {
81
+ try {
82
+ const { message, userContext } = req.body;
83
+ if (!message) {
84
+ res.status(400).json({ error: "Missing 'message' in request body." });
85
+ return;
86
+ }
87
+ if (!userContext?.orgId) {
88
+ res
89
+ .status(400)
90
+ .json({ error: "Missing 'userContext.orgId' in request body." });
91
+ return;
92
+ }
93
+ const result = await this.chat(message, userContext);
94
+ res.json(result);
95
+ }
96
+ catch (err) {
97
+ console.error("[databridgeai/toolkit] Middleware error:", err);
98
+ res.status(500).json({ error: err.message });
99
+ }
100
+ };
101
+ }
102
+ /**
103
+ * Returns Express middleware to serve the embedded Chat Playground UI.
104
+ * Mount it on your app: app.get('/playground', agent.playgroundUI())
105
+ *
106
+ * This provides a ready-to-use web interface for testing the AI agent.
107
+ */
108
+ playgroundUI(options) {
109
+ const { chatEndpoint = '/ai/chat', defaultUserId = 'user_1', defaultOrgId = 'org_acme', defaultRole = 'admin', projectName = 'AI Agent', } = options || {};
110
+ return (_req, res) => {
111
+ res.setHeader('Content-Type', 'text/html');
112
+ res.send((0, playground_1.getPlaygroundHTML)({
113
+ chatEndpoint,
114
+ defaultUserId,
115
+ defaultOrgId,
116
+ defaultRole,
117
+ projectName,
118
+ }));
119
+ };
120
+ }
121
+ // ─── Private methods ──────────────────────────────────
122
+ getDbType() {
123
+ if (this.config.db instanceof pg_1.Pool)
124
+ return "postgres";
125
+ // Check if it's a Mongo Db instance
126
+ if (this.config.db &&
127
+ typeof this.config.db.collection === "function" &&
128
+ typeof this.config.db.databaseName === "string") {
129
+ return "mongo";
130
+ }
131
+ throw new Error("Unable to detect database type from provided db instance.");
132
+ }
133
+ async introspectSchema() {
134
+ const dbType = this.getDbType();
135
+ if (dbType === "postgres") {
136
+ return (0, introspect_postgres_1.introspectPostgres)(this.config.db, this.config.exposeTables);
137
+ }
138
+ else {
139
+ return (0, introspect_mongo_1.introspectMongo)(this.config.db, this.config.exposeTables);
140
+ }
141
+ }
142
+ getConnectionString() {
143
+ const dbType = this.getDbType();
144
+ if (dbType === "postgres") {
145
+ const pool = this.config.db;
146
+ // Extract connection string from pool options
147
+ const opts = pool.options;
148
+ if (opts?.connectionString)
149
+ return opts.connectionString;
150
+ // Build from individual options
151
+ const host = opts?.host || "localhost";
152
+ const port = opts?.port || 5432;
153
+ const database = opts?.database || "postgres";
154
+ const user = opts?.user || "postgres";
155
+ const password = opts?.password || "";
156
+ return `postgresql://${user}:${password}@${host}:${port}/${database}`;
157
+ }
158
+ else {
159
+ // For Mongo, the connection string is typically in the client
160
+ const db = this.config.db;
161
+ const client = db.client;
162
+ // Try extracting from MongoClient
163
+ if (client?.options) {
164
+ const hosts = client.s?.options?.hosts;
165
+ const dbName = db.databaseName;
166
+ if (hosts && hosts.length > 0) {
167
+ return `mongodb://${hosts[0]}/${dbName}`;
168
+ }
169
+ }
170
+ return `mongodb://localhost:27017/${db.databaseName}`;
171
+ }
172
+ }
173
+ }
174
+ exports.AgentClient = AgentClient;
175
+ // ─── Convenience function ─────────────────────────────────
176
+ /**
177
+ * Create and initialize an agent.
178
+ *
179
+ * Usage:
180
+ * ```ts
181
+ * const agent = await initAgent({
182
+ * apiKey: process.env.AGENT_KEY!,
183
+ * db: pool, // pg Pool or mongo Db
184
+ * exposeTables: ["users", "orders"],
185
+ * tenantField: "org_id"
186
+ * });
187
+ * ```
188
+ */
189
+ async function initAgent(config) {
190
+ const client = new AgentClient(config);
191
+ await client.init();
192
+ return client;
193
+ }
194
+ //# sourceMappingURL=agent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent.js","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export { AgentClient, initAgent } from "./agent";
2
+ export type { AgentConfig } from "./agent";
3
+ export { introspectPostgres } from "./introspect-postgres";
4
+ export { introspectMongo } from "./introspect-mongo";
5
+ export { getPlaygroundHTML } from "./playground";
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACjD,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ // ─── @databridgeai/toolkit ────────────────────────────────────────────
3
+ // Customer-facing SDK for AI Agent integration.
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports.getPlaygroundHTML = exports.introspectMongo = exports.introspectPostgres = exports.initAgent = exports.AgentClient = void 0;
6
+ var agent_1 = require("./agent");
7
+ Object.defineProperty(exports, "AgentClient", { enumerable: true, get: function () { return agent_1.AgentClient; } });
8
+ Object.defineProperty(exports, "initAgent", { enumerable: true, get: function () { return agent_1.initAgent; } });
9
+ var introspect_postgres_1 = require("./introspect-postgres");
10
+ Object.defineProperty(exports, "introspectPostgres", { enumerable: true, get: function () { return introspect_postgres_1.introspectPostgres; } });
11
+ var introspect_mongo_1 = require("./introspect-mongo");
12
+ Object.defineProperty(exports, "introspectMongo", { enumerable: true, get: function () { return introspect_mongo_1.introspectMongo; } });
13
+ var playground_1 = require("./playground");
14
+ Object.defineProperty(exports, "getPlaygroundHTML", { enumerable: true, get: function () { return playground_1.getPlaygroundHTML; } });
15
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,yEAAyE;AACzE,gDAAgD;;;AAEhD,iCAAiD;AAAxC,oGAAA,WAAW,OAAA;AAAE,kGAAA,SAAS,OAAA;AAE/B,6DAA2D;AAAlD,yHAAA,kBAAkB,OAAA;AAC3B,uDAAqD;AAA5C,mHAAA,eAAe,OAAA;AACxB,2CAAiD;AAAxC,+GAAA,iBAAiB,OAAA"}
@@ -0,0 +1,8 @@
1
+ import { Db } from "mongodb";
2
+ import { SchemaMetadata } from "@databridgeai/core";
3
+ /**
4
+ * Introspects a MongoDB database by sampling documents from each collection
5
+ * to infer field names and types.
6
+ */
7
+ export declare function introspectMongo(db: Db, exposeCollections: string[]): Promise<SchemaMetadata>;
8
+ //# sourceMappingURL=introspect-mongo.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"introspect-mongo.d.ts","sourceRoot":"","sources":["../src/introspect-mongo.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,EAAE,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EACL,cAAc,EAGf,MAAM,oBAAoB,CAAC;AAE5B;;;GAGG;AACH,wBAAsB,eAAe,CACnC,EAAE,EAAE,EAAE,EACN,iBAAiB,EAAE,MAAM,EAAE,GAC1B,OAAO,CAAC,cAAc,CAAC,CA0DzB"}
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.introspectMongo = introspectMongo;
4
+ /**
5
+ * Introspects a MongoDB database by sampling documents from each collection
6
+ * to infer field names and types.
7
+ */
8
+ async function introspectMongo(db, exposeCollections) {
9
+ const tables = [];
10
+ for (const collectionName of exposeCollections) {
11
+ const collection = db.collection(collectionName);
12
+ // Sample up to 100 documents to infer schema
13
+ const sampleDocs = await collection
14
+ .find({})
15
+ .limit(100)
16
+ .toArray();
17
+ if (sampleDocs.length === 0) {
18
+ console.warn(`[sdk] Warning: collection "${collectionName}" is empty. Adding with no fields.`);
19
+ tables.push({ name: collectionName, fields: [] });
20
+ continue;
21
+ }
22
+ // Build a union of all field names and their most common types
23
+ const fieldTypeMap = new Map();
24
+ for (const doc of sampleDocs) {
25
+ for (const [key, value] of Object.entries(doc)) {
26
+ if (key === "_id")
27
+ continue; // Skip _id by default
28
+ if (!fieldTypeMap.has(key)) {
29
+ fieldTypeMap.set(key, new Map());
30
+ }
31
+ const typeCount = fieldTypeMap.get(key);
32
+ const jsType = inferMongoFieldType(value);
33
+ typeCount.set(jsType, (typeCount.get(jsType) || 0) + 1);
34
+ }
35
+ }
36
+ const fields = [];
37
+ for (const [fieldName, typeCounts] of fieldTypeMap) {
38
+ // Pick the most common type
39
+ let maxType = "string";
40
+ let maxCount = 0;
41
+ for (const [type, count] of typeCounts) {
42
+ if (count > maxCount) {
43
+ maxType = type;
44
+ maxCount = count;
45
+ }
46
+ }
47
+ fields.push({ name: fieldName, type: maxType });
48
+ }
49
+ // MongoDB doesn't have native foreign keys, so relations are empty
50
+ tables.push({
51
+ name: collectionName,
52
+ fields,
53
+ });
54
+ }
55
+ return { tables };
56
+ }
57
+ function inferMongoFieldType(value) {
58
+ if (value === null || value === undefined)
59
+ return "string";
60
+ if (typeof value === "number") {
61
+ return Number.isInteger(value) ? "integer" : "number";
62
+ }
63
+ if (typeof value === "boolean")
64
+ return "boolean";
65
+ if (typeof value === "string")
66
+ return "string";
67
+ if (value instanceof Date)
68
+ return "date";
69
+ if (Array.isArray(value))
70
+ return "array";
71
+ if (typeof value === "object")
72
+ return "object";
73
+ return "string";
74
+ }
75
+ //# sourceMappingURL=introspect-mongo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"introspect-mongo.js","sourceRoot":"","sources":["../src/introspect-mongo.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import { Pool } from "pg";
2
+ import { SchemaMetadata } from "@databridgeai/core";
3
+ /**
4
+ * Introspects a PostgreSQL database using information_schema to extract
5
+ * table names, column names/types, and foreign key relationships.
6
+ */
7
+ export declare function introspectPostgres(pool: Pool, exposeTables: string[]): Promise<SchemaMetadata>;
8
+ //# sourceMappingURL=introspect-postgres.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"introspect-postgres.d.ts","sourceRoot":"","sources":["../src/introspect-postgres.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,IAAI,CAAC;AAC1B,OAAO,EACL,cAAc,EAIf,MAAM,oBAAoB,CAAC;AAE5B;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,IAAI,EACV,YAAY,EAAE,MAAM,EAAE,GACrB,OAAO,CAAC,cAAc,CAAC,CA6DzB"}
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.introspectPostgres = introspectPostgres;
4
+ /**
5
+ * Introspects a PostgreSQL database using information_schema to extract
6
+ * table names, column names/types, and foreign key relationships.
7
+ */
8
+ async function introspectPostgres(pool, exposeTables) {
9
+ const tables = [];
10
+ for (const tableName of exposeTables) {
11
+ // ─── Get columns ──────────────────────────────────────
12
+ const colResult = await pool.query(`SELECT column_name, data_type
13
+ FROM information_schema.columns
14
+ WHERE table_name = $1
15
+ AND table_schema = 'public'
16
+ ORDER BY ordinal_position`, [tableName]);
17
+ if (colResult.rows.length === 0) {
18
+ console.warn(`[sdk] Warning: table "${tableName}" not found or has no columns.`);
19
+ continue;
20
+ }
21
+ const fields = colResult.rows.map((row) => ({
22
+ name: row.column_name,
23
+ type: row.data_type,
24
+ }));
25
+ // ─── Get foreign keys ─────────────────────────────────
26
+ const fkResult = await pool.query(`SELECT
27
+ kcu.column_name AS local_field,
28
+ ccu.table_name AS foreign_table,
29
+ ccu.column_name AS foreign_field
30
+ FROM information_schema.table_constraints AS tc
31
+ JOIN information_schema.key_column_usage AS kcu
32
+ ON tc.constraint_name = kcu.constraint_name
33
+ AND tc.table_schema = kcu.table_schema
34
+ JOIN information_schema.constraint_column_usage AS ccu
35
+ ON ccu.constraint_name = tc.constraint_name
36
+ AND ccu.table_schema = tc.table_schema
37
+ WHERE tc.constraint_type = 'FOREIGN KEY'
38
+ AND tc.table_name = $1
39
+ AND tc.table_schema = 'public'`, [tableName]);
40
+ const relations = fkResult.rows
41
+ .filter((row) => exposeTables.includes(row.foreign_table))
42
+ .map((row) => ({
43
+ table: row.foreign_table,
44
+ localField: row.local_field,
45
+ foreignField: row.foreign_field,
46
+ }));
47
+ tables.push({
48
+ name: tableName,
49
+ fields,
50
+ relations: relations.length > 0 ? relations : undefined,
51
+ });
52
+ }
53
+ return { tables };
54
+ }
55
+ //# sourceMappingURL=introspect-postgres.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"introspect-postgres.js","sourceRoot":"","sources":["../src/introspect-postgres.ts"],"names":[],"mappings":";;AAYA,gDAgEC;AApED;;;GAGG;AACI,KAAK,UAAU,kBAAkB,CACtC,IAAU,EACV,YAAsB;IAEtB,MAAM,MAAM,GAAoB,EAAE,CAAC;IAEnC,KAAK,MAAM,SAAS,IAAI,YAAY,EAAE,CAAC;QACrC,yDAAyD;QACzD,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,KAAK,CAChC;;;;iCAI2B,EAC3B,CAAC,SAAS,CAAC,CACZ,CAAC;QAEF,IAAI,SAAS,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAChC,OAAO,CAAC,IAAI,CACV,yBAAyB,SAAS,gCAAgC,CACnE,CAAC;YACF,SAAS;QACX,CAAC;QAED,MAAM,MAAM,GAAoB,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YAC3D,IAAI,EAAE,GAAG,CAAC,WAAW;YACrB,IAAI,EAAE,GAAG,CAAC,SAAS;SACpB,CAAC,CAAC,CAAC;QAEJ,yDAAyD;QACzD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,KAAK,CAC/B;;;;;;;;;;;;;wCAakC,EAClC,CAAC,SAAS,CAAC,CACZ,CAAC;QAEF,MAAM,SAAS,GAAuB,QAAQ,CAAC,IAAI;aAChD,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,YAAY,CAAC,QAAQ,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;aACzD,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YACb,KAAK,EAAE,GAAG,CAAC,aAAa;YACxB,UAAU,EAAE,GAAG,CAAC,WAAW;YAC3B,YAAY,EAAE,GAAG,CAAC,aAAa;SAChC,CAAC,CAAC,CAAC;QAEN,MAAM,CAAC,IAAI,CAAC;YACV,IAAI,EAAE,SAAS;YACf,MAAM;YACN,SAAS,EAAE,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;SACxD,CAAC,CAAC;IACL,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,CAAC;AACpB,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Embedded Chat Playground for SDK users
3
+ *
4
+ * Developers can mount this in their Express apps:
5
+ * app.get('/playground', agent.playgroundUI())
6
+ *
7
+ * This provides a ready-to-use chat interface for testing the AI agent.
8
+ */
9
+ export declare function getPlaygroundHTML(config: {
10
+ chatEndpoint: string;
11
+ defaultUserId?: string;
12
+ defaultOrgId?: string;
13
+ defaultRole?: string;
14
+ projectName?: string;
15
+ }): string;
16
+ //# sourceMappingURL=playground.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"playground.d.ts","sourceRoot":"","sources":["../src/playground.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE;IACxC,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,GAAG,MAAM,CAw0BT"}