sendTurn was constructing a fresh runtimePayload with only modelSelection, activeTurnId, lastRuntimeEvent, and lastRuntimeEventAt—completely overwriting persisted fields like cwd, model, and providerOptions set during startSession. Now reads the existing binding's runtimePayload and spreads it as the base, so fields persisted by startSession survive through sendTurn updates.
Unified · Split
| @@ -368,12 +368,20 @@ const makeProviderService = (options?: ProviderServiceLiveOptions) => · 367 unmodified lines | ||
| 368 | 368 | allowRecovery: true, |
| 369 | 369 | }); |
| 370 | 370 | const turn = yield* routed.adapter.sendTurn(input); |
| 371 | + const existingBinding = Option.getOrUndefined(yield* directory.getBinding(input.threadId)); | |
| 372 | + const existingPayload = | |
| 373 | + existingBinding?.runtimePayload && | |
| 374 | + typeof existingBinding.runtimePayload === "object" && | |
| 375 | + !Array.isArray(existingBinding.runtimePayload) | |
| 376 | + ? existingBinding.runtimePayload | |
| 377 | + : {}; | |
| 371 | 378 | yield* directory.upsert({ |
| 372 | 379 | threadId: input.threadId, |
| 373 | 380 | provider: routed.adapter.provider, |
| 374 | 381 | status: "running", |
| 375 | 382 | ...(turn.resumeCursor !== undefined ? { resumeCursor: turn.resumeCursor } : {}), |
| 376 | 383 | runtimePayload: { |
| 384 | + ...existingPayload, | |
| 377 | 385 | ...(input.modelSelection !== undefined ? { modelSelection: input.modelSelection } : {}), |
| 378 | 386 | activeTurnId: turn.turnId, |
| 379 | 387 | lastRuntimeEvent: "provider.sendTurn", |