Przeglądaj źródła

chore: generate

opencode-agent[bot] 4 miesięcy temu
rodzic
commit
ba8c920639

+ 4 - 1
packages/http-recorder/src/cassette.ts

@@ -90,7 +90,10 @@ export const layer = (options: { readonly directory?: string } = {}) =>
         return (yield* walk(directory))
           .filter((file) => file.endsWith(".json"))
           .map((file) => ({
-            name: path.relative(directory, file).replace(/\\/g, "/").replace(/\.json$/, ""),
+            name: path
+              .relative(directory, file)
+              .replace(/\\/g, "/")
+              .replace(/\.json$/, ""),
             path: file,
           }))
           .toSorted((a, b) => a.name.localeCompare(b.name))

+ 5 - 1
packages/http-recorder/src/redaction.ts

@@ -65,7 +65,11 @@ const redactionSet = (values: ReadonlyArray<string> | undefined, defaults: Reado
 
 export type UrlRedactor = (url: string) => string
 
-export const redactUrl = (raw: string, query: ReadonlyArray<string> = DEFAULT_REDACT_QUERY, urlRedactor?: UrlRedactor) => {
+export const redactUrl = (
+  raw: string,
+  query: ReadonlyArray<string> = DEFAULT_REDACT_QUERY,
+  urlRedactor?: UrlRedactor,
+) => {
   if (!URL.canParse(raw)) return urlRedactor?.(raw) ?? raw
   const url = new URL(raw)
   if (url.username) url.username = REDACTED

+ 2 - 4
packages/http-recorder/test/record-replay.test.ts

@@ -64,10 +64,8 @@ describe("http-recorder", () => {
 
   test("applies custom URL redaction after built-in redaction", () => {
     expect(
-      HttpRecorder.redactUrl(
-        "https://example.test/accounts/real-account/path?key=secret-key",
-        undefined,
-        (url) => url.replace("/accounts/real-account/", "/accounts/{account}/"),
+      HttpRecorder.redactUrl("https://example.test/accounts/real-account/path?key=secret-key", undefined, (url) =>
+        url.replace("/accounts/real-account/", "/accounts/{account}/"),
       ),
     ).toBe("https://example.test/accounts/{account}/path?key=%5BREDACTED%5D")
   })

+ 1 - 1
packages/llm/AGENTS.md

@@ -28,7 +28,7 @@ const request = LLM.request({
   prompt: "Say hello.",
 })
 
-const response = yield* LLMClient.generate(request)
+const response = yield * LLMClient.generate(request)
 ```
 
 `LLM.request(...)` builds an `LLMRequest`. `LLMClient.generate(...)` selects a registered route by `request.model.route`, builds the provider-native body, asks the route's transport for a real `HttpClientRequest.HttpClientRequest`, sends it through `RequestExecutor.Service`, parses the provider stream into common `LLMEvent`s, and finally returns an `LLMResponse`.

+ 6 - 1
packages/llm/script/setup-recording-env.ts

@@ -110,7 +110,12 @@ const PROVIDERS: ReadonlyArray<Provider> = [
     note: "Cloudflare Unified/OpenAI-compatible gateway; supports provider/model ids like workers-ai/@cf/...",
     vars: [
       { name: "CLOUDFLARE_ACCOUNT_ID", label: "Cloudflare account ID", secret: false },
-      { name: "CLOUDFLARE_GATEWAY_ID", label: "Cloudflare AI Gateway ID (defaults to default)", optional: true, secret: false },
+      {
+        name: "CLOUDFLARE_GATEWAY_ID",
+        label: "Cloudflare AI Gateway ID (defaults to default)",
+        optional: true,
+        secret: false,
+      },
       { name: "CLOUDFLARE_API_TOKEN", label: "Cloudflare AI Gateway token" },
     ],
     validate: (env) =>

+ 4 - 9
packages/llm/src/llm.ts

@@ -1,10 +1,5 @@
 import { Effect, JsonSchema, Schema } from "effect"
-import {
-  LLMClient,
-  modelLimits,
-  modelRef,
-  type ModelRefInput,
-} from "./route/client"
+import { LLMClient, modelLimits, modelRef, type ModelRefInput } from "./route/client"
 import {
   GenerationOptions,
   HttpOptions,
@@ -196,10 +191,10 @@ const runGenerateObject = Effect.fn("LLM.generateObject")(function* (
 export function generateObject<S extends ToolSchema<any>>(
   options: GenerateObjectOptions<S>,
 ): Effect.Effect<GenerateObjectResponse<Schema.Schema.Type<S>>, LLMError>
-export function generateObject(options: GenerateObjectDynamicOptions): Effect.Effect<GenerateObjectResponse<unknown>, LLMError>
 export function generateObject(
-  options: GenerateObjectOptions<ToolSchema<any>> | GenerateObjectDynamicOptions,
-) {
+  options: GenerateObjectDynamicOptions,
+): Effect.Effect<GenerateObjectResponse<unknown>, LLMError>
+export function generateObject(options: GenerateObjectOptions<ToolSchema<any>> | GenerateObjectDynamicOptions) {
   if ("schema" in options) {
     const { schema, ...rest } = options
     return runGenerateObject(

+ 4 - 2
packages/llm/src/providers/anthropic.ts

@@ -7,8 +7,10 @@ export const id = ProviderID.make("anthropic")
 
 export const routes = [AnthropicMessages.route]
 
-export const model = (id: string | ModelID, options: Omit<RouteModelInput, "id" | "baseURL"> & { readonly baseURL?: string } = {}) =>
-  AnthropicMessages.model({ ...options, id })
+export const model = (
+  id: string | ModelID,
+  options: Omit<RouteModelInput, "id" | "baseURL"> & { readonly baseURL?: string } = {},
+) => AnthropicMessages.model({ ...options, id })
 
 export const provider = Provider.make({
   id,

+ 4 - 2
packages/llm/src/providers/google.ts

@@ -7,8 +7,10 @@ export const id = ProviderID.make("google")
 
 export const routes = [Gemini.route]
 
-export const model = (id: string | ModelID, options: Omit<RouteModelInput, "id" | "baseURL"> & { readonly baseURL?: string } = {}) =>
-  Gemini.model({ ...options, id })
+export const model = (
+  id: string | ModelID,
+  options: Omit<RouteModelInput, "id" | "baseURL"> & { readonly baseURL?: string } = {},
+) => Gemini.model({ ...options, id })
 
 export const provider = Provider.make({
   id,

+ 3 - 2
packages/llm/src/route/auth.ts

@@ -168,8 +168,9 @@ export function bearerHeader(
   name: string,
   source?: string | Redacted.Redacted<string> | Config.Config<string | Redacted.Redacted<string>> | Credential,
 ) {
-  const render = (input: string | Redacted.Redacted<string> | Config.Config<string | Redacted.Redacted<string>> | Credential) =>
-    fromCredential(credentialInput(input), (secret) => ({ [name]: `Bearer ${secret}` }))
+  const render = (
+    input: string | Redacted.Redacted<string> | Config.Config<string | Redacted.Redacted<string>> | Credential,
+  ) => fromCredential(credentialInput(input), (secret) => ({ [name]: `Bearer ${secret}` }))
   if (source === undefined) return render
   return render(source)
 }

+ 1 - 3
packages/llm/src/route/client.ts

@@ -142,9 +142,7 @@ const modelWithDefaults =
     if (!provider) throw new Error(`Route.model(${route.id}) requires a provider`)
     const baseURL = mapped.baseURL ?? defaults.baseURL ?? route.defaults.baseURL
     if (!baseURL)
-      throw new Error(
-        `Route.model(${route.id}) requires a baseURL — supply it via input, defaults, or route defaults`,
-      )
+      throw new Error(`Route.model(${route.id}) requires a baseURL — supply it via input, defaults, or route defaults`)
     const generation = mergeGenerationOptions(route.defaults.generation, defaults.generation)
     const providerOptions = mergeProviderOptions(route.defaults.providerOptions, defaults.providerOptions)
     const http = mergeHttpOptions(httpOptions(route.defaults.http), httpOptions(defaults.http))

+ 1 - 3
packages/llm/src/route/endpoint.ts

@@ -30,9 +30,7 @@ const renderPart = <Body>(part: EndpointPart<Body>, input: EndpointInput<Body>)
   typeof part === "function" ? part(input) : part
 
 export const render = <Body>(endpoint: Endpoint<Body>, input: EndpointInput<Body>) => {
-  const url = new URL(
-    `${ProviderShared.trimBaseUrl(input.request.model.baseURL)}${renderPart(endpoint.path, input)}`,
-  )
+  const url = new URL(`${ProviderShared.trimBaseUrl(input.request.model.baseURL)}${renderPart(endpoint.path, input)}`)
   const params = input.request.model.queryParams
   if (params) for (const [key, value] of Object.entries(params)) url.searchParams.set(key, value)
   return url

+ 4 - 7
packages/llm/test/endpoint.test.ts

@@ -2,12 +2,7 @@ import { describe, expect, test } from "bun:test"
 import { LLM } from "../src"
 import { Endpoint } from "../src/route"
 
-const request = (
-  input: {
-    readonly baseURL: string
-    readonly queryParams?: Record<string, string>
-  },
-) =>
+const request = (input: { readonly baseURL: string; readonly queryParams?: Record<string, string> }) =>
   LLM.request({
     model: LLM.model({
       id: "model-1",
@@ -43,7 +38,9 @@ describe("Endpoint", () => {
 
   test("path may be a function of the validated body", () => {
     const url = Endpoint.render(
-      Endpoint.path<{ readonly modelId: string }>(({ body }) => `/model/${encodeURIComponent(body.modelId)}/converse-stream`),
+      Endpoint.path<{ readonly modelId: string }>(
+        ({ body }) => `/model/${encodeURIComponent(body.modelId)}/converse-stream`,
+      ),
       {
         request: request({ baseURL: "https://bedrock-runtime.us-east-1.amazonaws.com" }),
         body: { modelId: "us.amazon.nova-micro-v1:0" },

+ 1 - 7
packages/llm/test/fixtures/recordings/cloudflare-ai-gateway/cloudflare-ai-gateway-workers-ai-gpt-oss-20b-tools-tool-call.json

@@ -7,13 +7,7 @@
     "route": "cloudflare-ai-gateway",
     "transport": "http",
     "model": "workers-ai/@cf/openai/gpt-oss-20b",
-    "tags": [
-      "prefix:cloudflare-ai-gateway",
-      "provider:cloudflare-ai-gateway",
-      "tool",
-      "tool-call",
-      "golden"
-    ]
+    "tags": ["prefix:cloudflare-ai-gateway", "provider:cloudflare-ai-gateway", "tool", "tool-call", "golden"]
   },
   "interactions": [
     {

+ 1 - 6
packages/llm/test/fixtures/recordings/cloudflare-ai-gateway/cloudflare-ai-gateway-workers-ai-llama-3-1-8b-text.json

@@ -7,12 +7,7 @@
     "route": "cloudflare-ai-gateway",
     "transport": "http",
     "model": "workers-ai/@cf/meta/llama-3.1-8b-instruct",
-    "tags": [
-      "prefix:cloudflare-ai-gateway",
-      "provider:cloudflare-ai-gateway",
-      "text",
-      "golden"
-    ]
+    "tags": ["prefix:cloudflare-ai-gateway", "provider:cloudflare-ai-gateway", "text", "golden"]
   },
   "interactions": [
     {

+ 1 - 7
packages/llm/test/fixtures/recordings/cloudflare-workers-ai/cloudflare-workers-ai-gpt-oss-20b-tools-tool-call.json

@@ -7,13 +7,7 @@
     "route": "cloudflare-workers-ai",
     "transport": "http",
     "model": "@cf/openai/gpt-oss-20b",
-    "tags": [
-      "prefix:cloudflare-workers-ai",
-      "provider:cloudflare-workers-ai",
-      "tool",
-      "tool-call",
-      "golden"
-    ]
+    "tags": ["prefix:cloudflare-workers-ai", "provider:cloudflare-workers-ai", "tool", "tool-call", "golden"]
   },
   "interactions": [
     {

+ 1 - 6
packages/llm/test/fixtures/recordings/cloudflare-workers-ai/cloudflare-workers-ai-llama-3-1-8b-text.json

@@ -7,12 +7,7 @@
     "route": "cloudflare-workers-ai",
     "transport": "http",
     "model": "@cf/meta/llama-3.1-8b-instruct",
-    "tags": [
-      "prefix:cloudflare-workers-ai",
-      "provider:cloudflare-workers-ai",
-      "text",
-      "golden"
-    ]
+    "tags": ["prefix:cloudflare-workers-ai", "provider:cloudflare-workers-ai", "text", "golden"]
   },
   "interactions": [
     {

+ 4 - 1
packages/llm/test/generate-object.test.ts

@@ -164,7 +164,10 @@ describe("LLM.generateObject", () => {
       const layer = dynamicResponse((input) =>
         Effect.sync(() =>
           input.respond(
-            sseEvents(toolCallChunk("call_1", "generate_object", '{"value":"not-a-number"}'), finishChunk("tool_calls")),
+            sseEvents(
+              toolCallChunk("call_1", "generate_object", '{"value":"not-a-number"}'),
+              finishChunk("tool_calls"),
+            ),
             { headers: { "content-type": "text/event-stream" } },
           ),
         ),

+ 1 - 3
packages/llm/test/provider/cloudflare.test.ts

@@ -181,9 +181,7 @@ describe("Cloudflare", () => {
           dynamicResponse((input) =>
             Effect.gen(function* () {
               const web = yield* HttpClientRequest.toWeb(input.request).pipe(Effect.orDie)
-              expect(web.url).toBe(
-                "https://api.cloudflare.com/client/v4/accounts/test-account/ai/v1/chat/completions",
-              )
+              expect(web.url).toBe("https://api.cloudflare.com/client/v4/accounts/test-account/ai/v1/chat/completions")
               expect(web.headers.get("authorization")).toBe("Bearer test-token")
               expect(decodeJson(input.text)).toMatchObject({
                 model: "@cf/meta/llama-3.1-8b-instruct",

+ 1 - 9
packages/llm/test/schema.test.ts

@@ -1,14 +1,6 @@
 import { describe, expect, test } from "bun:test"
 import { Schema } from "effect"
-import {
-  ContentPart,
-  LLMEvent,
-  LLMRequest,
-  ModelID,
-  ModelLimits,
-  ModelRef,
-  ProviderID,
-} from "../src/schema"
+import { ContentPart, LLMEvent, LLMRequest, ModelID, ModelLimits, ModelRef, ProviderID } from "../src/schema"
 
 const model = new ModelRef({
   id: ModelID.make("fake-model"),