diff --git a/worker/serve.ts b/worker/serve.ts new file mode 100644 index 0000000..aea4a96 --- /dev/null +++ b/worker/serve.ts @@ -0,0 +1,42 @@ +/** + * Container entrypoint for the always-on Telegram worker. + * + * The platform's docker deploy proxies the domain to APP_PORT, so we expose a + * tiny health / status endpoint and boot the worker loop in the same process. + * Secrets (TELEGRAM_BOT_TOKEN / TELEGRAM_CHAT_ID) arrive as real env vars via + * Forgejo Secrets + RUNTIME_KEYS — config.ts falls back to process.env when + * there is no .env.local. State persists to QUANT_DATA_FILE (=/data on the + * persistent volume) so the paper track record survives redeploys. + * + * Local dev still uses `pnpm worker` (worker/loop.ts) directly — this file is + * only the HTTP wrapper the platform needs. + */ +import { createServer } from 'node:http' +import { getState } from './store.ts' +import './loop.ts' // boots the worker: boot message → tick loop → command poll + +const started = Date.now() +const PORT = Number(process.env.APP_PORT || process.env.PORT || 8080) + +createServer((req, res) => { + if (req.url === '/health') { + res.writeHead(200, { 'content-type': 'text/plain' }) + res.end('ok') + return + } + const body: Record = { + ok: true, + service: 'quant-agent-bot', + uptimeSec: Math.round((Date.now() - started) / 1000), + } + try { + const st = getState() + body.equity = Math.round(st.equity) + body.open = st.positions.length + body.closed = st.closed.length + } catch { + /* state not loaded yet — health still ok */ + } + res.writeHead(200, { 'content-type': 'application/json' }) + res.end(JSON.stringify(body)) +}).listen(PORT, () => console.log(`[serve] health on :${PORT}`))