| ... | @@ -284,7 +284,11 @@ const hasMetricSnapshot = ( | ... | @@ -284,7 +284,11 @@ const hasMetricSnapshot = ( |
| 284 | Object.entries(attributes).every(([key, value]) => snapshot.attributes?.[key] === value), | 284 | Object.entries(attributes).every(([key, value]) => snapshot.attributes?.[key] === value), |
| 285 | ); | 285 | ); |
| 286 | | 286 | |
| 287 | function makeProviderServiceLayer() { | 287 | function makeProviderServiceLayer( |
| | 288 | input: { |
| | 289 | readonly directory?: ProviderSessionDirectory.ProviderSessionDirectory["Service"]; |
| | 290 | } = {}, |
| | 291 | ) { |
| 288 | const codex = makeFakeCodexAdapter(); | 292 | const codex = makeFakeCodexAdapter(); |
| 289 | const claude = makeFakeCodexAdapter(CLAUDE_AGENT_DRIVER); | 293 | const claude = makeFakeCodexAdapter(CLAUDE_AGENT_DRIVER); |
| 290 | const cursor = makeFakeCodexAdapter(CURSOR_DRIVER); | 294 | const cursor = makeFakeCodexAdapter(CURSOR_DRIVER); |
| ... | @@ -301,7 +305,10 @@ function makeProviderServiceLayer() { | ... | @@ -301,7 +305,10 @@ function makeProviderServiceLayer() { |
| 301 | const runtimeRepositoryLayer = ProviderSessionRuntime.layer.pipe( | 305 | const runtimeRepositoryLayer = ProviderSessionRuntime.layer.pipe( |
| 302 | Layer.provide(SqlitePersistenceMemory), | 306 | Layer.provide(SqlitePersistenceMemory), |
| 303 | ); | 307 | ); |
| 304 | const directoryLayer = ProviderSessionDirectoryLive.pipe(Layer.provide(runtimeRepositoryLayer)); | 308 | const directoryLayer = |
| | 309 | input.directory === undefined |
| | 310 | ? ProviderSessionDirectoryLive.pipe(Layer.provide(runtimeRepositoryLayer)) |
| | 311 | : Layer.succeed(ProviderSessionDirectory.ProviderSessionDirectory, input.directory); |
| 305 | | 312 | |
| 306 | const layer = it.layer( | 313 | const layer = it.layer( |
| 307 | Layer.mergeAll( | 314 | Layer.mergeAll( |
| ... | @@ -2208,6 +2215,53 @@ validation.layer("ProviderServiceLive validation", (it) => { | ... | @@ -2208,6 +2215,53 @@ validation.layer("ProviderServiceLive validation", (it) => { |
| 2208 | ); | 2215 | ); |
| 2209 | }); | 2216 | }); |
| 2210 | | 2217 | |
| | 2218 | const activeSessionThreadId = asThreadId("thread-active-session"); |
| | 2219 | const historicalSessionThreadId = asThreadId("thread-historical-session"); |
| | 2220 | const listThreadIds = vi.fn(() => |
| | 2221 | Effect.succeed([activeSessionThreadId, historicalSessionThreadId]), |
| | 2222 | ); |
| | 2223 | const getBinding = vi.fn((threadId: ThreadId) => |
| | 2224 | Effect.succeed( |
| | 2225 | Option.some({ |
| | 2226 | threadId, |
| | 2227 | provider: CODEX_DRIVER, |
| | 2228 | providerInstanceId: codexInstanceId, |
| | 2229 | }), |
| | 2230 | ), |
| | 2231 | ); |
| | 2232 | const boundedListing = makeProviderServiceLayer({ |
| | 2233 | directory: { |
| | 2234 | upsert: () => Effect.void, |
| | 2235 | getProvider: () => Effect.die("ProviderService.listSessions does not use getProvider"), |
| | 2236 | getBinding, |
| | 2237 | listThreadIds, |
| | 2238 | listBindings: () => Effect.die("ProviderService.listSessions does not use listBindings"), |
| | 2239 | }, |
| | 2240 | }); |
| | 2241 | |
| | 2242 | boundedListing.layer("ProviderServiceLive session listing", (it) => { |
| | 2243 | it.effect("looks up bindings for active sessions without scanning historical threads", () => |
| | 2244 | Effect.gen(function* () { |
| | 2245 | const provider = yield* ProviderService.ProviderService; |
| | 2246 | yield* boundedListing.codex.startSession({ |
| | 2247 | provider: CODEX_DRIVER, |
| | 2248 | providerInstanceId: codexInstanceId, |
| | 2249 | threadId: activeSessionThreadId, |
| | 2250 | cwd: "/tmp/project-active-session", |
| | 2251 | runtimeMode: "full-access", |
| | 2252 | }); |
| | 2253 | listThreadIds.mockClear(); |
| | 2254 | getBinding.mockClear(); |
| | 2255 | |
| | 2256 | const sessions = yield* provider.listSessions(); |
| | 2257 | |
| | 2258 | assert.equal(sessions.length, 1); |
| | 2259 | assert.equal(listThreadIds.mock.calls.length, 0); |
| | 2260 | assert.deepEqual(getBinding.mock.calls, [[activeSessionThreadId]]); |
| | 2261 | }), |
| | 2262 | ); |
| | 2263 | }); |
| | 2264 | |
| 2211 | describe("agent browser access", () => { | 2265 | describe("agent browser access", () => { |
| 2212 | const revokedThreads: Array<ThreadId> = []; | 2266 | const revokedThreads: Array<ThreadId> = []; |
| 2213 | | 2267 | |