Skip to content
Open
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
2,261 changes: 2,261 additions & 0 deletions erst_extension/package-lock.json

Large diffs are not rendered by default.

84 changes: 42 additions & 42 deletions erst_extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,55 +46,55 @@
]
},
"categories": [
"Debuggers"
"Debuggers"
],
"activationEvents": [],
"main": "./out/extension.js",
"contributes": {
"commands": [
{
"command": "erst.triggerDebug",
"title": "ERST: Trigger Debug",
"category": "ERST"
}
],
"viewsContainers": {
"activitybar": [
{
"id": "erst-explorer",
"title": "ERST",
"icon": "$(debug-console)"
}
]
},
"views": {
"erst-explorer": [
{
"id": "erst-traces",
"name": "Traces"
}
]
"commands": [
{
"command": "erst.triggerDebug",
"title": "ERST: Trigger Debug",
"category": "ERST"
}
],
"viewsContainers": {
"activitybar": [
{
"id": "erst-explorer",
"title": "ERST",
"icon": "$(debug-console)"
}
]
},
"views": {
"erst-explorer": [
{
"id": "erst-traces",
"name": "Traces"
}
]
}
},
"scripts": {
"vscode:prepublish": "npm run compile",
"compile": "tsc -p ./",
"watch": "tsc -watch -p ./",
"pretest": "npm run compile && npm run lint",
"lint": "eslint src --ext ts",
"test": "node ./out/test/runTest.js"
"vscode:prepublish": "npm run compile",
"compile": "tsc -p ./",
"watch": "tsc -watch -p ./",
"pretest": "npm run compile && npm run lint",
"lint": "eslint src --ext ts",
"test": "node ./out/test/runTest.js"
},
"dependencies": {
"vscode-jsonrpc": "^8.2.1"
"vscode-jsonrpc": "^8.2.1"
},
"devDependencies": {
"@types/vscode": "^1.90.0",
"@types/node": "^20.0.0",
"@typescript-eslint/eslint-plugin": "^7.0.0",
"@typescript-eslint/parser": "^7.0.0",
"eslint": "^8.0.0",
"typescript": "^5.4.0",
"@vscode/test-electron": "^2.4.0"
"@types/vscode": "^1.90.0",
"@types/node": "^20.0.0",
"@typescript-eslint/eslint-plugin": "^7.0.0",
"@typescript-eslint/parser": "^7.0.0",
"eslint": "^8.0.0",
"typescript": "^5.4.0",
"@vscode/test-electron": "^2.4.0"
}
},
"scripts": {
Expand All @@ -110,12 +110,12 @@
"vscode-jsonrpc": "^8.2.1"
},
"devDependencies": {
"@types/vscode": "^1.90.0",
"@types/node": "^20.0.0",
"@types/node": "^20.19.37",
"@types/vscode": "^1.110.0",
"@typescript-eslint/eslint-plugin": "^7.0.0",
"@typescript-eslint/parser": "^7.0.0",
"@vscode/test-electron": "^2.4.0",
"eslint": "^8.0.0",
"typescript": "^5.4.0",
"@vscode/test-electron": "^2.4.0"
"typescript": "^5.4.0"
}
}
12 changes: 12 additions & 0 deletions internal/cmd/debug.go
Original file line number Diff line number Diff line change
Expand Up @@ -1336,6 +1336,18 @@ func init() {
debugCmd.Flags().Uint32Var(&protocolVersionFlag, "protocol-version", 0, "Override protocol version for simulation")

rootCmd.AddCommand(debugCmd)
// Register temp snapshot cleanup hook
registerShutdownHook("cleanup-temp-snapshots", func(ctx context.Context) error {
count, err := session.CleanupTempArtifacts()
if verbose {
if err != nil {
fmt.Fprintf(os.Stderr, "[cleanup] Error cleaning temp snapshots: %v\n", err)
} else {
fmt.Fprintf(os.Stderr, "[cleanup] Removed %d temp snapshot files\n", count)
}
}
return err
})
}

// checkLTOWarning searches the directory tree around a WASM file for
Expand Down
29 changes: 29 additions & 0 deletions internal/session/cleanup.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright 2026 Erst Users
// SPDX-License-Identifier: Apache-2.0

package session

import (
"os"
"path/filepath"
"runtime"
)

// CleanupTempArtifacts removes temporary snapshot/session files from the temp directory.
// Returns the number of files removed and any error encountered.
func CleanupTempArtifacts() (int, error) {
tmpDir := os.TempDir()
pattern := "erst-snapshot-*"
matches, err := filepath.Glob(filepath.Join(tmpDir, pattern))
if err != nil {
return 0, err
}
count := 0
for _, file := range matches {
err := os.RemoveAll(file)
if err == nil {
count++
}
}
return count, nil
}
37 changes: 37 additions & 0 deletions internal/session/cleanup_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright 2026 Erst Users
// SPDX-License-Identifier: Apache-2.0

package session

import (
"os"
"path/filepath"
"testing"
)

func TestCleanupTempArtifacts(t *testing.T) {
tmpDir := os.TempDir()
// Create fake temp files
files := []string{
filepath.Join(tmpDir, "erst-snapshot-foo"),
filepath.Join(tmpDir, "erst-snapshot-bar"),
}
for _, f := range files {
if err := os.WriteFile(f, []byte("test"), 0644); err != nil {
t.Fatalf("failed to create temp file: %v", err)
}
}

count, err := CleanupTempArtifacts()
if err != nil {
t.Fatalf("cleanup failed: %v", err)
}
if count < len(files) {
t.Errorf("expected at least %d files cleaned, got %d", len(files), count)
}
for _, f := range files {
if _, err := os.Stat(f); !os.IsNotExist(err) {
t.Errorf("file %s was not removed", f)
}
}
}
29 changes: 23 additions & 6 deletions internal/simulator/runner.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
// SnapshotRegistry defines snapshot/session management methods
type SnapshotRegistry interface {

Check failure on line 2 in internal/simulator/runner.go

View workflow job for this annotation

GitHub Actions / Go Strict Linting

expected 'package', found 'type'

Check failure on line 2 in internal/simulator/runner.go

View workflow job for this annotation

GitHub Actions / Go Strict Linting

expected 'package', found 'type'

Check failure on line 2 in internal/simulator/runner.go

View workflow job for this annotation

GitHub Actions / Validate CI scripts from non-root cwd

expected 'package', found 'type'

Check failure on line 2 in internal/simulator/runner.go

View workflow job for this annotation

GitHub Actions / Validate CI scripts from non-root cwd

expected 'package', found 'type'

Check failure on line 2 in internal/simulator/runner.go

View workflow job for this annotation

GitHub Actions / Integration / Windows

expected 'package', found 'type'

Check failure on line 2 in internal/simulator/runner.go

View workflow job for this annotation

GitHub Actions / Integration / macOS-Apple-Silicon

expected 'package', found 'type'

Check failure on line 2 in internal/simulator/runner.go

View workflow job for this annotation

GitHub Actions / Integration / Linux

expected 'package', found 'type'

Check failure on line 2 in internal/simulator/runner.go

View workflow job for this annotation

GitHub Actions / Integration / macOS-Intel

expected 'package', found 'type'
SaveSession(s *Session) error
SearchSessions(filters SearchFilters) ([]Session, error)
}

// Copyright 2026 Erst Users
// SPDX-License-Identifier: Apache-2.0

Expand Down Expand Up @@ -32,6 +38,7 @@
closed bool
MockTime int64 // non-zero overrides Timestamp in every SimulationRequest
Validator *Validator
Registry SnapshotRegistry
}

// Compile-time check to ensure Runner implements RunnerInterface
Expand All @@ -58,12 +65,22 @@
)
}

return &Runner{
BinaryPath: path,
Debug: debug,
activeCmds: make(map[*exec.Cmd]struct{}),
Validator: NewValidator(false),
}, nil
return &Runner{
BinaryPath: path,
Debug: debug,
activeCmds: make(map[*exec.Cmd]struct{}),
Validator: NewValidator(false),
}, nil

// NewRunnerWithRegistry allows injecting a SnapshotRegistry
func NewRunnerWithRegistry(simPathOverride string, debug bool, reg SnapshotRegistry) (*Runner, error) {
r, err := NewRunner(simPathOverride, debug)
if err != nil {
return nil, err
}
r.Registry = reg
return r, nil
}
}

// NewRunnerWithMockTime creates a Runner that overrides the ledger timestamp on
Expand Down
2 changes: 2 additions & 0 deletions internal/simulator/session.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Ensure DB implements SnapshotRegistry
var _ SnapshotRegistry = (*DB)(nil)

Check failure on line 2 in internal/simulator/session.go

View workflow job for this annotation

GitHub Actions / Go Strict Linting

expected 'package', found 'var'

Check failure on line 2 in internal/simulator/session.go

View workflow job for this annotation

GitHub Actions / Go Strict Linting

expected 'package', found 'var'

Check failure on line 2 in internal/simulator/session.go

View workflow job for this annotation

GitHub Actions / Validate CI scripts from non-root cwd

expected 'package', found 'var'

Check failure on line 2 in internal/simulator/session.go

View workflow job for this annotation

GitHub Actions / Validate CI scripts from non-root cwd

expected 'package', found 'var'
// Copyright 2026 Erst Users
// SPDX-License-Identifier: Apache-2.0

Expand Down
32 changes: 31 additions & 1 deletion internal/trace/viewer.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"strconv"
"strings"

"encoding/json"
"github.com/atotto/clipboard"
"github.com/dotandev/hintents/internal/dwarf"
"github.com/dotandev/hintents/internal/visualizer"
Expand Down Expand Up @@ -154,6 +155,9 @@ func (v *InteractiveViewer) handleCommand(command string) bool {
}

switch cmd {
case "e", "export":
v.exportCurrentFrame()
return false
case "n", "next", "forward":
v.stepForward()
case "p", "prev", "back", "backward":
Expand Down Expand Up @@ -203,6 +207,32 @@ func (v *InteractiveViewer) handleCommand(command string) bool {

return false
}
// exportCurrentFrame prompts for a filename and saves the current state as pretty JSON
func (v *InteractiveViewer) exportCurrentFrame() {
state, err := v.trace.GetCurrentState()
if err != nil {
fmt.Printf("%s %s\n", visualizer.Error(), err)
return
}
defaultName := fmt.Sprintf("frame_%d.json", state.Step)
fmt.Printf("Export current frame to file (default: %s): ", defaultName)
input, _ := v.reader.ReadString('\n')
filename := strings.TrimSpace(input)
if filename == "" {
filename = defaultName
}
data, err := json.MarshalIndent(state, "", " ")
if err != nil {
fmt.Printf("%s Failed to encode frame: %v\n", visualizer.Error(), err)
return
}
err = os.WriteFile(filename, data, 0644)
if err != nil {
fmt.Printf("%s Failed to write file: %v\n", visualizer.Error(), err)
return
}
fmt.Printf("%s Frame exported to %s\n", visualizer.Success(), filename)
}

// stepForward moves to the next step, respecting the event filter and hideStdLib toggle.
func (v *InteractiveViewer) stepForward() {
Expand Down Expand Up @@ -565,7 +595,7 @@ func (v *InteractiveViewer) showHelp() {
fmt.Println()
fmt.Println("Display:")
fmt.Println(" s, show, state - Show current state")
fmt.Println(" e, expand - Expand / show full detail of current step")
fmt.Println(" e, export - Export current frame as JSON")
fmt.Println(" S - Toggle hiding/showing Rust core::* traces")
fmt.Println(" e, expand - Expand / collapse the current trace node")
fmt.Println(" r, reconstruct [step] - Reconstruct state")
Expand Down
Loading