[pull] main from danny-avila:main - #169
Merged
Merged
Conversation
* fix: improve activity label Langfuse traces * fix: scope activity trace correlation
* feat: add run step lifecycle timestamps and on_run_step_closed event
Stamps every run step with created_at + status ('in_progress') at dispatch
and closes each step exactly once with a terminal status and timestamp:
- New GraphEvents.ON_RUN_STEP_CLOSED custom event carrying
{ id, index, type, status, created_at, closed_at, runId?, agentId?,
groupId?, stepIndex? }, dual-dispatched (handler registry + custom
event) with the standard echo dedup. Purely additive: hosts that
register nothing observe identical behavior.
- RunStep gains optional created_at / completed_at / cancelled_at /
failed_at / status fields (the previously commented-out
OpenAI-Assistants shape); ToolCompleteEvent gains completed_at so tool
durations also ride the existing ON_RUN_STEP_COMPLETED event.
- StandardGraph.closeRunStep is the idempotent close funnel
(first-close-wins; a narrow completed->completed restamp lets a
completed TOOL_CALLS step refresh its timestamp when a late-registered
parallel call finishes). recordStepCompletion counts pending tool
calls per step (N-of-M) so multi-call steps close on their last
completion.
- Close triggers: tool completions are observed centrally in run.ts's
custom-event callback (ToolNode holds no graph reference), directly at
the registry-only summarization/tool-error sites, on CHAT_MODEL_END
for the lane's open message step, and when a successor step opens in
the same agent lane.
- End-of-run sweep in processStream's finally closes anything still
open: completed on natural finish, cancelled on caller abort or hook
halt, failed on unexpected stream errors. Skipped while paused on a
HITL interrupt so resumed steps keep their original created_at.
- Subagent forwarding: run_step_closed phase + sanitizer allowlists for
the new fields; manual session compaction emits the closed event for
its synthetic steps; session streams gain a 'step.finished' event.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014vLhxCFMYkCaTsoFTiAjJ5
* refactor: tighten run-step accounting hot paths
- untrackRunStep: replace the per-close scan of openMessageStepByAgent
with an O(1) keyed delete — the lane key is recomputable as
runStep.agentId ?? '', exactly how both funnels insert it.
- dispatchRunStep: hoist the pending-set get-or-create out of the
existing per-tool-call loop (one lookup per step instead of per call).
- Deduplicate the successor-close + content-map + open-step accounting
shared by dispatchRunStep and the summarization adapter into
trackDispatchedRunStep.
- Replace linear contentData.find with O(1) contentIndexMap lookups in
the summarization adapter's completion dispatch and manual
compaction's synthetic graph.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014vLhxCFMYkCaTsoFTiAjJ5
* refactor: options-bag close API, typed completion narrowing, invariant docs
- closeRunStep(stepId, status, options): fold the positional `at` timestamp
into RunStepCloseOptions, removing undefined-hole call sites.
- run.ts: narrow ON_RUN_STEP_COMPLETED payloads through getToolCompletionIds
instead of an inline structural cast.
- Document the RunStep terminal-status/timestamp invariant on the type,
noting it is runtime-enforced to stay wire-compatible.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014vLhxCFMYkCaTsoFTiAjJ5
* perf: short-circuit message-step closure on the model-end path
closeOpenMessageStep runs on every CHAT_MODEL_END. Return early when no
message step is tracked, and gate getStepAgentKey's context lookup behind
the constant-time multi-agent check — getAgentContext signals a miss by
throwing, so single-agent graphs were constructing and discarding an Error
per model call to derive a lane key that is always ''.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014vLhxCFMYkCaTsoFTiAjJ5
* fix: address Codex review findings on step closure
- Keep ON_RUN_STEP_CLOSED single-shot: a restamp for a late parallel tool
completion now updates the stored completed_at without re-emitting, so
consumers cannot double-count a step (duplicate session step.finished).
- Isolate sweep dispatch per step so one throwing host handler no longer
strands every later step in_progress with no terminal event.
- Dual-dispatch swept closures instead of registry-only, so callback-only
subscribers receive cancelled/failed terminals when the channel is alive.
- Stop tracking summarization steps as the lane's open message step: their
model call emits CHAT_MODEL_END long before the summary is assembled, so
model-end was publishing an authoritative completed closure early. They
close through their own completion instead.
- Sweep open steps in manual compaction, which runs outside processStream
and had no failure path to close a published summary step.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014vLhxCFMYkCaTsoFTiAjJ5
* fix: preserve producer completion time and corroborate abort status
- Carry the producer's `completed_at` from ON_RUN_STEP_COMPLETED through to
the close, so a slow host completion handler no longer inflates the
recorded step duration. recordStepCompletion takes an options bag rather
than growing a fourth positional parameter.
- Classify the terminal sweep from an actually-aborted caller/construction
signal instead of the error name: a provider or host rejection that merely
borrows the AbortError name is an unexpected failure, and reporting it as
`cancelled` corrupts abort forensics.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014vLhxCFMYkCaTsoFTiAjJ5
* fix: reserve step indexes synchronously and stamp closes at their source
- Register a dispatched step in contentData/contentIndexMap synchronously
before awaiting the predecessor's closure. Parallel agent lanes both
dispatching successors could otherwise push with the same index, letting
contentIndexMap resolve one step id to the other lane's entry so later
deltas and completions mutated the wrong agent's step. The predecessor's
CLOSED event still precedes the successor's ON_RUN_STEP.
- Capture the model-end timestamp before host CHAT_MODEL_END handlers run
and pass it into the message-step close, so a slow usage sink cannot
inflate the step duration.
- Close manual compaction steps as failed rather than inferring cancellation
from an error name; compaction has no caller abort signal to corroborate.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014vLhxCFMYkCaTsoFTiAjJ5
* fix: drop the restamp path and close summary steps that never complete
- Remove the completed->completed restamp. Its only two registration sites
cannot reach a terminal step (dispatchRunStep registers at creation; the
reuse path in tools/handlers requires an empty step, so no completion can
reference it yet), so it guarded an unreachable race. Worse, if it had
fired it would leave RunStep.completed_at disagreeing with the closed_at
already delivered. First close now wins outright.
- Isolate the predecessor close in trackDispatchedRunStep: the successor is
already registered in contentData, so a throwing predecessor handler would
abort the caller before it published the successor's ON_RUN_STEP, leaving
the sweep to emit a terminal event for a step that never started.
- Close the summary step as failed when summarization produces empty output.
That branch returns without a completion, so the step previously stayed
in_progress until the run-end sweep reported an inflated duration and a
successful status for an explicitly failed summary.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014vLhxCFMYkCaTsoFTiAjJ5
* fix: stamp step lifecycle times at their true boundaries
- Run the terminal sweep before the callback teardown so callback-only
subscribers still receive abort/failure/halt closures instead of being
left with unmatched starts.
- Capture the stream's terminal time when it ends, throws, or halts, and
pass it through the sweep, so Stop/StopFailure hooks and Langfuse
disposal no longer inflate swept terminal stamps.
- Stamp created_at after the predecessor closure is delivered and just
before the start event publishes, so a slow predecessor handler is not
charged to the successor's duration.
- Track the latest producer completion time per step and close multi-call
steps with it; parallel calls can settle out of producer order, so the
call that drains the pending set is not necessarily the last to finish.
- Implement closeRunStep on the manual compaction adapter so an empty
summary closes as failed there too, instead of no-opping into the
success path.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014vLhxCFMYkCaTsoFTiAjJ5
---------
Co-authored-by: Claude <noreply@anthropic.com>
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 subscribe to this conversation on GitHub.
Already have an account?
Sign in.
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.
See Commits and Changes for more details.
Created by
pull[bot] (v2.0.0-alpha.4)
Can you help keep this open source service alive? 💖 Please sponsor : )