Skip to content

Commit 6ca5415

Browse files
committed
test message
1 parent 6672aa9 commit 6ca5415

3 files changed

Lines changed: 26 additions & 35 deletions

File tree

cmd/iterate/repl.go

Lines changed: 1 addition & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -131,40 +131,19 @@ func replHooks() iteragent.AgentHooks {
131131
}
132132
}
133133

134-
// ctrlCExitCh is closed when the user presses Ctrl+C while idle (no active request).
135-
// The REPL loop listens on this channel to exit cleanly.
136-
var ctrlCExitCh = make(chan struct{}, 1)
137-
138134
// initREPL loads config, applies theme, sets up signal handling and runtime state.
139135
func setupSigintHandler() {
140136
sigCh := make(chan os.Signal, 1)
141137
signal.Notify(sigCh, syscall.SIGINT)
142138
go func() {
143-
var lastIdle time.Time
144139
for range sigCh {
145140
if sess.RequestCancel != nil {
146-
// Active request — cancel it.
147141
sess.RequestCancel()
142+
// Snapshot colors under read lock — applyTheme writes these from the main goroutine.
148143
colorMu.RLock()
149144
y, r := colorYellow, colorReset
150145
colorMu.RUnlock()
151146
fmt.Printf("\r\033[K%s[cancelled]%s\n", y, r)
152-
lastIdle = time.Time{} // reset idle timer after cancel
153-
} else {
154-
// Idle — double-Ctrl+C to exit.
155-
now := time.Now()
156-
if !lastIdle.IsZero() && now.Sub(lastIdle) < 2*time.Second {
157-
select {
158-
case ctrlCExitCh <- struct{}{}:
159-
default:
160-
}
161-
} else {
162-
lastIdle = now
163-
colorMu.RLock()
164-
d, r := colorDim, colorReset
165-
colorMu.RUnlock()
166-
fmt.Printf("\r\033[K%s(press Ctrl+C again to exit)%s\n", d, r)
167-
}
168147
}
169148
}
170149
}()
@@ -242,20 +221,8 @@ func runREPL(ctx context.Context, p iteragent.Provider, repoPath string, thinkin
242221
}
243222

244223
for {
245-
// Check for double-Ctrl+C exit signal before blocking on ReadInput.
246-
select {
247-
case <-ctrlCExitCh:
248-
return
249-
default:
250-
}
251-
252224
line, ok := selector.ReadInput()
253225
if !ok {
254-
// Check if this was a double-Ctrl+C exit.
255-
select {
256-
case <-ctrlCExitCh:
257-
default:
258-
}
259226
break
260227
}
261228
if line == "" {

internal/commands/newfeatures_test.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,25 @@ func TestCmdTrim_KeepsLastTurns(t *testing.T) {
306306
}
307307
}
308308

309+
// TestCmdTrim_NoUserMessageInTail covers the out-of-bounds case where every
310+
// message in the kept tail has a non-user role (pathological but must not panic).
311+
func TestCmdTrim_NoUserMessageInTail(t *testing.T) {
312+
ag := &iteragent.Agent{}
313+
// 10 assistant-only messages — no user messages anywhere.
314+
for i := 0; i < 10; i++ {
315+
ag.Messages = append(ag.Messages, iteragent.Message{Role: "assistant", Content: "a"})
316+
}
317+
ctx := Context{
318+
Parts: []string{"/trim", "2"},
319+
Agent: ag,
320+
}
321+
// Must not panic.
322+
result := cmdTrim(ctx)
323+
if !result.Handled {
324+
t.Error("expected handled")
325+
}
326+
}
327+
309328
func TestCmdTrim_AlreadySmall(t *testing.T) {
310329
ag := &iteragent.Agent{}
311330
ag.Messages = []iteragent.Message{

internal/commands/session.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -474,9 +474,14 @@ func cmdTrim(ctx Context) Result {
474474

475475
// Align to a user-message boundary so we always start on a user turn.
476476
startIdx := len(msgs) - keep
477-
for startIdx > 0 && msgs[startIdx].Role != "user" {
477+
for startIdx > 0 && startIdx < len(msgs) && msgs[startIdx].Role != "user" {
478478
startIdx++
479479
}
480+
if startIdx >= len(msgs) {
481+
// Pathological case: no user message found in the tail — keep everything.
482+
fmt.Printf("Context already at minimum (%d messages).\n", len(msgs))
483+
return Result{Handled: true}
484+
}
480485

481486
before := len(msgs)
482487
ctx.Agent.Messages = msgs[startIdx:]

0 commit comments

Comments
 (0)