ask-my-llm 1.1.6 → 1.1.8
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/index.js +28 -18
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -39,13 +39,30 @@ function loadConfig(options) {
|
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
function parseSSE(output) {
|
|
43
|
+
let content = '';
|
|
44
|
+
for (const line of output.split('\n')) {
|
|
45
|
+
if (!line.startsWith('data: ')) continue;
|
|
46
|
+
const payload = line.slice(6).trim();
|
|
47
|
+
if (payload === '[DONE]') break;
|
|
48
|
+
try {
|
|
49
|
+
const parsed = JSON.parse(payload);
|
|
50
|
+
const delta = parsed.choices && parsed.choices[0] && parsed.choices[0].delta;
|
|
51
|
+
if (delta && delta.content) content += delta.content;
|
|
52
|
+
} catch (e) { /* skip malformed SSE */ }
|
|
53
|
+
}
|
|
54
|
+
if (!content) throw new Error('API returned no content:\n' + output.slice(0, 2000));
|
|
55
|
+
return content;
|
|
56
|
+
}
|
|
57
|
+
|
|
42
58
|
function ask(prompt, options) {
|
|
43
59
|
const config = loadConfig(options);
|
|
44
60
|
|
|
45
61
|
const postData = JSON.stringify({
|
|
46
62
|
model: config.model,
|
|
47
63
|
messages: [{ role: 'user', content: prompt }],
|
|
48
|
-
temperature: 0.7
|
|
64
|
+
temperature: 0.7,
|
|
65
|
+
stream: true
|
|
49
66
|
});
|
|
50
67
|
|
|
51
68
|
let baseUrl = config.baseApi.replace(/\/$/, '');
|
|
@@ -64,18 +81,18 @@ function ask(prompt, options) {
|
|
|
64
81
|
}
|
|
65
82
|
|
|
66
83
|
const args = [
|
|
67
|
-
'-s', '-S', '-X', 'POST',
|
|
84
|
+
'-s', '-S', '-X', 'POST', '-N',
|
|
68
85
|
...headerArgs,
|
|
69
|
-
'-d',
|
|
86
|
+
'-d', '@-',
|
|
70
87
|
url
|
|
71
88
|
];
|
|
72
89
|
|
|
73
|
-
const result = spawnSync('curl', args, { encoding: 'utf8' });
|
|
90
|
+
const result = spawnSync('curl', args, { encoding: 'utf8', input: postData });
|
|
74
91
|
|
|
75
92
|
if (result.error) throw result.error;
|
|
76
93
|
if (result.status !== 0) throw new Error('curl failed: ' + (result.stderr || result.stdout));
|
|
77
94
|
|
|
78
|
-
return
|
|
95
|
+
return parseSSE(result.stdout);
|
|
79
96
|
}
|
|
80
97
|
|
|
81
98
|
function askAsync(prompt, options) {
|
|
@@ -85,7 +102,8 @@ function askAsync(prompt, options) {
|
|
|
85
102
|
const postData = JSON.stringify({
|
|
86
103
|
model: config.model,
|
|
87
104
|
messages: [{ role: 'user', content: prompt }],
|
|
88
|
-
temperature: 0.7
|
|
105
|
+
temperature: 0.7,
|
|
106
|
+
stream: true
|
|
89
107
|
});
|
|
90
108
|
|
|
91
109
|
let baseUrl = config.baseApi.replace(/\/$/, '');
|
|
@@ -95,7 +113,7 @@ function askAsync(prompt, options) {
|
|
|
95
113
|
const url = baseUrl + '/chat/completions';
|
|
96
114
|
|
|
97
115
|
const headerArgs = [
|
|
98
|
-
'-s', '-S', '-X', 'POST',
|
|
116
|
+
'-s', '-S', '-X', 'POST', '-N',
|
|
99
117
|
'-H', 'Content-Type: application/json',
|
|
100
118
|
'-H', 'HTTP-Referer: https://cows.info.gf',
|
|
101
119
|
'-H', 'X-OpenRouter-Title: ask-my-llm'
|
|
@@ -103,7 +121,7 @@ function askAsync(prompt, options) {
|
|
|
103
121
|
if (config.apiKey) {
|
|
104
122
|
headerArgs.push('-H', `Authorization: Bearer ${config.apiKey}`);
|
|
105
123
|
}
|
|
106
|
-
headerArgs.push('-d',
|
|
124
|
+
headerArgs.push('-d', '@-', url);
|
|
107
125
|
|
|
108
126
|
const child = spawn('curl', headerArgs, { encoding: 'utf8' });
|
|
109
127
|
let data = '';
|
|
@@ -111,12 +129,13 @@ function askAsync(prompt, options) {
|
|
|
111
129
|
|
|
112
130
|
child.stdout.on('data', chunk => data += chunk);
|
|
113
131
|
child.stderr.on('data', chunk => error += chunk);
|
|
132
|
+
child.stdin.end(postData);
|
|
114
133
|
child.on('close', code => {
|
|
115
134
|
if (code !== 0) {
|
|
116
135
|
reject(new Error('curl failed: ' + (error || data)));
|
|
117
136
|
} else {
|
|
118
137
|
try {
|
|
119
|
-
resolve(
|
|
138
|
+
resolve(parseSSE(data));
|
|
120
139
|
} catch (e) {
|
|
121
140
|
reject(e);
|
|
122
141
|
}
|
|
@@ -126,15 +145,6 @@ function askAsync(prompt, options) {
|
|
|
126
145
|
});
|
|
127
146
|
}
|
|
128
147
|
|
|
129
|
-
function parseResponse(stdout) {
|
|
130
|
-
const parsed = JSON.parse(stdout);
|
|
131
|
-
if (parsed.choices && parsed.choices[0]) {
|
|
132
|
-
return parsed.choices[0].message.content;
|
|
133
|
-
} else {
|
|
134
|
-
throw new Error('API Error: ' + stdout);
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
148
|
/**
|
|
139
149
|
* Returns the model name from the current configuration.
|
|
140
150
|
* Synchronous.
|