moving
This commit is contained in:
@@ -5,6 +5,7 @@ import path from 'node:path';
|
||||
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
||||
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { shutdown } from '../src/core/setup.js';
|
||||
|
||||
const ROOT = path.resolve(import.meta.dirname, '..', '..', '..');
|
||||
const SERVER_ENTRY = path.join(ROOT, 'packages', 'memory-mcp', 'dist', 'index.js');
|
||||
@@ -20,14 +21,16 @@ interface AsyncRunResult {
|
||||
stderr: string;
|
||||
}
|
||||
|
||||
function run(command: string, args: string[]): Promise<AsyncRunResult> {
|
||||
return runInCwd(command, args, ROOT);
|
||||
}
|
||||
|
||||
function runInCwd(command: string, args: string[], cwd: string): Promise<AsyncRunResult> {
|
||||
function runInCwd(
|
||||
command: string,
|
||||
args: string[],
|
||||
cwd: string,
|
||||
env: NodeJS.ProcessEnv = process.env,
|
||||
): Promise<AsyncRunResult> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const child = spawn(command, args, {
|
||||
cwd,
|
||||
env,
|
||||
shell: process.platform === 'win32' && command.endsWith('.cmd'),
|
||||
});
|
||||
let stdout = '';
|
||||
@@ -41,6 +44,37 @@ function runInCwd(command: string, args: string[], cwd: string): Promise<AsyncRu
|
||||
});
|
||||
}
|
||||
|
||||
function runNpm(args: string[], cwd: string = ROOT): Promise<AsyncRunResult> {
|
||||
const bundledNpmCli = path.join(
|
||||
path.dirname(process.execPath),
|
||||
'node_modules',
|
||||
'waggle-node-runtime',
|
||||
'node_modules',
|
||||
'npm',
|
||||
'bin',
|
||||
'npm-cli.js',
|
||||
);
|
||||
const npmCli = [bundledNpmCli, process.env.npm_execpath]
|
||||
.find((candidate): candidate is string => (
|
||||
typeof candidate === 'string' && fs.existsSync(candidate)
|
||||
));
|
||||
const npmEnv = { ...process.env };
|
||||
const inheritedPath = Object.entries(npmEnv)
|
||||
.find(([key]) => key.toLowerCase() === 'path')?.[1] ?? '';
|
||||
for (const key of Object.keys(npmEnv)) {
|
||||
if (key.toLowerCase() === 'path') delete npmEnv[key];
|
||||
}
|
||||
npmEnv.PATH = [
|
||||
...(npmCli ? [path.dirname(npmCli)] : []),
|
||||
path.dirname(process.execPath),
|
||||
inheritedPath,
|
||||
].filter(Boolean).join(path.delimiter);
|
||||
|
||||
return npmCli
|
||||
? runInCwd(process.execPath, [npmCli, ...args], cwd, npmEnv)
|
||||
: runInCwd(bin('npm'), args, cwd, npmEnv);
|
||||
}
|
||||
|
||||
async function withTimeout<T>(work: Promise<T>, ms: number): Promise<T> {
|
||||
let timeout: NodeJS.Timeout | undefined;
|
||||
const timer = new Promise<never>((_, reject) => {
|
||||
@@ -62,14 +96,19 @@ const WAGGLE_MEMORY_MCP_PACKAGE_CLOSURE = [
|
||||
] as const;
|
||||
|
||||
describe('waggle-memory-mcp built runtime', () => {
|
||||
it('shuts down safely before initialization and remains idempotent', () => {
|
||||
expect(() => shutdown()).not.toThrow();
|
||||
expect(() => shutdown()).not.toThrow();
|
||||
});
|
||||
|
||||
it('completes MCP initialize and lists read-only tools from built JS', async () => {
|
||||
const coreBuild = await run(bin('npm'), ['run', 'build', '--workspace', '@waggle/core']);
|
||||
const coreBuild = await runNpm(['run', 'build', '--workspace', '@waggle/core']);
|
||||
expect(coreBuild.status).toBe(0);
|
||||
|
||||
const wikiBuild = await run(bin('npm'), ['run', 'build', '--workspace', '@waggle/wiki-compiler']);
|
||||
const wikiBuild = await runNpm(['run', 'build', '--workspace', '@waggle/wiki-compiler']);
|
||||
expect(wikiBuild.status).toBe(0);
|
||||
|
||||
const mcpBuild = await run(bin('npm'), ['run', 'build', '--workspace', 'waggle-memory-mcp']);
|
||||
const mcpBuild = await runNpm(['run', 'build', '--workspace', 'waggle-memory-mcp']);
|
||||
expect(mcpBuild.status).toBe(0);
|
||||
|
||||
const dataDir = fs.mkdtempSync(path.join(os.tmpdir(), 'waggle-memory-mcp-'));
|
||||
@@ -97,16 +136,16 @@ describe('waggle-memory-mcp built runtime', () => {
|
||||
await client.close().catch(() => {});
|
||||
fs.rmSync(dataDir, { recursive: true, force: true });
|
||||
}
|
||||
}, 30_000);
|
||||
}, 60_000);
|
||||
|
||||
it('saves and recalls memory through the built write-scope MCP server', async () => {
|
||||
const coreBuild = await run(bin('npm'), ['run', 'build', '--workspace', '@waggle/core']);
|
||||
const coreBuild = await runNpm(['run', 'build', '--workspace', '@waggle/core']);
|
||||
expect(coreBuild.status).toBe(0);
|
||||
|
||||
const wikiBuild = await run(bin('npm'), ['run', 'build', '--workspace', '@waggle/wiki-compiler']);
|
||||
const wikiBuild = await runNpm(['run', 'build', '--workspace', '@waggle/wiki-compiler']);
|
||||
expect(wikiBuild.status).toBe(0);
|
||||
|
||||
const mcpBuild = await run(bin('npm'), ['run', 'build', '--workspace', 'waggle-memory-mcp']);
|
||||
const mcpBuild = await runNpm(['run', 'build', '--workspace', 'waggle-memory-mcp']);
|
||||
expect(mcpBuild.status).toBe(0);
|
||||
|
||||
const dataDir = fs.mkdtempSync(path.join(os.tmpdir(), 'waggle-memory-mcp-write-'));
|
||||
@@ -161,7 +200,7 @@ describe('waggle-memory-mcp built runtime', () => {
|
||||
await client.close().catch(() => {});
|
||||
fs.rmSync(dataDir, { recursive: true, force: true });
|
||||
}
|
||||
}, 30_000);
|
||||
}, 60_000);
|
||||
|
||||
it('installs the local package closure and lists tools from the installed server', async () => {
|
||||
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'waggle-memory-mcp-installed-'));
|
||||
@@ -176,11 +215,10 @@ describe('waggle-memory-mcp built runtime', () => {
|
||||
try {
|
||||
const dependencies: Record<string, string> = {};
|
||||
for (const workspace of WAGGLE_MEMORY_MCP_PACKAGE_CLOSURE) {
|
||||
const build = await run(bin('npm'), ['run', 'build', '--workspace', workspace]);
|
||||
const build = await runNpm(['run', 'build', '--workspace', workspace]);
|
||||
expect(build.status).toBe(0);
|
||||
|
||||
const pack = await run(
|
||||
bin('npm'),
|
||||
const pack = await runNpm(
|
||||
['pack', '--workspace', workspace, '--pack-destination', packsDir, '--json'],
|
||||
);
|
||||
expect(pack.status).toBe(0);
|
||||
@@ -195,8 +233,7 @@ describe('waggle-memory-mcp built runtime', () => {
|
||||
JSON.stringify({ private: true, type: 'module', dependencies }, null, 2),
|
||||
);
|
||||
|
||||
const install = await runInCwd(
|
||||
bin('npm'),
|
||||
const install = await runNpm(
|
||||
['install', '--no-audit', '--no-fund', '--prefer-offline'],
|
||||
projectDir,
|
||||
);
|
||||
@@ -220,7 +257,7 @@ describe('waggle-memory-mcp built runtime', () => {
|
||||
} as Record<string, string>,
|
||||
});
|
||||
|
||||
await withTimeout(client.connect(transport), 10_000);
|
||||
await withTimeout(client.connect(transport), 30_000);
|
||||
const tools = await withTimeout(client.listTools(), 10_000);
|
||||
const names = tools.tools.map((tool) => tool.name);
|
||||
|
||||
@@ -231,5 +268,5 @@ describe('waggle-memory-mcp built runtime', () => {
|
||||
await client.close().catch(() => {});
|
||||
fs.rmSync(tempDir, { recursive: true, force: true });
|
||||
}
|
||||
}, 120_000);
|
||||
}, 180_000);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user