heyi 2.1.0 → 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/README.md CHANGED
@@ -33,9 +33,9 @@ heyi preset [file] [options]
33
33
 
34
34
  #### Environment Variables
35
35
 
36
- - `API_KEY` - OpenRouter API key (required, can be set via environment or `.env` file)
37
- - `MODEL` - Default AI model to use (optional, can be overridden with `--model` flag)
38
- - `CRAWLER` - Default crawler to use for fetching URLs (optional, can be overridden with `--crawler` flag)
36
+ - `HEYI_API_KEY` - OpenRouter API key (required, can be set via environment or `.env` file)
37
+ - `HEYI_MODEL` - Default AI model to use (optional, can be overridden with `--model` flag)
38
+ - `HEYI_CRAWLER` - Default crawler to use for fetching URLs (optional, can be overridden with `--crawler` flag)
39
39
 
40
40
  ### Examples
41
41
 
@@ -66,10 +66,10 @@ heyi prompt "Preset in {{input}} and output in {{output}}" --var input="German"
66
66
  echo "Translate to {{language}}" | heyi prompt --var language="Spanish"
67
67
 
68
68
  # Set default model via environment variable
69
- MODEL=perplexity/sonar heyi prompt "Explain AI"
69
+ HEYI_MODEL=perplexity/sonar heyi prompt "Explain AI"
70
70
 
71
71
  # Set API key via environment variable
72
- API_KEY=your-key heyi prompt "Hello, AI!"
72
+ HEYI_API_KEY=your-key heyi prompt "Hello, AI!"
73
73
 
74
74
  # Input from file as context
75
75
  heyi prompt "Summarize this content" --file input.txt
@@ -86,7 +86,7 @@ heyi prompt "Compare these articles" --url https://example.com/article1.html --u
86
86
 
87
87
  # Use Chrome crawler for JavaScript-heavy pages
88
88
  heyi prompt "Summarize this SPA" --url https://example.com/spa --crawler chrome
89
- CRAWLER=chrome heyi prompt "Get content from dynamic page" --url https://example.com/dynamic
89
+ HEYI_CRAWLER=chrome heyi prompt "Get content from dynamic page" --url https://example.com/dynamic
90
90
 
91
91
  # Mix files and URLs as context
92
92
  heyi prompt "Compare local and remote content" --file local.txt --url https://example.com/remote.txt
@@ -240,7 +240,7 @@ heyi prompt "Summarize this page" --url https://example.com
240
240
  heyi prompt "Extract data from SPA" --url https://app.example.com --crawler chrome
241
241
 
242
242
  # Set Chrome as default crawler via environment
243
- CRAWLER=chrome heyi prompt "Get content" --url https://dynamic-site.com
243
+ HEYI_CRAWLER=chrome heyi prompt "Get content" --url https://dynamic-site.com
244
244
  ```
245
245
 
246
246
  ## Development
package/bin/index.js CHANGED
@@ -13,7 +13,7 @@ import { replaceVariables } from '../src/utils/variables.js'
13
13
  const DEFAULT_MODEL = 'openai/gpt-4o-mini'
14
14
  const DEFAULT_CRAWLER = 'fetch'
15
15
 
16
- const modelFlag = ['-m, --model <model>', 'AI model to use', process.env.MODEL ?? DEFAULT_MODEL]
16
+ const modelFlag = ['-m, --model <model>', 'AI model to use', process.env.HEYI_MODEL ?? DEFAULT_MODEL]
17
17
  const formatFlag = ['-f, --format <format>', 'Output format: string, number, object, array', 'string']
18
18
  const schemaFlag = [
19
19
  '-s, --schema <schema>',
@@ -22,7 +22,7 @@ const schemaFlag = [
22
22
  const crawlerFlag = [
23
23
  '-c, --crawler <crawler>',
24
24
  'Crawler to use for fetching URLs: fetch, chrome',
25
- process.env.CRAWLER ?? DEFAULT_CRAWLER,
25
+ process.env.HEYI_CRAWLER ?? DEFAULT_CRAWLER,
26
26
  ]
27
27
  const fileFlag = [
28
28
  '--file <path>',
@@ -87,8 +87,8 @@ Examples:
87
87
  $ heyi prompt "Preset in {{language}}" --var language="German"
88
88
 
89
89
  # Environment variables
90
- $ MODEL=perplexity/sonar heyi prompt "Explain AI"
91
- $ API_KEY=your-key heyi prompt "Hello, AI!"
90
+ $ HEYI_MODEL=perplexity/sonar heyi prompt "Explain AI"
91
+ $ HEYI_API_KEY=your-key heyi prompt "Hello, AI!"
92
92
 
93
93
  # Attach context
94
94
  $ heyi prompt "Summarize this content" --file input.txt
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "heyi",
3
- "version": "2.1.0",
3
+ "version": "3.0.0",
4
4
  "description": "CLI tool to execute AI prompts with flexible output formatting",
5
5
  "keywords": [
6
6
  "ai",
package/src/index.js CHANGED
@@ -19,9 +19,9 @@ config()
19
19
  export const executePrompt = async (prompt, options = {}) => {
20
20
  const { model, format = 'string', schema } = options
21
21
 
22
- const apiKey = process.env.API_KEY
22
+ const apiKey = process.env.HEYI_API_KEY
23
23
  if (!apiKey) {
24
- throw new Error('API_KEY environment variable is required. Set it via environment or .env file.')
24
+ throw new Error('HEYI_API_KEY environment variable is required. Set it via environment or .env file.')
25
25
  }
26
26
 
27
27
  const openrouter = createOpenRouter({
@@ -108,17 +108,34 @@ const fetchUrlContentWithFetch = async (url) => {
108
108
  */
109
109
  const fetchUrlContentWithChrome = async (url) => {
110
110
  validateUrl(url)
111
+
111
112
  const browser = await launch({
112
113
  headless: true,
113
114
  // These args are required for running in containerized environments (e.g., Docker, CI/CD)
114
115
  args: ['--no-sandbox', '--disable-setuid-sandbox'],
115
116
  })
117
+
116
118
  try {
117
119
  const page = await browser.newPage()
118
- // Wait for network to be idle, with a 30-second timeout to prevent indefinite waiting
119
- // networkidle0 is specifically used for JavaScript-heavy pages to ensure all dynamic content is loaded
120
- await page.goto(url, { waitUntil: 'networkidle0', timeout: 30000 })
120
+
121
+ // Wait for network to be idle, with a 10-second timeout to prevent indefinite waiting.
122
+ // If timeout occurs, continue with whatever content is available.
123
+ // Wait for navigation first in case there are redirects.
124
+ try {
125
+ await Promise.all([
126
+ page.waitForNavigation({ timeout: 10000 }),
127
+ page.goto(url, { waitUntil: 'networkidle0', timeout: 10000 }),
128
+ ])
129
+ } catch (error) {
130
+ // If it's a timeout error, continue with the content that's already loaded
131
+ // For other errors (e.g., network errors), rethrow
132
+ if (!error.message.includes('timeout') && !error.message.includes('Navigation timeout')) {
133
+ throw error
134
+ }
135
+ }
136
+
121
137
  const html = await page.content()
138
+
122
139
  // Sanitize HTML to extract only text content and avoid large data
123
140
  const cleanText = sanitizeHtml(html, {
124
141
  allowedTags: [],