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
12 changes: 6 additions & 6 deletions lib/httpapi/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ type Server struct {
srv *http.Server
mu sync.RWMutex
logger *slog.Logger
conversation *st.Conversation
conversation *st.PTYConversation
Copy link
Collaborator

@35C4n0r 35C4n0r Jan 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@johnstcn Shouldn't this be *st.Conversation ? (It's possible that I'm lacking the context/motive behind this refactor, If we have extracted an interface, shouldn't we be using it rather than coupling this to the concrete implementation ?)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should, but there's some more coupling to be disentangled here before we can do that.

agentio *termexec.Process
agentType mf.AgentType
emitter *EventEmitter
Expand Down Expand Up @@ -237,7 +237,7 @@ func NewServer(ctx context.Context, config ServerConfig) (*Server, error) {
return mf.FormatToolCall(config.AgentType, message)
}

conversation := st.NewConversation(ctx, st.ConversationConfig{
conversation := st.NewPTY(ctx, st.PTYConversationConfig{
AgentType: config.AgentType,
AgentIO: config.Process,
GetTime: func() time.Time {
Expand Down Expand Up @@ -331,15 +331,15 @@ func sseMiddleware(ctx huma.Context, next func(huma.Context)) {
}

func (s *Server) StartSnapshotLoop(ctx context.Context) {
s.conversation.StartSnapshotLoop(ctx)
s.conversation.Start(ctx)
go func() {
for {
currentStatus := s.conversation.Status()

// Send initial prompt when agent becomes stable for the first time
if !s.conversation.InitialPromptSent && convertStatus(currentStatus) == AgentStatusStable {

if err := s.conversation.SendMessage(FormatMessage(s.agentType, s.conversation.InitialPrompt)...); err != nil {
if err := s.conversation.Send(FormatMessage(s.agentType, s.conversation.InitialPrompt)...); err != nil {
s.logger.Error("Failed to send initial prompt", "error", err)
} else {
s.conversation.InitialPromptSent = true
Expand All @@ -350,7 +350,7 @@ func (s *Server) StartSnapshotLoop(ctx context.Context) {
}
s.emitter.UpdateStatusAndEmitChanges(currentStatus, s.agentType)
s.emitter.UpdateMessagesAndEmitChanges(s.conversation.Messages())
s.emitter.UpdateScreenAndEmitChanges(s.conversation.Screen())
s.emitter.UpdateScreenAndEmitChanges(s.conversation.String())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question: Are there repercussions to implementing fmt.Stringer here? While Screen may have been too focused on CLI tooling, perhaps another function name like Text would be more appropriate/portable? Or if the intent isn't to support other protocols (like ACP), then we could consider sticking to screen.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good point. I'd prefer for the method name to be applicable to be all protocols, so Text() seems appropriate.

time.Sleep(snapshotInterval)
}
}()
Expand Down Expand Up @@ -449,7 +449,7 @@ func (s *Server) createMessage(ctx context.Context, input *MessageRequest) (*Mes

switch input.Body.Type {
case MessageTypeUser:
if err := s.conversation.SendMessage(FormatMessage(s.agentType, input.Body.Content)...); err != nil {
if err := s.conversation.Send(FormatMessage(s.agentType, input.Body.Content)...); err != nil {
return nil, xerrors.Errorf("failed to send message: %w", err)
}
case MessageTypeRaw:
Expand Down
Loading