Feature: Insert Message Above/Below in Conversation (InsertMessage) #144

Closed
opened 2025-12-23 23:21:46 +00:00 by rwachters · 0 comments
rwachters commented 2025-12-23 23:21:46 +00:00 (Migrated from github.com)

Summary

Add a feature that allows inserting a new user or assistant message above or below an existing message in a conversation thread. Users pick "Insert" from a message's More Actions menu, configure insertion options (position, role, optional content) via a dialog, and confirm to insert a new message into the conversation tree in the appropriate place.

Why

This improves editing/fine-tuning conversations by letting users introduce new messages at a specific point in a thread without manually copying content or moving messages.

Acceptance criteria

  • A dialog is available to choose position (above/below), role (user/assistant), and optional initial content.
  • The More Actions menu for a message contains an "Insert" action that opens the dialog for the targeted message.
  • On confirm, the new message is created via the server API and the client updates the session state so the UI shows the new message in the correct location and updates session leaf when appropriate.
  • Server validates the request and persists the message with correct parent/child/sibling relationships.
  • Repository and service layers return clear error types (use Arrow Either for repo errors and logical errors per project guidance).

Implementation tasks (suggested order)

Frontend (app module)

  • Add InsertMessage dialog state to ChatAreaDialogState with fields:

    • targetMessage (message id or message object)
    • position (default: BELOW)
    • role (default: USER)
    • content (optional string)
    • onConfirm callback
    • onDismiss callback
  • Create Insert Message dialog UI in Dialogs.kt:

    • Radio buttons for position: Above / Below.
    • Radio buttons for role: User / Assistant.
    • Text field for optional content.
    • Confirm and Cancel buttons.
  • Add "Insert" menu item to MoreActionsMenu in MessageActionRow.kt that triggers an onRequestInsertMessage(targetMessage) action.

  • Add onRequestInsertMessage to MessageActions and ChatAreaActions interfaces and wire through to ChatViewModel so the view model can show the dialog with the target message preselected.

  • Implement requestInsertMessage and confirmInsertMessage flows in ChatViewModel:

    • requestInsertMessage shows the InsertMessage dialog with the selected target message.
    • confirmInsertMessage calls the MessageRepository.insertMessage with modelId and settingsId from the current session, then updates the session's message tree/leaf with the new message ID.

Common (shared module)

  • Create InsertMessageRequest model in common/src/commonMain/kotlin/eu/torvian/chatbot/common/models/api/core/ with fields:

    • targetMessageId: String
    • position: Position enum (ABOVE | BELOW)
    • role: Role enum (USER | ASSISTANT)
    • content: String?
    • modelId: String
    • settingsId: String
  • Add serialization annotations consistent with existing API models.

Client API / Repository

  • Add insertMessage method to MessageApiClient that POSTs InsertMessageRequest to server endpoint /api/v1/messages/insert and returns the created ChatMessage.

  • Add insertMessage method to MessageRepository that calls the API client, wraps results in Arrow Either returning RepositoryError or ChatMessage.

    • Ensure logical error types are used for expected failure cases (e.g., invalid target, permission), not low-level technical errors.

Server (server module)

  • Add POST /api/v1/messages/insert route in message routes that:

    • Validates request body and required permissions/session.
    • Calls MessageService.insertMessage(request).
    • Returns HTTP 201 with the created message or appropriate error codes.
  • Extend MessageService with insertMessage(request: InsertMessageRequest): ChatMessage that:

    • Loads the target message to determine parent/child relationships.
    • Determines parentMessageId: for ABOVE => target.parentMessageId; for BELOW => target.id.
    • Creates the new message with the chosen role and content, linking to parentMessageId.
    • Updates sibling relationships: if inserting ABOVE, adjust parent's child ordering such that the new message is placed before the target; if inserting BELOW, place after target in target's thread.
    • If insertion is BELOW and the session leaf needs to point to the new message, update session leaf accordingly.
    • Ensures operations are transactional and handles concurrency/conflicts.
  • Add insertMessage to MessageDao with SQL/Exposed logic to create the message and update sibling orderings and session leaf in a single transaction.

Testing

  • Add unit tests for MessageService.insertMessage covering ABOVE and BELOW cases, edge cases (target is root, target has no parent, inserting into empty thread), and session leaf update behavior.
  • Add integration test for the new API route.

Notes / assumptions

  • Use kotlinx.datetime for any date/time handling.
  • Use Arrow Either for repository error handling and return logical errors per project guidelines.
  • Message IDs and session IDs are strings in the current codebase—adapt if different.

Suggested labels: enhancement, backend, frontend

If you'd like, I can also open a PR scaffolding the InsertMessageRequest model and the client API method, or implement the frontend dialog first. Which subtask do you want me to take on next?

Summary Add a feature that allows inserting a new user or assistant message above or below an existing message in a conversation thread. Users pick "Insert" from a message's More Actions menu, configure insertion options (position, role, optional content) via a dialog, and confirm to insert a new message into the conversation tree in the appropriate place. Why This improves editing/fine-tuning conversations by letting users introduce new messages at a specific point in a thread without manually copying content or moving messages. Acceptance criteria - A dialog is available to choose position (above/below), role (user/assistant), and optional initial content. - The More Actions menu for a message contains an "Insert" action that opens the dialog for the targeted message. - On confirm, the new message is created via the server API and the client updates the session state so the UI shows the new message in the correct location and updates session leaf when appropriate. - Server validates the request and persists the message with correct parent/child/sibling relationships. - Repository and service layers return clear error types (use Arrow Either for repo errors and logical errors per project guidance). Implementation tasks (suggested order) Frontend (app module) - Add InsertMessage dialog state to `ChatAreaDialogState` with fields: - targetMessage (message id or message object) - position (default: BELOW) - role (default: USER) - content (optional string) - onConfirm callback - onDismiss callback - Create Insert Message dialog UI in `Dialogs.kt`: - Radio buttons for position: Above / Below. - Radio buttons for role: User / Assistant. - Text field for optional content. - Confirm and Cancel buttons. - Add "Insert" menu item to `MoreActionsMenu` in `MessageActionRow.kt` that triggers an `onRequestInsertMessage(targetMessage)` action. - Add `onRequestInsertMessage` to `MessageActions` and `ChatAreaActions` interfaces and wire through to `ChatViewModel` so the view model can show the dialog with the target message preselected. - Implement `requestInsertMessage` and `confirmInsertMessage` flows in `ChatViewModel`: - `requestInsertMessage` shows the `InsertMessage` dialog with the selected target message. - `confirmInsertMessage` calls the `MessageRepository.insertMessage` with `modelId` and `settingsId` from the current session, then updates the session's message tree/leaf with the new message ID. Common (shared module) - Create `InsertMessageRequest` model in `common/src/commonMain/kotlin/eu/torvian/chatbot/common/models/api/core/` with fields: - `targetMessageId: String` - `position: Position` enum (ABOVE | BELOW) - `role: Role` enum (USER | ASSISTANT) - `content: String?` - `modelId: String` - `settingsId: String` - Add serialization annotations consistent with existing API models. Client API / Repository - Add `insertMessage` method to `MessageApiClient` that POSTs `InsertMessageRequest` to server endpoint `/api/v1/messages/insert` and returns the created `ChatMessage`. - Add `insertMessage` method to `MessageRepository` that calls the API client, wraps results in Arrow `Either` returning `RepositoryError` or `ChatMessage`. - Ensure logical error types are used for expected failure cases (e.g., invalid target, permission), not low-level technical errors. Server (server module) - Add POST `/api/v1/messages/insert` route in message routes that: - Validates request body and required permissions/session. - Calls `MessageService.insertMessage(request)`. - Returns HTTP 201 with the created message or appropriate error codes. - Extend `MessageService` with `insertMessage(request: InsertMessageRequest): ChatMessage` that: - Loads the target message to determine parent/child relationships. - Determines `parentMessageId`: for ABOVE => target.parentMessageId; for BELOW => target.id. - Creates the new message with the chosen role and content, linking to `parentMessageId`. - Updates sibling relationships: if inserting ABOVE, adjust parent's child ordering such that the new message is placed before the target; if inserting BELOW, place after target in target's thread. - If insertion is BELOW and the session leaf needs to point to the new message, update session leaf accordingly. - Ensures operations are transactional and handles concurrency/conflicts. - Add `insertMessage` to `MessageDao` with SQL/Exposed logic to create the message and update sibling orderings and session leaf in a single transaction. Testing - Add unit tests for `MessageService.insertMessage` covering ABOVE and BELOW cases, edge cases (target is root, target has no parent, inserting into empty thread), and session leaf update behavior. - Add integration test for the new API route. Notes / assumptions - Use kotlinx.datetime for any date/time handling. - Use Arrow `Either` for repository error handling and return logical errors per project guidelines. - Message IDs and session IDs are strings in the current codebase—adapt if different. Suggested labels: enhancement, backend, frontend If you'd like, I can also open a PR scaffolding the `InsertMessageRequest` model and the client API method, or implement the frontend dialog first. Which subtask do you want me to take on next?
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Torvian.eu/chatbot#144
No description provided.