Skip to content

Commit 70cebc2

Browse files
fix: implement PR #26 review feedback - type safety, URL params, Array.isArray guard, safe iterators, chronological processing
Co-authored-by: groupthinking <154503486+groupthinking@users.noreply.github.com>
1 parent 5391d03 commit 70cebc2

File tree

4 files changed

+22
-7
lines changed

4 files changed

+22
-7
lines changed

src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { XMCPServer } from './mcp/server.js';
1010
async function main() {
1111
// Redirect console.log to stderr so it doesn't conflict with
1212
// MCP StdioServerTransport which uses stdout for protocol messages
13-
console.log = (...args: any[]) => console.error(...args);
13+
console.log = (...args: unknown[]) => console.error(...args);
1414

1515
console.log('═══════════════════════════════════════════════════');
1616
console.log(' MyXstack - Autonomous AI Agent on X (Twitter)');

src/services/agent.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,9 @@ export class AutonomousAgent {
9191

9292
console.log(`\n📬 [${new Date().toLocaleTimeString()}] Found ${newMentions.length} new mention(s)!\n`);
9393

94-
// Process each mention
95-
for (const mention of newMentions) {
94+
// Process mentions oldest-first (API returns newest-first) so Set
95+
// insertion order is chronological and oldest entries are pruned first
96+
for (const mention of [...newMentions].reverse()) {
9697
await this.processMention(mention);
9798
this.processedMentions.add(mention.post.id);
9899
}
@@ -102,7 +103,11 @@ export class AutonomousAgent {
102103
const excess = this.processedMentions.size - AutonomousAgent.MAX_PROCESSED_MENTIONS;
103104
const iter = this.processedMentions.values();
104105
for (let i = 0; i < excess; i++) {
105-
this.processedMentions.delete(iter.next().value as string);
106+
const { value, done } = iter.next();
107+
if (done) {
108+
break;
109+
}
110+
this.processedMentions.delete(value);
106111
}
107112
}
108113
} catch (error) {

src/services/grok.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ export class GrokService {
5959
throw new Error(`Grok API error: ${response.status}`);
6060
}
6161

62-
const data: any = await response.json();
62+
const data = await response.json() as { choices: { message?: { content?: string } }[] };
6363
const analysisText = data.choices[0]?.message?.content || '';
6464

6565
// Use the mention post ID so replies target the specific post where the agent was mentioned

src/services/xapi.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,15 @@ export class XAPIClient {
4444
throw new Error('Failed to get user ID from response');
4545
}
4646

47-
let mentionsUrl = `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`;
47+
const params = new URLSearchParams({
48+
max_results: '10',
49+
expansions: 'author_id',
50+
'tweet.fields': 'created_at,conversation_id,in_reply_to_user_id,referenced_tweets',
51+
});
4852
if (this.lastMentionId) {
49-
mentionsUrl += `&since_id=${this.lastMentionId}`;
53+
params.set('since_id', this.lastMentionId);
5054
}
55+
const mentionsUrl = `https://api.twitter.com/2/users/${userId}/mentions?${params.toString()}`;
5156

5257
const mentionsResponse = await this.makeXAPIRequest(mentionsUrl, 'GET');
5358

@@ -91,6 +96,11 @@ export class XAPIClient {
9196
return null;
9297
}
9398

99+
if (!Array.isArray(response.data)) {
100+
console.warn('Unexpected response shape from X API (thread): data is not an array');
101+
return null;
102+
}
103+
94104
return this.parseThread(response.data);
95105
} catch (error) {
96106
console.error('Error fetching thread:', error);

0 commit comments

Comments
 (0)