[feat] Extend sessions#5363
Draft
jp-agenta wants to merge 39 commits into
Draft
Conversation
MountDBA had a bare nullable session_id but no agent_id, so agent mounts were only findable by slug pattern-matching (asymmetric with session mounts). Add a nullable agent_id String column + partial index mirroring session_id, and backfill existing agent-mount rows by parsing the id out of their `__ag__agent__<id>__<name>` slug (deterministic — the agent segment is the raw canonical artifact id, unlike the session segment which is a uuid5 hash). Mounts are core DB, so this backfill is allowed (unlike the tracing DB). Session-mount rows stay agent_id-null. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Populate agent_id in get_or_create_agent_mount (the caller already holds artifact_id) via a new mint_agent_id helper shared with mint_agent_slug, so the slug's id segment and the column derive byte-identically from the same artifact id. Add agent_id to the mount query DTO/DAO filter and the /mounts/query request/router, mirroring the existing session_id filter. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…arsing Unit tests: a new agent mount's agent_id matches its slug's id segment; session mounts stay agent_id-null; query_mounts filters by agent_id (extends the in-memory DAO test double to support it); and the migration's SQL backfill parser is pinned in Python against mint_agent_slug/mint_agent_id so any slug-format drift is caught without a live DB (the SQL itself was verified against a real Postgres instance during implementation). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Promote session/user/agent identity from JSONB attributes to nullable root-level columns on the spans table (tracing_oss migration oss000000003, chained off oss000000002_add_records — the live OSS tracing tree, post-park). Wire the columns through SpanDBA/SpanDBE, the OTelFlatSpan DTO, and the DAO mappings/filtering so they're queryable via the existing Condition/Filtering API. Add a (project_id, session_id) index. No data migration — old spans stay null (tracing-DB forward-fill only rule). Leaves a deferred note on the JSONB list_sessions query that could become an indexed scan once this lands. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add promote_identity_by_trace, grouped by trace_id alongside the existing trace-type inference and metrics propagation in ingest_span_dtos. Lifts ag.session.id/ag.user.id/ag.agent.id from each trace's root span (parent_id is None) onto the new DTO fields; child spans are left untouched. Root-only because ingestion is span-by-span / partial-batch — a trace's root and children can arrive in different requests, so there is no cheap way to propagate to children safely. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add Tracing.store_agent (mirrors store_session/store_user) stamping ag.agent.id on the current span. Resolve the agent id in NormalizerMiddleware.__call__ from RunningContext.revision.artifact_id (falling back to the workflow_id alias) — workflow, application, and evaluator invocations all resolve through the same WorkflowRevision shape, so one seam covers all three. Called once per invocation alongside store_session, before the handler runs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add gen_ai.agent.id -> ag.agent.id to the GenAI semconv table shared by the Logfire adapter (OpenInference and Vercel AI have no agent-identity telemetry field to map from). Wiring this through required more than the adapter's own mapping table: SpanFeatures had no `agent` bucket, NAMESPACE_PREFIX_FEATURE_MAPPING had no ag.agent. prefix entry, and span_data_builders.py never flushed a features.agent bucket back onto attributes — session/user only. All three needed the same treatment already given to session/user for agent id to actually reach the span. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
New core-DB table, one row per turn (1:many by session_id), absorbing the per-turn resume fold currently folded into session_states.data. Composite pk (project_id, id), FK to session_streams (project_id, id) ON DELETE NO ACTION (no cascade — delete is an explicit session-scoped fan-out), GIN jsonb_path_ops index on references (eval_runs pattern), indexes on (project_id, session_id) and (project_id, session_id, turn_index). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
core/sessions/turns/: SessionTurn DTOs, Harness(str, Enum) enumerated from the runner's services/runner/src/version.ts HARNESSES (pi_core default, pi_agenta, claude), SessionTurnsDAOInterface, SessionTurnsService. dbs/postgres/sessions/turns/: SessionTurnDBE (no data/flags/tags/meta — every field first-class/queryable), mappings, and SessionTurnsDAO with: - append / fetch_turn / query_turns (apply_windowing + references .contains(), the eval_runs GIN jsonb_path_ops pattern, not the git temporary adapter) - latest_turn / latest_turn_per_harness — the resume-read the runner needs (WP3): ORDER BY turn_index DESC LIMIT 1, so a late lower-index write can never win - delete_by_session_id — hard delete (WP5's session-delete fan-out) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
SessionTurnsRouter (apis/fastapi/sessions/router.py) exposes:
POST /sessions/turns/ append_turn (RUN_SESSIONS)
POST /sessions/turns/query query_turns (VIEW_SESSIONS)
GET /sessions/turns/{id} fetch_turn (VIEW_SESSIONS)
append_turn reads user_id from the caller's credential and threads it through
service -> dao -> created_by_id, mirroring the streams/interactions pattern.
Composed into SessionsRouter as `.turns`; entrypoints/routers.py instantiates
SessionTurnsDAO/SessionTurnsService next to the streams wiring and mounts the
router under /sessions/turns.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Against a real Postgres (core_oss migration chain applied): append round-trips every field and sets created_by_id from the caller; query_turns filters by references via the GIN .contains() pattern; windowed query lists newest first; latest_turn / latest_turn_per_harness resolve correctly even when a lower-turn_index row is appended last; delete_by_session_id hard-deletes and leaves no rows. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds two nullable, plain (no-FK) columns to the tracing DB's records table: turn_id (str) groups records by the turn that produced them; span_id (uuid) bridges to the observability span. Both are forward-fill only per the tracing-DB rule (never backfill/data-migrate that DB) -- new records carry them, existing rows stay null since they carry no turn key to reconstruct one from. Migration oss000000003 chains from this worktree's real tracing_oss head (oss000000002_add_records). Threads the columns through RecordDBA/RecordDBE, SessionRecord/SessionRecordEvent DTOs, SessionRecordIngestRequest, the ingest router handler, and the DAO's upsert (both insert and on-conflict paths), plus an optional (project_id, session_id, turn_id) index for grouping. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
buildPersistingEmitter and postEvent (services/runner/src/sessions/persist.ts) now accept optional turnId/spanId and stamp them onto every record's ingest body, so the API's new session_records.turn_id/span_id columns get populated at the source. server.ts's session-owned call site passes the turn id already minted at resolveTurnId (turnId, in scope since line ~859) and the request's propagated span (request.runContext?.trace?.span_id) when tracing supplied one. Both params are optional and appended at the end of existing signatures, so this stays additive for WP3's later edit to the same file. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add name/description (HeaderDBA) to session_streams and point the
/sessions/states/ header surface at the merged row: GET reads the header,
PUT/POST is a full-PUT {name, description} rename edit gated EDIT_SESSIONS,
off the runner's write path. The flag-mirror/heartbeat paths use a separate
SessionStreamEdit path that never carries name/description, so heartbeats
can't churn the header. session_states stays present-but-unused; the DROP
is deferred to WPI after WP3's runner cutover.
Migration oss000000015 chains from WP1's oss000000014 head.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Unit tests (test_stream_header_merge.py): the header edit round-trips
through the DBE mapping and DAO, a heartbeat/detach/kill flag-mirror write
never clobbers a prior rename, flags still mirror the Redis nest, and the
rename creates the row on a session's first touch (with a race fallback
to update when a concurrent heartbeat wins the create).
Rewrites the two acceptance suites under session_states/ that asserted the
old data-blob/sandbox_id RMW semantics (retired by the merge) to instead
exercise the new {name, description} rename contract.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The runner already POSTs /sessions/streams/heartbeat every turn and discarded the response; it carries stream.id (the session_streams row uuid) at zero extra cost. Await the watchdog's first heartbeat (only) so stream_id is ready before the turn starts, and thread it onto AgentRunRequest.streamId for the turn-append write site to consume. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace syncHarnessSessionDurable's GET-then-PUT of the whole session_states
.data blob with appendSessionTurn, a plain POST /sessions/turns/ insert per
completed turn (session_id, stream_id, harness, agent_session_id, sandbox_id,
turn_index, references, trace_id) — no read, no merge, no race.
Resume/eligibility reads (hydrateHarnessSessionFromDurable) and the sandbox
reconnect pointer (readStoredSandboxPointer) now query the latest turn
(POST /sessions/turns/query, windowed limit=1 order=descending on the uuid7
id, equivalent to turn_index DESC for an append-only table) instead of the
1:1 states row. The old atomic sandbox_turn_index staleness guard dissolves:
a late lower-index turn can never win the ordered read, so the separate
writeSandboxPointer/clearSandboxPointer PUTs and the terminal-reconnect clear
are retired — the live sandbox id rides forward as a field on the next
completed turn's row instead.
W3.0 verify-first finding: the per-turn resume write at the one write site
(sandbox_agent.ts runTurn, ~2295) is agent_session_id-shaped only (harness,
agentSessionId, turnIndex) — no richer separate SDK blob is round-tripped.
This confirms the session_states drop (WPI, after this cutover) is safe.
References populate from request.runContext.workflow.{artifact,variant,
revision} (buildWorkflowReferences, flattened to a bare list per the eval_runs
convention — the dict key is dropped, only {id,slug,version} survive) and
trace_id from run.traceId(), both already in scope at the write site.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
New DAO methods for the session-level delete/archive fan-out, all previously soft-delete-only: SessionInteractionsDAO.delete_by_session_id (hard delete, was soft-only via cancel_session_pending's status flip), SessionStreamsDAO.hard_delete_by_session_id (hard delete, kill only soft-deletes) + unarchive_by_session_id/get_by_session_id_including_archived (the archive round-trip's reverse + confirmation read), and MountsDAO.delete_by_session_id (hard delete of session-bound mount rows, returning the deleted rows for object-store teardown). Streams query() also gains optional windowing + session_ids filtering for the root query_sessions endpoint. MountsService grows delete_session_mounts (rows + ObjectStore prefix teardown) and archive/unarchive_session_mounts (soft, reversible). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
New root-level session operations orchestrating across the streams/turns/ interactions/mounts facets, anchored on session_id (never stream_id): - POST /sessions/query (query_sessions): lists/filters the merged stream rows, newest->oldest, windowed. A references filter joins the turns' references (WP1's GIN .contains()) to resolve matching session_ids first, then filters the stream query to that set — no denormalization onto the stream row (B3). - DELETE /sessions/?session_id=: hard-delete fan-out (turns, interactions, mounts + their object-store prefixes, then the stream row). Records are never touched — cross-DB, left to tracing retention. - POST /sessions/archive / /sessions/unarchive: the same fan-out but soft (deleted_at), including the bound mounts (reversible); folders untouched. RBAC: VIEW_SESSIONS for query, EDIT_SESSIONS for the three mutations. Wired as SessionsRouter.root in apis/fastapi/sessions/router.py and mounted unprefixed in api/entrypoints/routers.py alongside the other session sub-routers. peek (S12/E1) is deliberately NOT built as a server-side aggregate: the individual reads (query_sessions here, GET /sessions/streams/?session_id=, turns/records query-or-fetch) are the whole read surface, documented in the router module docstring as what the front-end composes. Renamed the deprecated OTel-side /tracing/sessions/query operation_id to query_sessions_tracing (was query_sessions) to resolve the FastAPI duplicate-operation-id collision with the new endpoint, following the existing delete_trace_tracing disambiguation precedent in the same router. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- test_sessions_root_service.py: SessionsService orchestration (fakes each sub-service) — delete fan-out order/keys, archive/unarchive round-trip, reference-join query with windowing pass-through and no-match short-circuit. - test_wp5_root_router.py: SessionsRootRouter RBAC gating + service delegation (mirrors test_record_ingest_endpoint.py's mock-Request pattern). - test_wp5_dao_fanout.py: integration tests against a real Postgres for the new hard-delete/unarchive DAO methods (interactions, streams, mounts), including the soft-vs-hard-delete distinction and session-scoping. - test_wp5_mount_teardown.py: MountsService delete/archive/unarchive_session_ mounts — object-store delete_prefix call shape, and that archive/unarchive never touch the store. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… (W7.1/E6) send/steer/cancel/attach in SessionStreamsService.command() are now keyed on data.inputs (a WorkflowServiceRequestData, matching WorkflowInvokeRequest.data.inputs) present-or-not x force, replacing the bespoke prompt string. Also fixes heartbeat()'s acquire-then-refresh fallback, which previously masked a cancel/steer/kill that raced a heartbeat by silently re-acquiring the alive/running lock under the SAME turn_id; SessionHeartbeatResult now carries is_current_turn so the runner's watchdog can tell a genuine interruption from this turn's own first-touch establishment. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
SessionStreamsService.kill() previously only force-cleared the Redis nest and soft-deleted the stream row -- nothing called the runner's POST /kill (services/runner/src/server.ts), so a live sandbox kept running until its own idle-TTL eviction. kill_runner_sandbox (core/sessions/streams/runner_client.py) adds that direct API -> runner hop, scoped to (project_id, session_id), reusing the same AGENTA_RUNNER_INTERNAL_URL/AGENTA_RUNNER_TOKEN the Python agent service already uses. Best-effort: kill's Redis/row edit remains authoritative and must not depend on the runner being reachable. Wires the two env vars into the API container/deployment across all compose files and the Helm chart (previously only the services/agent-service container had them), and updates the self-host configuration reference doc. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…uption (W7.4) For a session-owned run, server.ts's AbortController was never fed by anything -- a client disconnect only flipped clientDisconnected (a park-vs-destroy signal), and losing the alive lock to a cancel/steer/kill was invisible to the runner process (the heartbeat loop only logged non-OK responses and never inspected the body). startAliveWatchdog now takes an onInterrupted callback, fired at most once when a beat's is_current_turn:false; server.ts wires it to controller.abort(), which already feeds the sandbox-agent engine's existing signal-based teardown (runSandboxAgent's startOptions.signal) -- the same mechanism a client disconnect used for non-session runs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ns 014, header 015) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…r span-identity 003) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Resolves alive.ts + server.ts conflicts with WP7 (both restructured the heartbeat
path for orthogonal reasons): sendHeartbeat returns { streamId, interrupted } (both
signals from the one response body); startAliveWatchdog is async (WP3, awaits first
beat for stream_id) AND takes onInterrupted (WP7, control-signal -> controller.abort).
WP7's interrupt test updated to await the now-async watchdog.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ates Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…runner tests Picks the 3-file dependency bump from vibes/runner-daytona-otel-bump so the installed 2.x OTel deps match the otel.ts API (resourceFromAttributes/spanProcessors/ parentSpanContext). Resolves 39 pre-existing 'Resource is not a constructor' failures. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This was referenced Jul 18, 2026
mmabrouk
added a commit
that referenced
this pull request
Jul 18, 2026
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
mmabrouk
added a commit
that referenced
this pull request
Jul 18, 2026
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
mmabrouk
added a commit
that referenced
this pull request
Jul 18, 2026
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
mmabrouk
added a commit
that referenced
this pull request
Jul 18, 2026
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
mmabrouk
added a commit
that referenced
this pull request
Jul 18, 2026
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
mmabrouk
added a commit
that referenced
this pull request
Jul 19, 2026
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
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.
No description provided.