Переглянути джерело

refactor(core): move server routes around to clarify workspacing (#23031)

James Long 1 день тому
батько
коміт
7605acff65
32 змінених файлів з 995 додано та 932 видалено
  1. 2 2
      packages/opencode/src/control-plane/workspace-context.ts
  2. 3 3
      packages/opencode/src/server/routes/control/index.ts
  3. 5 5
      packages/opencode/src/server/routes/control/workspace.ts
  4. 0 0
      packages/opencode/src/server/routes/global.ts
  5. 5 5
      packages/opencode/src/server/routes/instance/config.ts
  6. 1 1
      packages/opencode/src/server/routes/instance/event.ts
  7. 14 16
      packages/opencode/src/server/routes/instance/experimental.ts
  8. 6 6
      packages/opencode/src/server/routes/instance/file.ts
  9. 0 0
      packages/opencode/src/server/routes/instance/httpapi/config.ts
  10. 0 0
      packages/opencode/src/server/routes/instance/httpapi/permission.ts
  11. 0 0
      packages/opencode/src/server/routes/instance/httpapi/project.ts
  12. 0 0
      packages/opencode/src/server/routes/instance/httpapi/provider.ts
  13. 0 0
      packages/opencode/src/server/routes/instance/httpapi/question.ts
  14. 0 0
      packages/opencode/src/server/routes/instance/httpapi/server.ts
  15. 9 10
      packages/opencode/src/server/routes/instance/index.ts
  16. 6 6
      packages/opencode/src/server/routes/instance/mcp.ts
  17. 2 2
      packages/opencode/src/server/routes/instance/permission.ts
  18. 6 6
      packages/opencode/src/server/routes/instance/project.ts
  19. 8 8
      packages/opencode/src/server/routes/instance/provider.ts
  20. 2 2
      packages/opencode/src/server/routes/instance/pty.ts
  21. 3 3
      packages/opencode/src/server/routes/instance/question.ts
  22. 13 13
      packages/opencode/src/server/routes/instance/session.ts
  23. 1 1
      packages/opencode/src/server/routes/instance/sync.ts
  24. 1 1
      packages/opencode/src/server/routes/instance/trace.ts
  25. 5 5
      packages/opencode/src/server/routes/instance/tui.ts
  26. 0 0
      packages/opencode/src/server/routes/ui.ts
  27. 53 17
      packages/opencode/src/server/server.ts
  28. 5 38
      packages/opencode/src/server/workspace.ts
  29. 0 13
      packages/opencode/test/server/session-messages.test.ts
  30. 294 272
      packages/sdk/js/src/v2/gen/sdk.gen.ts
  31. 181 181
      packages/sdk/js/src/v2/gen/types.gen.ts
  32. 370 316
      packages/sdk/openapi.json

+ 2 - 2
packages/opencode/src/control-plane/workspace-context.ts

@@ -2,13 +2,13 @@ import { LocalContext } from "../util"
 import type { WorkspaceID } from "../control-plane/schema"
 
 export interface WorkspaceContext {
-  workspaceID: WorkspaceID
+  workspaceID: WorkspaceID | undefined
 }
 
 const context = LocalContext.create<WorkspaceContext>("instance")
 
 export const WorkspaceContext = {
-  async provide<R>(input: { workspaceID: WorkspaceID; fn: () => R }): Promise<R> {
+  async provide<R>(input: { workspaceID?: WorkspaceID; fn: () => R }): Promise<R> {
     return context.provide({ workspaceID: input.workspaceID }, () => input.fn())
   },
 

+ 3 - 3
packages/opencode/src/server/control/index.ts → packages/opencode/src/server/routes/control/index.ts

@@ -6,13 +6,12 @@ import { ProviderID } from "@/provider/schema"
 import { Hono } from "hono"
 import { describeRoute, resolver, validator, openAPIRouteHandler } from "hono-openapi"
 import z from "zod"
-import { errors } from "../error"
-import { GlobalRoutes } from "../instance/global"
+import { errors } from "../../error"
+import { WorkspaceRoutes } from "./workspace"
 
 export function ControlPlaneRoutes(): Hono {
   const app = new Hono()
   return app
-    .route("/global", GlobalRoutes())
     .put(
       "/auth/:providerID",
       describeRoute({
@@ -159,4 +158,5 @@ export function ControlPlaneRoutes(): Hono {
         return c.json(true)
       },
     )
+    .route("/experimental/workspace", WorkspaceRoutes())
 }

+ 5 - 5
packages/opencode/src/server/instance/workspace.ts → packages/opencode/src/server/routes/control/workspace.ts

@@ -1,11 +1,11 @@
 import { Hono } from "hono"
 import { describeRoute, resolver, validator } from "hono-openapi"
 import z from "zod"
-import { listAdaptors } from "../../control-plane/adaptors"
-import { Workspace } from "../../control-plane/workspace"
-import { Instance } from "../../project/instance"
-import { errors } from "../error"
-import { lazy } from "../../util/lazy"
+import { listAdaptors } from "@/control-plane/adaptors"
+import { Workspace } from "@/control-plane/workspace"
+import { Instance } from "@/project/instance"
+import { errors } from "../../error"
+import { lazy } from "@/util/lazy"
 import { Log } from "@/util"
 import { errorData } from "@/util/error"
 

+ 0 - 0
packages/opencode/src/server/instance/global.ts → packages/opencode/src/server/routes/global.ts


+ 5 - 5
packages/opencode/src/server/instance/config.ts → packages/opencode/src/server/routes/instance/config.ts

@@ -1,11 +1,11 @@
 import { Hono } from "hono"
 import { describeRoute, validator, resolver } from "hono-openapi"
 import z from "zod"
-import { Config } from "../../config"
-import { Provider } from "../../provider"
-import { errors } from "../error"
-import { lazy } from "../../util/lazy"
-import { AppRuntime } from "../../effect/app-runtime"
+import { Config } from "@/config"
+import { Provider } from "@/provider"
+import { errors } from "../../error"
+import { lazy } from "@/util/lazy"
+import { AppRuntime } from "@/effect/app-runtime"
 import { jsonRequest } from "./trace"
 
 export const ConfigRoutes = lazy(() =>

+ 1 - 1
packages/opencode/src/server/instance/event.ts → packages/opencode/src/server/routes/instance/event.ts

@@ -5,7 +5,7 @@ import { streamSSE } from "hono/streaming"
 import { Log } from "@/util"
 import { BusEvent } from "@/bus/bus-event"
 import { Bus } from "@/bus"
-import { AsyncQueue } from "../../util/queue"
+import { AsyncQueue } from "@/util/queue"
 
 const log = Log.create({ service: "server" })
 

+ 14 - 16
packages/opencode/src/server/instance/experimental.ts → packages/opencode/src/server/routes/instance/experimental.ts

@@ -1,22 +1,21 @@
 import { Hono } from "hono"
 import { describeRoute, validator, resolver } from "hono-openapi"
 import z from "zod"
-import { ProviderID, ModelID } from "../../provider/schema"
-import { ToolRegistry } from "../../tool"
-import { Worktree } from "../../worktree"
-import { Instance } from "../../project/instance"
-import { Project } from "../../project"
-import { MCP } from "../../mcp"
-import { Session } from "../../session"
-import { Config } from "../../config"
-import { ConsoleState } from "../../config/console-state"
-import { Account } from "../../account/account"
-import { AccountID, OrgID } from "../../account/schema"
-import { AppRuntime } from "../../effect/app-runtime"
-import { errors } from "../error"
-import { lazy } from "../../util/lazy"
+import { ProviderID, ModelID } from "@/provider/schema"
+import { ToolRegistry } from "@/tool"
+import { Worktree } from "@/worktree"
+import { Instance } from "@/project/instance"
+import { Project } from "@/project"
+import { MCP } from "@/mcp"
+import { Session } from "@/session"
+import { Config } from "@/config"
+import { ConsoleState } from "@/config/console-state"
+import { Account } from "@/account/account"
+import { AccountID, OrgID } from "@/account/schema"
+import { AppRuntime } from "@/effect/app-runtime"
+import { errors } from "../../error"
+import { lazy } from "@/util/lazy"
 import { Effect, Option } from "effect"
-import { WorkspaceRoutes } from "./workspace"
 import { Agent } from "@/agent/agent"
 
 const ConsoleOrgOption = z.object({
@@ -231,7 +230,6 @@ export const ExperimentalRoutes = lazy(() =>
         )
       },
     )
-    .route("/workspace", WorkspaceRoutes())
     .post(
       "/worktree",
       describeRoute({

+ 6 - 6
packages/opencode/src/server/instance/file.ts → packages/opencode/src/server/routes/instance/file.ts

@@ -2,12 +2,12 @@ import { Hono } from "hono"
 import { describeRoute, validator, resolver } from "hono-openapi"
 import { Effect } from "effect"
 import z from "zod"
-import { AppRuntime } from "../../effect/app-runtime"
-import { File } from "../../file"
-import { Ripgrep } from "../../file/ripgrep"
-import { LSP } from "../../lsp"
-import { Instance } from "../../project/instance"
-import { lazy } from "../../util/lazy"
+import { AppRuntime } from "@/effect/app-runtime"
+import { File } from "@/file"
+import { Ripgrep } from "@/file/ripgrep"
+import { LSP } from "@/lsp"
+import { Instance } from "@/project/instance"
+import { lazy } from "@/util/lazy"
 
 export const FileRoutes = lazy(() =>
   new Hono()

+ 0 - 0
packages/opencode/src/server/instance/httpapi/config.ts → packages/opencode/src/server/routes/instance/httpapi/config.ts


+ 0 - 0
packages/opencode/src/server/instance/httpapi/permission.ts → packages/opencode/src/server/routes/instance/httpapi/permission.ts


+ 0 - 0
packages/opencode/src/server/instance/httpapi/project.ts → packages/opencode/src/server/routes/instance/httpapi/project.ts


+ 0 - 0
packages/opencode/src/server/instance/httpapi/provider.ts → packages/opencode/src/server/routes/instance/httpapi/provider.ts


+ 0 - 0
packages/opencode/src/server/instance/httpapi/question.ts → packages/opencode/src/server/routes/instance/httpapi/question.ts


+ 0 - 0
packages/opencode/src/server/instance/httpapi/server.ts → packages/opencode/src/server/routes/instance/httpapi/server.ts


+ 9 - 10
packages/opencode/src/server/instance/index.ts → packages/opencode/src/server/routes/instance/index.ts

@@ -3,15 +3,15 @@ import { Hono } from "hono"
 import type { UpgradeWebSocket } from "hono/ws"
 import { Context, Effect } from "effect"
 import z from "zod"
-import { Format } from "../../format"
+import { Format } from "@/format"
 import { TuiRoutes } from "./tui"
-import { Instance } from "../../project/instance"
-import { Vcs } from "../../project"
-import { Agent } from "../../agent/agent"
-import { Skill } from "../../skill"
-import { Global } from "../../global"
-import { LSP } from "../../lsp"
-import { Command } from "../../command"
+import { Instance } from "@/project/instance"
+import { Vcs } from "@/project"
+import { Agent } from "@/agent/agent"
+import { Skill } from "@/skill"
+import { Global } from "@/global"
+import { LSP } from "@/lsp"
+import { Command } from "@/command"
 import { QuestionRoutes } from "./question"
 import { PermissionRoutes } from "./permission"
 import { Flag } from "@/flag/flag"
@@ -26,11 +26,10 @@ import { ExperimentalRoutes } from "./experimental"
 import { ProviderRoutes } from "./provider"
 import { EventRoutes } from "./event"
 import { SyncRoutes } from "./sync"
-import { WorkspaceRouterMiddleware } from "./middleware"
 import { AppRuntime } from "@/effect/app-runtime"
 
 export const InstanceRoutes = (upgrade: UpgradeWebSocket): Hono => {
-  const app = new Hono().use(WorkspaceRouterMiddleware(upgrade))
+  const app = new Hono()
 
   if (Flag.OPENCODE_EXPERIMENTAL_HTTPAPI) {
     const handler = ExperimentalHttpApiServer.webHandler().handler

+ 6 - 6
packages/opencode/src/server/instance/mcp.ts → packages/opencode/src/server/routes/instance/mcp.ts

@@ -1,12 +1,12 @@
 import { Hono } from "hono"
 import { describeRoute, validator, resolver } from "hono-openapi"
 import z from "zod"
-import { MCP } from "../../mcp"
-import { Config } from "../../config"
-import { ConfigMCP } from "../../config/mcp"
-import { AppRuntime } from "../../effect/app-runtime"
-import { errors } from "../error"
-import { lazy } from "../../util/lazy"
+import { MCP } from "@/mcp"
+import { Config } from "@/config"
+import { ConfigMCP } from "@/config/mcp"
+import { AppRuntime } from "@/effect/app-runtime"
+import { errors } from "../../error"
+import { lazy } from "@/util/lazy"
 import { Effect } from "effect"
 
 export const McpRoutes = lazy(() =>

+ 2 - 2
packages/opencode/src/server/instance/permission.ts → packages/opencode/src/server/routes/instance/permission.ts

@@ -4,8 +4,8 @@ import z from "zod"
 import { AppRuntime } from "@/effect/app-runtime"
 import { Permission } from "@/permission"
 import { PermissionID } from "@/permission/schema"
-import { errors } from "../error"
-import { lazy } from "../../util/lazy"
+import { errors } from "../../error"
+import { lazy } from "@/util/lazy"
 
 export const PermissionRoutes = lazy(() =>
   new Hono()

+ 6 - 6
packages/opencode/src/server/instance/project.ts → packages/opencode/src/server/routes/instance/project.ts

@@ -1,13 +1,13 @@
 import { Hono } from "hono"
 import { describeRoute, validator } from "hono-openapi"
 import { resolver } from "hono-openapi"
-import { Instance } from "../../project/instance"
-import { Project } from "../../project"
+import { Instance } from "@/project/instance"
+import { Project } from "@/project"
 import z from "zod"
-import { ProjectID } from "../../project/schema"
-import { errors } from "../error"
-import { lazy } from "../../util/lazy"
-import { InstanceBootstrap } from "../../project/bootstrap"
+import { ProjectID } from "@/project/schema"
+import { errors } from "../../error"
+import { lazy } from "@/util/lazy"
+import { InstanceBootstrap } from "@/project/bootstrap"
 import { AppRuntime } from "@/effect/app-runtime"
 
 export const ProjectRoutes = lazy(() =>

+ 8 - 8
packages/opencode/src/server/instance/provider.ts → packages/opencode/src/server/routes/instance/provider.ts

@@ -1,15 +1,15 @@
 import { Hono } from "hono"
 import { describeRoute, validator, resolver } from "hono-openapi"
 import z from "zod"
-import { Config } from "../../config"
-import { Provider } from "../../provider"
-import { ModelsDev } from "../../provider"
-import { ProviderAuth } from "../../provider"
-import { ProviderID } from "../../provider/schema"
-import { AppRuntime } from "../../effect/app-runtime"
+import { Config } from "@/config"
+import { Provider } from "@/provider"
+import { ModelsDev } from "@/provider"
+import { ProviderAuth } from "@/provider"
+import { ProviderID } from "@/provider/schema"
+import { AppRuntime } from "@/effect/app-runtime"
 import { mapValues } from "remeda"
-import { errors } from "../error"
-import { lazy } from "../../util/lazy"
+import { errors } from "../../error"
+import { lazy } from "@/util/lazy"
 import { Effect } from "effect"
 
 export const ProviderRoutes = lazy(() =>

+ 2 - 2
packages/opencode/src/server/instance/pty.ts → packages/opencode/src/server/routes/instance/pty.ts

@@ -6,8 +6,8 @@ import z from "zod"
 import { AppRuntime } from "@/effect/app-runtime"
 import { Pty } from "@/pty"
 import { PtyID } from "@/pty/schema"
-import { NotFoundError } from "../../storage"
-import { errors } from "../error"
+import { NotFoundError } from "@/storage"
+import { errors } from "../../error"
 
 export function PtyRoutes(upgradeWebSocket: UpgradeWebSocket) {
   return new Hono()

+ 3 - 3
packages/opencode/src/server/instance/question.ts → packages/opencode/src/server/routes/instance/question.ts

@@ -2,11 +2,11 @@ import { Hono } from "hono"
 import { describeRoute, validator } from "hono-openapi"
 import { resolver } from "hono-openapi"
 import { QuestionID } from "@/question/schema"
-import { Question } from "../../question"
+import { Question } from "@/question"
 import { AppRuntime } from "@/effect/app-runtime"
 import z from "zod"
-import { errors } from "../error"
-import { lazy } from "../../util/lazy"
+import { errors } from "../../error"
+import { lazy } from "@/util/lazy"
 
 const Reply = z.object({
   answers: Question.Answer.zod

+ 13 - 13
packages/opencode/src/server/instance/session.ts → packages/opencode/src/server/routes/instance/session.ts

@@ -3,28 +3,28 @@ import { stream } from "hono/streaming"
 import { describeRoute, validator, resolver } from "hono-openapi"
 import { SessionID, MessageID, PartID } from "@/session/schema"
 import z from "zod"
-import { Session } from "../../session"
-import { MessageV2 } from "../../session/message-v2"
-import { SessionPrompt } from "../../session/prompt"
+import { Session } from "@/session"
+import { MessageV2 } from "@/session/message-v2"
+import { SessionPrompt } from "@/session/prompt"
 import { SessionRunState } from "@/session/run-state"
-import { SessionCompaction } from "../../session/compaction"
-import { SessionRevert } from "../../session/revert"
+import { SessionCompaction } from "@/session/compaction"
+import { SessionRevert } from "@/session/revert"
 import { SessionShare } from "@/share"
 import { SessionStatus } from "@/session/status"
 import { SessionSummary } from "@/session/summary"
-import { Todo } from "../../session/todo"
+import { Todo } from "@/session/todo"
 import { Effect } from "effect"
-import { AppRuntime } from "../../effect/app-runtime"
-import { Agent } from "../../agent/agent"
+import { AppRuntime } from "@/effect/app-runtime"
+import { Agent } from "@/agent/agent"
 import { Snapshot } from "@/snapshot"
-import { Command } from "../../command"
-import { Log } from "../../util"
+import { Command } from "@/command"
+import { Log } from "@/util"
 import { Permission } from "@/permission"
 import { PermissionID } from "@/permission/schema"
 import { ModelID, ProviderID } from "@/provider/schema"
-import { errors } from "../error"
-import { lazy } from "../../util/lazy"
-import { Bus } from "../../bus"
+import { errors } from "../../error"
+import { lazy } from "@/util/lazy"
+import { Bus } from "@/bus"
 import { NamedError } from "@opencode-ai/shared/util/error"
 import { jsonRequest } from "./trace"
 

+ 1 - 1
packages/opencode/src/server/instance/sync.ts → packages/opencode/src/server/routes/instance/sync.ts

@@ -6,7 +6,7 @@ import { Database, asc, and, not, or, lte, eq } from "@/storage"
 import { EventTable } from "@/sync/event.sql"
 import { lazy } from "@/util/lazy"
 import { Log } from "@/util"
-import { errors } from "../error"
+import { errors } from "../../error"
 
 const ReplayEvent = z.object({
   id: z.string(),

+ 1 - 1
packages/opencode/src/server/instance/trace.ts → packages/opencode/src/server/routes/instance/trace.ts

@@ -1,6 +1,6 @@
 import type { Context } from "hono"
 import { Effect } from "effect"
-import { AppRuntime } from "../../effect/app-runtime"
+import { AppRuntime } from "@/effect/app-runtime"
 
 type AppEnv = Parameters<typeof AppRuntime.runPromise>[0] extends Effect.Effect<any, any, infer R> ? R : never
 

+ 5 - 5
packages/opencode/src/server/instance/tui.ts → packages/opencode/src/server/routes/instance/tui.ts

@@ -1,13 +1,13 @@
 import { Hono, type Context } from "hono"
 import { describeRoute, validator, resolver } from "hono-openapi"
 import z from "zod"
-import { Bus } from "../../bus"
-import { Session } from "../../session"
+import { Bus } from "@/bus"
+import { Session } from "@/session"
 import { TuiEvent } from "@/cli/cmd/tui/event"
 import { AppRuntime } from "@/effect/app-runtime"
-import { AsyncQueue } from "../../util/queue"
-import { errors } from "../error"
-import { lazy } from "../../util/lazy"
+import { AsyncQueue } from "@/util/queue"
+import { errors } from "../../error"
+import { lazy } from "@/util/lazy"
 
 const TuiRequest = z.object({
   path: z.string(),

+ 0 - 0
packages/opencode/src/server/ui/index.ts → packages/opencode/src/server/routes/ui.ts


+ 53 - 17
packages/opencode/src/server/server.ts

@@ -1,16 +1,25 @@
 import { generateSpecs } from "hono-openapi"
 import { Hono } from "hono"
+import type { MiddlewareHandler } from "hono"
 import { adapter } from "#hono"
-import { MDNS } from "./mdns"
 import { lazy } from "@/util/lazy"
+import { Log } from "@/util"
+import { Flag } from "@/flag/flag"
+import { Instance } from "@/project/instance"
+import { InstanceBootstrap } from "@/project/bootstrap"
+import { AppRuntime } from "@/effect/app-runtime"
+import { AppFileSystem } from "@opencode-ai/shared/filesystem"
+import { WorkspaceID } from "@/control-plane/schema"
+import { WorkspaceContext } from "@/control-plane/workspace-context"
+import { MDNS } from "./mdns"
 import { AuthMiddleware, CompressionMiddleware, CorsMiddleware, ErrorMiddleware, LoggerMiddleware } from "./middleware"
 import { FenceMiddleware } from "./fence"
-import { InstanceRoutes } from "./instance"
 import { initProjectors } from "./projectors"
-import { Log } from "@/util"
-import { Flag } from "@/flag/flag"
-import { ControlPlaneRoutes } from "./control"
-import { UIRoutes } from "./ui"
+import { InstanceRoutes } from "./routes/instance"
+import { ControlPlaneRoutes } from "./routes/control"
+import { UIRoutes } from "./routes/ui"
+import { GlobalRoutes } from "./routes/global"
+import { WorkspaceRouterMiddleware } from "./workspace"
 
 // @ts-ignore This global is needed to prevent ai-sdk from logging warnings to stdout https://github.com/vercel/ai/blob/2dc67e0ef538307f21368db32d5a12345d98831b/packages/ai/src/logger/log-warnings.ts#L85
 globalThis.AI_SDK_LOG_WARNINGS = false
@@ -30,18 +39,48 @@ export const Default = lazy(() => create({}))
 
 function create(opts: { cors?: string[] }) {
   const app = new Hono()
+    .onError(ErrorMiddleware)
+    .use(AuthMiddleware)
+    .use(LoggerMiddleware)
+    .use(CompressionMiddleware)
+    .use(CorsMiddleware(opts))
+    .route("/global", GlobalRoutes())
+
   const runtime = adapter.create(app)
 
+  function InstanceMiddleware(workspaceID?: WorkspaceID): MiddlewareHandler {
+    return async (c, next) => {
+      const raw = c.req.query("directory") || c.req.header("x-opencode-directory") || process.cwd()
+      const directory = AppFileSystem.resolve(
+        (() => {
+          try {
+            return decodeURIComponent(raw)
+          } catch {
+            return raw
+          }
+        })(),
+      )
+
+      return WorkspaceContext.provide({
+        workspaceID,
+        async fn() {
+          return Instance.provide({
+            directory,
+            init: () => AppRuntime.runPromise(InstanceBootstrap),
+            async fn() {
+              return next()
+            },
+          })
+        },
+      })
+    }
+  }
+
   if (Flag.OPENCODE_WORKSPACE_ID) {
     return {
       app: app
-        .onError(ErrorMiddleware)
-        .use(AuthMiddleware)
-        .use(LoggerMiddleware)
-        .use(CompressionMiddleware)
-        .use(CorsMiddleware(opts))
+        .use(InstanceMiddleware(Flag.OPENCODE_WORKSPACE_ID ? WorkspaceID.make(Flag.OPENCODE_WORKSPACE_ID) : undefined))
         .use(FenceMiddleware)
-        .route("/", ControlPlaneRoutes())
         .route("/", InstanceRoutes(runtime.upgradeWebSocket)),
       runtime,
     }
@@ -49,12 +88,9 @@ function create(opts: { cors?: string[] }) {
 
   return {
     app: app
-      .onError(ErrorMiddleware)
-      .use(AuthMiddleware)
-      .use(LoggerMiddleware)
-      .use(CompressionMiddleware)
-      .use(CorsMiddleware(opts))
+      .use(InstanceMiddleware())
       .route("/", ControlPlaneRoutes())
+      .use(WorkspaceRouterMiddleware(runtime.upgradeWebSocket))
       .route("/", InstanceRoutes(runtime.upgradeWebSocket))
       .route("/", UIRoutes()),
     runtime,

+ 5 - 38
packages/opencode/src/server/instance/middleware.ts → packages/opencode/src/server/workspace.ts

@@ -2,17 +2,16 @@ import type { MiddlewareHandler } from "hono"
 import type { UpgradeWebSocket } from "hono/ws"
 import { getAdaptor } from "@/control-plane/adaptors"
 import { WorkspaceID } from "@/control-plane/schema"
+import { WorkspaceContext } from "@/control-plane/workspace-context"
 import { Workspace } from "@/control-plane/workspace"
-import { ServerProxy } from "../proxy"
-import { Instance } from "@/project/instance"
-import { InstanceBootstrap } from "@/project/bootstrap"
 import { Flag } from "@/flag/flag"
+import { InstanceBootstrap } from "@/project/bootstrap"
+import { Instance } from "@/project/instance"
 import { Session } from "@/session"
 import { SessionID } from "@/session/schema"
-import { WorkspaceContext } from "@/control-plane/workspace-context"
 import { AppRuntime } from "@/effect/app-runtime"
 import { Log } from "@/util"
-import { AppFileSystem } from "@opencode-ai/shared/filesystem"
+import { ServerProxy } from "./proxy"
 
 type Rule = { method?: string; path: string; exact?: boolean; action: "local" | "forward" }
 
@@ -51,45 +50,13 @@ export function WorkspaceRouterMiddleware(upgrade: UpgradeWebSocket): Middleware
   const log = Log.create({ service: "workspace-router" })
 
   return async (c, next) => {
-    const raw = c.req.query("directory") || c.req.header("x-opencode-directory") || process.cwd()
-    const directory = AppFileSystem.resolve(
-      (() => {
-        try {
-          return decodeURIComponent(raw)
-        } catch {
-          return raw
-        }
-      })(),
-    )
-
     const url = new URL(c.req.url)
 
     const sessionWorkspaceID = await getSessionWorkspace(url)
     const workspaceID = sessionWorkspaceID || url.searchParams.get("workspace")
 
     if (!workspaceID || url.pathname.startsWith("/console") || Flag.OPENCODE_WORKSPACE_ID) {
-      if (Flag.OPENCODE_WORKSPACE_ID) {
-        return WorkspaceContext.provide({
-          workspaceID: WorkspaceID.make(Flag.OPENCODE_WORKSPACE_ID),
-          async fn() {
-            return Instance.provide({
-              directory,
-              init: () => AppRuntime.runPromise(InstanceBootstrap),
-              async fn() {
-                return next()
-              },
-            })
-          },
-        })
-      }
-
-      return Instance.provide({
-        directory,
-        init: () => AppRuntime.runPromise(InstanceBootstrap),
-        async fn() {
-          return next()
-        },
-      })
+      return next()
     }
 
     const workspace = await Workspace.get(WorkspaceID.make(workspaceID))

+ 0 - 13
packages/opencode/test/server/session-messages.test.ts

@@ -165,16 +165,3 @@ describe("session messages endpoint", () => {
     )
   })
 })
-
-describe("session.prompt_async error handling", () => {
-  test("prompt_async route has error handler for detached prompt call", async () => {
-    const src = await Bun.file(new URL("../../src/server/instance/session.ts", import.meta.url)).text()
-    const start = src.indexOf('"/:sessionID/prompt_async"')
-    const end = src.indexOf('"/:sessionID/command"', start)
-    expect(start).toBeGreaterThan(-1)
-    expect(end).toBeGreaterThan(start)
-    const route = src.slice(start, end)
-    expect(route).toContain(".catch(")
-    expect(route).toContain("Bus.publish(Session.Event.Error")
-  })
-})

Різницю між файлами не показано, бо вона завелика
+ 294 - 272
packages/sdk/js/src/v2/gen/sdk.gen.ts


+ 181 - 181
packages/sdk/js/src/v2/gen/types.gen.ts

@@ -1706,6 +1706,16 @@ export type WellKnownAuth = {
 
 export type Auth = OAuth | ApiAuth | WellKnownAuth
 
+export type Workspace = {
+  id: string
+  type: string
+  name: string
+  branch: string | null
+  directory: string | null
+  extra: unknown | null
+  projectID: string
+}
+
 export type NotFoundError = {
   name: "NotFoundError"
   data: {
@@ -1808,16 +1818,6 @@ export type ToolListItem = {
 
 export type ToolList = Array<ToolListItem>
 
-export type Workspace = {
-  id: string
-  type: string
-  name: string
-  branch: string | null
-  directory: string | null
-  extra: unknown | null
-  projectID: string
-}
-
 export type Worktree = {
   name: string
   branch: string
@@ -2394,6 +2394,177 @@ export type AppLogResponses = {
 
 export type AppLogResponse = AppLogResponses[keyof AppLogResponses]
 
+export type ExperimentalWorkspaceAdaptorListData = {
+  body?: never
+  path?: never
+  query?: {
+    directory?: string
+    workspace?: string
+  }
+  url: "/experimental/workspace/adaptor"
+}
+
+export type ExperimentalWorkspaceAdaptorListResponses = {
+  /**
+   * Workspace adaptors
+   */
+  200: Array<{
+    type: string
+    name: string
+    description: string
+  }>
+}
+
+export type ExperimentalWorkspaceAdaptorListResponse =
+  ExperimentalWorkspaceAdaptorListResponses[keyof ExperimentalWorkspaceAdaptorListResponses]
+
+export type ExperimentalWorkspaceListData = {
+  body?: never
+  path?: never
+  query?: {
+    directory?: string
+    workspace?: string
+  }
+  url: "/experimental/workspace"
+}
+
+export type ExperimentalWorkspaceListResponses = {
+  /**
+   * Workspaces
+   */
+  200: Array<Workspace>
+}
+
+export type ExperimentalWorkspaceListResponse =
+  ExperimentalWorkspaceListResponses[keyof ExperimentalWorkspaceListResponses]
+
+export type ExperimentalWorkspaceCreateData = {
+  body?: {
+    id?: string
+    type: string
+    branch: string | null
+    extra: unknown | null
+  }
+  path?: never
+  query?: {
+    directory?: string
+    workspace?: string
+  }
+  url: "/experimental/workspace"
+}
+
+export type ExperimentalWorkspaceCreateErrors = {
+  /**
+   * Bad request
+   */
+  400: BadRequestError
+}
+
+export type ExperimentalWorkspaceCreateError =
+  ExperimentalWorkspaceCreateErrors[keyof ExperimentalWorkspaceCreateErrors]
+
+export type ExperimentalWorkspaceCreateResponses = {
+  /**
+   * Workspace created
+   */
+  200: Workspace
+}
+
+export type ExperimentalWorkspaceCreateResponse =
+  ExperimentalWorkspaceCreateResponses[keyof ExperimentalWorkspaceCreateResponses]
+
+export type ExperimentalWorkspaceStatusData = {
+  body?: never
+  path?: never
+  query?: {
+    directory?: string
+    workspace?: string
+  }
+  url: "/experimental/workspace/status"
+}
+
+export type ExperimentalWorkspaceStatusResponses = {
+  /**
+   * Workspace status
+   */
+  200: Array<{
+    workspaceID: string
+    status: "connected" | "connecting" | "disconnected" | "error"
+    error?: string
+  }>
+}
+
+export type ExperimentalWorkspaceStatusResponse =
+  ExperimentalWorkspaceStatusResponses[keyof ExperimentalWorkspaceStatusResponses]
+
+export type ExperimentalWorkspaceRemoveData = {
+  body?: never
+  path: {
+    id: string
+  }
+  query?: {
+    directory?: string
+    workspace?: string
+  }
+  url: "/experimental/workspace/{id}"
+}
+
+export type ExperimentalWorkspaceRemoveErrors = {
+  /**
+   * Bad request
+   */
+  400: BadRequestError
+}
+
+export type ExperimentalWorkspaceRemoveError =
+  ExperimentalWorkspaceRemoveErrors[keyof ExperimentalWorkspaceRemoveErrors]
+
+export type ExperimentalWorkspaceRemoveResponses = {
+  /**
+   * Workspace removed
+   */
+  200: Workspace
+}
+
+export type ExperimentalWorkspaceRemoveResponse =
+  ExperimentalWorkspaceRemoveResponses[keyof ExperimentalWorkspaceRemoveResponses]
+
+export type ExperimentalWorkspaceSessionRestoreData = {
+  body?: {
+    sessionID: string
+  }
+  path: {
+    id: string
+  }
+  query?: {
+    directory?: string
+    workspace?: string
+  }
+  url: "/experimental/workspace/{id}/session-restore"
+}
+
+export type ExperimentalWorkspaceSessionRestoreErrors = {
+  /**
+   * Bad request
+   */
+  400: BadRequestError
+}
+
+export type ExperimentalWorkspaceSessionRestoreError =
+  ExperimentalWorkspaceSessionRestoreErrors[keyof ExperimentalWorkspaceSessionRestoreErrors]
+
+export type ExperimentalWorkspaceSessionRestoreResponses = {
+  /**
+   * Session replay started
+   */
+  200: {
+    total: number
+  }
+}
+
+export type ExperimentalWorkspaceSessionRestoreResponse =
+  ExperimentalWorkspaceSessionRestoreResponses[keyof ExperimentalWorkspaceSessionRestoreResponses]
+
 export type ProjectListData = {
   body?: never
   path?: never
@@ -2883,177 +3054,6 @@ export type ToolListResponses = {
 
 export type ToolListResponse = ToolListResponses[keyof ToolListResponses]
 
-export type ExperimentalWorkspaceAdaptorListData = {
-  body?: never
-  path?: never
-  query?: {
-    directory?: string
-    workspace?: string
-  }
-  url: "/experimental/workspace/adaptor"
-}
-
-export type ExperimentalWorkspaceAdaptorListResponses = {
-  /**
-   * Workspace adaptors
-   */
-  200: Array<{
-    type: string
-    name: string
-    description: string
-  }>
-}
-
-export type ExperimentalWorkspaceAdaptorListResponse =
-  ExperimentalWorkspaceAdaptorListResponses[keyof ExperimentalWorkspaceAdaptorListResponses]
-
-export type ExperimentalWorkspaceListData = {
-  body?: never
-  path?: never
-  query?: {
-    directory?: string
-    workspace?: string
-  }
-  url: "/experimental/workspace"
-}
-
-export type ExperimentalWorkspaceListResponses = {
-  /**
-   * Workspaces
-   */
-  200: Array<Workspace>
-}
-
-export type ExperimentalWorkspaceListResponse =
-  ExperimentalWorkspaceListResponses[keyof ExperimentalWorkspaceListResponses]
-
-export type ExperimentalWorkspaceCreateData = {
-  body?: {
-    id?: string
-    type: string
-    branch: string | null
-    extra: unknown | null
-  }
-  path?: never
-  query?: {
-    directory?: string
-    workspace?: string
-  }
-  url: "/experimental/workspace"
-}
-
-export type ExperimentalWorkspaceCreateErrors = {
-  /**
-   * Bad request
-   */
-  400: BadRequestError
-}
-
-export type ExperimentalWorkspaceCreateError =
-  ExperimentalWorkspaceCreateErrors[keyof ExperimentalWorkspaceCreateErrors]
-
-export type ExperimentalWorkspaceCreateResponses = {
-  /**
-   * Workspace created
-   */
-  200: Workspace
-}
-
-export type ExperimentalWorkspaceCreateResponse =
-  ExperimentalWorkspaceCreateResponses[keyof ExperimentalWorkspaceCreateResponses]
-
-export type ExperimentalWorkspaceStatusData = {
-  body?: never
-  path?: never
-  query?: {
-    directory?: string
-    workspace?: string
-  }
-  url: "/experimental/workspace/status"
-}
-
-export type ExperimentalWorkspaceStatusResponses = {
-  /**
-   * Workspace status
-   */
-  200: Array<{
-    workspaceID: string
-    status: "connected" | "connecting" | "disconnected" | "error"
-    error?: string
-  }>
-}
-
-export type ExperimentalWorkspaceStatusResponse =
-  ExperimentalWorkspaceStatusResponses[keyof ExperimentalWorkspaceStatusResponses]
-
-export type ExperimentalWorkspaceRemoveData = {
-  body?: never
-  path: {
-    id: string
-  }
-  query?: {
-    directory?: string
-    workspace?: string
-  }
-  url: "/experimental/workspace/{id}"
-}
-
-export type ExperimentalWorkspaceRemoveErrors = {
-  /**
-   * Bad request
-   */
-  400: BadRequestError
-}
-
-export type ExperimentalWorkspaceRemoveError =
-  ExperimentalWorkspaceRemoveErrors[keyof ExperimentalWorkspaceRemoveErrors]
-
-export type ExperimentalWorkspaceRemoveResponses = {
-  /**
-   * Workspace removed
-   */
-  200: Workspace
-}
-
-export type ExperimentalWorkspaceRemoveResponse =
-  ExperimentalWorkspaceRemoveResponses[keyof ExperimentalWorkspaceRemoveResponses]
-
-export type ExperimentalWorkspaceSessionRestoreData = {
-  body?: {
-    sessionID: string
-  }
-  path: {
-    id: string
-  }
-  query?: {
-    directory?: string
-    workspace?: string
-  }
-  url: "/experimental/workspace/{id}/session-restore"
-}
-
-export type ExperimentalWorkspaceSessionRestoreErrors = {
-  /**
-   * Bad request
-   */
-  400: BadRequestError
-}
-
-export type ExperimentalWorkspaceSessionRestoreError =
-  ExperimentalWorkspaceSessionRestoreErrors[keyof ExperimentalWorkspaceSessionRestoreErrors]
-
-export type ExperimentalWorkspaceSessionRestoreResponses = {
-  /**
-   * Session replay started
-   */
-  200: {
-    total: number
-  }
-}
-
-export type ExperimentalWorkspaceSessionRestoreResponse =
-  ExperimentalWorkspaceSessionRestoreResponses[keyof ExperimentalWorkspaceSessionRestoreResponses]
-
 export type WorktreeRemoveData = {
   body?: WorktreeRemoveInput
   path?: never

Різницю між файлами не показано, бо вона завелика
+ 370 - 316
packages/sdk/openapi.json


Деякі файли не було показано, через те що забагато файлів було змінено