[release] v0.106.0 - #5468
Merged
Merged
Conversation
…review The schedule drawer's 'next runs' preview ANDed the day-of-month and day-of-week cron fields, so an expression like `0 0 1 * 1` only matched when the 1st of the month was also a Monday — previewing the next run as 2027-02-01 instead of the coming Monday. POSIX cron and the backend croniter treat the two fields as a union when both are restricted, so the preview disagreed with what the schedule actually fires. Match either field when both are restricted (plain AND otherwise, since a `*` field is always-true). Add unit coverage for the union case and for the single-restricted-field AND case.
Rebases the backend two-thirds of JP's feat/sessions-extensions (PR #5363) onto current main (v0.105.5). Covers api, SDK, Fern python client, and the web generated client: the append-only session_turns domain replacing session_states, the stream command discriminator rename (prompt -> inputs/data), the root /sessions router and SessionsService, /kill teardown wiring, span identity columns plus ag.agent.id, and mounts agent_id. Ported from feat/sessions-extensions@1532ec7fe5 (JP). Reconciliations with the release main: - Kept main's pi-openai model_ref threading (PiHarness/AgentaHarness) and the EndpointResolutionError export alongside JP's HarnessType -> HarnessKind rename. - Kept main's 0.105.5 version in api/pyproject.toml while re-adding JP's greenlet dependency; api/uv.lock updated for greenlet only. - Kept main's sdks/python and services uv.lock (JP's were stale transitive bumps). Claude-Session: https://claude.ai/code/session_01DnWRxU3dCJ11hgDidm26vW
The record-ingest span_id is an OpenTelemetry span id (64-bit / 16 hex chars), not a UUID (128-bit / 32 hex). Typed as Optional[UUID], pydantic rejected every runner ingest with a 422 and session records silently dropped. Model it as what it is end to end: a validated 16-hex string (OTelSpanId) on the API model, core DTOs, and DAO column; varchar in the two unreleased migrations. trace_id stays UUID (genuinely the 32-hex OTel trace id). Adds contract + backfill + multi-turn tests. Claude-Session: https://claude.ai/code/session_01DnWRxU3dCJ11hgDidm26vW
Rebases the runner third of JP's feat/sessions-extensions (PR #5363) onto current main, ported into the post-decomposition module layout (PR #5369). JP wrote these against the old monolithic sandbox_agent.ts; they are re-homed by region into the decomposed modules: - The SandboxAgentDeps interface change (syncHarnessSessionDurable renamed to appendSessionTurn; the write/clear sandbox-pointer deps dropped) goes into runtime-contracts.ts. - The two acquireEnvironment branches (the reconnect-failure path and the post-hydrate pointer write, both now append-only with no pre-turn pointer PUT) go into environment.ts. - The turn-completion sync (syncHarnessSessionDurable replaced by appendSessionTurn with the streamId gate, workflow references, sandbox id, and trace id) goes into run-turn.ts. The sandbox-reconnect.ts and session-continuity-durable.ts rewrites apply as-is. protocol.ts, sessions/alive.ts, sessions/persist.ts, version.ts, and the tests are JP's versions verbatim. Ported from feat/sessions-extensions@1532ec7fe5 (JP). Reconciliations with the release main: - server.ts: kept main's session-identity / session-pool import split from the decomposition and applied JP's watchdog changes (startAliveWatchdog is now awaited and takes an onInterrupted callback that aborts the controller, request.streamId is threaded from the heartbeat, and buildPersistingEmitter gets turnId and span_id). - tracing/otel.ts, package.json, pnpm-lock.yaml: kept main's. The OTel 2.x bump JP carried is already in main, and main additionally has the #5364 trace-id-on-done feature that JP's branch predates. Verified: pnpm run typecheck clean, pnpm test 1202/1202 pass, build:extension ok. Claude-Session: https://claude.ai/code/session_01DnWRxU3dCJ11hgDidm26vW
…persist test Add a persist test whose fetch stub enforces the API contract (span_id must be a 16-hex OTel span id, else 422), so a regression to a non-span-shaped span_id fails here instead of silently dropping records. The old stub returned 200 for any body and hid the mismatch. Also switch the turn/span tagging test to a real 16-hex span id. Claude-Session: https://claude.ai/code/session_01DnWRxU3dCJ11hgDidm26vW
Plan-only workspace for removing the one-approval-per-turn latch so each gated tool call in a turn emits its own approval card, pluralizing the parked-approval record and the warm/keep-alive resume path, and verifying the already-plural frontend and SDK behavior with tests. Plans #5373, assesses #5078 and #5097. Claude-Session: https://claude.ai/code/session_01DnWRxU3dCJ11hgDidm26vW
Remove the one-approval-per-turn latch (PendingApprovalLatch) so each gated tool call in a turn emits its own approval card; pluralize the parked-approval record (a Map keyed by tool-call id) and the warm keep-alive resume input (a list of decisions), settling each parked gate by its own tool-call id on a live resume; defer orphan-sibling settling to the post-drain sweep so a concurrent gate is not force-settled before its own permission request arrives. Add runner unit tests (two cards emit, neither force-settled; multi-gate warm park + resume; deny-one-approve-one; mixed/unresumable sets stay cold), SDK vercel adapter plural egress/ingress tests, and a playground all-settled resume test. Closes #5373. Claude-Session: https://claude.ai/code/session_01DnWRxU3dCJ11hgDidm26vW
Complete the plural approval path in run-turn: record every parkable gate into env.parkedApprovals (keyed by tool-call id), iterate opts.resume.decisions to answer each parked gate by its own permissionId on the live session, defer the orphan-sibling settle to the post-drain sweep (so a concurrent gate is not force-settled before its own permission request arrives), and wire the non-parkable-pause signal. Update the acp-interactions unit test to assert both concurrent gates emit their own card. Part of the concurrent-approvals change (#5373); sits on the deny-frame egress lane whose markToolCallDenied the live-resume deny path reuses. Claude-Session: https://claude.ai/code/session_01DnWRxU3dCJ11hgDidm26vW
feat(runner): reliable multi-gate approvals: truthful results, persisted answers, per-card dispatch
One CSS-native, reduced-motion-proof collapse primitive (HeightCollapse) for everything that enters/leaves the composer region and config pane, plus the config-section header shimmer + draft/agent indicator tones on ConfigAccordionSection (and a useRecentFlag helper). Migrates RevealCollapse and AgentCommitNotice onto it so the motion language is consistent. Adds the motion dependency. (cherry picked from commit b79dbf9)
Reusable, dependency-free primitives for showing 'what changed' in a config surface: ChangedPathsContext (which dot-paths have uncommitted changes + a host-supplied revert), FocusPathsContext (narrow a surface to just the paths that matter — the same idea as rendering an input only when needed), and RailField opting into both via a path. sectionChanges maps the commit-diff classifier to the config panel's sections. Adds the draft-change and provider-key-added signal atoms the config pane consumes. (cherry picked from commit 351be6c)
…nline provider key Drawer-backed config sections (Model & harness, Advanced) surface only what needs attention inline instead of routing to the drawer: a missing provider key shows the key field right there, and uncommitted changes show the changed controls (focus-filtered via FocusPaths/ChangedPaths), each row marked and revertable, with a link out to the full drawer. Wires the sandbox/harness permission controls and the provider-credentials/key fields with their dot-paths; adds the provider-key-added notice. (cherry picked from commit 2fe28f9)
…olve Approval dock gains an 'Always allow <tool> for this agent' toggle that writes a per-tool permission (gateway/custom-function) or harness allow-rule into the draft config (toolPermission helpers), so the tool stops gating on resume and future runs; a contained notice offers Undo. Answering resolves the whole parked batch in one step — 'Approve all', or 'Approve' with the toggle on also clears that tool's sibling gates — instead of stepping through 1-of-N. (cherry picked from commit bf96673)
(cherry picked from commit 9c4ffd1)
fix(runner): keep the warm session when the client sends a minimal history
fix(runner): stop replaying the current prompt as a prior turn
fix(api): attach SessionsConfig so smart truncation stops dropping records
fix(api): order session records by producer time so turns stop interleaving
style(agent-chat): format transcriptToMessages.test.ts with prettier
[feat] Durable cross-device agent session list (archive, ended, titles)
feat(agent-chat): warm Stop + approval dock polish (steer UI flag-gated)
…to fe-feat/approval-batch-actions # Conflicts: # web/oss/src/components/AgentChatSlice/components/ApprovalDock.tsx
feat(agent-chat): batch approvals — Deny all + context peek [blocked on runner collect window]
…ords fix(runner): fail the turn instead of answering with a lost conversation
feat(sessions): sessions integration — storage rework, reliable approvals, and approval UX
bekossy
approved these changes
Jul 28, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
New version v0.106.0 in