import assert from "node:assert/strict";
import { existsSync, mkdtempSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { DatabaseSync } from "node:sqlite";
import { createServer as createHttpServer } from "node:http";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
import { z } from "zod";
import { createServer as createApiServer } from "../apps/api/dist/server.js";
import { resolveRunConfig } from "../apps/api/dist/run-config-resolver.js";
import { resolveEffectiveRunConfig } from "../apps/api/dist/run-input.js";
import { createTaskStateRuntime } from "../packages/agent-runtime/dist/index.js";
import { LocalDataGateway } from "../packages/data-gateway/dist/index.js";
import { RunEventWriter, createMetadataStore } from "../packages/metadata/dist/index.js";
import { createAuthenticatedTestClient } from "./lib/authenticated-test-client.mjs";
const root = mkdtempSync(join(tmpdir(), "open-data-foundry-config-smoke-"));
const datasourcePath = join(root, "source.sqlite");
const source = new DatabaseSync(datasourcePath);
source.exec(`
CREATE TABLE metrics (name TEXT, value INTEGER, secret TEXT);
INSERT INTO metrics VALUES ('revenue', 42, 'top-secret'), ('cost', 12, 'hidden-cost');
CREATE TABLE private_metrics (name TEXT, value INTEGER);
INSERT INTO private_metrics VALUES ('internal', 999);
`);
source.close();
process.env.AUTH_SESSION_SECRET = "config-smoke-session-secret-32bytes!!";
process.env.AUTH_PUBLIC_BASE_URL = "http://127.0.0.1:3000";
process.env.AUTH_EMAIL_DELIVERY = "test";
process.env.AUTH_REGISTRATION_MODE = "open";
process.env.EMBEDDING_API_KEY = "";
process.env.MASTRA_STORAGE_PATH = join(root, "mastra.sqlite");
process.env.STORAGE_ROOT_DIR = root;
const metadataStore = createMetadataStore({
database_path: join(root, "metadata.sqlite"),
secret_master_key: "config-smoke-master-key"
});
const taskStateRuntime = await createTaskStateRuntime(join(root, "task-state.sqlite"));
let modelProbeRequest;
const modelProviderServer = createHttpServer(async (request, response) => {
const chunks = [];
for await (const chunk of request) {
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
}
const body = chunks.length > 0 ? JSON.parse(Buffer.concat(chunks).toString("utf8")) : {};
modelProbeRequest = {
authorization: request.headers.authorization,
body,
method: request.method,
path: request.url
};
response.writeHead(200, { "Connection": "close", "Content-Type": "application/json" });
response.end(JSON.stringify({
id: "chatcmpl-config-smoke",
object: "chat.completion",
created: Math.floor(Date.now() / 1000),
model: body.model,
choices: [{
index: 0,
message: { role: "assistant", content: "OK" },
finish_reason: "stop"
}],
usage: { prompt_tokens: 8, completion_tokens: 1, total_tokens: 9 }
}));
});
await new Promise((resolve) => modelProviderServer.listen(0, "127.0.0.1", resolve));
const modelProviderAddress = modelProviderServer.address();
assert(modelProviderAddress && typeof modelProviderAddress === "object");
process.env.LLM_PROVIDER = "openai-compatible";
process.env.LLM_MODEL = "smoke-model";
process.env.LLM_BASE_URL = `http://127.0.0.1:${modelProviderAddress.port}`;
process.env.LLM_API_KEY = "smoke-model-key";
const mcpServer = createHttpServer(async (request, response) => {
const server = new McpServer({ name: "config-smoke-mcp", version: "1.0.0" });
server.registerTool("echo", {
description: "Echo one value.",
inputSchema: { value: z.string() }
}, async ({ value }) => ({ content: [{ type: "text", text: value }] }));
server.registerTool("hidden", {
description: "Hidden tool.",
inputSchema: { value: z.string() }
}, async ({ value }) => ({ content: [{ type: "text", text: value }] }));
const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined });
await server.connect(transport);
await transport.handleRequest(request, response);
response.on("close", () => {
void transport.close();
void server.close();
});
});
await new Promise((resolve) => mcpServer.listen(0, "127.0.0.1", resolve));
const mcpAddress = mcpServer.address();
assert(mcpAddress && typeof mcpAddress === "object");
const datalinkApiRequests = [];
const datalinkApiServer = createHttpServer(async (request, response) => {
const chunks = [];
for await (const chunk of request) {
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
}
const text = Buffer.concat(chunks).toString("utf8");
const body = text ? JSON.parse(text) : undefined;
datalinkApiRequests.push({ method: request.method, path: request.url, body });
const responseBody = request.method === "GET" && request.url === "/show"
? {
nodes: [{ id: "table:metrics", name: "metrics", properties: {}, type: "table" }],
edges: [],
}
: request.method === "POST" && request.url === "/explore"
? "metrics table"
: request.method === "POST" && request.url === "/add-table"
? { added_tables: ["metrics"] }
: request.method === "POST" && request.url === "/remove-table"
? { removed_table: "metrics" }
: request.method === "POST" && request.url === "/rebuild"
? { rebuilt: true }
: undefined;
const isTextResponse = typeof responseBody === "string";
response.writeHead(responseBody ? 200 : 404, {
"Content-Type": isTextResponse ? "text/plain; charset=utf-8" : "application/json",
});
response.end(isTextResponse ? responseBody : JSON.stringify(responseBody ?? { detail: "not found" }));
});
await new Promise((resolve) => datalinkApiServer.listen(0, "127.0.0.1", resolve));
const datalinkApiAddress = datalinkApiServer.address();
assert(datalinkApiAddress && typeof datalinkApiAddress === "object");
const server = await createApiServer({ metadataStore, taskStateRuntime });
await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));
const address = server.address();
assert(address && typeof address === "object");
const baseUrl = `http://127.0.0.1:${address.port}`;
const client = createAuthenticatedTestClient({ baseUrl });
const identity = await client.registerAndLogin({ displayName: "Config Smoke User" });
const { userId, workspaceId } = identity;
const tenantClient = createAuthenticatedTestClient({ baseUrl });
const tenantIdentity = await tenantClient.registerAndLogin({ displayName: "Tenant User" });
const requestJson = async (path, init = {}, authClient = client) => {
const response = await authClient.fetch(path, init);
const body = await response.json();
return { body, response };
};
const requestRaw = async (path, init = {}, authClient = client) => authClient.fetch(path, init);
const closeHttpServer = async (httpServer) => {
await new Promise((resolve, reject) => {
httpServer.close((error) => error ? reject(error) : resolve());
setImmediate(() => httpServer.closeAllConnections?.());
});
httpServer.unref?.();
};
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
try {
const capabilities = await requestJson("/api/v1/capabilities");
assert.equal(capabilities.body.data["chat.fileUpload"], true);
assert.equal(capabilities.body.data["chat.imageInput"], true);
assert.equal(capabilities.body.data["datasource.fieldMasking"], true);
assert.equal(capabilities.body.data["datasource.extendedTypes"], true);
assert.equal(capabilities.body.data["datasource.introspectionPolicy"], true);
assert.equal(capabilities.body.data["datasource.samplePolicy"], true);
assert.equal(capabilities.body.data["kb.chunking"], true);
assert.equal(capabilities.body.data["kb.citationPolicy"], true);
assert.equal(capabilities.body.data["kb.scope"], true);
assert.equal(capabilities.body.data["llm.advancedSampling"], true);
assert.equal(capabilities.body.data["mcp.stdio"], true);
assert.equal(capabilities.body.data["mcp.toolPolicy"], true);
assert.equal(capabilities.body.data["skill.resourceBinding"], true);
const datasourceTypes = await requestJson("/api/v1/datasource-types");
assert.equal(datasourceTypes.response.status, 200);
for (const typeName of [
"sqlite",
"postgresql",
"clickhouse",
"duckdb",
"snowflake",
"bigquery",
"sqlserver",
"oracle",
"mongodb",
"gaussdb",
"access",
"redis",
"starrocks",
"trino",
"presto",
"spark",
"databricks",
"redshift",
"elasticsearch",
"opensearch",
"doris",
"mariadb",
"tidb",
"oceanbase",
"greenplum"
]) {
assert(
datasourceTypes.body.data.some((type) => type.name === typeName && type.enabled === true),
`datasource-types should expose enabled ${typeName}`
);
}
const anonymousClient = createAuthenticatedTestClient({ baseUrl });
const unauthenticated = await requestJson("/api/v1/workspace-config", {}, anonymousClient);
assert.equal(unauthenticated.response.status, 401);
assert.equal(unauthenticated.body.error.code, "UNAUTHORIZED");
const defaultMe = await requestJson("/api/v1/me");
assert.equal(defaultMe.response.status, 200);
assert.equal(defaultMe.body.data.user.id, userId);
assert.equal(defaultMe.body.data.workspace.id, workspaceId);
const analystClient = createAuthenticatedTestClient({ baseUrl });
const analystIdentity = await analystClient.registerAndLogin({
email: `analyst-${Date.now()}@example.test`,
displayName: "Analyst User"
});
const analystMe = await requestJson("/api/v1/me", {}, analystClient);
assert.equal(analystMe.response.status, 200);
assert.equal(analystMe.body.data.user.id, analystIdentity.userId);
assert.equal(analystMe.body.data.workspace.id, analystIdentity.workspaceId);
assert.notEqual(analystIdentity.userId, userId);
const tenantDatasource = await requestJson("/api/v1/datasources", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
id: "local-sqlite",
name: "Tenant SQLite",
type: "sqlite",
settings: { filePath: datasourcePath }
})
}, tenantClient);
assert.equal(tenantDatasource.response.status, 201, JSON.stringify(tenantDatasource.body));
const devDatasourceListBeforeTenant = await requestJson("/api/v1/datasources");
assert.equal(devDatasourceListBeforeTenant.body.data.some((item) => item.id === "local-sqlite"), false);
const tenantKnowledge = await requestJson("/api/v1/knowledge-bases", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
id: "tenant-docs",
name: "Tenant Docs",
defaultEnabled: true,
retrievalTopK: 2
})
}, tenantClient);
assert.equal(tenantKnowledge.response.status, 201);
const devTenantKnowledge = await requestJson("/api/v1/knowledge-bases/tenant-docs");
assert.equal(devTenantKnowledge.response.status, 404);
const tenantVisibleKnowledge = await requestJson("/api/v1/knowledge-bases/tenant-docs", {}, tenantClient);
assert.equal(tenantVisibleKnowledge.response.status, 200);
const uploadForm = new FormData();
uploadForm.append("sessionId", "session-smoke-upload");
uploadForm.append("file", new Blob(["name,value\nrevenue,42\n"], { type: "text/csv" }), "metrics.csv");
const chatUpload = await requestJson("/api/v1/chat/uploads", {
method: "POST",
body: uploadForm
});
assert.equal(chatUpload.response.status, 200);
assert.equal(chatUpload.body.path, "uploads/metrics.csv");
assert.equal(chatUpload.body.mimeType, "text/csv");
assert.equal(chatUpload.body.size > 0, true);
const datasourceUploadForm = new FormData();
datasourceUploadForm.append(
"file",
new Blob(["name,value\nrevenue,42\n"], { type: "text/csv" }),
"sales-metrics.csv"
);
const datasourceUpload = await requestJson("/api/v1/datasources/uploads", {
method: "POST",
body: datasourceUploadForm
});
assert.equal(datasourceUpload.response.status, 200);
assert.equal(typeof datasourceUpload.body.path, "string");
assert.match(datasourceUpload.body.path, /datasources[/\\]sales-metrics\.csv$/);
assert.equal(datasourceUpload.body.originalName, "sales-metrics.csv");
assert.equal(datasourceUpload.body.mimeType, "text/csv");
assert.equal(datasourceUpload.body.size > 0, true);
assert.equal(existsSync(datasourceUpload.body.path), true);
const rejectedDatasourceUploadForm = new FormData();
rejectedDatasourceUploadForm.append(
"file",
new Blob(["not-a-datasource"], { type: "application/pdf" }),
"notes.pdf"
);
const rejectedDatasourceUpload = await requestJson("/api/v1/datasources/uploads", {
method: "POST",
body: rejectedDatasourceUploadForm
});
assert.equal(rejectedDatasourceUpload.response.status, 415);
const conversationSessionId = "conversation-api-session";
const conversationRunId = "conversation-api-run";
metadataStore.sessions.create({ user_id: userId, id: conversationSessionId, title: "conversation API" });
metadataStore.runs.create({
user_id: userId,
id: conversationRunId,
session_id: conversationSessionId,
request_fingerprint: "conversation-api-fingerprint",
user_input: "inspect orders",
status: "completed"
});
metadataStore.conversationMessages.append({
user_id: userId,
session_id: conversationSessionId,
run_id: conversationRunId,
id: `${conversationRunId}:user`,
role: "user",
source: "client",
message_id: "frontend-user-message",
content_text: "inspect orders",
content: { text: "inspect orders" }
});
metadataStore.conversationMessages.append({
user_id: userId,
session_id: conversationSessionId,
run_id: conversationRunId,
id: `${conversationRunId}:assistant`,
role: "assistant",
source: "agent",
message_id: "assistant-message",
content_text: "orders has 2 columns",
content: { text: "orders has 2 columns" }
});
metadataStore.conversationSummaries.create({
user_id: userId,
session_id: conversationSessionId,
id: `summary:${conversationSessionId}:1-1`,
source_run_id: conversationRunId,
from_position: 1,
to_position: 1,
summary_text: "User asked to inspect orders."
});
const conversationWriter = new RunEventWriter(metadataStore.runEvents);
conversationWriter.write({
user_id: userId,
run_id: conversationRunId,
session_id: conversationSessionId,
event: { type: "TOOL_CALL_START", toolCallId: "call_schema", toolCallName: "inspect_schema" }
});
conversationWriter.write({
user_id: userId,
run_id: conversationRunId,
session_id: conversationSessionId,
event: { type: "TOOL_CALL_END", toolCallId: "call_schema", toolCallName: "inspect_schema" }
});
conversationWriter.write({
user_id: userId,
run_id: conversationRunId,
session_id: conversationSessionId,
event: {
type: "TOOL_CALL_RESULT",
toolCallId: "call_schema",
toolCallName: "inspect_schema",
messageId: "tool-result-message",
content: JSON.stringify({ columns: 2 })
}
});
const conversation = await requestJson(`/api/v1/sessions/${conversationSessionId}/conversation?limit=10`);
assert.equal(conversation.response.status, 200);
assert.equal(conversation.body.data.sessionId, conversationSessionId);
assert.equal(conversation.body.data.messages.length, 2);
assert.equal(conversation.body.data.messages[0].messageId, "frontend-user-message");
assert.equal(conversation.body.data.summary.summaryText, "User asked to inspect orders.");
assert.equal(conversation.body.data.runEventRefs[0].eventCount, 3);
assert.deepEqual(
pick(conversation.body.data.checkpoints[0], [
"runId",
"status",
"messageStartPosition",
"messageEndPosition",
"firstEventSeq",
"lastEventSeq"
]),
{
runId: conversationRunId,
status: "completed",
messageStartPosition: 1,
messageEndPosition: 2,
firstEventSeq: 1,
lastEventSeq: 3
}
);
assert.deepEqual(
pick(conversation.body.data.toolCalls[0], [
"runId",
"toolCallId",
"status",
"toolName",
"callEventSeq",
"endEventSeq",
"resultEventSeq",
"resultMessageId",
"resultPreview"
]),
{
runId: conversationRunId,
toolCallId: "call_schema",
status: "completed",
toolName: "inspect_schema",
callEventSeq: 1,
endEventSeq: 2,
resultEventSeq: 3,
resultMessageId: "tool-result-message",
resultPreview: JSON.stringify({ columns: 2 })
}
);
const hitlOnlyRunId = "conversation-hitl-only-run";
metadataStore.runs.create({
user_id: userId,
id: hitlOnlyRunId,
session_id: conversationSessionId,
user_input: "ask the user",
status: "suspended"
});
metadataStore.interactions.request({
id: "interaction-hitl-only",
user_id: userId,
session_id: conversationSessionId,
run_id: hitlOnlyRunId,
tool_call_id: "call_ask_missing_start",
tool_name: "ask_user",
payload: { question: "Continue?" },
interrupt_event: {
type: "mastra_suspend",
toolCallId: "call_ask_missing_start",
toolName: "ask_user",
runId: hitlOnlyRunId,
args: { question: "Continue?" },
resumeSchema: {},
suspendPayload: { question: "Continue?" }
}
});
const hitlConversation = await requestJson(
`/api/v1/sessions/${conversationSessionId}/conversation?limit=20`
);
assert.equal(hitlConversation.response.status, 200);
const synthesizedHitl = hitlConversation.body.data.toolCalls.find(
(call) => call.toolCallId === "call_ask_missing_start"
);
assert.ok(synthesizedHitl, "Expected synthesized toolCall for pending interaction");
assert.equal(synthesizedHitl.toolName, "ask_user");
assert.equal(synthesizedHitl.status, "pending");
assert.equal(synthesizedHitl.awaitingInteraction, true);
const hitlCheckpoint = hitlConversation.body.data.checkpoints.find(
(checkpoint) => checkpoint.runId === hitlOnlyRunId
);
assert.ok(hitlCheckpoint, "Expected checkpoint for HITL-only run");
assert.equal(hitlCheckpoint.status, "suspended");
const branchBaseRunId = "conversation-branch-base-run";
const branchOriginalRunId = "conversation-branch-original-run";
const branchPendingRunId = "conversation-branch-pending-run";
metadataStore.runs.create({
user_id: userId,
id: branchBaseRunId,
session_id: conversationSessionId,
user_input: "summarize orders",
status: "completed"
});
metadataStore.conversationMessages.append({
user_id: userId,
session_id: conversationSessionId,
run_id: branchBaseRunId,
id: `${branchBaseRunId}:user`,
role: "user",
source: "client",
message_id: "branch-base-user-message",
content_text: "summarize orders",
content: { text: "summarize orders" }
});
metadataStore.conversationMessages.append({
user_id: userId,
session_id: conversationSessionId,
run_id: branchBaseRunId,
id: `${branchBaseRunId}:assistant`,
role: "assistant",
source: "agent",
message_id: "branch-base-assistant-message",
content_text: "orders summary",
content: { text: "orders summary" }
});
metadataStore.runs.create({
user_id: userId,
id: branchOriginalRunId,
session_id: conversationSessionId,
user_input: "make a chart",
status: "completed"
});
metadataStore.conversationMessages.append({
user_id: userId,
session_id: conversationSessionId,
run_id: branchOriginalRunId,
id: `${branchOriginalRunId}:user`,
role: "user",
source: "client",
message_id: "branch-original-user-message",
content_text: "make a chart",
content: { text: "make a chart" }
});
metadataStore.conversationMessages.append({
user_id: userId,
session_id: conversationSessionId,
run_id: branchOriginalRunId,
id: `${branchOriginalRunId}:assistant`,
role: "assistant",
source: "agent",
message_id: "branch-original-assistant-message",
content_text: "original chart answer",
content: { text: "original chart answer" }
});
metadataStore.runs.create({
user_id: userId,
id: branchPendingRunId,
session_id: conversationSessionId,
user_input: "still running",
status: "running"
});
const rejectedRunningBranch = await requestJson(`/api/v1/sessions/${conversationSessionId}/branches`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ runId: branchPendingRunId })
});
assert.equal(rejectedRunningBranch.response.status, 409);
assert.equal(rejectedRunningBranch.body.error.code, "RUN_NOT_BRANCHABLE");
const createdBranch = await requestJson(`/api/v1/sessions/${conversationSessionId}/branches`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ runId: branchOriginalRunId })
});
assert.equal(createdBranch.response.status, 201, JSON.stringify(createdBranch.body));
assert.equal(createdBranch.body.data.parentSessionId, conversationSessionId);
assert.equal(createdBranch.body.data.forkRunId, branchOriginalRunId);
assert.equal(createdBranch.body.data.forkMessageEndPosition, 4);
const branchSessionId = createdBranch.body.data.session.id;
const branchRunId = "conversation-branch-child-run";
metadataStore.runs.create({
user_id: userId,
id: branchRunId,
session_id: branchSessionId,
parent_run_id: branchOriginalRunId,
user_input: "make a table instead",
status: "completed"
});
metadataStore.conversationMessages.append({
user_id: userId,
session_id: branchSessionId,
run_id: branchRunId,
id: `${branchRunId}:user`,
role: "user",
source: "client",
message_id: "branch-child-user-message",
content_text: "make a table instead",
content: { text: "make a table instead" }
});
metadataStore.conversationMessages.append({
user_id: userId,
session_id: branchSessionId,
run_id: branchRunId,
id: `${branchRunId}:assistant`,
role: "assistant",
source: "agent",
message_id: "branch-child-assistant-message",
content_text: "branch table answer",
content: { text: "branch table answer" }
});
const branchConversation = await requestJson(`/api/v1/sessions/${branchSessionId}/conversation?limit=20`);
assert.equal(branchConversation.response.status, 200, JSON.stringify(branchConversation.body));
assert.deepEqual(
branchConversation.body.data.messages.map((message) => message.contentText),
[
"inspect orders",
"orders has 2 columns",
"summarize orders",
"orders summary",
"make a table instead",
"branch table answer"
]
);
assert.equal(
branchConversation.body.data.messages.some((message) => message.contentText === "original chart answer"),
false
);
assert.equal(branchConversation.body.data.branch.parentSessionId, conversationSessionId);
assert.equal(
branchConversation.body.data.branches.some((branch) =>
branch.forkRunId === branchOriginalRunId
&& branch.sessionId === branchSessionId
&& branch.parentSessionId === conversationSessionId
),
true
);
const createdDatasource = await requestJson("/api/v1/datasources", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
id: "local-sqlite",
name: "Local SQLite",
type: "sqlite",
settings: { filePath: datasourcePath, password: "must-not-leak" },
queryPolicy: { maxRows: 25, timeoutMs: 5000 }
})
});
assert.equal(createdDatasource.response.status, 201);
assert.equal(createdDatasource.body.data.hasSecret, true);
assert.equal(JSON.stringify(createdDatasource.body).includes("must-not-leak"), false);
assert.equal(createdDatasource.body.data.config.path, datasourcePath);
const datasource = await requestJson("/api/v1/datasources/local-sqlite");
assert.equal(JSON.stringify(datasource.body).includes("password"), false);
const datasourceRevision = datasource.body.data.revision;
const connection = await requestJson("/api/v1/datasources/local-sqlite/test", { method: "POST" });
assert.equal(connection.body.success, true);
const introspection = await requestJson("/api/v1/datasources/local-sqlite/introspect", {
method: "POST",
headers: { "Idempotency-Key": "schema-once" }
});
const repeatedIntrospection = await requestJson("/api/v1/datasources/local-sqlite/introspect", {
method: "POST",
headers: { "Idempotency-Key": "schema-once" }
});
assert.equal(introspection.body.data.id, repeatedIntrospection.body.data.id);
const schema = await requestJson("/api/v1/datasources/local-sqlite/schema");
assert(datasourceSchemaTables(schema.body.data).some((table) => table.name === "metrics"));
const refreshPatch = await requestJson("/api/v1/datasources/local-sqlite", {
method: "PATCH",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
revision: datasourceRevision,
introspection: { refreshIntervalSec: 1 }
})
});
assert.equal(refreshPatch.response.status, 200);
assert.equal(refreshPatch.body.data.config.introspection.refreshIntervalSec, 1);
const refreshSource = new DatabaseSync(datasourcePath);
refreshSource.exec("CREATE TABLE refreshed_metrics (name TEXT, value INTEGER);");
refreshSource.close();
await delay(1100);
const refreshedSchema = await requestJson("/api/v1/datasources/local-sqlite/schema");
const refreshedTableNames = datasourceSchemaTables(refreshedSchema.body.data).map((table) => table.name);
assert(
refreshedTableNames.includes("refreshed_metrics"),
`refreshIntervalSec should refresh expired datasource schema snapshots, got ${refreshedTableNames.join(",")}`
);
const conflict = await requestJson("/api/v1/datasources/local-sqlite", {
method: "PATCH",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ name: "Conflict", revision: datasourceRevision + 100 })
});
assert.equal(conflict.response.status, 409);
assert.equal(conflict.body.error.code, "REVISION_CONFLICT");
const policyPatch = await requestJson("/api/v1/datasources/local-sqlite", {
method: "PATCH",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
revision: refreshPatch.body.data.revision,
introspection: { tableAllowlist: ["metrics"] },
maskFields: ["secret"],
queryPolicy: { maxRows: 25, timeoutMs: 5000 },
samplePolicy: { allowSample: true, maxSampleRows: 1 }
})
});
assert.equal(policyPatch.response.status, 200);
assert.deepEqual(policyPatch.body.data.config.introspection.tableAllowlist, ["metrics"]);
assert.equal(policyPatch.body.data.config.introspection.refreshIntervalSec, 1);
assert.deepEqual(policyPatch.body.data.config.maskFields, ["secret"]);
assert.equal(policyPatch.body.data.config.samplePolicy.maxSampleRows, 1);
const policyGateway = new LocalDataGateway(metadataStore, {
defaultLimit: 100,
maxLimit: 1000,
timeoutMs: 10000,
workspaceId
});
const policySchema = await policyGateway.inspectSchema({
user_id: userId,
workspace_id: workspaceId,
datasource_id: "local-sqlite"
});
assert.deepEqual(policySchema.tables.map((table) => table.name), ["metrics"]);
const preview = await policyGateway.previewTable({
user_id: userId,
workspace_id: workspaceId,
datasource_id: "local-sqlite",
table: "metrics",
limit: 10
});
assert.equal(preview.row_count, 1, "samplePolicy.maxSampleRows should cap preview rows");
assert.equal(preview.rows[0]?.[preview.columns.indexOf("secret")], "[MASKED]");
const maskedSql = await policyGateway.runSqlReadonly({
user_id: userId,
workspace_id: workspaceId,
datasource_id: "local-sqlite",
sql: "SELECT name, secret FROM metrics",
limit: 10
});
assert.equal(maskedSql.rows[0]?.[maskedSql.columns.indexOf("secret")], "[MASKED]");
await assert.rejects(
() => policyGateway.previewTable({
user_id: userId,
workspace_id: workspaceId,
datasource_id: "local-sqlite",
table: "private_metrics",
limit: 1
}),
/TABLE_NOT_ALLOWED:private_metrics/u
);
await assert.rejects(
() => policyGateway.runSqlReadonly({
user_id: userId,
workspace_id: workspaceId,
datasource_id: "local-sqlite",
sql: "SELECT * FROM private_metrics",
limit: 1
}),
/TABLE_NOT_ALLOWED:private_metrics/u
);
const sampleDisabledPatch = await requestJson("/api/v1/datasources/local-sqlite", {
method: "PATCH",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
revision: policyPatch.body.data.revision,
samplePolicy: { allowSample: false, maxSampleRows: 1 }
})
});
assert.equal(sampleDisabledPatch.response.status, 200);
await assert.rejects(
() => policyGateway.previewTable({
user_id: userId,
workspace_id: workspaceId,
datasource_id: "local-sqlite",
table: "metrics",
limit: 1
}),
/SAMPLE_BLOCKED:local-sqlite:metrics/u
);
const knowledgeBase = await requestJson("/api/v1/knowledge-bases", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
id: "metrics-docs",
name: "Metrics Docs",
chunkOverlap: 25,
chunkSize: 1200,
citationRequired: true,
retrievalTopK: 3,
scope: "workspace"
})
});
assert.equal(knowledgeBase.response.status, 201);
assert.equal(knowledgeBase.body.data.chunkSize, 1200);
assert.equal(knowledgeBase.body.data.chunkOverlap, 25);
assert.equal(knowledgeBase.body.data.citationRequired, true);
assert.equal(knowledgeBase.body.data.scope, "workspace");
const fileForm = new FormData();
fileForm.append("files", new Blob(["Revenue metric can be imported from file assets."], {
type: "text/markdown"
}), "file-metrics.md");
const fileUploadResponse = await requestRaw("/api/v1/files", {
method: "POST",
headers: { "X-Session-Id": "config-smoke-session" },
body: fileForm
});
assert.equal(fileUploadResponse.status, 201);
const fileUpload = await fileUploadResponse.json();
assert.equal(fileUpload.body?.success ?? fileUpload.success, true);
const uploadedFile = fileUpload.body?.data?.files?.[0] ?? fileUpload.data.files[0];
assert.equal(uploadedFile.filename, "file-metrics.md");
const fileDownload = await requestRaw(`/api/v1/files/${uploadedFile.id}/download`);
assert.equal(fileDownload.status, 200);
assert.equal(await fileDownload.text(), "Revenue metric can be imported from file assets.");
const fileImport = await requestJson("/api/v1/knowledge-bases/metrics-docs/files/import", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ fileIds: [uploadedFile.id] })
});
assert.equal(fileImport.response.status, 207);
assert.equal(fileImport.body.data.results[0].status, "ready");
const upload = await requestJson("/api/v1/knowledge-bases/metrics-docs/files", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ filename: "metrics.md", content: "Revenue metric is gross sales before refunds." })
});
assert.equal(upload.response.status, 201);
assert.equal(upload.body.data.status, "ready");
const invalidPdfForm = new FormData();
invalidPdfForm.append(
"file",
new Blob(["%PDF-1.4"], { type: "application/pdf" }),
"doc.pdf"
);
const invalidPdf = await requestJson("/api/v1/knowledge-bases/metrics-docs/files", {
method: "POST",
body: invalidPdfForm
});
assert.equal(invalidPdf.response.status, 422);
assert.match(
String(invalidPdf.body?.error?.message ?? ""),
/KNOWLEDGE_PDF_(EMPTY|PARSE_FAILED)/
);
const rejectedDocxForm = new FormData();
rejectedDocxForm.append(
"file",
new Blob(["PK"], {
type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
}),
"report.docx"
);
const rejectedDocx = await requestJson("/api/v1/knowledge-bases/metrics-docs/files", {
method: "POST",
body: rejectedDocxForm
});
assert.equal(rejectedDocx.response.status, 415);
assert.match(String(rejectedDocx.body?.error?.message ?? ""), /KNOWLEDGE_FILE_TYPE_UNSUPPORTED/);
const forgedMimeForm = new FormData();
forgedMimeForm.append(
"file",
new Blob(["spoofed"], { type: "text/plain" }),
"doc.pdf"
);
const forgedMime = await requestJson("/api/v1/knowledge-bases/metrics-docs/files", {
method: "POST",
body: forgedMimeForm
});
assert.equal(forgedMime.response.status, 422);
assert.match(
String(forgedMime.body?.error?.message ?? ""),
/KNOWLEDGE_PDF_(EMPTY|PARSE_FAILED)/
);
const rejectedJsonPdf = await requestJson("/api/v1/knowledge-bases/metrics-docs/files", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ filename: "doc.pdf", content: "not a pdf but must still be rejected" })
});
assert.equal(rejectedJsonPdf.response.status, 422);
assert.match(
String(rejectedJsonPdf.body?.error?.message ?? ""),
/KNOWLEDGE_PDF_(EMPTY|PARSE_FAILED)/
);
const workspaceSessionId = "config-smoke-workspace-promote";
metadataStore.sessions.create({
user_id: userId,
id: workspaceSessionId,
title: "config smoke workspace promote"
});
const workspaceUploadForm = new FormData();
workspaceUploadForm.append(
"files",
new Blob(["workspace-asset-body"], { type: "text/plain" }),
"workspace-asset.txt"
);
const workspaceUploadResponse = await requestRaw("/api/v1/files", {
method: "POST",
headers: { "X-Session-Id": workspaceSessionId },
body: workspaceUploadForm
});
assert.equal(workspaceUploadResponse.status, 201);
const workspaceUploadBody = await workspaceUploadResponse.json();
const workspaceUploaded =
workspaceUploadBody.body?.data?.files?.[0] ?? workspaceUploadBody.data.files[0];
assert.equal(workspaceUploaded.filename, "workspace-asset.txt");
const promotedWorkspace = await requestJson(`/api/v1/files/${workspaceUploaded.id}/promote`, {
method: "POST"
});
assert.equal(promotedWorkspace.response.status, 200);
assert.equal(promotedWorkspace.body.data.scope, "workspace");
assert.equal(promotedWorkspace.body.data.sessionId ?? null, null);
const workspaceList = await requestJson("/api/v1/files?scope=workspace&origin=uploaded,saved");
assert.equal(workspaceList.response.status, 200);
assert.equal(
workspaceList.body.data.files.some((file) => file.id === promotedWorkspace.body.data.id),
true
);
const search = await requestJson("/api/v1/knowledge-bases/metrics-docs/search", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ query: "revenue metric" })
});
assert.equal(search.body.data[0].filename, "metrics.md");
const mcpConfig = await requestJson("/api/v1/mcp-servers", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
id: "smoke-mcp",
name: "Smoke MCP",
transport: "streamable-http",
serverUrl: `http://127.0.0.1:${mcpAddress.port}`,
toolAllowlist: ["echo"],
timeoutMs: 5000
})
});
assert.equal(mcpConfig.response.status, 201);
assert.deepEqual(mcpConfig.body.data.toolAllowlist, ["echo"]);
assert.equal(mcpConfig.body.data.timeoutMs, 5000);
const mcpTest = await requestJson("/api/v1/mcp-servers/smoke-mcp/test", { method: "POST" });
assert.equal(mcpTest.body.data.toolCount, 1);
const mcpTools = await requestJson("/api/v1/mcp-servers/smoke-mcp/tools");
assert.equal(mcpTools.body.data.length, 1);
assert.equal(mcpTools.body.data[0].name, "echo");
const datalinkConfig = await requestJson("/api/v1/mcp-servers", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
id: "datalink",
name: "DataLink",
transport: "streamable-http",
serverUrl: `http://127.0.0.1:${mcpAddress.port}/mcp`,
apiUrl: `http://127.0.0.1:${datalinkApiAddress.port}`,
})
});
assert.equal(datalinkConfig.response.status, 201);
assert.equal(datalinkConfig.body.data.apiUrl, `http://127.0.0.1:${datalinkApiAddress.port}`);
const datalinkServers = await requestJson("/api/v1/datalink/servers");
assert.equal(datalinkServers.body.data.servers[0].apiUrl, `http://127.0.0.1:${datalinkApiAddress.port}`);
const datalinkGraph = await requestJson("/api/v1/datalink/datalink/graph");
assert.equal(datalinkGraph.body.data.graph.nodes[0].id, "table:metrics");
const datalinkExplore = await requestJson("/api/v1/datalink/datalink/explore", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ query: "metrics", focus: "schema" })
});
assert.equal(datalinkExplore.body.data.result, "metrics table");
await requestJson("/api/v1/datalink/datalink/tables", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ source: "/data/metrics.csv", sourceType: "csv" })
});
await requestJson("/api/v1/datalink/datalink/tables", {
method: "DELETE",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ tableId: "table:metrics" })
});
await requestJson("/api/v1/datalink/datalink/rebuild", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({})
});
assert.deepEqual(
datalinkApiRequests.map((entry) => [entry.method, entry.path]),
[
["GET", "/show"],
["POST", "/explore"],
["POST", "/add-table"],
["POST", "/remove-table"],
["POST", "/rebuild"],
],
);
const skillForm = new FormData();
skillForm.set("file", new Blob([
"---\n",
"name: Smoke Skill\n",
"description: Smoke skill package\n",
"version: 1.0.0\n",
"allowed-tools: [inspect_schema, echo]\n",
"---\n",
"Inspect schema first.\n"
], { type: "text/markdown" }), "SKILL.md");
skillForm.set("defaultDbIds", "local-sqlite");
skillForm.set("defaultKbIds", "metrics-docs");
skillForm.set("defaultMcpIds", "smoke-mcp");
skillForm.set("modelProfileId", "smoke-openai-compatible");
const skill = await requestJson("/api/v1/skills", { method: "POST", body: skillForm });
assert.equal(skill.response.status, 201);
assert.equal(skill.body.data.validationStatus, "valid");
assert.equal("packageContent" in skill.body.data, false);
assert.equal(typeof skill.body.data.packageFileRefId, "string");
assert.deepEqual(skill.body.data.allowedTools, ["inspect_schema", "echo"]);
assert.deepEqual(skill.body.data.defaultDbIds, ["local-sqlite"]);
assert.deepEqual(skill.body.data.defaultKbIds, ["metrics-docs"]);
assert.deepEqual(skill.body.data.defaultMcpIds, ["smoke-mcp"]);
assert.equal(skill.body.data.modelProfileId, "smoke-openai-compatible");
const workspaceFileAssets = await requestJson("/api/v1/files?scope=workspace&origin=uploaded,saved");
assert.equal(workspaceFileAssets.response.status, 200);
assert.equal(
workspaceFileAssets.body.data.files.some((file) => file.id === skill.body.data.packageFileRefId),
false
);
const skillDownload = await requestRaw(`/api/v1/skills/${skill.body.data.id}/download`);
assert.equal(skillDownload.status, 200);
assert.equal((await skillDownload.text()).includes("Inspect schema first."), true);
const skillSelection = await requestJson("/api/v1/skills/select", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
user_input: "use smoke skill to inspect schema",
run_config: {
activeDatasourceId: "local-sqlite",
enabledDatasourceIds: ["local-sqlite"],
skill_mode: "auto"
}
})
});
assert.equal(skillSelection.response.status, 200);
assert.equal(skillSelection.body.data.skills.some((item) => item.id === skill.body.data.id), true);
assert.equal(skillSelection.body.data.effectivePolicy.allowedTools.includes("inspect_schema"), true);
const modelProfile = await requestJson("/api/v1/model-profiles", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
id: "smoke-openai-compatible",
name: "Smoke OpenAI Compatible",
provider: "openai-compatible",
modelName: "smoke-model",
baseUrl: `http://127.0.0.1:${modelProviderAddress.port}`,
credentials: { apiKey: "smoke-model-key" },
topP: 0.75,
frequencyPenalty: 0.25,
presencePenalty: -0.25,
contextLength: 64000,
reasoningModel: true,
timeoutMs: 5000
})
});
assert.equal(modelProfile.response.status, 201);
assert.equal(modelProfile.body.data.hasSecret, true);
assert.equal(modelProfile.body.data.contextLength, 64000);
assert.equal(modelProfile.body.data.reasoningModel, true);
assert.equal(JSON.stringify(modelProfile.body).includes("smoke-model-key"), false);
assert.equal(modelProfile.body.data.connectionStatus, "untested");
const serverDefaultProfile = await requestJson("/api/v1/model-profiles/server-default");
assert.equal(serverDefaultProfile.body.data.connectionStatus, "untested");
const modelProfileTest = await requestJson("/api/v1/model-profiles/smoke-openai-compatible/test", {
method: "POST"
});
assert.equal(modelProfileTest.body.success, true);
assert.equal(modelProfileTest.body.data.status, "connected");
assert.equal(modelProfileTest.body.data.model, "smoke-model");
assert.equal(modelProfileTest.body.data.response, "OK");
assert.match(
modelProfileTest.body.data.reason,
/Model "smoke-model" responded successfully \(OK\)\./
);
assert.equal(modelProbeRequest.method, "POST");
assert.equal(modelProbeRequest.path, "/chat/completions");
assert.equal(modelProbeRequest.authorization, "Bearer smoke-model-key");
assert.equal(modelProbeRequest.body.model, "smoke-model");
assert.equal(modelProbeRequest.body.messages.some((message) => message.role === "system"), true);
const resolvedModelRun = resolveRunConfig({
defaultDatasourceId: "dtc-growth-demo",
metadataStore,
runInput: {
threadId: "model-profile-session",
runId: "model-profile-run",
parentRunId: undefined,
messages: [{ id: "user-message-model-profile", role: "user", content: "inspect metrics" }],
tools: [],
context: [],
state: {},
forwardedProps: {
run_config: {
activeDatasourceId: "local-sqlite",
activeLlmProfileId: "smoke-openai-compatible",
enabledDatasourceIds: ["local-sqlite"],
enabledKnowledgeIds: [],
enabledMcpServerIds: [],
enabledSkillIds: []
}
}
},
userId: userId,
userInput: "inspect metrics",
workspaceId
});
assert.equal(resolvedModelRun.modelSettings?.topP, 0.75);
assert.equal(resolvedModelRun.modelSettings?.frequencyPenalty, 0.25);
assert.equal(resolvedModelRun.modelSettings?.presencePenalty, -0.25);
assert.equal(resolvedModelRun.modelContextProfile?.contextWindow, 64000);
assert.equal(resolvedModelRun.modelContextProfile?.outputReserve, 4096);
assert.equal(resolvedModelRun.reasoningModel, true);
assert.equal(resolvedModelRun.runTimeoutMs, 5000);
const skillBoundRun = resolveRunConfig({
defaultDatasourceId: "dtc-growth-demo",
metadataStore,
runInput: {
threadId: "skill-bound-session",
runId: "skill-bound-run",
parentRunId: undefined,
messages: [{ id: "user-message-skill-bound", role: "user", content: "use smoke skill to inspect schema" }],
tools: [],
context: [],
state: {},
forwardedProps: {
run_config: {
enabledDatasourceIds: ["dtc-growth-demo"],
enabledKnowledgeIds: [],
enabledMcpServerIds: [],
enabledSkillIds: [skill.body.data.id],
skill_mode: "auto"
}
}
},
userId: userId,
userInput: "use smoke skill to inspect schema",
workspaceId
});
assert.equal(skillBoundRun.effectiveRunConfig.activeDatasourceId, "local-sqlite");
assert.equal(skillBoundRun.effectiveRunConfig.activeLlmProfileId, "smoke-openai-compatible");
assert(skillBoundRun.effectiveRunConfig.enabledDatasourceIds.includes("local-sqlite"));
assert(skillBoundRun.effectiveRunConfig.enabledKnowledgeIds.includes("metrics-docs"));
assert(skillBoundRun.effectiveRunConfig.enabledMcpServerIds.includes("smoke-mcp"));
assert.deepEqual(skillBoundRun.mcpRuntime.toolNames, ["echo"]);
assert.equal(skillBoundRun.mcpRuntime.servers[0]?.timeoutMs, 5000);
assert.deepEqual(skillBoundRun.mcpRuntime.servers[0]?.toolAllowlist, ["echo"]);
const currentMetricsDocsResource = metadataStore.configResources.get({
id: "metrics-docs",
workspace_id: workspaceId,
user_id: userId,
kind: "knowledge-base"
});
const currentMcpResource = metadataStore.configResources.get({
id: "smoke-mcp",
workspace_id: workspaceId,
user_id: userId,
kind: "mcp-server"
});
const currentModelProfileResource = metadataStore.configResources.get({
id: "smoke-openai-compatible",
workspace_id: workspaceId,
user_id: userId,
kind: "model-profile"
});
assert.equal(
skillBoundRun.effectiveRunConfig.resourceRevisions["datasource:local-sqlite"],
sampleDisabledPatch.body.data.revision
);
assert.equal(
skillBoundRun.effectiveRunConfig.resourceRevisions["knowledge-base:metrics-docs"],
currentMetricsDocsResource.revision
);
assert.equal(skillBoundRun.effectiveRunConfig.resourceRevisions["mcp-server:smoke-mcp"], currentMcpResource.revision);
assert.equal(
skillBoundRun.effectiveRunConfig.resourceRevisions["model-profile:smoke-openai-compatible"],
currentModelProfileResource.revision
);
const explicitResourceRun = resolveRunConfig({
defaultDatasourceId: "dtc-growth-demo",
metadataStore,
runInput: {
threadId: "skill-explicit-session",
runId: "skill-explicit-run",
parentRunId: undefined,
messages: [{ id: "user-message-skill-explicit", role: "user", content: "use smoke skill to inspect schema" }],
tools: [],
context: [],
state: {},
forwardedProps: {
run_config: {
activeDatasourceId: "dtc-growth-demo",
enabledDatasourceIds: ["dtc-growth-demo"],
enabledKnowledgeIds: [],
enabledMcpServerIds: [],
enabledSkillIds: [skill.body.data.id],
skill_mode: "auto"
}
}
},
userId: userId,
userInput: "use smoke skill to inspect schema",
workspaceId
});
assert.equal(explicitResourceRun.effectiveRunConfig.activeDatasourceId, "dtc-growth-demo");
assert(explicitResourceRun.effectiveRunConfig.enabledDatasourceIds.includes("local-sqlite"));
const testedModelProfile = await requestJson("/api/v1/model-profiles/smoke-openai-compatible");
assert.equal(testedModelProfile.body.data.connectionStatus, "connected");
assert.equal(testedModelProfile.body.data.revision, modelProfileTest.body.data.revision);
const patchedModelProfile = await requestJson("/api/v1/model-profiles/smoke-openai-compatible", {
method: "PATCH",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
modelName: "smoke-model-v2",
revision: testedModelProfile.body.data.revision
})
});
assert.equal(patchedModelProfile.response.status, 200);
assert.equal(patchedModelProfile.body.data.connectionStatus, "untested");
const badModelProfile = await requestJson("/api/v1/model-profiles", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
id: "smoke-bad-model",
name: "Smoke Bad Model",
provider: "openai-compatible",
modelName: "smoke-model",
baseUrl: "http://127.0.0.1:1",
credentials: { apiKey: "bad-key" }
})
});
assert.equal(badModelProfile.response.status, 201);
const badModelProfileTest = await requestJson("/api/v1/model-profiles/smoke-bad-model/test", {
method: "POST"
});
assert.equal(badModelProfileTest.body.success, false);
assert.equal(badModelProfileTest.body.error.code, "PROVIDER_TEST_FAILED");
assert.match(badModelProfileTest.body.error.message, /^PROVIDER_TEST_FAILED:/);
assert.equal(
badModelProfileTest.body.error.message.includes("REVISION_CONFLICT"),
false
);
const failedModelProfile = await requestJson("/api/v1/model-profiles/smoke-bad-model");
assert.equal(failedModelProfile.body.data.connectionStatus, "failed");
const effective = resolveEffectiveRunConfig({
threadId: "effective-session",
runId: "effective-run",
parentRunId: undefined,
messages: [{ id: "user-message", role: "user", content: "inspect metrics" }],
tools: [],
context: [{
description: "run_config",
value: {
activeDatasourceId: "local-sqlite",
activeLlmProfileId: "server-default",
enabledDatasourceIds: ["local-sqlite"],
enabledKnowledgeIds: [],
enabledMcpServerIds: [],
enabledSkillIds: []
}
}],
state: {},
forwardedProps: {}
}, metadataStore, userId, "dtc-growth-demo", workspaceId);
assert.equal(effective.activeSkillId, undefined);
assert.equal(effective.resourceRevisions["datasource:local-sqlite"], sampleDisabledPatch.body.data.revision);
assert.equal(effective.resourceRevisions["model-profile:server-default"] > 0, true);
const currentKnowledgeBase = await requestJson("/api/v1/knowledge-bases/metrics-docs");
const workspacePatch = await requestJson("/api/v1/workspace-config", {
method: "PATCH",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
knowledgeBases: [{
id: "metrics-docs",
defaultEnabled: false,
revision: currentKnowledgeBase.body.data.revision
}]
})
});
assert.equal(workspacePatch.body.data.knowledgeBases[0].defaultEnabled, false);
const defaults = await requestJson("/api/v1/run-defaults");
assert.equal(defaults.body.data.enabledKnowledgeIds.includes("metrics-docs"), false);
metadataStore.sessions.create({ user_id: userId, id: "session-smoke", title: "config smoke" });
metadataStore.runs.create({
user_id: userId,
id: "run-smoke",
session_id: "session-smoke",
request_fingerprint: "config-smoke",
user_input: "config smoke",
status: "completed"
});
metadataStore.contextPackageSnapshots.create({
user_id: userId,
session_id: "session-smoke",
run_id: "run-smoke",
package_id: "context-smoke",
revision: 0,
payload: {}
});
metadataStore.protocolStates.compareAndSetWithEvents({
user_id: userId,
run_id: "run-smoke",
segment_id: "segment-smoke",
expected_revision: -1,
state: {
protocolId: "general-task",
protocolVersion: "1",
runId: "run-smoke",
segmentId: "segment-smoke",
revision: 0,
phase: "work",
status: "completed",
contextPackageRef: { packageId: "context-smoke", revision: 0 },
actions: [],
completionRejections: 0,
domain: {}
}
}, [{
eventId: "protocol-event-smoke",
type: "protocol.run.completed",
runId: "run-smoke",
segmentId: "segment-smoke",
revision: 0
}]);
assert.equal(metadataStore.protocolStates.pendingEvents({
user_id: userId,
run_id: "run-smoke"
}).length, 1);
const artifact = metadataStore.artifacts.create({
id: "artifact-smoke",
user_id: userId,
session_id: "session-smoke",
run_id: "run-smoke",
type: "table",
name: "metrics",
preview_json: { columns: ["name", "value"], rows: [{ name: "revenue", value: 42 }] }
});
assert.equal(artifact.id, "artifact-smoke");
const download = await client.fetch("/api/v1/artifacts/artifact-smoke/download");
assert.equal(download.headers.get("content-type"), "text/csv; charset=utf-8");
assert.equal((await download.text()).includes("revenue,42"), true);
const deletedSession = await requestJson("/api/v1/sessions/session-smoke", { method: "DELETE" });
assert.equal(deletedSession.response.status, 200, JSON.stringify(deletedSession.body));
assert.deepEqual(deletedSession.body.data, {
sessionId: "session-smoke",
deleted: true,
deletedSessionIds: ["session-smoke"]
});
assert.equal(metadataStore.protocolStates.find({
user_id: userId,
run_id: "run-smoke",
segment_id: "segment-smoke"
}), undefined);
assert.deepEqual(metadataStore.protocolStates.pendingEvents({
user_id: userId,
run_id: "run-smoke"
}), []);
const builtinDelete = await requestJson("/api/v1/datasources/dtc-growth-demo", { method: "DELETE" });
assert.equal(builtinDelete.response.status, 200);
assert.equal(builtinDelete.body.data.deleted, true);
metadataStore.sqlAuditLogs.create({
user_id: userId,
id: "audit-before-delete",
datasource_id: "local-sqlite",
sql_text: "SELECT 1",
status: "succeeded"
});
const deletedDatasource = await requestJson("/api/v1/datasources/local-sqlite", { method: "DELETE" });
assert.equal(deletedDatasource.body.data.deleted, true);
const datasourceList = await requestJson("/api/v1/datasources");
assert.equal(datasourceList.body.data.some((item) => item.id === "local-sqlite"), false);
assert.throws(() => metadataStore.secrets.get({
ref: createdDatasource.body.data.secretRef,
workspace_id: workspaceId,
user_id: userId
}), /SECRET_NOT_FOUND/u);
console.log(
"Config API smoke OK: secrets, datasource/types/policies, chat upload, datasource upload, conversation, revision, "
+ "KB, MCP, model profile, skill binding, defaults, artifact, session delete, tombstone"
);
} finally {
await closeHttpServer(server);
await closeHttpServer(datalinkApiServer);
await closeHttpServer(mcpServer);
await closeHttpServer(modelProviderServer);
await taskStateRuntime.close();
}
function pick(value, keys) {
return Object.fromEntries(keys.map((key) => [key, value[key]]));
}
function datasourceSchemaTables(value) {
return value?.schema?.tables ?? value?.tables ?? [];
}
process.exit(0);