@jam-nodes/nodes 0.1.2 → 0.2.0

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 (93) hide show
  1. package/dist/ai/analyze-posts.d.ts +175 -0
  2. package/dist/ai/analyze-posts.d.ts.map +1 -0
  3. package/dist/ai/analyze-posts.js +172 -0
  4. package/dist/ai/analyze-posts.js.map +1 -0
  5. package/dist/ai/draft-emails.d.ts +45 -0
  6. package/dist/ai/draft-emails.d.ts.map +1 -0
  7. package/dist/ai/draft-emails.js +134 -0
  8. package/dist/ai/draft-emails.js.map +1 -0
  9. package/dist/ai/index.d.ts +4 -0
  10. package/dist/ai/index.d.ts.map +1 -0
  11. package/dist/ai/index.js +4 -0
  12. package/dist/ai/index.js.map +1 -0
  13. package/dist/ai/keyword-generator.d.ts +37 -0
  14. package/dist/ai/keyword-generator.d.ts.map +1 -0
  15. package/dist/ai/keyword-generator.js +124 -0
  16. package/dist/ai/keyword-generator.js.map +1 -0
  17. package/dist/index.d.ts +323 -0
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +29 -0
  20. package/dist/index.js.map +1 -1
  21. package/dist/integrations/apollo/index.d.ts +2 -0
  22. package/dist/integrations/apollo/index.d.ts.map +1 -0
  23. package/dist/integrations/apollo/index.js +2 -0
  24. package/dist/integrations/apollo/index.js.map +1 -0
  25. package/dist/integrations/apollo/search-contacts.d.ts +158 -0
  26. package/dist/integrations/apollo/search-contacts.d.ts.map +1 -0
  27. package/dist/integrations/apollo/search-contacts.js +161 -0
  28. package/dist/integrations/apollo/search-contacts.js.map +1 -0
  29. package/dist/integrations/dataforseo/index.d.ts +3 -0
  30. package/dist/integrations/dataforseo/index.d.ts.map +1 -0
  31. package/dist/integrations/dataforseo/index.js +3 -0
  32. package/dist/integrations/dataforseo/index.js.map +1 -0
  33. package/dist/integrations/dataforseo/keyword-research.d.ts +96 -0
  34. package/dist/integrations/dataforseo/keyword-research.d.ts.map +1 -0
  35. package/dist/integrations/dataforseo/keyword-research.js +115 -0
  36. package/dist/integrations/dataforseo/keyword-research.js.map +1 -0
  37. package/dist/integrations/dataforseo/seo-audit.d.ts +257 -0
  38. package/dist/integrations/dataforseo/seo-audit.d.ts.map +1 -0
  39. package/dist/integrations/dataforseo/seo-audit.js +266 -0
  40. package/dist/integrations/dataforseo/seo-audit.js.map +1 -0
  41. package/dist/integrations/index.d.ts +5 -0
  42. package/dist/integrations/index.d.ts.map +1 -0
  43. package/dist/integrations/index.js +9 -0
  44. package/dist/integrations/index.js.map +1 -0
  45. package/dist/integrations/openai/index.d.ts +2 -0
  46. package/dist/integrations/openai/index.d.ts.map +1 -0
  47. package/dist/integrations/openai/index.js +2 -0
  48. package/dist/integrations/openai/index.js.map +1 -0
  49. package/dist/integrations/openai/sora-video.d.ts +89 -0
  50. package/dist/integrations/openai/sora-video.d.ts.map +1 -0
  51. package/dist/integrations/openai/sora-video.js +93 -0
  52. package/dist/integrations/openai/sora-video.js.map +1 -0
  53. package/dist/integrations/social/index.d.ts +4 -0
  54. package/dist/integrations/social/index.d.ts.map +1 -0
  55. package/dist/integrations/social/index.js +4 -0
  56. package/dist/integrations/social/index.js.map +1 -0
  57. package/dist/integrations/social/linkedin-monitor.d.ts +166 -0
  58. package/dist/integrations/social/linkedin-monitor.d.ts.map +1 -0
  59. package/dist/integrations/social/linkedin-monitor.js +167 -0
  60. package/dist/integrations/social/linkedin-monitor.js.map +1 -0
  61. package/dist/integrations/social/reddit-monitor.d.ts +177 -0
  62. package/dist/integrations/social/reddit-monitor.d.ts.map +1 -0
  63. package/dist/integrations/social/reddit-monitor.js +162 -0
  64. package/dist/integrations/social/reddit-monitor.js.map +1 -0
  65. package/dist/integrations/social/twitter-monitor.d.ts +186 -0
  66. package/dist/integrations/social/twitter-monitor.d.ts.map +1 -0
  67. package/dist/integrations/social/twitter-monitor.js +174 -0
  68. package/dist/integrations/social/twitter-monitor.js.map +1 -0
  69. package/dist/prompts/analyze-posts.d.ts +31 -0
  70. package/dist/prompts/analyze-posts.d.ts.map +1 -0
  71. package/dist/prompts/analyze-posts.js +87 -0
  72. package/dist/prompts/analyze-posts.js.map +1 -0
  73. package/dist/prompts/draft-emails.d.ts +19 -0
  74. package/dist/prompts/draft-emails.d.ts.map +1 -0
  75. package/dist/prompts/draft-emails.js +117 -0
  76. package/dist/prompts/draft-emails.js.map +1 -0
  77. package/dist/prompts/index.d.ts +4 -0
  78. package/dist/prompts/index.d.ts.map +1 -0
  79. package/dist/prompts/index.js +7 -0
  80. package/dist/prompts/index.js.map +1 -0
  81. package/dist/prompts/keyword-generator.d.ts +17 -0
  82. package/dist/prompts/keyword-generator.d.ts.map +1 -0
  83. package/dist/prompts/keyword-generator.js +61 -0
  84. package/dist/prompts/keyword-generator.js.map +1 -0
  85. package/dist/schemas/ai.d.ts +1212 -0
  86. package/dist/schemas/ai.d.ts.map +1 -0
  87. package/dist/schemas/ai.js +119 -0
  88. package/dist/schemas/ai.js.map +1 -0
  89. package/dist/schemas/index.d.ts +2 -0
  90. package/dist/schemas/index.d.ts.map +1 -0
  91. package/dist/schemas/index.js +9 -0
  92. package/dist/schemas/index.js.map +1 -0
  93. package/package.json +14 -6
@@ -0,0 +1,162 @@
1
+ import { z } from 'zod';
2
+ import { defineNode } from '@jam-nodes/core';
3
+ // =============================================================================
4
+ // Schemas
5
+ // =============================================================================
6
+ export const RedditMonitorInputSchema = z.object({
7
+ /** Keywords to search for */
8
+ keywords: z.array(z.string()),
9
+ /** Time filter for search results */
10
+ timeFilter: z.enum(['hour', 'day', 'week', 'month', 'year', 'all']).optional().default('day'),
11
+ /** Sort order for results */
12
+ sortBy: z.enum(['relevance', 'hot', 'top', 'new', 'comments']).optional().default('new'),
13
+ /** Maximum number of results to return */
14
+ maxResults: z.number().optional().default(50),
15
+ });
16
+ export const RedditMonitorOutputSchema = z.object({
17
+ posts: z.array(z.object({
18
+ id: z.string(),
19
+ platform: z.literal('reddit'),
20
+ url: z.string(),
21
+ text: z.string(),
22
+ title: z.string(),
23
+ authorName: z.string(),
24
+ authorHandle: z.string(),
25
+ authorUrl: z.string(),
26
+ subreddit: z.string(),
27
+ engagement: z.object({
28
+ likes: z.number(),
29
+ comments: z.number(),
30
+ shares: z.number(),
31
+ }),
32
+ upvoteRatio: z.number(),
33
+ postedAt: z.string(),
34
+ })),
35
+ totalFound: z.number(),
36
+ subredditsSearched: z.array(z.string()),
37
+ });
38
+ // =============================================================================
39
+ // Reddit API Helper
40
+ // =============================================================================
41
+ /**
42
+ * Search Reddit using the public search.json endpoint.
43
+ * No authentication required.
44
+ */
45
+ async function searchReddit(query, options = {}) {
46
+ const { sort = 'new', time = 'day', limit = 50 } = options;
47
+ const params = new URLSearchParams({
48
+ q: query,
49
+ type: 'link',
50
+ sort,
51
+ t: time,
52
+ limit: String(Math.min(limit, 100)),
53
+ restrict_sr: 'off',
54
+ });
55
+ const url = `https://www.reddit.com/search.json?${params.toString()}`;
56
+ const response = await fetch(url, {
57
+ headers: {
58
+ 'User-Agent': 'Mozilla/5.0 (compatible; JamNodes/1.0)',
59
+ },
60
+ });
61
+ if (!response.ok) {
62
+ throw new Error(`Reddit API error: ${response.status} ${response.statusText}`);
63
+ }
64
+ return response.json();
65
+ }
66
+ // =============================================================================
67
+ // Node Definition
68
+ // =============================================================================
69
+ /**
70
+ * Reddit Monitor Node
71
+ *
72
+ * Searches Reddit for posts matching keywords using the public search.json API.
73
+ * No authentication required - uses public Reddit API.
74
+ *
75
+ * @example
76
+ * ```typescript
77
+ * const result = await redditMonitorNode.executor({
78
+ * keywords: ['typescript', 'nodejs'],
79
+ * timeFilter: 'week',
80
+ * maxResults: 25
81
+ * }, context);
82
+ * // Returns: { posts: [...], totalFound: 25, subredditsSearched: ['all'] }
83
+ * ```
84
+ */
85
+ export const redditMonitorNode = defineNode({
86
+ type: 'reddit_monitor',
87
+ name: 'Reddit Monitor',
88
+ description: 'Search Reddit for posts matching keywords across all subreddits',
89
+ category: 'integration',
90
+ inputSchema: RedditMonitorInputSchema,
91
+ outputSchema: RedditMonitorOutputSchema,
92
+ estimatedDuration: 20,
93
+ capabilities: {
94
+ supportsRerun: true,
95
+ },
96
+ executor: async (input, context) => {
97
+ try {
98
+ const allPosts = [];
99
+ // Build search query with proper quoting for multi-word keywords
100
+ const query = input.keywords
101
+ .map((k) => (k.includes(' ') ? `"${k}"` : k))
102
+ .join(' OR ');
103
+ const maxResults = Math.min(input.maxResults || 50, 100);
104
+ // Search Reddit
105
+ const response = await searchReddit(query, {
106
+ sort: input.sortBy || 'new',
107
+ time: input.timeFilter || 'day',
108
+ limit: maxResults,
109
+ });
110
+ // Transform to unified format
111
+ for (const post of response.data.children) {
112
+ const submission = post.data;
113
+ allPosts.push({
114
+ id: submission.id,
115
+ platform: 'reddit',
116
+ url: `https://reddit.com${submission.permalink}`,
117
+ text: submission.selftext || '',
118
+ title: submission.title,
119
+ authorName: submission.author || '[deleted]',
120
+ authorHandle: submission.author || '[deleted]',
121
+ authorUrl: submission.author && submission.author !== '[deleted]'
122
+ ? `https://reddit.com/u/${submission.author}`
123
+ : '',
124
+ subreddit: submission.subreddit,
125
+ engagement: {
126
+ likes: submission.score,
127
+ comments: submission.num_comments,
128
+ shares: submission.num_crossposts || 0,
129
+ },
130
+ upvoteRatio: submission.upvote_ratio,
131
+ postedAt: new Date(submission.created_utc * 1000).toISOString(),
132
+ });
133
+ }
134
+ // Sort by recency
135
+ allPosts.sort((a, b) => new Date(b.postedAt).getTime() - new Date(a.postedAt).getTime());
136
+ // Optional: send notification if service available
137
+ if (context.services?.notifications && allPosts.length > 0) {
138
+ await context.services.notifications.send({
139
+ userId: context.userId,
140
+ title: 'Reddit Monitor Complete',
141
+ message: `Found ${allPosts.length} Reddit posts`,
142
+ data: { posts: allPosts.slice(0, 5) },
143
+ });
144
+ }
145
+ return {
146
+ success: true,
147
+ output: {
148
+ posts: allPosts,
149
+ totalFound: allPosts.length,
150
+ subredditsSearched: ['all'],
151
+ },
152
+ };
153
+ }
154
+ catch (error) {
155
+ return {
156
+ success: false,
157
+ error: error instanceof Error ? error.message : 'Failed to monitor Reddit',
158
+ };
159
+ }
160
+ },
161
+ });
162
+ //# sourceMappingURL=reddit-monitor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reddit-monitor.js","sourceRoot":"","sources":["../../../src/integrations/social/reddit-monitor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,186 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Twitter/X post in unified social format
4
+ */
5
+ export interface TwitterPost {
6
+ id: string;
7
+ platform: 'twitter';
8
+ url: string;
9
+ text: string;
10
+ authorName: string;
11
+ authorHandle: string;
12
+ authorUrl: string;
13
+ authorFollowers: number;
14
+ engagement: {
15
+ likes: number;
16
+ comments: number;
17
+ shares: number;
18
+ views: number;
19
+ };
20
+ postedAt: string;
21
+ }
22
+ export declare const TwitterMonitorInputSchema: z.ZodObject<{
23
+ /** Keywords to search for */
24
+ keywords: z.ZodArray<z.ZodString, "many">;
25
+ /** Exclude retweets from results */
26
+ excludeRetweets: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
27
+ /** Minimum likes filter */
28
+ minLikes: z.ZodOptional<z.ZodNumber>;
29
+ /** Maximum number of results */
30
+ maxResults: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
31
+ /** Language filter (e.g., 'en') */
32
+ lang: z.ZodOptional<z.ZodString>;
33
+ /** Search tweets from last N days */
34
+ sinceDays: z.ZodOptional<z.ZodNumber>;
35
+ }, "strip", z.ZodTypeAny, {
36
+ keywords: string[];
37
+ maxResults: number;
38
+ excludeRetweets: boolean;
39
+ minLikes?: number | undefined;
40
+ lang?: string | undefined;
41
+ sinceDays?: number | undefined;
42
+ }, {
43
+ keywords: string[];
44
+ maxResults?: number | undefined;
45
+ excludeRetweets?: boolean | undefined;
46
+ minLikes?: number | undefined;
47
+ lang?: string | undefined;
48
+ sinceDays?: number | undefined;
49
+ }>;
50
+ export type TwitterMonitorInput = z.infer<typeof TwitterMonitorInputSchema>;
51
+ export declare const TwitterMonitorOutputSchema: z.ZodObject<{
52
+ posts: z.ZodArray<z.ZodObject<{
53
+ id: z.ZodString;
54
+ platform: z.ZodLiteral<"twitter">;
55
+ url: z.ZodString;
56
+ text: z.ZodString;
57
+ authorName: z.ZodString;
58
+ authorHandle: z.ZodString;
59
+ authorUrl: z.ZodString;
60
+ authorFollowers: z.ZodNumber;
61
+ engagement: z.ZodObject<{
62
+ likes: z.ZodNumber;
63
+ comments: z.ZodNumber;
64
+ shares: z.ZodNumber;
65
+ views: z.ZodNumber;
66
+ }, "strip", z.ZodTypeAny, {
67
+ comments: number;
68
+ likes: number;
69
+ shares: number;
70
+ views: number;
71
+ }, {
72
+ comments: number;
73
+ likes: number;
74
+ shares: number;
75
+ views: number;
76
+ }>;
77
+ postedAt: z.ZodString;
78
+ }, "strip", z.ZodTypeAny, {
79
+ url: string;
80
+ id: string;
81
+ platform: "twitter";
82
+ text: string;
83
+ authorName: string;
84
+ authorHandle: string;
85
+ authorUrl: string;
86
+ engagement: {
87
+ comments: number;
88
+ likes: number;
89
+ shares: number;
90
+ views: number;
91
+ };
92
+ postedAt: string;
93
+ authorFollowers: number;
94
+ }, {
95
+ url: string;
96
+ id: string;
97
+ platform: "twitter";
98
+ text: string;
99
+ authorName: string;
100
+ authorHandle: string;
101
+ authorUrl: string;
102
+ engagement: {
103
+ comments: number;
104
+ likes: number;
105
+ shares: number;
106
+ views: number;
107
+ };
108
+ postedAt: string;
109
+ authorFollowers: number;
110
+ }>, "many">;
111
+ totalFound: z.ZodNumber;
112
+ hasMore: z.ZodBoolean;
113
+ cursor: z.ZodOptional<z.ZodString>;
114
+ }, "strip", z.ZodTypeAny, {
115
+ posts: {
116
+ url: string;
117
+ id: string;
118
+ platform: "twitter";
119
+ text: string;
120
+ authorName: string;
121
+ authorHandle: string;
122
+ authorUrl: string;
123
+ engagement: {
124
+ comments: number;
125
+ likes: number;
126
+ shares: number;
127
+ views: number;
128
+ };
129
+ postedAt: string;
130
+ authorFollowers: number;
131
+ }[];
132
+ totalFound: number;
133
+ hasMore: boolean;
134
+ cursor?: string | undefined;
135
+ }, {
136
+ posts: {
137
+ url: string;
138
+ id: string;
139
+ platform: "twitter";
140
+ text: string;
141
+ authorName: string;
142
+ authorHandle: string;
143
+ authorUrl: string;
144
+ engagement: {
145
+ comments: number;
146
+ likes: number;
147
+ shares: number;
148
+ views: number;
149
+ };
150
+ postedAt: string;
151
+ authorFollowers: number;
152
+ }[];
153
+ totalFound: number;
154
+ hasMore: boolean;
155
+ cursor?: string | undefined;
156
+ }>;
157
+ export type TwitterMonitorOutput = z.infer<typeof TwitterMonitorOutputSchema>;
158
+ /**
159
+ * Twitter Monitor Node
160
+ *
161
+ * Searches Twitter/X for posts matching keywords.
162
+ * Requires `context.services.twitter` to be provided by the host application.
163
+ *
164
+ * @example
165
+ * ```typescript
166
+ * const result = await twitterMonitorNode.executor({
167
+ * keywords: ['typescript', 'nodejs'],
168
+ * excludeRetweets: true,
169
+ * maxResults: 25,
170
+ * sinceDays: 7
171
+ * }, context);
172
+ * ```
173
+ */
174
+ export declare const twitterMonitorNode: import("@jam-nodes/core").NodeDefinition<{
175
+ keywords: string[];
176
+ maxResults?: number | undefined;
177
+ excludeRetweets?: boolean | undefined;
178
+ minLikes?: number | undefined;
179
+ lang?: string | undefined;
180
+ sinceDays?: number | undefined;
181
+ }, {
182
+ posts: TwitterPost[];
183
+ totalFound: number;
184
+ hasMore: boolean;
185
+ }>;
186
+ //# sourceMappingURL=twitter-monitor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"twitter-monitor.d.ts","sourceRoot":"","sources":["../../../src/integrations/social/twitter-monitor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAOxB;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,SAAS,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE;QACV,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;IACF,QAAQ,EAAE,MAAM,CAAC;CAClB;AAMD,eAAO,MAAM,yBAAyB;IACpC,6BAA6B;;IAE7B,oCAAoC;;IAEpC,2BAA2B;;IAE3B,gCAAgC;;IAEhC,mCAAmC;;IAEnC,qCAAqC;;;;;;;;;;;;;;;;EAErC,CAAC;AAEH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAE5E,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAqBrC,CAAC;AAEH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAgD9E;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,kBAAkB;;;;;;;;;;;EA6F7B,CAAC"}
@@ -0,0 +1,174 @@
1
+ import { z } from 'zod';
2
+ import { defineNode } from '@jam-nodes/core';
3
+ // =============================================================================
4
+ // Schemas
5
+ // =============================================================================
6
+ export const TwitterMonitorInputSchema = z.object({
7
+ /** Keywords to search for */
8
+ keywords: z.array(z.string()),
9
+ /** Exclude retweets from results */
10
+ excludeRetweets: z.boolean().optional().default(true),
11
+ /** Minimum likes filter */
12
+ minLikes: z.number().optional(),
13
+ /** Maximum number of results */
14
+ maxResults: z.number().optional().default(50),
15
+ /** Language filter (e.g., 'en') */
16
+ lang: z.string().optional(),
17
+ /** Search tweets from last N days */
18
+ sinceDays: z.number().optional(),
19
+ });
20
+ export const TwitterMonitorOutputSchema = z.object({
21
+ posts: z.array(z.object({
22
+ id: z.string(),
23
+ platform: z.literal('twitter'),
24
+ url: z.string(),
25
+ text: z.string(),
26
+ authorName: z.string(),
27
+ authorHandle: z.string(),
28
+ authorUrl: z.string(),
29
+ authorFollowers: z.number(),
30
+ engagement: z.object({
31
+ likes: z.number(),
32
+ comments: z.number(),
33
+ shares: z.number(),
34
+ views: z.number(),
35
+ }),
36
+ postedAt: z.string(),
37
+ })),
38
+ totalFound: z.number(),
39
+ hasMore: z.boolean(),
40
+ cursor: z.string().optional(),
41
+ });
42
+ // =============================================================================
43
+ // Query Builder
44
+ // =============================================================================
45
+ /**
46
+ * Build Twitter search query with proper syntax
47
+ */
48
+ function buildTwitterSearchQuery(keywords, options = {}) {
49
+ // Join keywords with OR
50
+ const keywordQuery = keywords
51
+ .map((k) => (k.includes(' ') ? `"${k}"` : k))
52
+ .join(' OR ');
53
+ let query = `(${keywordQuery})`;
54
+ if (options.excludeRetweets) {
55
+ query += ' -is:retweet';
56
+ }
57
+ if (options.minLikes) {
58
+ query += ` min_faves:${options.minLikes}`;
59
+ }
60
+ if (options.since) {
61
+ query += ` since:${options.since}`;
62
+ }
63
+ if (options.lang) {
64
+ query += ` lang:${options.lang}`;
65
+ }
66
+ return query;
67
+ }
68
+ // =============================================================================
69
+ // Node Definition
70
+ // =============================================================================
71
+ /**
72
+ * Twitter Monitor Node
73
+ *
74
+ * Searches Twitter/X for posts matching keywords.
75
+ * Requires `context.services.twitter` to be provided by the host application.
76
+ *
77
+ * @example
78
+ * ```typescript
79
+ * const result = await twitterMonitorNode.executor({
80
+ * keywords: ['typescript', 'nodejs'],
81
+ * excludeRetweets: true,
82
+ * maxResults: 25,
83
+ * sinceDays: 7
84
+ * }, context);
85
+ * ```
86
+ */
87
+ export const twitterMonitorNode = defineNode({
88
+ type: 'twitter_monitor',
89
+ name: 'Twitter Monitor',
90
+ description: 'Search Twitter/X for posts matching keywords',
91
+ category: 'integration',
92
+ inputSchema: TwitterMonitorInputSchema,
93
+ outputSchema: TwitterMonitorOutputSchema,
94
+ estimatedDuration: 15,
95
+ capabilities: {
96
+ supportsRerun: true,
97
+ },
98
+ executor: async (input, context) => {
99
+ try {
100
+ if (!input.keywords || input.keywords.length === 0) {
101
+ return {
102
+ success: false,
103
+ error: 'No keywords provided for Twitter search',
104
+ };
105
+ }
106
+ // Require Twitter service
107
+ if (!context.services?.twitter) {
108
+ return {
109
+ success: false,
110
+ error: 'Twitter service not configured. Please provide context.services.twitter.',
111
+ };
112
+ }
113
+ // Build the search query
114
+ const sinceDate = input.sinceDays
115
+ ? new Date(Date.now() - input.sinceDays * 24 * 60 * 60 * 1000)
116
+ .toISOString()
117
+ .split('T')[0]
118
+ : undefined;
119
+ const query = buildTwitterSearchQuery(input.keywords, {
120
+ excludeRetweets: input.excludeRetweets ?? true,
121
+ minLikes: input.minLikes,
122
+ since: sinceDate,
123
+ lang: input.lang,
124
+ });
125
+ // Search tweets
126
+ const tweets = await context.services.twitter.searchTweets(query, {
127
+ maxResults: input.maxResults || 50,
128
+ sinceDays: input.sinceDays,
129
+ });
130
+ // Transform to unified format
131
+ const posts = tweets.map((tweet) => ({
132
+ id: tweet.id,
133
+ platform: 'twitter',
134
+ url: tweet.url,
135
+ text: tweet.text,
136
+ authorName: tweet.authorName,
137
+ authorHandle: tweet.authorHandle,
138
+ authorUrl: `https://twitter.com/${tweet.authorHandle}`,
139
+ authorFollowers: tweet.authorFollowers,
140
+ engagement: {
141
+ likes: tweet.likes,
142
+ comments: tweet.replies,
143
+ shares: tweet.retweets,
144
+ views: tweet.views || 0,
145
+ },
146
+ postedAt: tweet.createdAt,
147
+ }));
148
+ // Optional: send notification if service available
149
+ if (context.services?.notifications && posts.length > 0) {
150
+ await context.services.notifications.send({
151
+ userId: context.userId,
152
+ title: 'Twitter Monitor Complete',
153
+ message: `Found ${posts.length} tweets`,
154
+ data: { posts: posts.slice(0, 5) },
155
+ });
156
+ }
157
+ return {
158
+ success: true,
159
+ output: {
160
+ posts,
161
+ totalFound: posts.length,
162
+ hasMore: false, // Simplified - pagination handled by service
163
+ },
164
+ };
165
+ }
166
+ catch (error) {
167
+ return {
168
+ success: false,
169
+ error: error instanceof Error ? error.message : 'Failed to monitor Twitter',
170
+ };
171
+ }
172
+ },
173
+ });
174
+ //# sourceMappingURL=twitter-monitor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"twitter-monitor.js","sourceRoot":"","sources":["../../../src/integrations/social/twitter-monitor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import type { SocialPost } from '../schemas/ai';
2
+ /**
3
+ * Prompt for analyzing social media posts for relevance, sentiment, and urgency.
4
+ *
5
+ * Template variables:
6
+ * - {{TOPIC}}: The monitoring topic
7
+ * - {{INTENT}}: What the user is looking for
8
+ * - {{POSTS_JSON}}: JSON array of posts to analyze
9
+ */
10
+ export declare const ANALYSIS_PROMPT = "You are analyzing social media posts to find ones relevant to a user's monitoring topic.\n\n<user_topic>\n{{TOPIC}}\n</user_topic>\n\n<user_intent>\n{{INTENT}}\n</user_intent>\n\nAnalyze each post and determine:\n1. **Relevance Score (0-100)**: How relevant is this post to what the user is looking for?\n2. **Sentiment**: Is the post positive, negative, or neutral about the topic?\n3. **Is Complaint**: Is this post a complaint or expressing frustration?\n4. **Urgency Level**:\n - HIGH: Urgent issue, direct complaint, someone actively looking for alternatives\n - MEDIUM: General discussion, mild frustration, asking questions\n - LOW: Casual mention, positive review, tangentially related\n5. **Summary**: 2-3 sentence summary of what this post is about\n6. **Matched Keywords**: Which keywords/concepts from the topic match this post\n\n<posts>\n{{POSTS_JSON}}\n</posts>\n\nRespond with a JSON array of analyzed posts:\n[\n {\n \"id\": \"post_id\",\n \"relevanceScore\": 85,\n \"sentiment\": \"negative\",\n \"isComplaint\": true,\n \"urgencyLevel\": \"high\",\n \"aiSummary\": \"User is frustrated with...\",\n \"matchedKeywords\": [\"keyword1\", \"keyword2\"]\n }\n]\n\nOnly include posts with relevance score >= 30. Filter out irrelevant posts entirely.";
11
+ /**
12
+ * Build the complete analysis prompt for a batch of posts.
13
+ */
14
+ export declare function buildAnalysisPrompt(topic: string, userIntent: string, posts: SocialPost[]): string;
15
+ /**
16
+ * Normalize sentiment values from Claude response.
17
+ */
18
+ export declare function normalizeSentiment(s: string): 'positive' | 'negative' | 'neutral';
19
+ /**
20
+ * Normalize urgency level values from Claude response.
21
+ */
22
+ export declare function normalizeUrgency(u: string): 'low' | 'medium' | 'high';
23
+ /**
24
+ * Minimum relevance score to include in results.
25
+ */
26
+ export declare const MIN_RELEVANCE_SCORE = 30;
27
+ /**
28
+ * Batch size for processing posts through Claude.
29
+ */
30
+ export declare const ANALYSIS_BATCH_SIZE = 20;
31
+ //# sourceMappingURL=analyze-posts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyze-posts.d.ts","sourceRoot":"","sources":["../../src/prompts/analyze-posts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,gxCAsCyD,CAAC;AAEtF;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,UAAU,EAAE,GAClB,MAAM,CAKR;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,MAAM,GAAG,UAAU,GAAG,UAAU,GAAG,SAAS,CAKjF;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAKrE;AAED;;GAEG;AACH,eAAO,MAAM,mBAAmB,KAAK,CAAC;AAEtC;;GAEG;AACH,eAAO,MAAM,mBAAmB,KAAK,CAAC"}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Prompt for analyzing social media posts for relevance, sentiment, and urgency.
3
+ *
4
+ * Template variables:
5
+ * - {{TOPIC}}: The monitoring topic
6
+ * - {{INTENT}}: What the user is looking for
7
+ * - {{POSTS_JSON}}: JSON array of posts to analyze
8
+ */
9
+ export const ANALYSIS_PROMPT = `You are analyzing social media posts to find ones relevant to a user's monitoring topic.
10
+
11
+ <user_topic>
12
+ {{TOPIC}}
13
+ </user_topic>
14
+
15
+ <user_intent>
16
+ {{INTENT}}
17
+ </user_intent>
18
+
19
+ Analyze each post and determine:
20
+ 1. **Relevance Score (0-100)**: How relevant is this post to what the user is looking for?
21
+ 2. **Sentiment**: Is the post positive, negative, or neutral about the topic?
22
+ 3. **Is Complaint**: Is this post a complaint or expressing frustration?
23
+ 4. **Urgency Level**:
24
+ - HIGH: Urgent issue, direct complaint, someone actively looking for alternatives
25
+ - MEDIUM: General discussion, mild frustration, asking questions
26
+ - LOW: Casual mention, positive review, tangentially related
27
+ 5. **Summary**: 2-3 sentence summary of what this post is about
28
+ 6. **Matched Keywords**: Which keywords/concepts from the topic match this post
29
+
30
+ <posts>
31
+ {{POSTS_JSON}}
32
+ </posts>
33
+
34
+ Respond with a JSON array of analyzed posts:
35
+ [
36
+ {
37
+ "id": "post_id",
38
+ "relevanceScore": 85,
39
+ "sentiment": "negative",
40
+ "isComplaint": true,
41
+ "urgencyLevel": "high",
42
+ "aiSummary": "User is frustrated with...",
43
+ "matchedKeywords": ["keyword1", "keyword2"]
44
+ }
45
+ ]
46
+
47
+ Only include posts with relevance score >= 30. Filter out irrelevant posts entirely.`;
48
+ /**
49
+ * Build the complete analysis prompt for a batch of posts.
50
+ */
51
+ export function buildAnalysisPrompt(topic, userIntent, posts) {
52
+ return ANALYSIS_PROMPT
53
+ .replace('{{TOPIC}}', topic)
54
+ .replace('{{INTENT}}', userIntent)
55
+ .replace('{{POSTS_JSON}}', JSON.stringify(posts, null, 2));
56
+ }
57
+ /**
58
+ * Normalize sentiment values from Claude response.
59
+ */
60
+ export function normalizeSentiment(s) {
61
+ const lower = String(s).toLowerCase().trim();
62
+ if (lower === 'positive')
63
+ return 'positive';
64
+ if (lower === 'negative')
65
+ return 'negative';
66
+ return 'neutral';
67
+ }
68
+ /**
69
+ * Normalize urgency level values from Claude response.
70
+ */
71
+ export function normalizeUrgency(u) {
72
+ const lower = String(u).toLowerCase().trim();
73
+ if (lower === 'high')
74
+ return 'high';
75
+ if (lower === 'medium')
76
+ return 'medium';
77
+ return 'low';
78
+ }
79
+ /**
80
+ * Minimum relevance score to include in results.
81
+ */
82
+ export const MIN_RELEVANCE_SCORE = 30;
83
+ /**
84
+ * Batch size for processing posts through Claude.
85
+ */
86
+ export const ANALYSIS_BATCH_SIZE = 20;
87
+ //# sourceMappingURL=analyze-posts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyze-posts.js","sourceRoot":"","sources":["../../src/prompts/analyze-posts.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qFAsCsD,CAAC;AAEtF;;GAEG;AACH,MAAM,UAAU,mBAAmB,CACjC,KAAa,EACb,UAAkB,EAClB,KAAmB;IAEnB,OAAO,eAAe;SACnB,OAAO,CAAC,WAAW,EAAE,KAAK,CAAC;SAC3B,OAAO,CAAC,YAAY,EAAE,UAAU,CAAC;SACjC,OAAO,CAAC,gBAAgB,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAC/D,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,CAAS;IAC1C,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC;IAC7C,IAAI,KAAK,KAAK,UAAU;QAAE,OAAO,UAAU,CAAC;IAC5C,IAAI,KAAK,KAAK,UAAU;QAAE,OAAO,UAAU,CAAC;IAC5C,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,CAAS;IACxC,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC;IAC7C,IAAI,KAAK,KAAK,MAAM;QAAE,OAAO,MAAM,CAAC;IACpC,IAAI,KAAK,KAAK,QAAQ;QAAE,OAAO,QAAQ,CAAC;IACxC,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,EAAE,CAAC;AAEtC;;GAEG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,EAAE,CAAC"}