@llm4ts/flow 0.15.0 → 0.15.1
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/TransientRetry.d.ts
CHANGED
|
@@ -13,6 +13,24 @@ export interface TransientRetryOptions {
|
|
|
13
13
|
readonly baseDelay?: Duration.Input;
|
|
14
14
|
readonly flakyRetries?: number;
|
|
15
15
|
readonly flakyDelay?: Duration.Input;
|
|
16
|
+
/**
|
|
17
|
+
* Re-asks a structured call whose response could not be parsed as the
|
|
18
|
+
* requested JSON, with the parse failure quoted back to the model. The
|
|
19
|
+
* model's output is not deterministic, so a malformed or off-schema reply
|
|
20
|
+
* is usually a one-off; but a schema the model cannot satisfy fails every
|
|
21
|
+
* time, so this budget is small (default 2) and independent of the others.
|
|
22
|
+
*/
|
|
23
|
+
readonly parseRetries?: number;
|
|
16
24
|
}
|
|
25
|
+
/** A structured call whose text came back but did not decode as the requested JSON. */
|
|
26
|
+
export declare const isStructuredParseFailure: (error: LlmError) => boolean;
|
|
27
|
+
/**
|
|
28
|
+
* The prompt for a structured re-ask: the original, plus what went wrong
|
|
29
|
+
* with the previous reply. Quoting the failure is what turns a blind retry
|
|
30
|
+
* into a repair — the common causes (prose around the JSON, a missing
|
|
31
|
+
* required field, a string where a number was asked for) are all things the
|
|
32
|
+
* model fixes on sight.
|
|
33
|
+
*/
|
|
34
|
+
export declare const repairPrompt: (prompt: string, error: LlmError) => string;
|
|
17
35
|
export declare const makeTransientRetry: (underlying: LlmServiceShape, retryOptions?: TransientRetryOptions | undefined) => Effect.Effect<LlmServiceShape, never, FlowEvents>;
|
|
18
36
|
//# sourceMappingURL=TransientRetry.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TransientRetry.d.ts","sourceRoot":"","sources":["../src/TransientRetry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,iBAAiB,CAAA;AAC3C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAEvC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,EAAc,KAAK,eAAe,EAAE,MAAM,yBAAyB,CAAA;AAG1E,OAAO,EAAE,UAAU,EAAQ,MAAM,iBAAiB,CAAA;AAmElD,eAAO,MAAM,aAAa,GAAI,OAAO,QAAQ,KAAG,OAE6C,CAAA;AAK7F,eAAO,MAAM,wBAAwB,GAAI,SAAS,MAAM,KAAG,OACV,CAAA;AAKjD,eAAO,MAAM,iBAAiB,GAAI,OAAO,QAAQ,KAAG,OACuB,CAAA;AAE3E,eAAO,MAAM,WAAW,GAAI,OAAO,QAAQ,KAAG,OAc7C,CAAA;AAID,eAAO,MAAM,cAAc,GAAI,OAAO,QAAQ,EAAE,SAAS,QAAQ,CAAC,QAAQ,KAAG,QAAQ,CAAC,QAMrF,CAAA;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,SAAS,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAA;IACnC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAA;IAC9B,QAAQ,CAAC,UAAU,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAA;
|
|
1
|
+
{"version":3,"file":"TransientRetry.d.ts","sourceRoot":"","sources":["../src/TransientRetry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,iBAAiB,CAAA;AAC3C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAEvC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,EAAc,KAAK,eAAe,EAAE,MAAM,yBAAyB,CAAA;AAG1E,OAAO,EAAE,UAAU,EAAQ,MAAM,iBAAiB,CAAA;AAmElD,eAAO,MAAM,aAAa,GAAI,OAAO,QAAQ,KAAG,OAE6C,CAAA;AAK7F,eAAO,MAAM,wBAAwB,GAAI,SAAS,MAAM,KAAG,OACV,CAAA;AAKjD,eAAO,MAAM,iBAAiB,GAAI,OAAO,QAAQ,KAAG,OACuB,CAAA;AAE3E,eAAO,MAAM,WAAW,GAAI,OAAO,QAAQ,KAAG,OAc7C,CAAA;AAID,eAAO,MAAM,cAAc,GAAI,OAAO,QAAQ,EAAE,SAAS,QAAQ,CAAC,QAAQ,KAAG,QAAQ,CAAC,QAMrF,CAAA;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,SAAS,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAA;IACnC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAA;IAC9B,QAAQ,CAAC,UAAU,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAA;IACpC;;;;;;OAMG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAC/B;AAkBD,uFAAuF;AACvF,eAAO,MAAM,wBAAwB,GAAI,OAAO,QAAQ,KAAG,OAAsC,CAAA;AAIjG;;;;;;GAMG;AACH,eAAO,MAAM,YAAY,GAAI,QAAQ,MAAM,EAAE,OAAO,QAAQ,KAAG,MAY9D,CAAA;AA4JD,eAAO,MAAM,kBAAkB,sIA8B7B,CAAA"}
|
package/dist/TransientRetry.js
CHANGED
|
@@ -96,8 +96,31 @@ const resolveOptions = (options) => ({
|
|
|
96
96
|
maxRetries: options.maxRetries ?? 3,
|
|
97
97
|
baseDelay: Duration.fromInputUnsafe(options.baseDelay ?? "1 second"),
|
|
98
98
|
flakyRetries: options.flakyRetries ?? 6,
|
|
99
|
-
flakyDelay: Duration.fromInputUnsafe(options.flakyDelay ?? "1 second")
|
|
99
|
+
flakyDelay: Duration.fromInputUnsafe(options.flakyDelay ?? "1 second"),
|
|
100
|
+
parseRetries: options.parseRetries ?? 2
|
|
100
101
|
});
|
|
102
|
+
/** A structured call whose text came back but did not decode as the requested JSON. */
|
|
103
|
+
export const isStructuredParseFailure = (error) => error._tag === "ParseError";
|
|
104
|
+
const repairReasonLimit = 400;
|
|
105
|
+
/**
|
|
106
|
+
* The prompt for a structured re-ask: the original, plus what went wrong
|
|
107
|
+
* with the previous reply. Quoting the failure is what turns a blind retry
|
|
108
|
+
* into a repair — the common causes (prose around the JSON, a missing
|
|
109
|
+
* required field, a string where a number was asked for) are all things the
|
|
110
|
+
* model fixes on sight.
|
|
111
|
+
*/
|
|
112
|
+
export const repairPrompt = (prompt, error) => {
|
|
113
|
+
const reason = error.message.trim();
|
|
114
|
+
const shown = reason.length <= repairReasonLimit ? reason : `${reason.slice(0, repairReasonLimit - 3)}...`;
|
|
115
|
+
return [
|
|
116
|
+
prompt,
|
|
117
|
+
"",
|
|
118
|
+
"Your previous reply could not be parsed as the requested JSON:",
|
|
119
|
+
shown,
|
|
120
|
+
"Reply again with ONLY the JSON object — no prose before or after it, no markdown",
|
|
121
|
+
"fences, every required field present, and values of the requested types."
|
|
122
|
+
].join("\n");
|
|
123
|
+
};
|
|
101
124
|
const backoff = (baseDelay, attempt) => Duration.times(baseDelay, 2 ** attempt);
|
|
102
125
|
const retryNotice = (events, what, attempt, maximum, error) => events.publish(Info.make({
|
|
103
126
|
message: `⟳ ${what} — retry ${attempt + 1}/${maximum}: ${error.message}`
|
|
@@ -128,6 +151,15 @@ const retryStream = (stream, what, options, events) => {
|
|
|
128
151
|
});
|
|
129
152
|
return loop(0, 0);
|
|
130
153
|
};
|
|
154
|
+
/**
|
|
155
|
+
* A structured call under all three budgets: `run(prompt)` is retried for
|
|
156
|
+
* transient and flaky failures as any effect is, and a parse failure re-asks
|
|
157
|
+
* with `repairPrompt` up to `parseRetries` times before it is surfaced.
|
|
158
|
+
*/
|
|
159
|
+
const retryStructured = (prompt, run, options, events) => {
|
|
160
|
+
const loop = (current, parseAttempt) => retryEffect(run(current), "structured", options, events).pipe(Effect.catchIf((error) => isStructuredParseFailure(error) && parseAttempt < options.parseRetries, (error) => waitForRetry(events, "structured output (repair retry)", parseAttempt, options.parseRetries, error, options.flakyDelay).pipe(Effect.andThen(Effect.suspend(() => loop(repairPrompt(prompt, error), parseAttempt + 1))))));
|
|
161
|
+
return loop(prompt, 0);
|
|
162
|
+
};
|
|
131
163
|
export const makeTransientRetry = Effect.fn("@llm4ts/flow/TransientRetry.make")(function* (underlying, retryOptions = {}) {
|
|
132
164
|
const events = yield* FlowEvents;
|
|
133
165
|
const options = resolveOptions(retryOptions);
|
|
@@ -135,8 +167,8 @@ export const makeTransientRetry = Effect.fn("@llm4ts/flow/TransientRetry.make")(
|
|
|
135
167
|
executeStream: (prompt) => retryStream(underlying.executeStream(prompt), "stream", options, events),
|
|
136
168
|
executeStreamWithHistory: (messages) => retryStream(underlying.executeStreamWithHistory(messages), "stream", options, events),
|
|
137
169
|
executeWithTools: (prompt, tools) => retryEffect(underlying.executeWithTools(prompt, tools), "tools", options, events),
|
|
138
|
-
executeStructured: (prompt, schema, jsonSchema) =>
|
|
139
|
-
executeStructuredWithUsage: (prompt, schema, jsonSchema) =>
|
|
170
|
+
executeStructured: (prompt, schema, jsonSchema) => retryStructured(prompt, (current) => underlying.executeStructured(current, schema, jsonSchema), options, events),
|
|
171
|
+
executeStructuredWithUsage: (prompt, schema, jsonSchema) => retryStructured(prompt, (current) => underlying.executeStructuredWithUsage(current, schema, jsonSchema), options, events),
|
|
140
172
|
isAvailable: underlying.isAvailable
|
|
141
173
|
});
|
|
142
174
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TransientRetry.js","sourceRoot":"","sources":["../src/TransientRetry.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"TransientRetry.js","sourceRoot":"","sources":["../src/TransientRetry.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@llm4ts/flow",
|
|
3
|
-
"version": "0.15.
|
|
3
|
+
"version": "0.15.1",
|
|
4
4
|
"description": "Effect-native LLM workflow, persistence, review, and repository automation",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -86,7 +86,7 @@
|
|
|
86
86
|
"typescript"
|
|
87
87
|
],
|
|
88
88
|
"dependencies": {
|
|
89
|
-
"@llm4ts/core": "0.15.
|
|
89
|
+
"@llm4ts/core": "0.15.1"
|
|
90
90
|
},
|
|
91
91
|
"peerDependencies": {
|
|
92
92
|
"effect": "4.0.0-beta.102"
|
package/src/TransientRetry.ts
CHANGED
|
@@ -119,6 +119,14 @@ export interface TransientRetryOptions {
|
|
|
119
119
|
readonly baseDelay?: Duration.Input
|
|
120
120
|
readonly flakyRetries?: number
|
|
121
121
|
readonly flakyDelay?: Duration.Input
|
|
122
|
+
/**
|
|
123
|
+
* Re-asks a structured call whose response could not be parsed as the
|
|
124
|
+
* requested JSON, with the parse failure quoted back to the model. The
|
|
125
|
+
* model's output is not deterministic, so a malformed or off-schema reply
|
|
126
|
+
* is usually a one-off; but a schema the model cannot satisfy fails every
|
|
127
|
+
* time, so this budget is small (default 2) and independent of the others.
|
|
128
|
+
*/
|
|
129
|
+
readonly parseRetries?: number
|
|
122
130
|
}
|
|
123
131
|
|
|
124
132
|
interface ResolvedTransientRetryOptions {
|
|
@@ -126,15 +134,43 @@ interface ResolvedTransientRetryOptions {
|
|
|
126
134
|
readonly baseDelay: Duration.Duration
|
|
127
135
|
readonly flakyRetries: number
|
|
128
136
|
readonly flakyDelay: Duration.Duration
|
|
137
|
+
readonly parseRetries: number
|
|
129
138
|
}
|
|
130
139
|
|
|
131
140
|
const resolveOptions = (options: TransientRetryOptions): ResolvedTransientRetryOptions => ({
|
|
132
141
|
maxRetries: options.maxRetries ?? 3,
|
|
133
142
|
baseDelay: Duration.fromInputUnsafe(options.baseDelay ?? "1 second"),
|
|
134
143
|
flakyRetries: options.flakyRetries ?? 6,
|
|
135
|
-
flakyDelay: Duration.fromInputUnsafe(options.flakyDelay ?? "1 second")
|
|
144
|
+
flakyDelay: Duration.fromInputUnsafe(options.flakyDelay ?? "1 second"),
|
|
145
|
+
parseRetries: options.parseRetries ?? 2
|
|
136
146
|
})
|
|
137
147
|
|
|
148
|
+
/** A structured call whose text came back but did not decode as the requested JSON. */
|
|
149
|
+
export const isStructuredParseFailure = (error: LlmError): boolean => error._tag === "ParseError"
|
|
150
|
+
|
|
151
|
+
const repairReasonLimit = 400
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* The prompt for a structured re-ask: the original, plus what went wrong
|
|
155
|
+
* with the previous reply. Quoting the failure is what turns a blind retry
|
|
156
|
+
* into a repair — the common causes (prose around the JSON, a missing
|
|
157
|
+
* required field, a string where a number was asked for) are all things the
|
|
158
|
+
* model fixes on sight.
|
|
159
|
+
*/
|
|
160
|
+
export const repairPrompt = (prompt: string, error: LlmError): string => {
|
|
161
|
+
const reason = error.message.trim()
|
|
162
|
+
const shown =
|
|
163
|
+
reason.length <= repairReasonLimit ? reason : `${reason.slice(0, repairReasonLimit - 3)}...`
|
|
164
|
+
return [
|
|
165
|
+
prompt,
|
|
166
|
+
"",
|
|
167
|
+
"Your previous reply could not be parsed as the requested JSON:",
|
|
168
|
+
shown,
|
|
169
|
+
"Reply again with ONLY the JSON object — no prose before or after it, no markdown",
|
|
170
|
+
"fences, every required field present, and values of the requested types."
|
|
171
|
+
].join("\n")
|
|
172
|
+
}
|
|
173
|
+
|
|
138
174
|
const backoff = (baseDelay: Duration.Duration, attempt: number): Duration.Duration =>
|
|
139
175
|
Duration.times(baseDelay, 2 ** attempt)
|
|
140
176
|
|
|
@@ -256,6 +292,39 @@ const retryStream = <R>(
|
|
|
256
292
|
return loop(0, 0)
|
|
257
293
|
}
|
|
258
294
|
|
|
295
|
+
/**
|
|
296
|
+
* A structured call under all three budgets: `run(prompt)` is retried for
|
|
297
|
+
* transient and flaky failures as any effect is, and a parse failure re-asks
|
|
298
|
+
* with `repairPrompt` up to `parseRetries` times before it is surfaced.
|
|
299
|
+
*/
|
|
300
|
+
const retryStructured = <A, R>(
|
|
301
|
+
prompt: string,
|
|
302
|
+
run: (prompt: string) => Effect.Effect<A, LlmError, R>,
|
|
303
|
+
options: ResolvedTransientRetryOptions,
|
|
304
|
+
events: FlowEvents["Service"]
|
|
305
|
+
): Effect.Effect<A, LlmError, R> => {
|
|
306
|
+
const loop = (current: string, parseAttempt: number): Effect.Effect<A, LlmError, R> =>
|
|
307
|
+
retryEffect(run(current), "structured", options, events).pipe(
|
|
308
|
+
Effect.catchIf(
|
|
309
|
+
(error) => isStructuredParseFailure(error) && parseAttempt < options.parseRetries,
|
|
310
|
+
(error) =>
|
|
311
|
+
waitForRetry(
|
|
312
|
+
events,
|
|
313
|
+
"structured output (repair retry)",
|
|
314
|
+
parseAttempt,
|
|
315
|
+
options.parseRetries,
|
|
316
|
+
error,
|
|
317
|
+
options.flakyDelay
|
|
318
|
+
).pipe(
|
|
319
|
+
Effect.andThen(
|
|
320
|
+
Effect.suspend(() => loop(repairPrompt(prompt, error), parseAttempt + 1))
|
|
321
|
+
)
|
|
322
|
+
)
|
|
323
|
+
)
|
|
324
|
+
)
|
|
325
|
+
return loop(prompt, 0)
|
|
326
|
+
}
|
|
327
|
+
|
|
259
328
|
export const makeTransientRetry = Effect.fn("@llm4ts/flow/TransientRetry.make")(function* (
|
|
260
329
|
underlying: LlmServiceShape,
|
|
261
330
|
retryOptions: TransientRetryOptions = {}
|
|
@@ -271,16 +340,16 @@ export const makeTransientRetry = Effect.fn("@llm4ts/flow/TransientRetry.make")(
|
|
|
271
340
|
executeWithTools: (prompt, tools) =>
|
|
272
341
|
retryEffect(underlying.executeWithTools(prompt, tools), "tools", options, events),
|
|
273
342
|
executeStructured: (prompt, schema, jsonSchema) =>
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
343
|
+
retryStructured(
|
|
344
|
+
prompt,
|
|
345
|
+
(current) => underlying.executeStructured(current, schema, jsonSchema),
|
|
277
346
|
options,
|
|
278
347
|
events
|
|
279
348
|
),
|
|
280
349
|
executeStructuredWithUsage: (prompt, schema, jsonSchema) =>
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
350
|
+
retryStructured(
|
|
351
|
+
prompt,
|
|
352
|
+
(current) => underlying.executeStructuredWithUsage(current, schema, jsonSchema),
|
|
284
353
|
options,
|
|
285
354
|
events
|
|
286
355
|
),
|