@effect-uai/typesafe-ai 0.17.0 → 0.18.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.
package/README.md CHANGED
@@ -17,12 +17,12 @@ pnpm add @effect-uai/core @effect-uai/typesafe-ai effect
17
17
 
18
18
  ```ts
19
19
  import { Config, Effect, Layer } from "effect"
20
- import { FetchHttpClient } from "effect/unstable/http"
20
+ import { FetchHttpClient } from "effect/http"
21
21
  import { layer as jevLayer } from "@effect-uai/typesafe-ai/Jev"
22
22
 
23
23
  const provider = Layer.unwrap(
24
24
  Effect.gen(function* () {
25
- const apiKey = yield* Config.redacted("TYPESAFE_AI_API_KEY")
25
+ const apiKey = yield* Config.Redacted("TYPESAFE_AI_API_KEY")
26
26
  return jevLayer({ apiKey })
27
27
  }),
28
28
  )
package/dist/Jev.d.mts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { JevModel } from "./models.mjs";
2
2
  import { Context, Effect, Layer, Redacted } from "effect";
3
- import { HttpClient } from "effect/unstable/http";
3
+ import { HttpClient } from "effect/http";
4
4
  import * as AiError from "@effect-uai/core/AiError";
5
5
  import { CommonDecideRequest, DecideResponse, DecisionModel } from "@effect-uai/core/DecisionModel";
6
6
  import * as Decision from "@effect-uai/core/Decision";
package/dist/Jev.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
2
2
  import { Context, Effect, Layer, Match, Record, Schema, pipe } from "effect";
3
- import { HttpClient, HttpClientRequest } from "effect/unstable/http";
3
+ import { HttpClient, HttpClientRequest } from "effect/http";
4
4
  import * as AiError from "@effect-uai/core/AiError";
5
5
  import { DecisionModel } from "@effect-uai/core/DecisionModel";
6
6
  //#region src/Jev.ts
package/dist/Jev.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"Jev.mjs","names":[],"sources":["../src/Jev.ts"],"sourcesContent":["import { Context, Effect, Layer, Match, type Redacted, Record, Schema, pipe } from \"effect\"\nimport { HttpClient, HttpClientRequest } from \"effect/unstable/http\"\nimport * as AiError from \"@effect-uai/core/AiError\"\nimport * as Decision from \"@effect-uai/core/Decision\"\nimport {\n type CommonDecideRequest,\n type DecideResponse,\n DecisionModel,\n type DecisionModelService,\n} from \"@effect-uai/core/DecisionModel\"\nimport type { JevModel } from \"./models.js\"\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\n/**\n * Jev reports its own `confidence` alongside the distribution, on Classify\n * and Rate but not on Probability. The formula is undocumented, so it is not\n * on the Common answer; `Decision.confidence` is ours and is defined for\n * every kind.\n */\nexport type JevAnswerFor<D> = Decision.AnswerFor<D> & ReportedConfidence<D>\n\n/**\n * Intersected rather than branched per kind, so `JevAnswers` stays provably\n * assignable to `Answers`: TypeScript cannot see one deferred conditional as\n * a subtype of another, but an intersection is always assignable to its\n * members.\n */\ntype ReportedConfidence<D> = D extends { readonly _tag: \"Probability\" }\n ? unknown\n : { readonly confidence: number }\n\nexport type JevAnswers<D extends Decision.Decisions> = {\n readonly [K in keyof D]: JevAnswerFor<D[K]>\n}\n\nexport type JevDecideResponse<D extends Decision.Decisions> = Omit<DecideResponse<D>, \"answers\"> & {\n readonly answers: JevAnswers<D>\n}\n\n/** Narrows `model` to Jev's roster. */\nexport type JevDecideRequest<A> = Omit<CommonDecideRequest<A>, \"model\"> & {\n readonly model: JevModel\n}\n\nexport type JevService = {\n readonly decide: <A, D extends Decision.Decisions>(\n definition: Decision.Definition<A, D>,\n request: JevDecideRequest<A>,\n ) => Effect.Effect<JevDecideResponse<D>, AiError.AiError>\n}\n\n/**\n * Provider-typed service tag. Yield this for Jev's own `confidence`; yield the\n * generic `DecisionModel` tag for provider-portable code. Both are registered\n * by {@link layer}.\n */\nexport class Jev extends Context.Service<Jev, JevService>()(\n \"@betalyra/effect-uai/providers/typesafe-ai/Jev\",\n) {}\n\nexport type Config = {\n readonly apiKey: Redacted.Redacted\n readonly baseUrl?: string\n}\n\n// ---------------------------------------------------------------------------\n// Codec - request body\n// ---------------------------------------------------------------------------\n\ntype WireQuestion =\n | { readonly type: \"choice\"; readonly instructions: string; readonly criteria: Decision.Labels }\n | {\n readonly type: \"score\"\n readonly instructions: string\n readonly criteria: ReadonlyArray<string>\n }\n | {\n readonly type: \"noul\"\n readonly instructions: string\n readonly criteria?: Decision.Boundary\n }\n\nconst questionToWire: (decision: Decision.Decision) => WireQuestion =\n Match.type<Decision.Decision>().pipe(\n Match.discriminatorsExhaustive(\"_tag\")({\n Classify: (decision) => ({\n type: \"choice\" as const,\n instructions: decision.instructions,\n criteria: decision.criteria,\n }),\n Rate: (decision) => ({\n type: \"score\" as const,\n instructions: decision.instructions,\n criteria: decision.criteria,\n }),\n Probability: (decision) => ({\n type: \"noul\" as const,\n instructions: decision.instructions,\n ...(decision.criteria !== undefined && { criteria: decision.criteria }),\n }),\n }),\n )\n\ntype WireBody = {\n readonly model: string\n readonly state: unknown\n readonly questions: Readonly<Record<string, WireQuestion>>\n}\n\n// ---------------------------------------------------------------------------\n// Codec - response\n// ---------------------------------------------------------------------------\n\nconst WireChoiceAnswer = Schema.Struct({\n type: Schema.Literal(\"choice\"),\n choice: Schema.String,\n confidence: Schema.Number,\n probabilities: Schema.Record(Schema.String, Schema.Number),\n})\n\nconst WireScoreAnswer = Schema.Struct({\n type: Schema.Literal(\"score\"),\n score: Schema.Number,\n confidence: Schema.Number,\n legend: Schema.Record(Schema.String, Schema.String),\n probabilities: Schema.Record(Schema.String, Schema.Number),\n})\n\nconst WireNoulAnswer = Schema.Struct({\n type: Schema.Literal(\"noul\"),\n noul: Schema.Number,\n})\n\nconst WireUsage = Schema.Struct({\n input_tokens: Schema.optional(Schema.Number),\n output_tokens: Schema.optional(Schema.Number),\n})\n\nconst WireResponse = Schema.Struct({\n model: Schema.optional(Schema.String),\n answers: Schema.Record(Schema.String, Schema.Unknown),\n usage: Schema.optional(WireUsage),\n})\ntype WireResponse = typeof WireResponse.Type\n\nconst decodeChoice = Schema.decodeUnknownEffect(WireChoiceAnswer)\nconst decodeScore = Schema.decodeUnknownEffect(WireScoreAnswer)\nconst decodeNoul = Schema.decodeUnknownEffect(WireNoulAnswer)\n\nconst wrongShape = (name: string, cause: unknown): AiError.AiError =>\n new AiError.GenerationFailed({\n provider: \"typesafe-ai\",\n message: `answer \"${name}\" did not match the kind its decision asked for`,\n raw: cause,\n })\n\nconst missing = (name: string): AiError.AiError =>\n new AiError.GenerationFailed({\n provider: \"typesafe-ai\",\n message: `no answer for decision \"${name}\"`,\n raw: undefined,\n })\n\n/**\n * `probabilities` arrives keyed by level index as a string. Read it back\n * positionally against the rubric we sent, so a missing or extra index is a\n * decode failure rather than a hole in the tuple.\n */\nconst levelsOf = (\n name: string,\n criteria: ReadonlyArray<string>,\n probabilities: Readonly<Record<string, number>>,\n): Effect.Effect<ReadonlyArray<number>, AiError.AiError> =>\n Effect.forEach(criteria, (_, index) => {\n const probability = probabilities[String(index)]\n return probability === undefined\n ? Effect.fail(wrongShape(name, `missing level ${index}`))\n : Effect.succeed(probability)\n })\n\nconst answerFor = (\n name: string,\n decision: Decision.Decision,\n raw: unknown,\n): Effect.Effect<Decision.Answer, AiError.AiError> =>\n Match.value(decision).pipe(\n Match.discriminatorsExhaustive(\"_tag\")({\n Classify: () =>\n decodeChoice(raw).pipe(\n Effect.mapError((cause) => wrongShape(name, cause)),\n Effect.map((wire) => ({ _tag: \"Classify\" as const, labels: wire.probabilities })),\n ),\n Rate: (rate) =>\n decodeScore(raw).pipe(\n Effect.mapError((cause) => wrongShape(name, cause)),\n Effect.flatMap((wire) =>\n Effect.map(levelsOf(name, rate.criteria, wire.probabilities), (levels) => ({\n _tag: \"Rate\" as const,\n levels,\n legend: rate.criteria,\n })),\n ),\n ),\n Probability: () =>\n decodeNoul(raw).pipe(\n Effect.mapError((cause) => wrongShape(name, cause)),\n Effect.map((wire) => ({ _tag: \"Probability\" as const, probability: wire.noul })),\n ),\n }),\n ) as Effect.Effect<Decision.Answer, AiError.AiError>\n\n/**\n * The cast is the generic boundary: a record assembled at runtime cannot\n * prove it inhabits the caller's `JevAnswers<D>`. Each entry is decoded\n * against the kind its own decision asked for, so the shape is checked even\n * though the mapping is not.\n */\nconst answersOf = <D extends Decision.Decisions>(\n decisions: D,\n wire: WireResponse,\n): Effect.Effect<JevAnswers<D>, AiError.AiError> =>\n pipe(\n Record.toEntries(decisions),\n Effect.forEach(([name, decision]) => {\n const raw = wire.answers[name]\n return raw === undefined\n ? Effect.fail(missing(name))\n : Effect.map(answerFor(name, decision, raw), (answer) => [name, answer] as const)\n }),\n Effect.map((entries) => Object.fromEntries(entries) as JevAnswers<D>),\n )\n\n// ---------------------------------------------------------------------------\n// HTTP\n// ---------------------------------------------------------------------------\n\nconst transportFailure = (cause: unknown): AiError.AiError =>\n new AiError.Unavailable({ provider: \"typesafe-ai\", raw: cause })\n\nconst httpStatusError = (status: number, body: string): AiError.AiError => {\n const provider = \"typesafe-ai\"\n const raw = body\n if (status === 429) return new AiError.RateLimited({ provider, raw })\n if (status === 408 || status === 504) return new AiError.Timeout({ provider, raw })\n if (status === 401) return new AiError.AuthFailed({ provider, subtype: \"auth\", raw })\n if (status === 403) return new AiError.AuthFailed({ provider, subtype: \"permission\", raw })\n if (status === 402) return new AiError.AuthFailed({ provider, subtype: \"billing\", raw })\n if (status === 413) return new AiError.ContextLengthExceeded({ provider, raw })\n if (status >= 500) return new AiError.Unavailable({ provider, status, raw })\n return new AiError.InvalidRequest({ provider, raw })\n}\n\nconst baseUrl = (config: Config): string => config.baseUrl ?? \"https://api.typesafe.ai\"\n\nconst postSystemOne = (\n config: Config,\n body: WireBody,\n): Effect.Effect<WireResponse, AiError.AiError, HttpClient.HttpClient> =>\n Effect.gen(function* () {\n const client = yield* HttpClient.HttpClient\n const httpRequest = HttpClientRequest.post(`${baseUrl(config)}/v1/systemone`).pipe(\n HttpClientRequest.bearerToken(config.apiKey),\n HttpClientRequest.bodyJsonUnsafe(body),\n )\n const response = yield* client.execute(httpRequest).pipe(Effect.mapError(transportFailure))\n if (response.status >= 400) {\n const text = yield* response.text.pipe(Effect.orElseSucceed(() => \"\"))\n return yield* httpStatusError(response.status, text)\n }\n const json = yield* response.json.pipe(Effect.mapError(transportFailure))\n return yield* Schema.decodeUnknownEffect(WireResponse)(json).pipe(\n Effect.mapError(transportFailure),\n )\n })\n\nconst decideImpl =\n (config: Config) =>\n <A, D extends Decision.Decisions>(\n definition: Decision.Definition<A, D>,\n request: JevDecideRequest<A>,\n ): Effect.Effect<JevDecideResponse<D>, AiError.AiError, HttpClient.HttpClient> =>\n Effect.gen(function* () {\n if (Record.isEmptyRecord(definition.decisions)) {\n return yield* Effect.fail(\n new AiError.InvalidRequest({\n provider: \"typesafe-ai\",\n param: \"decisions\",\n raw: \"a definition must carry at least one decision\",\n }),\n )\n }\n // A schema that rejects the input is the caller's bug, not a wire fault.\n const state = yield* Schema.encodeEffect(definition.inputSchema)(request.input).pipe(\n Effect.mapError(\n (cause) =>\n new AiError.InvalidRequest({ provider: \"typesafe-ai\", param: \"input\", raw: cause }),\n ),\n )\n const wire = yield* postSystemOne(config, {\n model: request.model,\n state,\n questions: Record.map(definition.decisions, questionToWire),\n })\n const answers = yield* answersOf(definition.decisions, wire)\n return {\n answers,\n usage: {\n ...(wire.usage?.input_tokens !== undefined && { inputTokens: wire.usage.input_tokens }),\n ...(wire.usage?.output_tokens !== undefined && {\n outputTokens: wire.usage.output_tokens,\n }),\n },\n }\n })\n\n// ---------------------------------------------------------------------------\n// Constructors\n// ---------------------------------------------------------------------------\n\n/** Build a `JevService` value. For Layer-based setup, prefer {@link layer}. */\nexport const make = (config: Config): Effect.Effect<JevService, never, HttpClient.HttpClient> =>\n Effect.map(HttpClient.HttpClient, (client) => ({\n decide: (definition, request) =>\n decideImpl(config)(definition, request).pipe(\n Effect.provideService(HttpClient.HttpClient, client),\n ),\n }))\n\n/**\n * Layer registering both the provider-typed `Jev` tag and the generic\n * `DecisionModel` tag over one implementation. `JevAnswers<D>` includes\n * `Answers<D>`, so the generic registration forwards directly.\n */\nexport const layer = (\n config: Config,\n): Layer.Layer<Jev | DecisionModel, never, HttpClient.HttpClient> => {\n const typed = Layer.effect(Jev, make(config))\n const generic = Layer.effect(\n DecisionModel,\n Effect.map(make(config), (service): DecisionModelService => ({\n decide: (definition, request) => service.decide(definition, request),\n })),\n )\n return Layer.merge(typed, generic)\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"Jev.mjs","names":[],"sources":["../src/Jev.ts"],"sourcesContent":["import { Context, Effect, Layer, Match, type Redacted, Record, Schema, pipe } from \"effect\"\nimport { HttpClient, HttpClientRequest } from \"effect/http\"\nimport * as AiError from \"@effect-uai/core/AiError\"\nimport * as Decision from \"@effect-uai/core/Decision\"\nimport {\n type CommonDecideRequest,\n type DecideResponse,\n DecisionModel,\n type DecisionModelService,\n} from \"@effect-uai/core/DecisionModel\"\nimport type { JevModel } from \"./models.js\"\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\n/**\n * Jev reports its own `confidence` alongside the distribution, on Classify\n * and Rate but not on Probability. The formula is undocumented, so it is not\n * on the Common answer; `Decision.confidence` is ours and is defined for\n * every kind.\n */\nexport type JevAnswerFor<D> = Decision.AnswerFor<D> & ReportedConfidence<D>\n\n/**\n * Intersected rather than branched per kind, so `JevAnswers` stays provably\n * assignable to `Answers`: TypeScript cannot see one deferred conditional as\n * a subtype of another, but an intersection is always assignable to its\n * members.\n */\ntype ReportedConfidence<D> = D extends { readonly _tag: \"Probability\" }\n ? unknown\n : { readonly confidence: number }\n\nexport type JevAnswers<D extends Decision.Decisions> = {\n readonly [K in keyof D]: JevAnswerFor<D[K]>\n}\n\nexport type JevDecideResponse<D extends Decision.Decisions> = Omit<DecideResponse<D>, \"answers\"> & {\n readonly answers: JevAnswers<D>\n}\n\n/** Narrows `model` to Jev's roster. */\nexport type JevDecideRequest<A> = Omit<CommonDecideRequest<A>, \"model\"> & {\n readonly model: JevModel\n}\n\nexport type JevService = {\n readonly decide: <A, D extends Decision.Decisions>(\n definition: Decision.Definition<A, D>,\n request: JevDecideRequest<A>,\n ) => Effect.Effect<JevDecideResponse<D>, AiError.AiError>\n}\n\n/**\n * Provider-typed service tag. Yield this for Jev's own `confidence`; yield the\n * generic `DecisionModel` tag for provider-portable code. Both are registered\n * by {@link layer}.\n */\nexport class Jev extends Context.Service<Jev, JevService>()(\n \"@betalyra/effect-uai/providers/typesafe-ai/Jev\",\n) {}\n\nexport type Config = {\n readonly apiKey: Redacted.Redacted\n readonly baseUrl?: string\n}\n\n// ---------------------------------------------------------------------------\n// Codec - request body\n// ---------------------------------------------------------------------------\n\ntype WireQuestion =\n | { readonly type: \"choice\"; readonly instructions: string; readonly criteria: Decision.Labels }\n | {\n readonly type: \"score\"\n readonly instructions: string\n readonly criteria: ReadonlyArray<string>\n }\n | {\n readonly type: \"noul\"\n readonly instructions: string\n readonly criteria?: Decision.Boundary\n }\n\nconst questionToWire: (decision: Decision.Decision) => WireQuestion =\n Match.type<Decision.Decision>().pipe(\n Match.discriminatorsExhaustive(\"_tag\")({\n Classify: (decision) => ({\n type: \"choice\" as const,\n instructions: decision.instructions,\n criteria: decision.criteria,\n }),\n Rate: (decision) => ({\n type: \"score\" as const,\n instructions: decision.instructions,\n criteria: decision.criteria,\n }),\n Probability: (decision) => ({\n type: \"noul\" as const,\n instructions: decision.instructions,\n ...(decision.criteria !== undefined && { criteria: decision.criteria }),\n }),\n }),\n )\n\ntype WireBody = {\n readonly model: string\n readonly state: unknown\n readonly questions: Readonly<Record<string, WireQuestion>>\n}\n\n// ---------------------------------------------------------------------------\n// Codec - response\n// ---------------------------------------------------------------------------\n\nconst WireChoiceAnswer = Schema.Struct({\n type: Schema.Literal(\"choice\"),\n choice: Schema.String,\n confidence: Schema.Number,\n probabilities: Schema.Record(Schema.String, Schema.Number),\n})\n\nconst WireScoreAnswer = Schema.Struct({\n type: Schema.Literal(\"score\"),\n score: Schema.Number,\n confidence: Schema.Number,\n legend: Schema.Record(Schema.String, Schema.String),\n probabilities: Schema.Record(Schema.String, Schema.Number),\n})\n\nconst WireNoulAnswer = Schema.Struct({\n type: Schema.Literal(\"noul\"),\n noul: Schema.Number,\n})\n\nconst WireUsage = Schema.Struct({\n input_tokens: Schema.optional(Schema.Number),\n output_tokens: Schema.optional(Schema.Number),\n})\n\nconst WireResponse = Schema.Struct({\n model: Schema.optional(Schema.String),\n answers: Schema.Record(Schema.String, Schema.Unknown),\n usage: Schema.optional(WireUsage),\n})\ntype WireResponse = typeof WireResponse.Type\n\nconst decodeChoice = Schema.decodeUnknownEffect(WireChoiceAnswer)\nconst decodeScore = Schema.decodeUnknownEffect(WireScoreAnswer)\nconst decodeNoul = Schema.decodeUnknownEffect(WireNoulAnswer)\n\nconst wrongShape = (name: string, cause: unknown): AiError.AiError =>\n new AiError.GenerationFailed({\n provider: \"typesafe-ai\",\n message: `answer \"${name}\" did not match the kind its decision asked for`,\n raw: cause,\n })\n\nconst missing = (name: string): AiError.AiError =>\n new AiError.GenerationFailed({\n provider: \"typesafe-ai\",\n message: `no answer for decision \"${name}\"`,\n raw: undefined,\n })\n\n/**\n * `probabilities` arrives keyed by level index as a string. Read it back\n * positionally against the rubric we sent, so a missing or extra index is a\n * decode failure rather than a hole in the tuple.\n */\nconst levelsOf = (\n name: string,\n criteria: ReadonlyArray<string>,\n probabilities: Readonly<Record<string, number>>,\n): Effect.Effect<ReadonlyArray<number>, AiError.AiError> =>\n Effect.forEach(criteria, (_, index) => {\n const probability = probabilities[String(index)]\n return probability === undefined\n ? Effect.fail(wrongShape(name, `missing level ${index}`))\n : Effect.succeed(probability)\n })\n\nconst answerFor = (\n name: string,\n decision: Decision.Decision,\n raw: unknown,\n): Effect.Effect<Decision.Answer, AiError.AiError> =>\n Match.value(decision).pipe(\n Match.discriminatorsExhaustive(\"_tag\")({\n Classify: () =>\n decodeChoice(raw).pipe(\n Effect.mapError((cause) => wrongShape(name, cause)),\n Effect.map((wire) => ({ _tag: \"Classify\" as const, labels: wire.probabilities })),\n ),\n Rate: (rate) =>\n decodeScore(raw).pipe(\n Effect.mapError((cause) => wrongShape(name, cause)),\n Effect.flatMap((wire) =>\n Effect.map(levelsOf(name, rate.criteria, wire.probabilities), (levels) => ({\n _tag: \"Rate\" as const,\n levels,\n legend: rate.criteria,\n })),\n ),\n ),\n Probability: () =>\n decodeNoul(raw).pipe(\n Effect.mapError((cause) => wrongShape(name, cause)),\n Effect.map((wire) => ({ _tag: \"Probability\" as const, probability: wire.noul })),\n ),\n }),\n ) as Effect.Effect<Decision.Answer, AiError.AiError>\n\n/**\n * The cast is the generic boundary: a record assembled at runtime cannot\n * prove it inhabits the caller's `JevAnswers<D>`. Each entry is decoded\n * against the kind its own decision asked for, so the shape is checked even\n * though the mapping is not.\n */\nconst answersOf = <D extends Decision.Decisions>(\n decisions: D,\n wire: WireResponse,\n): Effect.Effect<JevAnswers<D>, AiError.AiError> =>\n pipe(\n Record.toEntries(decisions),\n Effect.forEach(([name, decision]) => {\n const raw = wire.answers[name]\n return raw === undefined\n ? Effect.fail(missing(name))\n : Effect.map(answerFor(name, decision, raw), (answer) => [name, answer] as const)\n }),\n Effect.map((entries) => Object.fromEntries(entries) as JevAnswers<D>),\n )\n\n// ---------------------------------------------------------------------------\n// HTTP\n// ---------------------------------------------------------------------------\n\nconst transportFailure = (cause: unknown): AiError.AiError =>\n new AiError.Unavailable({ provider: \"typesafe-ai\", raw: cause })\n\nconst httpStatusError = (status: number, body: string): AiError.AiError => {\n const provider = \"typesafe-ai\"\n const raw = body\n if (status === 429) return new AiError.RateLimited({ provider, raw })\n if (status === 408 || status === 504) return new AiError.Timeout({ provider, raw })\n if (status === 401) return new AiError.AuthFailed({ provider, subtype: \"auth\", raw })\n if (status === 403) return new AiError.AuthFailed({ provider, subtype: \"permission\", raw })\n if (status === 402) return new AiError.AuthFailed({ provider, subtype: \"billing\", raw })\n if (status === 413) return new AiError.ContextLengthExceeded({ provider, raw })\n if (status >= 500) return new AiError.Unavailable({ provider, status, raw })\n return new AiError.InvalidRequest({ provider, raw })\n}\n\nconst baseUrl = (config: Config): string => config.baseUrl ?? \"https://api.typesafe.ai\"\n\nconst postSystemOne = (\n config: Config,\n body: WireBody,\n): Effect.Effect<WireResponse, AiError.AiError, HttpClient.HttpClient> =>\n Effect.gen(function* () {\n const client = yield* HttpClient.HttpClient\n const httpRequest = HttpClientRequest.post(`${baseUrl(config)}/v1/systemone`).pipe(\n HttpClientRequest.bearerToken(config.apiKey),\n HttpClientRequest.bodyJsonUnsafe(body),\n )\n const response = yield* client.execute(httpRequest).pipe(Effect.mapError(transportFailure))\n if (response.status >= 400) {\n const text = yield* response.text.pipe(Effect.orElseSucceed(() => \"\"))\n return yield* httpStatusError(response.status, text)\n }\n const json = yield* response.json.pipe(Effect.mapError(transportFailure))\n return yield* Schema.decodeUnknownEffect(WireResponse)(json).pipe(\n Effect.mapError(transportFailure),\n )\n })\n\nconst decideImpl =\n (config: Config) =>\n <A, D extends Decision.Decisions>(\n definition: Decision.Definition<A, D>,\n request: JevDecideRequest<A>,\n ): Effect.Effect<JevDecideResponse<D>, AiError.AiError, HttpClient.HttpClient> =>\n Effect.gen(function* () {\n if (Record.isEmptyRecord(definition.decisions)) {\n return yield* Effect.fail(\n new AiError.InvalidRequest({\n provider: \"typesafe-ai\",\n param: \"decisions\",\n raw: \"a definition must carry at least one decision\",\n }),\n )\n }\n // A schema that rejects the input is the caller's bug, not a wire fault.\n const state = yield* Schema.encodeEffect(definition.inputSchema)(request.input).pipe(\n Effect.mapError(\n (cause) =>\n new AiError.InvalidRequest({ provider: \"typesafe-ai\", param: \"input\", raw: cause }),\n ),\n )\n const wire = yield* postSystemOne(config, {\n model: request.model,\n state,\n questions: Record.map(definition.decisions, questionToWire),\n })\n const answers = yield* answersOf(definition.decisions, wire)\n return {\n answers,\n usage: {\n ...(wire.usage?.input_tokens !== undefined && { inputTokens: wire.usage.input_tokens }),\n ...(wire.usage?.output_tokens !== undefined && {\n outputTokens: wire.usage.output_tokens,\n }),\n },\n }\n })\n\n// ---------------------------------------------------------------------------\n// Constructors\n// ---------------------------------------------------------------------------\n\n/** Build a `JevService` value. For Layer-based setup, prefer {@link layer}. */\nexport const make = (config: Config): Effect.Effect<JevService, never, HttpClient.HttpClient> =>\n Effect.map(HttpClient.HttpClient, (client) => ({\n decide: (definition, request) =>\n decideImpl(config)(definition, request).pipe(\n Effect.provideService(HttpClient.HttpClient, client),\n ),\n }))\n\n/**\n * Layer registering both the provider-typed `Jev` tag and the generic\n * `DecisionModel` tag over one implementation. `JevAnswers<D>` includes\n * `Answers<D>`, so the generic registration forwards directly.\n */\nexport const layer = (\n config: Config,\n): Layer.Layer<Jev | DecisionModel, never, HttpClient.HttpClient> => {\n const typed = Layer.effect(Jev, make(config))\n const generic = Layer.effect(\n DecisionModel,\n Effect.map(make(config), (service): DecisionModelService => ({\n decide: (definition, request) => service.decide(definition, request),\n })),\n )\n return Layer.merge(typed, generic)\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@effect-uai/typesafe-ai",
3
- "version": "0.17.0",
3
+ "version": "0.18.0",
4
4
  "description": "TypeSafe AI provider for @effect-uai/core (Jev System One decision model).",
5
5
  "keywords": [
6
6
  "ai",
@@ -44,13 +44,13 @@
44
44
  "access": "public"
45
45
  },
46
46
  "devDependencies": {
47
- "effect": "4.0.0-rc.111",
47
+ "effect": "4.0.1",
48
48
  "typescript": "^7.0.2",
49
- "@effect-uai/core": "0.17.0"
49
+ "@effect-uai/core": "0.18.0"
50
50
  },
51
51
  "peerDependencies": {
52
52
  "@effect-uai/core": ">=0.17.0 <1",
53
- "effect": ">=4.0.0-rc.111 <5.0.0"
53
+ "effect": ">=4.0.1 <5.0.0"
54
54
  },
55
55
  "scripts": {
56
56
  "build": "tsdown",
package/src/Jev.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Context, Effect, Layer, Match, type Redacted, Record, Schema, pipe } from "effect"
2
- import { HttpClient, HttpClientRequest } from "effect/unstable/http"
2
+ import { HttpClient, HttpClientRequest } from "effect/http"
3
3
  import * as AiError from "@effect-uai/core/AiError"
4
4
  import * as Decision from "@effect-uai/core/Decision"
5
5
  import {