import test from 'node:test'; import assert from 'node:assert/strict'; import { registerDirigentTools } from '../plugin/tools/register-tools.ts'; type RegisteredTool = { name: string; handler: (params: Record, ctx?: Record) => Promise; }; function makeApi() { const tools = new Map(); return { config: { channels: { discord: { accounts: { bot: { token: 'discord-bot-token' }, }, }, }, }, logger: { info: (_msg: string) => {}, warn: (_msg: string) => {}, }, registerTool(def: RegisteredTool) { tools.set(def.name, def); }, tools, }; } function pickDefined(obj: Record) { return Object.fromEntries(Object.entries(obj).filter(([, value]) => value !== undefined)); } test('plain private channel create works unchanged without discussion params', async () => { const api = makeApi(); let initDiscussionCalls = 0; const originalFetch = globalThis.fetch; globalThis.fetch = (async (_url: string | URL | Request, _init?: RequestInit) => { return new Response(JSON.stringify({ id: 'created-channel-1', name: 'plain-room' }), { status: 200 }); }) as typeof fetch; try { registerDirigentTools({ api: api as any, baseConfig: {}, pickDefined, discussionService: { async initDiscussion() { initDiscussionCalls += 1; return {}; }, async handleCallback() { return { ok: true }; }, }, }); const tool = api.tools.get('dirigent_discord_control'); assert.ok(tool); const result = await tool!.handler({ action: 'channel-private-create', guildId: 'guild-1', name: 'plain-room', allowedUserIds: ['user-1'], }, { agentId: 'agent-a', sessionKey: 'session-a', }); assert.equal(result.isError, undefined); assert.match(result.content[0].text, /"discussionMode": false/); assert.equal(initDiscussionCalls, 0); } finally { globalThis.fetch = originalFetch; } }); test('private channel create rejects callbackChannelId without discussGuide', async () => { const api = makeApi(); registerDirigentTools({ api: api as any, baseConfig: {}, pickDefined, discussionService: { async initDiscussion() { return {}; }, async handleCallback() { return { ok: true }; }, }, }); const tool = api.tools.get('dirigent_discord_control'); assert.ok(tool); const result = await tool!.handler({ action: 'channel-private-create', guildId: 'guild-1', name: 'discussion-room', callbackChannelId: 'origin-1', }, { agentId: 'agent-a', sessionKey: 'session-a', }); assert.equal(result.isError, true); assert.equal(result.content[0].text, 'discussGuide is required when callbackChannelId is provided'); }); test('discussion-mode channel create initializes discussion metadata', async () => { const api = makeApi(); const initCalls: Array> = []; const originalFetch = globalThis.fetch; globalThis.fetch = (async (_url: string | URL | Request, _init?: RequestInit) => { return new Response(JSON.stringify({ id: 'discussion-channel-1', name: 'discussion-room' }), { status: 200 }); }) as typeof fetch; try { registerDirigentTools({ api: api as any, baseConfig: {}, pickDefined, discussionService: { async initDiscussion(params) { initCalls.push(params as Record); return {}; }, async handleCallback() { return { ok: true }; }, }, }); const tool = api.tools.get('dirigent_discord_control'); assert.ok(tool); const result = await tool!.handler({ action: 'channel-private-create', guildId: 'guild-1', name: 'discussion-room', callbackChannelId: 'origin-1', discussGuide: 'Decide the callback contract.', }, { agentId: 'agent-a', sessionKey: 'session-a', }); assert.equal(result.isError, undefined); assert.match(result.content[0].text, /"discussionMode": true/); assert.equal(initCalls.length, 1); assert.deepEqual(initCalls[0], { discussionChannelId: 'discussion-channel-1', originChannelId: 'origin-1', initiatorAgentId: 'agent-a', initiatorSessionId: 'session-a', discussGuide: 'Decide the callback contract.', }); } finally { globalThis.fetch = originalFetch; } }); test('discuss-callback registers and forwards channel/session/agent context', async () => { const api = makeApi(); const callbackCalls: Array> = []; registerDirigentTools({ api: api as any, baseConfig: {}, pickDefined, discussionService: { async initDiscussion() { return {}; }, async handleCallback(params) { callbackCalls.push(params as Record); return { ok: true, summaryPath: '/workspace/summary.md' }; }, }, }); const tool = api.tools.get('discuss-callback'); assert.ok(tool); const result = await tool!.handler({ summaryPath: 'plans/summary.md' }, { channelId: 'discussion-1', agentId: 'agent-a', sessionKey: 'session-a', }); assert.equal(result.isError, undefined); assert.deepEqual(callbackCalls, [{ channelId: 'discussion-1', summaryPath: 'plans/summary.md', callerAgentId: 'agent-a', callerSessionKey: 'session-a', }]); assert.match(result.content[0].text, /"summaryPath": "\/workspace\/summary.md"/); });