refactor: move destinations from JSON file into inbound.db

The per-session destination map was being written as a sidecar JSON file
(/workspace/.nanoclaw-destinations.json) — inconsistent with the rest of
v2, where all host↔container IO goes through inbound.db / outbound.db.

Move it into a `destinations` table in INBOUND_SCHEMA. The host writes
it before every container wake AND on demand (e.g. after create_agent)
so the creator sees the new child destination mid-session without a
restart. The container queries the table live on every lookup — no
cache, no staleness window.

- src/db/schema.ts: add `destinations` table to INBOUND_SCHEMA.
- src/session-manager.ts: writeDestinationsFile → writeDestinations,
  writes via DELETE + INSERT inside a transaction.
- src/delivery.ts: create_agent handler calls writeDestinations on the
  creator's session after inserting the new destination rows.
- container/agent-runner/src/destinations.ts: queries inbound.db
  directly in every findByName/getAllDestinations/findByRouting call.
  No more cache. No setDestinationsForTest (obsolete). No fs import.
- container/agent-runner/src/index.ts and mcp-tools/index.ts: remove
  loadDestinations() calls — no longer needed.
- Test helper initTestSessionDb creates the destinations table.
  Integration test inserts a row directly instead of mocking the cache.

No backwards compatibility: sessions predating the schema update must
be recreated. This is fine on the v2 branch.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
gavrielc
2026-04-10 16:45:53 +03:00
parent 09e1861a22
commit b591d7ce96
9 changed files with 132 additions and 79 deletions

View File

@@ -1,7 +1,6 @@
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import { initTestSessionDb, closeSessionDb, getInboundDb, getOutboundDb } from './db/connection.js';
import { setDestinationsForTest } from './destinations.js';
import { getUndeliveredMessages } from './db/messages-out.js';
import { getPendingMessages } from './db/messages-in.js';
import { MockProvider } from './providers/mock.js';
@@ -9,21 +8,17 @@ import { runPollLoop } from './poll-loop.js';
beforeEach(() => {
initTestSessionDb();
// Provide a test destination map so output parsing can resolve "discord-test" → routing
setDestinationsForTest([
{
name: 'discord-test',
displayName: 'Discord Test',
type: 'channel',
channelType: 'discord',
platformId: 'chan-1',
},
]);
// Seed a destination so output parsing can resolve "discord-test" → routing
getInboundDb()
.prepare(
`INSERT INTO destinations (name, display_name, type, channel_type, platform_id, agent_group_id)
VALUES ('discord-test', 'Discord Test', 'channel', 'discord', 'chan-1', NULL)`,
)
.run();
});
afterEach(() => {
closeSessionDb();
setDestinationsForTest([]);
});
function insertMessage(id: string, content: object, opts?: { platformId?: string; channelType?: string; threadId?: string }) {