Files
multica/server
Jiang Bohan 9a43fcf87e fix(daemon): migrate existing .local daemon_ids and normalize on register
PR #1070 stripped `.local` from the daemon-side hostname so CLI and
desktop daemons stop registering as separate devices on macOS, but it
left two gaps:

1. Existing rows in `agent_runtime` for every macOS user still carry
   the `.local` suffix. After upgrade the daemon registers under the
   new canonical `daemon_id`, hits the `(workspace_id, daemon_id,
   provider)` unique key as a miss, and INSERTs a fresh row. The old
   `agent.runtime_id` FK keeps pointing at the orphaned `.local` row,
   which never receives a heartbeat again — the user's agent appears
   offline until they manually rebind it.
2. Older or non-CLI clients (anyone calling /api/daemon/register
   directly) can still send the suffixed form and create the same
   orphan condition going forward.

Fixes:

- Migration 048 walks `agent_runtime` and, for every (workspace_id,
  provider) where both `X` and `X.local` rows exist, redirects the
  `agent` and `agent_task_queue` FK references from the `.local` row
  to the canonical row inside a single statement (so the RESTRICT
  constraint passes), then deletes the duplicate. Orphaned `.local`
  rows with no canonical counterpart are renamed in place.
- Handler-side `normalizeDaemonID` strips the suffix on every
  /api/daemon/register call before the upsert, so stale clients can't
  re-create the orphan.

Tests cover the normalization helper directly and exercise the
register endpoint twice — once with `.local` and once canonical — to
prove both forms upsert into the same row.

Refs: MUL-971
2026-04-17 00:32:24 +08:00
..