91e140d402
Memind CI / Test, build, and release guards (push) Failing after 8s
Give WeChat MP its own chat.general→page.generate LLM refinement layer with memindadm toggles, shadow mode, and canary openids so service account routing stays independent of the H5 chatIntentRouter. Co-authored-by: Cursor <cursoragent@cursor.com>
796 lines
26 KiB
JavaScript
796 lines
26 KiB
JavaScript
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import express from 'express';
|
|
import { once } from 'node:events';
|
|
import { createAdminApi } from './admin-routes.mjs';
|
|
|
|
async function startTestServer(router) {
|
|
const app = express();
|
|
app.use('/admin-api', router);
|
|
const server = app.listen(0, '127.0.0.1');
|
|
await once(server, 'listening');
|
|
const address = server.address();
|
|
return {
|
|
server,
|
|
baseUrl: `http://127.0.0.1:${address.port}`,
|
|
close: async () => {
|
|
server.close();
|
|
await once(server, 'close');
|
|
},
|
|
};
|
|
}
|
|
|
|
test('admin memory-v2 config routes expose config and runtime state', async () => {
|
|
const updates = [];
|
|
const router = createAdminApi({
|
|
jsonBody: express.json(),
|
|
getToken() {
|
|
return 'token-admin';
|
|
},
|
|
userAuth: {
|
|
async getMe(token) {
|
|
if (token !== 'token-admin') return null;
|
|
return { id: 'admin-1', role: 'admin' };
|
|
},
|
|
},
|
|
llmProviderService: null,
|
|
memoryV2ConfigService: {
|
|
async getAdminConfig() {
|
|
return { config: { chatIntentRouter: { enabled: true } }, updatedAt: 123 };
|
|
},
|
|
async updateAdminConfig(patch, { updatedBy }) {
|
|
updates.push({ patch, updatedBy });
|
|
return { config: patch, updatedAt: 456, updatedBy };
|
|
},
|
|
async getRuntimeState() {
|
|
return { source: 'admin-db', overrides: { MEMIND_CHAT_LLM_ROUTER_ENABLED: '1' } };
|
|
},
|
|
},
|
|
plazaPosts: null,
|
|
plazaOps: null,
|
|
wechatAdmin: null,
|
|
subscriptionService: null,
|
|
});
|
|
|
|
const server = await startTestServer(router);
|
|
try {
|
|
const configRes = await fetch(`${server.baseUrl}/admin-api/memory-v2/config`, {
|
|
headers: { cookie: 'h5_user_session=token-admin' },
|
|
});
|
|
assert.equal(configRes.status, 200);
|
|
assert.deepEqual(await configRes.json(), {
|
|
config: { chatIntentRouter: { enabled: true } },
|
|
updatedAt: 123,
|
|
});
|
|
|
|
const updateRes = await fetch(`${server.baseUrl}/admin-api/memory-v2/config`, {
|
|
method: 'PATCH',
|
|
headers: {
|
|
'content-type': 'application/json',
|
|
cookie: 'h5_user_session=token-admin',
|
|
},
|
|
body: JSON.stringify({ chatIntentRouter: { enabled: false } }),
|
|
});
|
|
assert.equal(updateRes.status, 200);
|
|
assert.deepEqual(updates, [{
|
|
patch: { chatIntentRouter: { enabled: false } },
|
|
updatedBy: 'admin-1',
|
|
}]);
|
|
|
|
const runtimeRes = await fetch(`${server.baseUrl}/admin-api/memory-v2/runtime`, {
|
|
headers: { cookie: 'h5_user_session=token-admin' },
|
|
});
|
|
assert.equal(runtimeRes.status, 200);
|
|
assert.deepEqual(await runtimeRes.json(), {
|
|
source: 'admin-db',
|
|
overrides: { MEMIND_CHAT_LLM_ROUTER_ENABLED: '1' },
|
|
});
|
|
} finally {
|
|
await server.close();
|
|
}
|
|
});
|
|
|
|
test('admin memory-v2 metrics and candidate review routes', async () => {
|
|
const router = createAdminApi({
|
|
jsonBody: express.json(),
|
|
getToken() {
|
|
return 'token-admin';
|
|
},
|
|
userAuth: {
|
|
async getMe(token) {
|
|
if (token !== 'token-admin') return null;
|
|
return { id: 'admin-1', role: 'admin' };
|
|
},
|
|
},
|
|
memoryV2AdminOpsService: {
|
|
async getProductMetrics() {
|
|
return {
|
|
window: { since: '7d', sinceMs: 1, untilMs: 2 },
|
|
userId: null,
|
|
events: {
|
|
memory_candidate_saved: 3,
|
|
memory_promoted: 2,
|
|
memory_resolved_injected: 1,
|
|
memory_recall_hit: 1,
|
|
},
|
|
sources: {},
|
|
};
|
|
},
|
|
async getShadowAudit() {
|
|
return {
|
|
falseStoreRate: 0,
|
|
autoAcceptRate: 0.1,
|
|
resolveHitRate: 0.5,
|
|
suspiciousCandidateCount: 0,
|
|
pgvectorLagUserCount: 0,
|
|
};
|
|
},
|
|
async countCandidatesByStatus() {
|
|
return { candidate: 4, accepted: 2 };
|
|
},
|
|
async listCandidates() {
|
|
return [{
|
|
id: 'cand-1',
|
|
userId: 'user-1',
|
|
sessionId: 'session-1',
|
|
memoryType: 'episodic',
|
|
content: '请记住我喜欢美式咖啡',
|
|
importance: 0.9,
|
|
confidence: 0.9,
|
|
status: 'candidate',
|
|
policyReason: 'explicit_memory_request',
|
|
createdAt: 1000,
|
|
updatedAt: 1000,
|
|
}];
|
|
},
|
|
async reviewCandidate(id, status, { reviewedBy }) {
|
|
assert.equal(id, 'cand-1');
|
|
assert.equal(status, 'accepted');
|
|
assert.equal(reviewedBy, 'admin-1');
|
|
return { updated: true, status, reviewedAt: 2000 };
|
|
},
|
|
},
|
|
llmProviderService: null,
|
|
memoryV2ConfigService: null,
|
|
plazaPosts: null,
|
|
plazaOps: null,
|
|
wechatAdmin: null,
|
|
subscriptionService: null,
|
|
});
|
|
|
|
const server = await startTestServer(router);
|
|
try {
|
|
const metricsRes = await fetch(`${server.baseUrl}/admin-api/memory-v2/metrics`, {
|
|
headers: { cookie: 'h5_user_session=token-admin' },
|
|
});
|
|
assert.equal(metricsRes.status, 200);
|
|
const metricsBody = await metricsRes.json();
|
|
assert.equal(metricsBody.metrics.events.memory_candidate_saved, 3);
|
|
assert.equal(metricsBody.candidateCounts.candidate, 4);
|
|
|
|
const listRes = await fetch(`${server.baseUrl}/admin-api/memory-v2/candidates`, {
|
|
headers: { cookie: 'h5_user_session=token-admin' },
|
|
});
|
|
assert.equal(listRes.status, 200);
|
|
const listBody = await listRes.json();
|
|
assert.equal(listBody.items.length, 1);
|
|
|
|
const reviewRes = await fetch(`${server.baseUrl}/admin-api/memory-v2/candidates/cand-1/review`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'content-type': 'application/json',
|
|
cookie: 'h5_user_session=token-admin',
|
|
},
|
|
body: JSON.stringify({ status: 'accepted' }),
|
|
});
|
|
assert.equal(reviewRes.status, 200);
|
|
assert.deepEqual(await reviewRes.json(), {
|
|
ok: true,
|
|
updated: true,
|
|
status: 'accepted',
|
|
reviewedAt: 2000,
|
|
});
|
|
} finally {
|
|
await server.close();
|
|
}
|
|
});
|
|
|
|
test('admin goal-runs routes expose summary, list, and detail', async () => {
|
|
const router = createAdminApi({
|
|
jsonBody: express.json(),
|
|
getToken() {
|
|
return 'token-admin';
|
|
},
|
|
userAuth: {
|
|
async getMe(token) {
|
|
if (token !== 'token-admin') return null;
|
|
return { id: 'admin-1', role: 'admin' };
|
|
},
|
|
},
|
|
goalRunAdminOpsService: {
|
|
getRuntime() {
|
|
return { enabled: true, canaryUserIds: ['user-1'], canaryMode: true };
|
|
},
|
|
async countByStatus() {
|
|
return { active: 2, completed: 1 };
|
|
},
|
|
async listGoals() {
|
|
return [{
|
|
id: 'goal-1',
|
|
userId: 'user-1',
|
|
username: 'john2',
|
|
title: '产品规划',
|
|
intentSummary: '分阶段完成',
|
|
status: 'active',
|
|
priority: 5,
|
|
sourceChannel: 'h5',
|
|
sourceSessionId: null,
|
|
currentCheckpointId: 'cp-1',
|
|
checkpointCount: 2,
|
|
activeAgentRunCount: 1,
|
|
createdAt: 1000,
|
|
updatedAt: 2000,
|
|
completedAt: null,
|
|
}];
|
|
},
|
|
async getGoalDetail(goalRunId) {
|
|
if (goalRunId !== 'goal-1') return null;
|
|
return {
|
|
id: 'goal-1',
|
|
userId: 'user-1',
|
|
username: 'john2',
|
|
title: '产品规划',
|
|
intentSummary: '分阶段完成',
|
|
status: 'active',
|
|
priority: 5,
|
|
sourceChannel: 'h5',
|
|
sourceSessionId: null,
|
|
sourceMessageId: null,
|
|
currentCheckpointId: 'cp-1',
|
|
context: null,
|
|
memorySnapshot: null,
|
|
createdAt: 1000,
|
|
updatedAt: 2000,
|
|
completedAt: null,
|
|
checkpoints: [{
|
|
id: 'cp-1',
|
|
goalRunId: 'goal-1',
|
|
sequence: 1,
|
|
title: '调研',
|
|
description: null,
|
|
status: 'running',
|
|
agentRunId: 'run-1',
|
|
outputSummary: null,
|
|
userFeedback: null,
|
|
approvedAt: null,
|
|
createdAt: 1000,
|
|
updatedAt: 2000,
|
|
startedAt: 1500,
|
|
completedAt: null,
|
|
}],
|
|
agentRuns: [{
|
|
id: 'run-1',
|
|
status: 'running',
|
|
requestId: 'req-1',
|
|
goalCheckpointId: 'cp-1',
|
|
createdAt: 1000,
|
|
updatedAt: 2000,
|
|
completedAt: null,
|
|
}],
|
|
canaryEnabled: true,
|
|
};
|
|
},
|
|
async approveCheckpoint({ goalRunId, checkpointId, feedback, reviewedBy }) {
|
|
assert.equal(goalRunId, 'goal-1');
|
|
assert.equal(checkpointId, 'cp-1');
|
|
assert.equal(feedback, 'looks good');
|
|
assert.equal(reviewedBy, 'admin-1');
|
|
return { id: 'goal-1', status: 'active', checkpoints: [] };
|
|
},
|
|
async cancelGoal({ goalRunId, reviewedBy }) {
|
|
assert.equal(goalRunId, 'goal-1');
|
|
assert.equal(reviewedBy, 'admin-1');
|
|
return { id: 'goal-1', status: 'cancelled', checkpoints: [] };
|
|
},
|
|
},
|
|
});
|
|
const server = await startTestServer(router);
|
|
try {
|
|
const summaryRes = await fetch(`${server.baseUrl}/admin-api/goal-runs/summary`, {
|
|
headers: { cookie: 'h5_user_session=token-admin' },
|
|
});
|
|
assert.equal(summaryRes.status, 200);
|
|
const summaryBody = await summaryRes.json();
|
|
assert.equal(summaryBody.counts.active, 2);
|
|
assert.equal(summaryBody.runtime.enabled, true);
|
|
|
|
const listRes = await fetch(`${server.baseUrl}/admin-api/goal-runs`, {
|
|
headers: { cookie: 'h5_user_session=token-admin' },
|
|
});
|
|
assert.equal(listRes.status, 200);
|
|
const listBody = await listRes.json();
|
|
assert.equal(listBody.items[0].id, 'goal-1');
|
|
|
|
const detailRes = await fetch(`${server.baseUrl}/admin-api/goal-runs/goal-1`, {
|
|
headers: { cookie: 'h5_user_session=token-admin' },
|
|
});
|
|
assert.equal(detailRes.status, 200);
|
|
const detailBody = await detailRes.json();
|
|
assert.equal(detailBody.goal.checkpoints.length, 1);
|
|
|
|
const approveRes = await fetch(`${server.baseUrl}/admin-api/goal-runs/goal-1/checkpoints/cp-1/approve`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'content-type': 'application/json',
|
|
cookie: 'h5_user_session=token-admin',
|
|
},
|
|
body: JSON.stringify({ feedback: 'looks good' }),
|
|
});
|
|
assert.equal(approveRes.status, 200);
|
|
|
|
const cancelRes = await fetch(`${server.baseUrl}/admin-api/goal-runs/goal-1/cancel`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'content-type': 'application/json',
|
|
cookie: 'h5_user_session=token-admin',
|
|
},
|
|
body: JSON.stringify({}),
|
|
});
|
|
assert.equal(cancelRes.status, 200);
|
|
} finally {
|
|
await server.close();
|
|
}
|
|
});
|
|
|
|
test('admin orchestrator routes expose a versioned plug-in control plane', async () => {
|
|
const updates = [];
|
|
const state = {
|
|
config: {
|
|
mode: 'off',
|
|
primaryEngine: 'langgraph',
|
|
fallbackEngine: 'native',
|
|
serviceUrl: '',
|
|
requestTimeoutMs: 5000,
|
|
rolloutPercent: 0,
|
|
userAllowlist: [],
|
|
workflowAllowlist: ['code-run-v1'],
|
|
fallbackToNative: true,
|
|
requireHealthy: true,
|
|
},
|
|
configVersion: 1,
|
|
runtime: { effective: false, reason: 'mode_off' },
|
|
engines: [{ id: 'native', configured: true }, { id: 'langgraph', configured: false }],
|
|
};
|
|
const router = createAdminApi({
|
|
jsonBody: express.json(),
|
|
getToken() {
|
|
return 'token-admin';
|
|
},
|
|
userAuth: {
|
|
async getMe() {
|
|
return { id: 'admin-1', role: 'admin' };
|
|
},
|
|
},
|
|
llmProviderService: null,
|
|
memoryV2ConfigService: null,
|
|
orchestratorConfigService: {
|
|
async getAdminConfig() {
|
|
return state;
|
|
},
|
|
async updateAdminConfig(config, context) {
|
|
updates.push({ config, context });
|
|
return { ...state, config: { ...state.config, ...config }, configVersion: 2 };
|
|
},
|
|
async getRuntimeState(options) {
|
|
assert.deepEqual(options, { probe: true });
|
|
return {
|
|
...state,
|
|
source: 'admin-db',
|
|
serviceHealth: { ok: true, status: 'healthy' },
|
|
};
|
|
},
|
|
},
|
|
orchestratorObservabilityService: {
|
|
async listExecutionPlans(options) {
|
|
assert.deepEqual(options, {
|
|
hours: '24',
|
|
limit: '50',
|
|
selection: 'candidate',
|
|
});
|
|
return {
|
|
metrics: { decisions: 3, candidateSelections: 2 },
|
|
plans: [{ runId: 'run-plan-1', candidateEngine: 'langgraph' }],
|
|
};
|
|
},
|
|
async getCanaryReadiness() {
|
|
return {
|
|
ready: false,
|
|
recommendation: 'keep_shadow',
|
|
blockers: ['sample_volume'],
|
|
samples: { eligibleObservations: 1 },
|
|
};
|
|
},
|
|
async listShadowRuns(options) {
|
|
assert.deepEqual(options, { hours: '12', limit: '25', status: 'failed' });
|
|
return {
|
|
metrics: { observations: 1, successes: 0, failures: 1 },
|
|
runs: [{ runId: 'run-shadow-1', shadowStatus: 'failed' }],
|
|
};
|
|
},
|
|
async getShadowRun(runId) {
|
|
assert.equal(runId, 'run-shadow-1');
|
|
return {
|
|
native: { runId, status: 'succeeded' },
|
|
remote: { available: true, events: [{ type: 'workflow_validated' }] },
|
|
};
|
|
},
|
|
},
|
|
plazaPosts: null,
|
|
plazaOps: null,
|
|
wechatAdmin: null,
|
|
subscriptionService: null,
|
|
});
|
|
|
|
const server = await startTestServer(router);
|
|
try {
|
|
const configResponse = await fetch(`${server.baseUrl}/admin-api/orchestrator/config`, {
|
|
headers: { cookie: 'h5_user_session=token-admin' },
|
|
});
|
|
assert.equal(configResponse.status, 200);
|
|
assert.equal((await configResponse.json()).config.mode, 'off');
|
|
|
|
const updateResponse = await fetch(`${server.baseUrl}/admin-api/orchestrator/config`, {
|
|
method: 'PATCH',
|
|
headers: {
|
|
'content-type': 'application/json',
|
|
cookie: 'h5_user_session=token-admin',
|
|
},
|
|
body: JSON.stringify({ config: { mode: 'shadow', serviceUrl: 'http://127.0.0.1:8093' } }),
|
|
});
|
|
assert.equal(updateResponse.status, 200);
|
|
assert.equal((await updateResponse.json()).configVersion, 2);
|
|
assert.deepEqual(updates, [{
|
|
config: { mode: 'shadow', serviceUrl: 'http://127.0.0.1:8093' },
|
|
context: { updatedBy: 'admin-1' },
|
|
}]);
|
|
|
|
const runtimeResponse = await fetch(`${server.baseUrl}/admin-api/orchestrator/runtime`, {
|
|
headers: { cookie: 'h5_user_session=token-admin' },
|
|
});
|
|
assert.equal(runtimeResponse.status, 200);
|
|
const runtimeBody = await runtimeResponse.json();
|
|
assert.equal(runtimeBody.source, 'admin-db');
|
|
assert.equal(runtimeBody.serviceHealth.status, 'healthy');
|
|
|
|
const shadowRunsResponse = await fetch(
|
|
`${server.baseUrl}/admin-api/orchestrator/shadow-runs?hours=12&limit=25&status=failed`,
|
|
{ headers: { cookie: 'h5_user_session=token-admin' } },
|
|
);
|
|
assert.equal(shadowRunsResponse.status, 200);
|
|
assert.equal((await shadowRunsResponse.json()).metrics.failures, 1);
|
|
|
|
const executionPlansResponse = await fetch(
|
|
`${server.baseUrl}/admin-api/orchestrator/execution-plans?hours=24&limit=50&selection=candidate`,
|
|
{ headers: { cookie: 'h5_user_session=token-admin' } },
|
|
);
|
|
assert.equal(executionPlansResponse.status, 200);
|
|
const executionPlansBody = await executionPlansResponse.json();
|
|
assert.equal(executionPlansBody.metrics.decisions, 3);
|
|
assert.equal(executionPlansBody.plans[0].candidateEngine, 'langgraph');
|
|
|
|
const readinessResponse = await fetch(
|
|
`${server.baseUrl}/admin-api/orchestrator/canary-readiness`,
|
|
{ headers: { cookie: 'h5_user_session=token-admin' } },
|
|
);
|
|
assert.equal(readinessResponse.status, 200);
|
|
const readinessBody = await readinessResponse.json();
|
|
assert.equal(readinessBody.ready, false);
|
|
assert.deepEqual(readinessBody.blockers, ['sample_volume']);
|
|
|
|
const shadowRunResponse = await fetch(
|
|
`${server.baseUrl}/admin-api/orchestrator/shadow-runs/run-shadow-1`,
|
|
{ headers: { cookie: 'h5_user_session=token-admin' } },
|
|
);
|
|
assert.equal(shadowRunResponse.status, 200);
|
|
assert.equal((await shadowRunResponse.json()).remote.available, true);
|
|
} finally {
|
|
await server.close();
|
|
}
|
|
});
|
|
|
|
test('admin system disclosure policy routes version config through the injected control-plane service', async () => {
|
|
const updates = [];
|
|
const config = {
|
|
enabled: true,
|
|
mode: 'shadow',
|
|
refusalText: '不提供内部技术信息。',
|
|
productNames: ['tkmind'],
|
|
selfReferences: ['本系统'],
|
|
categories: { architecture: true },
|
|
};
|
|
const router = createAdminApi({
|
|
jsonBody: express.json(),
|
|
getToken() {
|
|
return 'token-admin';
|
|
},
|
|
userAuth: {
|
|
async getMe() {
|
|
return { id: 'admin-1', role: 'admin' };
|
|
},
|
|
},
|
|
llmProviderService: null,
|
|
memoryV2ConfigService: null,
|
|
systemDisclosurePolicyService: {
|
|
async getAdminConfig() {
|
|
return { config, policyVersion: 2, source: 'admin-db' };
|
|
},
|
|
async updateAdminConfig(patch, context) {
|
|
updates.push({ patch, context });
|
|
return { config: patch, policyVersion: 3, source: 'admin-db' };
|
|
},
|
|
getRuntimeState() {
|
|
return { config, policyVersion: 2, source: 'admin-db', refreshedAt: 123 };
|
|
},
|
|
},
|
|
plazaPosts: null,
|
|
plazaOps: null,
|
|
wechatAdmin: null,
|
|
subscriptionService: null,
|
|
});
|
|
|
|
const server = await startTestServer(router);
|
|
try {
|
|
const getResponse = await fetch(`${server.baseUrl}/admin-api/system-disclosure-policy/config`, {
|
|
headers: { cookie: 'h5_user_session=token-admin' },
|
|
});
|
|
assert.equal(getResponse.status, 200);
|
|
assert.equal((await getResponse.json()).policyVersion, 2);
|
|
|
|
const updateResponse = await fetch(`${server.baseUrl}/admin-api/system-disclosure-policy/config`, {
|
|
method: 'PUT',
|
|
headers: {
|
|
'content-type': 'application/json',
|
|
cookie: 'h5_user_session=token-admin',
|
|
},
|
|
body: JSON.stringify({ config: { ...config, mode: 'enforce' } }),
|
|
});
|
|
assert.equal(updateResponse.status, 200);
|
|
assert.equal((await updateResponse.json()).policyVersion, 3);
|
|
assert.deepEqual(updates, [{
|
|
patch: { ...config, mode: 'enforce' },
|
|
context: { updatedBy: 'admin-1' },
|
|
}]);
|
|
|
|
const runtimeResponse = await fetch(`${server.baseUrl}/admin-api/system-disclosure-policy/runtime`, {
|
|
headers: { cookie: 'h5_user_session=token-admin' },
|
|
});
|
|
assert.equal(runtimeResponse.status, 200);
|
|
assert.equal((await runtimeResponse.json()).refreshedAt, 123);
|
|
} finally {
|
|
await server.close();
|
|
}
|
|
});
|
|
|
|
test('admin MindSearch routes persist only through injected control-plane service', async () => {
|
|
const updates = [];
|
|
const testedServices = [];
|
|
const router = createAdminApi({
|
|
jsonBody: express.json(), getToken() { return 'token-admin'; },
|
|
userAuth: { async getMe() { return { id: 'admin-1', role: 'admin' }; } },
|
|
llmProviderService: null, memoryV2ConfigService: null,
|
|
mindSearchConfigService: {
|
|
async getAdminConfig() { return { config: { enabled: false, mode: 'off', providers: { searxng: false, github: false, reader: false } }, source: 'env' }; },
|
|
async updateAdminConfig(patch, context) { updates.push({ patch, context }); return { config: { enabled: true, mode: 'shadow', providers: { searxng: true, github: false, reader: false } }, source: 'admin' }; },
|
|
async getRuntimeState() { return { effective: false, mode: 'off' }; },
|
|
async testService(serviceId) { testedServices.push(serviceId); return { ok: true, serviceId, latencyMs: 3 }; },
|
|
},
|
|
plazaPosts: null, plazaOps: null, wechatAdmin: null, subscriptionService: null,
|
|
});
|
|
const server = await startTestServer(router);
|
|
try {
|
|
const config = await fetch(`${server.baseUrl}/admin-api/mindsearch/config`, { headers: { cookie: 'h5_user_session=token-admin' } });
|
|
assert.equal(config.status, 200);
|
|
const update = await fetch(`${server.baseUrl}/admin-api/mindsearch/config`, { method: 'PATCH', headers: { 'content-type': 'application/json', cookie: 'h5_user_session=token-admin' }, body: JSON.stringify({ enabled: true, mode: 'shadow' }) });
|
|
assert.equal(update.status, 200);
|
|
assert.deepEqual(updates, [{ patch: { enabled: true, mode: 'shadow' }, context: { updatedBy: 'admin-1' } }]);
|
|
const runtime = await fetch(`${server.baseUrl}/admin-api/mindsearch/runtime`, { headers: { cookie: 'h5_user_session=token-admin' } });
|
|
assert.deepEqual(await runtime.json(), { effective: false, mode: 'off' });
|
|
const serviceTest = await fetch(`${server.baseUrl}/admin-api/mindsearch/services/searxng/test`, { method: 'POST', headers: { cookie: 'h5_user_session=token-admin' } });
|
|
assert.deepEqual(await serviceTest.json(), { ok: true, serviceId: 'searxng', latencyMs: 3 });
|
|
assert.deepEqual(testedServices, ['searxng']);
|
|
} finally { await server.close(); }
|
|
});
|
|
|
|
test('admin asset gateway routes preserve an explicit, admin-only control plane', async () => {
|
|
const calls = [];
|
|
const router = createAdminApi({
|
|
jsonBody: express.json(),
|
|
getToken() { return 'token-admin'; },
|
|
userAuth: { async getMe() { return { id: 'admin-1', role: 'admin' }; } },
|
|
llmProviderService: null,
|
|
memoryV2ConfigService: null,
|
|
assetGatewayConfigService: {
|
|
async getConfig() { return { enabled: false, plugins: [] }; },
|
|
async updateGlobalConfig(payload, context) { calls.push({ type: 'global', payload, context }); return { enabled: true }; },
|
|
async updatePluginConfig(pluginId, payload, context) {
|
|
calls.push({ type: 'plugin', pluginId, payload, context });
|
|
return { ok: true, config: { enabled: true, plugins: [] } };
|
|
},
|
|
},
|
|
plazaPosts: null,
|
|
plazaOps: null,
|
|
wechatAdmin: null,
|
|
subscriptionService: null,
|
|
});
|
|
const server = await startTestServer(router);
|
|
try {
|
|
const read = await fetch(`${server.baseUrl}/admin-api/asset-gateway/config`, {
|
|
headers: { cookie: 'h5_user_session=token-admin' },
|
|
});
|
|
assert.equal(read.status, 200);
|
|
assert.deepEqual(await read.json(), { enabled: false, plugins: [] });
|
|
|
|
const update = await fetch(`${server.baseUrl}/admin-api/asset-gateway/plugins/asset-generate`, {
|
|
method: 'PUT',
|
|
headers: { 'content-type': 'application/json', cookie: 'h5_user_session=token-admin' },
|
|
body: JSON.stringify({ enabled: true, provider: 'flux-schnell' }),
|
|
});
|
|
assert.equal(update.status, 200);
|
|
assert.equal(calls[0].pluginId, 'asset-generate');
|
|
assert.equal(calls[0].context.updatedBy, 'admin-1');
|
|
} finally {
|
|
await server.close();
|
|
}
|
|
});
|
|
|
|
test('admin system test route executes shared validation service', async () => {
|
|
const calls = [];
|
|
const router = createAdminApi({
|
|
jsonBody: express.json(),
|
|
getToken() {
|
|
return 'token-admin';
|
|
},
|
|
userAuth: {
|
|
async getMe(token) {
|
|
if (token !== 'token-admin') return null;
|
|
return { id: 'admin-1', role: 'admin' };
|
|
},
|
|
},
|
|
llmProviderService: null,
|
|
memoryV2ConfigService: null,
|
|
adminSystemTestService: {
|
|
async runSkillValidation(input) {
|
|
calls.push(input);
|
|
return {
|
|
ok: true,
|
|
selectedSkill: input.skillName,
|
|
account: { username: input.username },
|
|
summary: { passed: 1, warnings: 0, failed: 0 },
|
|
steps: [],
|
|
issues: [],
|
|
};
|
|
},
|
|
},
|
|
plazaPosts: null,
|
|
plazaOps: null,
|
|
wechatAdmin: null,
|
|
subscriptionService: null,
|
|
});
|
|
|
|
const server = await startTestServer(router);
|
|
try {
|
|
const response = await fetch(`${server.baseUrl}/admin-api/system-tests/skill-validation`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'content-type': 'application/json',
|
|
cookie: 'h5_user_session=token-admin',
|
|
},
|
|
body: JSON.stringify({
|
|
username: 'john',
|
|
password: 'secret',
|
|
skillName: 'service-integration-smoke',
|
|
}),
|
|
});
|
|
assert.equal(response.status, 200);
|
|
assert.deepEqual(calls, [{
|
|
username: 'john',
|
|
password: 'secret',
|
|
skillName: 'service-integration-smoke',
|
|
}]);
|
|
assert.equal((await response.json()).ok, true);
|
|
} finally {
|
|
await server.close();
|
|
}
|
|
});
|
|
|
|
test('admin wechat intent router config routes', async () => {
|
|
const updates = [];
|
|
const router = createAdminApi({
|
|
jsonBody: express.json(),
|
|
getToken() {
|
|
return 'token-admin';
|
|
},
|
|
userAuth: {
|
|
async getMe(token) {
|
|
if (token !== 'token-admin') return null;
|
|
return { id: 'admin-1', role: 'admin' };
|
|
},
|
|
},
|
|
wechatIntentRouterConfigService: {
|
|
async getConfig() {
|
|
return {
|
|
enabled: true,
|
|
shadowMode: true,
|
|
modelProviderKeyId: 'key-1',
|
|
model: 'deepseek-v4-pro',
|
|
minConfidence: 0.65,
|
|
timeoutMs: 4000,
|
|
canaryOpenids: ['openid-a'],
|
|
updatedAt: 123,
|
|
updatedBy: 'admin-1',
|
|
};
|
|
},
|
|
async updateConfig(patch, { updatedBy }) {
|
|
updates.push({ patch, updatedBy });
|
|
return {
|
|
enabled: false,
|
|
shadowMode: true,
|
|
modelProviderKeyId: null,
|
|
model: null,
|
|
minConfidence: 0.65,
|
|
timeoutMs: 4000,
|
|
canaryOpenids: [],
|
|
updatedAt: 456,
|
|
updatedBy,
|
|
};
|
|
},
|
|
async getRuntimeState() {
|
|
return {
|
|
source: 'admin-db',
|
|
updatedAt: 123,
|
|
updatedBy: 'admin-1',
|
|
fingerprint: 'fp-1',
|
|
overrides: { MEMIND_WECHAT_INTENT_LLM_ENABLED: '1' },
|
|
config: { enabled: true, shadowMode: true },
|
|
};
|
|
},
|
|
},
|
|
plazaPosts: null,
|
|
plazaOps: null,
|
|
wechatAdmin: null,
|
|
subscriptionService: null,
|
|
});
|
|
|
|
const server = await startTestServer(router);
|
|
try {
|
|
const configRes = await fetch(`${server.baseUrl}/admin-api/wechat/intent-router/config`, {
|
|
headers: { cookie: 'h5_user_session=token-admin' },
|
|
});
|
|
assert.equal(configRes.status, 200);
|
|
const configBody = await configRes.json();
|
|
assert.equal(configBody.config.enabled, true);
|
|
assert.equal(configBody.config.model, 'deepseek-v4-pro');
|
|
|
|
const updateRes = await fetch(`${server.baseUrl}/admin-api/wechat/intent-router/config`, {
|
|
method: 'PATCH',
|
|
headers: {
|
|
'content-type': 'application/json',
|
|
cookie: 'h5_user_session=token-admin',
|
|
},
|
|
body: JSON.stringify({ enabled: false }),
|
|
});
|
|
assert.equal(updateRes.status, 200);
|
|
assert.deepEqual(updates, [{ patch: { enabled: false }, updatedBy: 'admin-1' }]);
|
|
|
|
const runtimeRes = await fetch(`${server.baseUrl}/admin-api/wechat/intent-router/runtime`, {
|
|
headers: { cookie: 'h5_user_session=token-admin' },
|
|
});
|
|
assert.equal(runtimeRes.status, 200);
|
|
assert.deepEqual((await runtimeRes.json()).overrides, {
|
|
MEMIND_WECHAT_INTENT_LLM_ENABLED: '1',
|
|
});
|
|
} finally {
|
|
await server.close();
|
|
}
|
|
});
|