@proposit/proposit-core 2.3.1 → 2.4.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.
Files changed (90) hide show
  1. package/dist/cli/builder-repl.d.ts +3 -0
  2. package/dist/cli/builder-repl.d.ts.map +1 -0
  3. package/dist/cli/builder-repl.js +174 -0
  4. package/dist/cli/builder-repl.js.map +1 -0
  5. package/dist/extensions/builder/distill.d.ts +38 -0
  6. package/dist/extensions/builder/distill.d.ts.map +1 -0
  7. package/dist/extensions/builder/distill.js +81 -0
  8. package/dist/extensions/builder/distill.js.map +1 -0
  9. package/dist/extensions/builder/index.d.ts +7 -0
  10. package/dist/extensions/builder/index.d.ts.map +1 -0
  11. package/dist/extensions/builder/index.js +11 -0
  12. package/dist/extensions/builder/index.js.map +1 -0
  13. package/dist/extensions/builder/review.d.ts +11 -0
  14. package/dist/extensions/builder/review.d.ts.map +1 -0
  15. package/dist/extensions/builder/review.js +32 -0
  16. package/dist/extensions/builder/review.js.map +1 -0
  17. package/dist/extensions/builder/simulate.d.ts +12 -0
  18. package/dist/extensions/builder/simulate.d.ts.map +1 -0
  19. package/dist/extensions/builder/simulate.js +33 -0
  20. package/dist/extensions/builder/simulate.js.map +1 -0
  21. package/dist/extensions/openai/provider.d.ts.map +1 -1
  22. package/dist/extensions/openai/provider.js +3 -0
  23. package/dist/extensions/openai/provider.js.map +1 -1
  24. package/dist/extensions/openai/types.d.ts +2 -0
  25. package/dist/extensions/openai/types.d.ts.map +1 -1
  26. package/dist/lib/conversation/contract.d.ts +16 -0
  27. package/dist/lib/conversation/contract.d.ts.map +1 -0
  28. package/dist/lib/conversation/contract.js +9 -0
  29. package/dist/lib/conversation/contract.js.map +1 -0
  30. package/dist/lib/conversation/conversation.d.ts +43 -0
  31. package/dist/lib/conversation/conversation.d.ts.map +1 -0
  32. package/dist/lib/conversation/conversation.js +65 -0
  33. package/dist/lib/conversation/conversation.js.map +1 -0
  34. package/dist/lib/conversation/index.d.ts +8 -0
  35. package/dist/lib/conversation/index.d.ts.map +1 -0
  36. package/dist/lib/conversation/index.js +7 -0
  37. package/dist/lib/conversation/index.js.map +1 -0
  38. package/dist/lib/conversation/turn.d.ts +55 -0
  39. package/dist/lib/conversation/turn.d.ts.map +1 -0
  40. package/dist/lib/conversation/turn.js +112 -0
  41. package/dist/lib/conversation/turn.js.map +1 -0
  42. package/dist/lib/core/expression-manager-checks.d.ts +73 -0
  43. package/dist/lib/core/expression-manager-checks.d.ts.map +1 -0
  44. package/dist/lib/core/expression-manager-checks.js +355 -0
  45. package/dist/lib/core/expression-manager-checks.js.map +1 -0
  46. package/dist/lib/core/expression-manager-dirty-set.d.ts +21 -0
  47. package/dist/lib/core/expression-manager-dirty-set.d.ts.map +1 -0
  48. package/dist/lib/core/expression-manager-dirty-set.js +93 -0
  49. package/dist/lib/core/expression-manager-dirty-set.js.map +1 -0
  50. package/dist/lib/core/expression-manager-invariants.d.ts +14 -0
  51. package/dist/lib/core/expression-manager-invariants.d.ts.map +1 -0
  52. package/dist/lib/core/expression-manager-invariants.js +171 -0
  53. package/dist/lib/core/expression-manager-invariants.js.map +1 -0
  54. package/dist/lib/core/expression-manager.d.ts +2 -3
  55. package/dist/lib/core/expression-manager.d.ts.map +1 -1
  56. package/dist/lib/core/expression-manager.js +18 -523
  57. package/dist/lib/core/expression-manager.js.map +1 -1
  58. package/dist/lib/index.d.ts +4 -0
  59. package/dist/lib/index.d.ts.map +1 -1
  60. package/dist/lib/index.js +6 -0
  61. package/dist/lib/index.js.map +1 -1
  62. package/dist/lib/llm/index.d.ts +1 -1
  63. package/dist/lib/llm/index.d.ts.map +1 -1
  64. package/dist/lib/llm/types.d.ts +13 -0
  65. package/dist/lib/llm/types.d.ts.map +1 -1
  66. package/dist/lib/parsing/prompt-builder.d.ts.map +1 -1
  67. package/dist/lib/parsing/prompt-builder.js +13 -5
  68. package/dist/lib/parsing/prompt-builder.js.map +1 -1
  69. package/dist/lib/pipelines/index.d.ts +4 -2
  70. package/dist/lib/pipelines/index.d.ts.map +1 -1
  71. package/dist/lib/pipelines/index.js +2 -1
  72. package/dist/lib/pipelines/index.js.map +1 -1
  73. package/dist/lib/pipelines/llm-stage-helpers.d.ts +126 -0
  74. package/dist/lib/pipelines/llm-stage-helpers.d.ts.map +1 -0
  75. package/dist/lib/pipelines/llm-stage-helpers.js +567 -0
  76. package/dist/lib/pipelines/llm-stage-helpers.js.map +1 -0
  77. package/dist/lib/pipelines/scheduler.d.ts +62 -0
  78. package/dist/lib/pipelines/scheduler.d.ts.map +1 -0
  79. package/dist/lib/pipelines/{execute.js → scheduler.js} +8 -325
  80. package/dist/lib/pipelines/scheduler.js.map +1 -0
  81. package/dist/lib/pipelines/{execute.d.ts → single-stage.d.ts} +2 -22
  82. package/dist/lib/pipelines/{execute.d.ts.map → single-stage.d.ts.map} +1 -1
  83. package/dist/lib/pipelines/single-stage.js +333 -0
  84. package/dist/lib/pipelines/single-stage.js.map +1 -0
  85. package/dist/lib/pipelines/stage-helpers.d.ts +4 -123
  86. package/dist/lib/pipelines/stage-helpers.d.ts.map +1 -1
  87. package/dist/lib/pipelines/stage-helpers.js +28 -567
  88. package/dist/lib/pipelines/stage-helpers.js.map +1 -1
  89. package/package.json +13 -3
  90. package/dist/lib/pipelines/execute.js.map +0 -1
@@ -0,0 +1,567 @@
1
+ // The `llmStage` implementation and its supporting package-internal seam.
2
+ //
3
+ // `llmStage`'s body is factored into two package-internal seam functions
4
+ // — `buildLlmRequest` (prompt-build + `TLlmRequest` assembly) and
5
+ // `validateLlmOutcome` (parse → `Value.Check` → outcome/retry
6
+ // classification) — so the SAME logic backs both the in-process
7
+ // `llmStage.run` retry loop AND the launch/complete split
8
+ // (`launchStage`/`completeStage`, in `single-stage.ts`). None of this is
9
+ // exported from the package: there is no consumer use case, and
10
+ // `llmStage`'s public return type stays `TStage<TOutput>` (it does NOT
11
+ // widen). The resolved config rides an internal-symbol-keyed,
12
+ // non-enumerable carrier on the returned stage object, recovered only by
13
+ // the package-internal `readLlmStageConfig`.
14
+ //
15
+ // `stage-helpers.ts` re-exports every name this module exports (and
16
+ // nothing else moved) so the ~20 existing direct-import call sites under
17
+ // `src/extensions/` and the public barrel see no path change.
18
+ import { Pointer, Value } from "typebox/value";
19
+ import { debugMaxLengthTruncation } from "./debug-log.js";
20
+ import { LLM_NON_RETRYABLE_ERROR, LLM_QUOTA_EXHAUSTED, LLM_RATE_LIMITED, LLM_TRANSIENT_ERROR, LLM_UNKNOWN_ERROR, OUTPUT_SCHEMA_INVALID, } from "./failure-codes.js";
21
+ import { StageAbortedError, stashTokenUsage, DEFAULT_RETRY_POLICY, } from "./stage-helpers.js";
22
+ const TRUNCATION_SUFFIX = "…<truncated>";
23
+ function truncateValidationError(error, capBytes) {
24
+ // NOTE: `capBytes` is measured in JavaScript `string.length` —
25
+ // UTF-16 code units, not UTF-8 bytes. The spec (§6.3) phrases the
26
+ // cap as "bytes"; for ASCII-heavy validation errors the two are
27
+ // equal, and for non-ASCII paths a 2048 cap is roughly 2–4 KB of
28
+ // UTF-8 depending on character distribution. We accept this drift
29
+ // for V1: realistic TypeBox validation errors are short and
30
+ // English; a future polish pass can switch to
31
+ // `new TextEncoder().encode(error).length` if a real workload
32
+ // shows the distinction matters.
33
+ if (error.length <= capBytes) {
34
+ return error;
35
+ }
36
+ const head = Math.max(0, capBytes - TRUNCATION_SUFFIX.length);
37
+ return error.slice(0, head) + TRUNCATION_SUFFIX;
38
+ }
39
+ /**
40
+ * Thrown internally by `llmStage` after retry exhaustion. The
41
+ * executor catches it and converts it into a `ProcessingFailure`.
42
+ */
43
+ export class LlmStageRetryExhaustedError extends Error {
44
+ reason;
45
+ code;
46
+ attempts;
47
+ stageId;
48
+ failureContext;
49
+ constructor(args) {
50
+ super(args.message);
51
+ this.name = "LlmStageRetryExhaustedError";
52
+ this.stageId = args.stageId;
53
+ this.reason = args.reason;
54
+ this.code = args.code;
55
+ this.attempts = args.attempts;
56
+ this.failureContext = args.context;
57
+ }
58
+ }
59
+ function classifyError(err) {
60
+ if (typeof err !== "object" || err === null) {
61
+ return "non_retryable";
62
+ }
63
+ const tag = err.retryReason;
64
+ if (tag === "transient" ||
65
+ tag === "rate_limit" ||
66
+ tag === "quota_exhausted") {
67
+ return tag;
68
+ }
69
+ return "non_retryable";
70
+ }
71
+ async function sleep(ms, signal) {
72
+ if (ms <= 0)
73
+ return;
74
+ if (signal.aborted)
75
+ return;
76
+ await new Promise((resolve) => {
77
+ const timer = setTimeout(() => {
78
+ signal.removeEventListener("abort", onAbort);
79
+ resolve();
80
+ }, ms);
81
+ const onAbort = () => {
82
+ clearTimeout(timer);
83
+ signal.removeEventListener("abort", onAbort);
84
+ resolve();
85
+ };
86
+ signal.addEventListener("abort", onAbort, { once: true });
87
+ });
88
+ }
89
+ function emitRetry(ctx, stageId, attempt, reason) {
90
+ const event = {
91
+ kind: "stage:retry",
92
+ stageId,
93
+ attempt,
94
+ reason,
95
+ at: now(),
96
+ };
97
+ ctx.emit(event);
98
+ }
99
+ function now() {
100
+ return typeof performance !== "undefined" && performance.now
101
+ ? performance.now()
102
+ : Date.now();
103
+ }
104
+ // Internal-symbol key for the config carrier. Not exported, so no consumer
105
+ // can read or forge it; only this module's `readLlmStageConfig` recovers it.
106
+ const LLM_STAGE_CONFIG = Symbol("propositLlmStageConfig");
107
+ /**
108
+ * Recover the resolved `llmStage` config from a stage built by
109
+ * `llmStage`. Returns `undefined` for any stage that is not an LLM stage
110
+ * (a deterministic / sub-pipeline stage carries no config). Package-internal.
111
+ */
112
+ export function readLlmStageConfig(stage) {
113
+ return stage[LLM_STAGE_CONFIG];
114
+ }
115
+ /**
116
+ * True iff `stage` is an LLM-background stage — one built by `llmStage` that
117
+ * carries the resolved LLM config and is therefore driven by `launchStage` /
118
+ * `completeStage`. False for deterministic and sub-pipeline stages (drive those
119
+ * with `executeStage`). Mirrors exactly the check `launchStage`/`completeStage`
120
+ * apply internally, so a consumer driving a pipeline out-of-process can route a
121
+ * stage to the right driver without catching a thrown `PipelineConfigurationError`.
122
+ */
123
+ export function isLlmStage(stage) {
124
+ return readLlmStageConfig(stage) != null;
125
+ }
126
+ /**
127
+ * Append the retry-suffix the in-process loop adds after a failed
128
+ * schema-validation attempt. Shared by the loop and `launchStage` (so a
129
+ * re-launched attempt 2+ rebuilds the identical `userMessage`).
130
+ * Package-internal.
131
+ */
132
+ export function applyRetrySuffix(baseUser, validationError, errorCap) {
133
+ const truncated = truncateValidationError(validationError, errorCap);
134
+ return (baseUser +
135
+ "\n\nYour previous response failed schema validation: " +
136
+ truncated +
137
+ ". Please retry conforming to the schema.");
138
+ }
139
+ // Resolved error-cap for a config's retry policy (the per-retry appended
140
+ // validation-error byte bound), defaulted the same way the factory does.
141
+ function resolveErrorCap(policy) {
142
+ return (policy.maxAppendedErrorBytes ??
143
+ DEFAULT_RETRY_POLICY.maxAppendedErrorBytes ??
144
+ 2048);
145
+ }
146
+ /**
147
+ * Front half of the seam: build the per-attempt prompts + `TLlmRequest`.
148
+ * `userMessage` overrides the prompt's user message (the loop / launch
149
+ * pass the retry-suffixed message on attempt 2+); it defaults to
150
+ * `buildPrompt(ctx).user`. The returned `req` carries NO `onResponseCreated`
151
+ * — the in-process loop attaches its own emitter; the launch path uses the
152
+ * submit return value instead. Package-internal.
153
+ */
154
+ export function buildLlmRequest(cfg, ctx, userMessage) {
155
+ const prompt = cfg.buildPrompt(ctx);
156
+ const user = userMessage ?? prompt.user;
157
+ const req = {
158
+ model: cfg.model,
159
+ reasoningEffort: cfg.reasoningEffort,
160
+ systemPrompt: prompt.system,
161
+ userMessage: user,
162
+ outputSchema: cfg.outputSchema,
163
+ tools: cfg.tools,
164
+ maxOutputTokens: cfg.maxOutputTokens,
165
+ signal: ctx.signal,
166
+ };
167
+ return { req, prompts: { system: prompt.system, user } };
168
+ }
169
+ // The genuinely-shared validation core: check a PARSED output value
170
+ // against the stage schema and format the validation error. Used by both
171
+ // the in-process loop (output already parsed by the provider) and
172
+ // `validateLlmOutcome`'s completed branch (output parsed from raw text).
173
+ // Truncate every string longer than its schema's `maxLength` to that cap,
174
+ // mutating `value` in place. Driven off the validator's own `maxLength`
175
+ // errors (which carry the JSON-pointer path + the limit), so it handles
176
+ // nested objects, arrays, and discriminated unions without walking the
177
+ // schema by hand. Re-runs because a union surfaces a failing variant's
178
+ // inner errors only once its siblings are reconciled; truncation is
179
+ // monotonic (strings only shrink) so the loop converges. The pass cap is a
180
+ // backstop against a degenerate schema.
181
+ //
182
+ // Truncation is non-fatal (ingestion output is human-proofread before
183
+ // publish), so it does not surface to the caller. It does emit a
184
+ // debug-gated breadcrumb per clipped field — the only signal of whether
185
+ // the upstream length steering (shrunk wire `maxLength` + budget hint)
186
+ // is still letting overshoots through. `stageId` tags the breadcrumb so
187
+ // it groups with the stage's other diagnostic lines.
188
+ function clampMaxLengthStrings(stageId, schema, value) {
189
+ for (let pass = 0; pass < 16; pass++) {
190
+ let changed = false;
191
+ for (const err of Value.Errors(schema, value)) {
192
+ if (err.keyword !== "maxLength")
193
+ continue;
194
+ const limit = err.params.limit;
195
+ const current = Pointer.Get(value, err.instancePath);
196
+ if (typeof current === "string" && current.length > limit) {
197
+ debugMaxLengthTruncation({
198
+ stageId,
199
+ instancePath: err.instancePath,
200
+ limit,
201
+ originalLength: current.length,
202
+ });
203
+ Pointer.Set(value, err.instancePath, current.slice(0, limit));
204
+ changed = true;
205
+ }
206
+ }
207
+ if (!changed)
208
+ break;
209
+ }
210
+ }
211
+ function checkLlmOutput(cfg, output) {
212
+ if (Value.Check(cfg.outputSchema, output)) {
213
+ return { valid: true };
214
+ }
215
+ // OpenAI strict structured-output IGNORES JSON-Schema string `maxLength`,
216
+ // so a model can return an over-long string the schema forbids — a
217
+ // recoverable issue that must NOT fail the whole stage. Truncate any
218
+ // over-long string to its declared cap (in place) and re-check, rather
219
+ // than rejecting the output and halting the pipeline.
220
+ clampMaxLengthStrings(cfg.id, cfg.outputSchema, output);
221
+ if (Value.Check(cfg.outputSchema, output)) {
222
+ return { valid: true };
223
+ }
224
+ const errors = [...Value.Errors(cfg.outputSchema, output)];
225
+ const validationError = errors
226
+ .map((e) => `${e.instancePath}: ${e.message}`)
227
+ .join("; ");
228
+ return { valid: false, validationError };
229
+ }
230
+ /**
231
+ * Back half of the seam: turn a retrieved background response (RAW
232
+ * assistant text + terminal status + `incompleteReason`) into an outcome
233
+ * + optional typed output + a retry classification.
234
+ *
235
+ * The parse + `Value.Check` half is genuinely shared with the in-process
236
+ * loop (via `checkLlmOutput`). The status/reason → outcome+retry mapping
237
+ * is a DELIBERATE `lib/`-side MIRROR of the OpenAI provider's
238
+ * classification (`extensions/openai/provider.ts`): `src/lib/` may not
239
+ * import the extension classifier (the zero-SDK-import invariant), so the
240
+ * mapping is duplicated here and pinned to the provider by a contract test.
241
+ * Package-internal.
242
+ */
243
+ export function validateLlmOutcome(cfg, rawText, status, incompleteReason) {
244
+ if (status === "completed") {
245
+ // Parse the RAW assistant text first. A parse throw mirrors the
246
+ // provider's `SchemaValidationLlmError` (malformed structured-output
247
+ // JSON), which classifies as retryable `schema_validation`.
248
+ let parsed;
249
+ try {
250
+ parsed = JSON.parse(rawText ?? "");
251
+ }
252
+ catch (err) {
253
+ const message = `Provider returned malformed JSON in structured-output text: ${err instanceof Error ? err.message : String(err)}`;
254
+ return {
255
+ outcome: "failed",
256
+ failure: {
257
+ reason: "schema_validation",
258
+ code: OUTPUT_SCHEMA_INVALID,
259
+ message,
260
+ },
261
+ validationError: message,
262
+ };
263
+ }
264
+ const checked = checkLlmOutput(cfg, parsed);
265
+ if (checked.valid) {
266
+ return { outcome: "completed", output: parsed };
267
+ }
268
+ const validationError = checked.validationError ?? "schema validation failed";
269
+ return {
270
+ outcome: "failed",
271
+ failure: {
272
+ reason: "schema_validation",
273
+ code: OUTPUT_SCHEMA_INVALID,
274
+ message: validationError,
275
+ },
276
+ validationError,
277
+ };
278
+ }
279
+ if (status === "cancelled") {
280
+ // A cancelled background response mirrors a mid-flight abort:
281
+ // recorded `skipped`, NO `ProcessingFailure`, so a consumer can
282
+ // distinguish a cancel from a genuine error.
283
+ return { outcome: "skipped" };
284
+ }
285
+ if (status === "incomplete") {
286
+ const reason = incompleteReason ?? "unspecified";
287
+ if (reason === "content_filter") {
288
+ // Deterministic — the policy filter won't change on a re-roll;
289
+ // fail-fast (NO retryReason), mirroring NonRetryableLlmError.
290
+ return {
291
+ outcome: "failed",
292
+ failure: {
293
+ reason: "transient",
294
+ code: LLM_NON_RETRYABLE_ERROR,
295
+ message: formatIncompleteMirror(reason),
296
+ },
297
+ };
298
+ }
299
+ // `max_output_tokens` and any other/unspecified reason → retryable
300
+ // transient (mirrors the provider's conservative TransientLlmError).
301
+ return {
302
+ outcome: "failed",
303
+ failure: {
304
+ reason: "transient",
305
+ code: LLM_TRANSIENT_ERROR,
306
+ message: formatIncompleteMirror(reason),
307
+ },
308
+ };
309
+ }
310
+ // status === "failed" (or any other non-terminal value reaching here):
311
+ // a terminal failed envelope is NonRetryableLlmError → fail-fast (NO
312
+ // retryReason). `transient` would be WRONG (it's in the default
313
+ // retryOn, so the workflow would retry a definitively-failed response).
314
+ return {
315
+ outcome: "failed",
316
+ failure: {
317
+ reason: "transient",
318
+ code: LLM_NON_RETRYABLE_ERROR,
319
+ message: `Provider returned status "${status}".`,
320
+ },
321
+ };
322
+ }
323
+ // `lib/`-side mirror of the provider's incomplete-reason message. Kept
324
+ // terse + reason-naming (the provider's full guidance text lives in
325
+ // `extensions/openai/provider.ts#formatIncompleteMessage`, which `lib/`
326
+ // cannot import).
327
+ function formatIncompleteMirror(reason) {
328
+ return `Provider returned status "incomplete" (reason: ${reason}).`;
329
+ }
330
+ // Whether the failure's `reason` is a RETRYABLE classification to surface
331
+ // on `TExecuteStageResult.retryReason`. Fail-fast failures carry a
332
+ // `non-retryable` code (LLM_NON_RETRYABLE_ERROR) and surface NO
333
+ // retryReason; the genuinely-retryable reasons are the workflow's
334
+ // re-launch signal. Package-internal.
335
+ export function failureRetryReason(failure) {
336
+ if (failure.code === LLM_NON_RETRYABLE_ERROR)
337
+ return undefined;
338
+ return failure.reason;
339
+ }
340
+ // -- LLM stage --
341
+ export function llmStage(config) {
342
+ const policy = {
343
+ ...DEFAULT_RETRY_POLICY,
344
+ ...config.retry,
345
+ retryOn: config.retry?.retryOn ?? DEFAULT_RETRY_POLICY.retryOn,
346
+ };
347
+ const errorCap = resolveErrorCap(policy);
348
+ const cfg = {
349
+ id: config.id,
350
+ outputSchema: config.outputSchema,
351
+ model: config.model,
352
+ reasoningEffort: config.reasoningEffort,
353
+ buildPrompt: config.buildPrompt,
354
+ tools: config.tools,
355
+ maxOutputTokens: config.maxOutputTokens,
356
+ retryPolicy: policy,
357
+ };
358
+ const stage = {
359
+ id: config.id,
360
+ dependsOn: config.dependsOn,
361
+ outputSchema: config.outputSchema,
362
+ run: async (ctx) => {
363
+ const prompt = config.buildPrompt(ctx);
364
+ let userMessage = prompt.user;
365
+ let attempt = 0;
366
+ let lastError = null;
367
+ while (attempt < policy.maxAttempts) {
368
+ attempt += 1;
369
+ if (ctx.signal.aborted) {
370
+ // Loop-top abort: caller cancelled before (or
371
+ // between) attempts. Surface as a `skipped` stage
372
+ // rather than a failure.
373
+ throw new StageAbortedError({ stageId: config.id });
374
+ }
375
+ // Emit the `stage:llm-response-created` event the moment
376
+ // the provider surfaces a response id. In background-stream
377
+ // mode this fires MID-FLIGHT — before `respond()` resolves
378
+ // — from the provider's `onResponseCreated` callback (the
379
+ // first `response.created` SSE event). That early emit is
380
+ // load-bearing: a consumer persists the id before a
381
+ // possible crash, so a call interrupted mid-generation can
382
+ // be recovered from the upstream's stored copy rather than
383
+ // blindly re-run. In synchronous mode the callback never
384
+ // fires; the id is surfaced only at completion (below). The
385
+ // `responseIdEmitted` flag dedupes so the event fires at
386
+ // most once per attempt.
387
+ let responseIdEmitted = false;
388
+ const emitResponseCreated = (responseId) => {
389
+ if (responseIdEmitted)
390
+ return;
391
+ responseIdEmitted = true;
392
+ ctx.emit({
393
+ kind: "stage:llm-response-created",
394
+ stageId: config.id,
395
+ attempt,
396
+ responseId,
397
+ at: now(),
398
+ });
399
+ };
400
+ // Build the request via the shared seam, then attach this
401
+ // attempt's mid-flight id emitter (the seam leaves
402
+ // `onResponseCreated` unset — the launch path uses the
403
+ // submit return value instead).
404
+ const { req } = buildLlmRequest(cfg, ctx, userMessage);
405
+ req.onResponseCreated = emitResponseCreated;
406
+ // Emit the pre-call stage-input event. Fires inside the
407
+ // retry loop after `attempt` is incremented and after the
408
+ // request is built, immediately before `respond()` — so a
409
+ // consumer can surface the as-sent prompts the instant the
410
+ // call starts, without waiting for the post-call
411
+ // `stage:llm-call`. On attempt 2+ `userMessage` already
412
+ // carries the retry-suffix appended by the prior attempt's
413
+ // schema-validation failure path, matching this attempt's
414
+ // eventual `stage:llm-call.prompts.user`.
415
+ ctx.emit({
416
+ kind: "stage:llm-request",
417
+ stageId: config.id,
418
+ attempt,
419
+ prompts: {
420
+ system: prompt.system,
421
+ user: userMessage,
422
+ },
423
+ at: now(),
424
+ });
425
+ try {
426
+ const response = await ctx.llm.respond(req);
427
+ // Completion-time fallback: if the provider surfaced an
428
+ // id but did NOT fire the mid-flight callback (the
429
+ // synchronous / poll paths), emit here so the event
430
+ // still precedes `stage:llm-call` on this attempt.
431
+ if (response.rawResponseId) {
432
+ emitResponseCreated(response.rawResponseId);
433
+ }
434
+ // Shared validation core (same check the launch/complete
435
+ // path runs via validateLlmOutcome's completed branch).
436
+ const checked = checkLlmOutput(cfg, response.output);
437
+ const validationPassed = checked.valid;
438
+ const validationError = checked.validationError;
439
+ // Emit per-attempt LLM-call event. Fires after the
440
+ // call returns and after schema validation has run,
441
+ // before retry/return branching. `validationError`
442
+ // is `undefined` when the schema accepted the
443
+ // output, a string when it rejected. `prompts.user`
444
+ // is the as-sent message — on attempt 2+ this
445
+ // includes any retry-suffix appended by the prior
446
+ // attempt's schema-validation failure path.
447
+ ctx.emit({
448
+ kind: "stage:llm-call",
449
+ stageId: config.id,
450
+ attempt,
451
+ prompts: {
452
+ system: prompt.system,
453
+ user: userMessage,
454
+ },
455
+ output: response.output,
456
+ tokenUsage: response.tokenUsage,
457
+ rawResponseId: response.rawResponseId,
458
+ validationError,
459
+ at: now(),
460
+ });
461
+ if (!validationPassed) {
462
+ // validationError is defined here because
463
+ // validationPassed is false.
464
+ const validationMessage = validationError;
465
+ lastError = {
466
+ reason: "schema_validation",
467
+ code: OUTPUT_SCHEMA_INVALID,
468
+ message: validationMessage,
469
+ };
470
+ const retryable = policy.retryOn.includes("schema_validation");
471
+ if (!retryable || attempt >= policy.maxAttempts) {
472
+ break;
473
+ }
474
+ emitRetry(ctx, config.id, attempt, "schema_validation");
475
+ userMessage = applyRetrySuffix(prompt.user, validationMessage, errorCap);
476
+ await sleep(policy.backoffMs, ctx.signal);
477
+ continue;
478
+ }
479
+ // Token usage emission is handled by the executor at
480
+ // stage:end time; we return the response output and
481
+ // attach the usage onto a side channel via failure-free
482
+ // path.
483
+ // We stash token usage on a per-stage well-known key
484
+ // recognized by the executor.
485
+ stashTokenUsage(ctx, config.id, response.tokenUsage);
486
+ return response.output;
487
+ }
488
+ catch (err) {
489
+ if (err instanceof LlmStageRetryExhaustedError &&
490
+ err.stageId === config.id) {
491
+ // Re-throw our own marker; the catch below shouldn't
492
+ // see it. Defensive.
493
+ throw err;
494
+ }
495
+ if (err instanceof StageAbortedError) {
496
+ throw err;
497
+ }
498
+ // Mid-flight abort surfaces here when the provider
499
+ // honored the signal and threw. Recognize it before
500
+ // classifying as a generic non-retryable failure so
501
+ // the executor can mark this stage `skipped`, not
502
+ // `failed` with `LLM_NON_RETRYABLE_ERROR`.
503
+ if (ctx.signal.aborted) {
504
+ throw new StageAbortedError({ stageId: config.id });
505
+ }
506
+ const reason = classifyError(err);
507
+ const message = err instanceof Error ? err.message : String(err);
508
+ if (reason === "non_retryable") {
509
+ lastError = {
510
+ reason: "transient",
511
+ code: LLM_NON_RETRYABLE_ERROR,
512
+ message,
513
+ };
514
+ break;
515
+ }
516
+ lastError = {
517
+ reason,
518
+ code: reason === "quota_exhausted"
519
+ ? LLM_QUOTA_EXHAUSTED
520
+ : reason === "rate_limit"
521
+ ? LLM_RATE_LIMITED
522
+ : LLM_TRANSIENT_ERROR,
523
+ message,
524
+ };
525
+ // Fail-fast for any reason not opted into `retryOn`.
526
+ // `quota_exhausted` is absent from every default
527
+ // policy, so a quota 429 breaks here on attempt 1 —
528
+ // same control flow `rate_limit` already takes.
529
+ if (!policy.retryOn.includes(reason)) {
530
+ break;
531
+ }
532
+ if (attempt >= policy.maxAttempts) {
533
+ break;
534
+ }
535
+ emitRetry(ctx, config.id, attempt, reason);
536
+ await sleep(policy.backoffMs, ctx.signal);
537
+ }
538
+ }
539
+ const failure = lastError ?? {
540
+ reason: "transient",
541
+ code: LLM_UNKNOWN_ERROR,
542
+ message: "llmStage retry loop exited without error context",
543
+ };
544
+ throw new LlmStageRetryExhaustedError({
545
+ stageId: config.id,
546
+ reason: failure.reason,
547
+ code: failure.code,
548
+ attempts: attempt,
549
+ message: failure.message,
550
+ context: failure.context,
551
+ });
552
+ },
553
+ };
554
+ // Attach the resolved config on a non-enumerable, internal-symbol-keyed
555
+ // carrier so `launchStage`/`completeStage` (same package) can recover it
556
+ // via `readLlmStageConfig`. Non-enumerable + symbol-keyed keeps it off
557
+ // every enumeration and JSON serialization of the stage object, and out
558
+ // of the public `TStage` shape.
559
+ Object.defineProperty(stage, LLM_STAGE_CONFIG, {
560
+ value: cfg,
561
+ enumerable: false,
562
+ writable: false,
563
+ configurable: false,
564
+ });
565
+ return stage;
566
+ }
567
+ //# sourceMappingURL=llm-stage-helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llm-stage-helpers.js","sourceRoot":"","sources":["../../../src/lib/pipelines/llm-stage-helpers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,62 @@
1
+ import type { TPipeline, TPipelineEvent, TPipelineResult, TProcessingFailure, TStage, TStageContext, TStageStatus } from "./types.js";
2
+ import type { TLlmProvider, TLlmTokenUsage } from "../llm/types.js";
3
+ export type TExecutePipelineDeps = {
4
+ llm: TLlmProvider;
5
+ generateId?: () => string;
6
+ signal?: AbortSignal;
7
+ onEvent?: (event: TPipelineEvent) => void;
8
+ /** Default 4. */
9
+ concurrencyLimit?: number;
10
+ };
11
+ export declare class PipelineConfigurationError extends Error {
12
+ readonly code: "DAG_CYCLE" | "SELF_DEP" | "UNKNOWN_DEP" | "UNKNOWN_STAGE" | "DUPLICATE_STAGE_ID" | "GET_OUTSIDE_DEPS" | "STATUS_OUTSIDE_DEPS";
13
+ readonly stageId?: string;
14
+ readonly depId?: string;
15
+ constructor(args: {
16
+ code: PipelineConfigurationError["code"];
17
+ message: string;
18
+ stageId?: string;
19
+ depId?: string;
20
+ });
21
+ }
22
+ export declare function now(): number;
23
+ export declare function defaultGenerateId(): string;
24
+ export declare function noopEmit(_event: TPipelineEvent): void;
25
+ export type TStageRecord = {
26
+ outcome: TStageStatus;
27
+ output: unknown;
28
+ tokenUsage?: TLlmTokenUsage;
29
+ };
30
+ export type TStageRunState = {
31
+ /** The inter-stage record store `ctx.get` / `ctx.stageStatus` read. */
32
+ records: Map<string, TStageRecord>;
33
+ /** Aggregated structured failures the run produces. */
34
+ failures: TProcessingFailure[];
35
+ /** Cancellation signal threaded into each stage's `ctx.signal`. */
36
+ signal: AbortSignal;
37
+ /** Observability hook for `TPipelineEvent`s. */
38
+ emit: (event: TPipelineEvent) => void;
39
+ /** ID generator threaded into each stage's `ctx.generateId`. */
40
+ generateId: () => string;
41
+ /** The provider every `llmStage` calls. */
42
+ llm: TLlmProvider;
43
+ /**
44
+ * The parsed (Default/Convert/Clean-transformed) pipeline input that
45
+ * seeds every stage's `ctx.input`.
46
+ */
47
+ input: unknown;
48
+ /**
49
+ * Disposition seam for a `PipelineConfigurationError` raised by
50
+ * `ctx.get` / `ctx.stageStatus` on a non-dependency stage id (a
51
+ * caller bug). The whole-DAG scheduler captures the first one and
52
+ * re-throws it after emitting the bookend events; the single-stage
53
+ * path supplies a callback that throws immediately (it has no
54
+ * bookends to emit). One extracted body, two dispositions.
55
+ */
56
+ setConfigError: (error: PipelineConfigurationError) => void;
57
+ };
58
+ export declare function makeStageContext(state: TStageRunState, allowedDeps: Set<string>, contextLabel: string): TStageContext;
59
+ export declare function runOneStage(stage: TStage<unknown>, ctx: TStageContext, state: TStageRunState): Promise<void>;
60
+ export declare function runFinalize<TOutput>(pipeline: TPipeline<unknown, TOutput>, ctx: TStageContext, state: TStageRunState): TOutput | null;
61
+ export declare function executePipeline<TInput, TOutput>(pipeline: TPipeline<TInput, TOutput>, input: TInput, deps: TExecutePipelineDeps): Promise<TPipelineResult<TOutput>>;
62
+ //# sourceMappingURL=scheduler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduler.d.ts","sourceRoot":"","sources":["../../../src/lib/pipelines/scheduler.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAER,SAAS,EACT,cAAc,EACd,eAAe,EACf,kBAAkB,EAClB,MAAM,EACN,aAAa,EACb,YAAY,EACf,MAAM,YAAY,CAAA;AAcnB,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAEnE,MAAM,MAAM,oBAAoB,GAAG;IAC/B,GAAG,EAAE,YAAY,CAAA;IACjB,UAAU,CAAC,EAAE,MAAM,MAAM,CAAA;IACzB,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAA;IACzC,iBAAiB;IACjB,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAC5B,CAAA;AAED,qBAAa,0BAA2B,SAAQ,KAAK;IACjD,SAAgB,IAAI,EACd,WAAW,GACX,UAAU,GACV,aAAa,GACb,eAAe,GACf,oBAAoB,GACpB,kBAAkB,GAClB,qBAAqB,CAAA;IAC3B,SAAgB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChC,SAAgB,KAAK,CAAC,EAAE,MAAM,CAAA;gBAElB,IAAI,EAAE;QACd,IAAI,EAAE,0BAA0B,CAAC,MAAM,CAAC,CAAA;QACxC,OAAO,EAAE,MAAM,CAAA;QACf,OAAO,CAAC,EAAE,MAAM,CAAA;QAChB,KAAK,CAAC,EAAE,MAAM,CAAA;KACjB;CAOJ;AAED,wBAAgB,GAAG,IAAI,MAAM,CAI5B;AAED,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED,wBAAgB,QAAQ,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI,CAErD;AA+FD,MAAM,MAAM,YAAY,GAAG;IACvB,OAAO,EAAE,YAAY,CAAA;IACrB,MAAM,EAAE,OAAO,CAAA;IACf,UAAU,CAAC,EAAE,cAAc,CAAA;CAC9B,CAAA;AAYD,MAAM,MAAM,cAAc,GAAG;IACzB,uEAAuE;IACvE,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;IAClC,uDAAuD;IACvD,QAAQ,EAAE,kBAAkB,EAAE,CAAA;IAC9B,mEAAmE;IACnE,MAAM,EAAE,WAAW,CAAA;IACnB,gDAAgD;IAChD,IAAI,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAA;IACrC,gEAAgE;IAChE,UAAU,EAAE,MAAM,MAAM,CAAA;IACxB,2CAA2C;IAC3C,GAAG,EAAE,YAAY,CAAA;IACjB;;;OAGG;IACH,KAAK,EAAE,OAAO,CAAA;IACd;;;;;;;OAOG;IACH,cAAc,EAAE,CAAC,KAAK,EAAE,0BAA0B,KAAK,IAAI,CAAA;CAC9D,CAAA;AAMD,wBAAgB,gBAAgB,CAC5B,KAAK,EAAE,cAAc,EACrB,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,EACxB,YAAY,EAAE,MAAM,GACrB,aAAa,CA4Cf;AAQD,wBAAsB,WAAW,CAC7B,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC,EACtB,GAAG,EAAE,aAAa,EAClB,KAAK,EAAE,cAAc,GACtB,OAAO,CAAC,IAAI,CAAC,CAmJf;AASD,wBAAgB,WAAW,CAAC,OAAO,EAC/B,QAAQ,EAAE,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,EACrC,GAAG,EAAE,aAAa,EAClB,KAAK,EAAE,cAAc,GACtB,OAAO,GAAG,IAAI,CAyBhB;AAED,wBAAsB,eAAe,CAAC,MAAM,EAAE,OAAO,EACjD,QAAQ,EAAE,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,oBAAoB,GAC3B,OAAO,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CA0RnC"}