maestro/test-smoke.ts
2026-06-03 04:30:10 +00:00

96 lines
3.1 KiB
TypeScript

/**
* スモークテスト: LLM接続 → エージェントループの動作確認
* 実行: npx tsx test-smoke.ts
*/
import { OpenAICompatClient } from './src/llm/openai-compat.js';
import { executeMovement, Movement } from './src/engine/agent-loop.js';
import { ToolContext } from './src/engine/tools.js';
import { mkdirSync } from 'fs';
import { join } from 'path';
const BASE_URL = process.env['OLLAMA_BASE_URL'] ?? 'http://10.0.0.10:11434/v1';
const MODEL = process.env['OLLAMA_MODEL'] ?? 'qwen3:8b';
async function testLLMConnection() {
console.log('=== Test 1: LLM接続確認 ===');
const client = new OpenAICompatClient(BASE_URL, MODEL);
for await (const event of client.chat([
{ role: 'user', content: 'Say "hello" in one word.' }
])) {
if (event.type === 'text') process.stdout.write(event.text);
if (event.type === 'error') console.error('\nError:', event.error);
if (event.type === 'done') console.log('\n[done]', event.usage ?? '');
}
}
async function testToolUse() {
console.log('\n=== Test 2: ツール呼び出し確認 ===');
const client = new OpenAICompatClient(BASE_URL, MODEL);
// テスト用ワークスペース作成
const workspace = '/tmp/agent-test-workspace';
mkdirSync(join(workspace, 'input'), { recursive: true });
mkdirSync(join(workspace, 'output'), { recursive: true });
// テスト用入力ファイル作成
const { writeFileSync } = await import('fs');
writeFileSync(join(workspace, 'input', 'sample.txt'), 'これはテストファイルです。\n行1\n行2\n行3\n');
const movement: Movement = {
name: 'test',
edit: true,
persona: 'テスター',
instruction: 'input/sample.txt を読み込んで内容を確認し、output/result.txt に「確認完了」と書き込んでください。',
allowedTools: ['Read', 'Write', 'Bash', 'Glob'],
rules: [
{ condition: '作業が完了した', next: 'COMPLETE' },
],
};
const ctx: ToolContext = { workspacePath: workspace, editAllowed: true };
console.log(`Workspace: ${workspace}`);
console.log(`Model: ${MODEL}`);
console.log('Running agent loop...\n');
const result = await executeMovement(
movement,
'テストタスク: ファイルの読み書き確認',
client,
ctx,
{
onToolUse: (name, input) => console.log(` [tool] ${name}(${JSON.stringify(input).slice(0, 100)})`),
onText: (text) => process.stdout.write(text),
},
10, // max 10 iterations
);
console.log('\n\n--- Result ---');
console.log('next:', result.next);
console.log('tools used:', result.toolsUsed);
console.log('output length:', result.output.length);
// output/result.txt が存在するか確認
try {
const { readFileSync } = await import('fs');
const output = readFileSync(join(workspace, 'output', 'result.txt'), 'utf-8');
console.log('output/result.txt:', output);
} catch {
console.log('output/result.txt: (not created)');
}
}
async function main() {
try {
await testLLMConnection();
await testToolUse();
console.log('\n=== All tests passed ===');
} catch (err) {
console.error('Test failed:', err);
process.exit(1);
}
}
main();