@flue/client 0.0.27 → 0.0.28
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/dist/index.d.mts +4 -0
- package/dist/index.mjs +10 -8
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -101,6 +101,8 @@ interface SkillOptions<S extends v.GenericSchema | undefined = undefined> {
|
|
|
101
101
|
providerID: string;
|
|
102
102
|
modelID: string;
|
|
103
103
|
};
|
|
104
|
+
/** Max time to wait for the skill to complete (ms). Defaults to 60 minutes. */
|
|
105
|
+
timeout?: number;
|
|
104
106
|
}
|
|
105
107
|
interface PromptOptions<S extends v.GenericSchema | undefined = undefined> {
|
|
106
108
|
/** Valibot schema for structured result extraction. */
|
|
@@ -110,6 +112,8 @@ interface PromptOptions<S extends v.GenericSchema | undefined = undefined> {
|
|
|
110
112
|
providerID: string;
|
|
111
113
|
modelID: string;
|
|
112
114
|
};
|
|
115
|
+
/** Max time to wait for the prompt to complete (ms). Defaults to 60 minutes. */
|
|
116
|
+
timeout?: number;
|
|
113
117
|
}
|
|
114
118
|
interface ShellOptions {
|
|
115
119
|
/** Environment variables scoped to this subprocess only. */
|
package/dist/index.mjs
CHANGED
|
@@ -291,8 +291,8 @@ function extractLastResultBlock(text) {
|
|
|
291
291
|
const POLL_INTERVAL = 15e3;
|
|
292
292
|
/** Max times we'll see 0 assistant messages before giving up. */
|
|
293
293
|
const MAX_EMPTY_POLLS = 20;
|
|
294
|
-
/**
|
|
295
|
-
const
|
|
294
|
+
/** Default max time to poll before timing out (ms) - 60 minutes. */
|
|
295
|
+
const DEFAULT_POLL_TIMEOUT = 3600 * 1e3;
|
|
296
296
|
/**
|
|
297
297
|
* Low-level primitive: send a fully-formed prompt to OpenCode, poll until
|
|
298
298
|
* idle, and optionally extract a typed result.
|
|
@@ -301,7 +301,7 @@ const MAX_POLL_TIME = 2700 * 1e3;
|
|
|
301
301
|
* constructing their own prompt text.
|
|
302
302
|
*/
|
|
303
303
|
async function runPrompt(client, workdir, label, prompt, options) {
|
|
304
|
-
const { result: schema, model } = options ?? {};
|
|
304
|
+
const { result: schema, model, timeout } = options ?? {};
|
|
305
305
|
console.log(`[flue] ${label}: starting`);
|
|
306
306
|
console.log(`[flue] ${label}: creating session`);
|
|
307
307
|
const session = await client.session.create({
|
|
@@ -336,7 +336,7 @@ async function runPrompt(client, workdir, label, prompt, options) {
|
|
|
336
336
|
if (asyncResult.error) throw new Error(`Failed to send prompt for "${label}" (session ${sessionId}): ${JSON.stringify(asyncResult.error)}`);
|
|
337
337
|
await confirmSessionStarted(client, sessionId, workdir, label);
|
|
338
338
|
console.log(`[flue] ${label}: starting polling`);
|
|
339
|
-
const parts = await pollUntilIdle(client, sessionId, workdir, label, promptStart);
|
|
339
|
+
const parts = await pollUntilIdle(client, sessionId, workdir, label, promptStart, timeout);
|
|
340
340
|
const promptElapsed = ((Date.now() - promptStart) / 1e3).toFixed(1);
|
|
341
341
|
console.log(`[flue] ${label}: completed (${promptElapsed}s)`);
|
|
342
342
|
if (!schema) return;
|
|
@@ -347,11 +347,12 @@ async function runPrompt(client, workdir, label, prompt, options) {
|
|
|
347
347
|
* then delegates to runPrompt().
|
|
348
348
|
*/
|
|
349
349
|
async function runSkill(client, workdir, name, options, proxyInstructions) {
|
|
350
|
-
const { args, result: schema, model } = options ?? {};
|
|
350
|
+
const { args, result: schema, model, timeout } = options ?? {};
|
|
351
351
|
const prompt = buildSkillPrompt(name, args, schema, proxyInstructions);
|
|
352
352
|
return runPrompt(client, workdir, `skill("${name}")`, prompt, {
|
|
353
353
|
result: schema,
|
|
354
|
-
model
|
|
354
|
+
model,
|
|
355
|
+
timeout
|
|
355
356
|
});
|
|
356
357
|
}
|
|
357
358
|
/**
|
|
@@ -378,14 +379,15 @@ async function confirmSessionStarted(client, sessionId, workdir, label) {
|
|
|
378
379
|
}
|
|
379
380
|
throw new Error(`"${label}" failed to start: session ${sessionId} has no messages after 15s.\nThe prompt was accepted but OpenCode never began processing it.\nThis usually means no model is configured. Pass --model to the flue CLI or set "model" in opencode.json.`);
|
|
380
381
|
}
|
|
381
|
-
async function pollUntilIdle(client, sessionId, workdir, label, startTime) {
|
|
382
|
+
async function pollUntilIdle(client, sessionId, workdir, label, startTime, timeout) {
|
|
383
|
+
const maxPollTime = timeout ?? DEFAULT_POLL_TIMEOUT;
|
|
382
384
|
let emptyPolls = 0;
|
|
383
385
|
let pollCount = 0;
|
|
384
386
|
for (;;) {
|
|
385
387
|
await sleep(POLL_INTERVAL);
|
|
386
388
|
pollCount++;
|
|
387
389
|
const elapsed = ((Date.now() - startTime) / 1e3).toFixed(0);
|
|
388
|
-
if (Date.now() - startTime >
|
|
390
|
+
if (Date.now() - startTime > maxPollTime) throw new Error(`"${label}" timed out after ${elapsed}s. Session never went idle. This may indicate a stuck session or OpenCode bug.`);
|
|
389
391
|
const statusResult = await client.session.status({ query: { directory: workdir } });
|
|
390
392
|
const sessionStatus = statusResult.data?.[sessionId];
|
|
391
393
|
if (!sessionStatus || sessionStatus.type === "idle") {
|