#!/usr/bin/env node const baseUrl = (process.env.ZHINIAN_WORKER_BASE_URL || process.env.NEXT_PUBLIC_APP_URL || "http://127.0.0.1:3000").replace(/\/$/, ""); const token = (process.env.ZHINIAN_INTERNAL_WORKER_TOKEN || "").trim(); const intervalMs = positiveInt(process.env.ZHINIAN_WORKER_INTERVAL_MS, 5000); const limit = positiveInt(process.env.ZHINIAN_WORKER_BATCH_SIZE, 3); const once = process.argv.includes("--once"); const workerId = process.env.ZHINIAN_WORKER_ID || `worker-${Math.random().toString(16).slice(2)}`; if (process.env.NODE_ENV === "production" && !token) { console.error("[zhinian-worker] ZHINIAN_INTERNAL_WORKER_TOKEN is required in production. Set the same value for zhinian-aigc and zhinian-worker."); process.exit(1); } async function tick() { const response = await fetch(`${baseUrl}/api/internal/worker/tick`, { method: "POST", headers: { "Content-Type": "application/json", ...(token ? { "X-Zhinian-Worker-Token": token } : {}) }, body: JSON.stringify({ workerId, limit }) }); const text = await response.text(); if (!response.ok) throw new Error(`Worker tick failed: ${response.status} ${text}`); return text ? JSON.parse(text) : {}; } async function run() { do { try { const result = await tick(); console.log(`[zhinian-worker] claimed=${result.claimed || 0} worker=${result.workerId || workerId}`); } catch (error) { console.error(`[zhinian-worker] ${error instanceof Error ? error.message : String(error)}`); if (once) process.exitCode = 1; } if (!once) await sleep(intervalMs); } while (!once); } function positiveInt(value, fallback) { const parsed = Number(value); return Number.isFinite(parsed) && parsed > 0 ? Math.floor(parsed) : fallback; } function sleep(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); } run();