opencode 6 месяцев назад
Родитель
Сommit
e618cbc447

+ 9 - 9
bun.lock

@@ -26,7 +26,7 @@
     },
     "cloud/core": {
       "name": "@opencode/cloud-core",
-      "version": "0.9.7",
+      "version": "0.9.8",
       "dependencies": {
         "@aws-sdk/client-sts": "3.782.0",
         "@opencode/cloud-resource": "workspace:*",
@@ -43,7 +43,7 @@
     },
     "cloud/function": {
       "name": "@opencode/cloud-function",
-      "version": "0.9.7",
+      "version": "0.9.8",
       "dependencies": {
         "@ai-sdk/anthropic": "2.0.0",
         "@ai-sdk/openai": "2.0.2",
@@ -69,7 +69,7 @@
     },
     "cloud/scripts": {
       "name": "@opencode/cloud-scripts",
-      "version": "0.9.7",
+      "version": "0.9.8",
       "dependencies": {
         "@opencode/cloud-core": "workspace:*",
         "tsx": "4.20.5",
@@ -81,7 +81,7 @@
     },
     "packages/app": {
       "name": "@opencode/app",
-      "version": "0.9.7",
+      "version": "0.9.8",
       "dependencies": {
         "@kobalte/core": "0.13.11",
         "@opencode-ai/sdk": "workspace:*",
@@ -113,7 +113,7 @@
     },
     "packages/function": {
       "name": "@opencode/function",
-      "version": "0.9.7",
+      "version": "0.9.8",
       "dependencies": {
         "@octokit/auth-app": "8.0.1",
         "@octokit/rest": "22.0.0",
@@ -128,7 +128,7 @@
     },
     "packages/opencode": {
       "name": "opencode",
-      "version": "0.9.7",
+      "version": "0.9.8",
       "bin": {
         "opencode": "./bin/opencode",
       },
@@ -179,7 +179,7 @@
     },
     "packages/plugin": {
       "name": "@opencode-ai/plugin",
-      "version": "0.9.7",
+      "version": "0.9.8",
       "dependencies": {
         "@opencode-ai/sdk": "workspace:*",
       },
@@ -190,7 +190,7 @@
     },
     "packages/sdk/js": {
       "name": "@opencode-ai/sdk",
-      "version": "0.9.7",
+      "version": "0.9.8",
       "dependencies": {
         "@hey-api/openapi-ts": "0.81.0",
       },
@@ -202,7 +202,7 @@
     },
     "packages/web": {
       "name": "@opencode/web",
-      "version": "0.9.7",
+      "version": "0.9.8",
       "dependencies": {
         "@astrojs/cloudflare": "12.6.3",
         "@astrojs/markdown-remark": "6.3.1",

+ 1 - 1
cloud/app/package.json

@@ -7,7 +7,7 @@
     "dev:remote": "VITE_AUTH_URL=https://auth.dev.opencode.ai bun sst shell --stage=dev bun dev",
     "build": "vinxi build && ../../packages/opencode/script/schema.ts ./.output/public/config.json",
     "start": "vinxi start",
-    "version": "0.9.7"
+    "version": "0.9.8"
   },
   "dependencies": {
     "@ibm/plex": "6.4.1",

+ 1 - 1
cloud/core/package.json

@@ -1,7 +1,7 @@
 {
   "$schema": "https://json.schemastore.org/package.json",
   "name": "@opencode/cloud-core",
-  "version": "0.9.7",
+  "version": "0.9.8",
   "private": true,
   "type": "module",
   "dependencies": {

+ 1 - 1
cloud/function/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@opencode/cloud-function",
-  "version": "0.9.7",
+  "version": "0.9.8",
   "$schema": "https://json.schemastore.org/package.json",
   "private": true,
   "type": "module",

+ 1 - 1
cloud/scripts/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@opencode/cloud-scripts",
-  "version": "0.9.7",
+  "version": "0.9.8",
   "$schema": "https://json.schemastore.org/package.json",
   "private": true,
   "type": "module",

+ 1 - 1
packages/app/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@opencode/app",
-  "version": "0.9.7",
+  "version": "0.9.8",
   "description": "",
   "type": "module",
   "scripts": {

+ 1 - 1
packages/function/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@opencode/function",
-  "version": "0.9.7",
+  "version": "0.9.8",
   "$schema": "https://json.schemastore.org/package.json",
   "private": true,
   "type": "module",

+ 1 - 1
packages/opencode/package.json

@@ -1,6 +1,6 @@
 {
   "$schema": "https://json.schemastore.org/package.json",
-  "version": "0.9.7",
+  "version": "0.9.8",
   "name": "opencode",
   "type": "module",
   "private": true,

+ 1 - 1
packages/plugin/package.json

@@ -1,7 +1,7 @@
 {
   "$schema": "https://json.schemastore.org/package.json",
   "name": "@opencode-ai/plugin",
-  "version": "0.9.7",
+  "version": "0.9.8",
   "type": "module",
   "scripts": {
     "typecheck": "tsc --noEmit"

+ 1 - 1
packages/sdk/js/package.json

@@ -1,7 +1,7 @@
 {
   "$schema": "https://json.schemastore.org/package.json",
   "name": "@opencode-ai/sdk",
-  "version": "0.9.7",
+  "version": "0.9.8",
   "type": "module",
   "scripts": {
     "typecheck": "tsc --noEmit"

+ 30 - 68
packages/sdk/js/src/gen/client/client.gen.ts

@@ -1,8 +1,6 @@
 // This file is auto-generated by @hey-api/openapi-ts
 
 import { createSseClient } from "../core/serverSentEvents.gen.js"
-import type { HttpMethod } from "../core/types.gen.js"
-import { getValidRequestBody } from "../core/utils.gen.js"
 import type { Client, Config, RequestOptions, ResolvedRequestOptions } from "./types.gen.js"
 import {
   buildUrl,
@@ -51,12 +49,12 @@ export const createClient = (config: Config = {}): Client => {
       await opts.requestValidator(opts)
     }
 
-    if (opts.body !== undefined && opts.bodySerializer) {
+    if (opts.body && opts.bodySerializer) {
       opts.serializedBody = opts.bodySerializer(opts.body)
     }
 
     // remove Content-Type header if body is empty to avoid sending invalid requests
-    if (opts.body === undefined || opts.serializedBody === "") {
+    if (opts.serializedBody === undefined || opts.serializedBody === "") {
       opts.headers.delete("Content-Type")
     }
 
@@ -71,7 +69,7 @@ export const createClient = (config: Config = {}): Client => {
     const requestInit: ReqInit = {
       redirect: "follow",
       ...opts,
-      body: getValidRequestBody(opts),
+      body: opts.serializedBody,
     }
 
     let request = new Request(url, requestInit)
@@ -99,36 +97,18 @@ export const createClient = (config: Config = {}): Client => {
     }
 
     if (response.ok) {
-      const parseAs =
-        (opts.parseAs === "auto" ? getParseAs(response.headers.get("Content-Type")) : opts.parseAs) ?? "json"
-
       if (response.status === 204 || response.headers.get("Content-Length") === "0") {
-        let emptyData: any
-        switch (parseAs) {
-          case "arrayBuffer":
-          case "blob":
-          case "text":
-            emptyData = await response[parseAs]()
-            break
-          case "formData":
-            emptyData = new FormData()
-            break
-          case "stream":
-            emptyData = response.body
-            break
-          case "json":
-          default:
-            emptyData = {}
-            break
-        }
         return opts.responseStyle === "data"
-          ? emptyData
+          ? {}
           : {
-              data: emptyData,
+              data: {},
               ...result,
             }
       }
 
+      const parseAs =
+        (opts.parseAs === "auto" ? getParseAs(response.headers.get("Content-Type")) : opts.parseAs) ?? "json"
+
       let data: any
       switch (parseAs) {
         case "arrayBuffer":
@@ -198,53 +178,35 @@ export const createClient = (config: Config = {}): Client => {
         }
   }
 
-  const makeMethodFn = (method: Uppercase<HttpMethod>) => (options: RequestOptions) => request({ ...options, method })
-
-  const makeSseFn = (method: Uppercase<HttpMethod>) => async (options: RequestOptions) => {
-    const { opts, url } = await beforeRequest(options)
-    return createSseClient({
-      ...opts,
-      body: opts.body as BodyInit | null | undefined,
-      headers: opts.headers as unknown as Record<string, string>,
-      method,
-      onRequest: async (url, init) => {
-        let request = new Request(url, init)
-        for (const fn of interceptors.request._fns) {
-          if (fn) {
-            request = await fn(request, opts)
-          }
-        }
-        return request
-      },
-      url,
-    })
+  const makeMethod = (method: Required<Config>["method"]) => {
+    const fn = (options: RequestOptions) => request({ ...options, method })
+    fn.sse = async (options: RequestOptions) => {
+      const { opts, url } = await beforeRequest(options)
+      return createSseClient({
+        ...opts,
+        body: opts.body as BodyInit | null | undefined,
+        headers: opts.headers as unknown as Record<string, string>,
+        method,
+        url,
+      })
+    }
+    return fn
   }
 
   return {
     buildUrl,
-    connect: makeMethodFn("CONNECT"),
-    delete: makeMethodFn("DELETE"),
-    get: makeMethodFn("GET"),
+    connect: makeMethod("CONNECT"),
+    delete: makeMethod("DELETE"),
+    get: makeMethod("GET"),
     getConfig,
-    head: makeMethodFn("HEAD"),
+    head: makeMethod("HEAD"),
     interceptors,
-    options: makeMethodFn("OPTIONS"),
-    patch: makeMethodFn("PATCH"),
-    post: makeMethodFn("POST"),
-    put: makeMethodFn("PUT"),
+    options: makeMethod("OPTIONS"),
+    patch: makeMethod("PATCH"),
+    post: makeMethod("POST"),
+    put: makeMethod("PUT"),
     request,
     setConfig,
-    sse: {
-      connect: makeSseFn("CONNECT"),
-      delete: makeSseFn("DELETE"),
-      get: makeSseFn("GET"),
-      head: makeSseFn("HEAD"),
-      options: makeSseFn("OPTIONS"),
-      patch: makeSseFn("PATCH"),
-      post: makeSseFn("POST"),
-      put: makeSseFn("PUT"),
-      trace: makeSseFn("TRACE"),
-    },
-    trace: makeMethodFn("TRACE"),
+    trace: makeMethod("TRACE"),
   } as Client
 }

+ 8 - 4
packages/sdk/js/src/gen/client/types.gen.ts

@@ -20,7 +20,7 @@ export interface Config<T extends ClientOptions = ClientOptions>
    *
    * @default globalThis.fetch
    */
-  fetch?: typeof fetch
+  fetch?: (request: Request) => ReturnType<typeof fetch>
   /**
    * Please don't use the Fetch client for Next.js applications. The `next`
    * options won't have any effect.
@@ -128,7 +128,7 @@ export interface ClientOptions {
   throwOnError?: boolean
 }
 
-type MethodFn = <
+type MethodFnBase = <
   TData = unknown,
   TError = unknown,
   ThrowOnError extends boolean = false,
@@ -137,7 +137,7 @@ type MethodFn = <
   options: Omit<RequestOptions<TData, TResponseStyle, ThrowOnError>, "method">,
 ) => RequestResult<TData, TError, ThrowOnError, TResponseStyle>
 
-type SseFn = <
+type MethodFnServerSentEvents = <
   TData = unknown,
   TError = unknown,
   ThrowOnError extends boolean = false,
@@ -146,6 +146,10 @@ type SseFn = <
   options: Omit<RequestOptions<TData, TResponseStyle, ThrowOnError>, "method">,
 ) => Promise<ServerSentEventsResult<TData, TError>>
 
+type MethodFn = MethodFnBase & {
+  sse: MethodFnServerSentEvents
+}
+
 type RequestFn = <
   TData = unknown,
   TError = unknown,
@@ -167,7 +171,7 @@ type BuildUrlFn = <
   options: Pick<TData, "url"> & Options<TData>,
 ) => string
 
-export type Client = CoreClient<RequestFn, Config, MethodFn, BuildUrlFn, SseFn> & {
+export type Client = CoreClient<RequestFn, Config, MethodFn, BuildUrlFn> & {
   interceptors: Middleware<Request, Response, unknown, ResolvedRequestOptions>
 }
 

+ 2 - 10
packages/sdk/js/src/gen/client/utils.gen.ts

@@ -162,22 +162,14 @@ export const mergeConfigs = (a: Config, b: Config): Config => {
   return config
 }
 
-const headersEntries = (headers: Headers): Array<[string, string]> => {
-  const entries: Array<[string, string]> = []
-  headers.forEach((value, key) => {
-    entries.push([key, value])
-  })
-  return entries
-}
-
 export const mergeHeaders = (...headers: Array<Required<Config>["headers"] | undefined>): Headers => {
   const mergedHeaders = new Headers()
   for (const header of headers) {
-    if (!header) {
+    if (!header || typeof header !== "object") {
       continue
     }
 
-    const iterator = header instanceof Headers ? headersEntries(header) : Object.entries(header)
+    const iterator = header instanceof Headers ? header.entries() : Object.entries(header)
 
     for (const [key, value] of iterator) {
       if (value === null) {

+ 1 - 28
packages/sdk/js/src/gen/core/serverSentEvents.gen.ts

@@ -4,17 +4,6 @@ import type { Config } from "./types.gen.js"
 
 export type ServerSentEventsOptions<TData = unknown> = Omit<RequestInit, "method"> &
   Pick<Config, "method" | "responseTransformer" | "responseValidator"> & {
-    /**
-     * Fetch API implementation. You can use this option to provide a custom
-     * fetch instance.
-     *
-     * @default globalThis.fetch
-     */
-    fetch?: typeof fetch
-    /**
-     * Implementing clients can call request interceptors inside this hook.
-     */
-    onRequest?: (url: string, init: RequestInit) => Promise<Request>
     /**
      * Callback invoked when a network or parsing error occurs during streaming.
      *
@@ -32,7 +21,6 @@ export type ServerSentEventsOptions<TData = unknown> = Omit<RequestInit, "method
      * @returns Nothing (void).
      */
     onSseEvent?: (event: StreamEvent<TData>) => void
-    serializedBody?: RequestInit["body"]
     /**
      * Default retry delay in milliseconds.
      *
@@ -76,7 +64,6 @@ export type ServerSentEventsResult<TData = unknown, TReturn = void, TNext = unkn
 }
 
 export const createSseClient = <TData = unknown>({
-  onRequest,
   onSseError,
   onSseEvent,
   responseTransformer,
@@ -112,21 +99,7 @@ export const createSseClient = <TData = unknown>({
       }
 
       try {
-        const requestInit: RequestInit = {
-          redirect: "follow",
-          ...options,
-          body: options.serializedBody,
-          headers,
-          signal,
-        }
-        let request = new Request(url, requestInit)
-        if (onRequest) {
-          request = await onRequest(url, requestInit)
-        }
-        // fetch must be assigned here, otherwise it would throw the error:
-        // TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation
-        const _fetch = options.fetch ?? globalThis.fetch
-        const response = await _fetch(request)
+        const response = await fetch(url, { ...options, headers, signal })
 
         if (!response.ok) throw new Error(`SSE failed: ${response.status} ${response.statusText}`)
 

+ 12 - 7
packages/sdk/js/src/gen/core/types.gen.ts

@@ -3,19 +3,24 @@
 import type { Auth, AuthToken } from "./auth.gen.js"
 import type { BodySerializer, QuerySerializer, QuerySerializerOptions } from "./bodySerializer.gen.js"
 
-export type HttpMethod = "connect" | "delete" | "get" | "head" | "options" | "patch" | "post" | "put" | "trace"
-
-export type Client<RequestFn = never, Config = unknown, MethodFn = never, BuildUrlFn = never, SseFn = never> = {
+export interface Client<RequestFn = never, Config = unknown, MethodFn = never, BuildUrlFn = never> {
   /**
    * Returns the final request URL.
    */
   buildUrl: BuildUrlFn
+  connect: MethodFn
+  delete: MethodFn
+  get: MethodFn
   getConfig: () => Config
+  head: MethodFn
+  options: MethodFn
+  patch: MethodFn
+  post: MethodFn
+  put: MethodFn
   request: RequestFn
   setConfig: (config: Config) => Config
-} & {
-  [K in HttpMethod]: MethodFn
-} & ([SseFn] extends [never] ? { sse?: never } : { sse: { [K in HttpMethod]: SseFn } })
+  trace: MethodFn
+}
 
 export interface Config {
   /**
@@ -42,7 +47,7 @@ export interface Config {
    *
    * {@link https://developer.mozilla.org/docs/Web/API/fetch#method See more}
    */
-  method?: Uppercase<HttpMethod>
+  method?: "CONNECT" | "DELETE" | "GET" | "HEAD" | "OPTIONS" | "PATCH" | "POST" | "PUT" | "TRACE"
   /**
    * A function for serializing request query parameters. By default, arrays
    * will be exploded in form style, objects will be exploded in deepObject

+ 1 - 29
packages/sdk/js/src/gen/core/utils.gen.ts

@@ -1,6 +1,6 @@
 // This file is auto-generated by @hey-api/openapi-ts
 
-import type { BodySerializer, QuerySerializer } from "./bodySerializer.gen.js"
+import type { QuerySerializer } from "./bodySerializer.gen.js"
 import {
   type ArraySeparatorStyle,
   serializeArrayParam,
@@ -107,31 +107,3 @@ export const getUrl = ({
   }
   return url
 }
-
-export function getValidRequestBody(options: {
-  body?: unknown
-  bodySerializer?: BodySerializer | null
-  serializedBody?: unknown
-}) {
-  const hasBody = options.body !== undefined
-  const isSerializedBody = hasBody && options.bodySerializer
-
-  if (isSerializedBody) {
-    if ("serializedBody" in options) {
-      const hasSerializedBody = options.serializedBody !== undefined && options.serializedBody !== ""
-
-      return hasSerializedBody ? options.serializedBody : null
-    }
-
-    // not all clients implement a serializedBody property (i.e. client-axios)
-    return options.body !== "" ? options.body : null
-  }
-
-  // plain/text body
-  if (hasBody) {
-    return options.body
-  }
-
-  // no body was provided
-  return undefined
-}

+ 1 - 1
packages/sdk/js/src/gen/sdk.gen.ts

@@ -664,7 +664,7 @@ class Event extends _HeyApiClient {
    * Get events
    */
   public subscribe<ThrowOnError extends boolean = false>(options?: Options<EventSubscribeData, ThrowOnError>) {
-    return (options?.client ?? this._client).sse.get<EventSubscribeResponses, unknown, ThrowOnError>({
+    return (options?.client ?? this._client).get.sse<EventSubscribeResponses, unknown, ThrowOnError>({
       url: "/event",
       ...options,
     })

+ 1 - 1
packages/web/package.json

@@ -1,7 +1,7 @@
 {
   "name": "@opencode/web",
   "type": "module",
-  "version": "0.9.7",
+  "version": "0.9.8",
   "scripts": {
     "dev": "astro dev",
     "dev:remote": "VITE_API_URL=https://api.opencode.ai astro dev",

+ 1 - 1
sdks/vscode/package.json

@@ -2,7 +2,7 @@
   "name": "opencode",
   "displayName": "opencode",
   "description": "opencode for VS Code",
-  "version": "0.9.7",
+  "version": "0.9.8",
   "publisher": "sst-dev",
   "repository": {
     "type": "git",