Files
memind/server/portal-runtime-routes.test.mjs
T

225 lines
6.1 KiB
JavaScript

import assert from 'node:assert/strict';
import test from 'node:test';
import { attachPortalRuntimeRoutes } from './portal-runtime-routes.mjs';
function createRouterRecorder() {
const routes = new Map();
return {
routes,
get(path, handler) {
routes.set(path, handler);
},
};
}
function createResponseRecorder() {
return {
statusCode: 200,
body: undefined,
responseType: null,
status(code) {
this.statusCode = code;
return this;
},
send(body) {
this.responseType = 'send';
this.body = body;
return this;
},
json(body) {
this.responseType = 'json';
this.body = body;
return this;
},
};
}
test('portal runtime route module preserves the status route inventory', () => {
const api = createRouterRecorder();
attachPortalRuntimeRoutes(api);
assert.deepEqual([...api.routes.keys()], ['/status', '/runtime/status']);
});
test('GET /status preserves upstream status and body', async () => {
const api = createRouterRecorder();
let waited = false;
attachPortalRuntimeRoutes(api, {
waitForUserAuthReady: async () => {
waited = true;
},
getUserAuth: () => ({}),
getTkmindProxy: () => ({
async apiFetch(path, init) {
assert.equal(path, '/status');
assert.deepEqual(init, { method: 'GET' });
return {
status: 207,
async text() {
return 'upstream-status';
},
};
},
}),
});
const res = createResponseRecorder();
let nextCalled = false;
await api.routes.get('/status')({}, res, () => {
nextCalled = true;
});
assert.equal(waited, true);
assert.equal(nextCalled, false);
assert.equal(res.statusCode, 207);
assert.equal(res.responseType, 'send');
assert.equal(res.body, 'upstream-status');
});
test('GET /status falls through when multi-user proxy services are unavailable', async () => {
const api = createRouterRecorder();
attachPortalRuntimeRoutes(api);
const res = createResponseRecorder();
let nextCalled = false;
await api.routes.get('/status')({}, res, () => {
nextCalled = true;
});
assert.equal(nextCalled, true);
assert.equal(res.body, undefined);
});
test('GET /status preserves proxy failure response', async () => {
const api = createRouterRecorder();
attachPortalRuntimeRoutes(api, {
getUserAuth: () => ({}),
getTkmindProxy: () => ({
async apiFetch() {
throw new Error('proxy down');
},
}),
});
const res = createResponseRecorder();
await api.routes.get('/status')({}, res, () => {});
assert.equal(res.statusCode, 502);
assert.deepEqual(res.body, { message: 'proxy down' });
});
test('GET /runtime/status preserves memory, queue, and code-run policy projection', async () => {
const api = createRouterRecorder();
attachPortalRuntimeRoutes(api, {
getTkmindProxy: () => ({
async getRuntimeStatus() {
return { workers: [{ id: 'goosed-1' }], memory: { backend: 'legacy' } };
},
}),
getEpisodicMemoryService: () => ({
async getStatus() {
return { configuredEnabled: true, mode: 'canary' };
},
}),
getAgentRunGateway: () => ({
async getQueueStatus() {
return { active: 1, pendingDispatches: 2 };
},
}),
env: {
MEMIND_AGENT_CODE_RUNS_ENABLED: '1',
MEMIND_AGENT_CODE_RUNS_USER_IDS: 'user-a, user-b',
MEMIND_AGENT_CODE_RUN_TASK_TYPES: 'page,code',
MEMIND_AGENT_CODE_RUNS_REQUIRE_VALIDATION: 'true',
},
});
const res = createResponseRecorder();
await api.routes.get('/runtime/status')({}, res);
assert.equal(res.statusCode, 200);
assert.equal(res.body.ok, true);
assert.equal(typeof res.body.timestamp, 'string');
assert.deepEqual(res.body.memory, {
backend: 'legacy',
episodic: { configuredEnabled: true, mode: 'canary' },
});
assert.deepEqual(res.body.toolRuntime, {
codeRunPolicy: {
source: 'env',
enabled: true,
clientEnabled: false,
userAllowlist: ['user-a', 'user-b'],
taskTypeAllowlist: ['page', 'code'],
requireValidation: true,
pageDataDevAutodetect: false,
generalAutodetect: false,
envOverrideActive: false,
updatedAt: null,
updatedBy: null,
},
queue: { active: 1, pendingDispatches: 2 },
});
});
test('GET /runtime/status preserves fail-open dependency projections', async () => {
const api = createRouterRecorder();
attachPortalRuntimeRoutes(api, {
getTkmindProxy: () => ({
async getRuntimeStatus() {
return { memory: { backend: 'legacy' } };
},
}),
getEpisodicMemoryService: () => ({
async getStatus() {
throw new Error('episodic unavailable');
},
}),
getAgentRunGateway: () => ({
async getQueueStatus() {
throw new Error('queue unavailable');
},
}),
});
const res = createResponseRecorder();
await api.routes.get('/runtime/status')({}, res);
assert.deepEqual(res.body.memory, {
backend: 'legacy',
episodic: {
configuredEnabled: false,
mode: 'off',
error: 'episodic unavailable',
},
});
assert.deepEqual(res.body.toolRuntime.queue, { error: 'queue unavailable' });
});
test('GET /runtime/status preserves unavailable and upstream error responses', async () => {
const unavailableApi = createRouterRecorder();
attachPortalRuntimeRoutes(unavailableApi);
const unavailableRes = createResponseRecorder();
await unavailableApi.routes.get('/runtime/status')({}, unavailableRes);
assert.equal(unavailableRes.statusCode, 503);
assert.deepEqual(unavailableRes.body, {
ok: false,
message: 'runtime router unavailable',
});
const failingApi = createRouterRecorder();
attachPortalRuntimeRoutes(failingApi, {
getTkmindProxy: () => ({
async getRuntimeStatus() {
throw new Error('runtime down');
},
}),
});
const failingRes = createResponseRecorder();
await failingApi.routes.get('/runtime/status')({}, failingRes);
assert.equal(failingRes.statusCode, 502);
assert.deepEqual(failingRes.body, {
ok: false,
message: 'runtime down',
});
});