Format swarm code
- commit
- 37526a628691317f0ec831e401e07ec733e3e2a9
- author
- patriceckhart · · 2026-05-16 12:01 UTC
- parent
- 36f190a
- signature
- unsigned
8 files · +32 -32
M internal/agent/modes/swarm_dialog.go +8 -8
| @@ -948,7 +948,7 @@ func (d *swarmDialog) Render(th tui.Theme, width int) []string { | |||
| 948 | 948 | return d.renderTranscript(th, width) | |
| 949 | 949 | } | |
| 950 | 950 | ||
| 951 | - | out := []string{frameHeader(th, "swarm (n new · p prompt · R resume · ↑/↓ move · enter view · k kill · r remove · esc close)", width)} | |
| 951 | + | out := []string{frameHeader(th, "swarm (n new, p prompt, R resume, ↑/↓ move, enter view, k kill, r remove, esc close)", width)} | |
| 952 | 952 | if d.prompting { | |
| 953 | 953 | return d.renderPromptEditor(th, width, out) | |
| 954 | 954 | } | |
| @@ -960,7 +960,7 @@ func (d *swarmDialog) Render(th tui.Theme, width int) []string { | |||
| 960 | 960 | d.openModelPicker() | |
| 961 | 961 | } | |
| 962 | 962 | out = d.modelPicker.Render(th, width) | |
| 963 | - | out = append(out, " "+th.FG256(th.Muted, "select model for next spawn · esc to cancel")) | |
| 963 | + | out = append(out, " "+th.FG256(th.Muted, "select model for next spawn, esc to cancel")) | |
| 964 | 964 | return out | |
| 965 | 965 | } | |
| 966 | 966 | if d.spawning { | |
| @@ -998,7 +998,7 @@ func (d *swarmDialog) Render(th tui.Theme, width int) []string { | |||
| 998 | 998 | // Matching blank row below before the hint, mirroring the | |
| 999 | 999 | // main input's editor breathing room. | |
| 1000 | 1000 | out = append(out, "") | |
| 1001 | - | out = append(out, " "+th.FG256(th.Muted, "enter spawn · /model pick model · @ file/dir picker · paste/drop paths become [file:] / [dir:] chips · esc cancel")) | |
| 1001 | + | out = append(out, " "+th.FG256(th.Muted, "enter spawn, /model pick model, @ file/dir picker, paste/drop paths become [file:] / [dir:] chips, esc cancel")) | |
| 1002 | 1002 | out = append(out, frameRule(th, width)) | |
| 1003 | 1003 | return out | |
| 1004 | 1004 | } | |
| @@ -1031,11 +1031,11 @@ func (d *swarmDialog) renderTranscript(th tui.Theme, width int) []string { | |||
| 1031 | 1031 | return d.Render(th, width) | |
| 1032 | 1032 | } | |
| 1033 | 1033 | header := []string{ | |
| 1034 | - | frameHeader(th, "swarm: "+a.ID+" (type to send · esc back)", width), | |
| 1034 | + | frameHeader(th, "swarm: "+a.ID+" (type to send, esc back)", width), | |
| 1035 | 1035 | " " + th.FG256(th.Muted, "task: "+a.Task), | |
| 1036 | 1036 | " " + th.FG256(th.Muted, "branch: "+a.Branch), | |
| 1037 | 1037 | " " + th.FG256(th.Muted, "dir: "+a.Dir), | |
| 1038 | - | " " + th.FG256(th.Muted, fmt.Sprintf("status: %s · %s", a.Status, a.Activity)), | |
| 1038 | + | " " + th.FG256(th.Muted, fmt.Sprintf("status: %s, %s", a.Status, a.Activity)), | |
| 1039 | 1039 | } | |
| 1040 | 1040 | if a.Model != "" { | |
| 1041 | 1041 | modelLine := "model: " + a.Model | |
| @@ -1135,7 +1135,7 @@ func (d *swarmDialog) appendTranscriptEditor(out []string, th tui.Theme, width i | |||
| 1135 | 1135 | d.transcriptSpin.Start() | |
| 1136 | 1136 | } | |
| 1137 | 1137 | out = append(out, "") | |
| 1138 | - | prefix := fmt.Sprintf("%s %s · %s", | |
| 1138 | + | prefix := fmt.Sprintf("%s %s, %s", | |
| 1139 | 1139 | th.FG256(th.Assistant, d.transcriptSpin.Frame()), | |
| 1140 | 1140 | th.FG256(th.Assistant, a.Activity), | |
| 1141 | 1141 | th.FG256(th.Muted, d.transcriptSpin.Elapsed().String()), | |
| @@ -1153,7 +1153,7 @@ func (d *swarmDialog) appendTranscriptEditor(out []string, th tui.Theme, width i | |||
| 1153 | 1153 | out = append(out, " "+l) | |
| 1154 | 1154 | } | |
| 1155 | 1155 | out = append(out, "") | |
| 1156 | - | out = append(out, " "+th.FG256(th.Muted, "enter send · @ file/dir picker · esc back")) | |
| 1156 | + | out = append(out, " "+th.FG256(th.Muted, "enter send, @ file/dir picker, esc back")) | |
| 1157 | 1157 | return out | |
| 1158 | 1158 | } | |
| 1159 | 1159 | ||
| @@ -1315,7 +1315,7 @@ func (d *swarmDialog) renderPromptEditor(th tui.Theme, width int, out []string) | |||
| 1315 | 1315 | } | |
| 1316 | 1316 | // Matching blank row below before the hint. | |
| 1317 | 1317 | out = append(out, "") | |
| 1318 | - | out = append(out, " "+th.FG256(th.Muted, "enter send · @ file/dir picker · esc cancel")) | |
| 1318 | + | out = append(out, " "+th.FG256(th.Muted, "enter send, @ file/dir picker, esc cancel")) | |
| 1319 | 1319 | out = append(out, frameRule(th, width)) | |
| 1320 | 1320 | return out | |
| 1321 | 1321 | } | |
| @@ -948,7 +948,7 @@ func (d *swarmDialog) Render(th tui.Theme, width int) []string { | |||||
| 948 | return d.renderTranscript(th, width) | 948 | return d.renderTranscript(th, width) | ||
| 949 | } | 949 | } | ||
| 950 | 950 | ||||
| 951 | - | out := []string{frameHeader(th, "swarm (n new · p prompt · R resume · ↑/↓ move · enter view · k kill · r remove · esc close)", width)} | 951 | + | out := []string{frameHeader(th, "swarm (n new, p prompt, R resume, ↑/↓ move, enter view, k kill, r remove, esc close)", width)} |
| 952 | if d.prompting { | 952 | if d.prompting { | ||
| 953 | return d.renderPromptEditor(th, width, out) | 953 | return d.renderPromptEditor(th, width, out) | ||
| 954 | } | 954 | } | ||
| @@ -960,7 +960,7 @@ func (d *swarmDialog) Render(th tui.Theme, width int) []string { | |||||
| 960 | d.openModelPicker() | 960 | d.openModelPicker() | ||
| 961 | } | 961 | } | ||
| 962 | out = d.modelPicker.Render(th, width) | 962 | out = d.modelPicker.Render(th, width) | ||
| 963 | - | out = append(out, " "+th.FG256(th.Muted, "select model for next spawn · esc to cancel")) | 963 | + | out = append(out, " "+th.FG256(th.Muted, "select model for next spawn, esc to cancel")) |
| 964 | return out | 964 | return out | ||
| 965 | } | 965 | } | ||
| 966 | if d.spawning { | 966 | if d.spawning { | ||
| @@ -998,7 +998,7 @@ func (d *swarmDialog) Render(th tui.Theme, width int) []string { | |||||
| 998 | // Matching blank row below before the hint, mirroring the | 998 | // Matching blank row below before the hint, mirroring the | ||
| 999 | // main input's editor breathing room. | 999 | // main input's editor breathing room. | ||
| 1000 | out = append(out, "") | 1000 | out = append(out, "") | ||
| 1001 | - | out = append(out, " "+th.FG256(th.Muted, "enter spawn · /model pick model · @ file/dir picker · paste/drop paths become [file:] / [dir:] chips · esc cancel")) | 1001 | + | out = append(out, " "+th.FG256(th.Muted, "enter spawn, /model pick model, @ file/dir picker, paste/drop paths become [file:] / [dir:] chips, esc cancel")) |
| 1002 | out = append(out, frameRule(th, width)) | 1002 | out = append(out, frameRule(th, width)) | ||
| 1003 | return out | 1003 | return out | ||
| 1004 | } | 1004 | } | ||
| @@ -1031,11 +1031,11 @@ func (d *swarmDialog) renderTranscript(th tui.Theme, width int) []string { | |||||
| 1031 | return d.Render(th, width) | 1031 | return d.Render(th, width) | ||
| 1032 | } | 1032 | } | ||
| 1033 | header := []string{ | 1033 | header := []string{ | ||
| 1034 | - | frameHeader(th, "swarm: "+a.ID+" (type to send · esc back)", width), | 1034 | + | frameHeader(th, "swarm: "+a.ID+" (type to send, esc back)", width), |
| 1035 | " " + th.FG256(th.Muted, "task: "+a.Task), | 1035 | " " + th.FG256(th.Muted, "task: "+a.Task), | ||
| 1036 | " " + th.FG256(th.Muted, "branch: "+a.Branch), | 1036 | " " + th.FG256(th.Muted, "branch: "+a.Branch), | ||
| 1037 | " " + th.FG256(th.Muted, "dir: "+a.Dir), | 1037 | " " + th.FG256(th.Muted, "dir: "+a.Dir), | ||
| 1038 | - | " " + th.FG256(th.Muted, fmt.Sprintf("status: %s · %s", a.Status, a.Activity)), | 1038 | + | " " + th.FG256(th.Muted, fmt.Sprintf("status: %s, %s", a.Status, a.Activity)), |
| 1039 | } | 1039 | } | ||
| 1040 | if a.Model != "" { | 1040 | if a.Model != "" { | ||
| 1041 | modelLine := "model: " + a.Model | 1041 | modelLine := "model: " + a.Model | ||
| @@ -1135,7 +1135,7 @@ func (d *swarmDialog) appendTranscriptEditor(out []string, th tui.Theme, width i | |||||
| 1135 | d.transcriptSpin.Start() | 1135 | d.transcriptSpin.Start() | ||
| 1136 | } | 1136 | } | ||
| 1137 | out = append(out, "") | 1137 | out = append(out, "") | ||
| 1138 | - | prefix := fmt.Sprintf("%s %s · %s", | 1138 | + | prefix := fmt.Sprintf("%s %s, %s", |
| 1139 | th.FG256(th.Assistant, d.transcriptSpin.Frame()), | 1139 | th.FG256(th.Assistant, d.transcriptSpin.Frame()), | ||
| 1140 | th.FG256(th.Assistant, a.Activity), | 1140 | th.FG256(th.Assistant, a.Activity), | ||
| 1141 | th.FG256(th.Muted, d.transcriptSpin.Elapsed().String()), | 1141 | th.FG256(th.Muted, d.transcriptSpin.Elapsed().String()), | ||
| @@ -1153,7 +1153,7 @@ func (d *swarmDialog) appendTranscriptEditor(out []string, th tui.Theme, width i | |||||
| 1153 | out = append(out, " "+l) | 1153 | out = append(out, " "+l) | ||
| 1154 | } | 1154 | } | ||
| 1155 | out = append(out, "") | 1155 | out = append(out, "") | ||
| 1156 | - | out = append(out, " "+th.FG256(th.Muted, "enter send · @ file/dir picker · esc back")) | 1156 | + | out = append(out, " "+th.FG256(th.Muted, "enter send, @ file/dir picker, esc back")) |
| 1157 | return out | 1157 | return out | ||
| 1158 | } | 1158 | } | ||
| 1159 | 1159 | ||||
| @@ -1315,7 +1315,7 @@ func (d *swarmDialog) renderPromptEditor(th tui.Theme, width int, out []string) | |||||
| 1315 | } | 1315 | } | ||
| 1316 | // Matching blank row below before the hint. | 1316 | // Matching blank row below before the hint. | ||
| 1317 | out = append(out, "") | 1317 | out = append(out, "") | ||
| 1318 | - | out = append(out, " "+th.FG256(th.Muted, "enter send · @ file/dir picker · esc cancel")) | 1318 | + | out = append(out, " "+th.FG256(th.Muted, "enter send, @ file/dir picker, esc cancel")) |
| 1319 | out = append(out, frameRule(th, width)) | 1319 | out = append(out, frameRule(th, width)) | ||
| 1320 | return out | 1320 | return out | ||
| 1321 | } | 1321 | } | ||
M internal/agent/modes/swarm_dialog_test.go +2 -2
| @@ -1074,7 +1074,7 @@ func TestSwarmTranscriptGrowsWithNewMessages(t *testing.T) { | |||
| 1074 | 1074 | // both the new content AND keep the old content (no clipping). | |
| 1075 | 1075 | cur = []swarm.AgentSnapshot{{ | |
| 1076 | 1076 | ID: "agent-1", Task: "x", Status: swarm.StatusRunning, | |
| 1077 | - | Lines: []string{"old line 1", "old line 2", "new reply A", "new reply B"}, | |
| 1077 | + | Lines: []string{"old line 1", "old line 2", "new reply A", "new reply B"}, | |
| 1078 | 1078 | Started: cur[0].Started, | |
| 1079 | 1079 | }} | |
| 1080 | 1080 | out = strings.Join(d.Render(tui.Theme{}, 80), "\n") | |
| @@ -1262,7 +1262,7 @@ func TestSwarmTranscriptBusySpinnerRenders(t *testing.T) { | |||
| 1262 | 1262 | t.Error("spinner stayed live after agent reported idle") | |
| 1263 | 1263 | } | |
| 1264 | 1264 | // The bare word "thinking" must not appear anymore. | |
| 1265 | - | if strings.Contains(out, "· thinking ·") { | |
| 1265 | + | if strings.Contains(out, "· thinking, ") { | |
| 1266 | 1266 | t.Errorf("busy line still rendered when agent is idle:\n%s", out) | |
| 1267 | 1267 | } | |
| 1268 | 1268 | } | |
| @@ -1074,7 +1074,7 @@ func TestSwarmTranscriptGrowsWithNewMessages(t *testing.T) { | |||||
| 1074 | // both the new content AND keep the old content (no clipping). | 1074 | // both the new content AND keep the old content (no clipping). | ||
| 1075 | cur = []swarm.AgentSnapshot{{ | 1075 | cur = []swarm.AgentSnapshot{{ | ||
| 1076 | ID: "agent-1", Task: "x", Status: swarm.StatusRunning, | 1076 | ID: "agent-1", Task: "x", Status: swarm.StatusRunning, | ||
| 1077 | - | Lines: []string{"old line 1", "old line 2", "new reply A", "new reply B"}, | 1077 | + | Lines: []string{"old line 1", "old line 2", "new reply A", "new reply B"}, |
| 1078 | Started: cur[0].Started, | 1078 | Started: cur[0].Started, | ||
| 1079 | }} | 1079 | }} | ||
| 1080 | out = strings.Join(d.Render(tui.Theme{}, 80), "\n") | 1080 | out = strings.Join(d.Render(tui.Theme{}, 80), "\n") | ||
| @@ -1262,7 +1262,7 @@ func TestSwarmTranscriptBusySpinnerRenders(t *testing.T) { | |||||
| 1262 | t.Error("spinner stayed live after agent reported idle") | 1262 | t.Error("spinner stayed live after agent reported idle") | ||
| 1263 | } | 1263 | } | ||
| 1264 | // The bare word "thinking" must not appear anymore. | 1264 | // The bare word "thinking" must not appear anymore. | ||
| 1265 | - | if strings.Contains(out, "· thinking ·") { | 1265 | + | if strings.Contains(out, "· thinking, ") { |
| 1266 | t.Errorf("busy line still rendered when agent is idle:\n%s", out) | 1266 | t.Errorf("busy line still rendered when agent is idle:\n%s", out) | ||
| 1267 | } | 1267 | } | ||
| 1268 | } | 1268 | } | ||
M internal/agent/modes/swarm_slash.go +2 -2
| @@ -172,9 +172,9 @@ func (i *Interactive) runSwarm(ctx context.Context, args []string) { | |||
| 172 | 172 | case 0: | |
| 173 | 173 | i.swarmStatus("", "/swarm resume: no resumable agents (none detached or terminated)") | |
| 174 | 174 | case 1: | |
| 175 | - | i.swarmStatus("1 resumable agent · press R to resume", "") | |
| 175 | + | i.swarmStatus("1 resumable agent, press R to resume", "") | |
| 176 | 176 | default: | |
| 177 | - | i.swarmStatus(fmt.Sprintf("%d resumable agents · ↑/↓ to pick · R to resume", count), "") | |
| 177 | + | i.swarmStatus(fmt.Sprintf("%d resumable agents, ↑/↓ to pick, R to resume", count), "") | |
| 178 | 178 | } | |
| 179 | 179 | return | |
| 180 | 180 | } | |
| @@ -172,9 +172,9 @@ func (i *Interactive) runSwarm(ctx context.Context, args []string) { | |||||
| 172 | case 0: | 172 | case 0: | ||
| 173 | i.swarmStatus("", "/swarm resume: no resumable agents (none detached or terminated)") | 173 | i.swarmStatus("", "/swarm resume: no resumable agents (none detached or terminated)") | ||
| 174 | case 1: | 174 | case 1: | ||
| 175 | - | i.swarmStatus("1 resumable agent · press R to resume", "") | 175 | + | i.swarmStatus("1 resumable agent, press R to resume", "") |
| 176 | default: | 176 | default: | ||
| 177 | - | i.swarmStatus(fmt.Sprintf("%d resumable agents · ↑/↓ to pick · R to resume", count), "") | 177 | + | i.swarmStatus(fmt.Sprintf("%d resumable agents, ↑/↓ to pick, R to resume", count), "") |
| 178 | } | 178 | } | ||
| 179 | return | 179 | return | ||
| 180 | } | 180 | } | ||
M internal/agent/swarm_agent.go +7 -7
| @@ -11,8 +11,8 @@ import ( | |||
| 11 | 11 | ||
| 12 | 12 | "github.com/patriceckhart/zot/internal/agent/modes" | |
| 13 | 13 | "github.com/patriceckhart/zot/internal/core" | |
| 14 | - | "github.com/patriceckhart/zot/internal/swarm" | |
| 15 | 14 | "github.com/patriceckhart/zot/internal/provider" | |
| 15 | + | "github.com/patriceckhart/zot/internal/swarm" | |
| 16 | 16 | ) | |
| 17 | 17 | ||
| 18 | 18 | // runSwarmAgentMode is the daemon-mode entry point used by every | |
| @@ -85,12 +85,12 @@ func runSwarmAgentMode(ctx context.Context, args Args, version string) error { | |||
| 85 | 85 | // cancel so the "cancel" inbox message can interrupt an | |
| 86 | 86 | // in-flight turn without tearing down the whole daemon. | |
| 87 | 87 | var ( | |
| 88 | - | mu sync.Mutex | |
| 89 | - | turnCtx context.Context = ctx | |
| 90 | - | cancelFn context.CancelFunc | |
| 91 | - | busyTurn bool | |
| 92 | - | turnNo int | |
| 93 | - | shutdown = make(chan struct{}) | |
| 88 | + | mu sync.Mutex | |
| 89 | + | turnCtx context.Context = ctx | |
| 90 | + | cancelFn context.CancelFunc | |
| 91 | + | busyTurn bool | |
| 92 | + | turnNo int | |
| 93 | + | shutdown = make(chan struct{}) | |
| 94 | 94 | ) | |
| 95 | 95 | ||
| 96 | 96 | runOne := func(prompt string) { | |
| @@ -11,8 +11,8 @@ import ( | |||||
| 11 | 11 | ||||
| 12 | "github.com/patriceckhart/zot/internal/agent/modes" | 12 | "github.com/patriceckhart/zot/internal/agent/modes" | ||
| 13 | "github.com/patriceckhart/zot/internal/core" | 13 | "github.com/patriceckhart/zot/internal/core" | ||
| 14 | - | "github.com/patriceckhart/zot/internal/swarm" | |||
| 15 | "github.com/patriceckhart/zot/internal/provider" | 14 | "github.com/patriceckhart/zot/internal/provider" | ||
| 15 | + | "github.com/patriceckhart/zot/internal/swarm" | |||
| 16 | ) | 16 | ) | ||
| 17 | 17 | ||||
| 18 | // runSwarmAgentMode is the daemon-mode entry point used by every | 18 | // runSwarmAgentMode is the daemon-mode entry point used by every | ||
| @@ -85,12 +85,12 @@ func runSwarmAgentMode(ctx context.Context, args Args, version string) error { | |||||
| 85 | // cancel so the "cancel" inbox message can interrupt an | 85 | // cancel so the "cancel" inbox message can interrupt an | ||
| 86 | // in-flight turn without tearing down the whole daemon. | 86 | // in-flight turn without tearing down the whole daemon. | ||
| 87 | var ( | 87 | var ( | ||
| 88 | - | mu sync.Mutex | 88 | + | mu sync.Mutex |
| 89 | - | turnCtx context.Context = ctx | 89 | + | turnCtx context.Context = ctx |
| 90 | - | cancelFn context.CancelFunc | 90 | + | cancelFn context.CancelFunc |
| 91 | - | busyTurn bool | 91 | + | busyTurn bool |
| 92 | - | turnNo int | 92 | + | turnNo int |
| 93 | - | shutdown = make(chan struct{}) | 93 | + | shutdown = make(chan struct{}) |
| 94 | ) | 94 | ) | ||
| 95 | 95 | ||||
| 96 | runOne := func(prompt string) { | 96 | runOne := func(prompt string) { | ||
M internal/swarm/event.go +4 -4
| @@ -28,10 +28,10 @@ import ( | |||
| 28 | 28 | // stat the file size and read from their last offset on every | |
| 29 | 29 | // poll. | |
| 30 | 30 | type Event struct { | |
| 31 | - | Time time.Time `json:"time"` | |
| 32 | - | Type string `json:"type"` | |
| 33 | - | Data map[string]any `json:"-"` | |
| 34 | - | Raw map[string]any `json:"-"` // includes type+time+data for replay | |
| 31 | + | Time time.Time `json:"time"` | |
| 32 | + | Type string `json:"type"` | |
| 33 | + | Data map[string]any `json:"-"` | |
| 34 | + | Raw map[string]any `json:"-"` // includes type+time+data for replay | |
| 35 | 35 | } | |
| 36 | 36 | ||
| 37 | 37 | // MarshalJSON flattens Data into the top-level object so consumers | |
| @@ -28,10 +28,10 @@ import ( | |||||
| 28 | // stat the file size and read from their last offset on every | 28 | // stat the file size and read from their last offset on every | ||
| 29 | // poll. | 29 | // poll. | ||
| 30 | type Event struct { | 30 | type Event struct { | ||
| 31 | - | Time time.Time `json:"time"` | 31 | + | Time time.Time `json:"time"` |
| 32 | - | Type string `json:"type"` | 32 | + | Type string `json:"type"` |
| 33 | - | Data map[string]any `json:"-"` | 33 | + | Data map[string]any `json:"-"` |
| 34 | - | Raw map[string]any `json:"-"` // includes type+time+data for replay | 34 | + | Raw map[string]any `json:"-"` // includes type+time+data for replay |
| 35 | } | 35 | } | ||
| 36 | 36 | ||||
| 37 | // MarshalJSON flattens Data into the top-level object so consumers | 37 | // MarshalJSON flattens Data into the top-level object so consumers | ||
M internal/swarm/persist_test.go +5 -5
| @@ -179,7 +179,7 @@ func TestReloadReplaysTranscriptFromEventLog(t *testing.T) { | |||
| 179 | 179 | m := agentMeta{ | |
| 180 | 180 | ID: id, Task: "do thing", Branch: "swarm/alpha-9", | |
| 181 | 181 | Dir: filepath.Join(root, "wt", id), Started: time.Now().Add(-time.Hour), | |
| 182 | - | InboxPath: filepath.Join(stateDir, "in.sock"), | |
| 182 | + | InboxPath: filepath.Join(stateDir, "in.sock"), | |
| 183 | 183 | EventLogPath: filepath.Join(stateDir, "events.jsonl"), | |
| 184 | 184 | SessionPath: filepath.Join(stateDir, "session.json"), | |
| 185 | 185 | } | |
| @@ -606,11 +606,11 @@ func TestStopOnDetachedAgentIsNoopAndDoesNotPanic(t *testing.T) { | |||
| 606 | 606 | } | |
| 607 | 607 | m := agentMeta{ | |
| 608 | 608 | ID: id, Task: "t", Branch: "swarm/" + id, | |
| 609 | - | Dir: filepath.Join(root, "wt", id), | |
| 610 | - | Started: time.Now().Add(-time.Hour), | |
| 611 | - | InboxPath: filepath.Join(stateDir, "in.sock"), | |
| 609 | + | Dir: filepath.Join(root, "wt", id), | |
| 610 | + | Started: time.Now().Add(-time.Hour), | |
| 611 | + | InboxPath: filepath.Join(stateDir, "in.sock"), | |
| 612 | 612 | EventLogPath: filepath.Join(stateDir, "events.jsonl"), | |
| 613 | - | SessionPath: filepath.Join(stateDir, "session.json"), | |
| 613 | + | SessionPath: filepath.Join(stateDir, "session.json"), | |
| 614 | 614 | } | |
| 615 | 615 | mb, _ := json.MarshalIndent(m, "", " ") | |
| 616 | 616 | if err := os.WriteFile(filepath.Join(stateDir, "meta.json"), mb, 0o644); err != nil { | |
| @@ -179,7 +179,7 @@ func TestReloadReplaysTranscriptFromEventLog(t *testing.T) { | |||||
| 179 | m := agentMeta{ | 179 | m := agentMeta{ | ||
| 180 | ID: id, Task: "do thing", Branch: "swarm/alpha-9", | 180 | ID: id, Task: "do thing", Branch: "swarm/alpha-9", | ||
| 181 | Dir: filepath.Join(root, "wt", id), Started: time.Now().Add(-time.Hour), | 181 | Dir: filepath.Join(root, "wt", id), Started: time.Now().Add(-time.Hour), | ||
| 182 | - | InboxPath: filepath.Join(stateDir, "in.sock"), | 182 | + | InboxPath: filepath.Join(stateDir, "in.sock"), |
| 183 | EventLogPath: filepath.Join(stateDir, "events.jsonl"), | 183 | EventLogPath: filepath.Join(stateDir, "events.jsonl"), | ||
| 184 | SessionPath: filepath.Join(stateDir, "session.json"), | 184 | SessionPath: filepath.Join(stateDir, "session.json"), | ||
| 185 | } | 185 | } | ||
| @@ -606,11 +606,11 @@ func TestStopOnDetachedAgentIsNoopAndDoesNotPanic(t *testing.T) { | |||||
| 606 | } | 606 | } | ||
| 607 | m := agentMeta{ | 607 | m := agentMeta{ | ||
| 608 | ID: id, Task: "t", Branch: "swarm/" + id, | 608 | ID: id, Task: "t", Branch: "swarm/" + id, | ||
| 609 | - | Dir: filepath.Join(root, "wt", id), | 609 | + | Dir: filepath.Join(root, "wt", id), |
| 610 | - | Started: time.Now().Add(-time.Hour), | 610 | + | Started: time.Now().Add(-time.Hour), |
| 611 | - | InboxPath: filepath.Join(stateDir, "in.sock"), | 611 | + | InboxPath: filepath.Join(stateDir, "in.sock"), |
| 612 | EventLogPath: filepath.Join(stateDir, "events.jsonl"), | 612 | EventLogPath: filepath.Join(stateDir, "events.jsonl"), | ||
| 613 | - | SessionPath: filepath.Join(stateDir, "session.json"), | 613 | + | SessionPath: filepath.Join(stateDir, "session.json"), |
| 614 | } | 614 | } | ||
| 615 | mb, _ := json.MarshalIndent(m, "", " ") | 615 | mb, _ := json.MarshalIndent(m, "", " ") | ||
| 616 | if err := os.WriteFile(filepath.Join(stateDir, "meta.json"), mb, 0o644); err != nil { | 616 | if err := os.WriteFile(filepath.Join(stateDir, "meta.json"), mb, 0o644); err != nil { | ||
M internal/swarm/swarm.go +1 -1
| @@ -509,7 +509,7 @@ func (f *Swarm) SnapshotAll() []AgentSnapshot { | |||
| 509 | 509 | // agentSink is the Sink the Swarm hands to each Runner. | |
| 510 | 510 | type agentSink struct{ a *Agent } | |
| 511 | 511 | ||
| 512 | - | func (s agentSink) Activity(msg string) { s.a.setActivity(msg) } | |
| 512 | + | func (s agentSink) Activity(msg string) { s.a.setActivity(msg) } | |
| 513 | 513 | func (s agentSink) Transcript(chunk string) { s.a.appendTranscript(chunk) } | |
| 514 | 514 | ||
| 515 | 515 | func truncate(s string, n int) string { | |
| @@ -509,7 +509,7 @@ func (f *Swarm) SnapshotAll() []AgentSnapshot { | |||||
| 509 | // agentSink is the Sink the Swarm hands to each Runner. | 509 | // agentSink is the Sink the Swarm hands to each Runner. | ||
| 510 | type agentSink struct{ a *Agent } | 510 | type agentSink struct{ a *Agent } | ||
| 511 | 511 | ||||
| 512 | - | func (s agentSink) Activity(msg string) { s.a.setActivity(msg) } | 512 | + | func (s agentSink) Activity(msg string) { s.a.setActivity(msg) } |
| 513 | func (s agentSink) Transcript(chunk string) { s.a.appendTranscript(chunk) } | 513 | func (s agentSink) Transcript(chunk string) { s.a.appendTranscript(chunk) } | ||
| 514 | 514 | ||||
| 515 | func truncate(s string, n int) string { | 515 | func truncate(s string, n int) string { | ||
M internal/swarm/swarm_test.go +3 -3
| @@ -207,9 +207,9 @@ func TestSnapshotIsStableAcrossAccess(t *testing.T) { | |||
| 207 | 207 | ||
| 208 | 208 | func TestTaskSlug(t *testing.T) { | |
| 209 | 209 | cases := map[string]string{ | |
| 210 | - | "fix the login form": "fix-the-login-form", | |
| 211 | - | " weird --- spaces!! ": "weird-spaces", | |
| 212 | - | "": "agent", | |
| 210 | + | "fix the login form": "fix-the-login-form", | |
| 211 | + | " weird --- spaces!! ": "weird-spaces", | |
| 212 | + | "": "agent", | |
| 213 | 213 | "a-very-long-task-name-that-overflows": "a-very-long-task-name-th", | |
| 214 | 214 | } | |
| 215 | 215 | for in, want := range cases { | |
| @@ -207,9 +207,9 @@ func TestSnapshotIsStableAcrossAccess(t *testing.T) { | |||||
| 207 | 207 | ||||
| 208 | func TestTaskSlug(t *testing.T) { | 208 | func TestTaskSlug(t *testing.T) { | ||
| 209 | cases := map[string]string{ | 209 | cases := map[string]string{ | ||
| 210 | - | "fix the login form": "fix-the-login-form", | 210 | + | "fix the login form": "fix-the-login-form", |
| 211 | - | " weird --- spaces!! ": "weird-spaces", | 211 | + | " weird --- spaces!! ": "weird-spaces", |
| 212 | - | "": "agent", | 212 | + | "": "agent", |
| 213 | "a-very-long-task-name-that-overflows": "a-very-long-task-name-th", | 213 | "a-very-long-task-name-that-overflows": "a-very-long-task-name-th", | ||
| 214 | } | 214 | } | ||
| 215 | for in, want := range cases { | 215 | for in, want := range cases { | ||