@opentabs-dev/opentabs-plugin-twitch 0.0.74

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 (73) hide show
  1. package/README.md +159 -0
  2. package/dist/adapter.iife.js +15103 -0
  3. package/dist/adapter.iife.js.map +7 -0
  4. package/dist/index.d.ts +14 -0
  5. package/dist/index.d.ts.map +1 -0
  6. package/dist/index.js +60 -0
  7. package/dist/index.js.map +1 -0
  8. package/dist/tools/get-channel-emotes.d.ts +10 -0
  9. package/dist/tools/get-channel-emotes.d.ts.map +1 -0
  10. package/dist/tools/get-channel-emotes.js +38 -0
  11. package/dist/tools/get-channel-emotes.js.map +1 -0
  12. package/dist/tools/get-current-user.d.ts +18 -0
  13. package/dist/tools/get-current-user.d.ts.map +1 -0
  14. package/dist/tools/get-current-user.js +27 -0
  15. package/dist/tools/get-current-user.js.map +1 -0
  16. package/dist/tools/get-game-clips.d.ts +31 -0
  17. package/dist/tools/get-game-clips.d.ts.map +1 -0
  18. package/dist/tools/get-game-clips.js +44 -0
  19. package/dist/tools/get-game-clips.js.map +1 -0
  20. package/dist/tools/get-game.d.ts +15 -0
  21. package/dist/tools/get-game.d.ts.map +1 -0
  22. package/dist/tools/get-game.js +32 -0
  23. package/dist/tools/get-game.js.map +1 -0
  24. package/dist/tools/get-stream.d.ts +24 -0
  25. package/dist/tools/get-stream.d.ts.map +1 -0
  26. package/dist/tools/get-stream.js +36 -0
  27. package/dist/tools/get-stream.js.map +1 -0
  28. package/dist/tools/get-streams-by-game.d.ts +25 -0
  29. package/dist/tools/get-streams-by-game.d.ts.map +1 -0
  30. package/dist/tools/get-streams-by-game.js +44 -0
  31. package/dist/tools/get-streams-by-game.js.map +1 -0
  32. package/dist/tools/get-top-games.d.ts +14 -0
  33. package/dist/tools/get-top-games.d.ts.map +1 -0
  34. package/dist/tools/get-top-games.js +30 -0
  35. package/dist/tools/get-top-games.js.map +1 -0
  36. package/dist/tools/get-top-streams.d.ts +23 -0
  37. package/dist/tools/get-top-streams.d.ts.map +1 -0
  38. package/dist/tools/get-top-streams.js +34 -0
  39. package/dist/tools/get-top-streams.js.map +1 -0
  40. package/dist/tools/get-user-clips.d.ts +31 -0
  41. package/dist/tools/get-user-clips.d.ts.map +1 -0
  42. package/dist/tools/get-user-clips.js +44 -0
  43. package/dist/tools/get-user-clips.js.map +1 -0
  44. package/dist/tools/get-user-profile.d.ts +20 -0
  45. package/dist/tools/get-user-profile.d.ts.map +1 -0
  46. package/dist/tools/get-user-profile.js +31 -0
  47. package/dist/tools/get-user-profile.js.map +1 -0
  48. package/dist/tools/get-user-videos.d.ts +30 -0
  49. package/dist/tools/get-user-videos.d.ts.map +1 -0
  50. package/dist/tools/get-user-videos.js +58 -0
  51. package/dist/tools/get-user-videos.js.map +1 -0
  52. package/dist/tools/get-video.d.ts +23 -0
  53. package/dist/tools/get-video.d.ts.map +1 -0
  54. package/dist/tools/get-video.js +50 -0
  55. package/dist/tools/get-video.js.map +1 -0
  56. package/dist/tools/schemas.d.ts +153 -0
  57. package/dist/tools/schemas.d.ts.map +1 -0
  58. package/dist/tools/schemas.js +160 -0
  59. package/dist/tools/schemas.js.map +1 -0
  60. package/dist/tools/search-categories.d.ts +14 -0
  61. package/dist/tools/search-categories.d.ts.map +1 -0
  62. package/dist/tools/search-categories.js +29 -0
  63. package/dist/tools/search-categories.js.map +1 -0
  64. package/dist/tools/search-channels.d.ts +31 -0
  65. package/dist/tools/search-channels.d.ts.map +1 -0
  66. package/dist/tools/search-channels.js +56 -0
  67. package/dist/tools/search-channels.js.map +1 -0
  68. package/dist/tools.json +1492 -0
  69. package/dist/twitch-api.d.ts +6 -0
  70. package/dist/twitch-api.d.ts.map +1 -0
  71. package/dist/twitch-api.js +90 -0
  72. package/dist/twitch-api.js.map +1 -0
  73. package/package.json +54 -0
@@ -0,0 +1,14 @@
1
+ import { OpenTabsPlugin } from '@opentabs-dev/plugin-sdk';
2
+ import type { ToolDefinition } from '@opentabs-dev/plugin-sdk';
3
+ declare class TwitchPlugin extends OpenTabsPlugin {
4
+ readonly name = "twitch";
5
+ readonly description = "OpenTabs plugin for Twitch \u2014 browse streams, search channels and games, view clips and videos";
6
+ readonly displayName = "Twitch";
7
+ readonly urlPatterns: string[];
8
+ readonly homepage = "https://www.twitch.tv";
9
+ readonly tools: ToolDefinition[];
10
+ isReady(): Promise<boolean>;
11
+ }
12
+ declare const _default: TwitchPlugin;
13
+ export default _default;
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AA+B/D,cAAM,YAAa,SAAQ,cAAc;IACvC,QAAQ,CAAC,IAAI,YAAY;IACzB,QAAQ,CAAC,WAAW,wGAC8E;IAClG,SAAkB,WAAW,YAAY;IACzC,QAAQ,CAAC,WAAW,WAAyB;IAC7C,SAAkB,QAAQ,2BAA2B;IACrD,QAAQ,CAAC,KAAK,EAAE,cAAc,EAAE,CAsB9B;IAEI,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC;CAIlC;;AAED,wBAAkC"}
package/dist/index.js ADDED
@@ -0,0 +1,60 @@
1
+ import { OpenTabsPlugin } from '@opentabs-dev/plugin-sdk';
2
+ import { isAuthenticated, waitForAuth } from './twitch-api.js';
3
+ // Users
4
+ import { getCurrentUser } from './tools/get-current-user.js';
5
+ import { getUserProfile } from './tools/get-user-profile.js';
6
+ // Streams
7
+ import { getTopStreams } from './tools/get-top-streams.js';
8
+ import { getStreamsByGame } from './tools/get-streams-by-game.js';
9
+ import { getStream } from './tools/get-stream.js';
10
+ // Games
11
+ import { getTopGames } from './tools/get-top-games.js';
12
+ import { getGame } from './tools/get-game.js';
13
+ // Search
14
+ import { searchChannels } from './tools/search-channels.js';
15
+ import { searchCategories } from './tools/search-categories.js';
16
+ // Clips
17
+ import { getUserClips } from './tools/get-user-clips.js';
18
+ import { getGameClips } from './tools/get-game-clips.js';
19
+ // Videos
20
+ import { getUserVideos } from './tools/get-user-videos.js';
21
+ import { getVideo } from './tools/get-video.js';
22
+ // Chat
23
+ import { getChannelEmotes } from './tools/get-channel-emotes.js';
24
+ class TwitchPlugin extends OpenTabsPlugin {
25
+ name = 'twitch';
26
+ description = 'OpenTabs plugin for Twitch — browse streams, search channels and games, view clips and videos';
27
+ displayName = 'Twitch';
28
+ urlPatterns = ['*://*.twitch.tv/*'];
29
+ homepage = 'https://www.twitch.tv';
30
+ tools = [
31
+ // Users
32
+ getCurrentUser,
33
+ getUserProfile,
34
+ // Streams
35
+ getTopStreams,
36
+ getStreamsByGame,
37
+ getStream,
38
+ // Games
39
+ getTopGames,
40
+ getGame,
41
+ // Search
42
+ searchChannels,
43
+ searchCategories,
44
+ // Clips
45
+ getUserClips,
46
+ getGameClips,
47
+ // Videos
48
+ getUserVideos,
49
+ getVideo,
50
+ // Chat
51
+ getChannelEmotes,
52
+ ];
53
+ async isReady() {
54
+ if (isAuthenticated())
55
+ return true;
56
+ return waitForAuth();
57
+ }
58
+ }
59
+ export default new TwitchPlugin();
60
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE1D,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE/D,QAAQ;AACR,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAE7D,UAAU;AACV,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAElD,QAAQ;AACR,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAE9C,SAAS;AACT,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAEhE,QAAQ;AACR,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAEzD,SAAS;AACT,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAEhD,OAAO;AACP,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAEjE,MAAM,YAAa,SAAQ,cAAc;IAC9B,IAAI,GAAG,QAAQ,CAAC;IAChB,WAAW,GAClB,+FAA+F,CAAC;IAChF,WAAW,GAAG,QAAQ,CAAC;IAChC,WAAW,GAAG,CAAC,mBAAmB,CAAC,CAAC;IAC3B,QAAQ,GAAG,uBAAuB,CAAC;IAC5C,KAAK,GAAqB;QACjC,QAAQ;QACR,cAAc;QACd,cAAc;QACd,UAAU;QACV,aAAa;QACb,gBAAgB;QAChB,SAAS;QACT,QAAQ;QACR,WAAW;QACX,OAAO;QACP,SAAS;QACT,cAAc;QACd,gBAAgB;QAChB,QAAQ;QACR,YAAY;QACZ,YAAY;QACZ,SAAS;QACT,aAAa;QACb,QAAQ;QACR,OAAO;QACP,gBAAgB;KACjB,CAAC;IAEF,KAAK,CAAC,OAAO;QACX,IAAI,eAAe,EAAE;YAAE,OAAO,IAAI,CAAC;QACnC,OAAO,WAAW,EAAE,CAAC;IACvB,CAAC;CACF;AAED,eAAe,IAAI,YAAY,EAAE,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { z } from 'zod';
2
+ export declare const getChannelEmotes: import("@opentabs-dev/plugin-sdk").ToolDefinition<z.ZodObject<{
3
+ login: z.ZodString;
4
+ }, z.core.$strip>, z.ZodObject<{
5
+ emotes: z.ZodArray<z.ZodObject<{
6
+ id: z.ZodString;
7
+ token: z.ZodString;
8
+ }, z.core.$strip>>;
9
+ }, z.core.$strip>>;
10
+ //# sourceMappingURL=get-channel-emotes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-channel-emotes.d.ts","sourceRoot":"","sources":["../../src/tools/get-channel-emotes.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAQxB,eAAO,MAAM,gBAAgB;;;;;;;kBAsC3B,CAAC"}
@@ -0,0 +1,38 @@
1
+ import { defineTool, ToolError } from '@opentabs-dev/plugin-sdk';
2
+ import { z } from 'zod';
3
+ import { gql } from '../twitch-api.js';
4
+ const emoteSchema = z.object({
5
+ id: z.string().describe('Emote ID'),
6
+ token: z.string().describe('Emote name/token used in chat'),
7
+ });
8
+ export const getChannelEmotes = defineTool({
9
+ name: 'get_channel_emotes',
10
+ displayName: 'Get Channel Emotes',
11
+ description: 'Get subscription emotes for a Twitch channel. Returns the emote name (token) and ID for each emote across all subscription tiers.',
12
+ summary: 'Get subscription emotes for a channel',
13
+ icon: 'smile',
14
+ group: 'Chat',
15
+ input: z.object({
16
+ login: z.string().describe('Channel login name (e.g., "shroud")'),
17
+ }),
18
+ output: z.object({ emotes: z.array(emoteSchema) }),
19
+ handle: async (params) => {
20
+ const data = await gql(`{
21
+ user(login: "${params.login}") {
22
+ subscriptionProducts {
23
+ emotes { id token }
24
+ }
25
+ }
26
+ }`);
27
+ if (!data.user)
28
+ throw ToolError.notFound(`Channel "${params.login}" not found`);
29
+ const allEmotes = (data.user.subscriptionProducts ?? []).flatMap(p => p.emotes ?? []);
30
+ return {
31
+ emotes: allEmotes.map(e => ({
32
+ id: e.id ?? '',
33
+ token: e.token ?? '',
34
+ })),
35
+ };
36
+ },
37
+ });
38
+ //# sourceMappingURL=get-channel-emotes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-channel-emotes.js","sourceRoot":"","sources":["../../src/tools/get-channel-emotes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AAEvC,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3B,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC;IACnC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,+BAA+B,CAAC;CAC5D,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,gBAAgB,GAAG,UAAU,CAAC;IACzC,IAAI,EAAE,oBAAoB;IAC1B,WAAW,EAAE,oBAAoB;IACjC,WAAW,EACT,mIAAmI;IACrI,OAAO,EAAE,uCAAuC;IAChD,IAAI,EAAE,OAAO;IACb,KAAK,EAAE,MAAM;IACb,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC;QACd,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,qCAAqC,CAAC;KAClE,CAAC;IACF,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,CAAC;IAClD,MAAM,EAAE,KAAK,EAAC,MAAM,EAAC,EAAE;QAQrB,MAAM,IAAI,GAAG,MAAM,GAAG,CAEnB;qBACc,MAAM,CAAC,KAAK;;;;;MAK3B,CAAC,CAAC;QACJ,IAAI,CAAC,IAAI,CAAC,IAAI;YAAE,MAAM,SAAS,CAAC,QAAQ,CAAC,YAAY,MAAM,CAAC,KAAK,aAAa,CAAC,CAAC;QAChF,MAAM,SAAS,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,oBAAoB,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;QACtF,OAAO;YACL,MAAM,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;gBAC1B,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE;gBACd,KAAK,EAAE,CAAC,CAAC,KAAK,IAAI,EAAE;aACrB,CAAC,CAAC;SACJ,CAAC;IACJ,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,18 @@
1
+ import { z } from 'zod';
2
+ export declare const getCurrentUser: import("@opentabs-dev/plugin-sdk").ToolDefinition<z.ZodObject<{}, z.core.$strip>, z.ZodObject<{
3
+ user: z.ZodObject<{
4
+ id: z.ZodString;
5
+ login: z.ZodString;
6
+ displayName: z.ZodString;
7
+ profileImageURL: z.ZodString;
8
+ description: z.ZodString;
9
+ createdAt: z.ZodString;
10
+ hasPrime: z.ZodBoolean;
11
+ roles: z.ZodObject<{
12
+ isPartner: z.ZodBoolean;
13
+ isAffiliate: z.ZodBoolean;
14
+ }, z.core.$strip>;
15
+ followerCount: z.ZodNumber;
16
+ }, z.core.$strip>;
17
+ }, z.core.$strip>>;
18
+ //# sourceMappingURL=get-current-user.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-current-user.d.ts","sourceRoot":"","sources":["../../src/tools/get-current-user.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;kBAsBzB,CAAC"}
@@ -0,0 +1,27 @@
1
+ import { defineTool } from '@opentabs-dev/plugin-sdk';
2
+ import { z } from 'zod';
3
+ import { gql } from '../twitch-api.js';
4
+ import { userSchema, mapUser } from './schemas.js';
5
+ export const getCurrentUser = defineTool({
6
+ name: 'get_current_user',
7
+ displayName: 'Get Current User',
8
+ description: 'Get the authenticated Twitch user profile including email, display name, follower count, partner/affiliate status, and account creation date.',
9
+ summary: 'Get the authenticated Twitch user profile',
10
+ icon: 'user',
11
+ group: 'Users',
12
+ input: z.object({}),
13
+ output: z.object({ user: userSchema }),
14
+ handle: async () => {
15
+ const data = await gql(`{
16
+ currentUser {
17
+ id login displayName description
18
+ profileImageURL(width: 300)
19
+ createdAt hasPrime
20
+ roles { isPartner isAffiliate }
21
+ followers { totalCount }
22
+ }
23
+ }`);
24
+ return { user: mapUser(data.currentUser) };
25
+ },
26
+ });
27
+ //# sourceMappingURL=get-current-user.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-current-user.js","sourceRoot":"","sources":["../../src/tools/get-current-user.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAGnD,MAAM,CAAC,MAAM,cAAc,GAAG,UAAU,CAAC;IACvC,IAAI,EAAE,kBAAkB;IACxB,WAAW,EAAE,kBAAkB;IAC/B,WAAW,EACT,+IAA+I;IACjJ,OAAO,EAAE,2CAA2C;IACpD,IAAI,EAAE,MAAM;IACZ,KAAK,EAAE,OAAO;IACd,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;IACnB,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;IACtC,MAAM,EAAE,KAAK,IAAI,EAAE;QACjB,MAAM,IAAI,GAAG,MAAM,GAAG,CAA2B;;;;;;;;MAQ/C,CAAC,CAAC;QACJ,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;IAC7C,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,31 @@
1
+ import { z } from 'zod';
2
+ export declare const getGameClips: import("@opentabs-dev/plugin-sdk").ToolDefinition<z.ZodObject<{
3
+ name: z.ZodString;
4
+ period: z.ZodOptional<z.ZodEnum<{
5
+ LAST_DAY: "LAST_DAY";
6
+ LAST_WEEK: "LAST_WEEK";
7
+ LAST_MONTH: "LAST_MONTH";
8
+ ALL_TIME: "ALL_TIME";
9
+ }>>;
10
+ first: z.ZodOptional<z.ZodNumber>;
11
+ }, z.core.$strip>, z.ZodObject<{
12
+ clips: z.ZodArray<z.ZodObject<{
13
+ id: z.ZodString;
14
+ slug: z.ZodString;
15
+ title: z.ZodString;
16
+ viewCount: z.ZodNumber;
17
+ createdAt: z.ZodString;
18
+ thumbnailURL: z.ZodString;
19
+ durationSeconds: z.ZodNumber;
20
+ broadcaster: z.ZodObject<{
21
+ id: z.ZodString;
22
+ login: z.ZodString;
23
+ displayName: z.ZodString;
24
+ }, z.core.$strip>;
25
+ game: z.ZodObject<{
26
+ id: z.ZodString;
27
+ name: z.ZodString;
28
+ }, z.core.$strip>;
29
+ }, z.core.$strip>>;
30
+ }, z.core.$strip>>;
31
+ //# sourceMappingURL=get-game-clips.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-game-clips.d.ts","sourceRoot":"","sources":["../../src/tools/get-game-clips.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAwCvB,CAAC"}
@@ -0,0 +1,44 @@
1
+ import { defineTool, ToolError } from '@opentabs-dev/plugin-sdk';
2
+ import { z } from 'zod';
3
+ import { gql } from '../twitch-api.js';
4
+ import { clipSchema, mapClip } from './schemas.js';
5
+ export const getGameClips = defineTool({
6
+ name: 'get_game_clips',
7
+ displayName: 'Get Game Clips',
8
+ description: 'Get top clips for a specific game/category on Twitch. Provide the game name and optionally filter by time period.',
9
+ summary: 'Get top clips for a game or category',
10
+ icon: 'clapperboard',
11
+ group: 'Clips',
12
+ input: z.object({
13
+ name: z.string().describe('Game name (e.g., "Fortnite", "Just Chatting")'),
14
+ period: z
15
+ .enum(['LAST_DAY', 'LAST_WEEK', 'LAST_MONTH', 'ALL_TIME'])
16
+ .optional()
17
+ .describe('Time period filter (default LAST_WEEK)'),
18
+ first: z.number().int().min(1).max(25).optional().describe('Number of clips to return (default 10, max 25)'),
19
+ }),
20
+ output: z.object({ clips: z.array(clipSchema) }),
21
+ handle: async (params) => {
22
+ const first = params.first ?? 10;
23
+ const period = params.period ?? 'LAST_WEEK';
24
+ const data = await gql(`{
25
+ game(name: "${params.name.replace(/"/g, '\\"')}") {
26
+ clips(first: ${first}, criteria: { period: ${period} }) {
27
+ edges {
28
+ node {
29
+ id slug title viewCount createdAt thumbnailURL durationSeconds
30
+ broadcaster { id login displayName }
31
+ game { id name }
32
+ }
33
+ }
34
+ }
35
+ }
36
+ }`);
37
+ if (!data.game)
38
+ throw ToolError.notFound(`Game "${params.name}" not found`);
39
+ return {
40
+ clips: (data.game.clips?.edges ?? []).map(e => mapClip(e.node)),
41
+ };
42
+ },
43
+ });
44
+ //# sourceMappingURL=get-game-clips.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-game-clips.js","sourceRoot":"","sources":["../../src/tools/get-game-clips.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAGnD,MAAM,CAAC,MAAM,YAAY,GAAG,UAAU,CAAC;IACrC,IAAI,EAAE,gBAAgB;IACtB,WAAW,EAAE,gBAAgB;IAC7B,WAAW,EACT,mHAAmH;IACrH,OAAO,EAAE,sCAAsC;IAC/C,IAAI,EAAE,cAAc;IACpB,KAAK,EAAE,OAAO;IACd,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC;QACd,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,+CAA+C,CAAC;QAC1E,MAAM,EAAE,CAAC;aACN,IAAI,CAAC,CAAC,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,UAAU,CAAC,CAAC;aACzD,QAAQ,EAAE;aACV,QAAQ,CAAC,wCAAwC,CAAC;QACrD,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,gDAAgD,CAAC;KAC7G,CAAC;IACF,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC;IAChD,MAAM,EAAE,KAAK,EAAC,MAAM,EAAC,EAAE;QACrB,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC;QACjC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,WAAW,CAAC;QAC5C,MAAM,IAAI,GAAG,MAAM,GAAG,CAEnB;oBACa,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC;uBAC7B,KAAK,yBAAyB,MAAM;;;;;;;;;;MAUrD,CAAC,CAAC;QACJ,IAAI,CAAC,IAAI,CAAC,IAAI;YAAE,MAAM,SAAS,CAAC,QAAQ,CAAC,SAAS,MAAM,CAAC,IAAI,aAAa,CAAC,CAAC;QAC5E,OAAO;YACL,KAAK,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;SAChE,CAAC;IACJ,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { z } from 'zod';
2
+ export declare const getGame: import("@opentabs-dev/plugin-sdk").ToolDefinition<z.ZodObject<{
3
+ name: z.ZodOptional<z.ZodString>;
4
+ id: z.ZodOptional<z.ZodString>;
5
+ }, z.core.$strip>, z.ZodObject<{
6
+ game: z.ZodObject<{
7
+ id: z.ZodString;
8
+ name: z.ZodString;
9
+ displayName: z.ZodString;
10
+ viewersCount: z.ZodNumber;
11
+ broadcastersCount: z.ZodNumber;
12
+ boxArtURL: z.ZodString;
13
+ }, z.core.$strip>;
14
+ }, z.core.$strip>>;
15
+ //# sourceMappingURL=get-game.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-game.d.ts","sourceRoot":"","sources":["../../src/tools/get-game.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,eAAO,MAAM,OAAO;;;;;;;;;;;;kBA0BlB,CAAC"}
@@ -0,0 +1,32 @@
1
+ import { defineTool, ToolError } from '@opentabs-dev/plugin-sdk';
2
+ import { z } from 'zod';
3
+ import { gql } from '../twitch-api.js';
4
+ import { gameSchema, mapGame } from './schemas.js';
5
+ export const getGame = defineTool({
6
+ name: 'get_game',
7
+ displayName: 'Get Game',
8
+ description: 'Get details about a specific game/category on Twitch by name or ID. Returns viewer count, broadcaster count, and box art URL.',
9
+ summary: 'Get game/category details',
10
+ icon: 'gamepad-2',
11
+ group: 'Games',
12
+ input: z.object({
13
+ name: z.string().optional().describe('Game name (e.g., "Just Chatting", "Fortnite")'),
14
+ id: z.string().optional().describe('Game ID (alternative to name)'),
15
+ }),
16
+ output: z.object({ game: gameSchema }),
17
+ handle: async (params) => {
18
+ if (!params.id && !params.name) {
19
+ throw ToolError.validation('Either name or id is required');
20
+ }
21
+ const gameArg = params.id ? `id: "${params.id}"` : `name: "${params.name}"`;
22
+ const data = await gql(`{
23
+ game(${gameArg}) {
24
+ id name displayName viewersCount broadcastersCount boxArtURL
25
+ }
26
+ }`);
27
+ if (!data.game)
28
+ throw ToolError.notFound('Game not found');
29
+ return { game: mapGame(data.game) };
30
+ },
31
+ });
32
+ //# sourceMappingURL=get-game.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-game.js","sourceRoot":"","sources":["../../src/tools/get-game.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAGnD,MAAM,CAAC,MAAM,OAAO,GAAG,UAAU,CAAC;IAChC,IAAI,EAAE,UAAU;IAChB,WAAW,EAAE,UAAU;IACvB,WAAW,EACT,+HAA+H;IACjI,OAAO,EAAE,2BAA2B;IACpC,IAAI,EAAE,WAAW;IACjB,KAAK,EAAE,OAAO;IACd,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC;QACd,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,+CAA+C,CAAC;QACrF,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,+BAA+B,CAAC;KACpE,CAAC;IACF,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;IACtC,MAAM,EAAE,KAAK,EAAC,MAAM,EAAC,EAAE;QACrB,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;YAC/B,MAAM,SAAS,CAAC,UAAU,CAAC,+BAA+B,CAAC,CAAC;QAC9D,CAAC;QACD,MAAM,OAAO,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,UAAU,MAAM,CAAC,IAAI,GAAG,CAAC;QAC5E,MAAM,IAAI,GAAG,MAAM,GAAG,CAA2B;aACxC,OAAO;;;MAGd,CAAC,CAAC;QACJ,IAAI,CAAC,IAAI,CAAC,IAAI;YAAE,MAAM,SAAS,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC;QAC3D,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;IACtC,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,24 @@
1
+ import { z } from 'zod';
2
+ export declare const getStream: import("@opentabs-dev/plugin-sdk").ToolDefinition<z.ZodObject<{
3
+ login: z.ZodString;
4
+ }, z.core.$strip>, z.ZodObject<{
5
+ stream: z.ZodNullable<z.ZodObject<{
6
+ id: z.ZodString;
7
+ title: z.ZodString;
8
+ viewersCount: z.ZodNumber;
9
+ type: z.ZodString;
10
+ createdAt: z.ZodString;
11
+ broadcaster: z.ZodObject<{
12
+ id: z.ZodString;
13
+ login: z.ZodString;
14
+ displayName: z.ZodString;
15
+ profileImageURL: z.ZodString;
16
+ }, z.core.$strip>;
17
+ game: z.ZodObject<{
18
+ id: z.ZodString;
19
+ name: z.ZodString;
20
+ }, z.core.$strip>;
21
+ }, z.core.$strip>>;
22
+ isLive: z.ZodBoolean;
23
+ }, z.core.$strip>>;
24
+ //# sourceMappingURL=get-stream.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-stream.d.ts","sourceRoot":"","sources":["../../src/tools/get-stream.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;kBAmCpB,CAAC"}
@@ -0,0 +1,36 @@
1
+ import { defineTool, ToolError } from '@opentabs-dev/plugin-sdk';
2
+ import { z } from 'zod';
3
+ import { gql } from '../twitch-api.js';
4
+ import { streamSchema, mapStream } from './schemas.js';
5
+ export const getStream = defineTool({
6
+ name: 'get_stream',
7
+ displayName: 'Get Stream',
8
+ description: 'Get the current live stream for a channel by login name. Returns stream title, viewer count, game, and start time. Returns null stream if the channel is offline.',
9
+ summary: 'Get live stream info for a channel',
10
+ icon: 'radio',
11
+ group: 'Streams',
12
+ input: z.object({
13
+ login: z.string().describe('Channel login name (e.g., "shroud")'),
14
+ }),
15
+ output: z.object({
16
+ stream: streamSchema.nullable().describe('Current stream info, or null if offline'),
17
+ isLive: z.boolean().describe('Whether the channel is currently live'),
18
+ }),
19
+ handle: async (params) => {
20
+ const data = await gql(`{
21
+ user(login: "${params.login}") {
22
+ id
23
+ stream {
24
+ id title viewersCount type createdAt
25
+ broadcaster { id login displayName profileImageURL(width: 70) }
26
+ game { id name }
27
+ }
28
+ }
29
+ }`);
30
+ if (!data.user)
31
+ throw ToolError.notFound(`Channel "${params.login}" not found`);
32
+ const stream = data.user.stream ? mapStream(data.user.stream) : null;
33
+ return { stream, isLive: !!data.user.stream };
34
+ },
35
+ });
36
+ //# sourceMappingURL=get-stream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-stream.js","sourceRoot":"","sources":["../../src/tools/get-stream.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAGvD,MAAM,CAAC,MAAM,SAAS,GAAG,UAAU,CAAC;IAClC,IAAI,EAAE,YAAY;IAClB,WAAW,EAAE,YAAY;IACzB,WAAW,EACT,mKAAmK;IACrK,OAAO,EAAE,oCAAoC;IAC7C,IAAI,EAAE,OAAO;IACb,KAAK,EAAE,SAAS;IAChB,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC;QACd,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,qCAAqC,CAAC;KAClE,CAAC;IACF,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;QACf,MAAM,EAAE,YAAY,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,yCAAyC,CAAC;QACnF,MAAM,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,CAAC,uCAAuC,CAAC;KACtE,CAAC;IACF,MAAM,EAAE,KAAK,EAAC,MAAM,EAAC,EAAE;QACrB,MAAM,IAAI,GAAG,MAAM,GAAG,CAKnB;qBACc,MAAM,CAAC,KAAK;;;;;;;;MAQ3B,CAAC,CAAC;QACJ,IAAI,CAAC,IAAI,CAAC,IAAI;YAAE,MAAM,SAAS,CAAC,QAAQ,CAAC,YAAY,MAAM,CAAC,KAAK,aAAa,CAAC,CAAC;QAChF,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACrE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;IAChD,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,25 @@
1
+ import { z } from 'zod';
2
+ export declare const getStreamsByGame: import("@opentabs-dev/plugin-sdk").ToolDefinition<z.ZodObject<{
3
+ name: z.ZodOptional<z.ZodString>;
4
+ id: z.ZodOptional<z.ZodString>;
5
+ first: z.ZodOptional<z.ZodNumber>;
6
+ }, z.core.$strip>, z.ZodObject<{
7
+ streams: z.ZodArray<z.ZodObject<{
8
+ id: z.ZodString;
9
+ title: z.ZodString;
10
+ viewersCount: z.ZodNumber;
11
+ type: z.ZodString;
12
+ createdAt: z.ZodString;
13
+ broadcaster: z.ZodObject<{
14
+ id: z.ZodString;
15
+ login: z.ZodString;
16
+ displayName: z.ZodString;
17
+ profileImageURL: z.ZodString;
18
+ }, z.core.$strip>;
19
+ game: z.ZodObject<{
20
+ id: z.ZodString;
21
+ name: z.ZodString;
22
+ }, z.core.$strip>;
23
+ }, z.core.$strip>>;
24
+ }, z.core.$strip>>;
25
+ //# sourceMappingURL=get-streams-by-game.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-streams-by-game.d.ts","sourceRoot":"","sources":["../../src/tools/get-streams-by-game.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;kBAwC3B,CAAC"}
@@ -0,0 +1,44 @@
1
+ import { defineTool, ToolError } from '@opentabs-dev/plugin-sdk';
2
+ import { z } from 'zod';
3
+ import { gql } from '../twitch-api.js';
4
+ import { streamSchema, mapStream } from './schemas.js';
5
+ export const getStreamsByGame = defineTool({
6
+ name: 'get_streams_by_game',
7
+ displayName: 'Get Streams by Game',
8
+ description: 'Get live streams for a specific game/category. Provide either the game name (e.g., "Just Chatting") or game ID. Returns streams sorted by viewer count.',
9
+ summary: 'Get live streams for a game or category',
10
+ icon: 'radio',
11
+ group: 'Streams',
12
+ input: z.object({
13
+ name: z.string().optional().describe('Game name (e.g., "Just Chatting", "Fortnite")'),
14
+ id: z.string().optional().describe('Game ID (alternative to name)'),
15
+ first: z.number().int().min(1).max(25).optional().describe('Number of streams to return (default 10, max 25)'),
16
+ }),
17
+ output: z.object({ streams: z.array(streamSchema) }),
18
+ handle: async (params) => {
19
+ const first = params.first ?? 10;
20
+ const gameArg = params.id ? `id: "${params.id}"` : `name: "${params.name}"`;
21
+ if (!params.id && !params.name) {
22
+ throw ToolError.validation('Either name or id is required');
23
+ }
24
+ const data = await gql(`{
25
+ game(${gameArg}) {
26
+ streams(first: ${first}) {
27
+ edges {
28
+ node {
29
+ id title viewersCount type createdAt
30
+ broadcaster { id login displayName profileImageURL(width: 70) }
31
+ game { id name }
32
+ }
33
+ }
34
+ }
35
+ }
36
+ }`);
37
+ if (!data.game)
38
+ throw ToolError.notFound('Game not found');
39
+ return {
40
+ streams: (data.game.streams?.edges ?? []).map(e => mapStream(e.node)),
41
+ };
42
+ },
43
+ });
44
+ //# sourceMappingURL=get-streams-by-game.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-streams-by-game.js","sourceRoot":"","sources":["../../src/tools/get-streams-by-game.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAGvD,MAAM,CAAC,MAAM,gBAAgB,GAAG,UAAU,CAAC;IACzC,IAAI,EAAE,qBAAqB;IAC3B,WAAW,EAAE,qBAAqB;IAClC,WAAW,EACT,yJAAyJ;IAC3J,OAAO,EAAE,yCAAyC;IAClD,IAAI,EAAE,OAAO;IACb,KAAK,EAAE,SAAS;IAChB,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC;QACd,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,+CAA+C,CAAC;QACrF,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,+BAA+B,CAAC;QACnE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,kDAAkD,CAAC;KAC/G,CAAC;IACF,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE,CAAC;IACpD,MAAM,EAAE,KAAK,EAAC,MAAM,EAAC,EAAE;QACrB,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC;QACjC,MAAM,OAAO,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,UAAU,MAAM,CAAC,IAAI,GAAG,CAAC;QAC5E,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;YAC/B,MAAM,SAAS,CAAC,UAAU,CAAC,+BAA+B,CAAC,CAAC;QAC9D,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,GAAG,CAEnB;aACM,OAAO;yBACK,KAAK;;;;;;;;;;MAUxB,CAAC,CAAC;QACJ,IAAI,CAAC,IAAI,CAAC,IAAI;YAAE,MAAM,SAAS,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC;QAC3D,OAAO;YACL,OAAO,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;SACtE,CAAC;IACJ,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,14 @@
1
+ import { z } from 'zod';
2
+ export declare const getTopGames: import("@opentabs-dev/plugin-sdk").ToolDefinition<z.ZodObject<{
3
+ first: z.ZodOptional<z.ZodNumber>;
4
+ }, z.core.$strip>, z.ZodObject<{
5
+ games: z.ZodArray<z.ZodObject<{
6
+ id: z.ZodString;
7
+ name: z.ZodString;
8
+ displayName: z.ZodString;
9
+ viewersCount: z.ZodNumber;
10
+ broadcastersCount: z.ZodNumber;
11
+ boxArtURL: z.ZodString;
12
+ }, z.core.$strip>>;
13
+ }, z.core.$strip>>;
14
+ //# sourceMappingURL=get-top-games.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-top-games.d.ts","sourceRoot":"","sources":["../../src/tools/get-top-games.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,eAAO,MAAM,WAAW;;;;;;;;;;;kBA2BtB,CAAC"}
@@ -0,0 +1,30 @@
1
+ import { defineTool } from '@opentabs-dev/plugin-sdk';
2
+ import { z } from 'zod';
3
+ import { gql } from '../twitch-api.js';
4
+ import { gameSchema, mapGame } from './schemas.js';
5
+ export const getTopGames = defineTool({
6
+ name: 'get_top_games',
7
+ displayName: 'Get Top Games',
8
+ description: 'Get the top games/categories on Twitch sorted by viewer count. Returns game name, total viewers, number of broadcasters, and box art URL.',
9
+ summary: 'Get top games and categories by viewer count',
10
+ icon: 'gamepad-2',
11
+ group: 'Games',
12
+ input: z.object({
13
+ first: z.number().int().min(1).max(25).optional().describe('Number of games to return (default 10, max 25)'),
14
+ }),
15
+ output: z.object({ games: z.array(gameSchema) }),
16
+ handle: async (params) => {
17
+ const first = params.first ?? 10;
18
+ const data = await gql(`{
19
+ games(first: ${first}, options: { sort: VIEWER_COUNT }) {
20
+ edges {
21
+ node { id name displayName viewersCount broadcastersCount boxArtURL }
22
+ }
23
+ }
24
+ }`);
25
+ return {
26
+ games: (data.games?.edges ?? []).map(e => mapGame(e.node)),
27
+ };
28
+ },
29
+ });
30
+ //# sourceMappingURL=get-top-games.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-top-games.js","sourceRoot":"","sources":["../../src/tools/get-top-games.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAGnD,MAAM,CAAC,MAAM,WAAW,GAAG,UAAU,CAAC;IACpC,IAAI,EAAE,eAAe;IACrB,WAAW,EAAE,eAAe;IAC5B,WAAW,EACT,2IAA2I;IAC7I,OAAO,EAAE,8CAA8C;IACvD,IAAI,EAAE,WAAW;IACjB,KAAK,EAAE,OAAO;IACd,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC;QACd,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,gDAAgD,CAAC;KAC7G,CAAC;IACF,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC;IAChD,MAAM,EAAE,KAAK,EAAC,MAAM,EAAC,EAAE;QACrB,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC;QACjC,MAAM,IAAI,GAAG,MAAM,GAAG,CAEnB;qBACc,KAAK;;;;;MAKpB,CAAC,CAAC;QACJ,OAAO;YACL,KAAK,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;SAC3D,CAAC;IACJ,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,23 @@
1
+ import { z } from 'zod';
2
+ export declare const getTopStreams: import("@opentabs-dev/plugin-sdk").ToolDefinition<z.ZodObject<{
3
+ first: z.ZodOptional<z.ZodNumber>;
4
+ }, z.core.$strip>, z.ZodObject<{
5
+ streams: z.ZodArray<z.ZodObject<{
6
+ id: z.ZodString;
7
+ title: z.ZodString;
8
+ viewersCount: z.ZodNumber;
9
+ type: z.ZodString;
10
+ createdAt: z.ZodString;
11
+ broadcaster: z.ZodObject<{
12
+ id: z.ZodString;
13
+ login: z.ZodString;
14
+ displayName: z.ZodString;
15
+ profileImageURL: z.ZodString;
16
+ }, z.core.$strip>;
17
+ game: z.ZodObject<{
18
+ id: z.ZodString;
19
+ name: z.ZodString;
20
+ }, z.core.$strip>;
21
+ }, z.core.$strip>>;
22
+ }, z.core.$strip>>;
23
+ //# sourceMappingURL=get-top-streams.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-top-streams.d.ts","sourceRoot":"","sources":["../../src/tools/get-top-streams.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;kBA+BxB,CAAC"}
@@ -0,0 +1,34 @@
1
+ import { defineTool } from '@opentabs-dev/plugin-sdk';
2
+ import { z } from 'zod';
3
+ import { gql } from '../twitch-api.js';
4
+ import { streamSchema, mapStream } from './schemas.js';
5
+ export const getTopStreams = defineTool({
6
+ name: 'get_top_streams',
7
+ displayName: 'Get Top Streams',
8
+ description: 'Get the top live streams on Twitch sorted by viewer count. Returns stream title, viewer count, broadcaster info, and the game being played.',
9
+ summary: 'Get top live streams by viewer count',
10
+ icon: 'radio',
11
+ group: 'Streams',
12
+ input: z.object({
13
+ first: z.number().int().min(1).max(25).optional().describe('Number of streams to return (default 10, max 25)'),
14
+ }),
15
+ output: z.object({ streams: z.array(streamSchema) }),
16
+ handle: async (params) => {
17
+ const first = params.first ?? 10;
18
+ const data = await gql(`{
19
+ streams(first: ${first}) {
20
+ edges {
21
+ node {
22
+ id title viewersCount type createdAt
23
+ broadcaster { id login displayName profileImageURL(width: 70) }
24
+ game { id name }
25
+ }
26
+ }
27
+ }
28
+ }`);
29
+ return {
30
+ streams: (data.streams?.edges ?? []).map(e => mapStream(e.node)),
31
+ };
32
+ },
33
+ });
34
+ //# sourceMappingURL=get-top-streams.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-top-streams.js","sourceRoot":"","sources":["../../src/tools/get-top-streams.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAGvD,MAAM,CAAC,MAAM,aAAa,GAAG,UAAU,CAAC;IACtC,IAAI,EAAE,iBAAiB;IACvB,WAAW,EAAE,iBAAiB;IAC9B,WAAW,EACT,6IAA6I;IAC/I,OAAO,EAAE,sCAAsC;IAC/C,IAAI,EAAE,OAAO;IACb,KAAK,EAAE,SAAS;IAChB,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC;QACd,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,kDAAkD,CAAC;KAC/G,CAAC;IACF,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE,CAAC;IACpD,MAAM,EAAE,KAAK,EAAC,MAAM,EAAC,EAAE;QACrB,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC;QACjC,MAAM,IAAI,GAAG,MAAM,GAAG,CAEnB;uBACgB,KAAK;;;;;;;;;MAStB,CAAC,CAAC;QACJ,OAAO;YACL,OAAO,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;SACjE,CAAC;IACJ,CAAC;CACF,CAAC,CAAC"}