Repository navigation
Add built-in OpenCode sidebar status integration - #4797
austinywang wants to merge 30 commits into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds a bundled ChangesOpenCode wrapper and status integration
Sequence Diagram(s)sequenceDiagram
participant Shell as Shell (bash/zsh)
participant OpenCodeWrapper as opencode wrapper (JS)
participant cmuxRunner as cmux CLI
participant StatusNorm as Status Normalizer (JS)
participant SessionMap as Session Lifecycle Map (JS)
participant SwiftHook as runGenericAgentHook (Swift)
participant TermCtrl as TerminalController (Swift)
Shell->>OpenCodeWrapper: exec opencode (inside cmux socket)
OpenCodeWrapper->>cmuxRunner: cmux --socket ping
OpenCodeWrapper->>cmuxRunner: cmux --socket hooks opencode install --yes
OpenCodeWrapper->>OpenCodeWrapper: export CMUX_OPENCODE_PID / CMUX_AGENT_LAUNCH_KIND
Note over OpenCodeWrapper: OpenCode session events arrive
OpenCodeWrapper->>StatusNorm: tokenize session.status / permission.asked / etc.
StatusNorm-->>SessionMap: upsert lifecycle record (running/retrying/needs-input/error/idle)
SessionMap-->>OpenCodeWrapper: phase + one-time error gate
OpenCodeWrapper->>cmuxRunner: hooks opencode runtime-status <descriptor> --pid <pid>
cmuxRunner->>SwiftHook: .runtimeStatus action
SwiftHook->>TermCtrl: set_agent_pid + set_status
OpenCodeWrapper->>cmuxRunner: hooks opencode runtime-notification <type> ...
cmuxRunner->>SwiftHook: .runtimeNotification action
SwiftHook->>TermCtrl: notify_target_async
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Poem
Important Pre-merge checks failedPlease resolve all errors before merging. Addressing warnings is optional. ❌ Failed checks (3 errors, 1 warning, 1 inconclusive)
✅ Passed checks (16 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 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 |
…in-opencode-sidebar-status
Greptile SummaryAdds a bundled
Confidence Score: 5/5Safe to merge — the three blocking issues from earlier review rounds are all confirmed resolved, and the new lifecycle state machine, wrapper passthrough logic, and panel aggregation ordering are correct. The JS lifecycle cache uses bounded insertion-order eviction with a proper fallback for fully-pinned maps. The Swift runtimeStatus/runtimeNotification handlers follow existing patterns, localized strings are complete for every new key actually introduced by the PR, and the isCmuxOpenCodeWrapper inode-safe sentinel correctly prevents the shim from shadowing the real binary. Regression tests exercise the wrapper in both passthrough and hook-install paths using real processes and UNIX sockets. No files require special attention. Important Files Changed
Sequence Diagram%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant OC as OpenCode process
participant JS as Session plugin (JS)
participant CMX as cmux CLI
participant SW as cmux Swift (TerminalController)
participant SB as Sidebar / Panel
Note over OC,SB: Startup (inside cmux terminal)
OC->>CMX: wrapper: ping (socket liveness)
CMX-->>OC: ok
OC->>CMX: hooks opencode install --yes
OC->>OC: "export CMUX_OPENCODE_PID=$$"
Note over OC,SB: Runtime events
OC->>JS: session.created
JS->>CMX: hooks opencode session-start
CMX->>SW: .sessionStart handler
SW->>SB: upsert session, set running status
OC->>JS: permission.asked
JS->>CMX: hooks opencode runtime-status needs-input --pid
CMX->>SW: .runtimeStatus(needs-input)
SW->>SB: set_agent_lifecycle needsInput + set_status
JS->>CMX: hooks opencode runtime-notification permission
CMX->>SW: .runtimeNotification(permission)
SW->>SB: notify_target_async
OC->>JS: session.status idle / session.idle
JS->>CMX: hooks opencode stop
CMX->>SW: .stop handler
SW->>SB: setIdleStatus
OC->>JS: session.error
JS->>CMX: hooks opencode runtime-status error --pid
CMX->>SW: .runtimeStatus(error)
SW->>SB: set_agent_lifecycle error + set_status
JS->>CMX: hooks opencode runtime-notification error
CMX->>SW: .runtimeNotification(error)
SW->>SB: notify_target_async
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
participant OC as OpenCode process
participant JS as Session plugin (JS)
participant CMX as cmux CLI
participant SW as cmux Swift (TerminalController)
participant SB as Sidebar / Panel
Note over OC,SB: Startup (inside cmux terminal)
OC->>CMX: wrapper: ping (socket liveness)
CMX-->>OC: ok
OC->>CMX: hooks opencode install --yes
OC->>OC: "export CMUX_OPENCODE_PID=$$"
Note over OC,SB: Runtime events
OC->>JS: session.created
JS->>CMX: hooks opencode session-start
CMX->>SW: .sessionStart handler
SW->>SB: upsert session, set running status
OC->>JS: permission.asked
JS->>CMX: hooks opencode runtime-status needs-input --pid
CMX->>SW: .runtimeStatus(needs-input)
SW->>SB: set_agent_lifecycle needsInput + set_status
JS->>CMX: hooks opencode runtime-notification permission
CMX->>SW: .runtimeNotification(permission)
SW->>SB: notify_target_async
OC->>JS: session.status idle / session.idle
JS->>CMX: hooks opencode stop
CMX->>SW: .stop handler
SW->>SB: setIdleStatus
OC->>JS: session.error
JS->>CMX: hooks opencode runtime-status error --pid
CMX->>SW: .runtimeStatus(error)
SW->>SB: set_agent_lifecycle error + set_status
JS->>CMX: hooks opencode runtime-notification error
CMX->>SW: .runtimeNotification(error)
SW->>SB: notify_target_async
Reviews (18): Last reviewed commit: "fix: address opencode hook review feedba..." | Re-trigger Greptile |
|
Addressed the Greptile follow-up on the latest head: |
There was a problem hiding this comment.
Actionable comments posted: 5
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@cmuxTests/OpenCodeHookRegressionTests.swift`:
- Around line 70-74: The socket path created in
OpenCodeHookRegressionTests.swift is too long (socketURL under a UUID-named temp
directory) and can be rejected by createUnixSocket; change the socketURL to use
a short path (e.g., place the socket directly in the system temp directory or
use a fixed short filename under root with a truncated UUID) so the full UNIX
socket path stays well under system limits; update the variable socketURL
accordingly (while keeping root, binDir, and logURL usage intact) and ensure
uniqueness of the socket name to avoid collisions when tests run concurrently.
In `@docs/agent-hooks.md`:
- Line 5: Update the lifecycle list in the agent-hooks documentation to include
the new "error" runtime state alongside the existing "running", "idle",
"needsInput", and "unknown" lifecycle values so the docs match the runtime
notifications; find the lifecycle enumeration or list wording in the agent-hooks
content (the paragraph that currently lists running, idle, needsInput, unknown)
and add "error" in the same format and ordering used for the other states.
In `@README.md`:
- Around line 271-272: Update the sentence that currently reads "Claude Code and
OpenCode are handled by bundled wrappers inside cmux terminals" to state that
the Claude wrapper is only enabled via Settings (per docs/agent-hooks.md) rather
than unconditionally; mention "Claude wrapper" and "cmux terminals" and
reference the Settings toggle so the README aligns with the hook documentation
and avoids implying unconditional handling.
In `@Resources/bin/opencode`:
- Around line 15-16: The script currently validates resolved executables with [[
-x "$candidate" ]] which allows directories named like the executables to pass;
change these checks to require a regular file and executable with [[ -f
"$candidate" && -x "$candidate" ]] for the candidate resolution around the
opencode/cmux checks (the tests using the candidate variable and the if [[
"$candidate" -ef "$0" ]] logic), and update the other similar checks referenced
(the other occurrences at the next candidate-resolution blocks) so all resolved
candidates are validated as regular executable files rather than just executable
paths.
In `@Sources/AgentHibernation/AgentHibernationLifecycleState.swift`:
- Line 8: Add a brief doc comment above the new enum case to clarify its
purpose: locate the AgentHibernationLifecycleState enum and add a /// comment
for the case error describing when it is used (for example: "/// Agent session
encountered an unrecoverable error and cannot continue hibernation lifecycle").
Ensure the comment is concise and mentions any relevant conditions or expected
behavior so other domains consuming AgentHibernationLifecycleState understand
the semantics of .error.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: cabacc3c-a82f-4f02-b723-f0ecdc037027
📒 Files selected for processing (15)
CLI/CMUXCLI+AgentHookDefinitions.swiftCLI/CMUXCLI+ExecutableResolution.swiftCLI/cmux.swiftREADME.mdResources/Localizable.xcstringsResources/bin/opencodeResources/shell-integration/cmux-bash-integration.bashResources/shell-integration/cmux-zsh-integration.zshSources/AgentHibernation/AgentHibernationLifecycleState.swiftSources/TerminalController.swiftSources/Workspace.swiftcmux.xcodeproj/project.pbxprojcmuxTests/AgentHibernationTests.swiftcmuxTests/OpenCodeHookRegressionTests.swiftdocs/agent-hooks.md
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
Resources/bin/opencode (2)
134-134:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winAvoid exposing
PATHin the wrapper error text.This is production command output, so naming the
PATHenvironment variable leaks implementation detail. Prefer generic copy like “Error: unable to locate the OpenCode executable.”Suggested fix
-REAL_OPENCODE="$(find_real_opencode)" || { echo "Error: opencode not found in PATH" >&2; exit 127; } +REAL_OPENCODE="$(find_real_opencode)" || { echo "Error: unable to locate the OpenCode executable" >&2; exit 127; }As per coding guidelines: user-facing errors and command output must not expose environment variables.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@Resources/bin/opencode` at line 134, The error message printed when REAL_OPENCODE fails uses "opencode not found in PATH", which exposes an environment variable; change the message produced in the failure branch of the REAL_OPENCODE assignment (the find_real_opencode invocation) to a generic user-facing string like "Error: unable to locate the OpenCode executable" or similar that omits any mention of PATH or environment variables so the wrapper output does not leak implementation details.Source: Coding guidelines
49-56:⚠️ Potential issue | 🟠 Major | ⚡ Quick winHonor the relay socket contract in remote cmux terminals.
cmux_socket_available()hard-requiresCMUX_SOCKET_PATHto be a local UNIX socket via-S, but cmux remote shells intentionally expose the relay endpoint as127.0.0.1:<relayPort>. Those sessions will never pass this guard, so the wrapper silently skips OpenCode hook installation even thoughcmux --socket … pingis already the real liveness check.Suggested fix
cmux_socket_available() { - local socket="${CMUX_SOCKET_PATH:-}" - [[ -n "$socket" && -S "$socket" ]] || return 1 + local socket="${CMUX_SOCKET_PATH:-${CMUX_SOCKET:-}}" + [[ -n "$socket" ]] || return 1 local cmux_bin cmux_bin="$(resolve_cmux_bin)" || return 1 CMUXTERM_CLI_RESPONSE_TIMEOUT_SEC=0.75 \ "$cmux_bin" --socket "$socket" ping >/dev/null 2>&1 }Based on learnings: remote shells intentionally export
CMUX_SOCKET_PATH/CMUX_SOCKETas127.0.0.1:<relayPort>, so wrapper liveness checks need to honor that relay contract.Also applies to: 141-147
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@Resources/bin/opencode` around lines 49 - 56, cmux_socket_available() currently enforces CMUX_SOCKET_PATH must be a local UNIX socket (-S), skipping remote relay endpoints like 127.0.0.1:<port>; update the function to accept either a UNIX socket or a host:port relay string (honor CMUX_SOCKET_PATH / CMUX_SOCKET), detect whether the value is a socket path or contains ":"/is an IP:port, and in both cases call resolve_cmux_bin then run CMUXTERM_CLI_RESPONSE_TIMEOUT_SEC=0.75 "$cmux_bin" --socket "$socket" ping >/dev/null 2>&1 to determine liveness; also apply the same change to the other similar block (lines 141-147) so both checks consistently support relay endpoints.Source: Learnings
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@CLI/cmux.swift`:
- Around line 25598-25619: pruneLifecycleRecords can fail to reduce size if all
entries are un-evictable (phase "needs-input"/"error"), letting
SESSION_LIFECYCLE grow past SESSION_LIFECYCLE_LIMIT; change
pruneLifecycleRecords so that if the first pass finds no evictable entry it
falls back to forcibly removing the oldest entries until size <=
SESSION_LIFECYCLE_LIMIT (i.e., delete the oldest key(s) from SESSION_LIFECYCLE
unconditionally), keeping the existing canEvictLifecycleRecord check as the
preferred path but guaranteeing bounded size; update rememberLifecycleRecord to
rely on this revised pruneBehavior.
---
Outside diff comments:
In `@Resources/bin/opencode`:
- Line 134: The error message printed when REAL_OPENCODE fails uses "opencode
not found in PATH", which exposes an environment variable; change the message
produced in the failure branch of the REAL_OPENCODE assignment (the
find_real_opencode invocation) to a generic user-facing string like "Error:
unable to locate the OpenCode executable" or similar that omits any mention of
PATH or environment variables so the wrapper output does not leak implementation
details.
- Around line 49-56: cmux_socket_available() currently enforces CMUX_SOCKET_PATH
must be a local UNIX socket (-S), skipping remote relay endpoints like
127.0.0.1:<port>; update the function to accept either a UNIX socket or a
host:port relay string (honor CMUX_SOCKET_PATH / CMUX_SOCKET), detect whether
the value is a socket path or contains ":"/is an IP:port, and in both cases call
resolve_cmux_bin then run CMUXTERM_CLI_RESPONSE_TIMEOUT_SEC=0.75 "$cmux_bin"
--socket "$socket" ping >/dev/null 2>&1 to determine liveness; also apply the
same change to the other similar block (lines 141-147) so both checks
consistently support relay endpoints.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 31259405-59fc-4794-9ab2-0438307e4956
📒 Files selected for processing (6)
CLI/cmux.swiftREADME.mdResources/bin/opencodeSources/AgentHibernation/AgentHibernationLifecycleState.swiftcmuxTests/OpenCodeHookRegressionTests.swiftdocs/agent-hooks.md
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 57bf740. Configure here.
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
cmuxTests/OpenCodeHookRegressionTests.swift (1)
400-413:⚠️ Potential issue | 🟠 MajorPrevent test job hangs in
runProcessby bounding stdout/stderr reads
cmuxTests/OpenCodeHookRegressionTests.swiftcurrently times out only viaprocess.terminate(), but it still unconditionally blocks onstdoutPipe.fileHandleForReading.readDataToEndOfFile()/stderrPipe...afterward.readDataToEndOfFile()waits for EOF, and if the child (or any descendant) keeps stdout/stderr pipe FDs open after SIGTERM, those reads can hang the entire CI job.Drain stdout/stderr concurrently while the process runs, and on timeout escalate to a hard kill (SIGKILL) before finalizing captured output; ensure pipe readers complete with a bounded grace even when EOF never arrives.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@cmuxTests/OpenCodeHookRegressionTests.swift` around lines 400 - 413, The runProcess implementation blocks on stdoutPipe.fileHandleForReading.readDataToEndOfFile() and stderrPipe.fileHandleForReading.readDataToEndOfFile(), which can hang after a terminate(); change it to drain stdout/stderr concurrently into buffers using non-blocking readers (e.g., set readabilityHandler on stdoutPipe.fileHandleForReading and stderrPipe.fileHandleForReading or use readInBackgroundAndNotify) that append data into local Data/Strings while the process runs, keep the existing DispatchSemaphore/process.waitUntilExit for normal termination, and on timeout call process.terminate(), wait a short bounded grace, then escalate to process.kill() (SIGKILL) if still running; after escalate close the pipe file handles to force EOF and wait for the reader callbacks to finish before creating the ProcessRunResult from the accumulated buffers instead of calling readDataToEndOfFile().
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@CLI/cmux.swift`:
- Around line 25646-25653: The function markSessionUpdated currently prevents
recovery by returning false when record.phase is "needs-input" or "error";
remove that gating so a non-idle update can flip the lifecycle back to "active"
and clear errorNotified (i.e., delete the if (record.phase === "needs-input" ||
record.phase === "error") return false; check in markSessionUpdated and the
equivalent checks around the session-start emission at the other occurrence),
ensuring markSessionUpdated sets record.phase = "active" and
record.errorNotified = false for existing records so later prompts/retries
re-emit session-start and clear stale state.
---
Outside diff comments:
In `@cmuxTests/OpenCodeHookRegressionTests.swift`:
- Around line 400-413: The runProcess implementation blocks on
stdoutPipe.fileHandleForReading.readDataToEndOfFile() and
stderrPipe.fileHandleForReading.readDataToEndOfFile(), which can hang after a
terminate(); change it to drain stdout/stderr concurrently into buffers using
non-blocking readers (e.g., set readabilityHandler on
stdoutPipe.fileHandleForReading and stderrPipe.fileHandleForReading or use
readInBackgroundAndNotify) that append data into local Data/Strings while the
process runs, keep the existing DispatchSemaphore/process.waitUntilExit for
normal termination, and on timeout call process.terminate(), wait a short
bounded grace, then escalate to process.kill() (SIGKILL) if still running; after
escalate close the pipe file handles to force EOF and wait for the reader
callbacks to finish before creating the ProcessRunResult from the accumulated
buffers instead of calling readDataToEndOfFile().
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 29b8125b-87b8-4340-b66f-617536fccf96
📒 Files selected for processing (2)
CLI/cmux.swiftcmuxTests/OpenCodeHookRegressionTests.swift
…in-opencode-sidebar-status # Conflicts: # CLI/CMUXCLI+ExecutableResolution.swift # Resources/shell-integration/cmux-bash-integration.bash # Resources/shell-integration/cmux-zsh-integration.zsh # Sources/TerminalController.swift
Stale CodeRabbit review from 2026-06-06. All listed findings were fixed and current-head review/checks supersede it.

Closes #1425
Summary
opencodewrapper that auto-installs cmux OpenCode hooks when launched inside a cmux terminal with a live socketVerification
HQ build command
CMUX_SKIP_ZIG_BUILD=1 ./scripts/reload.sh --tag issue-1425-add-built-in-opencode-sidebar-status --launchNeed help on this PR? Tag
@codesmithwith what you need. Autofix is disabled.Note
Medium Risk
Touches agent hook CLI, session lifecycle, hibernation, and shell PATH wrapping; mistakes could mis-report status or affect when idle agents are killed, but scope is mostly OpenCode-specific with regression tests.
Overview
Adds built-in OpenCode sidebar status via a bundled
opencodewrapper and newruntime-status/runtime-notificationhook paths for OpenCode only.Inside cmux terminals, bash/zsh shell integration prefers the bundled wrapper, which pings the socket, runs
hooks opencode install, exports launch metadata andCMUX_OPENCODE_PID, then execs the real binary (passthrough outside cmux or for help/version-style invocations). Executable resolution skips the shim when locating the realopencode.The OpenCode session plugin now maps session events to sidebar states (running, retrying, needs input, idle, error), sends permission/question/error notifications, dedupes lifecycle transitions with a bounded per-session cache, and only fires
stopon genuine idle transitions. The CLI handler updates session store,set_status, lifecycle, and async notifications from those runtime hooks.Agent hibernation gains an
errorlifecycle (not hibernated; panel aggregation prefers error over needs-input). Docs/README note OpenCode’s wrapper-based integration; regression tests cover the wrapper and plugin behavior.Reviewed by Cursor Bugbot for commit ac9a1a5. Bugbot is set up for automated code reviews on this repo. Configure here.
Summary by cubic
Adds built-in OpenCode sidebar status with a bundled
opencodewrapper and new runtime hooks that auto-install incmuxterminals. Implements #1425 by mapping OpenCode events to Running/Retrying/Needs input/Idle/Error with notifications, PID tracking, and safer idle/error lifecycle.New Features
opencodewrapper: installs only whenCMUX_SOCKET_PATHis live andCMUX_SURFACE_IDis set; no-op outsidecmuxand for help/version/completion; exportsCMUX_OPENCODE_PIDandCMUX_AGENT_LAUNCH_*; bash/zsh/fish wrapper install;resolveOpenCodeExecutableskips the shim; included in Copy CLI; docs updated.runtime-status/runtime-notificationset Running/Retrying/Needs input/Idle/Error with icon/color/priority and PID; permission/question/error notifications with dedup; status parsing prefers OpenCode fields with token fallback; localized “Retrying”.session.updated; stop only on true idle transitions; addserrorlifecycle (not hibernated) and gives Error precedence in panel aggregation; cleanup on archive/delete; CLI addsset_agent_lifecycle ... errorandset_agent_pid.Bug Fixes
Written for commit e6fadb4. Summary will update on new commits.
Summary by CodeRabbit
New Features
Documentation
Tests