Skip to content

Commit 4d02ddb

Browse files
committed
Support streaming in Raycast AI provider
1 parent 21ac1bd commit 4d02ddb

File tree

1 file changed

+59
-4
lines changed

1 file changed

+59
-4
lines changed

src/api/Providers/special/raycast_ai.js

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,71 @@ export const RaycastAIProvider = {
99
const { AI } = await import("@raycast/api");
1010

1111
const prompt = format_chat_to_prompt(chat);
12-
const askOptions = { model: AI.Model[options.model], creativity: options.temperature * 2 + Number.EPSILON || 1.0 };
12+
const askOptions = {
13+
model: AI.Model[options.model],
14+
creativity: options.temperature * 2 + Number.EPSILON || 1.0,
15+
};
16+
1317
try {
14-
const answer = await AI.ask(prompt, askOptions);
15-
yield answer;
18+
const answerStream = AI.ask(prompt, askOptions);
19+
yield* eventEmitterToAsyncIterator(answerStream, answerStream);
20+
await answerStream;
1621
} catch (error) {
17-
console.log("Raycast AI error:", error);
22+
console.error("Raycast AI error:", error);
1823
}
1924
},
2025
};
2126

27+
/**
28+
* Converts an event emitter (using "data" and "error" events) into an async iterator.
29+
* It also takes a finishPromise which will resolve when the stream is complete.
30+
*/
31+
async function* eventEmitterToAsyncIterator(emitter, finishPromise) {
32+
const dataQueue = [];
33+
let error;
34+
35+
// Set up listeners.
36+
emitter.on("data", (data) => {
37+
dataQueue.push(data);
38+
if (waitingResolve) {
39+
waitingResolve();
40+
waitingResolve = null;
41+
}
42+
});
43+
44+
emitter.on("error", (err) => {
45+
error = err;
46+
if (waitingResolve) {
47+
waitingResolve();
48+
waitingResolve = null;
49+
}
50+
});
51+
52+
let waitingResolve = null;
53+
54+
while (true) {
55+
while (dataQueue.length) {
56+
yield dataQueue.shift();
57+
}
58+
59+
const finished = await Promise.race([
60+
new Promise((resolve) => {
61+
waitingResolve = resolve;
62+
}),
63+
finishPromise,
64+
]);
65+
if (finished !== undefined) {
66+
break;
67+
}
68+
if (error) {
69+
throw error;
70+
}
71+
}
72+
while (dataQueue.length) {
73+
yield dataQueue.shift();
74+
}
75+
}
76+
2277
export const RaycastAIModels = [
2378
"OpenAI_GPT4",
2479
"OpenAI_GPT4-turbo",

0 commit comments

Comments
 (0)