diff --git a/scripts/agent-run-worker.mjs b/scripts/agent-run-worker.mjs index 9300a88..cce6317 100644 --- a/scripts/agent-run-worker.mjs +++ b/scripts/agent-run-worker.mjs @@ -36,6 +36,7 @@ function parseArgs(argv) { const args = { once: false, status: false, + runId: '', pollMs: Number(process.env.MEMIND_AGENT_RUN_WORKER_POLL_MS ?? 1000), limit: Number(process.env.MEMIND_AGENT_RUN_WORKER_BATCH_SIZE ?? 1), }; @@ -43,6 +44,7 @@ function parseArgs(argv) { const item = argv[i]; if (item === '--once') args.once = true; else if (item === '--status') args.status = true; + else if (item === '--run-id') args.runId = String(argv[++i] ?? '').trim(); else if (item === '--poll-ms') args.pollMs = Number(argv[++i] ?? args.pollMs); else if (item === '--limit') args.limit = Number(argv[++i] ?? args.limit); else if (item === '--help' || item === '-h') args.help = true; @@ -53,11 +55,12 @@ function parseArgs(argv) { function printHelp() { console.log([ 'Usage:', - ' node scripts/agent-run-worker.mjs [--once] [--status] [--poll-ms 1000] [--limit 1]', + ' node scripts/agent-run-worker.mjs [--once] [--status] [--run-id ] [--poll-ms 1000] [--limit 1]', '', 'Notes:', ' - Processes existing h5_agent_runs queued/retryable rows through the Tool Gateway queue.', ' - Does not create agent runs by itself.', + ' - --run-id dispatches exactly one known run and avoids scanning the global queue.', ' - Set MEMIND_AGENT_RUN_AUTODISPATCH=0 on Portal only when this worker is ready to take over.', ].join('\n')); } @@ -72,10 +75,23 @@ if (args.help) { } const pool = createDbPool(); -const userAuth = createUserAuth(pool, { +const baseUserAuth = createUserAuth(pool, { usersRoot: process.env.H5_USERS_ROOT ?? path.join(root, 'users'), h5Root: root, }); +const overrideWorkingDir = String(process.env.MEMIND_AGENT_RUN_WORKDIR_OVERRIDE ?? '').trim(); +const overrideWorkingDirUserId = String(process.env.MEMIND_AGENT_RUN_WORKDIR_USER_ID ?? '').trim(); +const userAuth = overrideWorkingDir + ? { + ...baseUserAuth, + async resolveWorkingDir(userId) { + if (!overrideWorkingDirUserId || overrideWorkingDirUserId === userId) { + return path.resolve(overrideWorkingDir); + } + return baseUserAuth.resolveWorkingDir(userId); + }, + } + : baseUserAuth; const llmProviderService = createLlmProviderService(pool, { apiTarget: process.env.TKMIND_API_TARGET ?? 'https://127.0.0.1:18006', apiSecret: process.env.TKMIND_SERVER__SECRET_KEY ?? 'local-dev-secret', @@ -103,11 +119,22 @@ process.on('SIGINT', () => { stopping = true; }); process.on('SIGTERM', () => { stopping = true; }); async function runOnce() { - const result = await gateway.dispatchQueuedRuns({ limit: args.limit }); + let result = null; + if (args.runId) { + gateway.dispatchRun(args.runId); + result = { + considered: 1, + dispatched: 1, + runId: args.runId, + }; + } else { + result = await gateway.dispatchQueuedRuns({ limit: args.limit }); + } await waitForIdle(); console.log(JSON.stringify({ ok: true, mode: args.status ? 'status' : 'dispatch', + runId: args.runId || null, dispatched: args.status ? 0 : result.dispatched, queue: await gateway.getQueueStatus(), })); @@ -130,7 +157,7 @@ let exitCode = 0; try { if (args.status) { console.log(JSON.stringify({ ok: true, queue: await gateway.getQueueStatus() }, null, 2)); - } else if (args.once) { + } else if (args.once || args.runId) { await runOnce(); } else { console.log(JSON.stringify({ ok: true, worker: 'agent-run-worker', pollMs: args.pollMs, limit: args.limit }));