@dogpile/sdk 0.2.2 → 0.3.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/CHANGELOG.md +6 -0
- package/dist/browser/index.js +337 -22
- package/dist/browser/index.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/runtime/broadcast.d.ts +1 -0
- package/dist/runtime/broadcast.d.ts.map +1 -1
- package/dist/runtime/broadcast.js +27 -6
- package/dist/runtime/broadcast.js.map +1 -1
- package/dist/runtime/coordinator.d.ts +1 -0
- package/dist/runtime/coordinator.d.ts.map +1 -1
- package/dist/runtime/coordinator.js +45 -8
- package/dist/runtime/coordinator.js.map +1 -1
- package/dist/runtime/engine.d.ts.map +1 -1
- package/dist/runtime/engine.js +5 -0
- package/dist/runtime/engine.js.map +1 -1
- package/dist/runtime/sequential.d.ts +1 -0
- package/dist/runtime/sequential.d.ts.map +1 -1
- package/dist/runtime/sequential.js +24 -6
- package/dist/runtime/sequential.js.map +1 -1
- package/dist/runtime/shared.d.ts +1 -0
- package/dist/runtime/shared.d.ts.map +1 -1
- package/dist/runtime/shared.js +24 -6
- package/dist/runtime/shared.js.map +1 -1
- package/dist/runtime/termination.d.ts +6 -1
- package/dist/runtime/termination.d.ts.map +1 -1
- package/dist/runtime/termination.js +75 -0
- package/dist/runtime/termination.js.map +1 -1
- package/dist/runtime/validation.d.ts.map +1 -1
- package/dist/runtime/validation.js +22 -0
- package/dist/runtime/validation.js.map +1 -1
- package/dist/runtime/wrap-up.d.ts +26 -0
- package/dist/runtime/wrap-up.d.ts.map +1 -0
- package/dist/runtime/wrap-up.js +178 -0
- package/dist/runtime/wrap-up.js.map +1 -0
- package/dist/types.d.ts +68 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -1
- package/src/index.ts +3 -1
- package/src/runtime/broadcast.ts +49 -19
- package/src/runtime/coordinator.ts +83 -27
- package/src/runtime/engine.ts +6 -0
- package/src/runtime/sequential.ts +45 -19
- package/src/runtime/shared.ts +45 -19
- package/src/runtime/termination.ts +100 -0
- package/src/runtime/validation.ts +25 -0
- package/src/runtime/wrap-up.ts +257 -0
- package/src/types.ts +70 -0
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
BudgetCaps,
|
|
3
|
+
BudgetTier,
|
|
4
|
+
EngineOptions,
|
|
5
|
+
JsonObject,
|
|
6
|
+
ModelMessage,
|
|
7
|
+
Protocol,
|
|
8
|
+
ProtocolConfig,
|
|
9
|
+
RunEvent,
|
|
10
|
+
TerminationCondition,
|
|
11
|
+
TerminationEvaluationContext,
|
|
12
|
+
TranscriptEntry,
|
|
13
|
+
WrapUpHintConfig
|
|
14
|
+
} from "../types.js";
|
|
15
|
+
|
|
16
|
+
interface WrapUpControllerOptions {
|
|
17
|
+
readonly protocol: ProtocolConfig;
|
|
18
|
+
readonly tier: BudgetTier;
|
|
19
|
+
readonly budget?: BudgetCaps;
|
|
20
|
+
readonly terminate?: TerminationCondition;
|
|
21
|
+
readonly wrapUpHint?: WrapUpHintConfig;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
interface WrapUpContextOptions {
|
|
25
|
+
readonly runId: string;
|
|
26
|
+
readonly protocol: Protocol;
|
|
27
|
+
readonly protocolConfig?: ProtocolConfig;
|
|
28
|
+
readonly cost: TerminationEvaluationContext["cost"];
|
|
29
|
+
readonly events: readonly RunEvent[];
|
|
30
|
+
readonly transcript: readonly TranscriptEntry[];
|
|
31
|
+
readonly iteration?: number;
|
|
32
|
+
readonly protocolIteration?: number;
|
|
33
|
+
readonly elapsedMs?: number;
|
|
34
|
+
readonly metadata?: JsonObject;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function createWrapUpHintController(options: WrapUpControllerOptions) {
|
|
38
|
+
const hint = options.wrapUpHint;
|
|
39
|
+
const effectiveBudget = effectiveWrapUpBudget(options.budget, options.terminate);
|
|
40
|
+
let emitted = false;
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
context(context: WrapUpContextOptions): TerminationEvaluationContext {
|
|
44
|
+
return wrapUpEvaluationContext({
|
|
45
|
+
...context,
|
|
46
|
+
tier: options.tier,
|
|
47
|
+
...(effectiveBudget !== undefined ? { budget: effectiveBudget } : {})
|
|
48
|
+
});
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
inject(messages: readonly ModelMessage[], context: WrapUpContextOptions): readonly ModelMessage[] {
|
|
52
|
+
if (!hint || emitted) {
|
|
53
|
+
return messages;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const evaluationContext = wrapUpEvaluationContext({
|
|
57
|
+
...context,
|
|
58
|
+
tier: options.tier,
|
|
59
|
+
...(effectiveBudget !== undefined ? { budget: effectiveBudget } : {})
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
if (!shouldInjectWrapUpHint(hint, evaluationContext)) {
|
|
63
|
+
return messages;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const content = (hint.inject ?? defaultWrapUpHint)(evaluationContext);
|
|
67
|
+
emitted = true;
|
|
68
|
+
|
|
69
|
+
return [
|
|
70
|
+
messages[0] ?? { role: "system", content: "" },
|
|
71
|
+
{ role: "system", content },
|
|
72
|
+
...messages.slice(1)
|
|
73
|
+
];
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function wrapUpEvaluationContext(
|
|
79
|
+
options: WrapUpContextOptions & { readonly tier: BudgetTier; readonly budget?: BudgetCaps }
|
|
80
|
+
): TerminationEvaluationContext {
|
|
81
|
+
const iteration = options.iteration ?? options.transcript.length;
|
|
82
|
+
const elapsedMs = options.elapsedMs;
|
|
83
|
+
|
|
84
|
+
return {
|
|
85
|
+
runId: options.runId,
|
|
86
|
+
protocol: options.protocol,
|
|
87
|
+
tier: options.tier,
|
|
88
|
+
cost: options.cost,
|
|
89
|
+
events: options.events,
|
|
90
|
+
transcript: options.transcript,
|
|
91
|
+
...(options.protocolConfig !== undefined ? { protocolConfig: options.protocolConfig } : {}),
|
|
92
|
+
...(iteration !== undefined ? { iteration } : {}),
|
|
93
|
+
...(options.protocolIteration !== undefined ? { protocolIteration: options.protocolIteration } : {}),
|
|
94
|
+
...(elapsedMs !== undefined ? { elapsedMs } : {}),
|
|
95
|
+
...(options.budget !== undefined ? { budget: options.budget } : {}),
|
|
96
|
+
...(options.budget !== undefined
|
|
97
|
+
? {
|
|
98
|
+
remainingBudget: remainingBudget(options.budget, {
|
|
99
|
+
cost: options.cost,
|
|
100
|
+
iteration,
|
|
101
|
+
elapsedMs
|
|
102
|
+
})
|
|
103
|
+
}
|
|
104
|
+
: {}),
|
|
105
|
+
...(options.metadata !== undefined ? { metadata: options.metadata } : {})
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function shouldInjectWrapUpHint(hint: WrapUpHintConfig, context: TerminationEvaluationContext): boolean {
|
|
110
|
+
const iteration = context.iteration ?? context.transcript.length;
|
|
111
|
+
|
|
112
|
+
if (hint.atIteration !== undefined && iteration >= hint.atIteration) {
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (hint.atFraction === undefined || context.budget === undefined) {
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const fraction = hint.atFraction;
|
|
121
|
+
return (
|
|
122
|
+
capFractionReached(iteration, context.budget.maxIterations, fraction) ||
|
|
123
|
+
capFractionReached(context.elapsedMs, context.budget.timeoutMs, fraction)
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function capFractionReached(current: number | undefined, limit: number | undefined, fraction: number): boolean {
|
|
128
|
+
if (current === undefined || limit === undefined || limit <= 0) {
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return current / limit >= fraction;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function remainingBudget(
|
|
136
|
+
budget: BudgetCaps,
|
|
137
|
+
current: {
|
|
138
|
+
readonly cost: TerminationEvaluationContext["cost"];
|
|
139
|
+
readonly iteration: number | undefined;
|
|
140
|
+
readonly elapsedMs: number | undefined;
|
|
141
|
+
}
|
|
142
|
+
): NonNullable<TerminationEvaluationContext["remainingBudget"]> {
|
|
143
|
+
return {
|
|
144
|
+
...(budget.maxIterations !== undefined && current.iteration !== undefined
|
|
145
|
+
? { iterations: Math.max(0, budget.maxIterations - current.iteration) }
|
|
146
|
+
: {}),
|
|
147
|
+
...(budget.timeoutMs !== undefined && current.elapsedMs !== undefined
|
|
148
|
+
? { timeoutMs: Math.max(0, budget.timeoutMs - current.elapsedMs) }
|
|
149
|
+
: {}),
|
|
150
|
+
...(budget.maxUsd !== undefined ? { usd: Math.max(0, budget.maxUsd - current.cost.usd) } : {}),
|
|
151
|
+
...(budget.maxTokens !== undefined ? { tokens: Math.max(0, budget.maxTokens - current.cost.totalTokens) } : {})
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function defaultWrapUpHint(context: TerminationEvaluationContext): string {
|
|
156
|
+
const parts: string[] = [];
|
|
157
|
+
const remaining = context.remainingBudget;
|
|
158
|
+
|
|
159
|
+
if (remaining?.iterations !== undefined) {
|
|
160
|
+
const label = remaining.iterations === 1 ? "turn" : "turns";
|
|
161
|
+
parts.push(`${remaining.iterations} ${label} remaining`);
|
|
162
|
+
}
|
|
163
|
+
if (remaining?.timeoutMs !== undefined) {
|
|
164
|
+
parts.push(`${formatRemainingTime(remaining.timeoutMs)} remaining`);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const remainingText =
|
|
168
|
+
parts.length === 0 ? "You are approaching a configured hard limit." : `You are approaching a hard limit with ${parts.join(" and ")}.`;
|
|
169
|
+
return `[wrap-up] ${remainingText} If you have enough context, package your work now and return a final-ready answer.`;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function formatRemainingTime(timeoutMs: number): string {
|
|
173
|
+
if (timeoutMs >= 1_000) {
|
|
174
|
+
return `${(timeoutMs / 1_000).toFixed(1)}s`;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
return `${timeoutMs}ms`;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function effectiveWrapUpBudget(
|
|
181
|
+
budget: BudgetCaps | undefined,
|
|
182
|
+
terminate: EngineOptions["terminate"]
|
|
183
|
+
): BudgetCaps | undefined {
|
|
184
|
+
const terminationBudget = budgetCapsFromTermination(terminate);
|
|
185
|
+
if (!budget && !terminationBudget) {
|
|
186
|
+
return undefined;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const maxUsd = minCap(budget?.maxUsd, terminationBudget?.maxUsd);
|
|
190
|
+
const maxTokens = minCap(budget?.maxTokens, terminationBudget?.maxTokens);
|
|
191
|
+
const maxIterations = minCap(budget?.maxIterations, terminationBudget?.maxIterations);
|
|
192
|
+
const timeoutMs = minCap(budget?.timeoutMs, terminationBudget?.timeoutMs);
|
|
193
|
+
|
|
194
|
+
return {
|
|
195
|
+
...(maxUsd !== undefined ? { maxUsd } : {}),
|
|
196
|
+
...(maxTokens !== undefined ? { maxTokens } : {}),
|
|
197
|
+
...(maxIterations !== undefined ? { maxIterations } : {}),
|
|
198
|
+
...(timeoutMs !== undefined ? { timeoutMs } : {})
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
function budgetCapsFromTermination(condition: TerminationCondition | undefined): BudgetCaps | undefined {
|
|
203
|
+
if (!condition) {
|
|
204
|
+
return undefined;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
switch (condition.kind) {
|
|
208
|
+
case "budget":
|
|
209
|
+
return {
|
|
210
|
+
...(condition.maxUsd !== undefined ? { maxUsd: condition.maxUsd } : {}),
|
|
211
|
+
...(condition.maxTokens !== undefined ? { maxTokens: condition.maxTokens } : {}),
|
|
212
|
+
...(condition.maxIterations !== undefined ? { maxIterations: condition.maxIterations } : {}),
|
|
213
|
+
...(condition.timeoutMs !== undefined ? { timeoutMs: condition.timeoutMs } : {})
|
|
214
|
+
};
|
|
215
|
+
case "firstOf": {
|
|
216
|
+
let merged: BudgetCaps | undefined;
|
|
217
|
+
for (const child of condition.conditions) {
|
|
218
|
+
merged = mergeBudgetCaps(merged, budgetCapsFromTermination(child));
|
|
219
|
+
}
|
|
220
|
+
return merged;
|
|
221
|
+
}
|
|
222
|
+
case "convergence":
|
|
223
|
+
case "judge":
|
|
224
|
+
return undefined;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
function mergeBudgetCaps(left: BudgetCaps | undefined, right: BudgetCaps | undefined): BudgetCaps | undefined {
|
|
229
|
+
if (!left) {
|
|
230
|
+
return right;
|
|
231
|
+
}
|
|
232
|
+
if (!right) {
|
|
233
|
+
return left;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
const maxUsd = minCap(left.maxUsd, right.maxUsd);
|
|
237
|
+
const maxTokens = minCap(left.maxTokens, right.maxTokens);
|
|
238
|
+
const maxIterations = minCap(left.maxIterations, right.maxIterations);
|
|
239
|
+
const timeoutMs = minCap(left.timeoutMs, right.timeoutMs);
|
|
240
|
+
|
|
241
|
+
return {
|
|
242
|
+
...(maxUsd !== undefined ? { maxUsd } : {}),
|
|
243
|
+
...(maxTokens !== undefined ? { maxTokens } : {}),
|
|
244
|
+
...(maxIterations !== undefined ? { maxIterations } : {}),
|
|
245
|
+
...(timeoutMs !== undefined ? { timeoutMs } : {})
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
function minCap(left: number | undefined, right: number | undefined): number | undefined {
|
|
250
|
+
if (left === undefined) {
|
|
251
|
+
return right;
|
|
252
|
+
}
|
|
253
|
+
if (right === undefined) {
|
|
254
|
+
return left;
|
|
255
|
+
}
|
|
256
|
+
return Math.min(left, right);
|
|
257
|
+
}
|
package/src/types.ts
CHANGED
|
@@ -260,6 +260,12 @@ export interface SequentialProtocolConfig {
|
|
|
260
260
|
readonly kind: "sequential";
|
|
261
261
|
/** Maximum number of agent turns to execute; defaults to `3` for named protocols. */
|
|
262
262
|
readonly maxTurns?: number;
|
|
263
|
+
/**
|
|
264
|
+
* Floor for convergence and judge termination checks.
|
|
265
|
+
*
|
|
266
|
+
* Budget caps still apply immediately. Defaults to `0` when omitted.
|
|
267
|
+
*/
|
|
268
|
+
readonly minTurns?: number;
|
|
263
269
|
}
|
|
264
270
|
|
|
265
271
|
/**
|
|
@@ -274,6 +280,12 @@ export interface CoordinatorProtocolConfig {
|
|
|
274
280
|
readonly kind: "coordinator";
|
|
275
281
|
/** Maximum number of coordinator-managed turns to execute; defaults to `3` for named protocols. */
|
|
276
282
|
readonly maxTurns?: number;
|
|
283
|
+
/**
|
|
284
|
+
* Floor for convergence and judge termination checks.
|
|
285
|
+
*
|
|
286
|
+
* Budget caps still apply immediately. Defaults to `0` when omitted.
|
|
287
|
+
*/
|
|
288
|
+
readonly minTurns?: number;
|
|
277
289
|
}
|
|
278
290
|
|
|
279
291
|
/**
|
|
@@ -288,6 +300,12 @@ export interface BroadcastProtocolConfig {
|
|
|
288
300
|
readonly kind: "broadcast";
|
|
289
301
|
/** Maximum number of broadcast/merge rounds to execute; defaults to `2` for named protocols. */
|
|
290
302
|
readonly maxRounds?: number;
|
|
303
|
+
/**
|
|
304
|
+
* Floor for convergence and judge termination checks.
|
|
305
|
+
*
|
|
306
|
+
* Budget caps still apply immediately. Defaults to `0` when omitted.
|
|
307
|
+
*/
|
|
308
|
+
readonly minRounds?: number;
|
|
291
309
|
}
|
|
292
310
|
|
|
293
311
|
/**
|
|
@@ -302,6 +320,12 @@ export interface SharedProtocolConfig {
|
|
|
302
320
|
readonly kind: "shared";
|
|
303
321
|
/** Maximum number of shared-state turns to execute; defaults to `3` for named protocols. */
|
|
304
322
|
readonly maxTurns?: number;
|
|
323
|
+
/**
|
|
324
|
+
* Floor for convergence and judge termination checks.
|
|
325
|
+
*
|
|
326
|
+
* Budget caps still apply immediately. Defaults to `0` when omitted.
|
|
327
|
+
*/
|
|
328
|
+
readonly minTurns?: number;
|
|
305
329
|
/** Optional organizational memory snapshot visible to every shared agent. */
|
|
306
330
|
readonly organizationalMemory?: string;
|
|
307
331
|
}
|
|
@@ -526,6 +550,8 @@ export interface TerminationEvaluationContext {
|
|
|
526
550
|
readonly runId: string;
|
|
527
551
|
/** Protocol currently executing. */
|
|
528
552
|
readonly protocol: Protocol;
|
|
553
|
+
/** Exact normalized protocol configuration when the evaluator needs protocol-specific limits. */
|
|
554
|
+
readonly protocolConfig?: ProtocolConfig;
|
|
529
555
|
/** Cost/quality tier selected for the run. */
|
|
530
556
|
readonly tier: BudgetTier;
|
|
531
557
|
/** Current accumulated cost and token usage. */
|
|
@@ -536,8 +562,14 @@ export interface TerminationEvaluationContext {
|
|
|
536
562
|
readonly transcript: readonly TranscriptEntry[];
|
|
537
563
|
/** Completed model-turn iterations at the evaluation point. */
|
|
538
564
|
readonly iteration?: number;
|
|
565
|
+
/** Protocol-native progress count: turns for sequential/coordinator/shared, rounds for broadcast. */
|
|
566
|
+
readonly protocolIteration?: number;
|
|
539
567
|
/** Elapsed runtime in milliseconds at the evaluation point. */
|
|
540
568
|
readonly elapsedMs?: number;
|
|
569
|
+
/** Effective hard caps visible to this evaluation point. */
|
|
570
|
+
readonly budget?: BudgetCaps;
|
|
571
|
+
/** Remaining headroom computed from the effective hard caps at this evaluation point. */
|
|
572
|
+
readonly remainingBudget?: RemainingBudget;
|
|
541
573
|
/** Optional normalized judge or quality score in the inclusive range `0..1`. */
|
|
542
574
|
readonly quality?: NormalizedQualityScore;
|
|
543
575
|
/** Optional caller-owned judge decision for judge termination checks. */
|
|
@@ -546,6 +578,20 @@ export interface TerminationEvaluationContext {
|
|
|
546
578
|
readonly metadata?: JsonObject;
|
|
547
579
|
}
|
|
548
580
|
|
|
581
|
+
/**
|
|
582
|
+
* Remaining budget headroom derived from the current evaluation context.
|
|
583
|
+
*/
|
|
584
|
+
export interface RemainingBudget {
|
|
585
|
+
/** Remaining turn iterations before an iteration cap is reached. */
|
|
586
|
+
readonly iterations?: number;
|
|
587
|
+
/** Remaining elapsed milliseconds before a timeout cap is reached. */
|
|
588
|
+
readonly timeoutMs?: number;
|
|
589
|
+
/** Remaining spend in US dollars before a cost cap is reached. */
|
|
590
|
+
readonly usd?: number;
|
|
591
|
+
/** Remaining total tokens before a token cap is reached. */
|
|
592
|
+
readonly tokens?: number;
|
|
593
|
+
}
|
|
594
|
+
|
|
549
595
|
/**
|
|
550
596
|
* Decision returned by a termination condition evaluator.
|
|
551
597
|
*/
|
|
@@ -2547,6 +2593,26 @@ export interface BudgetCostTierOptions {
|
|
|
2547
2593
|
readonly budget?: BudgetCaps;
|
|
2548
2594
|
}
|
|
2549
2595
|
|
|
2596
|
+
/**
|
|
2597
|
+
* Advisory wrap-up hint injected into the next model turn near a hard cap.
|
|
2598
|
+
*/
|
|
2599
|
+
export interface WrapUpHintConfig {
|
|
2600
|
+
/** Absolute completed model-turn iteration at which to inject the hint once. */
|
|
2601
|
+
readonly atIteration?: number;
|
|
2602
|
+
/**
|
|
2603
|
+
* Fraction of `maxIterations` or `timeoutMs` at which to inject the hint once.
|
|
2604
|
+
*
|
|
2605
|
+
* `0.8` means the next turn after reaching 80% of a supported cap receives
|
|
2606
|
+
* the wrap-up hint.
|
|
2607
|
+
*/
|
|
2608
|
+
readonly atFraction?: number;
|
|
2609
|
+
/**
|
|
2610
|
+
* Optional custom hint builder. When omitted, the SDK injects a default
|
|
2611
|
+
* message that describes the remaining turn and/or time budget.
|
|
2612
|
+
*/
|
|
2613
|
+
readonly inject?: (context: TerminationEvaluationContext) => string;
|
|
2614
|
+
}
|
|
2615
|
+
|
|
2550
2616
|
/**
|
|
2551
2617
|
* Options accepted by the high-level single-call workflow APIs.
|
|
2552
2618
|
*
|
|
@@ -2576,6 +2642,8 @@ export interface DogpileOptions extends BudgetCostTierOptions {
|
|
|
2576
2642
|
readonly temperature?: number;
|
|
2577
2643
|
/** Optional composable termination policy for budget, convergence, judge, or firstOf stop conditions. */
|
|
2578
2644
|
readonly terminate?: TerminationCondition;
|
|
2645
|
+
/** Optional one-shot advisory hint injected into the next model turn near a hard cap. */
|
|
2646
|
+
readonly wrapUpHint?: WrapUpHintConfig;
|
|
2579
2647
|
/** Optional caller-owned evaluator that supplies quality and evaluation data. */
|
|
2580
2648
|
readonly evaluate?: RunEvaluator;
|
|
2581
2649
|
/** Optional deterministic seed recorded in the replay trace. */
|
|
@@ -2638,6 +2706,8 @@ export interface EngineOptions {
|
|
|
2638
2706
|
readonly budget?: Omit<Budget, "tier">;
|
|
2639
2707
|
/** Optional composable termination policy for budget, convergence, judge, or firstOf stop conditions. */
|
|
2640
2708
|
readonly terminate?: TerminationCondition;
|
|
2709
|
+
/** Optional one-shot advisory hint injected into the next model turn near a hard cap. */
|
|
2710
|
+
readonly wrapUpHint?: WrapUpHintConfig;
|
|
2641
2711
|
/** Optional caller-owned evaluator that supplies quality and evaluation data. */
|
|
2642
2712
|
readonly evaluate?: RunEvaluator;
|
|
2643
2713
|
/** Optional deterministic seed recorded in the replay trace. */
|