@link-assistant/hive-mind 2.13.5 → 2.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -63,6 +63,11 @@ export const createYargsConfig = yargsInstance =>
63
63
  choices: ['screen', 'none', 'docker'],
64
64
  default: 'docker',
65
65
  })
66
+ .option('use-router', {
67
+ type: 'boolean',
68
+ description: '[EXPERIMENTAL] Route model traffic through the hive-mind-router sidecar instead of mounting AI credentials into the task container (issue #2164)',
69
+ default: false,
70
+ })
66
71
  .option('screen-name', {
67
72
  type: 'string',
68
73
  description: 'Screen session name when --isolation screen is used',
package/src/task.mjs CHANGED
@@ -42,6 +42,7 @@ if (earlyArgs.length === 0 || earlyArgs.includes('--help') || earlyArgs.includes
42
42
  console.log(' --tool AI tool for agent-commander read-only mode (claude, codex, opencode, agent, qwen, gemini) [default: claude]');
43
43
  console.log(' --model, -m Model to use');
44
44
  console.log(' --isolation agent-commander isolation mode [default: docker]');
45
+ console.log(' --use-router [EXPERIMENTAL] Route model traffic through the hive-mind-router sidecar (issue #2164)');
45
46
  console.log(' --dry-run Print split output without creating GitHub issues');
46
47
  console.log(' --verbose, -v Enable verbose logging');
47
48
  console.log(' --output-format Output format (text or json) [default: text]');
@@ -255,6 +255,7 @@ const { createHeartbeat, resumeSessionsOnLaunch, createShutdownHandler } = await
255
255
  const { formatExecutingWorkSessionMessage, formatStartingWorkSessionMessage } = await import('./work-session-formatting.lib.mjs');
256
256
  const { buildTelegramHelpMessage, buildTelegramInfoBlock, buildSolveQueuedMessage } = await import('./telegram-ui-messages.lib.mjs');
257
257
  const { startFormalAiMaintenance } = await import('./formal-ai-maintenance.lib.mjs');
258
+ const { startRouterMaintenance } = await import('./router-maintenance.lib.mjs');
258
259
  // Initialize Sentry for error tracking
259
260
  await initializeSentry({
260
261
  debug: VERBOSE,
@@ -1198,6 +1199,7 @@ if (VERBOSE) {
1198
1199
  const launchAbortController = new AbortController();
1199
1200
  let sessionMonitoringTimer = null;
1200
1201
  let formalAiMaintenance = null;
1202
+ let routerMaintenance = null;
1201
1203
  let launchAnnouncementShown = false;
1202
1204
 
1203
1205
  function startSessionMonitoringOnce() {
@@ -1220,6 +1222,20 @@ function startFormalAiMaintenanceOnce() {
1220
1222
  });
1221
1223
  }
1222
1224
 
1225
+ // Issue #2164 (R5): the router sidecar must only run while at least one task
1226
+ // uses it. A task that finishes releases its own lease, but a killed task or a
1227
+ // host reboot leaves one behind — this tick reconciles those against Docker and
1228
+ // stops an idle router. The audit data volume is never removed.
1229
+ function startRouterMaintenanceOnce() {
1230
+ if (routerMaintenance) return;
1231
+ routerMaintenance = startRouterMaintenance({
1232
+ verbose: VERBOSE,
1233
+ log: async message => {
1234
+ console.log(message);
1235
+ },
1236
+ });
1237
+ }
1238
+
1223
1239
  // Issue #1927 (requirements #3/#4): a periodic timestamped heartbeat so the "last
1224
1240
  // time the bot was alive" is always discoverable from the log. The heartbeat
1225
1241
  // logic lives in bot-lifecycle.lib.mjs so it can be unit tested.
@@ -1240,6 +1256,7 @@ async function onBotLaunched() {
1240
1256
 
1241
1257
  startSessionMonitoringOnce();
1242
1258
  startFormalAiMaintenanceOnce();
1259
+ startRouterMaintenanceOnce();
1243
1260
  heartbeat.start();
1244
1261
  if (VERBOSE) {
1245
1262
  console.log('[VERBOSE] Bot launched successfully');
@@ -1334,6 +1351,7 @@ const handleShutdownSignal = createShutdownHandler({
1334
1351
  launchAbortController.abort();
1335
1352
  if (sessionMonitoringTimer) clearInterval(sessionMonitoringTimer);
1336
1353
  formalAiMaintenance?.stop();
1354
+ routerMaintenance?.stop();
1337
1355
  heartbeat.stop();
1338
1356
  stopSolveQueue();
1339
1357
  },