1/**
2 * The `OpenAiConfig` module lets a workflow temporarily customize the HTTP
3 * client used by `@effect/ai-openai` request helpers. OpenAI client, language
4 * model, and embedding code read this scoped transform when they execute
5 * provider calls.
6 *
7 * @since 4.0.0
8 */
9import * as Context from "effect/Context"
10import * as Effect from "effect/Effect"
11import { dual } from "effect/Function"
12import type { HttpClient } from "effect/http/HttpClient"
13
14/**
15 * Context service for scoped OpenAI configuration used by provider operations.
16 *
17 * **When to use**
18 *
19 * Use to provide scoped OpenAI client configuration, such as an HTTP client
20 * transform, to OpenAI provider operations without passing it through each call.
21 *
22 * @see {@link withClientTransform} for scoping an HTTP client transformation
23 *
24 * @category services
25 * @since 4.0.0
26 */
27export class OpenAiConfig extends Context.Service<
28 OpenAiConfig,
29 OpenAiConfig.Service
30>()("@effect/ai-openai/OpenAiConfig") {
31 /**
32 * Gets the configured OpenAI service from the current context when present.
33 *
34 * @since 4.0.0
35 */
36 static readonly getOrUndefined: Effect.Effect<typeof OpenAiConfig.Service | undefined> = Effect.map(
37 Effect.context<never>(),
38 Context.getOrUndefined(OpenAiConfig)
39 )
40}
41
42/**
43 * Types used by the `OpenAiConfig` context service.
44 *
45 * @since 4.0.0
46 */
47export declare namespace OpenAiConfig {
48 /**
49 * Configuration values read by OpenAI provider operations when executing
50 * requests.
51 *
52 * @category services
53 * @since 4.0.0
54 */
55 export interface Service {
56 readonly transformClient?: ((client: HttpClient) => HttpClient) | undefined
57 }
58}
59
60/**
61 * Provides a scoped transform for the OpenAI HTTP client used by provider
62 * operations.
63 *
64 * **When to use**
65 *
66 * Use when you need temporary OpenAI HTTP client customization for a single
67 * effect or workflow without rebuilding the client layer.
68 *
69 * **Details**
70 *
71 * Supports both data-first and data-last forms. The transform is stored in the
72 * scoped `OpenAiConfig` service and read by OpenAI provider operations while
73 * running the supplied effect.
74 *
75 * **Gotchas**
76 *
77 * If a transform is already present in the scoped config, this helper replaces
78 * it. Compose transforms manually when both should apply.
79 *
80 * @category configuration
81 * @since 4.0.0
82 */
83export const withClientTransform: {
84 (transform: (client: HttpClient) => HttpClient): <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>
85 <A, E, R>(self: Effect.Effect<A, E, R>, transform: (client: HttpClient) => HttpClient): Effect.Effect<A, E, R>
86} = dual(2, <A, E, R>(
87 self: Effect.Effect<A, E, R>,
88 transformClient: (client: HttpClient) => HttpClient
89) =>
90 Effect.flatMap(
91 OpenAiConfig.getOrUndefined,
92 (config) => Effect.provideService(self, OpenAiConfig, { ...config, transformClient })
93 ))