Parcourir la source

fix(opencode): fix full session fork (#26811)

Aiden Cline il y a 3 mois
Parent
commit
518264fcd9

+ 3 - 3
packages/opencode/src/project/instance-store.ts

@@ -86,7 +86,7 @@ export const layer: Layer.Layer<Service, never, Project.Service | InstanceBootst
       )
       )
 
 
     const disposeContext = Effect.fn("InstanceStore.disposeContext")(function* (ctx: InstanceContext) {
     const disposeContext = Effect.fn("InstanceStore.disposeContext")(function* (ctx: InstanceContext) {
-      yield* Effect.logInfo("disposing instance", { directory: ctx.directory })
+      yield* Effect.logInfo("disposing instance").pipe(Effect.annotateLogs("directory", ctx.directory))
       yield* Effect.promise(() => runDisposers(ctx.directory))
       yield* Effect.promise(() => runDisposers(ctx.directory))
       yield* emitDisposed({ directory: ctx.directory, project: ctx.project.id })
       yield* emitDisposed({ directory: ctx.directory, project: ctx.project.id })
     })
     })
@@ -109,7 +109,7 @@ export const layer: Layer.Layer<Service, never, Project.Service | InstanceBootst
           const entry: Entry = { deferred: Deferred.makeUnsafe<InstanceContext>() }
           const entry: Entry = { deferred: Deferred.makeUnsafe<InstanceContext>() }
           cache.set(directory, entry)
           cache.set(directory, entry)
           yield* Effect.gen(function* () {
           yield* Effect.gen(function* () {
-            yield* Effect.logInfo("creating instance", { directory })
+            yield* Effect.logInfo("creating instance").pipe(Effect.annotateLogs("directory", directory))
             yield* completeLoad(directory, input, entry)
             yield* completeLoad(directory, input, entry)
           }).pipe(Effect.forkIn(scope, { startImmediately: true }))
           }).pipe(Effect.forkIn(scope, { startImmediately: true }))
           return yield* restore(Deferred.await(entry.deferred))
           return yield* restore(Deferred.await(entry.deferred))
@@ -125,7 +125,7 @@ export const layer: Layer.Layer<Service, never, Project.Service | InstanceBootst
           const entry: Entry = { deferred: Deferred.makeUnsafe<InstanceContext>() }
           const entry: Entry = { deferred: Deferred.makeUnsafe<InstanceContext>() }
           cache.set(directory, entry)
           cache.set(directory, entry)
           yield* Effect.gen(function* () {
           yield* Effect.gen(function* () {
-            yield* Effect.logInfo("reloading instance", { directory })
+            yield* Effect.logInfo("reloading instance").pipe(Effect.annotateLogs("directory", directory))
             if (previous) {
             if (previous) {
               yield* Deferred.await(previous.deferred).pipe(Effect.ignore)
               yield* Deferred.await(previous.deferred).pipe(Effect.ignore)
               yield* Effect.promise(() => runDisposers(directory))
               yield* Effect.promise(() => runDisposers(directory))

+ 2 - 2
packages/opencode/src/server/routes/instance/httpapi/groups/session.ts

@@ -236,9 +236,9 @@ export const SessionApi = HttpApi.make("session")
         HttpApiEndpoint.post("fork", SessionPaths.fork, {
         HttpApiEndpoint.post("fork", SessionPaths.fork, {
           params: { sessionID: SessionID },
           params: { sessionID: SessionID },
           query: WorkspaceRoutingQuery,
           query: WorkspaceRoutingQuery,
-          payload: ForkPayload,
+          payload: Schema.optional(ForkPayload),
           success: described(Session.Info, "200"),
           success: described(Session.Info, "200"),
-          error: ApiNotFoundError,
+          error: [HttpApiError.BadRequest, ApiNotFoundError],
         }).annotateMerge(
         }).annotateMerge(
           OpenApi.annotations({
           OpenApi.annotations({
             identifier: "session.fork",
             identifier: "session.fork",

+ 20 - 3
packages/opencode/src/server/routes/instance/httpapi/handlers/session.ts

@@ -187,13 +187,30 @@ export const sessionHandlers = HttpApiBuilder.group(InstanceHttpApi, "session",
 
 
     const fork = Effect.fn("SessionHttpApi.fork")(function* (ctx: {
     const fork = Effect.fn("SessionHttpApi.fork")(function* (ctx: {
       params: { sessionID: SessionID }
       params: { sessionID: SessionID }
-      payload: typeof ForkPayload.Type
+      payload?: typeof ForkPayload.Type
     }) {
     }) {
       return yield* SessionError.mapStorageNotFound(
       return yield* SessionError.mapStorageNotFound(
-        session.fork({ sessionID: ctx.params.sessionID, messageID: ctx.payload.messageID }),
+        session.fork({ sessionID: ctx.params.sessionID, messageID: ctx.payload?.messageID }),
       )
       )
     })
     })
 
 
+    const forkRaw = Effect.fn("SessionHttpApi.forkRaw")(function* (ctx: {
+      params: { sessionID: SessionID }
+      request: HttpServerRequest.HttpServerRequest
+    }) {
+      const body = yield* Effect.orDie(ctx.request.text)
+      if (body.trim().length === 0) return yield* fork({ params: ctx.params })
+
+      const json = yield* Effect.try({
+        try: () => JSON.parse(body) as unknown,
+        catch: () => new HttpApiError.BadRequest({}),
+      })
+      const payload = yield* Schema.decodeUnknownEffect(ForkPayload)(json).pipe(
+        Effect.mapError(() => new HttpApiError.BadRequest({})),
+      )
+      return yield* fork({ params: ctx.params, payload })
+    })
+
     const abort = Effect.fn("SessionHttpApi.abort")(function* (ctx: { params: { sessionID: SessionID } }) {
     const abort = Effect.fn("SessionHttpApi.abort")(function* (ctx: { params: { sessionID: SessionID } }) {
       yield* promptSvc.cancel(ctx.params.sessionID)
       yield* promptSvc.cancel(ctx.params.sessionID)
       return true
       return true
@@ -373,7 +390,7 @@ export const sessionHandlers = HttpApiBuilder.group(InstanceHttpApi, "session",
       .handleRaw("create", createRaw)
       .handleRaw("create", createRaw)
       .handle("remove", remove)
       .handle("remove", remove)
       .handle("update", update)
       .handle("update", update)
-      .handle("fork", fork)
+      .handleRaw("fork", forkRaw)
       .handle("abort", abort)
       .handle("abort", abort)
       .handle("init", init)
       .handle("init", init)
       .handle("share", share)
       .handle("share", share)

+ 0 - 1
packages/opencode/test/server/httpapi-session.test.ts

@@ -356,7 +356,6 @@ describe("session HttpApi", () => {
         const forked = yield* requestJson<Session.Info>(pathFor(SessionPaths.fork, { sessionID: created.id }), {
         const forked = yield* requestJson<Session.Info>(pathFor(SessionPaths.fork, { sessionID: created.id }), {
           method: "POST",
           method: "POST",
           headers,
           headers,
-          body: JSON.stringify({}),
         })
         })
         expect(forked.id).not.toBe(created.id)
         expect(forked.id).not.toBe(created.id)