Skip to content

Commit 2714a33

Browse files
committed
fix(cmux): distinguish stopped agent sessions
1 parent ae44fc1 commit 2714a33

3 files changed

Lines changed: 26 additions & 16 deletions

File tree

home/dot_local/bin/executable_cmux-agent-board-state

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,17 @@ if [[ -z "$surface_id" ]]; then
1717
fi
1818

1919
working_marker=$'\342\201\240\342\200\213\342\201\240'
20-
idle_marker=$'\342\201\240\342\200\214\342\201\240'
20+
stopped_marker=$'\342\201\240\342\200\214\342\201\240'
2121
input_marker=$'\342\201\240\342\200\215\342\201\240'
2222

2323
case "$state" in
2424
working) marker="$working_marker" ;;
25-
# Existing sessions can retain the former Stop hook until they restart.
26-
stopped | idle) marker="$idle_marker" ;;
25+
stopped) marker="$stopped_marker" ;;
26+
idle) marker="" ;;
2727
input) marker="$input_marker" ;;
2828
clear) marker="" ;;
2929
*)
30-
echo "usage: cmux-agent-board-state {working|stopped|input|clear}" >&2
30+
echo "usage: cmux-agent-board-state {working|stopped|idle|input|clear}" >&2
3131
exit 2
3232
;;
3333
esac
@@ -54,7 +54,7 @@ current_surface_title="$({
5454

5555
workspace_has_marker=false
5656
if [[ "$current_workspace_title" == *"$working_marker"*
57-
|| "$current_workspace_title" == *"$idle_marker"*
57+
|| "$current_workspace_title" == *"$stopped_marker"*
5858
|| "$current_workspace_title" == *"$input_marker"* ]]; then
5959
workspace_has_marker=true
6060
fi
@@ -68,15 +68,15 @@ fi
6868

6969
if [[ -z "$marker"
7070
&& "$current_surface_title" != *"$working_marker"
71-
&& "$current_surface_title" != *"$idle_marker"
71+
&& "$current_surface_title" != *"$stopped_marker"
7272
&& "$current_surface_title" != *"$input_marker"
7373
&& "$workspace_has_marker" == false ]]; then
7474
echo '{}'
7575
exit 0
7676
fi
7777

7878
clean_surface_title="${current_surface_title//$working_marker/}"
79-
clean_surface_title="${clean_surface_title//$idle_marker/}"
79+
clean_surface_title="${clean_surface_title//$stopped_marker/}"
8080
clean_surface_title="${clean_surface_title//$input_marker/}"
8181

8282
next_surface_title="${clean_surface_title}${marker}"
@@ -90,7 +90,7 @@ fi
9090

9191
if [[ "$workspace_has_marker" == true ]]; then
9292
clean_workspace_title="${current_workspace_title//$working_marker/}"
93-
clean_workspace_title="${clean_workspace_title//$idle_marker/}"
93+
clean_workspace_title="${clean_workspace_title//$stopped_marker/}"
9494
clean_workspace_title="${clean_workspace_title//$input_marker/}"
9595
cmux workspace-action \
9696
--workspace "$workspace_id" \

home/dot_local/share/cmux/agent-board.swift

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ func managedTitleState(_ title: String) -> String {
4444
// Keep these zero-width markers literal. cmux 0.64.22 does not expand
4545
// Unicode escape sequences in interpreted sidebar string literals.
4646
if title.hasSuffix("⁠​⁠") { return "working" }
47-
if title.hasSuffix("⁠‌⁠") { return "idle" }
47+
if title.hasSuffix("⁠‌⁠") { return "stopped" }
4848
if title.hasSuffix("⁠‍⁠") { return "input" }
4949
return ""
5050
}
@@ -91,6 +91,13 @@ func agentState(_ workspace) -> String {
9191
return "done"
9292
}
9393

94+
let hasStoppedTab = workspace.tabs.contains {
95+
managedTitleState($0.title) == "stopped"
96+
}
97+
if hasStoppedTab || legacyTitleState == "stopped" {
98+
return "stopped"
99+
}
100+
94101
if label.contains("idle") {
95102
return "idle"
96103
}
@@ -103,6 +110,7 @@ func stateTint(_ state: String) -> String {
103110
if state == "working" { return "#30D158" }
104111
if state == "done" { return "#54A8FF" }
105112
if state == "idle" { return "#8E8E93" }
113+
if state == "stopped" { return "#FF9F0A" }
106114
return "#636366"
107115
}
108116

scripts/test-cmux-agent-board-state.sh

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ run_state() {
4848
}
4949

5050
working_marker=$'\342\201\240\342\200\213\342\201\240'
51-
idle_marker=$'\342\201\240\342\200\214\342\201\240'
51+
stopped_marker=$'\342\201\240\342\200\214\342\201\240'
5252
input_marker=$'\342\201\240\342\200\215\342\201\240'
5353

5454
run_state working >/dev/null
@@ -69,11 +69,11 @@ grep -Fq -- "tab-action --surface surface-id --action rename --title surface${in
6969
grep -Fq -- 'workspace-action --workspace workspace-id --action rename --title workspace' "$calls_file"
7070

7171
: >"$calls_file"
72-
MOCK_SURFACE_TITLE="surface${idle_marker}" run_state clear >/dev/null
72+
MOCK_SURFACE_TITLE="surface${stopped_marker}" run_state clear >/dev/null
7373
grep -Fq -- 'tab-action --surface surface-id --action rename --title surface' "$calls_file"
7474

7575
: >"$calls_file"
76-
MOCK_WORKSPACE_TITLE="workspace${idle_marker}" run_state clear >/dev/null
76+
MOCK_WORKSPACE_TITLE="workspace${stopped_marker}" run_state clear >/dev/null
7777
grep -Fq -- 'workspace-action --workspace workspace-id --action rename --title workspace' "$calls_file"
7878
if grep -Fq 'tab-action' "$calls_file"; then
7979
printf 'marker-free surface was unexpectedly renamed during workspace migration\n' >&2
@@ -82,11 +82,11 @@ fi
8282

8383
: >"$calls_file"
8484
run_state stopped >/dev/null
85-
grep -Fq -- "tab-action --surface surface-id --action rename --title surface${idle_marker}" "$calls_file"
85+
grep -Fq -- "tab-action --surface surface-id --action rename --title surface${stopped_marker}" "$calls_file"
8686

8787
: >"$calls_file"
88-
run_state idle >/dev/null
89-
grep -Fq -- "tab-action --surface surface-id --action rename --title surface${idle_marker}" "$calls_file"
88+
MOCK_SURFACE_TITLE="surface${working_marker}" run_state idle >/dev/null
89+
grep -Fq -- "tab-action --surface surface-id --action rename --title surface" "$calls_file"
9090

9191
shell_home="$test_dir/home"
9292
shell_calls="$test_dir/shell-calls"
@@ -165,7 +165,7 @@ jq -e '
165165
end))
166166
' <<<"$rendered_codex_hooks" >/dev/null
167167

168-
grep -Fq "if title.hasSuffix(\"${idle_marker}\") { return \"idle\" }" "$SIDEBAR"
168+
grep -Fq "if title.hasSuffix(\"${stopped_marker}\") { return \"stopped\" }" "$SIDEBAR"
169169
python3 - "$SIDEBAR" <<'PY'
170170
import pathlib
171171
import sys
@@ -175,7 +175,9 @@ agent_state = source.split("func agentState", 1)[1].split("func stateTint", 1)[0
175175
tab_state = source.split("func tabState", 1)[1].split("func workspaceRow", 1)[0]
176176
assert agent_state.rstrip().endswith('return "idle"\n}')
177177
assert "workspace.tabs.contains" in agent_state
178+
assert 'managedTitleState($0.title) == "stopped"' in agent_state
178179
assert "managedTitleState(tab.title)" in tab_state
180+
assert 'if state == "stopped" { return "#FF9F0A" }' in source
179181
assert "workspaceStatusText" not in source
180182
assert "workspaceMemoText" not in source
181183
assert "cmux-workspace-note" not in source

0 commit comments

Comments
 (0)