Refine discussion closure messaging

This commit is contained in:
zhi
2026-04-02 05:48:00 +00:00
parent 16daab666b
commit b40838f259
4 changed files with 112 additions and 10 deletions

View File

@@ -5,6 +5,7 @@ import os from 'node:os';
import path from 'node:path';
import { createDiscussionService } from '../plugin/core/discussion-service.ts';
import { buildDiscussionClosedMessage, buildDiscussionOriginCallbackMessage } from '../plugin/core/discussion-messages.ts';
function makeLogger() {
return {
@@ -244,3 +245,100 @@ test('handleCallback rejects an absolute path outside the initiator workspace',
/summaryPath must stay inside the initiator workspace/,
);
});
test('handleCallback notifies the origin channel with the resolved summary path', async () => {
const workspace = makeWorkspace();
const summaryRelPath = path.join('plans', 'discussion-summary.md');
const summaryAbsPath = path.join(workspace, summaryRelPath);
fs.mkdirSync(path.dirname(summaryAbsPath), { recursive: true });
fs.writeFileSync(summaryAbsPath, '# done\n');
const fetchCalls: Array<{ url: string; body: any }> = [];
const originalFetch = globalThis.fetch;
globalThis.fetch = (async (url: string | URL | Request, init?: RequestInit) => {
const body = init?.body ? JSON.parse(String(init.body)) : undefined;
fetchCalls.push({ url: String(url), body });
return new Response(JSON.stringify({ id: `msg-${fetchCalls.length}` }), { status: 200 });
}) as typeof fetch;
try {
const service = createDiscussionService({
api: makeApi() as any,
workspaceRoot: workspace,
moderatorBotToken: 'bot-token',
forceNoReplyForSession: () => {},
});
await service.initDiscussion({
discussionChannelId: 'discussion-origin-1',
originChannelId: 'origin-8',
initiatorAgentId: 'agent-theta',
initiatorSessionId: 'session-theta',
discussGuide: 'Notify the origin channel.',
});
await service.handleCallback({
channelId: 'discussion-origin-1',
summaryPath: summaryRelPath,
callerAgentId: 'agent-theta',
callerSessionKey: 'session-theta',
});
assert.equal(fetchCalls.length, 2);
assert.equal(fetchCalls[1]?.url, 'https://discord.com/api/v10/channels/origin-8/messages');
assert.equal(
fetchCalls[1]?.body?.content,
buildDiscussionOriginCallbackMessage(fs.realpathSync.native(summaryAbsPath), 'discussion-origin-1'),
);
} finally {
globalThis.fetch = originalFetch;
}
});
test('maybeReplyClosedChannel sends the archive-only closed message for later channel activity', async () => {
const workspace = makeWorkspace();
const summaryRelPath = 'summary.md';
const summaryAbsPath = path.join(workspace, summaryRelPath);
fs.writeFileSync(summaryAbsPath, 'closed\n');
const fetchCalls: Array<{ url: string; body: any }> = [];
const originalFetch = globalThis.fetch;
globalThis.fetch = (async (url: string | URL | Request, init?: RequestInit) => {
const body = init?.body ? JSON.parse(String(init.body)) : undefined;
fetchCalls.push({ url: String(url), body });
return new Response(JSON.stringify({ id: `msg-${fetchCalls.length}` }), { status: 200 });
}) as typeof fetch;
try {
const service = createDiscussionService({
api: makeApi() as any,
workspaceRoot: workspace,
moderatorBotToken: 'bot-token',
moderatorUserId: 'moderator-user',
forceNoReplyForSession: () => {},
});
await service.initDiscussion({
discussionChannelId: 'discussion-closed-1',
originChannelId: 'origin-9',
initiatorAgentId: 'agent-iota',
initiatorSessionId: 'session-iota',
discussGuide: 'Close and archive.',
});
await service.handleCallback({
channelId: 'discussion-closed-1',
summaryPath: summaryRelPath,
callerAgentId: 'agent-iota',
callerSessionKey: 'session-iota',
});
const handled = await service.maybeReplyClosedChannel('discussion-closed-1', 'human-user');
assert.equal(handled, true);
assert.equal(fetchCalls.length, 3);
assert.equal(fetchCalls[2]?.url, 'https://discord.com/api/v10/channels/discussion-closed-1/messages');
assert.equal(fetchCalls[2]?.body?.content, buildDiscussionClosedMessage());
} finally {
globalThis.fetch = originalFetch;
}
});