Skip to content

Commit ce50e6e

Browse files
authored
Discord: fix /codex_resume identity resolution in brand-new threads (#35)
1 parent 682e5f4 commit ce50e6e

File tree

2 files changed

+33
-1
lines changed

2 files changed

+33
-1
lines changed

src/controller.test.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,33 @@ describe("Discord controller flows", () => {
353353
expect(reply.text).toContain("no longer exists on disk");
354354
});
355355

356+
it("resolves channel identity from ctx.to when ctx.from is a slash identity in a new Discord thread", async () => {
357+
// Regression test for brand-new Discord threads where the slash interaction
358+
// places the slash user identity in ctx.from and the channel target in ctx.to.
359+
const { controller, sendComponentMessage } = await createControllerHarness();
360+
361+
const reply = await controller.handleCommand(
362+
"cas_resume",
363+
buildDiscordCommandContext({
364+
from: "slash:user-1",
365+
to: "discord:channel:chan-1",
366+
}),
367+
);
368+
369+
expect(reply).toEqual({
370+
text: "Sent a Codex thread picker to this Discord conversation.",
371+
});
372+
expect(sendComponentMessage).toHaveBeenCalledWith(
373+
"channel:chan-1",
374+
expect.objectContaining({
375+
text: expect.stringContaining("Showing recent Codex sessions"),
376+
}),
377+
expect.objectContaining({
378+
accountId: "default",
379+
}),
380+
);
381+
});
382+
356383
it("sends Discord model pickers directly instead of returning Telegram buttons", async () => {
357384
const { controller, sendComponentMessage } = await createControllerHarness();
358385
await (controller as any).store.upsertBinding({

src/controller.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,12 @@ function toConversationTargetFromCommand(ctx: PluginCommandContext): Conversatio
271271
};
272272
}
273273
if (isDiscordChannel(ctx.channel)) {
274-
const conversationId = normalizeDiscordConversationId(ctx.from ?? ctx.to);
274+
// In brand-new Discord threads, the slash interaction may place the slash
275+
// user identity in ctx.from (e.g. "slash:user-id") while ctx.to holds the
276+
// real channel target. Prefer ctx.to when ctx.from is a slash identity so
277+
// /cas_resume resolves to the correct channel from the first attempt.
278+
const sourceId = ctx.from?.startsWith("slash:") ? ctx.to : (ctx.from ?? ctx.to);
279+
const conversationId = normalizeDiscordConversationId(sourceId);
275280
if (!conversationId) {
276281
return null;
277282
}

0 commit comments

Comments
 (0)