Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions go/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,21 +130,22 @@ func normalizedTraceLevel(level string) string {
}
}

func formatError(err *evalError, level string) string {
func formatError(err *evalError, level, sessionID string) string {
traceHint := strings.TrimSpace(err.smart) != strings.TrimSpace(err.short)
hint := fmt.Sprintf("Trace saved: `repld trace %s`.", sessionID)
switch normalizedTraceLevel(level) {
case "short":
if !traceHint {
return err.short
}
return err.short + "\n\nTrace saved: run `trace --trace [smart|full]` to inspect"
return err.short + "\n\n" + hint
case "full":
return err.full
default:
if !traceHint {
return err.short
}
return err.smart + "Trace saved: run `trace` to inspect"
return err.smart + hint
}
}

Expand Down Expand Up @@ -243,7 +244,7 @@ func handleStreamingEval(state *daemonState, req protocolRequest, conn net.Conn)
}
if evalErr, ok := err.(*evalError); ok {
state.manager.recordError(req.Lang, req.Session, req.Cwd, disc, evalErr)
emit(streamFrame{Done: true, Error: formatError(evalErr, req.TraceLevel)})
emit(streamFrame{Done: true, Error: formatError(evalErr, req.TraceLevel, sess.id)})
return
}
emit(streamFrame{Done: true, Error: err.Error()})
Expand Down
9 changes: 8 additions & 1 deletion go/engine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,13 @@ func TestHandleRequest_UnknownAction(t *testing.T) {
require.NotEmpty(t, resp.Error)
}

func TestFormatErrorTraceHintIncludesSessionID(t *testing.T) {
err := &evalError{short: "short", smart: "smart\n", full: "full"}
require.Equal(t, "smart\nTrace saved: `repld trace klmnopqr`.", formatError(err, "smart", "klmnopqr"))
require.Equal(t, "short\n\nTrace saved: `repld trace klmnopqr`.", formatError(err, "short", "klmnopqr"))
require.Equal(t, "full", formatError(err, "full", "klmnopqr"))
}

func TestHandleRequest_Stop(t *testing.T) {
state := newTestState()
resp := handleRequest(state, protocolRequest{Action: "stop"})
Expand Down Expand Up @@ -206,4 +213,4 @@ func TestSessionManagerKey(t *testing.T) {
// a --session label is global: same key regardless of language/project.
require.Equal(t, sessionKey{label: "scratch"}, m.key("julia", "scratch", "/w", "@."))
require.Equal(t, sessionKey{label: "scratch"}, m.key("python", "scratch", "/other", ""))
}
}
8 changes: 5 additions & 3 deletions go/julia_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"os"
"os/exec"
"path/filepath"
"regexp"
"strings"
"testing"
"time"
Expand Down Expand Up @@ -110,15 +111,16 @@ func TestJuliaWarmSession(t *testing.T) {
require.Empty(t, res.stdout)
require.Contains(t, res.stderr, "boom")
require.Contains(t, res.stderr, "Stacktrace:")
require.Contains(t, res.stderr, "run `trace")
hint := regexp.MustCompile("Trace saved: `repld trace ([k-z]{8})`\\.").FindStringSubmatch(res.stderr)
require.Len(t, hint, 2)
require.NotContains(t, res.stderr, "eval_user_input")

res = repldOK(t, socketPath, cwd, "trace", "--trace", "smart", "julia")
res = repldOK(t, socketPath, cwd, "trace", "--trace", "smart", hint[1])
require.Contains(t, res.stdout, "Stacktrace:")
require.Contains(t, res.stdout, "repld-eval")
require.NotContains(t, res.stdout, "eval_user_input")

res = repldOK(t, socketPath, cwd, "trace", "--trace", "full", "julia")
res = repldOK(t, socketPath, cwd, "trace", "--trace", "full", hint[1])
require.Contains(t, res.stdout, "include_string")

res = repldErr(t, socketPath, cwd, "--trace", "full", "julia", "-e", `let f = () -> error("boom"); g = () -> f(); g(); end`)
Expand Down
5 changes: 3 additions & 2 deletions skills/repld/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,9 @@ See [julia.md](references/julia.md), [python.md](references/python.md), [r.md](r

```bash
repld sessions # list active sessions, show IDs
repld trace [id | exe | --session=LABEL] # last saved traceback
repld [interrupt | close] [id | exe | --session=LABEL]
repld trace <id | --session=LABEL> # last saved traceback
repld interrupt <id | --session=LABEL>
repld close <id | --session=LABEL>
repld stop # shut down daemon

timeout 30 repld julia -e 'might_hang()' # client death interrupts eval
Expand Down
Loading