@effect-agent/ai-typesafe 0.1.0-beta.102 → 0.1.0-beta.103

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,126 +1,39 @@
1
1
  # @effect-agent/ai-typesafe
2
2
 
3
- Evaluate TypeSafe AI choice, score, and noul questions with Effect. The package uses
4
- Effect's platform-neutral `HttpClient`, `Schema`, `Config`, and `AiError` and has
5
- only an Effect runtime peer dependency (`^4.0.0-rc.115`).
3
+ Use Jev to evaluate typed questions with Effect. `TypeSafeDecisionModel` supplies the
4
+ provider for [`@effect-agent/ai-decision`](../ai-decision); `TypeSafeClient` owns HTTP
5
+ configuration and also exposes Jev's API directly.
6
6
 
7
- ```ts
8
- import { TypeSafeClient } from "@effect-agent/ai-typesafe";
9
- import { Config, Effect, Layer } from "effect";
10
- import { FetchHttpClient } from "effect/unstable/http";
11
-
12
- const evaluation = Effect.gen(function* () {
13
- const client = yield* TypeSafeClient.TypeSafeClient;
14
- const result = yield* client.evaluate({
15
- model: "jev-latest",
16
- state: { message: "I was charged twice. Please refund the duplicate." },
17
- questions: {
18
- department: {
19
- type: "choice",
20
- instructions: "Which team should handle this ticket?",
21
- criteria: { billing: "Payments and refunds", technical: "Bugs and outages" },
22
- },
23
- },
24
- });
25
-
26
- return result.answers.department.choice; // "billing" | "technical"
27
- });
28
-
29
- const ClientLive = TypeSafeClient.layerConfig({
30
- apiKey: Config.Redacted("TYPESAFE_API_KEY"),
31
- }).pipe(Layer.provide(FetchHttpClient.layer));
32
-
33
- const program = evaluation.pipe(Effect.provide(ClientLive));
7
+ ```text
8
+ DecisionModel TypeSafeDecisionModel → TypeSafeClient Jev
34
9
  ```
35
10
 
36
- Run `program` with your application's Effect runtime. The compiling
37
- [mixed-question example](examples/evaluate.ts) also shows bounded retries and an
38
- overall timeout. Acquiring the client does not send requests.
39
-
40
- ## Questions and answers
41
-
42
- `evaluate` sends `POST https://api.typesafe.ai/v1/systemone` with bearer authentication
43
- and the required `{ model, state, questions }` body. State and instructions accept
44
- strings, JSON objects, and JSON arrays. Nested values must be JSON-compatible.
45
-
46
- | Question | Criteria | Answer |
47
- | -------- | ------------------------------------------------------------------------ | ----------------------------------------------------------- |
48
- | `choice` | Nonempty map of option names to a string or `null` | `choice`, `probabilities`, `confidence` |
49
- | `score` | At least two ordered string descriptions | Fractional `score`, `legend`, `probabilities`, `confidence` |
50
- | `noul` | Optional object with optional string descriptions for `true` and `false` | `noul` in [0, 1] |
51
-
52
- Every answer includes its `type`. `model` and `usage.input_tokens` /
53
- `usage.output_tokens` are retained. A returned model may resolve the requested alias
54
- to a concrete version. Required fields are never filled in from examples or defaults.
55
- The supported wire shapes follow the [API reference](https://docs.typesafe.ai/api),
56
- including string-valued score legends.
57
-
58
- Use `satisfies TypeSafeSchema.Questions` to retain question keys and choice literals
59
- when defining questions separately. Runtime-built maps retain broader types:
60
- unknown answer IDs and probability keys may be absent, and mixed answers must be
61
- narrowed by `type`. Optional criteria remain optional in the probability map.
62
- Open string, numeric, and template-pattern indexes allow absent entries;
63
- explicitly required keys keep their required types.
11
+ ## Connect a decision model
64
12
 
65
- The client builds a response schema from each request. It checks the exact answer
66
- IDs and kinds, permitted choices, complete probability keys, and matching score
67
- legends. Probabilities and confidence must be finite and in [0, 1]. A choice must
68
- have maximal probability; ties are valid. Scores range from zero to the last level
69
- and must match their probability-weighted value. Distribution sums allow `1e-6`
70
- rounding error, and score comparisons allow `1e-6` times the highest level index.
71
- Values are preserved rather than normalized. Unexpected response fields are rejected.
72
-
73
- Confidence summarizes a distribution; it is not a correctness guarantee. Noul has
74
- no separate confidence. Choose application thresholds using evaluated examples for
75
- your domain. See TypeSafe's [confidence guide](https://docs.typesafe.ai/confidence).
76
-
77
- ## Errors, cancellation, and HTTP policies
78
-
79
- Evaluation failures use native `AiError` reasons:
80
-
81
- | Failure | Reason |
82
- | ------------------------------------------------------------ | ------------------------------------ |
83
- | Invalid local request or HTTP 422 | `InvalidRequestError` |
84
- | HTTP 401 | `AuthenticationError` (`InvalidKey`) |
85
- | HTTP 429 | `RateLimitError` |
86
- | HTTP 529 | `InternalProviderError` |
87
- | Transport failure | `NetworkError` |
88
- | Malformed JSON or a response that disagrees with the request | `InvalidOutputError` |
89
-
90
- `layerConfig` can also fail with `ConfigError`. Defects and interruption remain
91
- defects and interruption. Cancellation reaches the supplied HttpClient, including
92
- while reading the response body.
93
-
94
- HTTP status failures retain the status, request details, response headers, and raw
95
- provider error text without assuming an error-body protocol. Sensitive headers and
96
- the configured API key are redacted from diagnostics. Provider error text may contain
97
- submitted content. The integration adds no body logging; HTTP tracing is controlled
98
- by Effect HttpClient and the application.
99
-
100
- There are no default retries or deadlines. Compose `Effect.retry` with a bounded
101
- schedule and `Effect.timeout`, or supply `transformClient` to `make`, `layer`, or
102
- `layerConfig`. The transformer receives the client after authentication and status
103
- filtering. `apiUrl` overrides the versioned base URL for a proxy or substitute.
13
+ ```ts
14
+ import { TypeSafeClient, TypeSafeDecisionModel } from "@effect-agent/ai-typesafe";
15
+ import { Layer } from "effect";
16
+ import { FetchHttpClient } from "effect/unstable/http";
104
17
 
105
- ## Native Effect AI tools
18
+ const DecisionLive = TypeSafeDecisionModel.model("jev-latest").pipe(
19
+ Layer.provide(TypeSafeClient.layerConfig().pipe(Layer.provide(FetchHttpClient.layer))),
20
+ );
21
+ ```
106
22
 
107
- The compiling [tool example](examples/tool.ts) declares a native `Tool` with
108
- `failure: AiError.AiError` and `dependencies: [TypeSafeClient.TypeSafeClient]`, then
109
- implements it through `Toolkit.toLayer`. The declared default failure mode keeps
110
- failures in the Effect error channel. Supply TypeSafeClient when executing the tool
111
- or providing it to an agent's language model.
23
+ Set `TYPESAFE_API_KEY`, then provide `DecisionLive` to the Effect that evaluates your
24
+ decision set. The adapter maps shared `probability` questions to Jev's `noul` and retains
25
+ choice and score distributions. Application code chooses how to use the answers.
112
26
 
113
- The package exposes evaluations directly. Language generation, chat, streaming,
114
- and tool planning are outside its API.
27
+ There are no default retries or deadlines. Add those policies with Effect or the client's
28
+ `transformClient` option. See the [configuration and error reference](https://effect-agent.com/reference/decision-models#typesafe-client)
29
+ for details, including Jev's [rounded probabilities](https://effect-agent.com/reference/decision-models#probability-validation).
115
30
 
116
- ## Modules and extraction
31
+ ## Examples
117
32
 
118
- Root exports are the `TypeSafeClient` and `TypeSafeSchema` namespaces. Direct imports
119
- use `@effect-agent/ai-typesafe/type-safe-client` and
120
- `@effect-agent/ai-typesafe/type-safe-schema`.
33
+ - [Decision set and state transition](examples/decision.ts): all three query types with provider setup.
34
+ - [Direct evaluation](examples/evaluate.ts): native choice, score, and noul answers, bounded retries, and a timeout.
35
+ - [Native Effect AI tool](examples/tool.ts): expose a fixed assessment through `Tool` and `Toolkit`.
121
36
 
122
- This package follows Effect provider module conventions while incubating in the
123
- Effect Agent release group. Its source imports only `effect/*`; it has no engine,
124
- platform, persistence, or vendor SDK dependency. Upstream extraction would change
125
- package metadata, service identity, import paths, and release documentation while
126
- retaining the HTTP contracts and tests.
37
+ Each example exports an Effect to run with your application's runtime. Start with the
38
+ [decision guide](https://effect-agent.com/guide/tools#decision-transitions), or use the
39
+ [reference](https://effect-agent.com/reference/decision-models) for options, results, and errors.
@@ -90,7 +90,13 @@ const mapHttpClientError = Effect.fnUntraced(function* (error, redact) {
90
90
  //#endregion
91
91
  //#region src/internal/schema.ts
92
92
  const tolerance = 1e-6;
93
- const distribution = (keys) => Schema.Record(Schema.Literals(keys), Probability).check(Schema.makeFilter((probabilities) => Math.abs(Object.values(probabilities).reduce((sum, value) => sum + value, 0) - 1) <= tolerance, { expected: "probabilities summing to 1 (within 1e-6)" }));
93
+ const probabilitySum = Schema.makeFilter((probabilities) => Math.abs(Object.values(probabilities).reduce((sum, value) => sum + value, 0) - 1) <= tolerance, { expected: "probabilities summing to 1 (within 1e-6)" });
94
+ const choiceProbabilitySum = Schema.makeFilter((probabilities) => {
95
+ const values = Object.values(probabilities);
96
+ const error = Math.abs(values.reduce((sum, value) => sum + value, 0) - 1);
97
+ return error <= tolerance || error <= Math.min(.01, values.length * .005) + tolerance && values.every((value) => Math.abs(value * 100 - Math.round(value * 100)) < 1e-8);
98
+ }, { expected: "probabilities summing to 1 within bounded two-decimal Choice rounding" });
99
+ const distribution = (keys, sumCheck = probabilitySum) => Schema.Record(Schema.Literals(keys), Probability).check(sumCheck);
94
100
  const answerFor = (question) => {
95
101
  switch (question.type) {
96
102
  case "choice": {
@@ -98,7 +104,7 @@ const answerFor = (question) => {
98
104
  return Schema.Struct({
99
105
  ...ChoiceAnswer.fields,
100
106
  choice: Schema.Literals(keys),
101
- probabilities: distribution(keys)
107
+ probabilities: distribution(keys, choiceProbabilitySum)
102
108
  }).check(Schema.makeFilter(({ choice, probabilities }) => Object.values(probabilities).every((value) => value <= probabilities[choice]), { expected: "a highest-probability choice" }));
103
109
  }
104
110
  case "score": {
@@ -184,6 +190,6 @@ const layerConfig = (options) => Layer.effect(TypeSafeClient, Effect.gen(functio
184
190
  });
185
191
  }));
186
192
  //#endregion
187
- export { make as a, layerConfig as i, TypeSafeClient_exports as n, layer as r, TypeSafeClient as t };
193
+ export { make as a, layerConfig as i, TypeSafeClient_exports as n, choiceProbabilitySum as o, layer as r, TypeSafeClient as t };
188
194
 
189
- //# sourceMappingURL=TypeSafeClient-OS5hTVMz.mjs.map
195
+ //# sourceMappingURL=TypeSafeClient-SjzPX2Gl.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TypeSafeClient-SjzPX2Gl.mjs","names":["make","TypeSafeSchema.Probability","TypeSafeSchema.NoulAnswer","TypeSafeSchema.EvaluateRequest","Errors.make","Errors.mapHttpClientError","Errors.mapSchemaError"],"sources":["../src/internal/errors.ts","../src/internal/schema.ts","../src/TypeSafeClient.ts"],"sourcesContent":["import * as Effect from \"effect/Effect\";\nimport * as Option from \"effect/Option\";\nimport * as Record from \"effect/Record\";\nimport * as Redacted from \"effect/Redacted\";\nimport type * as Schema from \"effect/Schema\";\nimport * as AiError from \"effect/unstable/ai/AiError\";\nimport * as Headers from \"effect/unstable/http/Headers\";\nimport type * as HttpClientError from \"effect/unstable/http/HttpClientError\";\n\nexport const make = (reason: AiError.AiErrorReason): AiError.AiError =>\n AiError.make({ module: \"TypeSafeClient\", method: \"evaluate\", reason });\n\nexport const mapSchemaError = (\n error: Schema.SchemaError,\n redact: (text: string) => string,\n): AiError.AiError => {\n const reason = AiError.InvalidOutputError.fromSchemaError(error);\n\n return make(\n new AiError.InvalidOutputError({ ...reason, description: redact(reason.description) }),\n );\n};\n\nconst redactRequest = (\n request: typeof AiError.HttpRequestDetails.Type,\n redact: (text: string) => string,\n): typeof AiError.HttpRequestDetails.Type => ({\n ...request,\n url: redact(request.url),\n urlParams: request.urlParams.map(([key, value]) => [key, redact(value)]),\n hash: request.hash === undefined ? undefined : redact(request.hash),\n headers: Record.map(request.headers, (value) =>\n Redacted.isRedacted(value) ? \"<redacted>\" : redact(value),\n ),\n});\n\nexport const mapHttpClientError = Effect.fnUntraced(function* (\n error: HttpClientError.HttpClientError,\n redact: (text: string) => string,\n): Effect.fn.Return<never, AiError.AiError> {\n const reason = error.reason;\n\n switch (reason._tag) {\n case \"TransportError\":\n case \"EncodeError\":\n case \"InvalidUrlError\": {\n const network = AiError.NetworkError.fromRequestError(reason);\n\n return yield* make(\n new AiError.NetworkError({\n ...network,\n request: redactRequest(network.request, redact),\n description: network.description === undefined ? undefined : redact(network.description),\n }),\n );\n }\n case \"DecodeError\":\n case \"EmptyBodyError\":\n return yield* make(\n new AiError.InvalidOutputError({\n description: redact(reason.description ?? \"Could not decode the TypeSafe response body\"),\n }),\n );\n case \"StatusCodeError\": {\n const { request, response } = reason;\n const redactedNames = yield* Headers.CurrentRedactedNames;\n\n const headers = (value: Headers.Headers) =>\n Record.map(Headers.redact(value, redactedNames), (value) =>\n Redacted.isRedacted(value) ? \"<redacted>\" : redact(value),\n );\n\n const text = yield* Effect.option(response.text);\n const body = Option.isSome(text) ? redact(text.value) : undefined;\n\n const http: typeof AiError.HttpContext.Type = {\n request: {\n method: request.method,\n url: redact(request.url),\n urlParams: Array.from(request.urlParams, ([key, value]) => [key, redact(value)]),\n hash: Option.getOrUndefined(Option.map(request.hash, redact)),\n headers: headers(request.headers),\n },\n response: { status: response.status, headers: headers(response.headers) },\n body,\n };\n\n const description = AiError.buildErrorDescription({\n status: response.status,\n method: request.method,\n url: http.request.url,\n message: undefined,\n body,\n });\n\n return yield* make(\n response.status === 422\n ? new AiError.InvalidRequestError({ description, http })\n : AiError.reasonFromHttpStatus({ status: response.status, description, http }),\n );\n }\n }\n});\n","import * as Schema from \"effect/Schema\";\n\nimport * as TypeSafeSchema from \"../TypeSafeSchema.ts\";\n\n// Permit floating-point serialization error without changing provider values.\nconst tolerance = 1e-6;\n\nconst probabilitySum = Schema.makeFilter(\n (probabilities: Readonly<Record<string, number>>) =>\n Math.abs(Object.values(probabilities).reduce((sum, value) => sum + value, 0) - 1) <= tolerance,\n { expected: \"probabilities summing to 1 (within 1e-6)\" },\n);\n\n// Jev Choice responses have been observed with two-decimal probabilities totaling 0.99.\n// Limit compatibility to one percentage point, even for very large option catalogues.\n// Score sums/weighting retain their strict checks; no Score rounding contract is assumed.\nexport const choiceProbabilitySum = Schema.makeFilter(\n (probabilities: Readonly<Record<string, number>>) => {\n const values = Object.values(probabilities);\n const error = Math.abs(values.reduce((sum, value) => sum + value, 0) - 1);\n\n return (\n error <= tolerance ||\n (error <= Math.min(0.01, values.length * 0.005) + tolerance &&\n values.every((value) => Math.abs(value * 100 - Math.round(value * 100)) < 1e-8))\n );\n },\n { expected: \"probabilities summing to 1 within bounded two-decimal Choice rounding\" },\n);\n\nconst distribution = (keys: ReadonlyArray<string>, sumCheck = probabilitySum) =>\n Schema.Record(Schema.Literals(keys), TypeSafeSchema.Probability).check(sumCheck);\n\nconst answerFor = (question: TypeSafeSchema.Question) => {\n switch (question.type) {\n case \"choice\": {\n const keys = Object.keys(question.criteria);\n\n return Schema.Struct({\n ...TypeSafeSchema.ChoiceAnswer.fields,\n choice: Schema.Literals(keys),\n probabilities: distribution(keys, choiceProbabilitySum),\n }).check(\n Schema.makeFilter(\n ({ choice, probabilities }) =>\n Object.values(probabilities).every((value) => value <= probabilities[choice]),\n { expected: \"a highest-probability choice\" },\n ),\n );\n }\n case \"score\": {\n const maxLevel = question.criteria.length - 1;\n\n const levels = question.criteria.map(\n (description, index) => [String(index), description] as const,\n );\n\n return Schema.Struct({\n ...TypeSafeSchema.ScoreAnswer.fields,\n score: Schema.Finite.check(Schema.isBetween({ minimum: 0, maximum: maxLevel })),\n legend: Schema.Struct(\n Object.fromEntries(\n levels.map(([key, description]) => [key, Schema.Literal(description)]),\n ),\n ),\n probabilities: distribution(levels.map(([key]) => key)),\n }).check(\n Schema.makeFilter(\n ({ score, probabilities }) =>\n Math.abs(\n score -\n Object.entries(probabilities).reduce(\n (sum, [level, probability]) => sum + Number(level) * probability,\n 0,\n ),\n ) <=\n tolerance * Math.max(1, maxLevel),\n { expected: \"the probability-weighted score (within 1e-6 per level)\" },\n ),\n );\n }\n case \"noul\":\n return TypeSafeSchema.NoulAnswer;\n }\n};\n\n// The overload describes the dependent type enforced by the literal keys and\n// per-question schemas below. No JSON value is asserted to have that type.\nexport function responseFor<const Q extends TypeSafeSchema.Questions>(\n questions: Q,\n): Schema.Codec<TypeSafeSchema.EvaluateResponse<Q>>;\n\nexport function responseFor(questions: TypeSafeSchema.Questions): Schema.Top {\n return Schema.Struct({\n ...TypeSafeSchema.EvaluateResponse.fields,\n answers: Schema.Struct(\n Object.fromEntries(\n Object.entries(questions).map(([id, question]) => [id, answerFor(question)]),\n ),\n ),\n });\n}\n","/**\n * An Effect HttpClient integration for TypeSafe's System One evaluations.\n *\n * @since 0.1.0\n */\nimport * as Config from \"effect/Config\";\nimport * as Context from \"effect/Context\";\nimport * as Effect from \"effect/Effect\";\nimport { flow, identity } from \"effect/Function\";\nimport * as Layer from \"effect/Layer\";\nimport * as Redacted from \"effect/Redacted\";\nimport * as Schema from \"effect/Schema\";\nimport * as AiError from \"effect/unstable/ai/AiError\";\nimport * as Headers from \"effect/unstable/http/Headers\";\nimport * as HttpClient from \"effect/unstable/http/HttpClient\";\nimport * as HttpClientRequest from \"effect/unstable/http/HttpClientRequest\";\nimport * as HttpClientResponse from \"effect/unstable/http/HttpClientResponse\";\n\nimport * as Errors from \"./internal/errors.ts\";\nimport { responseFor } from \"./internal/schema.ts\";\nimport * as TypeSafeSchema from \"./TypeSafeSchema.ts\";\n\n/** @category services\n * @since 0.1.0\n */\nexport interface Service {\n readonly client: HttpClient.HttpClient;\n\n /**\n * Evaluate mixed questions against one state. Answers are validated against\n * the submitted IDs, types, and criteria before receiving their inferred type.\n * There are no automatic retries or timeouts; compose those with Effect.\n */\n readonly evaluate: <const Q extends TypeSafeSchema.Questions>(\n options: TypeSafeSchema.EvaluateRequest<Q>,\n ) => Effect.Effect<TypeSafeSchema.EvaluateResponse<Q>, AiError.AiError>;\n}\n\n/** @category services\n * @since 0.1.0\n */\nexport class TypeSafeClient extends Context.Service<TypeSafeClient, Service>()(\n \"@effect-agent/ai-typesafe/TypeSafeClient\",\n) {}\n\n/** @category options\n * @since 0.1.0\n */\nexport interface Options {\n readonly apiKey: Redacted.Redacted<string>;\n /** Base URL, including the API version. Defaults to https://api.typesafe.ai/v1. */\n readonly apiUrl?: string | undefined;\n /** Applied after authentication and status filtering, for explicit HTTP policies. */\n readonly transformClient?: ((client: HttpClient.HttpClient) => HttpClient.HttpClient) | undefined;\n}\n\nconst encodeRequest = Schema.encodeEffect(Schema.fromJsonString(TypeSafeSchema.EvaluateRequest));\n\n/**\n * Construct the client using a supplied, platform-neutral HttpClient.\n * Acquiring the service does not send a request.\n *\n * @category constructors\n * @since 0.1.0\n */\nexport const make = Effect.fnUntraced(function* (\n options: Options,\n): Effect.fn.Return<Service, never, HttpClient.HttpClient> {\n const apiKey = Redacted.value(options.apiKey);\n\n const redact = (text: string) =>\n apiKey.length === 0 ? text : text.replaceAll(apiKey, \"<redacted>\");\n\n const client = (yield* HttpClient.HttpClient).pipe(\n HttpClient.mapRequest(\n flow(\n HttpClientRequest.prependUrl(options.apiUrl ?? \"https://api.typesafe.ai/v1\"),\n HttpClientRequest.bearerToken(options.apiKey),\n HttpClientRequest.acceptJson,\n ),\n ),\n HttpClient.filterStatusOk,\n options.transformClient ?? identity,\n );\n\n const evaluate = Effect.fnUntraced(function* <const Q extends TypeSafeSchema.Questions>(\n options: TypeSafeSchema.EvaluateRequest<Q>,\n ): Effect.fn.Return<TypeSafeSchema.EvaluateResponse<Q>, AiError.AiError> {\n const body = yield* encodeRequest(options).pipe(\n Effect.mapError((error) =>\n Errors.make(new AiError.InvalidRequestError({ description: redact(error.message) })),\n ),\n );\n\n const schema = responseFor(options.questions);\n\n return yield* client\n .execute(\n HttpClientRequest.post(\"/systemone\").pipe(\n HttpClientRequest.bodyText(body, \"application/json\"),\n ),\n )\n .pipe(\n Effect.flatMap(HttpClientResponse.schemaBodyJson(schema, { onExcessProperty: \"error\" })),\n Effect.catchTags({\n HttpClientError: (error) => Errors.mapHttpClientError(error, redact),\n SchemaError: (error) => Effect.fail(Errors.mapSchemaError(error, redact)),\n }),\n Effect.updateService(Headers.CurrentRedactedNames, (names) => [...names, \"authorization\"]),\n );\n });\n\n return TypeSafeClient.of({ client, evaluate });\n});\n\n/** @category layers\n * @since 0.1.0\n */\nexport const layer = (\n options: Options,\n): Layer.Layer<TypeSafeClient, never, HttpClient.HttpClient> =>\n Layer.effect(TypeSafeClient, make(options));\n\n/**\n * Configure the client with Effect Config. The API key defaults to\n * `Config.Redacted(\"TYPESAFE_API_KEY\")`.\n *\n * @category layers\n * @since 0.1.0\n */\nexport const layerConfig = (options?: {\n readonly apiKey?: Config.Config<Redacted.Redacted<string>> | undefined;\n readonly apiUrl?: Config.Config<string> | undefined;\n readonly transformClient?: Options[\"transformClient\"];\n}): Layer.Layer<TypeSafeClient, Config.ConfigError, HttpClient.HttpClient> =>\n Layer.effect(\n TypeSafeClient,\n Effect.gen(function* () {\n return yield* make({\n apiKey: yield* options?.apiKey ?? Config.Redacted(\"TYPESAFE_API_KEY\"),\n apiUrl: options?.apiUrl === undefined ? undefined : yield* options.apiUrl,\n transformClient: options?.transformClient,\n });\n }),\n );\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { EvaluateRequest, EvaluateResponse, Questions, t as TypeSafeSchema_d_exports } from "./TypeSafeSchema.mjs";
1
+ import { c as EvaluateResponse, g as TypeSafeSchema_d_exports, p as Questions, s as EvaluateRequest } from "./TypeSafeSchema-Dn4_Tptf.mjs";
2
2
  import * as Config from "effect/Config";
3
3
  import * as Context from "effect/Context";
4
4
  import * as Effect from "effect/Effect";
@@ -1,3 +1,3 @@
1
- import { a as make, i as layerConfig, r as layer, t as TypeSafeClient } from "./TypeSafeClient-OS5hTVMz.mjs";
1
+ import { a as make, i as layerConfig, r as layer, t as TypeSafeClient } from "./TypeSafeClient-SjzPX2Gl.mjs";
2
2
  import "./TypeSafeSchema.mjs";
3
3
  export { TypeSafeClient, layer, layerConfig, make };
@@ -0,0 +1,25 @@
1
+ import { TypeSafeClient } from "./TypeSafeClient.mjs";
2
+ import { DecisionModel } from "@effect-agent/ai-decision";
3
+ import { Layer, Schema } from "effect";
4
+ declare namespace TypeSafeDecisionModel_d_exports {
5
+ export { ProviderMetadata, model };
6
+ }
7
+ /**
8
+ * TypeSafe's distribution statistics, under result.providerMetadata.typesafe.
9
+ * Noul questions have no confidence entry.
10
+ *
11
+ * @category schemas
12
+ * @since 0.1.0
13
+ */
14
+ export declare const ProviderMetadata: Schema.Struct<{
15
+ readonly confidence: Schema.$Record<Schema.String, Schema.Finite>;
16
+ }>;
17
+ /**
18
+ * Supply a TypeSafe model as a provider-neutral decision model. The client retains HTTP policy;
19
+ * this adapter translates probability questions to noul and preserves returned evidence/usage.
20
+ * Capture TypeSafeClient at Layer construction. This Layer does not supply LanguageModel.
21
+ */
22
+ export declare const model: (model: string) => Layer.Layer<DecisionModel.DecisionModel, never, TypeSafeClient>;
23
+ //#endregion
24
+ export { TypeSafeDecisionModel_d_exports as t };
25
+ //# sourceMappingURL=TypeSafeDecisionModel.d.mts.map
@@ -0,0 +1,68 @@
1
+ import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
2
+ import { o as choiceProbabilitySum, t as TypeSafeClient } from "./TypeSafeClient-SjzPX2Gl.mjs";
3
+ import { Probability } from "./TypeSafeSchema.mjs";
4
+ import { DecisionModel } from "@effect-agent/ai-decision";
5
+ import { Effect, Layer, Schema } from "effect";
6
+ //#region src/TypeSafeDecisionModel.ts
7
+ var TypeSafeDecisionModel_exports = /* @__PURE__ */ __exportAll({
8
+ ProviderMetadata: () => ProviderMetadata,
9
+ model: () => model
10
+ });
11
+ /**
12
+ * TypeSafe's distribution statistics, under result.providerMetadata.typesafe.
13
+ * Noul questions have no confidence entry.
14
+ *
15
+ * @category schemas
16
+ * @since 0.1.0
17
+ */
18
+ const ProviderMetadata = Schema.Struct({ confidence: Schema.Record(Schema.String, Probability) });
19
+ /**
20
+ * Supply a TypeSafe model as a provider-neutral decision model. The client retains HTTP policy;
21
+ * this adapter translates probability questions to noul and preserves returned evidence/usage.
22
+ * Capture TypeSafeClient at Layer construction. This Layer does not supply LanguageModel.
23
+ */
24
+ const model = (model) => Layer.effect(DecisionModel.DecisionModel, Effect.gen(function* () {
25
+ const client = yield* TypeSafeClient;
26
+ return yield* DecisionModel.make({
27
+ choiceProbabilitySum,
28
+ evaluate: Effect.fnUntraced(function* (request) {
29
+ const questions = Object.fromEntries(Object.entries(request.questions).map(([id, question]) => [id, question.type === "probability" ? {
30
+ ...question,
31
+ type: "noul"
32
+ } : question]));
33
+ const response = yield* client.evaluate({
34
+ model,
35
+ state: request.state,
36
+ questions
37
+ });
38
+ const answers = [];
39
+ const confidence = [];
40
+ for (const [id, answer] of Object.entries(response.answers)) {
41
+ if (answer === void 0) continue;
42
+ if (answer.type === "noul") answers.push([id, {
43
+ type: "probability",
44
+ probability: answer.noul
45
+ }]);
46
+ else {
47
+ const { confidence: statistic, ...evidence } = answer;
48
+ answers.push([id, evidence]);
49
+ confidence.push([id, statistic]);
50
+ }
51
+ }
52
+ return {
53
+ provider: "typesafe",
54
+ model: response.model,
55
+ answers: Object.fromEntries(answers),
56
+ usage: {
57
+ inputTokens: response.usage.input_tokens,
58
+ outputTokens: response.usage.output_tokens
59
+ },
60
+ providerMetadata: { typesafe: { confidence: Object.fromEntries(confidence) } }
61
+ };
62
+ })
63
+ });
64
+ }));
65
+ //#endregion
66
+ export { ProviderMetadata, model, TypeSafeDecisionModel_exports as t };
67
+
68
+ //# sourceMappingURL=TypeSafeDecisionModel.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TypeSafeDecisionModel.mjs","names":["TypeSafeSchema.Probability"],"sources":["../src/TypeSafeDecisionModel.ts"],"sourcesContent":["import { DecisionModel, type DecisionSchema } from \"@effect-agent/ai-decision\";\nimport { Effect, Layer, Schema } from \"effect\";\n\nimport { choiceProbabilitySum } from \"./internal/schema.ts\";\nimport { TypeSafeClient } from \"./TypeSafeClient.ts\";\nimport * as TypeSafeSchema from \"./TypeSafeSchema.ts\";\n\n/**\n * TypeSafe's distribution statistics, under result.providerMetadata.typesafe.\n * Noul questions have no confidence entry.\n *\n * @category schemas\n * @since 0.1.0\n */\nexport const ProviderMetadata = Schema.Struct({\n confidence: Schema.Record(Schema.String, TypeSafeSchema.Probability),\n});\n\n/**\n * Supply a TypeSafe model as a provider-neutral decision model. The client retains HTTP policy;\n * this adapter translates probability questions to noul and preserves returned evidence/usage.\n * Capture TypeSafeClient at Layer construction. This Layer does not supply LanguageModel.\n */\nexport const model = (\n model: string,\n): Layer.Layer<DecisionModel.DecisionModel, never, TypeSafeClient> =>\n Layer.effect(\n DecisionModel.DecisionModel,\n Effect.gen(function* () {\n const client = yield* TypeSafeClient;\n\n return yield* DecisionModel.make({\n choiceProbabilitySum,\n evaluate: Effect.fnUntraced(function* (request) {\n const questions: TypeSafeSchema.Questions = Object.fromEntries(\n Object.entries(request.questions).map(([id, question]) => [\n id,\n question.type === \"probability\" ? { ...question, type: \"noul\" } : question,\n ]),\n );\n\n const response = yield* client.evaluate({ model, state: request.state, questions });\n\n const answers: Array<readonly [string, DecisionSchema.Answer]> = [];\n\n const confidence: Array<readonly [string, number]> = [];\n\n for (const [id, answer] of Object.entries(response.answers)) {\n if (answer === undefined) continue;\n if (answer.type === \"noul\") {\n answers.push([id, { type: \"probability\", probability: answer.noul }]);\n } else {\n const { confidence: statistic, ...evidence } = answer;\n\n answers.push([id, evidence]);\n confidence.push([id, statistic]);\n }\n }\n\n return {\n provider: \"typesafe\",\n model: response.model,\n answers: Object.fromEntries(answers),\n usage: {\n inputTokens: response.usage.input_tokens,\n outputTokens: response.usage.output_tokens,\n },\n providerMetadata: {\n typesafe: {\n confidence: Object.fromEntries(confidence),\n },\n },\n };\n }),\n });\n }),\n );\n"],"mappings":";;;;;;;;;;;;;;;;;AAcA,MAAa,mBAAmB,OAAO,OAAO,EAC5C,YAAY,OAAO,OAAO,OAAO,QAAQA,WAA0B,EACrE,CAAC;;;;;;AAOD,MAAa,SACX,UAEA,MAAM,OACJ,cAAc,eACd,OAAO,IAAI,aAAa;CACtB,MAAM,SAAS,OAAO;CAEtB,OAAO,OAAO,cAAc,KAAK;EAC/B;EACA,UAAU,OAAO,WAAW,WAAW,SAAS;GAC9C,MAAM,YAAsC,OAAO,YACjD,OAAO,QAAQ,QAAQ,SAAS,CAAC,CAAC,KAAK,CAAC,IAAI,cAAc,CACxD,IACA,SAAS,SAAS,gBAAgB;IAAE,GAAG;IAAU,MAAM;GAAO,IAAI,QACpE,CAAC,CACH;GAEA,MAAM,WAAW,OAAO,OAAO,SAAS;IAAE;IAAO,OAAO,QAAQ;IAAO;GAAU,CAAC;GAElF,MAAM,UAA2D,CAAC;GAElE,MAAM,aAA+C,CAAC;GAEtD,KAAK,MAAM,CAAC,IAAI,WAAW,OAAO,QAAQ,SAAS,OAAO,GAAG;IAC3D,IAAI,WAAW,KAAA,GAAW;IAC1B,IAAI,OAAO,SAAS,QAClB,QAAQ,KAAK,CAAC,IAAI;KAAE,MAAM;KAAe,aAAa,OAAO;IAAK,CAAC,CAAC;SAC/D;KACL,MAAM,EAAE,YAAY,WAAW,GAAG,aAAa;KAE/C,QAAQ,KAAK,CAAC,IAAI,QAAQ,CAAC;KAC3B,WAAW,KAAK,CAAC,IAAI,SAAS,CAAC;IACjC;GACF;GAEA,OAAO;IACL,UAAU;IACV,OAAO,SAAS;IAChB,SAAS,OAAO,YAAY,OAAO;IACnC,OAAO;KACL,aAAa,SAAS,MAAM;KAC5B,cAAc,SAAS,MAAM;IAC/B;IACA,kBAAkB,EAChB,UAAU,EACR,YAAY,OAAO,YAAY,UAAU,EAC3C,EACF;GACF;EACF,CAAC;CACH,CAAC;AACH,CAAC,CACH"}