textopt 0.0.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.
Files changed (69) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +509 -0
  3. package/dist/bootstrap-search/index.cjs +308 -0
  4. package/dist/bootstrap-search/index.d.cts +162 -0
  5. package/dist/bootstrap-search/index.d.mts +162 -0
  6. package/dist/bootstrap-search/index.mjs +307 -0
  7. package/dist/cache-CuSo0NJ8.d.cts +24 -0
  8. package/dist/cache-CuSo0NJ8.d.mts +24 -0
  9. package/dist/concurrency-C-cFzWW2.cjs +44 -0
  10. package/dist/concurrency-D58PWeSk.mjs +39 -0
  11. package/dist/demos-B0pVQjYC.d.mts +88 -0
  12. package/dist/demos-B9BJiNKz.cjs +143 -0
  13. package/dist/demos-BTuzFNsp.d.cts +88 -0
  14. package/dist/demos-Degx6UmP.mjs +126 -0
  15. package/dist/evaluation-BV0nSZVx.mjs +521 -0
  16. package/dist/evaluation-OZOp6TB7.cjs +598 -0
  17. package/dist/file-cache.cjs +70 -0
  18. package/dist/file-cache.d.cts +21 -0
  19. package/dist/file-cache.d.mts +21 -0
  20. package/dist/file-cache.mjs +69 -0
  21. package/dist/gepa/index.cjs +1671 -0
  22. package/dist/gepa/index.d.cts +385 -0
  23. package/dist/gepa/index.d.mts +385 -0
  24. package/dist/gepa/index.mjs +1652 -0
  25. package/dist/index.cjs +266 -0
  26. package/dist/index.d.cts +221 -0
  27. package/dist/index.d.mts +221 -0
  28. package/dist/index.mjs +245 -0
  29. package/dist/math-COOofUyv.cjs +101 -0
  30. package/dist/math-DhrDmpFS.mjs +78 -0
  31. package/dist/mipro/index.cjs +739 -0
  32. package/dist/mipro/index.d.cts +372 -0
  33. package/dist/mipro/index.d.mts +372 -0
  34. package/dist/mipro/index.mjs +736 -0
  35. package/dist/opro/index.cjs +487 -0
  36. package/dist/opro/index.d.cts +230 -0
  37. package/dist/opro/index.d.mts +230 -0
  38. package/dist/opro/index.mjs +485 -0
  39. package/dist/optimizer-B7SpRwl7.d.cts +288 -0
  40. package/dist/optimizer-DqCoth_w.d.mts +288 -0
  41. package/dist/random-search/index.cjs +321 -0
  42. package/dist/random-search/index.d.cts +156 -0
  43. package/dist/random-search/index.d.mts +156 -0
  44. package/dist/random-search/index.mjs +319 -0
  45. package/dist/reflection-CQToe-5B.d.cts +283 -0
  46. package/dist/reflection-Cr_upzU0.d.mts +283 -0
  47. package/dist/reflection-DRfbk6hu.cjs +249 -0
  48. package/dist/reflection-mwMhrjs_.mjs +214 -0
  49. package/dist/rng-BR5MOedA.d.cts +22 -0
  50. package/dist/rng-BR5MOedA.d.mts +22 -0
  51. package/dist/rng-DbA_rPIo.cjs +67 -0
  52. package/dist/rng-Dtc5eZ_W.mjs +62 -0
  53. package/dist/sampling-CfHt7Gue.mjs +59 -0
  54. package/dist/sampling-DFo_7RNJ.d.mts +23 -0
  55. package/dist/sampling-Dars7ctR.cjs +64 -0
  56. package/dist/sampling-axOwfZf5.d.cts +23 -0
  57. package/dist/simba/index.cjs +709 -0
  58. package/dist/simba/index.d.cts +289 -0
  59. package/dist/simba/index.d.mts +289 -0
  60. package/dist/simba/index.mjs +700 -0
  61. package/dist/testing.cjs +155 -0
  62. package/dist/testing.d.cts +53 -0
  63. package/dist/testing.d.mts +53 -0
  64. package/dist/testing.mjs +148 -0
  65. package/dist/text--v4Ffbus.mjs +21 -0
  66. package/dist/text-CK_HB3su.cjs +26 -0
  67. package/dist/types-CWv4IQFF.d.cts +129 -0
  68. package/dist/types-CWv4IQFF.d.mts +129 -0
  69. package/package.json +135 -0
@@ -0,0 +1,283 @@
1
+ import { i as EvaluationBatch, n as Candidate, o as EvaluationPhase, s as EvaluationSplit, t as Adapter, u as TextModel } from "./types-CWv4IQFF.mjs";
2
+ import { t as CachedScore } from "./cache-CuSo0NJ8.mjs";
3
+ import { t as Rng } from "./rng-BR5MOedA.mjs";
4
+ //#region src/gepa/types.d.ts
5
+ /**
6
+ * One piece of evidence reflection reads: what went in, what came out, and how
7
+ * it scored. `Evidence` is the adapter's own slot — trace steps, retrieved
8
+ * documents, errors — typed rather than smuggled in through an index signature.
9
+ */
10
+ interface ReflectiveRecord<Evidence = unknown> {
11
+ inputs: unknown;
12
+ generatedOutputs: unknown;
13
+ feedback: string;
14
+ score?: number;
15
+ evidence?: Evidence;
16
+ }
17
+ /**
18
+ * Component name -> records shown to the reflection model for that component.
19
+ *
20
+ * Partial, not total: an adapter only fills the components it was asked to
21
+ * update, so a component with nothing to diagnose is simply absent.
22
+ */
23
+ type ReflectiveDataset<K extends string = string> = Partial<Record<K, ReflectiveRecord[]>>;
24
+ interface MakeReflectiveDatasetArgs<Datum, Trajectory, Output, K extends string = string> {
25
+ candidate: Candidate<K>;
26
+ batch: readonly Datum[];
27
+ evaluation: EvaluationBatch<Trajectory, Output>;
28
+ componentsToUpdate: readonly K[];
29
+ }
30
+ /** New text for the subset of components a proposal actually changed. */
31
+ type ComponentPatch<K extends string = string> = Partial<Record<K, string>>;
32
+ /**
33
+ * A component text that was proposed and lost on the minibatch. Showing these
34
+ * back to the reflection model is what stops a run from re-deriving the same
35
+ * dead end: only exact duplicates are filtered structurally, so without this
36
+ * the model can spend the whole budget circling one bad idea.
37
+ */
38
+ interface RejectedProposal {
39
+ text: string;
40
+ parentScore: number;
41
+ childScore: number;
42
+ }
43
+ interface ProposeArgs<K extends string = string> {
44
+ candidate: Candidate<K>;
45
+ reflectiveDataset: ReflectiveDataset<K>;
46
+ componentsToUpdate: readonly K[];
47
+ /** Component name -> texts already tried and rejected for it. */
48
+ rejectedProposals?: Partial<Record<K, RejectedProposal[]>>;
49
+ /**
50
+ * Which proposal this is in the run, counting from 0. Assigned when the
51
+ * iteration is planned rather than when it executes, so concurrent
52
+ * proposals get stable, distinct values instead of racing for a counter.
53
+ * The default proposer rotates its strategies on it.
54
+ */
55
+ attempt?: number;
56
+ reflect: TextModel;
57
+ signal?: AbortSignal;
58
+ }
59
+ /**
60
+ * An adapter GEPA can reflect against: evaluation, plus the traces reflection
61
+ * reads. `makeReflectiveDataset` is what turns a scored batch into the
62
+ * per-component evidence a reflection call is written from.
63
+ */
64
+ interface GepaAdapter<Datum, Trajectory = unknown, Output = unknown, K extends string = string> extends Adapter<Datum, Trajectory, Output, K> {
65
+ makeReflectiveDataset(args: MakeReflectiveDatasetArgs<Datum, Trajectory, Output, K>): Promise<ReflectiveDataset<K>> | ReflectiveDataset<K>;
66
+ proposeNewTexts?(args: ProposeArgs<K>): Promise<ComponentPatch<K>> | ComponentPatch<K>;
67
+ }
68
+ type CandidateSource = "seed" | "mutation" | "merge";
69
+ interface CandidateRecord<K extends string = string> {
70
+ id: number;
71
+ candidate: Candidate<K>;
72
+ parentIds: number[];
73
+ /**
74
+ * One entry per validation instance. `undefined` marks an instance the
75
+ * evaluation policy did not select for this candidate — unknown, not zero.
76
+ */
77
+ instanceScores: (number | undefined)[];
78
+ /** Mean over the instances that were scored. */
79
+ aggregateScore: number;
80
+ /** Mean of each objective over the evaluated validation instances. */
81
+ objectiveScores?: Record<string, number>;
82
+ source: CandidateSource;
83
+ updatedComponents: K[];
84
+ iteration: number;
85
+ /**
86
+ * Round-robin position this candidate resumes from the next time it is
87
+ * chosen as a parent. Per-candidate rather than global: a lineage that is
88
+ * only reselected every fifth iteration must still walk its own components
89
+ * one at a time instead of being pinned to whichever one the global counter
90
+ * happens to land on.
91
+ */
92
+ componentCursor: number;
93
+ }
94
+ /** What a Pareto frontier is taken over. */
95
+ type ParetoFrontier = "instance" | "objective" | "hybrid";
96
+ /** Read-only view handed to candidate selectors. */
97
+ interface SelectionState {
98
+ scoreMatrix: readonly (readonly (number | undefined)[])[];
99
+ aggregateScores: readonly number[];
100
+ /** Per-candidate objective means, absent when the adapter reports none. */
101
+ objectiveScores?: readonly (Readonly<Record<string, number>> | undefined)[];
102
+ }
103
+ type CandidateSelector = (args: {
104
+ state: SelectionState;
105
+ rng: Rng;
106
+ }) => number;
107
+ type ComponentSelector<K extends string = string> = (args: {
108
+ candidate: Candidate<K>;
109
+ /** This candidate's own round-robin position, advanced after each selection. */
110
+ cursor: number;
111
+ iteration: number;
112
+ rng: Rng;
113
+ }) => K[];
114
+ type AcceptancePolicy = (args: {
115
+ parentScores: readonly number[];
116
+ childScores: readonly number[];
117
+ }) => boolean;
118
+ /**
119
+ * Which validation instances a candidate is scored on, and how the best
120
+ * candidate is read back out of possibly partial coverage.
121
+ *
122
+ * A full sweep per accepted candidate is the published behaviour and the
123
+ * default. Swapping in a partial policy trades frontier fidelity for rollouts:
124
+ * candidates scored on different instances are no longer strictly comparable,
125
+ * which is why picking the best is the policy's job too.
126
+ */
127
+ interface ValEvaluationPolicy<Datum = unknown, K extends string = string> {
128
+ selectInstances(args: {
129
+ validationSet: readonly Datum[];
130
+ candidate: Candidate<K>;
131
+ records: readonly CandidateRecord<K>[];
132
+ iteration: number;
133
+ rng: Rng;
134
+ }): number[];
135
+ bestCandidate(records: readonly CandidateRecord<K>[]): number;
136
+ }
137
+ type GepaStopReason = "budgetExhausted" | "costExhausted" | "deadlineReached" | "reflectionBudgetExhausted" | "aborted" | "maxIterations";
138
+ type GepaEvent<K extends string = string> = {
139
+ type: "start";
140
+ components: K[];
141
+ validationSetSize: number;
142
+ } | {
143
+ type: "iterationStart";
144
+ iteration: number;
145
+ parentIds: number[];
146
+ } | {
147
+ type: "evaluation";
148
+ iteration: number;
149
+ phase: EvaluationPhase;
150
+ split: EvaluationSplit;
151
+ candidateId: number | null;
152
+ metricCalls: number;
153
+ cacheHits: number;
154
+ meanScore: number;
155
+ } | {
156
+ type: "proposal";
157
+ iteration: number;
158
+ parentId: number;
159
+ componentsToUpdate: K[];
160
+ changed: boolean;
161
+ } | {
162
+ type: "candidateAccepted";
163
+ iteration: number;
164
+ candidateId: number;
165
+ parentIds: number[];
166
+ aggregateScore: number;
167
+ source: CandidateSource;
168
+ } | {
169
+ type: "candidateRejected";
170
+ iteration: number;
171
+ parentId: number;
172
+ parentScore: number;
173
+ childScore: number;
174
+ source: CandidateSource;
175
+ /**
176
+ * "worse" lost to its parent on the minibatch. "notSelected" beat its
177
+ * parent but lost to a stronger proposal from the same iteration — it is
178
+ * not a dead end, and is never fed back to reflection as one.
179
+ */
180
+ reason: "worse" | "notSelected";
181
+ } | {
182
+ type: "error";
183
+ iteration: number;
184
+ err: unknown;
185
+ } | {
186
+ type: "finish";
187
+ reason: GepaStopReason;
188
+ bestCandidateId: number;
189
+ metricCalls: number;
190
+ /** The winner's held-out score, when a testSet was given. */
191
+ testScore?: number;
192
+ };
193
+ /**
194
+ * Everything needed to continue a run: the candidate pool with its scores, the
195
+ * budget already spent, the position of the random stream, and the bookkeeping
196
+ * that stops merges and proposals from being relitigated. Plain JSON — write it
197
+ * wherever you like and hand it back as `resumeFrom`.
198
+ *
199
+ * Deliberately not generic over component names. It leaves the process and
200
+ * comes back through `JSON.parse` with plain string keys, so the narrowing back
201
+ * to a run's own components happens once inside the engine, guarded by the
202
+ * fingerprint, rather than being a type the caller has to reconstruct.
203
+ *
204
+ * A resumed run follows the same trajectory an uninterrupted one would, as long
205
+ * as the batch sampler reports its state and the evaluation cache is either
206
+ * checkpointed or disabled — a cache that is neither leaves the resumed run
207
+ * paying again for rollouts the first one had already bought.
208
+ */
209
+ interface GepaSnapshot {
210
+ version: 1;
211
+ /**
212
+ * Identifies the run this checkpoint came from — seed candidate, instance
213
+ * ids and seed. Resuming against a different setup is refused rather than
214
+ * silently scoring old candidates against new data.
215
+ */
216
+ fingerprint: string;
217
+ records: CandidateRecord[];
218
+ iteration: number;
219
+ metricCalls: number;
220
+ reflectionCalls: number;
221
+ cacheHits: number;
222
+ rngState: number;
223
+ /** Whatever the batch sampler reports from `state()`, when it has one. */
224
+ sampler?: unknown;
225
+ rejectedProposals: Record<string, RejectedProposal[]>;
226
+ merge: {
227
+ attempts: string[];
228
+ descriptions: string[];
229
+ due: number;
230
+ tested: number;
231
+ lastIterationAccepted: boolean;
232
+ };
233
+ /** Cached instance scores, when the cache can enumerate them. */
234
+ cache?: [string, CachedScore][];
235
+ }
236
+ //#endregion
237
+ //#region src/gepa/reflection.d.ts
238
+ interface ReflectionPromptArgs {
239
+ componentName: string;
240
+ currentText: string;
241
+ records: readonly ReflectiveRecord[];
242
+ /** Texts already tried for this component that lost to their parent. */
243
+ rejected?: readonly RejectedProposal[];
244
+ }
245
+ type ReflectionPromptBuilder = (args: ReflectionPromptArgs) => string;
246
+ /**
247
+ * Adapted from the reflection prompt in the GEPA paper (Agrawal et al., 2025).
248
+ * The instruction to mine domain facts out of the traces matters as much as the
249
+ * instruction to fix failures — most of the lift comes from the model writing
250
+ * down knowledge the traces revealed.
251
+ */
252
+ declare function buildReflectionPrompt(args: ReflectionPromptArgs): string;
253
+ /**
254
+ * Cut rather than add. Reflective evolution only ever appends — every
255
+ * iteration diagnoses a failure and writes a rule preventing it — so an
256
+ * instruction grows monotonically until it is mostly edge cases that no longer
257
+ * fire. Nothing else in the loop ever removes one.
258
+ */
259
+ declare function buildSimplifyPrompt(args: ReflectionPromptArgs): string;
260
+ /**
261
+ * Replace a rule that fits the instances it was written from with the
262
+ * principle behind it. Feedback is drawn from minibatches, so a rule written
263
+ * to fix three examples routinely encodes those three examples.
264
+ */
265
+ declare function buildGeneralizePrompt(args: ReflectionPromptArgs): string;
266
+ /**
267
+ * Start from the evidence rather than from the incumbent. Every other strategy
268
+ * edits the current text, which anchors each proposal to whatever the search
269
+ * happened to reach first; this one is the only escape from a bad opening.
270
+ */
271
+ declare function buildRewritePrompt(args: ReflectionPromptArgs): string;
272
+ /**
273
+ * A rotation covering the four directions a proposal can move in: fix what is
274
+ * broken, cut what is dead, widen what is too narrow, and start over.
275
+ *
276
+ * Drawing a proposal k times from one template samples one direction k times.
277
+ * Rotating costs nothing extra — same call count, same rollouts — and is the
278
+ * cheapest diversity available. Opt in via `reflection.strategies`; the
279
+ * default stays the published single prompt.
280
+ */
281
+ declare function diverseReflectionStrategies(): ReflectionPromptBuilder[];
282
+ //#endregion
283
+ export { RejectedProposal as C, ReflectiveRecord as S, ValEvaluationPolicy as T, GepaStopReason as _, buildRewritePrompt as a, ProposeArgs as b, AcceptancePolicy as c, CandidateSource as d, ComponentPatch as f, GepaSnapshot as g, GepaEvent as h, buildReflectionPrompt as i, CandidateRecord as l, GepaAdapter as m, ReflectionPromptBuilder as n, buildSimplifyPrompt as o, ComponentSelector as p, buildGeneralizePrompt as r, diverseReflectionStrategies as s, ReflectionPromptArgs as t, CandidateSelector as u, MakeReflectiveDatasetArgs as v, SelectionState as w, ReflectiveDataset as x, ParetoFrontier as y };
@@ -0,0 +1,249 @@
1
+ const require_text = require("./text-CK_HB3su.cjs");
2
+ //#region src/gepa/reflection.ts
3
+ const TRUNCATION_MARKER = "… [truncated]";
4
+ const MIN_STRING_BUDGET = 40;
5
+ /**
6
+ * Adapted from the reflection prompt in the GEPA paper (Agrawal et al., 2025).
7
+ * The instruction to mine domain facts out of the traces matters as much as the
8
+ * instruction to fix failures — most of the lift comes from the model writing
9
+ * down knowledge the traces revealed.
10
+ */
11
+ function buildReflectionPrompt(args) {
12
+ const { componentName, currentText, records, rejected = [] } = args;
13
+ return [
14
+ `I gave an assistant the following instruction for the "${componentName}" component of a larger system:`,
15
+ "",
16
+ "<current_instruction>",
17
+ currentText,
18
+ "</current_instruction>",
19
+ "",
20
+ "Below are task inputs the assistant received, the outputs it produced, and feedback on how each output could be better:",
21
+ "",
22
+ "<examples>",
23
+ serializeRecords(records),
24
+ "</examples>",
25
+ ...rejected.length === 0 ? [] : [
26
+ "",
27
+ "These instructions have already been tried for this component and scored worse than the one they replaced. Do not propose them again, and do not propose a variation that repeats the idea that made them fail:",
28
+ "",
29
+ "<rejected_instructions>",
30
+ JSON.stringify(rejected, jsonSafeReplacer, 2),
31
+ "</rejected_instructions>"
32
+ ],
33
+ "",
34
+ "Write a new instruction for this component.",
35
+ "Read the inputs carefully and infer a detailed description of the task the component is solving, including its input format.",
36
+ "Read every output and its feedback. Identify all niche or domain-specific factual information the task depends on and state it explicitly in the instruction — the assistant will not have access to these examples in future.",
37
+ "If the assistant used a generalizable strategy that worked, describe that strategy.",
38
+ "If the feedback shows a recurring failure, add a precise rule that prevents it.",
39
+ "",
40
+ "Return only the new instruction, inside a ``` block."
41
+ ].join("\n");
42
+ }
43
+ /**
44
+ * Cut rather than add. Reflective evolution only ever appends — every
45
+ * iteration diagnoses a failure and writes a rule preventing it — so an
46
+ * instruction grows monotonically until it is mostly edge cases that no longer
47
+ * fire. Nothing else in the loop ever removes one.
48
+ */
49
+ function buildSimplifyPrompt(args) {
50
+ const { componentName, currentText, records } = args;
51
+ return [
52
+ `The instruction below drives the "${componentName}" component of a larger system. It has been edited many times and has accumulated rules.`,
53
+ "",
54
+ "<current_instruction>",
55
+ currentText,
56
+ "</current_instruction>",
57
+ "",
58
+ "Here is how it behaved on recent inputs, with feedback on each output:",
59
+ "",
60
+ "<examples>",
61
+ serializeRecords(records),
62
+ "</examples>",
63
+ "",
64
+ "Write a shorter instruction.",
65
+ "Remove any rule that is redundant, that restates something already said, that contradicts another rule, or that no longer earns the space it takes.",
66
+ "Keep every rule the examples show is load-bearing. The component must still behave the same way on the inputs above.",
67
+ "Do not add new rules. If nothing can be removed, say the same thing in fewer words.",
68
+ "",
69
+ "Return only the new instruction, inside a ``` block."
70
+ ].join("\n");
71
+ }
72
+ /**
73
+ * Replace a rule that fits the instances it was written from with the
74
+ * principle behind it. Feedback is drawn from minibatches, so a rule written
75
+ * to fix three examples routinely encodes those three examples.
76
+ */
77
+ function buildGeneralizePrompt(args) {
78
+ const { componentName, currentText, records } = args;
79
+ return [
80
+ `The instruction below drives the "${componentName}" component of a larger system.`,
81
+ "",
82
+ "<current_instruction>",
83
+ currentText,
84
+ "</current_instruction>",
85
+ "",
86
+ "It was written from a small sample of inputs, so parts of it may describe those specific inputs rather than the task. Here is how it behaved on recent inputs, with feedback on each output:",
87
+ "",
88
+ "<examples>",
89
+ serializeRecords(records),
90
+ "</examples>",
91
+ "",
92
+ "Write a new instruction that states the underlying principle instead of the special cases.",
93
+ "Where a rule names a specific input, value or phrasing, ask what general property that case is an instance of, and write that property.",
94
+ "Keep concrete domain facts that are genuinely fixed — names, thresholds, formats. Those are knowledge, not overfitting.",
95
+ "",
96
+ "Return only the new instruction, inside a ``` block."
97
+ ].join("\n");
98
+ }
99
+ /**
100
+ * Start from the evidence rather than from the incumbent. Every other strategy
101
+ * edits the current text, which anchors each proposal to whatever the search
102
+ * happened to reach first; this one is the only escape from a bad opening.
103
+ */
104
+ function buildRewritePrompt(args) {
105
+ const { componentName, records } = args;
106
+ return [
107
+ `Write the instruction for the "${componentName}" component of a larger system, from scratch.`,
108
+ "",
109
+ "Below are task inputs the component received, the outputs it produced, and feedback on how each output could be better:",
110
+ "",
111
+ "<examples>",
112
+ serializeRecords(records),
113
+ "</examples>",
114
+ "",
115
+ "You are deliberately not being shown the instruction currently in use. Work out what the component is for from the inputs and outputs alone.",
116
+ "Infer the task, its input format, and what a correct output looks like.",
117
+ "State explicitly any domain-specific facts the task depends on — the component will not have access to these examples in future.",
118
+ "",
119
+ "Return only the new instruction, inside a ``` block."
120
+ ].join("\n");
121
+ }
122
+ /**
123
+ * A rotation covering the four directions a proposal can move in: fix what is
124
+ * broken, cut what is dead, widen what is too narrow, and start over.
125
+ *
126
+ * Drawing a proposal k times from one template samples one direction k times.
127
+ * Rotating costs nothing extra — same call count, same rollouts — and is the
128
+ * cheapest diversity available. Opt in via `reflection.strategies`; the
129
+ * default stays the published single prompt.
130
+ */
131
+ function diverseReflectionStrategies() {
132
+ return [
133
+ buildReflectionPrompt,
134
+ buildSimplifyPrompt,
135
+ buildGeneralizePrompt,
136
+ buildRewritePrompt
137
+ ];
138
+ }
139
+ /**
140
+ * Trims a reflective dataset down to what one prompt should carry: the worst
141
+ * scoring records first, since reflection is about diagnosing failures, and
142
+ * long strings cut to a share of the character budget.
143
+ */
144
+ function limitReflectiveRecords(args) {
145
+ const { records, maxRecords, maxCharacters } = args;
146
+ let kept = [...records];
147
+ if (maxRecords !== void 0 && kept.length > maxRecords) kept = kept.map((record, position) => ({
148
+ record,
149
+ position
150
+ })).sort((a, b) => (a.record.score ?? Number.POSITIVE_INFINITY) - (b.record.score ?? Number.POSITIVE_INFINITY)).slice(0, maxRecords).sort((a, b) => a.position - b.position).map((entry) => entry.record);
151
+ if (maxCharacters === void 0 || kept.length === 0) return kept;
152
+ const perRecord = Math.max(MIN_STRING_BUDGET, Math.floor(maxCharacters / kept.length));
153
+ kept = kept.map((record) => truncateStrings(record, perRecord));
154
+ while (kept.length > 1 && serializeRecords(kept).length > maxCharacters) kept.pop();
155
+ return kept;
156
+ }
157
+ /**
158
+ * Default instruction proposer: one reflection call per component being
159
+ * updated. Adapters override this via `proposeNewTexts` when components need
160
+ * coupled updates or a structured proposal format; `buildPrompt` is the
161
+ * lighter seam for changing only the wording.
162
+ */
163
+ function createDefaultProposer(options = {}) {
164
+ const { buildPrompt, strategies, limits = {} } = options;
165
+ if (buildPrompt !== void 0 && strategies !== void 0) throw new Error("createDefaultProposer takes buildPrompt or strategies, not both");
166
+ if (strategies !== void 0 && strategies.length === 0) throw new Error("createDefaultProposer requires a non-empty strategies list");
167
+ const rotation = strategies ?? [buildPrompt ?? buildReflectionPrompt];
168
+ return async (args) => {
169
+ const { candidate, reflectiveDataset, componentsToUpdate, rejectedProposals, attempt = 0, reflect, signal } = args;
170
+ const proposed = {};
171
+ const strategy = rotation[attempt % rotation.length];
172
+ for (const componentName of componentsToUpdate) {
173
+ const records = reflectiveDataset[componentName];
174
+ if (records === void 0 || records.length === 0) continue;
175
+ const currentText = candidate[componentName] ?? "";
176
+ const response = await reflect({
177
+ prompt: strategy({
178
+ componentName,
179
+ currentText,
180
+ records: limitReflectiveRecords({
181
+ records,
182
+ ...limits
183
+ }),
184
+ rejected: rejectedProposals?.[componentName]
185
+ }),
186
+ signal
187
+ });
188
+ const newText = require_text.parseProposedText(response);
189
+ if (newText.length > 0 && newText !== currentText) proposed[componentName] = newText;
190
+ }
191
+ return proposed;
192
+ };
193
+ }
194
+ function serializeRecords(records) {
195
+ return JSON.stringify(records, jsonSafeReplacer, 2);
196
+ }
197
+ /** Recursive so a long trace buried in a nested output is cut too. */
198
+ function truncateStrings(value, budget) {
199
+ if (typeof value === "string") return value.length <= budget ? value : `${value.slice(0, budget)}${TRUNCATION_MARKER}`;
200
+ if (Array.isArray(value)) return value.map((item) => truncateStrings(item, budget));
201
+ if (value !== null && typeof value === "object") return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, truncateStrings(item, budget)]));
202
+ return value;
203
+ }
204
+ function jsonSafeReplacer(_key, value) {
205
+ if (value instanceof Error) return {
206
+ name: value.name,
207
+ message: value.message
208
+ };
209
+ if (value instanceof Map) return Object.fromEntries(value);
210
+ if (value instanceof Set) return [...value];
211
+ return value;
212
+ }
213
+ //#endregion
214
+ Object.defineProperty(exports, "buildGeneralizePrompt", {
215
+ enumerable: true,
216
+ get: function() {
217
+ return buildGeneralizePrompt;
218
+ }
219
+ });
220
+ Object.defineProperty(exports, "buildReflectionPrompt", {
221
+ enumerable: true,
222
+ get: function() {
223
+ return buildReflectionPrompt;
224
+ }
225
+ });
226
+ Object.defineProperty(exports, "buildRewritePrompt", {
227
+ enumerable: true,
228
+ get: function() {
229
+ return buildRewritePrompt;
230
+ }
231
+ });
232
+ Object.defineProperty(exports, "buildSimplifyPrompt", {
233
+ enumerable: true,
234
+ get: function() {
235
+ return buildSimplifyPrompt;
236
+ }
237
+ });
238
+ Object.defineProperty(exports, "createDefaultProposer", {
239
+ enumerable: true,
240
+ get: function() {
241
+ return createDefaultProposer;
242
+ }
243
+ });
244
+ Object.defineProperty(exports, "diverseReflectionStrategies", {
245
+ enumerable: true,
246
+ get: function() {
247
+ return diverseReflectionStrategies;
248
+ }
249
+ });