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
5 changes: 5 additions & 0 deletions cmd/dev.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package cmd

import (
"context"
"errors"
"fmt"
"io"
"os"
Expand Down Expand Up @@ -123,6 +124,10 @@ Examples:
tuiLoggerErr := dev.NewTUILogger(logLevel, ui, dev.StdErr)

if err := server.Connect(ui, tuiLogger, tuiLoggerErr); err != nil {
if errors.Is(err, context.Canceled) {
ui.Close(true)
return
}
log.Error("failed to start live dev connection: %s", err)
ui.Close(true)
return
Expand Down
60 changes: 32 additions & 28 deletions internal/bundler/shim.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,39 +69,43 @@ function getSourceMap(filename) {
}
const frameRegex = /(.+)\((.+):(\d+):(\d+)\)$/;
Error.prepareStackTrace = function (err, stack) {
const _stack = __prepareStackTrace(err, stack);
const tok = _stack.split('\n');
const lines = [];
for (const t of tok) {
if (t.includes('.agentuity/') && frameRegex.test(t)) {
const parts = frameRegex.exec(t);
if (parts.length === 5) {
const filename = parts[2];
const sm = getSourceMap(filename+'.map');
if (sm) {
const lineno = parts[3];
const colno = parts[4];
const pos = sm.originalPositionFor({
line: +lineno,
column: +colno,
})
if (pos && pos.source) {
const startIndex = filename.indexOf('.agentuity/');
const offset = filename.includes('../node_modules/') ? 11 : 0;
const basedir = filename.substring(0, startIndex + offset);
const sourceOffset = pos.source.indexOf('src/');
const source = pos.source.substring(sourceOffset);
const newfile = __agentuity_join(basedir, source);
const newline = parts[1] + '(' + newfile + ':' + pos.line + ':' + pos.column + ')';
lines.push(newline);
continue;
try {
const _stack = __prepareStackTrace(err, stack);
const tok = _stack.split('\n');
const lines = [];
for (const t of tok) {
if (t.includes('.agentuity/') && frameRegex.test(t)) {
const parts = frameRegex.exec(t);
if (parts.length === 5) {
const filename = parts[2];
const sm = getSourceMap(filename+'.map');
if (sm) {
const lineno = parts[3];
const colno = parts[4];
const pos = sm.originalPositionFor({
line: +lineno,
column: +colno,
})
if (pos && pos.source) {
const startIndex = filename.indexOf('.agentuity/');
const offset = filename.includes('../node_modules/') ? 11 : 0;
const basedir = filename.substring(0, startIndex + offset);
const sourceOffset = pos.source.indexOf('src/');
const source = pos.source.substring(sourceOffset);
const newfile = __agentuity_join(basedir, source);
const newline = parts[1] + '(' + newfile + ':' + pos.line + ':' + pos.column + ')';
lines.push(newline);
continue;
}
}
}
}
lines.push(t);
}
lines.push(t);
return lines.join('\n');
} catch (e) {
return stack;
}
return lines.join('\n');
};
})();
`
40 changes: 25 additions & 15 deletions internal/dev/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ type Server struct {
apiclient *util.APIClient
publicUrl string
port int
connected chan string
connected chan error
pendingLogger logger.Logger
expiresAt *time.Time
tlsCertificate *tls.Certificate
Expand Down Expand Up @@ -161,14 +161,16 @@ func (s *Server) reconnect() {
func (s *Server) connect(initial bool) {
var gerr error

s.logger.Trace("connecting to devmode server")

// hold a connection lock to prevent multiple go routines from trying to reconnect
// before the previous connect goroutine has finished
s.connectionLock.Lock()
defer s.connectionLock.Unlock()

defer func() {
if initial && gerr != nil {
s.connected <- gerr.Error()
s.connected <- gerr
}
s.logger.Debug("connection closed")
select {
Expand Down Expand Up @@ -201,12 +203,19 @@ func (s *Server) connect(initial bool) {
}
}()

s.logger.Trace("refreshing connection metadata")
refreshStart := time.Now()
if err := s.refreshConnection(); err != nil {
s.logger.Error("failed to refresh connection: %s", err)
if !initial {
s.logger.Error("failed to refresh connection: %s", err)
}
// initial will bubble this up
gerr = err
return
}

s.logger.Trace("refreshed connection metadata in %v", time.Since(refreshStart))

var tlsConfig tls.Config
tlsConfig.Certificates = []tls.Certificate{*s.tlsCertificate}
tlsConfig.NextProtos = []string{"h2"}
Expand All @@ -221,16 +230,19 @@ func (s *Server) connect(initial bool) {
hostname = fmt.Sprintf("%s:443", hostname)
}

s.logger.Trace("dialing devmode server: %s", hostname)
dialStart := time.Now()
conn, err := tls.Dial("tcp", hostname, &tlsConfig)
if err != nil {
gerr = err
s.logger.Warn("failed to dial devmode server: %s (%s), will retry ...", hostname, err)
return
}
s.conn = conn
s.logger.Trace("dialed devmode server in %v", time.Since(dialStart))

if initial {
s.connected <- ""
s.connected <- nil
}

// if we successfully connect, reset our connection failures
Expand Down Expand Up @@ -557,18 +569,15 @@ func (s *Server) HealthCheck(devModeUrl string) error {
}

func (s *Server) Connect(ui *DevModeUI, tuiLogger logger.Logger, tuiLoggerErr logger.Logger) error {
s.logger = tuiLogger
if pl, ok := tuiLoggerErr.(*PendingLogger); ok {
pl.drain(ui, tuiLoggerErr)
}
if pl, ok := s.logger.(*PendingLogger); ok {
pl.drain(ui, s.logger)
pl.drain(ui, tuiLogger)
}
s.logger = tuiLogger
s.pendingLogger = s.logger
msg := <-s.connected
err := <-s.connected
close(s.connected)
if msg != "" {
return fmt.Errorf("%s", msg)
if err != nil {
return err
}
return nil
}
Expand All @@ -590,11 +599,12 @@ func (s *Server) monitor() {
}

func New(args ServerArgs) (*Server, error) {
id := cstr.NewHash(args.OrgId, args.UserId)
id := cstr.NewHash(args.Project.Project.ProjectId, args.UserId)
tracer := otel.Tracer("@agentuity/cli", trace.WithInstrumentationAttributes(
attribute.String("id", id),
attribute.String("@agentuity/orgId", args.OrgId),
attribute.String("@agentuity/userId", args.UserId),
attribute.String("@agentuity/projectId", args.Project.Project.ProjectId),
attribute.Bool("@agentuity/devmode", true),
attribute.String("name", "@agentuity/cli"),
attribute.String("version", args.Version),
Expand All @@ -618,9 +628,9 @@ func New(args ServerArgs) (*Server, error) {
tracer: tracer,
version: args.Version,
port: args.Port,
apiclient: util.NewAPIClient(context.Background(), pendingLogger, args.APIURL, args.APIKey),
apiclient: util.NewAPIClient(ctx, pendingLogger, args.APIURL, args.APIKey),
pendingLogger: pendingLogger,
connected: make(chan string, 1),
connected: make(chan error, 1),
}

go server.connect(true)
Expand Down
3 changes: 3 additions & 0 deletions internal/util/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,9 @@ func (c *APIClient) Do(method, pathParam string, payload interface{}, response i
continue
}
if err != nil {
if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) {
return err
}
return NewAPIError(u.String(), method, 0, "", fmt.Errorf("error sending request: %w", err), traceID)
}
break
Expand Down
Loading