Skip to content

Commit ed5de41

Browse files
Berkay2002claude
andauthored
fix(server): resolve pre-existing typecheck drift (#2)
- CodexProvider: use conditional spread for optional `skills` so `exactOptionalPropertyTypes` does not surface `undefined`. - PerfProviderRegistry: add `slashCommands: []` and `skills: []` to the codex and claudeAgent fixture snapshots so they satisfy ServerProvider. - PerfProviderAdapter: add a no-op `compactThread` stub (succeeds with `null` for known sessions) to satisfy ProviderAdapterShape. - PerfProviderAdapter: capture the runtime context once and use `Effect.runForkWith` inside the timer callback; yield tagged errors directly instead of wrapping them in `Effect.fail`. - PerfProviderLayers: switch to `Layer.provideMerge` for the session directory so the perf provider exposes it to downstream consumers (matches DefaultProviderLayerLive) — this also resolves the `ProviderSessionDirectory` context leak flagged by cli.test.ts and server.ts. - ProviderSessionReaper.test: add `stopSessionForProvider` and `compactThread` mocks to the mock `ProviderServiceShape`. Co-authored-by: Claude <noreply@anthropic.com>
1 parent 6f34a03 commit ed5de41

5 files changed

Lines changed: 21 additions & 7 deletions

File tree

apps/server/src/perf/PerfProviderAdapter.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,8 @@ function buildRuntimeEvent(input: {
167167
export const makePerfProviderAdapter = Effect.gen(function* () {
168168
const runtimeEvents = yield* Queue.unbounded<ProviderRuntimeEvent>();
169169
const sessions = new Map<ThreadId, PerfSessionState>();
170+
const context = yield* Effect.context<never>();
171+
const runFork = Effect.runForkWith(context);
170172

171173
const clearPendingTimers = (threadId: ThreadId) =>
172174
Effect.sync(() => {
@@ -189,7 +191,7 @@ export const makePerfProviderAdapter = Effect.gen(function* () {
189191
Effect.sync(() => {
190192
const timer = setTimeout(() => {
191193
input.state.pendingTimers.delete(timer);
192-
Effect.runFork(
194+
runFork(
193195
Queue.offer(runtimeEvents, input.event).pipe(
194196
Effect.tap(() => Effect.sync(() => input.onAfterEmit?.())),
195197
Effect.asVoid,
@@ -245,7 +247,7 @@ export const makePerfProviderAdapter = Effect.gen(function* () {
245247
Effect.gen(function* () {
246248
const state = sessions.get(input.threadId);
247249
if (!state) {
248-
return yield* Effect.fail(sessionNotFound(input.threadId));
250+
return yield* sessionNotFound(input.threadId);
249251
}
250252

251253
yield* clearPendingTimers(input.threadId);
@@ -343,7 +345,7 @@ export const makePerfProviderAdapter = Effect.gen(function* () {
343345
Effect.gen(function* () {
344346
const state = sessions.get(threadId);
345347
if (!state) {
346-
return yield* Effect.fail(sessionNotFound(threadId));
348+
return yield* sessionNotFound(threadId);
347349
}
348350
yield* clearPendingTimers(threadId);
349351
const interruptedTurnId = turnId ?? state.session.activeTurnId;
@@ -380,12 +382,17 @@ export const makePerfProviderAdapter = Effect.gen(function* () {
380382
const stopSession: ProviderAdapterShape<ProviderAdapterError>["stopSession"] = (threadId) =>
381383
Effect.gen(function* () {
382384
if (!sessions.has(threadId)) {
383-
return yield* Effect.fail(sessionNotFound(threadId));
385+
return yield* sessionNotFound(threadId);
384386
}
385387
yield* clearPendingTimers(threadId);
386388
sessions.delete(threadId);
387389
});
388390

391+
const compactThread: ProviderAdapterShape<ProviderAdapterError>["compactThread"] = (threadId) =>
392+
sessions.has(threadId)
393+
? Effect.succeed<string | null>(null)
394+
: Effect.fail(sessionNotFound(threadId));
395+
389396
const listSessions: ProviderAdapterShape<ProviderAdapterError>["listSessions"] = () =>
390397
Effect.sync(() => Array.from(sessions.values(), (state) => state.session));
391398

@@ -404,7 +411,7 @@ export const makePerfProviderAdapter = Effect.gen(function* () {
404411
Effect.gen(function* () {
405412
const state = sessions.get(threadId);
406413
if (!state) {
407-
return yield* Effect.fail(sessionNotFound(threadId));
414+
return yield* sessionNotFound(threadId);
408415
}
409416
if (!Number.isInteger(numTurns) || numTurns < 0 || numTurns > state.snapshot.turns.length) {
410417
return yield* new ProviderAdapterValidationError({
@@ -444,6 +451,7 @@ export const makePerfProviderAdapter = Effect.gen(function* () {
444451
respondToRequest,
445452
respondToUserInput,
446453
stopSession,
454+
compactThread,
447455
listSessions,
448456
hasSession,
449457
readThread,

apps/server/src/perf/PerfProviderLayers.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export const PerfProviderLayerLive = Layer.unwrap(
2323

2424
return makeProviderServiceLive().pipe(
2525
Layer.provide(adapterRegistryLayer),
26-
Layer.provide(providerSessionDirectoryLayer),
26+
Layer.provideMerge(providerSessionDirectoryLayer),
2727
);
2828
}),
2929
);

apps/server/src/perf/PerfProviderRegistry.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ const makeProviderSnapshot = (input: {
6464
checkedAt: input.checkedAt,
6565
message: input.enabled ? "Perf fixture provider active." : "Disabled in T3 Code settings.",
6666
models: CODEX_MODELS,
67+
slashCommands: [],
68+
skills: [],
6769
};
6870
}
6971

@@ -81,6 +83,8 @@ const makeProviderSnapshot = (input: {
8183
? "Perf harness only stubs Codex runtime sessions."
8284
: "Disabled in T3 Code settings.",
8385
models: CLAUDE_MODELS,
86+
slashCommands: [],
87+
skills: [],
8488
};
8589
};
8690

apps/server/src/provider/Layers/CodexProvider.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,7 @@ export const checkCodexProviderStatus = Effect.fn("checkCodexProviderStatus")(fu
399399
enabled: codexSettings.enabled,
400400
checkedAt,
401401
models: input.models ?? models,
402-
skills: input.skills,
402+
...(input.skills ? { skills: input.skills } : {}),
403403
probe: input.probe,
404404
...(input.usageLimits ? { usageLimits: input.usageLimits } : {}),
405405
});

apps/server/src/provider/Layers/ProviderSessionReaper.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,8 @@ describe("ProviderSessionReaper", () => {
138138
respondToRequest: () => unsupported(),
139139
respondToUserInput: () => unsupported(),
140140
stopSession,
141+
stopSessionForProvider: vi.fn(() => Effect.void),
142+
compactThread: vi.fn(() => Effect.succeed(null)),
141143
listSessions: () => Effect.succeed([]),
142144
getCapabilities: () => Effect.succeed({ sessionModelSwitch: "in-session" }),
143145
rollbackConversation: () => unsupported(),

0 commit comments

Comments
 (0)