@openclaw/twitch 2026.2.21 → 2026.5.2-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/README.md +2 -2
  2. package/api.ts +21 -0
  3. package/channel-plugin-api.ts +1 -0
  4. package/index.test.ts +13 -0
  5. package/index.ts +12 -16
  6. package/openclaw.plugin.json +224 -1
  7. package/package.json +36 -7
  8. package/runtime-api.ts +22 -0
  9. package/setup-entry.ts +9 -0
  10. package/setup-plugin-api.ts +3 -0
  11. package/src/access-control.test.ts +136 -239
  12. package/src/access-control.ts +11 -4
  13. package/src/actions.test.ts +74 -0
  14. package/src/actions.ts +7 -6
  15. package/src/client-manager-registry.ts +0 -28
  16. package/src/config-schema.test.ts +46 -0
  17. package/src/config-schema.ts +25 -21
  18. package/src/config.test.ts +147 -1
  19. package/src/config.ts +76 -15
  20. package/src/monitor.ts +126 -85
  21. package/src/outbound.test.ts +140 -75
  22. package/src/outbound.ts +4 -5
  23. package/src/plugin.test.ts +39 -1
  24. package/src/plugin.ts +176 -242
  25. package/src/probe.test.ts +1 -1
  26. package/src/probe.ts +16 -5
  27. package/src/resolver.ts +5 -3
  28. package/src/runtime.ts +8 -13
  29. package/src/send.test.ts +92 -59
  30. package/src/send.ts +18 -15
  31. package/src/setup-surface.test.ts +511 -0
  32. package/src/setup-surface.ts +520 -0
  33. package/src/status.test.ts +120 -153
  34. package/src/status.ts +1 -1
  35. package/src/test-fixtures.ts +1 -1
  36. package/src/token.test.ts +22 -1
  37. package/src/token.ts +8 -6
  38. package/src/twitch-client.test.ts +18 -25
  39. package/src/twitch-client.ts +5 -6
  40. package/src/types.ts +7 -46
  41. package/src/utils/twitch.ts +8 -2
  42. package/tsconfig.json +16 -0
  43. package/CHANGELOG.md +0 -21
  44. package/src/onboarding.test.ts +0 -316
  45. package/src/onboarding.ts +0 -417
package/README.md CHANGED
@@ -5,7 +5,7 @@ Twitch channel plugin for OpenClaw.
5
5
  ## Install (local checkout)
6
6
 
7
7
  ```bash
8
- openclaw plugins install ./extensions/twitch
8
+ openclaw plugins install ./path/to/local/twitch-plugin
9
9
  ```
10
10
 
11
11
  ## Install (npm)
@@ -31,7 +31,7 @@ Minimal config (simplified single-account):
31
31
  accessToken: "oauth:abc123...", // OAuth Access Token (add oauth: prefix)
32
32
  clientId: "xyz789...", // Client ID from Token Generator
33
33
  channel: "vevisk", // Channel to join (required)
34
- allowFrom: ["123456789"], // (recommended) Your Twitch user ID only (Convert your twitch username to ID at https://www.streamweasels.com/tools/convert-twitch-username-%20to-user-id/)
34
+ allowFrom: ["123456789"], // (recommended) Your Twitch user ID only (Convert your twitch username to ID at https://www.streamweasels.com/tools/convert-twitch-username-to-user-id/)
35
35
  },
36
36
  },
37
37
  }
package/api.ts ADDED
@@ -0,0 +1,21 @@
1
+ export {
2
+ type ChannelAccountSnapshot,
3
+ type ChannelCapabilities,
4
+ type ChannelGatewayContext,
5
+ type ChannelLogSink,
6
+ type ChannelMessageActionAdapter,
7
+ type ChannelMessageActionContext,
8
+ type ChannelMeta,
9
+ type ChannelOutboundAdapter,
10
+ type ChannelOutboundContext,
11
+ type ChannelPlugin,
12
+ type ChannelResolveKind,
13
+ type ChannelResolveResult,
14
+ type ChannelStatusAdapter,
15
+ type OpenClawConfig,
16
+ type OutboundDeliveryResult,
17
+ type RuntimeEnv,
18
+ type WizardPrompter,
19
+ } from "./runtime-api.js";
20
+ export { twitchPlugin } from "./src/plugin.js";
21
+ export { setTwitchRuntime } from "./src/runtime.js";
@@ -0,0 +1 @@
1
+ export { twitchPlugin } from "./src/plugin.js";
package/index.test.ts ADDED
@@ -0,0 +1,13 @@
1
+ import { assertBundledChannelEntries } from "openclaw/plugin-sdk/channel-test-helpers";
2
+ import { describe } from "vitest";
3
+ import entry from "./index.js";
4
+ import setupEntry from "./setup-entry.js";
5
+
6
+ describe("twitch bundled entries", () => {
7
+ assertBundledChannelEntries({
8
+ entry,
9
+ expectedId: "twitch",
10
+ expectedName: "Twitch",
11
+ setupEntry,
12
+ });
13
+ });
package/index.ts CHANGED
@@ -1,20 +1,16 @@
1
- import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
2
- import { emptyPluginConfigSchema } from "openclaw/plugin-sdk";
3
- import { twitchPlugin } from "./src/plugin.js";
4
- import { setTwitchRuntime } from "./src/runtime.js";
1
+ import { defineBundledChannelEntry } from "openclaw/plugin-sdk/channel-entry-contract";
5
2
 
6
- export { monitorTwitchProvider } from "./src/monitor.js";
7
-
8
- const plugin = {
3
+ export default defineBundledChannelEntry({
9
4
  id: "twitch",
10
5
  name: "Twitch",
11
- description: "Twitch channel plugin",
12
- configSchema: emptyPluginConfigSchema(),
13
- register(api: OpenClawPluginApi) {
14
- setTwitchRuntime(api.runtime);
15
- // oxlint-disable-next-line typescript/no-explicit-any
16
- api.registerChannel({ plugin: twitchPlugin as any });
6
+ description: "Twitch IRC chat channel plugin",
7
+ importMetaUrl: import.meta.url,
8
+ plugin: {
9
+ specifier: "./channel-plugin-api.js",
10
+ exportName: "twitchPlugin",
17
11
  },
18
- };
19
-
20
- export default plugin;
12
+ runtime: {
13
+ specifier: "./api.js",
14
+ exportName: "setTwitchRuntime",
15
+ },
16
+ });
@@ -1,9 +1,232 @@
1
1
  {
2
2
  "id": "twitch",
3
- "channels": ["twitch"],
3
+ "activation": {
4
+ "onStartup": false
5
+ },
6
+ "channels": [
7
+ "twitch"
8
+ ],
9
+ "channelEnvVars": {
10
+ "twitch": [
11
+ "OPENCLAW_TWITCH_ACCESS_TOKEN"
12
+ ]
13
+ },
4
14
  "configSchema": {
5
15
  "type": "object",
6
16
  "additionalProperties": false,
7
17
  "properties": {}
18
+ },
19
+ "channelConfigs": {
20
+ "twitch": {
21
+ "schema": {
22
+ "$schema": "http://json-schema.org/draft-07/schema#",
23
+ "anyOf": [
24
+ {
25
+ "type": "object",
26
+ "properties": {
27
+ "name": {
28
+ "type": "string"
29
+ },
30
+ "enabled": {
31
+ "type": "boolean"
32
+ },
33
+ "markdown": {
34
+ "type": "object",
35
+ "properties": {
36
+ "tables": {
37
+ "type": "string",
38
+ "enum": [
39
+ "off",
40
+ "bullets",
41
+ "code",
42
+ "block"
43
+ ]
44
+ }
45
+ },
46
+ "additionalProperties": false
47
+ },
48
+ "defaultAccount": {
49
+ "type": "string"
50
+ },
51
+ "username": {
52
+ "type": "string"
53
+ },
54
+ "accessToken": {
55
+ "type": "string"
56
+ },
57
+ "clientId": {
58
+ "type": "string"
59
+ },
60
+ "channel": {
61
+ "type": "string",
62
+ "minLength": 1
63
+ },
64
+ "allowFrom": {
65
+ "type": "array",
66
+ "items": {
67
+ "type": "string"
68
+ }
69
+ },
70
+ "allowedRoles": {
71
+ "type": "array",
72
+ "items": {
73
+ "type": "string",
74
+ "enum": [
75
+ "moderator",
76
+ "owner",
77
+ "vip",
78
+ "subscriber",
79
+ "all"
80
+ ]
81
+ }
82
+ },
83
+ "requireMention": {
84
+ "type": "boolean"
85
+ },
86
+ "responsePrefix": {
87
+ "type": "string"
88
+ },
89
+ "clientSecret": {
90
+ "type": "string"
91
+ },
92
+ "refreshToken": {
93
+ "type": "string"
94
+ },
95
+ "expiresIn": {
96
+ "anyOf": [
97
+ {
98
+ "type": "number"
99
+ },
100
+ {
101
+ "type": "null"
102
+ }
103
+ ]
104
+ },
105
+ "obtainmentTimestamp": {
106
+ "type": "number"
107
+ }
108
+ },
109
+ "required": [
110
+ "username",
111
+ "accessToken",
112
+ "channel"
113
+ ],
114
+ "additionalProperties": false
115
+ },
116
+ {
117
+ "type": "object",
118
+ "properties": {
119
+ "name": {
120
+ "type": "string"
121
+ },
122
+ "enabled": {
123
+ "type": "boolean"
124
+ },
125
+ "markdown": {
126
+ "type": "object",
127
+ "properties": {
128
+ "tables": {
129
+ "type": "string",
130
+ "enum": [
131
+ "off",
132
+ "bullets",
133
+ "code",
134
+ "block"
135
+ ]
136
+ }
137
+ },
138
+ "additionalProperties": false
139
+ },
140
+ "defaultAccount": {
141
+ "type": "string"
142
+ },
143
+ "accounts": {
144
+ "type": "object",
145
+ "propertyNames": {
146
+ "type": "string"
147
+ },
148
+ "additionalProperties": {
149
+ "type": "object",
150
+ "properties": {
151
+ "username": {
152
+ "type": "string"
153
+ },
154
+ "accessToken": {
155
+ "type": "string"
156
+ },
157
+ "clientId": {
158
+ "type": "string"
159
+ },
160
+ "channel": {
161
+ "type": "string",
162
+ "minLength": 1
163
+ },
164
+ "enabled": {
165
+ "type": "boolean"
166
+ },
167
+ "allowFrom": {
168
+ "type": "array",
169
+ "items": {
170
+ "type": "string"
171
+ }
172
+ },
173
+ "allowedRoles": {
174
+ "type": "array",
175
+ "items": {
176
+ "type": "string",
177
+ "enum": [
178
+ "moderator",
179
+ "owner",
180
+ "vip",
181
+ "subscriber",
182
+ "all"
183
+ ]
184
+ }
185
+ },
186
+ "requireMention": {
187
+ "type": "boolean"
188
+ },
189
+ "responsePrefix": {
190
+ "type": "string"
191
+ },
192
+ "clientSecret": {
193
+ "type": "string"
194
+ },
195
+ "refreshToken": {
196
+ "type": "string"
197
+ },
198
+ "expiresIn": {
199
+ "anyOf": [
200
+ {
201
+ "type": "number"
202
+ },
203
+ {
204
+ "type": "null"
205
+ }
206
+ ]
207
+ },
208
+ "obtainmentTimestamp": {
209
+ "type": "number"
210
+ }
211
+ },
212
+ "required": [
213
+ "username",
214
+ "accessToken",
215
+ "channel"
216
+ ],
217
+ "additionalProperties": false
218
+ }
219
+ }
220
+ },
221
+ "required": [
222
+ "accounts"
223
+ ],
224
+ "additionalProperties": false
225
+ }
226
+ ]
227
+ },
228
+ "label": "Twitch",
229
+ "description": "Twitch chat integration"
230
+ }
8
231
  }
9
232
  }
package/package.json CHANGED
@@ -1,20 +1,49 @@
1
1
  {
2
2
  "name": "@openclaw/twitch",
3
- "version": "2026.2.21",
3
+ "version": "2026.5.2-beta.1",
4
4
  "description": "OpenClaw Twitch channel plugin",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "https://github.com/openclaw/openclaw"
8
+ },
5
9
  "type": "module",
6
10
  "dependencies": {
7
- "@twurple/api": "^8.0.3",
8
- "@twurple/auth": "^8.0.3",
9
- "@twurple/chat": "^8.0.3",
10
- "zod": "^4.3.6"
11
+ "@twurple/api": "^8.1.3",
12
+ "@twurple/auth": "^8.1.3",
13
+ "@twurple/chat": "^8.1.3"
11
14
  },
12
15
  "devDependencies": {
13
- "openclaw": "workspace:*"
16
+ "@openclaw/plugin-sdk": "workspace:*"
14
17
  },
15
18
  "openclaw": {
16
19
  "extensions": [
17
20
  "./index.ts"
18
- ]
21
+ ],
22
+ "setupEntry": "./setup-entry.ts",
23
+ "install": {
24
+ "npmSpec": "@openclaw/twitch",
25
+ "defaultChoice": "npm",
26
+ "minHostVersion": ">=2026.4.10"
27
+ },
28
+ "compat": {
29
+ "pluginApi": ">=2026.5.2-beta.1"
30
+ },
31
+ "build": {
32
+ "openclawVersion": "2026.5.2-beta.1"
33
+ },
34
+ "channel": {
35
+ "id": "twitch",
36
+ "label": "Twitch",
37
+ "selectionLabel": "Twitch (Chat)",
38
+ "docsPath": "/channels/twitch",
39
+ "blurb": "Twitch chat integration",
40
+ "aliases": [
41
+ "twitch-chat"
42
+ ]
43
+ },
44
+ "release": {
45
+ "publishToClawHub": true,
46
+ "publishToNpm": true
47
+ }
19
48
  }
20
49
  }
package/runtime-api.ts ADDED
@@ -0,0 +1,22 @@
1
+ // Private runtime barrel for the bundled Twitch extension.
2
+ // Keep this barrel thin and aligned with the local extension surface.
3
+
4
+ export type {
5
+ ChannelAccountSnapshot,
6
+ ChannelCapabilities,
7
+ ChannelGatewayContext,
8
+ ChannelLogSink,
9
+ ChannelMessageActionAdapter,
10
+ ChannelMessageActionContext,
11
+ ChannelMeta,
12
+ ChannelOutboundAdapter,
13
+ ChannelOutboundContext,
14
+ ChannelResolveKind,
15
+ ChannelResolveResult,
16
+ ChannelStatusAdapter,
17
+ } from "openclaw/plugin-sdk/channel-contract";
18
+ export type { ChannelPlugin } from "openclaw/plugin-sdk/channel-core";
19
+ export type { OutboundDeliveryResult } from "openclaw/plugin-sdk/channel-send-result";
20
+ export type { OpenClawConfig } from "openclaw/plugin-sdk/config-types";
21
+ export type { RuntimeEnv } from "openclaw/plugin-sdk/runtime";
22
+ export type { WizardPrompter } from "openclaw/plugin-sdk/setup";
package/setup-entry.ts ADDED
@@ -0,0 +1,9 @@
1
+ import { defineBundledChannelSetupEntry } from "openclaw/plugin-sdk/channel-entry-contract";
2
+
3
+ export default defineBundledChannelSetupEntry({
4
+ importMetaUrl: import.meta.url,
5
+ plugin: {
6
+ specifier: "./setup-plugin-api.js",
7
+ exportName: "twitchSetupPlugin",
8
+ },
9
+ });
@@ -0,0 +1,3 @@
1
+ // Keep bundled setup entry imports narrow so setup loads do not pull the
2
+ // broader Twitch channel plugin surface.
3
+ export { twitchSetupPlugin } from "./src/setup-surface.js";