movie-agent 1.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.
Files changed (60) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +464 -0
  3. package/bin/movie-agent +209 -0
  4. package/dist/agent.d.ts +89 -0
  5. package/dist/agent.d.ts.map +1 -0
  6. package/dist/agent.js +365 -0
  7. package/dist/agent.js.map +1 -0
  8. package/dist/cache.d.ts +75 -0
  9. package/dist/cache.d.ts.map +1 -0
  10. package/dist/cache.js +133 -0
  11. package/dist/cache.js.map +1 -0
  12. package/dist/config.d.ts +17 -0
  13. package/dist/config.d.ts.map +1 -0
  14. package/dist/config.js +31 -0
  15. package/dist/config.js.map +1 -0
  16. package/dist/discover.d.ts +38 -0
  17. package/dist/discover.d.ts.map +1 -0
  18. package/dist/discover.js +121 -0
  19. package/dist/discover.js.map +1 -0
  20. package/dist/factory.d.ts +87 -0
  21. package/dist/factory.d.ts.map +1 -0
  22. package/dist/factory.js +118 -0
  23. package/dist/factory.js.map +1 -0
  24. package/dist/filters.d.ts +61 -0
  25. package/dist/filters.d.ts.map +1 -0
  26. package/dist/filters.js +97 -0
  27. package/dist/filters.js.map +1 -0
  28. package/dist/format.d.ts +33 -0
  29. package/dist/format.d.ts.map +1 -0
  30. package/dist/format.js +85 -0
  31. package/dist/format.js.map +1 -0
  32. package/dist/index.d.ts +6 -0
  33. package/dist/index.d.ts.map +1 -0
  34. package/dist/index.js +20 -0
  35. package/dist/index.js.map +1 -0
  36. package/dist/mood.d.ts +7 -0
  37. package/dist/mood.d.ts.map +1 -0
  38. package/dist/mood.js +21 -0
  39. package/dist/mood.js.map +1 -0
  40. package/dist/providers.d.ts +10 -0
  41. package/dist/providers.d.ts.map +1 -0
  42. package/dist/providers.js +70 -0
  43. package/dist/providers.js.map +1 -0
  44. package/dist/ranking.d.ts +57 -0
  45. package/dist/ranking.d.ts.map +1 -0
  46. package/dist/ranking.js +198 -0
  47. package/dist/ranking.js.map +1 -0
  48. package/dist/tmdbApi.d.ts +79 -0
  49. package/dist/tmdbApi.d.ts.map +1 -0
  50. package/dist/tmdbApi.js +88 -0
  51. package/dist/tmdbApi.js.map +1 -0
  52. package/dist/types.d.ts +99 -0
  53. package/dist/types.d.ts.map +1 -0
  54. package/dist/types.js +3 -0
  55. package/dist/types.js.map +1 -0
  56. package/dist/validate.d.ts +13 -0
  57. package/dist/validate.d.ts.map +1 -0
  58. package/dist/validate.js +47 -0
  59. package/dist/validate.js.map +1 -0
  60. package/package.json +72 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Wei Yan
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,464 @@
1
+ # Movie Agent
2
+
3
+ An intelligent movie recommendation system that helps users discover movies based on their preferences and shows where they're available to stream in Canada.
4
+
5
+ ## Features
6
+
7
+ - šŸŽ¬ Personalized movie recommendations based on mood, genre, and preferences
8
+ - šŸ“ŗ Real-time streaming availability for Canadian platforms
9
+ - ⚔ Fast responses using TMDb API
10
+ - šŸŽÆ Smart filtering by runtime, release year, and streaming platforms
11
+ - šŸ“¦ Easy integration into web applications and APIs
12
+
13
+ ## Prerequisites
14
+
15
+ - Node.js (v18 or higher)
16
+ - TMDb API key ([Get one here](https://www.themoviedb.org/settings/api))
17
+
18
+ ## Installation
19
+
20
+ ```bash
21
+ npm install movie-agent
22
+ ```
23
+
24
+ ## Quick Start
25
+
26
+ ### Option 1: Using MovieAgentFactory.create() with explicit config (Recommended)
27
+
28
+ ```typescript
29
+ import { MovieAgentFactory } from 'movie-agent';
30
+
31
+ // Create agent with explicit configuration
32
+ const agent = MovieAgentFactory.create({
33
+ tmdbApiKey: process.env.TMDB_API_KEY!,
34
+ tmdbRegion: 'CA',
35
+ debug: true, // Enable debug logging
36
+ });
37
+
38
+ // Get recommendations
39
+ const recommendations = await agent.getRecommendations({
40
+ mood: 'excited',
41
+ genre: 'Action',
42
+ platforms: ['Netflix', 'Prime Video'],
43
+ });
44
+
45
+ console.log(recommendations);
46
+ ```
47
+
48
+ ### Option 2: Using MovieAgentFactory.fromEnv() convenience method
49
+
50
+ ```typescript
51
+ import { MovieAgentFactory } from 'movie-agent';
52
+ import dotenv from 'dotenv';
53
+
54
+ // Load your .env file BEFORE creating the agent
55
+ dotenv.config();
56
+
57
+ // Create agent from environment variables
58
+ const agent = MovieAgentFactory.fromEnv(true); // true = enable debug logging
59
+
60
+ // Get recommendations
61
+ const recommendations = await agent.getRecommendations({
62
+ mood: 'relaxed',
63
+ genre: ['Comedy', 'Romance'],
64
+ runtime: { max: 120 },
65
+ });
66
+ ```
67
+
68
+ ## API Examples
69
+
70
+ ```typescript
71
+ // Simple mood-based search
72
+ await agent.getRecommendations({
73
+ mood: 'happy'
74
+ });
75
+
76
+ // Genre-specific with platform filter
77
+ await agent.getRecommendations({
78
+ genre: 'Action',
79
+ platforms: ['Disney+']
80
+ });
81
+
82
+ // Complex filtering
83
+ await agent.getRecommendations({
84
+ mood: 'adventurous',
85
+ platforms: ['Netflix', 'Prime Video'],
86
+ runtime: { min: 90, max: 150 },
87
+ releaseYear: { from: 2020, to: 2024 }
88
+ });
89
+
90
+ // Multiple genres
91
+ await agent.getRecommendations({
92
+ genre: ['Comedy', 'Romance'],
93
+ platforms: ['Netflix'],
94
+ runtime: { max: 120 }
95
+ });
96
+ ```
97
+
98
+ ## Integration Examples
99
+
100
+ ### Next.js API Route
101
+
102
+ ```typescript
103
+ // pages/api/recommendations.ts
104
+ import { MovieAgentFactory } from 'movie-agent';
105
+ import type { NextApiRequest, NextApiResponse } from 'next';
106
+
107
+ const agent = MovieAgentFactory.create({
108
+ tmdbApiKey: process.env.TMDB_API_KEY!,
109
+ tmdbRegion: 'CA',
110
+ });
111
+
112
+ export default async function handler(req: NextApiRequest, res: NextApiResponse) {
113
+ if (req.method !== 'POST') {
114
+ return res.status(405).json({ error: 'Method not allowed' });
115
+ }
116
+
117
+ try {
118
+ const { mood, genre, platforms } = req.body;
119
+ const recommendations = await agent.getRecommendations({ mood, genre, platforms });
120
+ res.status(200).json(recommendations);
121
+ } catch (error) {
122
+ console.error('Error getting recommendations:', error);
123
+ res.status(500).json({ error: 'Failed to get recommendations' });
124
+ }
125
+ }
126
+ ```
127
+
128
+ ### Express Server
129
+
130
+ ```typescript
131
+ import express from 'express';
132
+ import { MovieAgentFactory } from 'movie-agent';
133
+ import dotenv from 'dotenv';
134
+
135
+ dotenv.config();
136
+
137
+ const app = express();
138
+ app.use(express.json());
139
+
140
+ const agent = MovieAgentFactory.create({
141
+ tmdbApiKey: process.env.TMDB_API_KEY!,
142
+ tmdbRegion: 'CA',
143
+ });
144
+
145
+ app.post('/api/recommendations', async (req, res) => {
146
+ try {
147
+ const recommendations = await agent.getRecommendations(req.body);
148
+ res.json(recommendations);
149
+ } catch (error) {
150
+ console.error(error);
151
+ res.status(500).json({ error: 'Failed to get recommendations' });
152
+ }
153
+ });
154
+
155
+ app.listen(3000, () => {
156
+ console.log('Server running on http://localhost:3000');
157
+ });
158
+ ```
159
+
160
+ ## Configuration
161
+
162
+ ### Environment Variables
163
+
164
+ ```bash
165
+ # Required
166
+ TMDB_API_KEY=your_tmdb_api_key_here
167
+
168
+ # Optional
169
+ TMDB_REGION=CA
170
+ CACHE_TTL=86400
171
+ MAX_RECOMMENDATIONS=5
172
+ MIN_RECOMMENDATIONS=3
173
+ ```
174
+
175
+ ### Input Parameters
176
+
177
+ ```typescript
178
+ interface UserInput {
179
+ mood?: string; // e.g., 'excited', 'relaxed', 'thoughtful'
180
+ genre?: string | string[]; // e.g., 'Action' or ['Action', 'Thriller']
181
+ platforms?: string[]; // e.g., ['Netflix', 'Prime Video']
182
+ runtime?: {
183
+ min?: number; // Minimum runtime in minutes
184
+ max?: number; // Maximum runtime in minutes
185
+ };
186
+ releaseYear?: number | { // Single year or range
187
+ from: number;
188
+ to: number;
189
+ };
190
+ }
191
+ ```
192
+
193
+ ## Error Handling
194
+
195
+ ```typescript
196
+ const result = await agent.getRecommendations(input);
197
+
198
+ if ('error' in result) {
199
+ console.error(`Error: ${result.errorType} - ${result.message}`);
200
+
201
+ switch (result.errorType) {
202
+ case 'INVALID_API_KEY':
203
+ // Handle invalid API key
204
+ break;
205
+ case 'RATE_LIMIT_EXCEEDED':
206
+ // Handle rate limit
207
+ break;
208
+ case 'NO_RESULTS':
209
+ // No movies found matching criteria
210
+ break;
211
+ }
212
+ } else {
213
+ // Success! Use recommendations
214
+ console.log(result.recommendations);
215
+ }
216
+ ```
217
+
218
+ ## Supported Streaming Platforms (Canada)
219
+
220
+ - Netflix
221
+ - Prime Video
222
+ - Crave
223
+ - Disney+
224
+ - Apple TV+
225
+ - Paramount+
226
+ - And many more regional platforms
227
+
228
+ ## TypeScript Support
229
+
230
+ The package is fully typed. Import types as needed:
231
+
232
+ ```typescript
233
+ import {
234
+ MovieAgentFactory,
235
+ UserInput,
236
+ AgentResponse,
237
+ MovieRecommendation,
238
+ ErrorResponse,
239
+ } from 'movie-agent';
240
+ ```
241
+
242
+ ## Response Format
243
+
244
+ ### Success Response
245
+
246
+ ```typescript
247
+ interface AgentResponse {
248
+ recommendations: MovieRecommendation[];
249
+ metadata?: {
250
+ timestamp?: string;
251
+ inputParameters?: UserInput;
252
+ };
253
+ }
254
+
255
+ interface MovieRecommendation {
256
+ tmdbId: number;
257
+ title: string;
258
+ releaseYear: string;
259
+ runtime: number;
260
+ genres: string[];
261
+ overview: string;
262
+ streamingPlatforms: StreamingPlatform[];
263
+ matchReason: string;
264
+ }
265
+ ```
266
+
267
+ ### Error Response
268
+
269
+ ```typescript
270
+ interface ErrorResponse {
271
+ error: true;
272
+ errorType: 'VALIDATION_ERROR' | 'INVALID_API_KEY' | 'RATE_LIMIT_EXCEEDED' | 'NO_RESULTS' | 'UNKNOWN_ERROR';
273
+ message: string;
274
+ timestamp: string;
275
+ }
276
+ ```
277
+
278
+ ## Development
279
+
280
+ ### For Contributors
281
+
282
+ If you want to develop or modify this package:
283
+
284
+ ```bash
285
+ # Clone the repository
286
+ git clone https://github.com/imWayneWY/movie-agent.git
287
+ cd movie-agent
288
+
289
+ # Install dependencies
290
+ npm install
291
+
292
+ # Copy environment variables template
293
+ cp .env.example .env
294
+
295
+ # Add your API keys to .env
296
+ ```
297
+
298
+ ### Building
299
+
300
+ ```bash
301
+ # Type checking
302
+ npm run type-check
303
+
304
+ # Lint code
305
+ npm run lint
306
+
307
+ # Fix linting issues automatically
308
+ npm run lint:fix
309
+
310
+ # Format code
311
+ npm run format
312
+
313
+ # Check formatting without modifying files
314
+ npm run format:check
315
+
316
+ # Run all validations (type-check + lint + coverage)
317
+ npm run validate
318
+ ```
319
+
320
+ ### Building
321
+
322
+ ```bash
323
+ # Clean build artifacts
324
+ npm run clean
325
+
326
+ # Build TypeScript to JavaScript
327
+ npm run build
328
+
329
+ # Clean and build (runs validation first)
330
+ npm run prebuild && npm run build
331
+ ```
332
+
333
+ ## Testing
334
+
335
+ The project follows Test-Driven Development (TDD) practices with comprehensive test coverage.
336
+
337
+ ### Running Tests
338
+
339
+ ```bash
340
+ # Run all tests (unit + E2E)
341
+ npm test
342
+
343
+ # Run only unit tests (excludes E2E and live integration tests)
344
+ npm run test:unit
345
+
346
+ # Run E2E tests
347
+ npm run test:e2e
348
+
349
+ # Run live integration tests (requires API keys)
350
+ npm run test:integration
351
+
352
+ # Run tests with coverage report
353
+ npm run test:coverage
354
+
355
+ # Run tests in watch mode (for development)
356
+ npm run test:watch
357
+
358
+ # Run tests in CI mode (with coverage)
359
+ npm run test:ci
360
+ ```
361
+
362
+ ### Test Structure
363
+
364
+ - **Unit Tests** (`src/__tests__/*.test.ts`) - Test individual modules and functions
365
+ - **E2E Tests** (`src/__tests__/e2e.test.ts`) - Test complete recommendation pipeline
366
+ - **Integration Tests** (`src/__tests__/*.live.test.ts`) - Test with real APIs (requires credentials)
367
+
368
+ ### Coverage Requirements
369
+
370
+ The project enforces minimum 90% code coverage across:
371
+ - Branches: 90%
372
+ - Functions: 90%
373
+ - Lines: 90%
374
+ - Statements: 90%
375
+
376
+ View coverage report after running tests:
377
+ ```bash
378
+ npm run test:coverage
379
+ open coverage/lcov-report/index.html
380
+ ```
381
+
382
+ ## CI/CD Workflow
383
+
384
+ ### GitHub Actions Example
385
+
386
+ ```yaml
387
+ name: CI
388
+
389
+ on: [push, pull_request]
390
+
391
+ jobs:
392
+ test:
393
+ runs-on: ubuntu-latest
394
+ steps:
395
+ - uses: actions/checkout@v3
396
+ - uses: actions/setup-node@v3
397
+ with:
398
+ node-version: '18'
399
+ - run: npm ci
400
+ - run: npm run type-check
401
+ - run: npm run lint
402
+ - run: npm run test:ci
403
+ - uses: codecov/codecov-action@v3
404
+ with:
405
+ files: ./coverage/lcov.info
406
+ ```
407
+
408
+ ### Pre-commit Workflow
409
+
410
+ Recommended pre-commit hook (`.git/hooks/pre-commit`):
411
+ ```bash
412
+ #!/bin/sh
413
+ npm run type-check && npm run lint && npm run test:unit
414
+ ```
415
+
416
+ ### Development Workflow
417
+
418
+ 1. **Create a new branch**
419
+ ```bash
420
+ git checkout -b feature/your-feature
421
+ ```
422
+
423
+ 2. **Make changes with TDD**
424
+ ```bash
425
+ # Write tests first
426
+ npm run test:watch
427
+ # Implement feature
428
+ # Ensure tests pass
429
+ ```
430
+
431
+ 3. **Validate before commit**
432
+ ```bash
433
+ npm run validate
434
+ ```
435
+
436
+ 4. **Commit and push**
437
+ ```bash
438
+ git add .
439
+ git commit -m "feat: your feature description"
440
+ git push origin feature/your-feature
441
+ ```
442
+
443
+ 5. **Create Pull Request**
444
+ - Ensure CI passes
445
+ - Request code review
446
+ - Merge when approved
447
+
448
+ ## Contributing
449
+
450
+ 1. Fork the repository
451
+ 2. Create a feature branch (`git checkout -b feature/amazing-feature`)
452
+ 3. Commit your changes (`git commit -m 'Add amazing feature'`)
453
+ 4. Push to the branch (`git push origin feature/amazing-feature`)
454
+ 5. Open a Pull Request
455
+
456
+ ## License
457
+
458
+ MIT
459
+
460
+ ## Acknowledgments
461
+
462
+ - [The Movie Database (TMDb)](https://www.themoviedb.org/) for movie data and streaming availability
463
+ - [LangChain.js](https://js.langchain.com/) for agent framework
464
+ - [OpenAI](https://openai.com/) for LLM capabilities
@@ -0,0 +1,209 @@
1
+ #!/usr/bin/env node
2
+
3
+ // bin/movie-agent
4
+ const path = require('path');
5
+ const fs = require('fs');
6
+
7
+ /**
8
+ * Parse command-line arguments
9
+ */
10
+ function parseArgs() {
11
+ const args = process.argv.slice(2);
12
+ const input = {};
13
+
14
+ for (let i = 0; i < args.length; i++) {
15
+ const arg = args[i];
16
+ const nextArg = args[i + 1];
17
+
18
+ if (arg.startsWith('--') && nextArg && !nextArg.startsWith('--')) {
19
+ const key = arg.substring(2);
20
+
21
+ switch (key) {
22
+ case 'mood':
23
+ input.mood = nextArg;
24
+ i++;
25
+ break;
26
+
27
+ case 'platforms':
28
+ // Support comma-separated platforms
29
+ input.platforms = nextArg.split(',').map(p => p.trim());
30
+ i++;
31
+ break;
32
+
33
+ case 'genre':
34
+ // Support comma-separated genres
35
+ const genres = nextArg.split(',').map(g => g.trim());
36
+ input.genre = genres.length === 1 ? genres[0] : genres;
37
+ i++;
38
+ break;
39
+
40
+ case 'runtimeMax':
41
+ if (!input.runtime) input.runtime = {};
42
+ input.runtime.max = parseInt(nextArg, 10);
43
+ i++;
44
+ break;
45
+
46
+ case 'runtimeMin':
47
+ if (!input.runtime) input.runtime = {};
48
+ input.runtime.min = parseInt(nextArg, 10);
49
+ i++;
50
+ break;
51
+
52
+ case 'year':
53
+ input.releaseYear = parseInt(nextArg, 10);
54
+ i++;
55
+ break;
56
+
57
+ case 'yearFrom':
58
+ if (typeof input.releaseYear !== 'object') {
59
+ input.releaseYear = {};
60
+ }
61
+ input.releaseYear.from = parseInt(nextArg, 10);
62
+ i++;
63
+ break;
64
+
65
+ case 'yearTo':
66
+ if (typeof input.releaseYear !== 'object') {
67
+ input.releaseYear = {};
68
+ }
69
+ input.releaseYear.to = parseInt(nextArg, 10);
70
+ i++;
71
+ break;
72
+
73
+ default:
74
+ console.error(`Unknown flag: ${arg}`);
75
+ printUsage();
76
+ process.exit(1);
77
+ }
78
+ } else if (arg === '--help' || arg === '-h') {
79
+ printUsage();
80
+ process.exit(0);
81
+ }
82
+ }
83
+
84
+ return input;
85
+ }
86
+
87
+ /**
88
+ * Print usage information
89
+ */
90
+ function printUsage() {
91
+ console.log(`
92
+ Usage: movie-agent [options]
93
+
94
+ Options:
95
+ --mood <string> User's mood (e.g., "happy", "excited", "thoughtful")
96
+ --platforms <list> Comma-separated list of platforms (e.g., "Netflix,Prime Video")
97
+ --genre <list> Genre or comma-separated genres (e.g., "Action" or "Action,Comedy")
98
+ --runtimeMax <number> Maximum runtime in minutes
99
+ --runtimeMin <number> Minimum runtime in minutes
100
+ --year <number> Specific release year
101
+ --yearFrom <number> Release year range start
102
+ --yearTo <number> Release year range end
103
+ --help, -h Show this help message
104
+
105
+ Examples:
106
+ movie-agent --mood excited --platforms Netflix
107
+ movie-agent --genre Action,Thriller --runtimeMax 120
108
+ movie-agent --mood relaxed --yearFrom 2020 --yearTo 2023
109
+ `);
110
+ }
111
+
112
+ /**
113
+ * Format recommendations for human-readable display
114
+ */
115
+ function formatOutput(response) {
116
+ let output = '\nšŸŽ¬ Movie Recommendations for You\n\n';
117
+
118
+ response.recommendations.forEach((movie, index) => {
119
+ output += `${index + 1}. **${movie.title}** (${movie.releaseYear}) • ${movie.runtime} min\n`;
120
+ output += ` Genres: ${movie.genres.join(', ')}\n\n`;
121
+ output += ` ${movie.description}\n\n`;
122
+
123
+ // Format streaming platforms
124
+ const availablePlatforms = movie.streamingPlatforms
125
+ .filter(p => p.available)
126
+ .map(p => p.name);
127
+
128
+ if (availablePlatforms.length > 0) {
129
+ output += ` šŸ“ŗ Available on: ${availablePlatforms.join(', ')}\n`;
130
+ } else {
131
+ output += ` šŸ“ŗ No streaming availability found\n`;
132
+ }
133
+
134
+ output += ` ✨ Why: ${movie.matchReason}\n`;
135
+
136
+ if (index < response.recommendations.length - 1) {
137
+ output += '\n───────────────────────────────────────────────────────────\n\n';
138
+ }
139
+ });
140
+
141
+ return output;
142
+ }
143
+
144
+ /**
145
+ * Main execution
146
+ */
147
+ async function main() {
148
+ try {
149
+ // Parse arguments first (for --help)
150
+ const args = process.argv.slice(2);
151
+ if (args.includes('--help') || args.includes('-h')) {
152
+ printUsage();
153
+ process.exit(0);
154
+ }
155
+
156
+ // Check if .env file exists and load it
157
+ const envPath = path.resolve(__dirname, '../.env.development');
158
+ if (fs.existsSync(envPath)) {
159
+ require('dotenv').config({ path: envPath });
160
+ }
161
+
162
+ // Check for TMDb API key
163
+ if (!process.env.TMDB_API_KEY) {
164
+ console.error(`
165
+ āŒ Error: TMDb API key not found
166
+
167
+ Please set the TMDB_API_KEY environment variable:
168
+ export TMDB_API_KEY=your_api_key_here
169
+
170
+ Or create a .env.development file with:
171
+ TMDB_API_KEY=your_api_key_here
172
+ `);
173
+ process.exit(1);
174
+ }
175
+
176
+ // Now it's safe to load the agent module
177
+ const { MovieAgent } = require('../dist/agent');
178
+
179
+ const input = parseArgs();
180
+
181
+ // Show help if no arguments provided
182
+ if (Object.keys(input).length === 0) {
183
+ printUsage();
184
+ process.exit(0);
185
+ }
186
+
187
+ console.log('\nšŸ” Finding movie recommendations...\n');
188
+
189
+ const agent = new MovieAgent();
190
+ const response = await agent.getRecommendations(input);
191
+
192
+ const output = formatOutput(response);
193
+ console.log(output);
194
+
195
+ } catch (error) {
196
+ console.error('\nāŒ Error:', error.message);
197
+
198
+ if (error.message.includes('API') || error.message.includes('network')) {
199
+ console.error('\nPlease check your internet connection and TMDb API key.');
200
+ } else if (error.message.includes('Invalid') || error.message.includes('validation')) {
201
+ console.error('\nPlease check your input parameters and try again.');
202
+ console.error('Use --help for usage information.');
203
+ }
204
+
205
+ process.exit(1);
206
+ }
207
+ }
208
+
209
+ main();