repositories / will
will
owned by admin
src/agent/e2e.int.test.ts
Rawimport assert from 'node:assert/strict'
import { mkdir, mkdtemp, writeFile } from 'node:fs/promises'
import { createServer } from 'node:http'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import { test } from 'node:test'
import { startService } from '../service/main.ts'
import type { TgUpdateRaw } from '../shared/telegram.ts'
import { loadAgentConfig } from './config.ts'
import { startAgent } from './main.ts'
/**
* Walking skeleton (vertical slice): telegram mention -> durable wake ->
* fake resident session turn -> readiness flips healthy. Uses the real
* service, real telegram runtime against a fake Telegram, real queue and
* spool; only the model session is faked (WILL_SESSION_MODE=fake).
*/
test('end to end: mention reaches the resident session and readiness is healthy', async () => {
const updates: TgUpdateRaw[] = []
const sent: { method: string }[] = []
const tgServer = createServer((req, res) => {
const url = new URL(req.url ?? '/', 'http://x')
let data = ''
req.on('data', (c: Buffer) => {
data += c.toString()
})
req.on('end', () => {
let body: Record<string, unknown> = {}
try {
body = data === '' ? {} : (JSON.parse(data) as Record<string, unknown>)
} catch {
body = {}
}
const json = (p: unknown) => {
res.writeHead(200, { 'content-type': 'application/json' })
res.end(JSON.stringify(p))
}
const method = url.pathname.split('/').pop() ?? ''
switch (method) {
case 'getMe':
return json({ ok: true, result: { id: 42, username: 'will_bot' } })
case 'getUpdates':
return json({
ok: true,
result: updates.filter((u) => u.update_id >= ((body.offset as number) ?? 0)),
})
case 'getFile':
return json({ ok: true, result: { file_id: 'f', file_path: 'x' } })
default:
sent.push({ method })
return json({ ok: true, result: { message_id: 1 } })
}
})
})
await new Promise<void>((r) => tgServer.listen(0, '127.0.0.1', () => r()))
const tgUrl = `http://127.0.0.1:${(tgServer.address() as { port: number }).port}`
const dir = await mkdtemp(join(tmpdir(), 'e2e-'))
const webDist = join(dir, 'web-dist')
const resourceDir = join(dir, 'resources')
await mkdir(webDist, { recursive: true })
await mkdir(join(resourceDir, 'persona'), { recursive: true })
await writeFile(join(resourceDir, 'persona', '10-identity.md'), '# identity\nI am will.', 'utf8')
const service = await startService({
dataDir: join(dir, 'data'),
publicAddr: '127.0.0.1:0',
internalAddr: '127.0.0.1:0',
webDist,
docsDist: webDist,
mediaMaxBytes: 100 << 20,
storageWarnPct: 20,
storageStopPct: 10,
workerUrl: join(import.meta.dirname, '../service/worker.ts'),
})
const intPort = (service.internalServer.address() as { port: number }).port
const prev = { ...process.env }
process.env.WILL_SESSION_MODE = 'fake'
process.env.WILL_AGENT_DIR = join(dir, 'agent')
process.env.WILL_RESOURCE_DIR = resourceDir
process.env.WILL_SERVICE_INTERNAL_URL = `http://127.0.0.1:${intPort}`
process.env.WILL_AGENT_READY_ADDR = '127.0.0.1:0'
process.env.WILL_TELEGRAM_TOKEN = 'TOKEN'
process.env.WILL_TELEGRAM_CHAT_ID = '-100'
process.env.WILL_TELEGRAM_OLIVER_ID = '1'
process.env.WILL_TELEGRAM_API_BASE = tgUrl
process.env.ZAI_BASE_URL = tgUrl // unused without a key; keeps config total
delete process.env.WILL_VCS_GIT_URL
try {
updates.push({
update_id: 1,
message: {
message_id: 7,
date: Math.floor(Date.now() / 1000),
chat: { id: -100 },
from: { id: 5, username: 'friend' },
text: 'hey @will_bot are you alive',
entities: [{ type: 'mention', offset: 4, length: 9 }],
},
})
const agent = await startAgent(loadAgentConfig())
// wait for the wake to be consumed by the fake session
const fake = agent.session as unknown as { prompts: string[] }
const deadline = Date.now() + 15_000
while ((fake.prompts.length === 0 || !fake.prompts[0]) && Date.now() < deadline) {
await new Promise((r) => setTimeout(r, 100))
}
assert.ok(fake.prompts[0], 'resident session received a wake prompt')
assert.match(fake.prompts[0], /<chat_wake/)
assert.match(fake.prompts[0], /are you alive/)
const statusRes = await fetch(`http://127.0.0.1:${intPort}/v1/status`)
const status = (await statusRes.json()) as { counts: { chat: number } }
assert.equal(status.counts.chat, 1, 'message archived in service')
await agent.close()
assert.ok(agent.config.serviceUrl.includes('127.0.0.1'))
} finally {
for (const [k, v] of Object.entries(prev)) {
if (v === undefined) delete process.env[k]
else process.env[k] = v
}
await service.close()
tgServer.close()
}
})