fix(twitch): register chat intent for refreshing auth

This commit is contained in:
Andy Ye
2026-05-19 07:39:15 -07:00
committed by clawsweeper
parent d0f7c8fa28
commit 0b43ba4460
3 changed files with 38 additions and 6 deletions
+1
View File
@@ -86,6 +86,7 @@ Docs: https://docs.openclaw.ai
- Telegram: keep queued forum-topic follow-up messages from inheriting superseded source abort signals, so later same-topic user turns can still run and reply after an active turn is replaced. (#83827) Thanks @VACInc.
- CLI/update: bypass npm freshness filters consistently during managed package and plugin installs so freshly published release plugins remain installable. Thanks @jalehman.
- CLI/update: guide root-owned npm install EACCES recovery by stopping the managed Gateway before manual package replacement, then reinstalling and restarting the service. Fixes #83747. (#83757) Thanks @brokemac79.
- Twitch: register refreshing chat tokens with Twurple's chat intent so automatic token refresh keeps chat access available. (#83750) Thanks @TurboTheTurtle.
- Agents/subagents: keep collect-mode announce queues batching unresolved-origin items with compatible same-route messages and resume collection after a true cross-channel drain when a later compatible batch remains. Fixes #83577.
- Skills: refresh existing session skill snapshots when watched skill roots change, so changed extra skill directories take effect without starting a new session. Fixes #83782. (#83800) Thanks @hclsys.
- Providers/Anthropic: preserve native image input for current Claude model rows when stale local catalog data marks them text-only. (#83756) Thanks @TurboTheTurtle.
@@ -201,6 +201,32 @@ describe("TwitchClientManager", () => {
);
});
it("should register refreshing tokens for Twurple chat intent", async () => {
const refreshingAccount: TwitchAccountConfig = {
...testAccount,
clientSecret: "test-client-secret",
refreshToken: "test-refresh-token",
expiresIn: 3600,
obtainmentTimestamp: 1_700_000_000_000,
};
await manager.getClient(refreshingAccount);
expect(mockAddUserForToken).toHaveBeenCalledWith(
{
accessToken: "mock-token-from-tests",
refreshToken: "test-refresh-token",
expiresIn: 3600,
obtainmentTimestamp: 1_700_000_000_000,
},
["chat"],
);
expect(mockAuthProvider.constructor).not.toHaveBeenCalled();
expect(mockLogger.info).toHaveBeenCalledWith(
"Using RefreshingAuthProvider for testbot (automatic token refresh enabled)",
);
});
it("should throw error when clientId is missing", async () => {
const accountWithoutClientId: TwitchAccountConfig = {
...testAccount,
+11 -6
View File
@@ -6,6 +6,8 @@ import { resolveTwitchToken } from "./token.js";
import type { ChannelLogSink, TwitchAccountConfig, TwitchChatMessage } from "./types.js";
import { normalizeToken } from "./utils/twitch.js";
const TWITCH_CHAT_AUTH_INTENTS = ["chat"];
/**
* Manages Twitch chat client connections
*/
@@ -33,12 +35,15 @@ export class TwitchClientManager {
});
await authProvider
.addUserForToken({
accessToken: normalizedToken,
refreshToken: account.refreshToken ?? null,
expiresIn: account.expiresIn ?? null,
obtainmentTimestamp: account.obtainmentTimestamp ?? Date.now(),
})
.addUserForToken(
{
accessToken: normalizedToken,
refreshToken: account.refreshToken ?? null,
expiresIn: account.expiresIn ?? null,
obtainmentTimestamp: account.obtainmentTimestamp ?? Date.now(),
},
TWITCH_CHAT_AUTH_INTENTS,
)
.then((userId) => {
this.logger.info(
`Added user ${userId} to RefreshingAuthProvider for ${account.username}`,