@axiom-lattice/gateway 2.1.40 → 2.1.41
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/.turbo/turbo-build.log +8 -8
- package/CHANGELOG.md +8 -0
- package/dist/index.js +464 -170
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +415 -118
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -3
- package/public/sdk/README.md +695 -0
- package/public/sdk/dashboard-engine-skill.md +1122 -0
- package/public/sdk/dashboard-single-file-spec.md +357 -0
- package/public/sdk/data-query-sdk-skill.md +307 -0
- package/public/sdk/data-query-sdk.d.ts +252 -0
- package/public/sdk/data-query-sdk.js +970 -0
- package/public/sdk/occupancy-dashboard.html +363 -0
- package/public/sdk/test-dashboard.html +690 -0
- package/src/__tests__/data-query.test.ts +77 -0
- package/src/controllers/data-query.ts +236 -0
- package/src/controllers/metrics-configs.ts +29 -25
- package/src/controllers/workspace.ts +95 -1
- package/src/index.ts +11 -0
- package/src/routes/index.ts +11 -0
- package/src/schemas/data-query.ts +69 -0
- package/src/schemas/index.ts +3 -0
- package/src/services/agent_task_consumer.ts +2 -0
package/dist/index.mjs
CHANGED
|
@@ -4,6 +4,8 @@ import cors from "@fastify/cors";
|
|
|
4
4
|
import multipart from "@fastify/multipart";
|
|
5
5
|
import sensible from "@fastify/sensible";
|
|
6
6
|
import websocket from "@fastify/websocket";
|
|
7
|
+
import staticPlugin from "@fastify/static";
|
|
8
|
+
import path2 from "path";
|
|
7
9
|
|
|
8
10
|
// src/services/agent_service.ts
|
|
9
11
|
import {
|
|
@@ -1841,6 +1843,215 @@ async function getToolConfigs(request, reply) {
|
|
|
1841
1843
|
}
|
|
1842
1844
|
}
|
|
1843
1845
|
|
|
1846
|
+
// src/controllers/data-query.ts
|
|
1847
|
+
import {
|
|
1848
|
+
getStoreLattice as getStoreLattice4,
|
|
1849
|
+
metricsServerManager
|
|
1850
|
+
} from "@axiom-lattice/core";
|
|
1851
|
+
function getTenantId5(request) {
|
|
1852
|
+
return request.headers["x-tenant-id"] || "default";
|
|
1853
|
+
}
|
|
1854
|
+
async function executeDataQuery(request, reply) {
|
|
1855
|
+
const tenantId = getTenantId5(request);
|
|
1856
|
+
const body = request.body;
|
|
1857
|
+
try {
|
|
1858
|
+
if (!body.serverKey && !body.datasourceId) {
|
|
1859
|
+
reply.code(400);
|
|
1860
|
+
return {
|
|
1861
|
+
success: false,
|
|
1862
|
+
message: "Either serverKey or datasourceId must be provided"
|
|
1863
|
+
};
|
|
1864
|
+
}
|
|
1865
|
+
const isSemanticQuery = body.metrics && body.metrics.length > 0;
|
|
1866
|
+
const isSqlQuery = body.customSql && body.customSql.trim().length > 0;
|
|
1867
|
+
if (!isSemanticQuery && !isSqlQuery) {
|
|
1868
|
+
reply.code(400);
|
|
1869
|
+
return {
|
|
1870
|
+
success: false,
|
|
1871
|
+
message: "Either metrics (for semantic query) or customSql (for SQL query) must be provided"
|
|
1872
|
+
};
|
|
1873
|
+
}
|
|
1874
|
+
if (isSemanticQuery && isSqlQuery) {
|
|
1875
|
+
reply.code(400);
|
|
1876
|
+
return {
|
|
1877
|
+
success: false,
|
|
1878
|
+
message: "Cannot provide both metrics and customSql. Use one query type only."
|
|
1879
|
+
};
|
|
1880
|
+
}
|
|
1881
|
+
const storeLattice = getStoreLattice4("default", "metrics");
|
|
1882
|
+
const store = storeLattice.store;
|
|
1883
|
+
if (!body.serverKey) {
|
|
1884
|
+
reply.code(400);
|
|
1885
|
+
return {
|
|
1886
|
+
success: false,
|
|
1887
|
+
message: "serverKey is required"
|
|
1888
|
+
};
|
|
1889
|
+
}
|
|
1890
|
+
const config = await store.getConfigByKey(tenantId, body.serverKey);
|
|
1891
|
+
if (!config) {
|
|
1892
|
+
reply.code(404);
|
|
1893
|
+
return {
|
|
1894
|
+
success: false,
|
|
1895
|
+
message: `Metrics server configuration not found: ${body.serverKey}`
|
|
1896
|
+
};
|
|
1897
|
+
}
|
|
1898
|
+
if (config.config.type !== "semantic") {
|
|
1899
|
+
reply.code(400);
|
|
1900
|
+
return {
|
|
1901
|
+
success: false,
|
|
1902
|
+
message: "This endpoint only supports semantic metrics servers"
|
|
1903
|
+
};
|
|
1904
|
+
}
|
|
1905
|
+
if (!body.datasourceId) {
|
|
1906
|
+
reply.code(400);
|
|
1907
|
+
return {
|
|
1908
|
+
success: false,
|
|
1909
|
+
message: "datasourceId is required"
|
|
1910
|
+
};
|
|
1911
|
+
}
|
|
1912
|
+
if (!metricsServerManager.hasServer(tenantId, body.serverKey)) {
|
|
1913
|
+
reply.code(400);
|
|
1914
|
+
return {
|
|
1915
|
+
success: false,
|
|
1916
|
+
message: `Metrics server not registered: ${body.serverKey}. Please register the server first.`
|
|
1917
|
+
};
|
|
1918
|
+
}
|
|
1919
|
+
const client = metricsServerManager.getClient(tenantId, body.serverKey);
|
|
1920
|
+
if (isSemanticQuery) {
|
|
1921
|
+
return await executeSemanticQuery(client, body, reply);
|
|
1922
|
+
} else {
|
|
1923
|
+
return await executeSqlQuery(client, body, reply);
|
|
1924
|
+
}
|
|
1925
|
+
} catch (error) {
|
|
1926
|
+
console.error("Failed to execute data query:", error);
|
|
1927
|
+
reply.code(500);
|
|
1928
|
+
return {
|
|
1929
|
+
success: false,
|
|
1930
|
+
message: `Failed to execute data query: ${error instanceof Error ? error.message : String(error)}`
|
|
1931
|
+
};
|
|
1932
|
+
}
|
|
1933
|
+
}
|
|
1934
|
+
async function executeSemanticQuery(client, body, reply) {
|
|
1935
|
+
const semanticFilters = (body.filters || []).map((f) => ({
|
|
1936
|
+
dimension: f.dimension,
|
|
1937
|
+
operator: f.operator,
|
|
1938
|
+
values: f.values
|
|
1939
|
+
}));
|
|
1940
|
+
const result = await client.semanticQuery({
|
|
1941
|
+
datasourceId: body.datasourceId,
|
|
1942
|
+
metrics: body.metrics,
|
|
1943
|
+
groupBy: body.groupBy,
|
|
1944
|
+
filters: semanticFilters,
|
|
1945
|
+
limit: body.limit || 1e3
|
|
1946
|
+
});
|
|
1947
|
+
return {
|
|
1948
|
+
success: true,
|
|
1949
|
+
message: "Semantic query executed successfully",
|
|
1950
|
+
data: {
|
|
1951
|
+
semanticModel: result.semanticModel,
|
|
1952
|
+
columns: result.columns,
|
|
1953
|
+
rows: result.rows,
|
|
1954
|
+
rowsObject: result.rowsObject,
|
|
1955
|
+
metadata: {
|
|
1956
|
+
rowCount: result.rowCount,
|
|
1957
|
+
executionTimeMs: result.executionTimeMs
|
|
1958
|
+
}
|
|
1959
|
+
}
|
|
1960
|
+
};
|
|
1961
|
+
}
|
|
1962
|
+
async function executeSqlQuery(client, body, reply) {
|
|
1963
|
+
const result = await client.executeSqlQuery({
|
|
1964
|
+
datasourceId: body.datasourceId,
|
|
1965
|
+
customSql: body.customSql,
|
|
1966
|
+
params: body.params,
|
|
1967
|
+
limit: body.limit || 100
|
|
1968
|
+
});
|
|
1969
|
+
return {
|
|
1970
|
+
success: true,
|
|
1971
|
+
message: "SQL query executed successfully",
|
|
1972
|
+
data: {
|
|
1973
|
+
tableName: result.tableName,
|
|
1974
|
+
columns: result.columns.map((name) => ({ name, type: "unknown" })),
|
|
1975
|
+
rows: result.rows,
|
|
1976
|
+
rowsObject: result.rowsObject,
|
|
1977
|
+
executedSql: result.executedSql,
|
|
1978
|
+
metadata: {
|
|
1979
|
+
rowCount: result.rowCount,
|
|
1980
|
+
executionTimeMs: result.executionTimeMs
|
|
1981
|
+
}
|
|
1982
|
+
}
|
|
1983
|
+
};
|
|
1984
|
+
}
|
|
1985
|
+
|
|
1986
|
+
// src/schemas/data-query.ts
|
|
1987
|
+
var dataQuerySchema = {
|
|
1988
|
+
description: "Execute data query (semantic or SQL)",
|
|
1989
|
+
tags: ["Data Query"],
|
|
1990
|
+
summary: "Query Data",
|
|
1991
|
+
body: {
|
|
1992
|
+
type: "object",
|
|
1993
|
+
properties: {
|
|
1994
|
+
serverKey: {
|
|
1995
|
+
type: "string",
|
|
1996
|
+
description: "Target semantic metrics server key (optional if configured in runConfig)"
|
|
1997
|
+
},
|
|
1998
|
+
datasourceId: {
|
|
1999
|
+
type: "string",
|
|
2000
|
+
description: "Data source ID (optional if configured in runConfig)"
|
|
2001
|
+
},
|
|
2002
|
+
// Semantic query parameters
|
|
2003
|
+
metrics: {
|
|
2004
|
+
type: "array",
|
|
2005
|
+
items: { type: "string" },
|
|
2006
|
+
description: "Array of metric names for semantic query"
|
|
2007
|
+
},
|
|
2008
|
+
groupBy: {
|
|
2009
|
+
type: "array",
|
|
2010
|
+
items: { type: "string" },
|
|
2011
|
+
description: "Optional array of dimensions to group by"
|
|
2012
|
+
},
|
|
2013
|
+
filters: {
|
|
2014
|
+
type: "array",
|
|
2015
|
+
items: {
|
|
2016
|
+
type: "object",
|
|
2017
|
+
properties: {
|
|
2018
|
+
dimension: { type: "string" },
|
|
2019
|
+
operator: { type: "string" },
|
|
2020
|
+
values: {
|
|
2021
|
+
type: "array",
|
|
2022
|
+
items: { type: ["string", "number", "boolean"] }
|
|
2023
|
+
}
|
|
2024
|
+
},
|
|
2025
|
+
required: ["dimension", "operator", "values"]
|
|
2026
|
+
},
|
|
2027
|
+
description: "Optional array of filters"
|
|
2028
|
+
},
|
|
2029
|
+
// SQL query parameters
|
|
2030
|
+
customSql: {
|
|
2031
|
+
type: "string",
|
|
2032
|
+
description: "Custom SQL query string with named parameters"
|
|
2033
|
+
},
|
|
2034
|
+
params: {
|
|
2035
|
+
type: "object",
|
|
2036
|
+
additionalProperties: { type: ["string", "number", "boolean"] },
|
|
2037
|
+
description: "Optional parameters for SQL query"
|
|
2038
|
+
},
|
|
2039
|
+
// Common parameters
|
|
2040
|
+
limit: {
|
|
2041
|
+
type: "number",
|
|
2042
|
+
description: "Maximum number of results (default: 1000)"
|
|
2043
|
+
},
|
|
2044
|
+
format: {
|
|
2045
|
+
type: "string",
|
|
2046
|
+
enum: ["echarts", "raw"],
|
|
2047
|
+
description: "Response format (default: echarts)"
|
|
2048
|
+
}
|
|
2049
|
+
}
|
|
2050
|
+
}
|
|
2051
|
+
// Response schema temporarily removed - format not yet finalized
|
|
2052
|
+
// TODO: Add proper response schema once data format is confirmed
|
|
2053
|
+
};
|
|
2054
|
+
|
|
1844
2055
|
// src/schemas/index.ts
|
|
1845
2056
|
var getAllMemoryItemsSchema = {
|
|
1846
2057
|
description: "Get all memory items for an assistant thread",
|
|
@@ -2302,8 +2513,8 @@ var sandboxService = new SandboxService();
|
|
|
2302
2513
|
|
|
2303
2514
|
// src/controllers/sandbox.ts
|
|
2304
2515
|
import { getSandBoxManager as getSandBoxManager2 } from "@axiom-lattice/core";
|
|
2305
|
-
function getFilenameFromPath(
|
|
2306
|
-
const segments =
|
|
2516
|
+
function getFilenameFromPath(path3) {
|
|
2517
|
+
const segments = path3.replace(/\/+$/, "").split("/");
|
|
2307
2518
|
return segments[segments.length - 1] || "download";
|
|
2308
2519
|
}
|
|
2309
2520
|
var EXT_TO_MIME = {
|
|
@@ -2355,10 +2566,10 @@ function registerSandboxProxyRoutes(app2) {
|
|
|
2355
2566
|
const pathValue = pathEntry && typeof pathEntry === "object" && "value" in pathEntry ? String(pathEntry.value) : typeof pathEntry === "string" ? pathEntry : void 0;
|
|
2356
2567
|
const formData = new FormData();
|
|
2357
2568
|
formData.append("file", new Blob([buffer]), data.filename ?? "file");
|
|
2358
|
-
const
|
|
2569
|
+
const path3 = `/home/gem/uploads/${pathValue ? pathValue : ""}${data.filename}`;
|
|
2359
2570
|
const uploadResult = await sandbox.file.uploadFile({
|
|
2360
2571
|
file: buffer,
|
|
2361
|
-
path:
|
|
2572
|
+
path: path3
|
|
2362
2573
|
});
|
|
2363
2574
|
if (!uploadResult.ok) {
|
|
2364
2575
|
return reply.status(502).send({ error: `Upload error: ${uploadResult.error}` });
|
|
@@ -2446,14 +2657,14 @@ function registerSandboxProxyRoutes(app2) {
|
|
|
2446
2657
|
import * as fs from "fs/promises";
|
|
2447
2658
|
import * as path from "path";
|
|
2448
2659
|
import { Readable as Readable2 } from "stream";
|
|
2449
|
-
import { getStoreLattice as
|
|
2660
|
+
import { getStoreLattice as getStoreLattice5 } from "@axiom-lattice/core";
|
|
2450
2661
|
import { SandboxFilesystem, FilesystemBackend } from "@axiom-lattice/core";
|
|
2451
2662
|
import { getSandBoxManager as getSandBoxManager3 } from "@axiom-lattice/core";
|
|
2452
2663
|
import { v4 as uuidv4 } from "uuid";
|
|
2453
2664
|
var WorkspaceController = class {
|
|
2454
2665
|
constructor() {
|
|
2455
|
-
this.workspaceStore =
|
|
2456
|
-
this.projectStore =
|
|
2666
|
+
this.workspaceStore = getStoreLattice5("default", "workspace").store;
|
|
2667
|
+
this.projectStore = getStoreLattice5("default", "project").store;
|
|
2457
2668
|
}
|
|
2458
2669
|
getTenantId(request) {
|
|
2459
2670
|
const userTenantId = request.user?.tenantId;
|
|
@@ -2731,6 +2942,33 @@ var WorkspaceController = class {
|
|
|
2731
2942
|
const webStream = body.stream();
|
|
2732
2943
|
const nodeStream = Readable2.fromWeb(webStream);
|
|
2733
2944
|
const contentType2 = body.contentType ?? inferredContentType;
|
|
2945
|
+
console.log(`[viewFile] Sandbox returned stream, contentType: ${contentType2}, filename: ${filename2}`);
|
|
2946
|
+
const isHtml2 = contentType2?.toLowerCase().includes("text/html") || filename2.toLowerCase().endsWith(".html") || filename2.toLowerCase().endsWith(".htm");
|
|
2947
|
+
if (isHtml2) {
|
|
2948
|
+
console.log(`[viewFile] HTML stream detected, collecting for context injection`);
|
|
2949
|
+
const chunks = [];
|
|
2950
|
+
for await (const chunk of nodeStream) {
|
|
2951
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
2952
|
+
}
|
|
2953
|
+
let content2 = Buffer.concat(chunks).toString("utf-8");
|
|
2954
|
+
const contextScript = `<script>window.__AI2APP_CONTEXT__=${JSON.stringify({
|
|
2955
|
+
tenantId,
|
|
2956
|
+
workspaceId,
|
|
2957
|
+
projectId,
|
|
2958
|
+
timestamp: Date.now()
|
|
2959
|
+
})};</script>`;
|
|
2960
|
+
if (content2.toLowerCase().includes("</head>")) {
|
|
2961
|
+
content2 = content2.replace(/<\/head>/i, `${contextScript}</head>`);
|
|
2962
|
+
console.log(`[viewFile] Context script injected before </head> (stream)`);
|
|
2963
|
+
} else if (content2.toLowerCase().includes("<html>")) {
|
|
2964
|
+
content2 = content2.replace(/<html>/i, `<html>${contextScript}`);
|
|
2965
|
+
console.log(`[viewFile] Context script injected after <html> (stream)`);
|
|
2966
|
+
} else {
|
|
2967
|
+
content2 = contextScript + content2;
|
|
2968
|
+
console.log(`[viewFile] Context script prepended to content (stream)`);
|
|
2969
|
+
}
|
|
2970
|
+
return reply.status(200).type(contentType2).header("Content-Disposition", "inline").send(Buffer.from(content2, "utf-8"));
|
|
2971
|
+
}
|
|
2734
2972
|
return reply.status(200).type(contentType2).header("Content-Disposition", "inline").send(nodeStream);
|
|
2735
2973
|
}
|
|
2736
2974
|
const bodyUnknown = downloadResult.body;
|
|
@@ -2750,13 +2988,56 @@ var WorkspaceController = class {
|
|
|
2750
2988
|
} else {
|
|
2751
2989
|
return reply.status(502).send({ success: false, error: "Unexpected view response format" });
|
|
2752
2990
|
}
|
|
2991
|
+
const isHtml = contentType?.toLowerCase().includes("text/html") || filename2.toLowerCase().endsWith(".html") || filename2.toLowerCase().endsWith(".htm");
|
|
2992
|
+
if (isHtml) {
|
|
2993
|
+
console.log(`[viewFile] Injecting AI2APP context for sandbox HTML file: ${filename2}, tenantId: ${tenantId}, contentType: ${contentType}`);
|
|
2994
|
+
let content2 = buf.toString("utf-8");
|
|
2995
|
+
const contextScript = `<script>window.__AI2APP_CONTEXT__=${JSON.stringify({
|
|
2996
|
+
tenantId,
|
|
2997
|
+
workspaceId,
|
|
2998
|
+
projectId,
|
|
2999
|
+
timestamp: Date.now()
|
|
3000
|
+
})};</script>`;
|
|
3001
|
+
if (content2.toLowerCase().includes("</head>")) {
|
|
3002
|
+
content2 = content2.replace(/<\/head>/i, `${contextScript}</head>`);
|
|
3003
|
+
console.log(`[viewFile] Context script injected before </head>`);
|
|
3004
|
+
} else if (content2.toLowerCase().includes("<html>")) {
|
|
3005
|
+
content2 = content2.replace(/<html>/i, `<html>${contextScript}`);
|
|
3006
|
+
console.log(`[viewFile] Context script injected after <html>`);
|
|
3007
|
+
} else {
|
|
3008
|
+
content2 = contextScript + content2;
|
|
3009
|
+
console.log(`[viewFile] Context script prepended to content`);
|
|
3010
|
+
}
|
|
3011
|
+
buf = Buffer.from(content2, "utf-8");
|
|
3012
|
+
}
|
|
2753
3013
|
return reply.status(200).type(contentType).header("Content-Disposition", "inline").send(buf);
|
|
2754
3014
|
}
|
|
2755
3015
|
const { backend } = await this.getBackend(tenantId, workspaceId, projectId);
|
|
2756
3016
|
const content = await backend.read(resolvedPath, 0, Infinity);
|
|
2757
3017
|
const filename = this.getFilenameFromPath(resolvedPath);
|
|
2758
3018
|
const mimeType = this.getMimeType(filename);
|
|
2759
|
-
|
|
3019
|
+
let finalContent = content;
|
|
3020
|
+
const isHtmlFs = mimeType?.toLowerCase().includes("text/html") || filename.toLowerCase().endsWith(".html") || filename.toLowerCase().endsWith(".htm");
|
|
3021
|
+
if (isHtmlFs) {
|
|
3022
|
+
console.log(`[viewFile] Injecting AI2APP context for filesystem HTML file: ${filename}, tenantId: ${tenantId}, mimeType: ${mimeType}`);
|
|
3023
|
+
const contextScript = `<script>window.__AI2APP_CONTEXT__=${JSON.stringify({
|
|
3024
|
+
tenantId,
|
|
3025
|
+
workspaceId,
|
|
3026
|
+
projectId,
|
|
3027
|
+
timestamp: Date.now()
|
|
3028
|
+
})};</script>`;
|
|
3029
|
+
if (content.toLowerCase().includes("</head>")) {
|
|
3030
|
+
finalContent = content.replace(/<\/head>/i, `${contextScript}</head>`);
|
|
3031
|
+
console.log(`[viewFile] Context script injected before </head>`);
|
|
3032
|
+
} else if (content.toLowerCase().includes("</html>")) {
|
|
3033
|
+
finalContent = content.replace(/<\/html>/i, `${contextScript}</html>`);
|
|
3034
|
+
console.log(`[viewFile] Context script injected before </html>`);
|
|
3035
|
+
} else {
|
|
3036
|
+
finalContent = content + contextScript;
|
|
3037
|
+
console.log(`[viewFile] Context script appended to content`);
|
|
3038
|
+
}
|
|
3039
|
+
}
|
|
3040
|
+
const buffer = Buffer.from(finalContent, "utf-8");
|
|
2760
3041
|
return reply.status(200).type(mimeType).header("Content-Disposition", "inline").send(buffer);
|
|
2761
3042
|
} catch (error) {
|
|
2762
3043
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -2766,17 +3047,17 @@ var WorkspaceController = class {
|
|
|
2766
3047
|
async listPath(request) {
|
|
2767
3048
|
const tenantId = this.getTenantId(request);
|
|
2768
3049
|
const { workspaceId, projectId } = request.params;
|
|
2769
|
-
const
|
|
3050
|
+
const path3 = request.query.path || "/";
|
|
2770
3051
|
const { backend } = await this.getBackend(tenantId, workspaceId, projectId);
|
|
2771
|
-
const files = await backend.lsInfo(
|
|
3052
|
+
const files = await backend.lsInfo(path3);
|
|
2772
3053
|
return { success: true, data: files };
|
|
2773
3054
|
}
|
|
2774
3055
|
async readFile(request) {
|
|
2775
3056
|
const tenantId = this.getTenantId(request);
|
|
2776
3057
|
const { workspaceId, projectId } = request.params;
|
|
2777
|
-
const { path:
|
|
3058
|
+
const { path: path3, offset = 0, limit = 1e3 } = request.query;
|
|
2778
3059
|
const { backend } = await this.getBackend(tenantId, workspaceId, projectId);
|
|
2779
|
-
const content = await backend.read(
|
|
3060
|
+
const content = await backend.read(path3, Number(offset), Number(limit));
|
|
2780
3061
|
return { success: true, data: { content, offset, limit } };
|
|
2781
3062
|
}
|
|
2782
3063
|
/**
|
|
@@ -2919,11 +3200,11 @@ function registerWorkspaceRoutes(app2) {
|
|
|
2919
3200
|
|
|
2920
3201
|
// src/controllers/database-configs.ts
|
|
2921
3202
|
import {
|
|
2922
|
-
getStoreLattice as
|
|
3203
|
+
getStoreLattice as getStoreLattice6,
|
|
2923
3204
|
sqlDatabaseManager
|
|
2924
3205
|
} from "@axiom-lattice/core";
|
|
2925
3206
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
2926
|
-
function
|
|
3207
|
+
function getTenantId6(request) {
|
|
2927
3208
|
const userTenantId = request.user?.tenantId;
|
|
2928
3209
|
if (userTenantId) {
|
|
2929
3210
|
return userTenantId;
|
|
@@ -2931,9 +3212,9 @@ function getTenantId5(request) {
|
|
|
2931
3212
|
return request.headers["x-tenant-id"] || "default";
|
|
2932
3213
|
}
|
|
2933
3214
|
async function getDatabaseConfigList(request, reply) {
|
|
2934
|
-
const tenantId =
|
|
3215
|
+
const tenantId = getTenantId6(request);
|
|
2935
3216
|
try {
|
|
2936
|
-
const storeLattice =
|
|
3217
|
+
const storeLattice = getStoreLattice6("default", "database");
|
|
2937
3218
|
const store = storeLattice.store;
|
|
2938
3219
|
const configs = await store.getAllConfigs(tenantId);
|
|
2939
3220
|
console.log("Backend: getAllConfigs returned:", configs);
|
|
@@ -2961,10 +3242,10 @@ async function getDatabaseConfigList(request, reply) {
|
|
|
2961
3242
|
}
|
|
2962
3243
|
}
|
|
2963
3244
|
async function getDatabaseConfig(request, reply) {
|
|
2964
|
-
const tenantId =
|
|
3245
|
+
const tenantId = getTenantId6(request);
|
|
2965
3246
|
const { key } = request.params;
|
|
2966
3247
|
try {
|
|
2967
|
-
const storeLattice =
|
|
3248
|
+
const storeLattice = getStoreLattice6("default", "database");
|
|
2968
3249
|
const store = storeLattice.store;
|
|
2969
3250
|
const config = await store.getConfigByKey(tenantId, key);
|
|
2970
3251
|
if (!config) {
|
|
@@ -2987,10 +3268,10 @@ async function getDatabaseConfig(request, reply) {
|
|
|
2987
3268
|
}
|
|
2988
3269
|
}
|
|
2989
3270
|
async function createDatabaseConfig(request, reply) {
|
|
2990
|
-
const tenantId =
|
|
3271
|
+
const tenantId = getTenantId6(request);
|
|
2991
3272
|
const body = request.body;
|
|
2992
3273
|
try {
|
|
2993
|
-
const storeLattice =
|
|
3274
|
+
const storeLattice = getStoreLattice6("default", "database");
|
|
2994
3275
|
const store = storeLattice.store;
|
|
2995
3276
|
const existing = await store.getConfigByKey(tenantId, body.key);
|
|
2996
3277
|
if (existing) {
|
|
@@ -3022,11 +3303,11 @@ async function createDatabaseConfig(request, reply) {
|
|
|
3022
3303
|
}
|
|
3023
3304
|
}
|
|
3024
3305
|
async function updateDatabaseConfig(request, reply) {
|
|
3025
|
-
const tenantId =
|
|
3306
|
+
const tenantId = getTenantId6(request);
|
|
3026
3307
|
const { key } = request.params;
|
|
3027
3308
|
const updates = request.body;
|
|
3028
3309
|
try {
|
|
3029
|
-
const storeLattice =
|
|
3310
|
+
const storeLattice = getStoreLattice6("default", "database");
|
|
3030
3311
|
const store = storeLattice.store;
|
|
3031
3312
|
const existing = await store.getConfigByKey(tenantId, key);
|
|
3032
3313
|
if (!existing) {
|
|
@@ -3064,10 +3345,10 @@ async function updateDatabaseConfig(request, reply) {
|
|
|
3064
3345
|
}
|
|
3065
3346
|
}
|
|
3066
3347
|
async function deleteDatabaseConfig(request, reply) {
|
|
3067
|
-
const tenantId =
|
|
3348
|
+
const tenantId = getTenantId6(request);
|
|
3068
3349
|
const { keyOrId } = request.params;
|
|
3069
3350
|
try {
|
|
3070
|
-
const storeLattice =
|
|
3351
|
+
const storeLattice = getStoreLattice6("default", "database");
|
|
3071
3352
|
const store = storeLattice.store;
|
|
3072
3353
|
console.log("Delete request - keyOrId:", keyOrId);
|
|
3073
3354
|
let config = await store.getConfigByKey(tenantId, keyOrId);
|
|
@@ -3113,10 +3394,10 @@ async function deleteDatabaseConfig(request, reply) {
|
|
|
3113
3394
|
}
|
|
3114
3395
|
}
|
|
3115
3396
|
async function testDatabaseConnection(request, reply) {
|
|
3116
|
-
const tenantId =
|
|
3397
|
+
const tenantId = getTenantId6(request);
|
|
3117
3398
|
const { key } = request.params;
|
|
3118
3399
|
try {
|
|
3119
|
-
const storeLattice =
|
|
3400
|
+
const storeLattice = getStoreLattice6("default", "database");
|
|
3120
3401
|
const store = storeLattice.store;
|
|
3121
3402
|
const config = await store.getConfigByKey(tenantId, key);
|
|
3122
3403
|
if (!config) {
|
|
@@ -3201,12 +3482,12 @@ function registerDatabaseConfigRoutes(app2) {
|
|
|
3201
3482
|
|
|
3202
3483
|
// src/controllers/metrics-configs.ts
|
|
3203
3484
|
import {
|
|
3204
|
-
getStoreLattice as
|
|
3205
|
-
metricsServerManager,
|
|
3206
|
-
SemanticMetricsClient
|
|
3485
|
+
getStoreLattice as getStoreLattice7,
|
|
3486
|
+
metricsServerManager as metricsServerManager2,
|
|
3487
|
+
SemanticMetricsClient as SemanticMetricsClient2
|
|
3207
3488
|
} from "@axiom-lattice/core";
|
|
3208
3489
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
3209
|
-
function
|
|
3490
|
+
function getTenantId7(request) {
|
|
3210
3491
|
const userTenantId = request.user?.tenantId;
|
|
3211
3492
|
if (userTenantId) {
|
|
3212
3493
|
return userTenantId;
|
|
@@ -3214,9 +3495,9 @@ function getTenantId6(request) {
|
|
|
3214
3495
|
return request.headers["x-tenant-id"] || "default";
|
|
3215
3496
|
}
|
|
3216
3497
|
async function getMetricsServerConfigList(request, reply) {
|
|
3217
|
-
const tenantId =
|
|
3498
|
+
const tenantId = getTenantId7(request);
|
|
3218
3499
|
try {
|
|
3219
|
-
const storeLattice =
|
|
3500
|
+
const storeLattice = getStoreLattice7("default", "metrics");
|
|
3220
3501
|
const store = storeLattice.store;
|
|
3221
3502
|
const configs = await store.getAllConfigs(tenantId);
|
|
3222
3503
|
return {
|
|
@@ -3240,10 +3521,10 @@ async function getMetricsServerConfigList(request, reply) {
|
|
|
3240
3521
|
}
|
|
3241
3522
|
}
|
|
3242
3523
|
async function getMetricsServerConfig(request, reply) {
|
|
3243
|
-
const tenantId =
|
|
3524
|
+
const tenantId = getTenantId7(request);
|
|
3244
3525
|
const { key } = request.params;
|
|
3245
3526
|
try {
|
|
3246
|
-
const storeLattice =
|
|
3527
|
+
const storeLattice = getStoreLattice7("default", "metrics");
|
|
3247
3528
|
const store = storeLattice.store;
|
|
3248
3529
|
const config = await store.getConfigByKey(tenantId, key);
|
|
3249
3530
|
if (!config) {
|
|
@@ -3266,10 +3547,10 @@ async function getMetricsServerConfig(request, reply) {
|
|
|
3266
3547
|
}
|
|
3267
3548
|
}
|
|
3268
3549
|
async function createMetricsServerConfig(request, reply) {
|
|
3269
|
-
const tenantId =
|
|
3550
|
+
const tenantId = getTenantId7(request);
|
|
3270
3551
|
const body = request.body;
|
|
3271
3552
|
try {
|
|
3272
|
-
const storeLattice =
|
|
3553
|
+
const storeLattice = getStoreLattice7("default", "metrics");
|
|
3273
3554
|
const store = storeLattice.store;
|
|
3274
3555
|
const existing = await store.getConfigByKey(tenantId, body.key);
|
|
3275
3556
|
if (existing) {
|
|
@@ -3298,7 +3579,7 @@ async function createMetricsServerConfig(request, reply) {
|
|
|
3298
3579
|
};
|
|
3299
3580
|
const config = await store.createConfig(tenantId, id, configData);
|
|
3300
3581
|
try {
|
|
3301
|
-
|
|
3582
|
+
metricsServerManager2.registerServer(tenantId, config.key, config.config);
|
|
3302
3583
|
} catch (error) {
|
|
3303
3584
|
console.warn("Failed to auto-register metrics server:", error);
|
|
3304
3585
|
}
|
|
@@ -3317,11 +3598,11 @@ async function createMetricsServerConfig(request, reply) {
|
|
|
3317
3598
|
}
|
|
3318
3599
|
}
|
|
3319
3600
|
async function updateMetricsServerConfig(request, reply) {
|
|
3320
|
-
const tenantId =
|
|
3601
|
+
const tenantId = getTenantId7(request);
|
|
3321
3602
|
const { key } = request.params;
|
|
3322
3603
|
const updates = request.body;
|
|
3323
3604
|
try {
|
|
3324
|
-
const storeLattice =
|
|
3605
|
+
const storeLattice = getStoreLattice7("default", "metrics");
|
|
3325
3606
|
const store = storeLattice.store;
|
|
3326
3607
|
const existing = await store.getConfigByKey(tenantId, key);
|
|
3327
3608
|
if (!existing) {
|
|
@@ -3349,7 +3630,7 @@ async function updateMetricsServerConfig(request, reply) {
|
|
|
3349
3630
|
}
|
|
3350
3631
|
if (updates.config) {
|
|
3351
3632
|
try {
|
|
3352
|
-
|
|
3633
|
+
metricsServerManager2.registerServer(tenantId, updated.key, updated.config);
|
|
3353
3634
|
} catch (error) {
|
|
3354
3635
|
console.warn("Failed to re-register metrics server:", error);
|
|
3355
3636
|
}
|
|
@@ -3368,10 +3649,10 @@ async function updateMetricsServerConfig(request, reply) {
|
|
|
3368
3649
|
}
|
|
3369
3650
|
}
|
|
3370
3651
|
async function deleteMetricsServerConfig(request, reply) {
|
|
3371
|
-
const tenantId =
|
|
3652
|
+
const tenantId = getTenantId7(request);
|
|
3372
3653
|
const { keyOrId } = request.params;
|
|
3373
3654
|
try {
|
|
3374
|
-
const storeLattice =
|
|
3655
|
+
const storeLattice = getStoreLattice7("default", "metrics");
|
|
3375
3656
|
const store = storeLattice.store;
|
|
3376
3657
|
let config = await store.getConfigByKey(tenantId, keyOrId);
|
|
3377
3658
|
let configKey = keyOrId;
|
|
@@ -3396,8 +3677,8 @@ async function deleteMetricsServerConfig(request, reply) {
|
|
|
3396
3677
|
};
|
|
3397
3678
|
}
|
|
3398
3679
|
try {
|
|
3399
|
-
if (
|
|
3400
|
-
|
|
3680
|
+
if (metricsServerManager2.hasServer(tenantId, configKey)) {
|
|
3681
|
+
metricsServerManager2.removeServer(tenantId, configKey);
|
|
3401
3682
|
}
|
|
3402
3683
|
} catch (error) {
|
|
3403
3684
|
console.warn("Failed to remove from MetricsServerManager:", error);
|
|
@@ -3415,10 +3696,10 @@ async function deleteMetricsServerConfig(request, reply) {
|
|
|
3415
3696
|
}
|
|
3416
3697
|
}
|
|
3417
3698
|
async function testMetricsServerConnection(request, reply) {
|
|
3418
|
-
const tenantId =
|
|
3699
|
+
const tenantId = getTenantId7(request);
|
|
3419
3700
|
const { key } = request.params;
|
|
3420
3701
|
try {
|
|
3421
|
-
const storeLattice =
|
|
3702
|
+
const storeLattice = getStoreLattice7("default", "metrics");
|
|
3422
3703
|
const store = storeLattice.store;
|
|
3423
3704
|
const config = await store.getConfigByKey(tenantId, key);
|
|
3424
3705
|
if (!config) {
|
|
@@ -3429,11 +3710,11 @@ async function testMetricsServerConnection(request, reply) {
|
|
|
3429
3710
|
};
|
|
3430
3711
|
}
|
|
3431
3712
|
const testKey = `__test_${key}_${Date.now()}`;
|
|
3432
|
-
|
|
3713
|
+
metricsServerManager2.registerServer(tenantId, testKey, config.config);
|
|
3433
3714
|
try {
|
|
3434
|
-
const client =
|
|
3715
|
+
const client = metricsServerManager2.getClient(tenantId, testKey);
|
|
3435
3716
|
const result = await client.testConnection();
|
|
3436
|
-
|
|
3717
|
+
metricsServerManager2.removeServer(tenantId, testKey);
|
|
3437
3718
|
return {
|
|
3438
3719
|
success: true,
|
|
3439
3720
|
message: result.connected ? "Connection test successful" : "Connection test failed",
|
|
@@ -3441,7 +3722,7 @@ async function testMetricsServerConnection(request, reply) {
|
|
|
3441
3722
|
};
|
|
3442
3723
|
} catch (error) {
|
|
3443
3724
|
try {
|
|
3444
|
-
|
|
3725
|
+
metricsServerManager2.removeServer(tenantId, testKey);
|
|
3445
3726
|
} catch {
|
|
3446
3727
|
}
|
|
3447
3728
|
return {
|
|
@@ -3466,10 +3747,10 @@ async function testMetricsServerConnection(request, reply) {
|
|
|
3466
3747
|
}
|
|
3467
3748
|
}
|
|
3468
3749
|
async function listAvailableMetrics(request, reply) {
|
|
3469
|
-
const tenantId =
|
|
3750
|
+
const tenantId = getTenantId7(request);
|
|
3470
3751
|
const { key } = request.params;
|
|
3471
3752
|
try {
|
|
3472
|
-
const storeLattice =
|
|
3753
|
+
const storeLattice = getStoreLattice7("default", "metrics");
|
|
3473
3754
|
const store = storeLattice.store;
|
|
3474
3755
|
const config = await store.getConfigByKey(tenantId, key);
|
|
3475
3756
|
if (!config) {
|
|
@@ -3479,10 +3760,10 @@ async function listAvailableMetrics(request, reply) {
|
|
|
3479
3760
|
message: "Metrics server configuration not found"
|
|
3480
3761
|
};
|
|
3481
3762
|
}
|
|
3482
|
-
if (!
|
|
3483
|
-
|
|
3763
|
+
if (!metricsServerManager2.hasServer(tenantId, key)) {
|
|
3764
|
+
metricsServerManager2.registerServer(tenantId, key, config.config);
|
|
3484
3765
|
}
|
|
3485
|
-
const client =
|
|
3766
|
+
const client = metricsServerManager2.getClient(tenantId, key);
|
|
3486
3767
|
const metrics = await client.listMetrics();
|
|
3487
3768
|
return {
|
|
3488
3769
|
success: true,
|
|
@@ -3504,11 +3785,11 @@ async function listAvailableMetrics(request, reply) {
|
|
|
3504
3785
|
}
|
|
3505
3786
|
}
|
|
3506
3787
|
async function queryMetricsData(request, reply) {
|
|
3507
|
-
const tenantId =
|
|
3788
|
+
const tenantId = getTenantId7(request);
|
|
3508
3789
|
const { key } = request.params;
|
|
3509
3790
|
const { metricName, startTime, endTime, step, labels } = request.body;
|
|
3510
3791
|
try {
|
|
3511
|
-
const storeLattice =
|
|
3792
|
+
const storeLattice = getStoreLattice7("default", "metrics");
|
|
3512
3793
|
const store = storeLattice.store;
|
|
3513
3794
|
const config = await store.getConfigByKey(tenantId, key);
|
|
3514
3795
|
if (!config) {
|
|
@@ -3525,10 +3806,10 @@ async function queryMetricsData(request, reply) {
|
|
|
3525
3806
|
message: "metricName is required"
|
|
3526
3807
|
};
|
|
3527
3808
|
}
|
|
3528
|
-
if (!
|
|
3529
|
-
|
|
3809
|
+
if (!metricsServerManager2.hasServer(tenantId, key)) {
|
|
3810
|
+
metricsServerManager2.registerServer(tenantId, key, config.config);
|
|
3530
3811
|
}
|
|
3531
|
-
const client =
|
|
3812
|
+
const client = metricsServerManager2.getClient(tenantId, key);
|
|
3532
3813
|
const result = await client.queryMetricData(metricName, {
|
|
3533
3814
|
startTime,
|
|
3534
3815
|
endTime,
|
|
@@ -3552,10 +3833,10 @@ async function queryMetricsData(request, reply) {
|
|
|
3552
3833
|
}
|
|
3553
3834
|
}
|
|
3554
3835
|
async function getDataSources(request, reply) {
|
|
3555
|
-
const tenantId =
|
|
3836
|
+
const tenantId = getTenantId7(request);
|
|
3556
3837
|
const { key } = request.params;
|
|
3557
3838
|
try {
|
|
3558
|
-
const storeLattice =
|
|
3839
|
+
const storeLattice = getStoreLattice7("default", "metrics");
|
|
3559
3840
|
const store = storeLattice.store;
|
|
3560
3841
|
const config = await store.getConfigByKey(tenantId, key);
|
|
3561
3842
|
if (!config) {
|
|
@@ -3573,7 +3854,7 @@ async function getDataSources(request, reply) {
|
|
|
3573
3854
|
};
|
|
3574
3855
|
}
|
|
3575
3856
|
const semanticConfig = config.config;
|
|
3576
|
-
const client = new
|
|
3857
|
+
const client = new SemanticMetricsClient2(semanticConfig);
|
|
3577
3858
|
const allDatasources = await client.getDataSources();
|
|
3578
3859
|
const selectedIds = semanticConfig.selectedDataSources || [];
|
|
3579
3860
|
const filteredDatasources = selectedIds.length > 0 ? allDatasources.filter((ds) => selectedIds.includes(String(ds.id))) : allDatasources;
|
|
@@ -3593,10 +3874,10 @@ async function getDataSources(request, reply) {
|
|
|
3593
3874
|
}
|
|
3594
3875
|
}
|
|
3595
3876
|
async function getDatasourceMetrics(request, reply) {
|
|
3596
|
-
const tenantId =
|
|
3877
|
+
const tenantId = getTenantId7(request);
|
|
3597
3878
|
const { key, datasourceId } = request.params;
|
|
3598
3879
|
try {
|
|
3599
|
-
const storeLattice =
|
|
3880
|
+
const storeLattice = getStoreLattice7("default", "metrics");
|
|
3600
3881
|
const store = storeLattice.store;
|
|
3601
3882
|
const config = await store.getConfigByKey(tenantId, key);
|
|
3602
3883
|
if (!config) {
|
|
@@ -3614,7 +3895,7 @@ async function getDatasourceMetrics(request, reply) {
|
|
|
3614
3895
|
};
|
|
3615
3896
|
}
|
|
3616
3897
|
const semanticConfig = config.config;
|
|
3617
|
-
const client = new
|
|
3898
|
+
const client = new SemanticMetricsClient2(semanticConfig);
|
|
3618
3899
|
const metrics = await client.getDatasourceMetrics(datasourceId);
|
|
3619
3900
|
return {
|
|
3620
3901
|
success: true,
|
|
@@ -3630,11 +3911,11 @@ async function getDatasourceMetrics(request, reply) {
|
|
|
3630
3911
|
}
|
|
3631
3912
|
}
|
|
3632
3913
|
async function querySemanticMetrics(request, reply) {
|
|
3633
|
-
const tenantId =
|
|
3914
|
+
const tenantId = getTenantId7(request);
|
|
3634
3915
|
const { key } = request.params;
|
|
3635
3916
|
const body = request.body;
|
|
3636
3917
|
try {
|
|
3637
|
-
const storeLattice =
|
|
3918
|
+
const storeLattice = getStoreLattice7("default", "metrics");
|
|
3638
3919
|
const store = storeLattice.store;
|
|
3639
3920
|
const config = await store.getConfigByKey(tenantId, key);
|
|
3640
3921
|
if (!config) {
|
|
@@ -3659,33 +3940,37 @@ async function querySemanticMetrics(request, reply) {
|
|
|
3659
3940
|
};
|
|
3660
3941
|
}
|
|
3661
3942
|
const semanticConfig = config.config;
|
|
3662
|
-
const client = new
|
|
3943
|
+
const client = new SemanticMetricsClient2(semanticConfig);
|
|
3663
3944
|
const result = await client.semanticQuery(body);
|
|
3945
|
+
const columnNames = result.columns.map((col) => col.name);
|
|
3664
3946
|
const allDataPoints = [];
|
|
3665
|
-
const
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
|
|
3677
|
-
|
|
3947
|
+
const timestampColIdx = columnNames.findIndex(
|
|
3948
|
+
(col) => col.toLowerCase().includes("date") || col.toLowerCase().includes("time")
|
|
3949
|
+
);
|
|
3950
|
+
const valueColIdx = columnNames.findIndex(
|
|
3951
|
+
(col) => col.toLowerCase().includes("value") || col.toLowerCase().includes("rate") || col.toLowerCase().includes("amt")
|
|
3952
|
+
);
|
|
3953
|
+
for (const row of result.rows) {
|
|
3954
|
+
const timestamp = timestampColIdx >= 0 ? row[timestampColIdx] : void 0;
|
|
3955
|
+
const value = valueColIdx >= 0 ? row[valueColIdx] : row[row.length - 1];
|
|
3956
|
+
allDataPoints.push({
|
|
3957
|
+
timestamp: timestamp ? new Date(String(timestamp)).getTime() : void 0,
|
|
3958
|
+
value: typeof value === "number" ? value : Number(value) || 0,
|
|
3959
|
+
labels: Object.fromEntries(
|
|
3960
|
+
columnNames.map((col, idx) => [col, String(row[idx] ?? "")])
|
|
3961
|
+
)
|
|
3962
|
+
});
|
|
3678
3963
|
}
|
|
3679
3964
|
return {
|
|
3680
3965
|
success: true,
|
|
3681
3966
|
message: "Semantic query executed successfully",
|
|
3682
3967
|
data: {
|
|
3683
|
-
|
|
3684
|
-
|
|
3968
|
+
semanticModel: result.semanticModel,
|
|
3969
|
+
columns: columnNames,
|
|
3685
3970
|
dataPoints: allDataPoints,
|
|
3686
3971
|
metadata: {
|
|
3687
|
-
rowCount:
|
|
3688
|
-
|
|
3972
|
+
rowCount: result.rows.length,
|
|
3973
|
+
columnCount: result.columns.length
|
|
3689
3974
|
}
|
|
3690
3975
|
}
|
|
3691
3976
|
};
|
|
@@ -3715,7 +4000,7 @@ async function testSemanticDataSources(request, reply) {
|
|
|
3715
4000
|
password: body.password,
|
|
3716
4001
|
headers: body.headers
|
|
3717
4002
|
};
|
|
3718
|
-
const client = new
|
|
4003
|
+
const client = new SemanticMetricsClient2(testConfig);
|
|
3719
4004
|
const datasources = await client.getDataSources();
|
|
3720
4005
|
return {
|
|
3721
4006
|
success: true,
|
|
@@ -3751,7 +4036,7 @@ async function testDatasourceMetrics(request, reply) {
|
|
|
3751
4036
|
password: body.password,
|
|
3752
4037
|
headers: body.headers
|
|
3753
4038
|
};
|
|
3754
|
-
const client = new
|
|
4039
|
+
const client = new SemanticMetricsClient2(testConfig);
|
|
3755
4040
|
const metrics = await client.getDatasourceMetrics(datasourceId);
|
|
3756
4041
|
return {
|
|
3757
4042
|
success: true,
|
|
@@ -3784,12 +4069,12 @@ function registerMetricsServerConfigRoutes(app2) {
|
|
|
3784
4069
|
|
|
3785
4070
|
// src/controllers/mcp-configs.ts
|
|
3786
4071
|
import {
|
|
3787
|
-
getStoreLattice as
|
|
4072
|
+
getStoreLattice as getStoreLattice8,
|
|
3788
4073
|
mcpManager,
|
|
3789
4074
|
toolLatticeManager as toolLatticeManager2
|
|
3790
4075
|
} from "@axiom-lattice/core";
|
|
3791
4076
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
3792
|
-
function
|
|
4077
|
+
function getTenantId8(request) {
|
|
3793
4078
|
const userTenantId = request.user?.tenantId;
|
|
3794
4079
|
if (userTenantId) {
|
|
3795
4080
|
return userTenantId;
|
|
@@ -3797,9 +4082,9 @@ function getTenantId7(request) {
|
|
|
3797
4082
|
return request.headers["x-tenant-id"] || "default";
|
|
3798
4083
|
}
|
|
3799
4084
|
async function getMcpServerConfigList(request, reply) {
|
|
3800
|
-
const tenantId =
|
|
4085
|
+
const tenantId = getTenantId8(request);
|
|
3801
4086
|
try {
|
|
3802
|
-
const storeLattice =
|
|
4087
|
+
const storeLattice = getStoreLattice8("default", "mcp");
|
|
3803
4088
|
const store = storeLattice.store;
|
|
3804
4089
|
const configs = await store.getAllConfigs(tenantId);
|
|
3805
4090
|
return {
|
|
@@ -3823,10 +4108,10 @@ async function getMcpServerConfigList(request, reply) {
|
|
|
3823
4108
|
}
|
|
3824
4109
|
}
|
|
3825
4110
|
async function getMcpServerConfig(request, reply) {
|
|
3826
|
-
const tenantId =
|
|
4111
|
+
const tenantId = getTenantId8(request);
|
|
3827
4112
|
const { key } = request.params;
|
|
3828
4113
|
try {
|
|
3829
|
-
const storeLattice =
|
|
4114
|
+
const storeLattice = getStoreLattice8("default", "mcp");
|
|
3830
4115
|
const store = storeLattice.store;
|
|
3831
4116
|
const config = await store.getConfigByKey(tenantId, key);
|
|
3832
4117
|
if (!config) {
|
|
@@ -3849,10 +4134,10 @@ async function getMcpServerConfig(request, reply) {
|
|
|
3849
4134
|
}
|
|
3850
4135
|
}
|
|
3851
4136
|
async function createMcpServerConfig(request, reply) {
|
|
3852
|
-
const tenantId =
|
|
4137
|
+
const tenantId = getTenantId8(request);
|
|
3853
4138
|
const body = request.body;
|
|
3854
4139
|
try {
|
|
3855
|
-
const storeLattice =
|
|
4140
|
+
const storeLattice = getStoreLattice8("default", "mcp");
|
|
3856
4141
|
const store = storeLattice.store;
|
|
3857
4142
|
const existing = await store.getConfigByKey(tenantId, body.key);
|
|
3858
4143
|
if (existing) {
|
|
@@ -3888,11 +4173,11 @@ async function createMcpServerConfig(request, reply) {
|
|
|
3888
4173
|
}
|
|
3889
4174
|
}
|
|
3890
4175
|
async function updateMcpServerConfig(request, reply) {
|
|
3891
|
-
const tenantId =
|
|
4176
|
+
const tenantId = getTenantId8(request);
|
|
3892
4177
|
const { key } = request.params;
|
|
3893
4178
|
const updates = request.body;
|
|
3894
4179
|
try {
|
|
3895
|
-
const storeLattice =
|
|
4180
|
+
const storeLattice = getStoreLattice8("default", "mcp");
|
|
3896
4181
|
const store = storeLattice.store;
|
|
3897
4182
|
const existing = await store.getConfigByKey(tenantId, key);
|
|
3898
4183
|
if (!existing) {
|
|
@@ -3938,10 +4223,10 @@ async function updateMcpServerConfig(request, reply) {
|
|
|
3938
4223
|
}
|
|
3939
4224
|
}
|
|
3940
4225
|
async function deleteMcpServerConfig(request, reply) {
|
|
3941
|
-
const tenantId =
|
|
4226
|
+
const tenantId = getTenantId8(request);
|
|
3942
4227
|
const { keyOrId } = request.params;
|
|
3943
4228
|
try {
|
|
3944
|
-
const storeLattice =
|
|
4229
|
+
const storeLattice = getStoreLattice8("default", "mcp");
|
|
3945
4230
|
const store = storeLattice.store;
|
|
3946
4231
|
let config = await store.getConfigByKey(tenantId, keyOrId);
|
|
3947
4232
|
let configKey = keyOrId;
|
|
@@ -3985,10 +4270,10 @@ async function deleteMcpServerConfig(request, reply) {
|
|
|
3985
4270
|
}
|
|
3986
4271
|
}
|
|
3987
4272
|
async function testMcpServerConnection(request, reply) {
|
|
3988
|
-
const tenantId =
|
|
4273
|
+
const tenantId = getTenantId8(request);
|
|
3989
4274
|
const { key } = request.params;
|
|
3990
4275
|
try {
|
|
3991
|
-
const storeLattice =
|
|
4276
|
+
const storeLattice = getStoreLattice8("default", "mcp");
|
|
3992
4277
|
const store = storeLattice.store;
|
|
3993
4278
|
const config = await store.getConfigByKey(tenantId, key);
|
|
3994
4279
|
if (!config) {
|
|
@@ -4038,10 +4323,10 @@ async function testMcpServerConnection(request, reply) {
|
|
|
4038
4323
|
}
|
|
4039
4324
|
}
|
|
4040
4325
|
async function listMcpServerTools(request, reply) {
|
|
4041
|
-
const tenantId =
|
|
4326
|
+
const tenantId = getTenantId8(request);
|
|
4042
4327
|
const { key } = request.params;
|
|
4043
4328
|
try {
|
|
4044
|
-
const storeLattice =
|
|
4329
|
+
const storeLattice = getStoreLattice8("default", "mcp");
|
|
4045
4330
|
const store = storeLattice.store;
|
|
4046
4331
|
const config = await store.getConfigByKey(tenantId, key);
|
|
4047
4332
|
if (!config) {
|
|
@@ -4071,10 +4356,10 @@ async function listMcpServerTools(request, reply) {
|
|
|
4071
4356
|
}
|
|
4072
4357
|
}
|
|
4073
4358
|
async function connectMcpServer(request, reply) {
|
|
4074
|
-
const tenantId =
|
|
4359
|
+
const tenantId = getTenantId8(request);
|
|
4075
4360
|
const { key } = request.params;
|
|
4076
4361
|
try {
|
|
4077
|
-
const storeLattice =
|
|
4362
|
+
const storeLattice = getStoreLattice8("default", "mcp");
|
|
4078
4363
|
const store = storeLattice.store;
|
|
4079
4364
|
const config = await store.getConfigByKey(tenantId, key);
|
|
4080
4365
|
if (!config) {
|
|
@@ -4095,7 +4380,7 @@ async function connectMcpServer(request, reply) {
|
|
|
4095
4380
|
};
|
|
4096
4381
|
} catch (error) {
|
|
4097
4382
|
console.error("Failed to connect MCP server:", error);
|
|
4098
|
-
const storeLattice =
|
|
4383
|
+
const storeLattice = getStoreLattice8("default", "mcp");
|
|
4099
4384
|
const store = storeLattice.store;
|
|
4100
4385
|
const config = await store.getConfigByKey(tenantId, key);
|
|
4101
4386
|
if (config) {
|
|
@@ -4108,10 +4393,10 @@ async function connectMcpServer(request, reply) {
|
|
|
4108
4393
|
}
|
|
4109
4394
|
}
|
|
4110
4395
|
async function disconnectMcpServer(request, reply) {
|
|
4111
|
-
const tenantId =
|
|
4396
|
+
const tenantId = getTenantId8(request);
|
|
4112
4397
|
const { key } = request.params;
|
|
4113
4398
|
try {
|
|
4114
|
-
const storeLattice =
|
|
4399
|
+
const storeLattice = getStoreLattice8("default", "mcp");
|
|
4115
4400
|
const store = storeLattice.store;
|
|
4116
4401
|
const config = await store.getConfigByKey(tenantId, key);
|
|
4117
4402
|
if (!config) {
|
|
@@ -4216,11 +4501,11 @@ function registerMcpServerConfigRoutes(app2) {
|
|
|
4216
4501
|
}
|
|
4217
4502
|
|
|
4218
4503
|
// src/controllers/users.ts
|
|
4219
|
-
import { getStoreLattice as
|
|
4504
|
+
import { getStoreLattice as getStoreLattice9 } from "@axiom-lattice/core";
|
|
4220
4505
|
import { v4 as uuidv42 } from "uuid";
|
|
4221
4506
|
var UsersController = class {
|
|
4222
4507
|
constructor() {
|
|
4223
|
-
this.userStore =
|
|
4508
|
+
this.userStore = getStoreLattice9("default", "user").store;
|
|
4224
4509
|
}
|
|
4225
4510
|
async listUsers(request, reply) {
|
|
4226
4511
|
const { email } = request.query;
|
|
@@ -4298,11 +4583,11 @@ function registerUserRoutes(app2) {
|
|
|
4298
4583
|
}
|
|
4299
4584
|
|
|
4300
4585
|
// src/controllers/tenants.ts
|
|
4301
|
-
import { getStoreLattice as
|
|
4586
|
+
import { getStoreLattice as getStoreLattice10 } from "@axiom-lattice/core";
|
|
4302
4587
|
import { v4 as uuidv43 } from "uuid";
|
|
4303
4588
|
var TenantsController = class {
|
|
4304
4589
|
constructor() {
|
|
4305
|
-
this.tenantStore =
|
|
4590
|
+
this.tenantStore = getStoreLattice10("default", "tenant").store;
|
|
4306
4591
|
}
|
|
4307
4592
|
// ==================== Tenant CRUD ====================
|
|
4308
4593
|
async listTenants(request, reply) {
|
|
@@ -4366,7 +4651,7 @@ function registerTenantRoutes(app2) {
|
|
|
4366
4651
|
}
|
|
4367
4652
|
|
|
4368
4653
|
// src/controllers/auth.ts
|
|
4369
|
-
import { getStoreLattice as
|
|
4654
|
+
import { getStoreLattice as getStoreLattice11 } from "@axiom-lattice/core";
|
|
4370
4655
|
import { v4 as uuidv44 } from "uuid";
|
|
4371
4656
|
var defaultAuthConfig = {
|
|
4372
4657
|
autoApproveUsers: true,
|
|
@@ -4375,9 +4660,9 @@ var defaultAuthConfig = {
|
|
|
4375
4660
|
};
|
|
4376
4661
|
var AuthController = class {
|
|
4377
4662
|
constructor(config = {}) {
|
|
4378
|
-
this.userStore =
|
|
4379
|
-
this.tenantStore =
|
|
4380
|
-
this.userTenantLinkStore =
|
|
4663
|
+
this.userStore = getStoreLattice11("default", "user").store;
|
|
4664
|
+
this.tenantStore = getStoreLattice11("default", "tenant").store;
|
|
4665
|
+
this.userTenantLinkStore = getStoreLattice11("default", "userTenantLink").store;
|
|
4381
4666
|
this.config = { ...defaultAuthConfig, ...config };
|
|
4382
4667
|
}
|
|
4383
4668
|
async register(request, reply) {
|
|
@@ -4814,6 +5099,11 @@ var registerLatticeRoutes = (app2) => {
|
|
|
4814
5099
|
registerWorkspaceRoutes(app2);
|
|
4815
5100
|
registerDatabaseConfigRoutes(app2);
|
|
4816
5101
|
registerMetricsServerConfigRoutes(app2);
|
|
5102
|
+
app2.post(
|
|
5103
|
+
"/api/data/query",
|
|
5104
|
+
{ schema: dataQuerySchema },
|
|
5105
|
+
executeDataQuery
|
|
5106
|
+
);
|
|
4817
5107
|
registerMcpServerConfigRoutes(app2);
|
|
4818
5108
|
registerUserRoutes(app2);
|
|
4819
5109
|
registerTenantRoutes(app2);
|
|
@@ -4915,7 +5205,9 @@ var handleAgentTask = async (taskRequest, retryCount = 0) => {
|
|
|
4915
5205
|
}),
|
|
4916
5206
|
headers: {
|
|
4917
5207
|
"Content-Type": "application/json",
|
|
4918
|
-
"x-tenant-id": tenant_id
|
|
5208
|
+
"x-tenant-id": tenant_id,
|
|
5209
|
+
"x-workspace-id": runConfig?.workspaceId,
|
|
5210
|
+
"x-project-id": runConfig?.projectId
|
|
4919
5211
|
}
|
|
4920
5212
|
}).catch((err) => {
|
|
4921
5213
|
console.error(`fetch\u8BF7\u6C42\u5931\u8D25: ${err.message || String(err)}`);
|
|
@@ -5248,6 +5540,10 @@ app.register(multipart, {
|
|
|
5248
5540
|
}
|
|
5249
5541
|
});
|
|
5250
5542
|
app.register(websocket);
|
|
5543
|
+
app.register(staticPlugin, {
|
|
5544
|
+
root: path2.join(__dirname, "../public"),
|
|
5545
|
+
prefix: "/"
|
|
5546
|
+
});
|
|
5251
5547
|
app.setErrorHandler((error, request, reply) => {
|
|
5252
5548
|
const getHeaderValue = (header) => {
|
|
5253
5549
|
if (Array.isArray(header)) {
|
|
@@ -5286,6 +5582,7 @@ var start = async (config) => {
|
|
|
5286
5582
|
logger = loggerLattice.client;
|
|
5287
5583
|
}
|
|
5288
5584
|
app.decorate("loggerLattice", loggerLattice);
|
|
5585
|
+
registerLatticeRoutes(app);
|
|
5289
5586
|
if (!sandboxLatticeManager2.hasLattice("default")) {
|
|
5290
5587
|
const sandboxBaseURL = process.env.SANDBOX_BASE_URL || "http://localhost:8080";
|
|
5291
5588
|
sandboxLatticeManager2.registerLattice("default", {
|