@semanticintent/semantic-chirp-intelligence-mcp 3.0.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.
- package/.env.example +8 -0
- package/LICENSE +21 -0
- package/README.md +250 -0
- package/authenticate.js +207 -0
- package/build/analyses/BreakoutAnalysis.js +386 -0
- package/build/analyses/GamesInHandAnalysis.js +257 -0
- package/build/analyses/IceAnalysis.js +316 -0
- package/build/analyses/LineupAnalysis.js +284 -0
- package/build/analyses/StreamingAnalysis.js +246 -0
- package/build/analyses/WeekendStreamAnalysis.js +599 -0
- package/build/config/chirp-styles.js +36 -0
- package/build/config/personality-modes.js +36 -0
- package/build/config/tool-metadata.js +113 -0
- package/build/domain/governance.js +322 -0
- package/build/domain/types.js +14 -0
- package/build/experimental/semantic-breakout-tool.js +188 -0
- package/build/experimental/semantic-intent-parser.js +222 -0
- package/build/experimental/semantic-tool-integration.js +146 -0
- package/build/experimental/test-parser.js +61 -0
- package/build/index.js +1549 -0
- package/build/services/ChirpIntelligence.js +213 -0
- package/build/services/YahooApiClient.js +309 -0
- package/build/template/AnalysisTemplate.js +167 -0
- package/build/types.js +2 -0
- package/package.json +50 -0
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
/**
|
|
3
|
+
* StreamingAnalysis - Template Method Pattern Implementation
|
|
4
|
+
*
|
|
5
|
+
* Recommends waiver wire pickups based on schedule advantages and player trends.
|
|
6
|
+
*/
|
|
7
|
+
import { AnalysisTemplate } from '../template/AnalysisTemplate.js';
|
|
8
|
+
import { ChirpIntelligence } from '../services/ChirpIntelligence.js';
|
|
9
|
+
export class StreamingAnalysis extends AnalysisTemplate {
|
|
10
|
+
apiClient;
|
|
11
|
+
leagueId;
|
|
12
|
+
teamId;
|
|
13
|
+
constructor(apiClient, leagueId, teamId) {
|
|
14
|
+
super("get_streaming_recommendations", "streaming_strategy");
|
|
15
|
+
this.apiClient = apiClient;
|
|
16
|
+
this.leagueId = leagueId;
|
|
17
|
+
this.teamId = teamId;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Hook 1: Fetch raw data from Yahoo API
|
|
21
|
+
*/
|
|
22
|
+
async fetchData(args) {
|
|
23
|
+
try {
|
|
24
|
+
// Fetch trending players (hot pickups)
|
|
25
|
+
// Note: apiClient.request() already includes /fantasy/v2 base
|
|
26
|
+
const cleanLeagueId = this.leagueId.replace(/^nhl\.l\./, '');
|
|
27
|
+
const trendingData = await this.apiClient.request(`/league/nhl.l.${cleanLeagueId}/players;status=A;sort=AR`);
|
|
28
|
+
// Fetch your current roster to avoid recommending owned players
|
|
29
|
+
const rosterData = await this.apiClient.getTeamRoster(this.leagueId, this.teamId);
|
|
30
|
+
// Fetch league scoreboard for schedule data
|
|
31
|
+
const scoreboardData = await this.apiClient.getLeagueScoreboard(this.leagueId);
|
|
32
|
+
return {
|
|
33
|
+
trending: trendingData,
|
|
34
|
+
roster: rosterData,
|
|
35
|
+
scoreboard: scoreboardData
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
throw new Error(`Failed to fetch streaming data: ${error}`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Hook 2: Prepare data into FantasyData structure
|
|
44
|
+
*/
|
|
45
|
+
async prepareData(rawData, args) {
|
|
46
|
+
const { trending, roster, scoreboard } = rawData;
|
|
47
|
+
// Parse current roster to filter out owned players
|
|
48
|
+
const ownedPlayerIds = new Set();
|
|
49
|
+
const rosterPlayers = roster.fantasy_content?.team?.[1]?.roster?.['0']?.players?.['0']?.player || [];
|
|
50
|
+
for (const playerData of rosterPlayers) {
|
|
51
|
+
const player = playerData.player?.[0] || playerData;
|
|
52
|
+
ownedPlayerIds.add(player.player_id);
|
|
53
|
+
}
|
|
54
|
+
// Parse available trending players
|
|
55
|
+
const availablePlayers = [];
|
|
56
|
+
const trendingPlayers = trending.fantasy_content?.league?.[1]?.players?.['0']?.player || [];
|
|
57
|
+
for (const playerData of trendingPlayers) {
|
|
58
|
+
const player = playerData.player?.[0] || playerData;
|
|
59
|
+
const playerId = player.player_id;
|
|
60
|
+
// Skip if already owned
|
|
61
|
+
if (ownedPlayerIds.has(playerId)) {
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
// Apply position filter if specified
|
|
65
|
+
const position = player.display_position || player.primary_positions?.[0] || 'Unknown';
|
|
66
|
+
if (args.position_filter && args.position_filter.length > 0) {
|
|
67
|
+
if (!args.position_filter.includes(position)) {
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
availablePlayers.push({
|
|
72
|
+
player_id: playerId,
|
|
73
|
+
name: player.name?.full || 'Unknown',
|
|
74
|
+
position: position,
|
|
75
|
+
team: player.editorial_team_abbr || '',
|
|
76
|
+
selected_position: ['FA'], // Free agent
|
|
77
|
+
status: player.status,
|
|
78
|
+
percent_owned: parseFloat(player.percent_owned?.value || '0'),
|
|
79
|
+
stats: this.parsePlayerStats(player)
|
|
80
|
+
});
|
|
81
|
+
// Limit to top available players
|
|
82
|
+
if (availablePlayers.length >= (args.max_recommendations || 10) * 2) {
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return {
|
|
87
|
+
availablePlayers,
|
|
88
|
+
roster: this.parseRoster(roster),
|
|
89
|
+
scoreboard: scoreboard
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Hook 3: Analyze data to generate streaming recommendations
|
|
94
|
+
*/
|
|
95
|
+
async analyzeData(data, args) {
|
|
96
|
+
const lookAheadDays = args.look_ahead_days || 7;
|
|
97
|
+
const maxRecommendations = args.max_recommendations || 5;
|
|
98
|
+
const streamingRecommendations = [];
|
|
99
|
+
// Analyze each available player
|
|
100
|
+
for (const player of data.availablePlayers || []) {
|
|
101
|
+
// Calculate games this week (simplified - would use actual schedule in production)
|
|
102
|
+
const gamesThisWeek = this.estimateGamesThisWeek(player, lookAheadDays);
|
|
103
|
+
// Determine pickup priority based on games and ownership
|
|
104
|
+
let pickupPriority;
|
|
105
|
+
let reasoning;
|
|
106
|
+
if (gamesThisWeek >= 4 && (player.percent_owned || 0) < 20) {
|
|
107
|
+
pickupPriority = 'HIGH';
|
|
108
|
+
reasoning = `${gamesThisWeek} games this week, low ownership (${player.percent_owned?.toFixed(1)}%)`;
|
|
109
|
+
}
|
|
110
|
+
else if (gamesThisWeek >= 3) {
|
|
111
|
+
pickupPriority = 'MEDIUM';
|
|
112
|
+
reasoning = `${gamesThisWeek} games this week, good volume play`;
|
|
113
|
+
}
|
|
114
|
+
else if ((player.percent_owned || 0) > 50) {
|
|
115
|
+
pickupPriority = 'HIGH';
|
|
116
|
+
reasoning = `High ownership (${player.percent_owned?.toFixed(1)}%) trending player`;
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
pickupPriority = 'LOW';
|
|
120
|
+
reasoning = `${gamesThisWeek} games this week, speculative add`;
|
|
121
|
+
}
|
|
122
|
+
streamingRecommendations.push({
|
|
123
|
+
player,
|
|
124
|
+
games_this_week: gamesThisWeek,
|
|
125
|
+
recent_performance: this.describePerformance(player),
|
|
126
|
+
pickup_priority: pickupPriority,
|
|
127
|
+
reasoning
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
// Sort by priority and games
|
|
131
|
+
streamingRecommendations.sort((a, b) => {
|
|
132
|
+
const priorityOrder = { CRITICAL: 0, HIGH: 1, MEDIUM: 2, LOW: 3 };
|
|
133
|
+
const priorityDiff = priorityOrder[a.pickup_priority] - priorityOrder[b.pickup_priority];
|
|
134
|
+
if (priorityDiff !== 0)
|
|
135
|
+
return priorityDiff;
|
|
136
|
+
return b.games_this_week - a.games_this_week;
|
|
137
|
+
});
|
|
138
|
+
return streamingRecommendations.slice(0, maxRecommendations);
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Hook 4: Generate chirp-enhanced response
|
|
142
|
+
*/
|
|
143
|
+
async generateChirp(analysisResults, semanticContract, data) {
|
|
144
|
+
return ChirpIntelligence.enhance(this.toolName, { streaming_recommendations: analysisResults }, semanticContract);
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Hook 5: Format final response
|
|
148
|
+
*/
|
|
149
|
+
async formatResponse(chirpEnhanced, data) {
|
|
150
|
+
const streamingData = chirpEnhanced.streaming_recommendations;
|
|
151
|
+
// Convert to standard Recommendation format
|
|
152
|
+
const recommendations = streamingData.map(analysis => ({
|
|
153
|
+
priority: analysis.pickup_priority,
|
|
154
|
+
action: 'pickup',
|
|
155
|
+
pickup: analysis.player,
|
|
156
|
+
reasoning: analysis.reasoning
|
|
157
|
+
}));
|
|
158
|
+
const analysisInsights = {
|
|
159
|
+
streaming_summary: {
|
|
160
|
+
total_recommendations: streamingData.length,
|
|
161
|
+
high_priority_count: streamingData.filter(s => s.pickup_priority === 'HIGH' || s.pickup_priority === 'CRITICAL').length,
|
|
162
|
+
average_games_per_player: streamingData.reduce((sum, s) => sum + s.games_this_week, 0) / streamingData.length || 0
|
|
163
|
+
},
|
|
164
|
+
top_targets: streamingData.slice(0, 3).map(s => ({
|
|
165
|
+
player: s.player.name,
|
|
166
|
+
games: s.games_this_week,
|
|
167
|
+
reasoning: s.reasoning
|
|
168
|
+
}))
|
|
169
|
+
};
|
|
170
|
+
const metadata = {
|
|
171
|
+
analysis_type: this.analysisType,
|
|
172
|
+
timestamp: new Date().toISOString(),
|
|
173
|
+
team_context: {
|
|
174
|
+
team_name: data.roster?.team_name || 'Your Team'
|
|
175
|
+
},
|
|
176
|
+
semantic_contract_applied: true
|
|
177
|
+
};
|
|
178
|
+
return {
|
|
179
|
+
analysis_insights: analysisInsights,
|
|
180
|
+
recommendations,
|
|
181
|
+
chirp_intelligence: chirpEnhanced.chirp_intelligence,
|
|
182
|
+
metadata
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Helper: Parse roster data
|
|
187
|
+
*/
|
|
188
|
+
parseRoster(rosterData) {
|
|
189
|
+
const team = rosterData.fantasy_content?.team?.[0] || {};
|
|
190
|
+
const rosterPlayers = rosterData.fantasy_content?.team?.[1]?.roster?.['0']?.players?.['0']?.player || [];
|
|
191
|
+
const players = rosterPlayers.map((playerData) => {
|
|
192
|
+
const player = playerData.player?.[0] || playerData;
|
|
193
|
+
return {
|
|
194
|
+
player_id: player.player_id,
|
|
195
|
+
name: player.name?.full || 'Unknown',
|
|
196
|
+
position: player.display_position || player.primary_positions?.[0] || 'Unknown',
|
|
197
|
+
team: player.editorial_team_abbr || '',
|
|
198
|
+
selected_position: player.selected_position || [],
|
|
199
|
+
status: player.status
|
|
200
|
+
};
|
|
201
|
+
});
|
|
202
|
+
return {
|
|
203
|
+
team_key: team.team_key || '',
|
|
204
|
+
team_name: team.name || 'Your Team',
|
|
205
|
+
players
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Helper: Parse player stats from API response
|
|
210
|
+
*/
|
|
211
|
+
parsePlayerStats(player) {
|
|
212
|
+
// Simplified - would parse actual stats in production
|
|
213
|
+
return {
|
|
214
|
+
percent_owned: player.percent_owned?.value || 0,
|
|
215
|
+
display_position: player.display_position
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Helper: Estimate games this week for a player
|
|
220
|
+
*/
|
|
221
|
+
estimateGamesThisWeek(player, lookAheadDays) {
|
|
222
|
+
// Simplified calculation - in production would use actual NHL schedule
|
|
223
|
+
// Average NHL team plays 3-4 games per week
|
|
224
|
+
const gamesPerWeek = 3.5;
|
|
225
|
+
return Math.round((lookAheadDays / 7) * gamesPerWeek);
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Helper: Describe recent performance
|
|
229
|
+
*/
|
|
230
|
+
describePerformance(player) {
|
|
231
|
+
// Simplified - would analyze actual recent stats in production
|
|
232
|
+
const ownership = player.percent_owned || 0;
|
|
233
|
+
if (ownership > 70) {
|
|
234
|
+
return "Widely owned hot player";
|
|
235
|
+
}
|
|
236
|
+
else if (ownership > 40) {
|
|
237
|
+
return "Trending upward";
|
|
238
|
+
}
|
|
239
|
+
else if (ownership > 20) {
|
|
240
|
+
return "Under-the-radar option";
|
|
241
|
+
}
|
|
242
|
+
else {
|
|
243
|
+
return "Deep league sleeper";
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|