@proposit/proposit-core 2.1.0 → 2.2.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 (55) hide show
  1. package/dist/extensions/chat-completions/errors.d.ts +66 -0
  2. package/dist/extensions/chat-completions/errors.d.ts.map +1 -0
  3. package/dist/extensions/chat-completions/errors.js +139 -0
  4. package/dist/extensions/chat-completions/errors.js.map +1 -0
  5. package/dist/extensions/chat-completions/http.d.ts +10 -0
  6. package/dist/extensions/chat-completions/http.d.ts.map +1 -0
  7. package/dist/extensions/chat-completions/http.js +80 -0
  8. package/dist/extensions/chat-completions/http.js.map +1 -0
  9. package/dist/extensions/chat-completions/index.d.ts +7 -0
  10. package/dist/extensions/chat-completions/index.d.ts.map +1 -0
  11. package/dist/extensions/chat-completions/index.js +18 -0
  12. package/dist/extensions/chat-completions/index.js.map +1 -0
  13. package/dist/extensions/chat-completions/provider.d.ts +5 -0
  14. package/dist/extensions/chat-completions/provider.d.ts.map +1 -0
  15. package/dist/extensions/chat-completions/provider.js +192 -0
  16. package/dist/extensions/chat-completions/provider.js.map +1 -0
  17. package/dist/extensions/chat-completions/structured-output.d.ts +18 -0
  18. package/dist/extensions/chat-completions/structured-output.d.ts.map +1 -0
  19. package/dist/extensions/{ollama → chat-completions}/structured-output.js +14 -10
  20. package/dist/extensions/chat-completions/structured-output.js.map +1 -0
  21. package/dist/extensions/chat-completions/types.d.ts +65 -0
  22. package/dist/extensions/chat-completions/types.d.ts.map +1 -0
  23. package/dist/extensions/chat-completions/types.js +19 -0
  24. package/dist/extensions/chat-completions/types.js.map +1 -0
  25. package/dist/extensions/openai/provider.d.ts +2 -2
  26. package/dist/extensions/pipelines/base/types.d.ts +6 -5
  27. package/dist/extensions/pipelines/base/types.d.ts.map +1 -1
  28. package/dist/lib/pipelines/stage-helpers.d.ts.map +1 -1
  29. package/dist/lib/pipelines/stage-helpers.js +37 -1
  30. package/dist/lib/pipelines/stage-helpers.js.map +1 -1
  31. package/dist/lib/pipelines/types.d.ts +2 -2
  32. package/package.json +6 -16
  33. package/dist/extensions/ollama/errors.d.ts +0 -73
  34. package/dist/extensions/ollama/errors.d.ts.map +0 -1
  35. package/dist/extensions/ollama/errors.js +0 -228
  36. package/dist/extensions/ollama/errors.js.map +0 -1
  37. package/dist/extensions/ollama/index.d.ts +0 -6
  38. package/dist/extensions/ollama/index.d.ts.map +0 -1
  39. package/dist/extensions/ollama/index.js +0 -17
  40. package/dist/extensions/ollama/index.js.map +0 -1
  41. package/dist/extensions/ollama/provider.d.ts +0 -22
  42. package/dist/extensions/ollama/provider.d.ts.map +0 -1
  43. package/dist/extensions/ollama/provider.js +0 -417
  44. package/dist/extensions/ollama/provider.js.map +0 -1
  45. package/dist/extensions/ollama/structured-output.d.ts +0 -18
  46. package/dist/extensions/ollama/structured-output.d.ts.map +0 -1
  47. package/dist/extensions/ollama/structured-output.js.map +0 -1
  48. package/dist/extensions/ollama/timeout-fetch.d.ts +0 -24
  49. package/dist/extensions/ollama/timeout-fetch.d.ts.map +0 -1
  50. package/dist/extensions/ollama/timeout-fetch.js +0 -76
  51. package/dist/extensions/ollama/timeout-fetch.js.map +0 -1
  52. package/dist/extensions/ollama/types.d.ts +0 -219
  53. package/dist/extensions/ollama/types.d.ts.map +0 -1
  54. package/dist/extensions/ollama/types.js +0 -7
  55. package/dist/extensions/ollama/types.js.map +0 -1
@@ -0,0 +1,66 @@
1
+ export declare class TransientLlmError extends Error {
2
+ readonly retryReason: "transient";
3
+ readonly status?: number;
4
+ constructor(args: {
5
+ message: string;
6
+ status?: number;
7
+ });
8
+ }
9
+ export declare class RateLimitLlmError extends Error {
10
+ readonly retryReason: "rate_limit";
11
+ readonly status?: number;
12
+ constructor(args: {
13
+ message: string;
14
+ status?: number;
15
+ });
16
+ }
17
+ /**
18
+ * Persistent provider budget exhaustion — surfaced as a 429 whose body
19
+ * carries an `insufficient_quota` code/type. Distinct from the transient
20
+ * {@link RateLimitLlmError} throttle: the framework reads the
21
+ * `quota_exhausted` tag, which is absent from every default `retryOn`,
22
+ * so the stage fails fast on attempt 1.
23
+ */
24
+ export declare class QuotaExhaustedLlmError extends Error {
25
+ readonly retryReason: "quota_exhausted";
26
+ readonly status?: number;
27
+ constructor(args: {
28
+ message: string;
29
+ status?: number;
30
+ });
31
+ }
32
+ /**
33
+ * Thrown when the endpoint rejects our request because the model's
34
+ * output failed server-side JSON-Schema enforcement (typical 422).
35
+ * Tagged `transient` so the framework's default retry policy retries — a
36
+ * single re-roll often produces conforming output.
37
+ */
38
+ export declare class SchemaValidationLlmError extends Error {
39
+ readonly retryReason: "transient";
40
+ readonly status?: number;
41
+ constructor(args: {
42
+ message: string;
43
+ status?: number;
44
+ });
45
+ }
46
+ export declare class NonRetryableLlmError extends Error {
47
+ readonly status?: number;
48
+ constructor(args: {
49
+ message: string;
50
+ status?: number;
51
+ });
52
+ }
53
+ /**
54
+ * Route an HTTP status family (plus an optional structured provider
55
+ * error code) into the framework-recognized error class.
56
+ */
57
+ export declare function classifyHttpError(status: number, message: string, providerErrorCode?: string): Error;
58
+ /**
59
+ * Map a low-level `fetch` failure (server unreachable, connection reset,
60
+ * the request timeout firing as a non-Abort transport error) to a
61
+ * transient error. Talking to a local OpenAI-compatible server that is
62
+ * down or mid-generation is retryable — a retry after backoff can
63
+ * succeed once the server is up / a slow generation completes.
64
+ */
65
+ export declare function classifyFetchError(err: unknown): Error;
66
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/extensions/chat-completions/errors.ts"],"names":[],"mappings":"AAmCA,qBAAa,iBAAkB,SAAQ,KAAK;IACxC,SAAgB,WAAW,EAAG,WAAW,CAAS;IAClD,SAAgB,MAAM,CAAC,EAAE,MAAM,CAAA;gBAEnB,IAAI,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE;CAKzD;AAED,qBAAa,iBAAkB,SAAQ,KAAK;IACxC,SAAgB,WAAW,EAAG,YAAY,CAAS;IACnD,SAAgB,MAAM,CAAC,EAAE,MAAM,CAAA;gBAEnB,IAAI,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE;CAKzD;AAED;;;;;;GAMG;AACH,qBAAa,sBAAuB,SAAQ,KAAK;IAC7C,SAAgB,WAAW,EAAG,iBAAiB,CAAS;IACxD,SAAgB,MAAM,CAAC,EAAE,MAAM,CAAA;gBAEnB,IAAI,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE;CAKzD;AAED;;;;;GAKG;AACH,qBAAa,wBAAyB,SAAQ,KAAK;IAC/C,SAAgB,WAAW,EAAG,WAAW,CAAS;IAClD,SAAgB,MAAM,CAAC,EAAE,MAAM,CAAA;gBAEnB,IAAI,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE;CAKzD;AAED,qBAAa,oBAAqB,SAAQ,KAAK;IAC3C,SAAgB,MAAM,CAAC,EAAE,MAAM,CAAA;gBAEnB,IAAI,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE;CAKzD;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC7B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,iBAAiB,CAAC,EAAE,MAAM,GAC3B,KAAK,CA6BP;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,OAAO,GAAG,KAAK,CAKtD"}
@@ -0,0 +1,139 @@
1
+ // chat-completions-provider error classes + the `classifyHttpError` /
2
+ // `classifyFetchError` mappings.
3
+ //
4
+ // The framework's `llmStage` retry policy classifies provider errors by
5
+ // inspecting a `retryReason` tag on the thrown object (see
6
+ // `src/lib/pipelines/stage-helpers.ts#classifyError`). To play cleanly
7
+ // with that mechanism, each error class carries the appropriate tag as
8
+ // an own property. The framework derives the `TProcessingFailure.code`
9
+ // from the tag, so these classes need no `code` of their own.
10
+ //
11
+ // The class names intentionally mirror the OpenAI provider's names but
12
+ // are *distinct* classes living in this extension; they are surfaced
13
+ // only from this subpath (NOT the package root) to avoid colliding with
14
+ // the root-exported OpenAI error classes.
15
+ //
16
+ // Mapping for the framework's default retry policy
17
+ // (`retryOn: ["schema_validation", "transient"]`):
18
+ //
19
+ // * `TransientLlmError` — `retryReason: "transient"`. 5xx responses +
20
+ // low-level fetch failures (server unreachable, connection reset, a
21
+ // request timeout). Retried under the default policy.
22
+ // * `RateLimitLlmError` — `retryReason: "rate_limit"`. A 429 whose body
23
+ // is NOT `insufficient_quota`. Not retried by default — callers can
24
+ // opt into `retryOn: ["..., "rate_limit"]`.
25
+ // * `QuotaExhaustedLlmError` — `retryReason: "quota_exhausted"`.
26
+ // Persistent budget exhaustion (a 429 whose body code/type is
27
+ // `insufficient_quota`). Fail-fast: the tag is absent from every
28
+ // default `retryOn`, so the stage breaks on attempt 1.
29
+ // * `SchemaValidationLlmError` — `retryReason: "transient"`. The
30
+ // model's output failed schema enforcement on the server side
31
+ // (typical 422). A single re-roll often produces conforming output.
32
+ // * `NonRetryableLlmError` — no tag; the framework classifies it as
33
+ // `non_retryable` and surfaces it immediately. Used for 400/401/403
34
+ // and other unrecoverable 4xx.
35
+ export class TransientLlmError extends Error {
36
+ retryReason = "transient";
37
+ status;
38
+ constructor(args) {
39
+ super(args.message);
40
+ this.name = "TransientLlmError";
41
+ this.status = args.status;
42
+ }
43
+ }
44
+ export class RateLimitLlmError extends Error {
45
+ retryReason = "rate_limit";
46
+ status;
47
+ constructor(args) {
48
+ super(args.message);
49
+ this.name = "RateLimitLlmError";
50
+ this.status = args.status;
51
+ }
52
+ }
53
+ /**
54
+ * Persistent provider budget exhaustion — surfaced as a 429 whose body
55
+ * carries an `insufficient_quota` code/type. Distinct from the transient
56
+ * {@link RateLimitLlmError} throttle: the framework reads the
57
+ * `quota_exhausted` tag, which is absent from every default `retryOn`,
58
+ * so the stage fails fast on attempt 1.
59
+ */
60
+ export class QuotaExhaustedLlmError extends Error {
61
+ retryReason = "quota_exhausted";
62
+ status;
63
+ constructor(args) {
64
+ super(args.message);
65
+ this.name = "QuotaExhaustedLlmError";
66
+ this.status = args.status;
67
+ }
68
+ }
69
+ /**
70
+ * Thrown when the endpoint rejects our request because the model's
71
+ * output failed server-side JSON-Schema enforcement (typical 422).
72
+ * Tagged `transient` so the framework's default retry policy retries — a
73
+ * single re-roll often produces conforming output.
74
+ */
75
+ export class SchemaValidationLlmError extends Error {
76
+ retryReason = "transient";
77
+ status;
78
+ constructor(args) {
79
+ super(args.message);
80
+ this.name = "SchemaValidationLlmError";
81
+ this.status = args.status;
82
+ }
83
+ }
84
+ export class NonRetryableLlmError extends Error {
85
+ status;
86
+ constructor(args) {
87
+ super(args.message);
88
+ this.name = "NonRetryableLlmError";
89
+ this.status = args.status;
90
+ }
91
+ }
92
+ /**
93
+ * Route an HTTP status family (plus an optional structured provider
94
+ * error code) into the framework-recognized error class.
95
+ */
96
+ export function classifyHttpError(status, message, providerErrorCode) {
97
+ if (status >= 500) {
98
+ return new TransientLlmError({ message, status });
99
+ }
100
+ if (status === 429) {
101
+ // 429 splits on the body's structured error code: persistent
102
+ // budget exhaustion (`insufficient_quota`) is fail-fast, every
103
+ // other (and every unparseable) 429 stays the transient throttle.
104
+ // The safe default is always "transient + retryable" — never a
105
+ // false quota trip.
106
+ if (providerErrorCode === "insufficient_quota") {
107
+ return new QuotaExhaustedLlmError({ message, status });
108
+ }
109
+ return new RateLimitLlmError({ message, status });
110
+ }
111
+ // 400 is a malformed request — a converter bug, an unsupported
112
+ // parameter, or a request shape the endpoint doesn't accept;
113
+ // retrying just burns the second attempt, so classify non-retryable.
114
+ if (status === 400) {
115
+ return new NonRetryableLlmError({ message, status });
116
+ }
117
+ // 422 signals the model's structured-output reply failed server-side
118
+ // schema validation; a re-roll can succeed, so route it through the
119
+ // schema-validation class (tagged transient).
120
+ if (status === 422) {
121
+ return new SchemaValidationLlmError({ message, status });
122
+ }
123
+ // 401/403 and every other 4xx are unrecoverable.
124
+ return new NonRetryableLlmError({ message, status });
125
+ }
126
+ /**
127
+ * Map a low-level `fetch` failure (server unreachable, connection reset,
128
+ * the request timeout firing as a non-Abort transport error) to a
129
+ * transient error. Talking to a local OpenAI-compatible server that is
130
+ * down or mid-generation is retryable — a retry after backoff can
131
+ * succeed once the server is up / a slow generation completes.
132
+ */
133
+ export function classifyFetchError(err) {
134
+ const message = err instanceof Error ? err.message : String(err);
135
+ return new TransientLlmError({
136
+ message: `Network error calling the chat-completions endpoint: ${message}`,
137
+ });
138
+ }
139
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../src/extensions/chat-completions/errors.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { TChatCompletionsFetch, TChatCompletionsResponse } from "./types.js";
2
+ export declare function requestJson(args: {
3
+ url: string;
4
+ apiKey: string;
5
+ body: unknown;
6
+ fetchImpl: TChatCompletionsFetch;
7
+ signal?: AbortSignal;
8
+ timeoutMs: number;
9
+ }): Promise<TChatCompletionsResponse>;
10
+ //# sourceMappingURL=http.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../../src/extensions/chat-completions/http.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EACR,qBAAqB,EACrB,wBAAwB,EAC3B,MAAM,YAAY,CAAA;AA2BnB,wBAAsB,WAAW,CAAC,IAAI,EAAE;IACpC,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,OAAO,CAAA;IACb,SAAS,EAAE,qBAAqB,CAAA;IAChC,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB,SAAS,EAAE,MAAM,CAAA;CACpB,GAAG,OAAO,CAAC,wBAAwB,CAAC,CA2DpC"}
@@ -0,0 +1,80 @@
1
+ // Raw-fetch HTTP transport for an OpenAI-compatible
2
+ // `/v1/chat/completions` endpoint: a single POST of JSON, a per-request
3
+ // timeout enforced via `AbortSignal.timeout` (composed with the caller's
4
+ // abort signal so a mid-flight cancel still propagates), and non-2xx →
5
+ // error-class classification. No SSE, no background poll — this provider
6
+ // is synchronous. The timeout is a standard `AbortSignal.timeout` with
7
+ // no extra HTTP-stack dependency.
8
+ import { classifyFetchError, classifyHttpError, TransientLlmError, } from "./errors.js";
9
+ function isAbortError(err) {
10
+ return (typeof err === "object" &&
11
+ err !== null &&
12
+ err.name === "AbortError");
13
+ }
14
+ // Compose the caller's AbortSignal with a timeout signal so EITHER one
15
+ // aborts the request. `AbortSignal.any` / `AbortSignal.timeout` are
16
+ // available on the supported Node floor (>=22). When no timeout is
17
+ // configured (timeoutMs <= 0) and no caller signal is present, returns
18
+ // undefined (no abort).
19
+ function resolveSignal(callerSignal, timeoutMs) {
20
+ const timeoutSignal = timeoutMs > 0 ? AbortSignal.timeout(timeoutMs) : undefined;
21
+ if (callerSignal && timeoutSignal) {
22
+ return AbortSignal.any([callerSignal, timeoutSignal]);
23
+ }
24
+ return callerSignal ?? timeoutSignal;
25
+ }
26
+ export async function requestJson(args) {
27
+ const signal = resolveSignal(args.signal, args.timeoutMs);
28
+ let response;
29
+ try {
30
+ response = await args.fetchImpl(args.url, {
31
+ method: "POST",
32
+ headers: {
33
+ "Content-Type": "application/json",
34
+ Authorization: `Bearer ${args.apiKey}`,
35
+ },
36
+ body: JSON.stringify(args.body),
37
+ signal,
38
+ });
39
+ }
40
+ catch (err) {
41
+ // A caller-initiated abort propagates verbatim so `llmStage`'s
42
+ // mid-flight-abort detector marks the stage skipped — gated on the
43
+ // caller's signal actually having fired (a caller abort surfaces as
44
+ // an `AbortError`). A timeout surfaces as a `TimeoutError` (not an
45
+ // `AbortError`), and every other transport failure surfaces with
46
+ // its own name — so both fall through to `classifyFetchError` and
47
+ // are retried as transient.
48
+ if (isAbortError(err) && args.signal?.aborted) {
49
+ throw err;
50
+ }
51
+ throw classifyFetchError(err);
52
+ }
53
+ if (!response.ok) {
54
+ const errorBody = await response.text().catch(() => "");
55
+ const message = `Chat-completions endpoint ${response.status.toString()}: ${errorBody || response.statusText}`;
56
+ // Best-effort structured extraction of the provider error
57
+ // code/type so a 429 can be split into persistent quota
58
+ // exhaustion vs. transient throttling. An unparseable body leaves
59
+ // `providerErrorCode` undefined, which `classifyHttpError` treats
60
+ // as the safe transient default.
61
+ let providerErrorCode;
62
+ try {
63
+ const parsed = JSON.parse(errorBody);
64
+ providerErrorCode = parsed.error?.code ?? parsed.error?.type;
65
+ }
66
+ catch {
67
+ providerErrorCode = undefined;
68
+ }
69
+ throw classifyHttpError(response.status, message, providerErrorCode);
70
+ }
71
+ return response
72
+ .json()
73
+ .then((j) => j)
74
+ .catch((err) => {
75
+ throw new TransientLlmError({
76
+ message: `Chat-completions response body was not valid JSON: ${err instanceof Error ? err.message : String(err)}`,
77
+ });
78
+ });
79
+ }
80
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../../../src/extensions/chat-completions/http.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export { createChatCompletionsProvider } from "./provider.js";
2
+ export type { TCreateChatCompletionsProviderOptions } from "./provider.js";
3
+ export type { TChatCompletionsProviderConfig } from "./types.js";
4
+ export { typeboxToJsonSchema } from "./structured-output.js";
5
+ export type { TChatCompletionsJsonSchema } from "./structured-output.js";
6
+ export { NonRetryableLlmError, QuotaExhaustedLlmError, RateLimitLlmError, SchemaValidationLlmError, TransientLlmError, classifyHttpError, classifyFetchError, } from "./errors.js";
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/extensions/chat-completions/index.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,6BAA6B,EAAE,MAAM,eAAe,CAAA;AAC7D,YAAY,EAAE,qCAAqC,EAAE,MAAM,eAAe,CAAA;AAC1E,YAAY,EAAE,8BAA8B,EAAE,MAAM,YAAY,CAAA;AAChE,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAA;AAC5D,YAAY,EAAE,0BAA0B,EAAE,MAAM,wBAAwB,CAAA;AACxE,OAAO,EACH,oBAAoB,EACpB,sBAAsB,EACtB,iBAAiB,EACjB,wBAAwB,EACxB,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,GACrB,MAAM,aAAa,CAAA"}
@@ -0,0 +1,18 @@
1
+ // Barrel for the chat-completions provider extension.
2
+ //
3
+ // Public surface consumed via the
4
+ // `@proposit/proposit-core/extensions/chat-completions` subpath: the
5
+ // provider factory + its config type + the lax JSON-schema converter +
6
+ // the error classes (which callers may `instanceof`-match for finer-
7
+ // grained observability) and the status/fetch classifiers.
8
+ //
9
+ // The error class names intentionally mirror the OpenAI provider's names
10
+ // but are *distinct* classes living in this extension; they are surfaced
11
+ // only from this subpath (NOT the package root) to avoid colliding with
12
+ // the root-exported OpenAI error classes. The framework classifies by
13
+ // the `retryReason` tag, not class identity, so the duplication is
14
+ // intentional and harmless.
15
+ export { createChatCompletionsProvider } from "./provider.js";
16
+ export { typeboxToJsonSchema } from "./structured-output.js";
17
+ export { NonRetryableLlmError, QuotaExhaustedLlmError, RateLimitLlmError, SchemaValidationLlmError, TransientLlmError, classifyHttpError, classifyFetchError, } from "./errors.js";
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/extensions/chat-completions/index.ts"],"names":[],"mappings":"AAAA,sDAAsD;AACtD,EAAE;AACF,kCAAkC;AAClC,qEAAqE;AACrE,uEAAuE;AACvE,qEAAqE;AACrE,2DAA2D;AAC3D,EAAE;AACF,yEAAyE;AACzE,yEAAyE;AACzE,wEAAwE;AACxE,sEAAsE;AACtE,mEAAmE;AACnE,4BAA4B;AAE5B,OAAO,EAAE,6BAA6B,EAAE,MAAM,eAAe,CAAA;AAG7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAA;AAE5D,OAAO,EACH,oBAAoB,EACpB,sBAAsB,EACtB,iBAAiB,EACjB,wBAAwB,EACxB,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,GACrB,MAAM,aAAa,CAAA"}
@@ -0,0 +1,5 @@
1
+ import type { TLlmProvider } from "../../lib/llm/types.js";
2
+ import { type TChatCompletionsProviderConfig } from "./types.js";
3
+ export type TCreateChatCompletionsProviderOptions = TChatCompletionsProviderConfig;
4
+ export declare function createChatCompletionsProvider(options?: TChatCompletionsProviderConfig): TLlmProvider;
5
+ //# sourceMappingURL=provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../../src/extensions/chat-completions/provider.ts"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EACR,YAAY,EAIf,MAAM,wBAAwB,CAAA;AAS/B,OAAO,EAMH,KAAK,8BAA8B,EAEtC,MAAM,YAAY,CAAA;AAInB,MAAM,MAAM,qCAAqC,GAC7C,8BAA8B,CAAA;AAoBlC,wBAAgB,6BAA6B,CACzC,OAAO,CAAC,EAAE,8BAA8B,GACzC,YAAY,CA8Jd"}
@@ -0,0 +1,192 @@
1
+ // Concrete `TLlmProvider` backed by an OpenAI-compatible
2
+ // `/v1/chat/completions` endpoint (a local llama-server by default, or
3
+ // any OpenAI-compatible chat backend by swapping baseUrl + token).
4
+ //
5
+ // Synchronous, structured-output-only:
6
+ // * One POST to `{baseUrl}/chat/completions` via raw `fetch` (the
7
+ // `./http.ts` `requestJson` helper) — no SSE, no background/poll, no
8
+ // mid-flight responseId. `TLlmProvider.respond` is the whole surface;
9
+ // the optional `onResponseCreated` hook is left uncalled (a
10
+ // synchronous provider never learns an id mid-flight), which is
11
+ // contract-legal — the same posture the prior local provider took.
12
+ // * Structured output via the lax `typeboxToJsonSchema` converter under
13
+ // a `response_format: { type: "json_schema", json_schema: { ... } }`.
14
+ // * `reasoningEffort` is ignored (no chat-completions analogue);
15
+ // `maxOutputTokens` maps to `max_tokens` (positive values only).
16
+ // * Function tools are NOT supported — a request carrying `tools` fails
17
+ // fast with `NonRetryableLlmError`. This provider serves the
18
+ // structured-output ingestion path, which uses no tools, so there is
19
+ // no multi-round tool loop to port.
20
+ // * `requestTimeoutMs` is enforced via `AbortSignal.timeout` inside
21
+ // `requestJson` — no extra HTTP-stack dependency.
22
+ //
23
+ // Error classification routes HTTP-status families + fetch failures into
24
+ // the framework-recognized error classes (see `./errors.ts`). The
25
+ // framework's `llmStage` retry policy classifies via the `retryReason`
26
+ // tag on the thrown error.
27
+ import { debugLlmFailure, debugLlmRequest, debugLlmResponse, } from "../../lib/pipelines/debug-log.js";
28
+ import { typeboxToJsonSchema } from "./structured-output.js";
29
+ import { requestJson } from "./http.js";
30
+ import { NonRetryableLlmError, SchemaValidationLlmError } from "./errors.js";
31
+ import { DEFAULT_API_KEY, DEFAULT_BASE_URL, DEFAULT_MODEL, DEFAULT_REQUEST_TIMEOUT_MS, } from "./types.js";
32
+ const STAGE_ID_MARKER = /<!--\s*stage-id:\s*([^\s>]+)\s*-->/;
33
+ function abortError() {
34
+ const e = new Error("The chat-completions request was aborted.");
35
+ e.name = "AbortError";
36
+ return e;
37
+ }
38
+ // Derive the `json_schema.name` from the schema's `$id` (sanitized to the
39
+ // `^[a-zA-Z0-9_-]{1,64}$` shape OpenAI-compatible servers accept), or a
40
+ // stable default when the schema is anonymous.
41
+ function deriveSchemaName(schema) {
42
+ const id = schema.$id;
43
+ if (typeof id === "string" && id.length > 0) {
44
+ const cleaned = id.replace(/[^a-zA-Z0-9_-]/g, "_").slice(0, 64);
45
+ if (cleaned.length > 0)
46
+ return cleaned;
47
+ }
48
+ return "structured_output";
49
+ }
50
+ export function createChatCompletionsProvider(options) {
51
+ const config = options ?? {};
52
+ const baseUrl = config.baseUrl ?? DEFAULT_BASE_URL;
53
+ const url = `${baseUrl}/chat/completions`;
54
+ const apiKey = config.apiKey ?? DEFAULT_API_KEY;
55
+ // The provider's configured model is a fallback: a per-request
56
+ // `req.model` (the framework's normal path) wins; the configured
57
+ // model (or the `local-coder` default) applies only when a request
58
+ // carries no model.
59
+ const configuredModel = config.model ?? DEFAULT_MODEL;
60
+ const timeoutMs = config.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
61
+ const fetchImpl = config.fetch ?? globalThis.fetch;
62
+ if (!fetchImpl) {
63
+ throw new Error("createChatCompletionsProvider: no fetch implementation available. Pass `fetch` explicitly or run in an environment that provides `globalThis.fetch` (Node ≥18, modern browsers, Expo).");
64
+ }
65
+ const respond = async (req) => {
66
+ if (req.signal?.aborted) {
67
+ throw abortError();
68
+ }
69
+ if (req.tools && req.tools.length > 0) {
70
+ throw new NonRetryableLlmError({
71
+ message: "The chat-completions provider does not support function tools — it serves structured-output requests only. Remove `tools` from the request or use a tool-capable provider.",
72
+ });
73
+ }
74
+ const stageIdMatch = STAGE_ID_MARKER.exec(req.systemPrompt);
75
+ const debugStageId = stageIdMatch ? stageIdMatch[1] : null;
76
+ const convertedSchema = typeboxToJsonSchema(req.outputSchema);
77
+ // Per-request model wins; the provider's configured model (or the
78
+ // `local-coder` default) is the fallback when a request carries none.
79
+ const model = req.model || configuredModel;
80
+ const body = {
81
+ model,
82
+ messages: [
83
+ { role: "system", content: req.systemPrompt },
84
+ { role: "user", content: req.userMessage },
85
+ ],
86
+ response_format: {
87
+ type: "json_schema",
88
+ json_schema: {
89
+ name: deriveSchemaName(req.outputSchema),
90
+ schema: convertedSchema,
91
+ },
92
+ },
93
+ // Deterministic structured output.
94
+ temperature: 0,
95
+ };
96
+ // `max_tokens`, positive only: 0 means "generate nothing".
97
+ if (req.maxOutputTokens !== undefined && req.maxOutputTokens > 0) {
98
+ body.max_tokens = req.maxOutputTokens;
99
+ }
100
+ debugLlmRequest({
101
+ stageId: debugStageId,
102
+ model,
103
+ maxOutputTokens: req.maxOutputTokens,
104
+ reasoningEffort: req.reasoningEffort,
105
+ systemPromptLen: req.systemPrompt.length,
106
+ userMessageLen: req.userMessage.length,
107
+ systemPromptHead: req.systemPrompt,
108
+ userMessageHead: req.userMessage,
109
+ });
110
+ let response;
111
+ try {
112
+ response = await requestJson({
113
+ url,
114
+ apiKey,
115
+ body,
116
+ fetchImpl,
117
+ signal: req.signal,
118
+ timeoutMs,
119
+ });
120
+ }
121
+ catch (err) {
122
+ // Honor a mid-flight abort: surface a clean AbortError so
123
+ // `llmStage`'s detector marks the stage skipped rather than
124
+ // failed. Other errors are already framework-classified by
125
+ // `requestJson`; re-throw them.
126
+ if (req.signal?.aborted ||
127
+ (err instanceof Error && err.name === "AbortError")) {
128
+ throw abortError();
129
+ }
130
+ const classified = err instanceof Error ? err : new Error(String(err));
131
+ debugLlmFailure({
132
+ stageId: debugStageId,
133
+ model,
134
+ errorName: classified.name,
135
+ errorMessage: classified.message,
136
+ tokenUsage: { input: 0, output: 0 },
137
+ });
138
+ throw classified;
139
+ }
140
+ const tokenUsage = {
141
+ input: response.usage?.prompt_tokens ?? 0,
142
+ output: response.usage?.completion_tokens ?? 0,
143
+ };
144
+ const text = response.choices?.[0]?.message?.content;
145
+ if (text === undefined || text === "") {
146
+ // Empty structured output is a schema-shaped failure — a re-roll
147
+ // can produce conforming output, so classify it (transient-
148
+ // tagged) `SchemaValidationLlmError`, not a generic transient.
149
+ debugLlmFailure({
150
+ stageId: debugStageId,
151
+ model,
152
+ errorName: "SchemaValidationLlmError",
153
+ errorMessage: "no assistant content",
154
+ tokenUsage,
155
+ });
156
+ throw new SchemaValidationLlmError({
157
+ message: "The chat-completions endpoint returned no assistant content.",
158
+ });
159
+ }
160
+ let parsed;
161
+ try {
162
+ parsed = JSON.parse(text);
163
+ }
164
+ catch (err) {
165
+ debugLlmFailure({
166
+ stageId: debugStageId,
167
+ model,
168
+ errorName: "SchemaValidationLlmError",
169
+ errorMessage: err instanceof Error ? err.message : String(err),
170
+ rawText: text,
171
+ tokenUsage,
172
+ });
173
+ throw new SchemaValidationLlmError({
174
+ message: `The chat-completions endpoint returned malformed JSON in structured-output content: ${err instanceof Error ? err.message : String(err)}`,
175
+ });
176
+ }
177
+ debugLlmResponse({
178
+ stageId: debugStageId,
179
+ outputTextLen: text.length,
180
+ tokenUsage,
181
+ });
182
+ return {
183
+ output: parsed,
184
+ tokenUsage,
185
+ // A chat-completions response carries no durable response id we
186
+ // surface; `rawResponseId` is optional, so leave it undefined.
187
+ rawResponseId: undefined,
188
+ };
189
+ };
190
+ return { respond };
191
+ }
192
+ //# sourceMappingURL=provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.js","sourceRoot":"","sources":["../../../src/extensions/chat-completions/provider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import type { TSchema } from "typebox";
2
+ /**
3
+ * The output shape is intentionally typed as a plain object literal
4
+ * (not a full JSON-Schema TS type). The endpoint's `json_schema`
5
+ * `schema` slot accepts this shape and we round-trip it through the
6
+ * request body. Keeping the return type loose avoids dragging a
7
+ * JSON-Schema dependency into the converter.
8
+ */
9
+ export type TChatCompletionsJsonSchema = Record<string, unknown>;
10
+ /**
11
+ * Convert a TypeBox schema into a standard JSON Schema document
12
+ * suitable for an OpenAI-compatible `json_schema` response format.
13
+ *
14
+ * Throws `UnsupportedSchemaError` when the source schema contains a
15
+ * TypeBox primitive outside the supported subset.
16
+ */
17
+ export declare function typeboxToJsonSchema(schema: TSchema): TChatCompletionsJsonSchema;
18
+ //# sourceMappingURL=structured-output.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"structured-output.d.ts","sourceRoot":"","sources":["../../../src/extensions/chat-completions/structured-output.ts"],"names":[],"mappings":"AA8BA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AAEtC;;;;;;GAMG;AACH,MAAM,MAAM,0BAA0B,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;AA6BhE;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAC/B,MAAM,EAAE,OAAO,GAChB,0BAA0B,CA0B5B"}