Simplify session lifecycle and MCP cleanup
This commit is contained in:
@@ -8,6 +8,7 @@ import (
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/hjbdev/patterm/internal/projectkey"
|
||||
"github.com/hjbdev/patterm/internal/trust"
|
||||
@@ -179,9 +180,18 @@ func defaultPattermBin() (string, error) {
|
||||
if p := os.Getenv("PATTERM_BIN"); p != "" {
|
||||
return p, nil
|
||||
}
|
||||
return buildPattermBinary()
|
||||
defaultBinOnce.Do(func() {
|
||||
defaultBinPath, defaultBinErr = buildPattermBinary()
|
||||
})
|
||||
return defaultBinPath, defaultBinErr
|
||||
}
|
||||
|
||||
var (
|
||||
defaultBinOnce sync.Once
|
||||
defaultBinPath string
|
||||
defaultBinErr error
|
||||
)
|
||||
|
||||
func buildPattermBinary() (string, error) {
|
||||
root, err := repoRoot()
|
||||
if err != nil {
|
||||
|
||||
@@ -21,9 +21,16 @@ func (s *Session) DumpArtifacts(sc *Scenario, failingStep int, cause error) (*Ar
|
||||
if name == "" {
|
||||
name = "scenario"
|
||||
}
|
||||
dir := filepath.Join("internal", "harness", ".artifacts", fmt.Sprintf("%s-%d", name, time.Now().Unix()))
|
||||
abs, _ := filepath.Abs(dir)
|
||||
if err := os.MkdirAll(abs, 0o700); err != nil {
|
||||
root, err := repoRoot()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
base := filepath.Join(root, "internal", "harness", ".artifacts")
|
||||
if err := os.MkdirAll(base, 0o700); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
abs, err := os.MkdirTemp(base, fmt.Sprintf("%s-%d-*", name, time.Now().UnixNano()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
screen, _ := s.em.ScreenText()
|
||||
|
||||
@@ -210,19 +210,19 @@ func (s *Session) WaitForStable(timeout time.Duration) error {
|
||||
}
|
||||
|
||||
func (s *Session) WaitForText(text string, timeout time.Duration) error {
|
||||
deadline := time.Now().Add(timeout)
|
||||
for time.Now().Before(deadline) {
|
||||
return pollUntil(timeout, 25*time.Millisecond, func() (bool, error) {
|
||||
screen, err := s.Screen()
|
||||
if err != nil {
|
||||
return err
|
||||
return false, err
|
||||
}
|
||||
if strings.Contains(screen, text) {
|
||||
return nil
|
||||
return true, nil
|
||||
}
|
||||
time.Sleep(25 * time.Millisecond)
|
||||
}
|
||||
screen, _ := s.Screen()
|
||||
return fmt.Errorf("text %q not found before timeout; screen:\n%s", text, screen)
|
||||
return false, nil
|
||||
}, func() error {
|
||||
screen, _ := s.Screen()
|
||||
return fmt.Errorf("text %q not found before timeout; screen:\n%s", text, screen)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *Session) WaitForRegex(pattern string, timeout time.Duration) error {
|
||||
@@ -230,19 +230,31 @@ func (s *Session) WaitForRegex(pattern string, timeout time.Duration) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
deadline := time.Now().Add(timeout)
|
||||
for time.Now().Before(deadline) {
|
||||
return pollUntil(timeout, 25*time.Millisecond, func() (bool, error) {
|
||||
screen, err := s.Screen()
|
||||
if err != nil {
|
||||
return err
|
||||
return false, err
|
||||
}
|
||||
if re.MatchString(screen) {
|
||||
return nil
|
||||
return true, nil
|
||||
}
|
||||
time.Sleep(25 * time.Millisecond)
|
||||
return false, nil
|
||||
}, func() error {
|
||||
screen, _ := s.Screen()
|
||||
return fmt.Errorf("regex %q not found before timeout; screen:\n%s", pattern, screen)
|
||||
})
|
||||
}
|
||||
|
||||
func pollUntil(timeout, interval time.Duration, check func() (bool, error), timeoutErr func() error) error {
|
||||
deadline := time.Now().Add(timeout)
|
||||
for time.Now().Before(deadline) {
|
||||
ok, err := check()
|
||||
if err != nil || ok {
|
||||
return err
|
||||
}
|
||||
time.Sleep(interval)
|
||||
}
|
||||
screen, _ := s.Screen()
|
||||
return fmt.Errorf("regex %q not found before timeout; screen:\n%s", pattern, screen)
|
||||
return timeoutErr()
|
||||
}
|
||||
|
||||
func (s *Session) MCPCall(method string, params json.RawMessage) (json.RawMessage, error) {
|
||||
|
||||
Reference in New Issue
Block a user