Browse Source

ignore: fix event type gen

Dax Raad 5 months ago
parent
commit
abd99aeb7d

+ 4 - 4
packages/opencode/src/bus/index.ts

@@ -33,16 +33,16 @@ export namespace Bus {
       "type",
       "type",
       registry
       registry
         .entries()
         .entries()
-        .map(([type, def]) =>
-          z
+        .map(([type, def]) => {
+          return z
             .object({
             .object({
               type: z.literal(type),
               type: z.literal(type),
               properties: def.properties,
               properties: def.properties,
             })
             })
             .meta({
             .meta({
               ref: "Event" + "." + def.type,
               ref: "Event" + "." + def.type,
-            }),
-        )
+            })
+        })
         .toArray() as any,
         .toArray() as any,
     )
     )
   }
   }

+ 2 - 1
packages/opencode/src/plugin/index.ts

@@ -15,7 +15,8 @@ export namespace Plugin {
   const state = Instance.state(async () => {
   const state = Instance.state(async () => {
     const client = createOpencodeClient({
     const client = createOpencodeClient({
       baseUrl: "http://localhost:4096",
       baseUrl: "http://localhost:4096",
-      fetch: async (...args) => Server.App.fetch(...args),
+      // @ts-expect-error
+      fetch: async (...args) => Server.App().fetch(...args),
     })
     })
     const config = await Config.get()
     const config = await Config.get()
     const hooks = []
     const hooks = []

File diff suppressed because it is too large
+ 1155 - 1152
packages/opencode/src/server/server.ts


+ 8 - 8
packages/opencode/test/tool/register.test.ts

@@ -31,7 +31,7 @@ describe("HTTP tool registration API", () => {
       }
       }
 
 
       // Register
       // Register
-      const registerRes = await Server.App.fetch(
+      const registerRes = await Server.App().fetch(
         makeRequest("POST", "http://localhost:4096/experimental/tool/register", toolSpec),
         makeRequest("POST", "http://localhost:4096/experimental/tool/register", toolSpec),
       )
       )
       expect(registerRes.status).toBe(200)
       expect(registerRes.status).toBe(200)
@@ -39,13 +39,13 @@ describe("HTTP tool registration API", () => {
       expect(ok).toBe(true)
       expect(ok).toBe(true)
 
 
       // IDs should include the new tool
       // IDs should include the new tool
-      const idsRes = await Server.App.fetch(makeRequest("GET", "http://localhost:4096/experimental/tool/ids"))
+      const idsRes = await Server.App().fetch(makeRequest("GET", "http://localhost:4096/experimental/tool/ids"))
       expect(idsRes.status).toBe(200)
       expect(idsRes.status).toBe(200)
       const ids = (await idsRes.json()) as string[]
       const ids = (await idsRes.json()) as string[]
       expect(ids).toContain("http-echo")
       expect(ids).toContain("http-echo")
 
 
       // List tools for a provider/model and check JSON Schema shape
       // List tools for a provider/model and check JSON Schema shape
-      const listRes = await Server.App.fetch(
+      const listRes = await Server.App().fetch(
         makeRequest("GET", "http://localhost:4096/experimental/tool?provider=openai&model=gpt-4o"),
         makeRequest("GET", "http://localhost:4096/experimental/tool?provider=openai&model=gpt-4o"),
       )
       )
       expect(listRes.status).toBe(200)
       expect(listRes.status).toBe(200)
@@ -105,7 +105,7 @@ describe("Plugin tool.register hook", () => {
       expect(allIDs).toContain("from-plugin")
       expect(allIDs).toContain("from-plugin")
 
 
       // Also verify via the HTTP surface
       // Also verify via the HTTP surface
-      const idsRes = await Server.App.fetch(makeRequest("GET", "http://localhost:4096/experimental/tool/ids"))
+      const idsRes = await Server.App().fetch(makeRequest("GET", "http://localhost:4096/experimental/tool/ids"))
       expect(idsRes.status).toBe(200)
       expect(idsRes.status).toBe(200)
       const ids = (await idsRes.json()) as string[]
       const ids = (await idsRes.json()) as string[]
       expect(ids).toContain("from-plugin")
       expect(ids).toContain("from-plugin")
@@ -168,7 +168,7 @@ test("Multiple plugins can each register tools", async () => {
     expect(ids).toContain("alpha-tool")
     expect(ids).toContain("alpha-tool")
     expect(ids).toContain("beta-tool")
     expect(ids).toContain("beta-tool")
 
 
-    const res = await Server.App.fetch(new Request("http://localhost:4096/experimental/tool/ids"))
+    const res = await Server.App().fetch(new Request("http://localhost:4096/experimental/tool/ids"))
     expect(res.status).toBe(200)
     expect(res.status).toBe(200)
     const httpIds = (await res.json()) as string[]
     const httpIds = (await res.json()) as string[]
     expect(httpIds).toContain("alpha-tool")
     expect(httpIds).toContain("alpha-tool")
@@ -241,14 +241,14 @@ test("Plugin registers native/local tool with function execution", async () => {
     expect(ids).toContain("http-tool-from-same-plugin")
     expect(ids).toContain("http-tool-from-same-plugin")
 
 
     // Verify via HTTP endpoint
     // Verify via HTTP endpoint
-    const res = await Server.App.fetch(new Request("http://localhost:4096/experimental/tool/ids"))
+    const res = await Server.App().fetch(new Request("http://localhost:4096/experimental/tool/ids"))
     expect(res.status).toBe(200)
     expect(res.status).toBe(200)
     const httpIds = (await res.json()) as string[]
     const httpIds = (await res.json()) as string[]
     expect(httpIds).toContain("my-native-tool")
     expect(httpIds).toContain("my-native-tool")
     expect(httpIds).toContain("http-tool-from-same-plugin")
     expect(httpIds).toContain("http-tool-from-same-plugin")
 
 
     // Get tool details to verify native tool has proper structure
     // Get tool details to verify native tool has proper structure
-    const toolsRes = await Server.App.fetch(
+    const toolsRes = await Server.App().fetch(
       new Request("http://localhost:4096/experimental/tool?provider=anthropic&model=claude"),
       new Request("http://localhost:4096/experimental/tool?provider=anthropic&model=claude"),
     )
     )
     expect(toolsRes.status).toBe(200)
     expect(toolsRes.status).toBe(200)
@@ -290,7 +290,7 @@ test("Plugin without tool.register is handled gracefully", async () => {
     const ids = ToolRegistry.ids()
     const ids = ToolRegistry.ids()
     expect(ids).not.toContain("malformed-tool")
     expect(ids).not.toContain("malformed-tool")
 
 
-    const res = await Server.App.fetch(new Request("http://localhost:4096/experimental/tool/ids"))
+    const res = await Server.App().fetch(new Request("http://localhost:4096/experimental/tool/ids"))
     expect(res.status).toBe(200)
     expect(res.status).toBe(200)
     const httpIds = (await res.json()) as string[]
     const httpIds = (await res.json()) as string[]
     expect(httpIds).not.toContain("malformed-tool")
     expect(httpIds).not.toContain("malformed-tool")

+ 1 - 1
packages/sdk/go/.release-please-manifest.json

@@ -1,3 +1,3 @@
 {
 {
-  ".": "0.14.0"
+  ".": "0.15.0"
 }
 }

+ 2 - 2
packages/sdk/go/.stats.yml

@@ -1,4 +1,4 @@
 configured_endpoints: 43
 configured_endpoints: 43
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-0a4165f1eabf826d3092ea6b789aa527048278dcd4bd891f9e5ac890b9bcbb35.yml
-openapi_spec_hash: da60e4fc813eb0f9ac3ab5f112e26bf6
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-ad911ed0bdbeca62807509f364f25fcafd7a83e0b43e027ec0a85f72b7a4d963.yml
+openapi_spec_hash: 15152513b4246bf4b5f8546fa6f1603f
 config_hash: 026ef000d34bf2f930e7b41e77d2d3ff
 config_hash: 026ef000d34bf2f930e7b41e77d2d3ff

+ 8 - 0
packages/sdk/go/CHANGELOG.md

@@ -1,5 +1,13 @@
 # Changelog
 # Changelog
 
 
+## 0.15.0 (2025-09-16)
+
+Full Changelog: [v0.14.0...v0.15.0](https://github.com/sst/opencode-sdk-go/compare/v0.14.0...v0.15.0)
+
+### Features
+
+- **api:** api update ([397048f](https://github.com/sst/opencode-sdk-go/commit/397048faca7a1de7a028edd2254a0ad7797b151f))
+
 ## 0.14.0 (2025-09-14)
 ## 0.14.0 (2025-09-14)
 
 
 Full Changelog: [v0.13.0...v0.14.0](https://github.com/sst/opencode-sdk-go/compare/v0.13.0...v0.14.0)
 Full Changelog: [v0.13.0...v0.14.0](https://github.com/sst/opencode-sdk-go/compare/v0.13.0...v0.14.0)

+ 1 - 1
packages/sdk/go/README.md

@@ -24,7 +24,7 @@ Or to pin the version:
 <!-- x-release-please-start-version -->
 <!-- x-release-please-start-version -->
 
 
 ```sh
 ```sh
-go get -u 'github.com/sst/[email protected]4.0'
+go get -u 'github.com/sst/[email protected]5.0'
 ```
 ```
 
 
 <!-- x-release-please-end -->
 <!-- x-release-please-end -->

+ 24 - 2
packages/sdk/go/config.go

@@ -90,8 +90,9 @@ type Config struct {
 	// TUI specific settings
 	// TUI specific settings
 	Tui ConfigTui `json:"tui"`
 	Tui ConfigTui `json:"tui"`
 	// Custom username to display in conversations instead of system username
 	// Custom username to display in conversations instead of system username
-	Username string     `json:"username"`
-	JSON     configJSON `json:"-"`
+	Username string        `json:"username"`
+	Watcher  ConfigWatcher `json:"watcher"`
+	JSON     configJSON    `json:"-"`
 }
 }
 
 
 // configJSON contains the JSON metadata for the struct [Config]
 // configJSON contains the JSON metadata for the struct [Config]
@@ -121,6 +122,7 @@ type configJSON struct {
 	Tools             apijson.Field
 	Tools             apijson.Field
 	Tui               apijson.Field
 	Tui               apijson.Field
 	Username          apijson.Field
 	Username          apijson.Field
+	Watcher           apijson.Field
 	raw               string
 	raw               string
 	ExtraFields       map[string]apijson.Field
 	ExtraFields       map[string]apijson.Field
 }
 }
@@ -1772,6 +1774,26 @@ func (r configTuiJSON) RawJSON() string {
 	return r.raw
 	return r.raw
 }
 }
 
 
+type ConfigWatcher struct {
+	Ignore []string          `json:"ignore"`
+	JSON   configWatcherJSON `json:"-"`
+}
+
+// configWatcherJSON contains the JSON metadata for the struct [ConfigWatcher]
+type configWatcherJSON struct {
+	Ignore      apijson.Field
+	raw         string
+	ExtraFields map[string]apijson.Field
+}
+
+func (r *ConfigWatcher) UnmarshalJSON(data []byte) (err error) {
+	return apijson.UnmarshalRoot(data, r)
+}
+
+func (r configWatcherJSON) RawJSON() string {
+	return r.raw
+}
+
 // Custom keybind configurations
 // Custom keybind configurations
 type KeybindsConfig struct {
 type KeybindsConfig struct {
 	// Next agent
 	// Next agent

+ 159 - 5
packages/sdk/go/event.go

@@ -64,7 +64,9 @@ type EventListResponse struct {
 	// [EventListResponseEventSessionIdleProperties],
 	// [EventListResponseEventSessionIdleProperties],
 	// [EventListResponseEventSessionUpdatedProperties],
 	// [EventListResponseEventSessionUpdatedProperties],
 	// [EventListResponseEventSessionDeletedProperties],
 	// [EventListResponseEventSessionDeletedProperties],
-	// [EventListResponseEventSessionErrorProperties], [interface{}].
+	// [EventListResponseEventSessionErrorProperties], [interface{}],
+	// [EventListResponseEventFileWatcherUpdatedProperties],
+	// [EventListResponseEventIdeInstalledProperties].
 	Properties interface{}           `json:"properties,required"`
 	Properties interface{}           `json:"properties,required"`
 	Type       EventListResponseType `json:"type,required"`
 	Type       EventListResponseType `json:"type,required"`
 	JSON       eventListResponseJSON `json:"-"`
 	JSON       eventListResponseJSON `json:"-"`
@@ -107,7 +109,9 @@ func (r *EventListResponse) UnmarshalJSON(data []byte) (err error) {
 // [EventListResponseEventPermissionReplied], [EventListResponseEventFileEdited],
 // [EventListResponseEventPermissionReplied], [EventListResponseEventFileEdited],
 // [EventListResponseEventSessionIdle], [EventListResponseEventSessionUpdated],
 // [EventListResponseEventSessionIdle], [EventListResponseEventSessionUpdated],
 // [EventListResponseEventSessionDeleted], [EventListResponseEventSessionError],
 // [EventListResponseEventSessionDeleted], [EventListResponseEventSessionError],
-// [EventListResponseEventServerConnected].
+// [EventListResponseEventServerConnected],
+// [EventListResponseEventFileWatcherUpdated],
+// [EventListResponseEventIdeInstalled].
 func (r EventListResponse) AsUnion() EventListResponseUnion {
 func (r EventListResponse) AsUnion() EventListResponseUnion {
 	return r.union
 	return r.union
 }
 }
@@ -121,8 +125,10 @@ func (r EventListResponse) AsUnion() EventListResponseUnion {
 // [EventListResponseEventPermissionUpdated],
 // [EventListResponseEventPermissionUpdated],
 // [EventListResponseEventPermissionReplied], [EventListResponseEventFileEdited],
 // [EventListResponseEventPermissionReplied], [EventListResponseEventFileEdited],
 // [EventListResponseEventSessionIdle], [EventListResponseEventSessionUpdated],
 // [EventListResponseEventSessionIdle], [EventListResponseEventSessionUpdated],
-// [EventListResponseEventSessionDeleted], [EventListResponseEventSessionError] or
-// [EventListResponseEventServerConnected].
+// [EventListResponseEventSessionDeleted], [EventListResponseEventSessionError],
+// [EventListResponseEventServerConnected],
+// [EventListResponseEventFileWatcherUpdated] or
+// [EventListResponseEventIdeInstalled].
 type EventListResponseUnion interface {
 type EventListResponseUnion interface {
 	implementsEventListResponse()
 	implementsEventListResponse()
 }
 }
@@ -191,6 +197,14 @@ func init() {
 			TypeFilter: gjson.JSON,
 			TypeFilter: gjson.JSON,
 			Type:       reflect.TypeOf(EventListResponseEventServerConnected{}),
 			Type:       reflect.TypeOf(EventListResponseEventServerConnected{}),
 		},
 		},
+		apijson.UnionVariant{
+			TypeFilter: gjson.JSON,
+			Type:       reflect.TypeOf(EventListResponseEventFileWatcherUpdated{}),
+		},
+		apijson.UnionVariant{
+			TypeFilter: gjson.JSON,
+			Type:       reflect.TypeOf(EventListResponseEventIdeInstalled{}),
+		},
 	)
 	)
 }
 }
 
 
@@ -1196,6 +1210,144 @@ func (r EventListResponseEventServerConnectedType) IsKnown() bool {
 	return false
 	return false
 }
 }
 
 
+type EventListResponseEventFileWatcherUpdated struct {
+	Properties EventListResponseEventFileWatcherUpdatedProperties `json:"properties,required"`
+	Type       EventListResponseEventFileWatcherUpdatedType       `json:"type,required"`
+	JSON       eventListResponseEventFileWatcherUpdatedJSON       `json:"-"`
+}
+
+// eventListResponseEventFileWatcherUpdatedJSON contains the JSON metadata for the
+// struct [EventListResponseEventFileWatcherUpdated]
+type eventListResponseEventFileWatcherUpdatedJSON struct {
+	Properties  apijson.Field
+	Type        apijson.Field
+	raw         string
+	ExtraFields map[string]apijson.Field
+}
+
+func (r *EventListResponseEventFileWatcherUpdated) UnmarshalJSON(data []byte) (err error) {
+	return apijson.UnmarshalRoot(data, r)
+}
+
+func (r eventListResponseEventFileWatcherUpdatedJSON) RawJSON() string {
+	return r.raw
+}
+
+func (r EventListResponseEventFileWatcherUpdated) implementsEventListResponse() {}
+
+type EventListResponseEventFileWatcherUpdatedProperties struct {
+	Event EventListResponseEventFileWatcherUpdatedPropertiesEvent `json:"event,required"`
+	File  string                                                  `json:"file,required"`
+	JSON  eventListResponseEventFileWatcherUpdatedPropertiesJSON  `json:"-"`
+}
+
+// eventListResponseEventFileWatcherUpdatedPropertiesJSON contains the JSON
+// metadata for the struct [EventListResponseEventFileWatcherUpdatedProperties]
+type eventListResponseEventFileWatcherUpdatedPropertiesJSON struct {
+	Event       apijson.Field
+	File        apijson.Field
+	raw         string
+	ExtraFields map[string]apijson.Field
+}
+
+func (r *EventListResponseEventFileWatcherUpdatedProperties) UnmarshalJSON(data []byte) (err error) {
+	return apijson.UnmarshalRoot(data, r)
+}
+
+func (r eventListResponseEventFileWatcherUpdatedPropertiesJSON) RawJSON() string {
+	return r.raw
+}
+
+type EventListResponseEventFileWatcherUpdatedPropertiesEvent string
+
+const (
+	EventListResponseEventFileWatcherUpdatedPropertiesEventAdd    EventListResponseEventFileWatcherUpdatedPropertiesEvent = "add"
+	EventListResponseEventFileWatcherUpdatedPropertiesEventChange EventListResponseEventFileWatcherUpdatedPropertiesEvent = "change"
+	EventListResponseEventFileWatcherUpdatedPropertiesEventUnlink EventListResponseEventFileWatcherUpdatedPropertiesEvent = "unlink"
+)
+
+func (r EventListResponseEventFileWatcherUpdatedPropertiesEvent) IsKnown() bool {
+	switch r {
+	case EventListResponseEventFileWatcherUpdatedPropertiesEventAdd, EventListResponseEventFileWatcherUpdatedPropertiesEventChange, EventListResponseEventFileWatcherUpdatedPropertiesEventUnlink:
+		return true
+	}
+	return false
+}
+
+type EventListResponseEventFileWatcherUpdatedType string
+
+const (
+	EventListResponseEventFileWatcherUpdatedTypeFileWatcherUpdated EventListResponseEventFileWatcherUpdatedType = "file.watcher.updated"
+)
+
+func (r EventListResponseEventFileWatcherUpdatedType) IsKnown() bool {
+	switch r {
+	case EventListResponseEventFileWatcherUpdatedTypeFileWatcherUpdated:
+		return true
+	}
+	return false
+}
+
+type EventListResponseEventIdeInstalled struct {
+	Properties EventListResponseEventIdeInstalledProperties `json:"properties,required"`
+	Type       EventListResponseEventIdeInstalledType       `json:"type,required"`
+	JSON       eventListResponseEventIdeInstalledJSON       `json:"-"`
+}
+
+// eventListResponseEventIdeInstalledJSON contains the JSON metadata for the struct
+// [EventListResponseEventIdeInstalled]
+type eventListResponseEventIdeInstalledJSON struct {
+	Properties  apijson.Field
+	Type        apijson.Field
+	raw         string
+	ExtraFields map[string]apijson.Field
+}
+
+func (r *EventListResponseEventIdeInstalled) UnmarshalJSON(data []byte) (err error) {
+	return apijson.UnmarshalRoot(data, r)
+}
+
+func (r eventListResponseEventIdeInstalledJSON) RawJSON() string {
+	return r.raw
+}
+
+func (r EventListResponseEventIdeInstalled) implementsEventListResponse() {}
+
+type EventListResponseEventIdeInstalledProperties struct {
+	Ide  string                                           `json:"ide,required"`
+	JSON eventListResponseEventIdeInstalledPropertiesJSON `json:"-"`
+}
+
+// eventListResponseEventIdeInstalledPropertiesJSON contains the JSON metadata for
+// the struct [EventListResponseEventIdeInstalledProperties]
+type eventListResponseEventIdeInstalledPropertiesJSON struct {
+	Ide         apijson.Field
+	raw         string
+	ExtraFields map[string]apijson.Field
+}
+
+func (r *EventListResponseEventIdeInstalledProperties) UnmarshalJSON(data []byte) (err error) {
+	return apijson.UnmarshalRoot(data, r)
+}
+
+func (r eventListResponseEventIdeInstalledPropertiesJSON) RawJSON() string {
+	return r.raw
+}
+
+type EventListResponseEventIdeInstalledType string
+
+const (
+	EventListResponseEventIdeInstalledTypeIdeInstalled EventListResponseEventIdeInstalledType = "ide.installed"
+)
+
+func (r EventListResponseEventIdeInstalledType) IsKnown() bool {
+	switch r {
+	case EventListResponseEventIdeInstalledTypeIdeInstalled:
+		return true
+	}
+	return false
+}
+
 type EventListResponseType string
 type EventListResponseType string
 
 
 const (
 const (
@@ -1214,11 +1366,13 @@ const (
 	EventListResponseTypeSessionDeleted       EventListResponseType = "session.deleted"
 	EventListResponseTypeSessionDeleted       EventListResponseType = "session.deleted"
 	EventListResponseTypeSessionError         EventListResponseType = "session.error"
 	EventListResponseTypeSessionError         EventListResponseType = "session.error"
 	EventListResponseTypeServerConnected      EventListResponseType = "server.connected"
 	EventListResponseTypeServerConnected      EventListResponseType = "server.connected"
+	EventListResponseTypeFileWatcherUpdated   EventListResponseType = "file.watcher.updated"
+	EventListResponseTypeIdeInstalled         EventListResponseType = "ide.installed"
 )
 )
 
 
 func (r EventListResponseType) IsKnown() bool {
 func (r EventListResponseType) IsKnown() bool {
 	switch r {
 	switch r {
-	case EventListResponseTypeInstallationUpdated, EventListResponseTypeLspClientDiagnostics, EventListResponseTypeMessageUpdated, EventListResponseTypeMessageRemoved, EventListResponseTypeMessagePartUpdated, EventListResponseTypeMessagePartRemoved, EventListResponseTypeSessionCompacted, EventListResponseTypePermissionUpdated, EventListResponseTypePermissionReplied, EventListResponseTypeFileEdited, EventListResponseTypeSessionIdle, EventListResponseTypeSessionUpdated, EventListResponseTypeSessionDeleted, EventListResponseTypeSessionError, EventListResponseTypeServerConnected:
+	case EventListResponseTypeInstallationUpdated, EventListResponseTypeLspClientDiagnostics, EventListResponseTypeMessageUpdated, EventListResponseTypeMessageRemoved, EventListResponseTypeMessagePartUpdated, EventListResponseTypeMessagePartRemoved, EventListResponseTypeSessionCompacted, EventListResponseTypePermissionUpdated, EventListResponseTypePermissionReplied, EventListResponseTypeFileEdited, EventListResponseTypeSessionIdle, EventListResponseTypeSessionUpdated, EventListResponseTypeSessionDeleted, EventListResponseTypeSessionError, EventListResponseTypeServerConnected, EventListResponseTypeFileWatcherUpdated, EventListResponseTypeIdeInstalled:
 		return true
 		return true
 	}
 	}
 	return false
 	return false

+ 1 - 1
packages/sdk/go/internal/version.go

@@ -2,4 +2,4 @@
 
 
 package internal
 package internal
 
 
-const PackageVersion = "0.14.0" // x-release-please-version
+const PackageVersion = "0.15.0" // x-release-please-version

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

@@ -1,6 +1,8 @@
 // This file is auto-generated by @hey-api/openapi-ts
 // This file is auto-generated by @hey-api/openapi-ts
 
 
 import { createSseClient } from "../core/serverSentEvents.gen.js"
 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 type { Client, Config, RequestOptions, ResolvedRequestOptions } from "./types.gen.js"
 import {
 import {
   buildUrl,
   buildUrl,
@@ -49,12 +51,12 @@ export const createClient = (config: Config = {}): Client => {
       await opts.requestValidator(opts)
       await opts.requestValidator(opts)
     }
     }
 
 
-    if (opts.body && opts.bodySerializer) {
+    if (opts.body !== undefined && opts.bodySerializer) {
       opts.serializedBody = opts.bodySerializer(opts.body)
       opts.serializedBody = opts.bodySerializer(opts.body)
     }
     }
 
 
     // remove Content-Type header if body is empty to avoid sending invalid requests
     // remove Content-Type header if body is empty to avoid sending invalid requests
-    if (opts.serializedBody === undefined || opts.serializedBody === "") {
+    if (opts.body === undefined || opts.serializedBody === "") {
       opts.headers.delete("Content-Type")
       opts.headers.delete("Content-Type")
     }
     }
 
 
@@ -69,7 +71,7 @@ export const createClient = (config: Config = {}): Client => {
     const requestInit: ReqInit = {
     const requestInit: ReqInit = {
       redirect: "follow",
       redirect: "follow",
       ...opts,
       ...opts,
-      body: opts.serializedBody,
+      body: getValidRequestBody(opts),
     }
     }
 
 
     let request = new Request(url, requestInit)
     let request = new Request(url, requestInit)
@@ -97,18 +99,36 @@ export const createClient = (config: Config = {}): Client => {
     }
     }
 
 
     if (response.ok) {
     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") {
       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"
         return opts.responseStyle === "data"
-          ? {}
+          ? emptyData
           : {
           : {
-              data: {},
+              data: emptyData,
               ...result,
               ...result,
             }
             }
       }
       }
 
 
-      const parseAs =
-        (opts.parseAs === "auto" ? getParseAs(response.headers.get("Content-Type")) : opts.parseAs) ?? "json"
-
       let data: any
       let data: any
       switch (parseAs) {
       switch (parseAs) {
         case "arrayBuffer":
         case "arrayBuffer":
@@ -178,35 +198,53 @@ export const createClient = (config: Config = {}): Client => {
         }
         }
   }
   }
 
 
-  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
+  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,
+    })
   }
   }
 
 
   return {
   return {
     buildUrl,
     buildUrl,
-    connect: makeMethod("CONNECT"),
-    delete: makeMethod("DELETE"),
-    get: makeMethod("GET"),
+    connect: makeMethodFn("CONNECT"),
+    delete: makeMethodFn("DELETE"),
+    get: makeMethodFn("GET"),
     getConfig,
     getConfig,
-    head: makeMethod("HEAD"),
+    head: makeMethodFn("HEAD"),
     interceptors,
     interceptors,
-    options: makeMethod("OPTIONS"),
-    patch: makeMethod("PATCH"),
-    post: makeMethod("POST"),
-    put: makeMethod("PUT"),
+    options: makeMethodFn("OPTIONS"),
+    patch: makeMethodFn("PATCH"),
+    post: makeMethodFn("POST"),
+    put: makeMethodFn("PUT"),
     request,
     request,
     setConfig,
     setConfig,
-    trace: makeMethod("TRACE"),
+    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"),
   } as Client
   } as Client
 }
 }

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

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

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

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

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

@@ -4,6 +4,17 @@ import type { Config } from "./types.gen.js"
 
 
 export type ServerSentEventsOptions<TData = unknown> = Omit<RequestInit, "method"> &
 export type ServerSentEventsOptions<TData = unknown> = Omit<RequestInit, "method"> &
   Pick<Config, "method" | "responseTransformer" | "responseValidator"> & {
   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.
      * Callback invoked when a network or parsing error occurs during streaming.
      *
      *
@@ -21,6 +32,7 @@ export type ServerSentEventsOptions<TData = unknown> = Omit<RequestInit, "method
      * @returns Nothing (void).
      * @returns Nothing (void).
      */
      */
     onSseEvent?: (event: StreamEvent<TData>) => void
     onSseEvent?: (event: StreamEvent<TData>) => void
+    serializedBody?: RequestInit["body"]
     /**
     /**
      * Default retry delay in milliseconds.
      * Default retry delay in milliseconds.
      *
      *
@@ -64,6 +76,7 @@ export type ServerSentEventsResult<TData = unknown, TReturn = void, TNext = unkn
 }
 }
 
 
 export const createSseClient = <TData = unknown>({
 export const createSseClient = <TData = unknown>({
+  onRequest,
   onSseError,
   onSseError,
   onSseEvent,
   onSseEvent,
   responseTransformer,
   responseTransformer,
@@ -99,7 +112,21 @@ export const createSseClient = <TData = unknown>({
       }
       }
 
 
       try {
       try {
-        const response = await fetch(url, { ...options, headers, signal })
+        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)
 
 
         if (!response.ok) throw new Error(`SSE failed: ${response.status} ${response.statusText}`)
         if (!response.ok) throw new Error(`SSE failed: ${response.status} ${response.statusText}`)
 
 

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

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

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

@@ -1,6 +1,6 @@
 // This file is auto-generated by @hey-api/openapi-ts
 // This file is auto-generated by @hey-api/openapi-ts
 
 
-import type { QuerySerializer } from "./bodySerializer.gen.js"
+import type { BodySerializer, QuerySerializer } from "./bodySerializer.gen.js"
 import {
 import {
   type ArraySeparatorStyle,
   type ArraySeparatorStyle,
   serializeArrayParam,
   serializeArrayParam,
@@ -107,3 +107,31 @@ export const getUrl = ({
   }
   }
   return url
   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
+}

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

@@ -6,8 +6,6 @@ import type {
   ProjectListResponses,
   ProjectListResponses,
   ProjectCurrentData,
   ProjectCurrentData,
   ProjectCurrentResponses,
   ProjectCurrentResponses,
-  EventSubscribeData,
-  EventSubscribeResponses,
   ConfigGetData,
   ConfigGetData,
   ConfigGetResponses,
   ConfigGetResponses,
   ToolRegisterData,
   ToolRegisterData,
@@ -101,6 +99,8 @@ import type {
   AuthSetData,
   AuthSetData,
   AuthSetResponses,
   AuthSetResponses,
   AuthSetErrors,
   AuthSetErrors,
+  EventSubscribeData,
+  EventSubscribeResponses,
 } from "./types.gen.js"
 } from "./types.gen.js"
 import { client as _heyApiClient } from "./client.gen.js"
 import { client as _heyApiClient } from "./client.gen.js"
 
 
@@ -153,18 +153,6 @@ class Project extends _HeyApiClient {
   }
   }
 }
 }
 
 
-class Event extends _HeyApiClient {
-  /**
-   * Get events
-   */
-  public subscribe<ThrowOnError extends boolean = false>(options?: Options<EventSubscribeData, ThrowOnError>) {
-    return (options?.client ?? this._client).get.sse<EventSubscribeResponses, unknown, ThrowOnError>({
-      url: "/event",
-      ...options,
-    })
-  }
-}
-
 class Config extends _HeyApiClient {
 class Config extends _HeyApiClient {
   /**
   /**
    * Get config info
    * Get config info
@@ -671,6 +659,18 @@ class Auth extends _HeyApiClient {
   }
   }
 }
 }
 
 
+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>({
+      url: "/event",
+      ...options,
+    })
+  }
+}
+
 export class OpencodeClient extends _HeyApiClient {
 export class OpencodeClient extends _HeyApiClient {
   /**
   /**
    * Respond to a permission request
    * Respond to a permission request
@@ -688,7 +688,6 @@ export class OpencodeClient extends _HeyApiClient {
     })
     })
   }
   }
   project = new Project({ client: this._client })
   project = new Project({ client: this._client })
-  event = new Event({ client: this._client })
   config = new Config({ client: this._client })
   config = new Config({ client: this._client })
   tool = new Tool({ client: this._client })
   tool = new Tool({ client: this._client })
   path = new Path({ client: this._client })
   path = new Path({ client: this._client })
@@ -699,4 +698,5 @@ export class OpencodeClient extends _HeyApiClient {
   app = new App({ client: this._client })
   app = new App({ client: this._client })
   tui = new Tui({ client: this._client })
   tui = new Tui({ client: this._client })
   auth = new Auth({ client: this._client })
   auth = new Auth({ client: this._client })
+  event = new Event({ client: this._client })
 }
 }

File diff suppressed because it is too large
+ 429 - 572
packages/sdk/js/src/gen/types.gen.ts


Some files were not shown because too many files changed in this diff