diff --git a/package-lock.json b/package-lock.json index 9b3d662..790aab4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -395,6 +395,7 @@ "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz", "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==", "license": "MIT", + "peer": true, "dependencies": { "accepts": "^2.0.0", "body-parser": "^2.2.1", @@ -1158,6 +1159,7 @@ "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz", "integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==", "license": "MIT", + "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } diff --git a/src/services/grok.ts b/src/services/grok.ts index 0fd6b2c..37de92b 100644 --- a/src/services/grok.ts +++ b/src/services/grok.ts @@ -58,7 +58,10 @@ export class GrokService { throw new Error(`Grok API error: ${response.status}`); } - const data: any = await response.json(); + const data = await response.json() as { choices?: Array<{ message?: { content?: string } }> }; + if (!Array.isArray(data.choices)) { + throw new Error('Unexpected Grok API response: missing choices array'); + } const analysisText = data.choices[0]?.message?.content || ''; // Use the root post ID from the thread, not the mention text @@ -113,9 +116,14 @@ export class GrokService { } const parsed = JSON.parse(jsonMatch[0]); - + + const validActions: AgentAction['type'][] = ['reply', 'search', 'generate', 'analyze']; + const actionType: AgentAction['type'] = validActions.includes(parsed.action) + ? parsed.action + : 'analyze'; + const action: AgentAction = { - type: parsed.action as any, + type: actionType, target_post_id: mentionPostId, content: parsed.content, query: parsed.action === 'search' ? parsed.content : undefined, diff --git a/src/services/xapi.ts b/src/services/xapi.ts index 1f62056..77e475b 100644 --- a/src/services/xapi.ts +++ b/src/services/xapi.ts @@ -44,10 +44,13 @@ export class XAPIClient { throw new Error('Failed to get user ID from response'); } - const mentionsResponse = await this.makeXAPIRequest( - `https://api.twitter.com/2/users/${userId}/mentions?max_results=10&expansions=author_id&tweet.fields=created_at,conversation_id,in_reply_to_user_id,referenced_tweets`, - 'GET' - ); + const params = new URLSearchParams({ + max_results: '10', + expansions: 'author_id', + 'tweet.fields': 'created_at,conversation_id,in_reply_to_user_id,referenced_tweets', + }); + const mentionsUrl = `https://api.twitter.com/2/users/${userId}/mentions?${params.toString()}`; + const mentionsResponse = await this.makeXAPIRequest(mentionsUrl, 'GET'); if (!mentionsResponse || !Array.isArray(mentionsResponse.data)) { console.warn('Invalid response from X API (mentions)'); @@ -77,7 +80,11 @@ export class XAPIClient { 'GET' ); - return this.parseThread(response.data || []); + if (!Array.isArray(response.data)) { + console.warn('Unexpected response shape from X API (thread): data is not an array'); + return null; + } + return this.parseThread(response.data); } catch (error) { console.error('Error fetching thread:', error); return null;