diff --git a/packages/app/src/session/requests/model.ts b/packages/app/src/session/requests/model.ts
index 844223d20458..48d227dd60cb 100644
--- a/packages/app/src/session/requests/model.ts
+++ b/packages/app/src/session/requests/model.ts
@@ -19,6 +19,21 @@ export function createSessionRequestModel() {
const data = useData()
const language = useLanguage()
const settings = useSettings()
+
+ const familySessions = createMemo(() => {
+ const id = params.id
+
+ if (!id) return []
+
+ return [...new Set([id, ...data.session.family(id)])].flatMap((sessionID) => {
+ const info = data.session.get(sessionID)
+
+ return info ? [info] : []
+ })
+ })
+
+ const treeIDs = createMemo(() => sessionTreeIDs(familySessions(), params.id))
+
createEffect(() => {
const id = params.id
@@ -28,16 +43,15 @@ export function createSessionRequestModel() {
)
})
createEffect(() => {
- const id = params.id
+ if (serverSDK.connection.status() !== "connected") return
+ const ids = treeIDs()
- if (!id || serverSDK.connection.status() !== "connected") return
- void Promise.all(
- sessionTreeIDs(data.session.list(), id).map((sessionID) => data.session.form.sync(sessionID)),
- ).catch(() => undefined)
+ if (!ids.length) return
+ void Promise.all(ids.map((sessionID) => data.session.form.sync(sessionID))).catch(() => undefined)
})
const formRequest = createMemo((): FormInfo | undefined => {
- return sessionFormRequest(data.session.list(), data.session.form.list, params.id)
+ return sessionFormRequest(familySessions(), data.session.form.list, params.id)
})
// MCP elicitations are owned by the Location rather than a Session, so they are listed per Location.
@@ -102,7 +116,7 @@ export function createSessionRequestModel() {
if (settings.permissions.autoApproves(project)) return
- return sessionPermissionRequest(data.session.list(), data.session.permission.list, id)
+ return sessionPermissionRequest(familySessions(), data.session.permission.list, id)
})
const blocked = createMemo(() => {
@@ -131,7 +145,7 @@ export function createSessionRequestModel() {
const running = createSessionBackground({
sessionID: owner,
messages: data.session.message.list,
- sessions: data.session.list,
+ sessions: familySessions,
status: data.session.status,
shells: () => data.shell.list({ directory: sdk().directory }),
})
diff --git a/packages/app/src/shell/layout/project-avatar-state.ts b/packages/app/src/shell/layout/project-avatar-state.ts
index d4fe45146bff..01298d33773f 100644
--- a/packages/app/src/shell/layout/project-avatar-state.ts
+++ b/packages/app/src/shell/layout/project-avatar-state.ts
@@ -21,7 +21,6 @@ export function useSessionTabAvatarState(
if (!data) return []
- if (!root?.()) return data.session.list()
const id = sessionId()
return [...new Set([id, ...data.session.family(id)])].flatMap((id) => {
@@ -68,8 +67,7 @@ export function useSessionTabAvatarState(
const busy = (id: string) =>
data.session.status(id) === "running" || data.session.pending.list(id).some((item) => item.type !== "synthetic")
- if (root?.())
- return data.session.list().some((session) => data.session.root(session.id) === sessionId() && busy(session.id))
+ if (root?.()) return [...new Set([sessionId(), ...data.session.family(sessionId())])].some(busy)
return busy(sessionId())
})
diff --git a/packages/core/src/effect/app-node-builder.ts b/packages/core/src/effect/app-node-builder.ts
index dfefbf8d6620..546e8becf544 100644
--- a/packages/core/src/effect/app-node-builder.ts
+++ b/packages/core/src/effect/app-node-builder.ts
@@ -11,9 +11,7 @@ const instances = makeGlobalNode({
Instance.Service,
Effect.gen(function* () {
const locations = yield* LocationServiceMap.Service
- return Instance.Service.of({
- provide: (session) => Effect.provide(locations.get(session.location)),
- })
+ return Instance.fromLocations(locations)
}),
),
deps: [LocationServiceMap.node],
diff --git a/packages/core/src/instance.ts b/packages/core/src/instance.ts
index 9bcde2c59225..241cf5ad2862 100644
--- a/packages/core/src/instance.ts
+++ b/packages/core/src/instance.ts
@@ -55,7 +55,7 @@ import { ToolOutput } from "./tool-output.js"
import { Vcs } from "./vcs.js"
export * as Instance from "./instance.js"
-export { Service, node, type Interface } from "./instance/service.js"
+export { Service, fromLocations, node, provideContextEffectOption, type Interface } from "./instance/service.js"
const nodes = [
Location.node,
diff --git a/packages/core/src/instance/service.ts b/packages/core/src/instance/service.ts
index f23d28f49f2d..9cc95644b069 100644
--- a/packages/core/src/instance/service.ts
+++ b/packages/core/src/instance/service.ts
@@ -1,7 +1,8 @@
export * as Instance from "./service.js"
export type { Services } from "../instance.js"
-import { Context, type Effect } from "effect"
+import { Context, Effect, type LayerMap, Option, Scope } from "effect"
+import type { Location } from "@opencode/schema/location"
import type { Session } from "@opencode/schema/session"
import { Node } from "@opencode/util/effect/app-node"
import { LayerNode } from "@opencode/util/effect/layer-node"
@@ -12,6 +13,32 @@ export interface Interface {
readonly provide: (
session: Session.Info,
) => (effect: Effect.Effect) => Effect.Effect>
+ readonly provideIfLoaded: (
+ session: Session.Info,
+ ) => (effect: Effect.Effect) => Effect.Effect, E, Exclude>
+}
+
+export function provideContextEffectOption(
+ get: (key: K) => Effect.Effect>, E0, Scope.Scope>,
+ key: K,
+) {
+ return (effect: Effect.Effect): Effect.Effect, E, Exclude> =>
+ Effect.scopedWith((scope) =>
+ Effect.gen(function* () {
+ const context = yield* get(key).pipe(Scope.provide(scope), Effect.option, Effect.map(Option.flatten))
+ if (Option.isNone(context)) return Option.none()
+ return Option.some(yield* effect.pipe(Effect.provide(context.value)))
+ }),
+ )
+}
+
+export function fromLocations(
+ locations: Pick, "get" | "contextEffectOption">,
+): Interface {
+ return Service.of({
+ provide: (session) => Effect.provide(locations.get(session.location)),
+ provideIfLoaded: (session) => provideContextEffectOption(locations.contextEffectOption, session.location),
+ })
}
export class Service extends Context.Service()("@opencode/Instance") {}
diff --git a/packages/core/src/location-services.ts b/packages/core/src/location-services.ts
index 8498df7f6f5b..191b44f3d6c3 100644
--- a/packages/core/src/location-services.ts
+++ b/packages/core/src/location-services.ts
@@ -73,11 +73,7 @@ export function buildLocationServiceMap(
}
// Cached instances borrow their owner instead of retaining its Layer scope.
const bindings: LayerNode.Replacements = [
- Instance.node.replace(
- Layer.succeed(Instance.Service, {
- provide: (session) => Effect.provide(map.get(session.location)),
- }),
- ),
+ Instance.node.replace(Layer.succeed(Instance.Service, Instance.fromLocations(map))),
...replacements,
LocationServiceMap.node.replace(Layer.succeed(LocationServiceMap.Service, map)),
]
diff --git a/packages/core/test/instance-vanilla.test.ts b/packages/core/test/instance-vanilla.test.ts
index 75d450aa56d4..78267d5d6062 100644
--- a/packages/core/test/instance-vanilla.test.ts
+++ b/packages/core/test/instance-vanilla.test.ts
@@ -50,11 +50,7 @@ const instances = Layer.effect(
Global.node.replace(tempGlobalLayer),
offlineModels,
LocationServiceMap.node.replace(Layer.succeed(LocationServiceMap.Service, map)),
- Instance.node.replace(
- Layer.succeed(Instance.Service, {
- provide: (session) => Effect.provide(map.get(session.location)),
- }),
- ),
+ Instance.node.replace(Layer.succeed(Instance.Service, Instance.fromLocations(map))),
]
return map
}),
diff --git a/packages/core/test/plugin/supervisor-reload.test.ts b/packages/core/test/plugin/supervisor-reload.test.ts
index e2ed79e23f95..f51ce3828d84 100644
--- a/packages/core/test/plugin/supervisor-reload.test.ts
+++ b/packages/core/test/plugin/supervisor-reload.test.ts
@@ -71,11 +71,7 @@ const instances = Layer.effect(
Npm.node.replace(npmLayer),
Watcher.node.replace(Layer.succeed(Watcher.Service, watcher)),
LocationServiceMap.node.replace(Layer.succeed(LocationServiceMap.Service, map)),
- Instance.node.replace(
- Layer.succeed(Instance.Service, {
- provide: (session) => Effect.provide(map.get(session.location)),
- }),
- ),
+ Instance.node.replace(Layer.succeed(Instance.Service, Instance.fromLocations(map))),
]
return map
}),
diff --git a/packages/core/test/plugin/supervisor.test.ts b/packages/core/test/plugin/supervisor.test.ts
index ffbc2f709cdd..cf40b1839aec 100644
--- a/packages/core/test/plugin/supervisor.test.ts
+++ b/packages/core/test/plugin/supervisor.test.ts
@@ -58,11 +58,7 @@ const instances = Layer.effect(
offlineModels,
ConfigPluginSource.node.replace(sourceLayer),
LocationServiceMap.node.replace(Layer.succeed(LocationServiceMap.Service, map)),
- Instance.node.replace(
- Layer.succeed(Instance.Service, {
- provide: (session) => Effect.provide(map.get(session.location)),
- }),
- ),
+ Instance.node.replace(Layer.succeed(Instance.Service, Instance.fromLocations(map))),
]
return map
}),
diff --git a/packages/core/test/session-generate.test.ts b/packages/core/test/session-generate.test.ts
index 54abd800447a..9fa2223abfaf 100644
--- a/packages/core/test/session-generate.test.ts
+++ b/packages/core/test/session-generate.test.ts
@@ -250,6 +250,7 @@ const setup = Effect.gen(function* () {
Layer.mock(Plugin.Service, { awaitActivation: Effect.void }),
) as Layer.Layer,
),
+ provideIfLoaded: () => () => Effect.die("Unexpected loaded-only instance lookup"),
}),
}
})
diff --git a/packages/core/test/session-move.test.ts b/packages/core/test/session-move.test.ts
index 99dc52b16579..228b89f62083 100644
--- a/packages/core/test/session-move.test.ts
+++ b/packages/core/test/session-move.test.ts
@@ -126,6 +126,8 @@ const sourceProbe = (options: { execution?: boolean } = {}) =>
}
return yield* effect.pipe(Effect.provide(locations.get(session.location)))
}),
+ provideIfLoaded: (session) =>
+ Instance.provideContextEffectOption(locations.contextEffectOption, session.location),
})
}),
),
@@ -287,7 +289,7 @@ describe("Session.move", () => {
Effect.gen(function* () {
const locations = yield* LocationServiceMap.Service
const privateInstances = yield* LayerMap.make(
- () =>
+ (_id: Session.ID) =>
Instance.layer(source, {
discovery: false,
replacements: [
@@ -306,6 +308,10 @@ describe("Session.move", () => {
? privateInstances.get(session.id)
: locations.get(session.location),
),
+ provideIfLoaded: (session) =>
+ session.id === selectedID && session.location.directory === source.directory
+ ? Instance.provideContextEffectOption(privateInstances.contextEffectOption, session.id)
+ : Instance.provideContextEffectOption(locations.contextEffectOption, session.location),
})
const bindings: LayerNode.Replacements = [
...replacements,
diff --git a/packages/core/test/session-owned.test.ts b/packages/core/test/session-owned.test.ts
index 327071b56771..83f58352e3f6 100644
--- a/packages/core/test/session-owned.test.ts
+++ b/packages/core/test/session-owned.test.ts
@@ -147,6 +147,7 @@ const setup = Effect.fnUntraced(function* (options?: {
const instances = Instance.Service.of({
// This fixture supplies only the instance services exercised by Session.
provide: (session) => Effect.provide(servicesFor(session.location) as Layer.Layer),
+ provideIfLoaded: () => () => Effect.die("Unexpected loaded-only instance lookup"),
})
const sessions = yield* Session.make().pipe(
Effect.satisfiesServicesType<
diff --git a/packages/core/test/session-remove.test.ts b/packages/core/test/session-remove.test.ts
index 2e39ee6233c3..45a477337364 100644
--- a/packages/core/test/session-remove.test.ts
+++ b/packages/core/test/session-remove.test.ts
@@ -1,5 +1,5 @@
import { describe, expect } from "bun:test"
-import { Effect, Layer, RcMap, Scope } from "effect"
+import { Effect, Layer, Option, RcMap, Scope } from "effect"
import { AppNodeBuilder } from "@opencode/core/effect/app-node-builder"
import { LayerNode } from "@opencode/util/effect/layer-node"
import { Database } from "@opencode/core/database/database"
@@ -115,3 +115,39 @@ describe("Session.remove", () => {
}),
)
})
+
+describe("Instance.provideIfLoaded", () => {
+ it.live("skips absent instances and scopes loaded borrows without replacing the caller's Scope", () =>
+ Effect.gen(function* () {
+ const temporary = yield* tmpdirScoped()
+ const sessions = yield* Session.Service
+ const instances = yield* Instance.Service
+ const locations = yield* LocationServiceMap.Service
+ const scope = yield* Scope.Scope
+ const session = yield* sessions.create({
+ location: Location.Ref.make({ directory: AbsolutePath.make(temporary.path) }),
+ })
+ const absent = Effect.die("An unloaded instance must not run the effect").pipe(instances.provideIfLoaded(session))
+
+ expect(yield* absent).toEqual(Option.none())
+ expect(Array.from(yield* RcMap.keys(locations.rcMap))).toEqual([])
+ yield* Location.Service.pipe(instances.provide(session))
+ expect(Array.from(yield* RcMap.keys(locations.rcMap))).toEqual([session.location])
+ expect(yield* Effect.void.pipe(instances.provideIfLoaded(session))).toEqual(Option.some(undefined))
+ const failure = new Error("Borrowed operation failed")
+ expect(yield* Effect.fail(failure).pipe(instances.provideIfLoaded(session), Effect.flip)).toBe(failure)
+
+ const borrowed = yield* Effect.gen(function* () {
+ const location = yield* Location.Service
+ const callerScope = yield* Scope.Scope
+ expect(callerScope).toBe(scope)
+ yield* locations.invalidate(session.location)
+ return location.directory
+ }).pipe(instances.provideIfLoaded(session), Effect.satisfiesServicesType())
+
+ expect(borrowed).toEqual(Option.some(session.location.directory))
+ expect(Array.from(yield* RcMap.keys(locations.rcMap))).toEqual([])
+ expect(yield* absent).toEqual(Option.none())
+ }),
+ )
+})
diff --git a/packages/protocol/openapi.json b/packages/protocol/openapi.json
index 73a54d345cb3..d660a6184627 100644
--- a/packages/protocol/openapi.json
+++ b/packages/protocol/openapi.json
@@ -4382,18 +4382,11 @@
}
},
"404": {
- "description": "SessionNotFoundError | LocationNotFoundError",
+ "description": "SessionNotFoundError",
"content": {
"application/json": {
"schema": {
- "anyOf": [
- {
- "$ref": "#/components/schemas/SessionNotFoundErrorEncoded"
- },
- {
- "$ref": "#/components/schemas/LocationNotFoundErrorEncoded"
- }
- ]
+ "$ref": "#/components/schemas/SessionNotFoundErrorEncoded"
}
}
}
@@ -9088,18 +9081,11 @@
}
},
"404": {
- "description": "SessionNotFoundError | LocationNotFoundError",
+ "description": "SessionNotFoundError",
"content": {
"application/json": {
"schema": {
- "anyOf": [
- {
- "$ref": "#/components/schemas/SessionNotFoundErrorEncoded"
- },
- {
- "$ref": "#/components/schemas/LocationNotFoundErrorEncoded"
- }
- ]
+ "$ref": "#/components/schemas/SessionNotFoundErrorEncoded"
}
}
}
diff --git a/packages/protocol/src/groups/permission.ts b/packages/protocol/src/groups/permission.ts
index 5cc0eb4b8502..e7a0baa684ba 100644
--- a/packages/protocol/src/groups/permission.ts
+++ b/packages/protocol/src/groups/permission.ts
@@ -8,7 +8,6 @@ import { Context, Schema } from "effect"
import { HttpApiEndpoint, HttpApiGroup, HttpApiMiddleware, HttpApiSchema, OpenApi } from "effect/http-api"
import {
ConflictError,
- LocationNotFoundError,
PermissionNotFoundError,
PermissionSavedNotFoundError,
SessionNotFoundError,
@@ -113,7 +112,7 @@ export const makePermissionGroup = <
HttpApiEndpoint.get("session.permission.list", "/api/session/:sessionID/permission", {
params: { sessionID: Session.ID },
success: Schema.Struct({ data: Schema.Array(Permission.Request) }),
- error: [SessionNotFoundError, LocationNotFoundError],
+ error: SessionNotFoundError,
}).annotateMerge(
OpenApi.annotations({
identifier: "session.permission.list",
diff --git a/packages/protocol/src/groups/session.ts b/packages/protocol/src/groups/session.ts
index 95683c846c3c..bac6cf73eb12 100644
--- a/packages/protocol/src/groups/session.ts
+++ b/packages/protocol/src/groups/session.ts
@@ -736,15 +736,13 @@ export const makeSessionGroup = LayerNode.Replacemen
...LocationServiceMap.canonical(session.location),
})
const provide = (session: Session.Info) => Effect.provide(instances.get(key(session)))
+ const provideIfLoaded = (session: Session.Info) =>
+ Instance.provideContextEffectOption(instances.contextEffectOption, key(session))
+ const selector = Instance.Service.of({ provide, provideIfLoaded })
const instances: LayerMap.LayerMap<
ReturnType,
Instance.Services,
@@ -71,7 +74,7 @@ export function layer(options: Options, replacements: () => LayerNode.Replacemen
...replacements(),
// Instances borrow this selector and the host's Location map instead of retaining
// their Layer scopes; retaining the selector would block its shutdown on its own entries.
- Instance.node.replace(Layer.succeed(Instance.Service, { provide })),
+ Instance.node.replace(Layer.succeed(Instance.Service, selector)),
LocationServiceMap.node.replace(Layer.succeed(LocationServiceMap.Service, locations)),
],
}).pipe(
@@ -101,7 +104,7 @@ export function layer(options: Options, replacements: () => LayerNode.Replacemen
),
{ idleTimeToLive: Duration.infinity },
)
- return Instance.Service.of({ provide })
+ return selector
}),
)
}
diff --git a/packages/sdk/test/instances.test.ts b/packages/sdk/test/instances.test.ts
index 87857bd08383..60bbf1adcf82 100644
--- a/packages/sdk/test/instances.test.ts
+++ b/packages/sdk/test/instances.test.ts
@@ -88,10 +88,10 @@ test("Promise instances are lazy, share by key and Location, and stay isolated b
expect(await second.sessions.get({ sessionID })).toEqual(separateHost)
expect(configured).toEqual([])
expect(setups).toEqual([])
- // Permission and form lists read instance services, so they acquire the Session's instance.
+ // Pending permissions and forms live only in a loaded instance, so listing them never acquires one.
expect(await first.permission.list({ sessionID })).toEqual([])
expect(await first.session.form.list({ sessionID })).toEqual([])
- expect(configured).toEqual(["first:alpha"])
+ expect(configured).toEqual([])
await Promise.all(
[
diff --git a/packages/server/src/handlers/permission.ts b/packages/server/src/handlers/permission.ts
index 68d0543a4c15..1958ab29aadc 100644
--- a/packages/server/src/handlers/permission.ts
+++ b/packages/server/src/handlers/permission.ts
@@ -3,11 +3,11 @@ import { Location } from "@opencode/core/location"
import { Permission } from "@opencode/core/permission"
import { PermissionSaved } from "@opencode/core/permission/saved"
import { Session } from "@opencode/core/session"
-import { Effect } from "effect"
+import { Effect, Option } from "effect"
import { HttpApiBuilder, HttpApiSchema } from "effect/http-api"
import { Api } from "../api"
import { ConflictError, PermissionNotFoundError, PermissionSavedNotFoundError } from "@opencode/protocol/errors"
-import { locationErrors, response, sessionInfo } from "../location"
+import { response, sessionInfo } from "../location"
import { missingSession } from "./session-error"
function missingRequest(id: Permission.ID) {
@@ -62,8 +62,8 @@ export const PermissionHandler = HttpApiBuilder.group(Api, "server.permission",
const session = yield* sessionInfo(sessions, ctx.params.sessionID)
const requests = yield* Permission.Service.use((permission) =>
permission.forSession(ctx.params.sessionID),
- ).pipe(instances.provide(session), locationErrors)
- return { data: requests }
+ ).pipe(instances.provideIfLoaded(session))
+ return { data: Option.getOrElse(requests, () => []) }
}),
)
.handle(
diff --git a/packages/server/src/handlers/session.ts b/packages/server/src/handlers/session.ts
index 0386bd44931a..063ca6727301 100644
--- a/packages/server/src/handlers/session.ts
+++ b/packages/server/src/handlers/session.ts
@@ -4,7 +4,9 @@ import { SessionTitle } from "@opencode/core/session/title"
import { SessionTransfer } from "@opencode/core/session/transfer"
import { InstructionEntry } from "@opencode/core/session/instruction-entry"
import { Form } from "@opencode/core/form"
-import { DateTime, Effect, Stream } from "effect"
+import { Instance } from "@opencode/core/instance/service"
+import { LocationServiceMap } from "@opencode/core/location-services"
+import { DateTime, Effect, Option, Stream } from "effect"
import { HttpApiBuilder, HttpApiSchema } from "effect/http-api"
import { Api } from "../api"
import {
@@ -22,7 +24,7 @@ import {
SkillNotFoundError,
} from "@opencode/protocol/errors"
import { AbsolutePath } from "@opencode/core/schema"
-import { locationErrors } from "../location"
+import { locationErrors, requestRef, sessionInfo } from "../location"
import { failedMessageDecode, failedSnapshot, missingMessage, missingSession } from "./session-error"
function missingForm(id: Form.ID) {
@@ -32,6 +34,8 @@ function missingForm(id: Form.ID) {
export const SessionHandler = HttpApiBuilder.group(Api, "server.session", (handlers) =>
Effect.gen(function* () {
const session = yield* Session.Service
+ const instances = yield* Instance.Service
+ const locations = yield* LocationServiceMap.Service
const transfer = yield* SessionTransfer.Service
const requireOwnedForm = Effect.fnUntraced(function* (sessionID: Form.Info["sessionID"], formID: Form.ID) {
const form = yield* Form.Service
@@ -616,8 +620,13 @@ export const SessionHandler = HttpApiBuilder.group(Api, "server.session", (handl
.handle(
"session.form.list",
Effect.fn(function* (ctx) {
- const form = yield* Form.Service
- return { data: yield* form.list({ sessionID: ctx.params.sessionID }) }
+ const current =
+ ctx.params.sessionID === "global" ? undefined : yield* sessionInfo(session, ctx.params.sessionID)
+ const read = Form.Service.use((form) => form.list({ sessionID: ctx.params.sessionID }))
+ const forms = yield* current
+ ? read.pipe(instances.provideIfLoaded(current))
+ : read.pipe(Instance.provideContextEffectOption(locations.contextEffectOption, requestRef(ctx.request)))
+ return { data: Option.getOrElse(forms, () => []) }
}),
)
.handle(
diff --git a/packages/server/test/fetch.test.ts b/packages/server/test/fetch.test.ts
index c2be48131ed4..a98ad0c6289d 100644
--- a/packages/server/test/fetch.test.ts
+++ b/packages/server/test/fetch.test.ts
@@ -41,10 +41,10 @@ it.live("returns LocationNotFoundError for a missing folder and recovers once it
const endpoints = [
"/api/model",
"/api/integration",
- `/api/session/${session.id}/permission`,
+ `/api/session/${session.id}/permission/per_missing`,
`/api/experimental/session/${session.id}/instructions/entries`,
- `/api/session/${session.id}/form`,
- "/api/session/global/form",
+ `/api/session/${session.id}/form/frm_missing`,
+ "/api/session/global/form/frm_missing",
]
for (const endpoint of endpoints) {
const response = yield* Effect.promise(() =>
@@ -466,7 +466,7 @@ it.live("serves the session view operation and missing-session error", () =>
}),
)
-it.live("routes pending requests through the Session's instance", () =>
+it.live("routes pending requests by Session without loading an instance", () =>
Effect.gen(function* () {
const config = yield* Effect.acquireDisposable(Effect.promise(() => tmpdir("opencode-pending-read-")))
const handler = yield* ServerFetch.make({
@@ -518,7 +518,7 @@ it.live("routes pending requests through the Session's instance", () =>
)
expect(global.status).toBe(200)
expect(yield* Effect.promise(() => global.json())).toEqual({ data: [] })
- expect(yield* loaded()).toEqual([{ directory: process.cwd() }])
+ expect(yield* loaded()).toEqual([])
const createdForm = yield* Effect.promise(() =>
handler(
diff --git a/packages/server/test/session-instances.test.ts b/packages/server/test/session-instances.test.ts
index 8ddc3601f94b..64ce25f4a2bb 100644
--- a/packages/server/test/session-instances.test.ts
+++ b/packages/server/test/session-instances.test.ts
@@ -145,6 +145,8 @@ it.live(
)
const selector = Instance.Service.of({
provide: (session) => Effect.provide(instances.get(session.id)),
+ provideIfLoaded: (session) =>
+ Instance.provideContextEffectOption(instances.contextEffectOption, session.id),
})
const bindings: LayerNode.Replacements = [
...replacements,
diff --git a/services/www/openapi.json b/services/www/openapi.json
index 73a54d345cb3..d660a6184627 100644
--- a/services/www/openapi.json
+++ b/services/www/openapi.json
@@ -4382,18 +4382,11 @@
}
},
"404": {
- "description": "SessionNotFoundError | LocationNotFoundError",
+ "description": "SessionNotFoundError",
"content": {
"application/json": {
"schema": {
- "anyOf": [
- {
- "$ref": "#/components/schemas/SessionNotFoundErrorEncoded"
- },
- {
- "$ref": "#/components/schemas/LocationNotFoundErrorEncoded"
- }
- ]
+ "$ref": "#/components/schemas/SessionNotFoundErrorEncoded"
}
}
}
@@ -9088,18 +9081,11 @@
}
},
"404": {
- "description": "SessionNotFoundError | LocationNotFoundError",
+ "description": "SessionNotFoundError",
"content": {
"application/json": {
"schema": {
- "anyOf": [
- {
- "$ref": "#/components/schemas/SessionNotFoundErrorEncoded"
- },
- {
- "$ref": "#/components/schemas/LocationNotFoundErrorEncoded"
- }
- ]
+ "$ref": "#/components/schemas/SessionNotFoundErrorEncoded"
}
}
}
diff --git a/services/www/public/openapi.json b/services/www/public/openapi.json
index 73a54d345cb3..d660a6184627 100644
--- a/services/www/public/openapi.json
+++ b/services/www/public/openapi.json
@@ -4382,18 +4382,11 @@
}
},
"404": {
- "description": "SessionNotFoundError | LocationNotFoundError",
+ "description": "SessionNotFoundError",
"content": {
"application/json": {
"schema": {
- "anyOf": [
- {
- "$ref": "#/components/schemas/SessionNotFoundErrorEncoded"
- },
- {
- "$ref": "#/components/schemas/LocationNotFoundErrorEncoded"
- }
- ]
+ "$ref": "#/components/schemas/SessionNotFoundErrorEncoded"
}
}
}
@@ -9088,18 +9081,11 @@
}
},
"404": {
- "description": "SessionNotFoundError | LocationNotFoundError",
+ "description": "SessionNotFoundError",
"content": {
"application/json": {
"schema": {
- "anyOf": [
- {
- "$ref": "#/components/schemas/SessionNotFoundErrorEncoded"
- },
- {
- "$ref": "#/components/schemas/LocationNotFoundErrorEncoded"
- }
- ]
+ "$ref": "#/components/schemas/SessionNotFoundErrorEncoded"
}
}
}