Skip to content

feat: proxy /conversations passthrough and response↔conversation linking #83

Description

@elevran

Scope

Extend cmd/proxyd to support the /conversations endpoints and to link response turns to conversations when a request carries conversation_id instead of previous_response_id.

Key design decisions

Mutual exclusion: conversation_id vs. previous_response_id

A POST /responses request may carry either conversation_id or previous_response_id, but not both. The proxy validates this at request parse time and returns 400 Bad Request with an error code invalid_request if both are present.

Conversation ID is a stable identifier

Unlike previous_response_id (which changes every turn), conversation_id is stable for the lifetime of the conversation. Each response turn that belongs to a conversation appends its input/output messages to the conversation via PUT /conversations/{id}/messages after inference.

Prior context resolution

When conversation_id is present:

  1. Proxy calls GET /conversations/{id}/messages to retrieve the full message history (flat context).
  2. Proxy appends the new input[] to the flat context and calls the inference backend.
  3. After inference, proxy calls PUT /conversations/{id}/messages to append the new input + output to the conversation.
  4. If store: true, proxy also calls POST /responses on Charon (responsed) with no previous_response_id — the response turn is stored as an independent node (not chained). The returned response_id is included in the POST /responses response to the client.

When previous_response_id is present: existing behaviour (unchanged).

/conversations passthrough

For POST /conversations, GET /conversations/{id}, DELETE /conversations/{id}, PUT /conversations/{id}/messages, and GET /conversations/{id}/messages: the proxy forwards these directly to conversationd with no transformation. The proxy acts as a transparent router for these routes.

Changes to cmd/proxyd

New dependency

cmd/proxyd (and cmd/conversationd) get a pkg/conversation client package (mirrors pkg/charon) with:

type Backend interface {
    Create(ctx context.Context, meta ConversationMeta) (ConversationMeta, error)
    Get(ctx context.Context, id string) (ConversationMeta, error)
    Delete(ctx context.Context, id string) error
    AppendMessages(ctx context.Context, id string, messages []Message) (uint64, error)
    ListMessages(ctx context.Context, id string, afterSeq uint64, limit int) ([]Message, error)
}

Handler changes (cmd/proxy/handler.go)

  • CreateRequest gains ConversationID *string json:"conversation_id,omitempty"``
  • HandleCreate dispatches on ConversationID != nil vs. PreviousResponseID != nil
  • Add HandleConversationCreate, HandleConversationGet, HandleConversationDelete, HandleConversationAppendMessages, HandleConversationListMessages — all forwarding to the conversation.Backend
  • Register routes: POST /conversations, GET /conversations/{id}, DELETE /conversations/{id}, PUT /conversations/{id}/messages, GET /conversations/{id}/messages

Config

ProxyOptions gains ConversationdURL string (see #78). Default derived from conversationd default listen address.

Acceptance criteria

  • POST /responses with both conversation_id and previous_response_id returns 400
  • POST /responses with conversation_id resolves context from conversation store, not chainstore
  • After inference with conversation_id, new messages are appended to the conversation
  • store: true + conversation_id: response is also stored in responsed as a standalone node
  • store: false + conversation_id: response is appended to conversation but not stored in responsed
  • All /conversations passthrough routes reach cmd/conversationd
  • make presubmit passes
  • Unit tests cover the conversation_id / previous_response_id dispatch paths

Blocked by: #81, #78

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions