Skip to content

WIP: multiturn UI#1135

Draft
leonardmq wants to merge 6 commits intoleonard/kil-447-feat-stream-multiturn-ai-sdk-openai-protocolsfrom
leonard/multiturn-hack
Draft

WIP: multiturn UI#1135
leonardmq wants to merge 6 commits intoleonard/kil-447-feat-stream-multiturn-ai-sdk-openai-protocolsfrom
leonard/multiturn-hack

Conversation

@leonardmq
Copy link
Collaborator

What does this PR do?

Temporary multiturn UI:

  • go into Run page
  • run the task with some input
  • adapter will do a full turn including tools, and respond
  • type in the run textbox again to continue the run
  • each message in the conversation creates a new TaskRun (snapshotting the conversation up until that message) visible in the Dataset page

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 17, 2026

Important

Review skipped

Ignore keyword(s) in the title.

⛔ Ignored keywords (2)
  • WIP
  • Draft

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: c9f0dab1-56c0-493a-93ff-21b8dd58882c

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch leonard/multiturn-hack
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request lays the groundwork for interactive, multi-turn conversations within the application. It enhances the core task execution logic to maintain conversation context across multiple turns and introduces streaming capabilities for real-time feedback. The user interface has been updated to reflect these new conversational features, providing a more dynamic interaction experience.

Highlights

  • Multi-turn Conversation Support: Introduced the ability to continue a task run from a prior trace, enabling multi-turn conversations. This is supported both via a new task_run_id field in the main /run endpoint and a deprecated /runs/{run_id}/continue endpoint.
  • Streaming API Endpoints: Added new API endpoints for streaming task responses in both OpenAI-style (/run/stream) and AI SDK-style (/run/stream/ai-sdk) formats.
  • Unified Task Execution Helper: A new run_task helper function was added to the backend, centralizing task execution logic and supporting conversation continuation and various streaming modes.
  • User Interface Enhancements: The UI now features a 'Continue Conversation' button on the dataset run page, a banner indicating conversation continuation, and displays the previous message trace on the run page.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • app/web_ui/src/lib/api_schema.d.ts
    • Added new API paths for /run/stream, /run/stream/ai-sdk, and /runs/{run_id}/continue.
    • Included an optional task_run_id field in the RunTaskRequest interface.
  • app/web_ui/src/routes/(app)/dataset/[project_id]/[task_id]/[run_id]/run/+page.svelte
    • Added a 'Continue Conversation' button to the run details page, appearing if a trace exists.
  • app/web_ui/src/routes/(app)/run/+page.svelte
    • Implemented logic to load prior run data for conversation continuation.
    • Modified the run_task function to pass task_run_id to the backend for continuing conversations.
    • Added UI elements to display a 'Continuing Conversation' banner and the previous message trace.
    • Cleared the input form after a successful run to facilitate subsequent turns.
  • libs/core/kiln_ai/adapters/adapter_registry.py
    • Introduced a unified run_task async helper function to manage task execution, supporting conversation continuation and different streaming modes.
    • Added necessary type hinting imports for TYPE_CHECKING, Literal, and Union.
  • libs/core/kiln_ai/adapters/test_adapter_registry.py
    • Imported AsyncMock and MagicMock for enhanced testing capabilities.
    • Added comprehensive unit tests for the new run_task helper function, covering various scenarios including sync mode, continuation from TaskRun objects and IDs, error handling, and streaming modes.
  • libs/server/kiln_server/run_api.py
    • Imported AsyncIterator, StreamingResponse, and AiSdkStreamEvent for streaming functionality.
    • Added the task_run_id field to the RunTaskRequest model.
    • Modified the main /run endpoint to accept task_run_id for conversation continuation.
    • Implemented new /run/stream and /run/stream/ai-sdk endpoints for OpenAI-style and AI SDK-style streaming, respectively.
    • Added a continue_task_run helper function and a deprecated /runs/{run_id}/continue endpoint for conversation continuation.
  • libs/server/kiln_server/test_run_api.py
    • Updated the task_run_setup fixture to include a new_task_run for testing conversation continuation.
    • Added extensive tests for the deprecated continue_task_run endpoint, covering success, no trace, not found, and no input scenarios.
    • Included tests for the main /run endpoint with task_run_id for continuation, including error cases.
    • Added tests for the new streaming endpoints (/run/stream and /run/stream/ai-sdk), verifying their functionality and continuation with task_run_id.
Activity
  • The pull request introduces a temporary, work-in-progress multi-turn UI.
  • The described flow involves running a task, receiving a response, and then typing in the run textbox again to continue the conversation.
  • Each message in the conversation is designed to create a new TaskRun, which is visible on the Dataset page.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@github-actions
Copy link

github-actions bot commented Mar 17, 2026

📊 Coverage Report

Overall Coverage: 91%

Diff: origin/leonard/kil-461-feat-nesting-task-runs-into-each-other...HEAD

  • libs/core/kiln_ai/adapters/adapter_registry.py (91.7%): Missing lines 25,70
  • libs/server/kiln_server/run_api.py (86.8%): Missing lines 374,377,390,429,432,441,444-445,449,462

Summary

  • Total: 100 lines
  • Missing: 12 lines
  • Coverage: 88%

Line-by-line

View line-by-line diff coverage

libs/core/kiln_ai/adapters/adapter_registry.py

Lines 21-29

  21 from kiln_ai.datamodel.task_output import DataSource
  22 from kiln_ai.utils.exhaustive_error import raise_exhaustive_enum_error
  23 
  24 if TYPE_CHECKING:
! 25     from kiln_ai.adapters.model_adapters.base_adapter import (
  26         AiSdkStreamResult,
  27         OpenAIStreamResult,
  28     )

Lines 66-74

  66         ValueError: If input is not provided
  67     """
  68     # Validate input is provided
  69     if new_input is None:
! 70         raise ValueError("Input is required. Provide new_input as either str or dict.")
  71 
  72     # Resolve task_run to a prior_trace if provided
  73     prior_trace = None
  74     if task_run is not None:

libs/server/kiln_server/run_api.py

Lines 370-381

  370         )
  371 
  372         input = request.plaintext_input
  373         if task.input_schema() is not None:
! 374             input = request.structured_input
  375 
  376         if input is None:
! 377             raise HTTPException(
  378                 status_code=400,
  379                 detail="No input provided. Ensure your provided the proper format (plaintext or structured).",
  380             )

Lines 386-394

  386             _, prior_run = task_and_run_from_id(
  387                 project_id, task_id, request.task_run_id
  388             )
  389             if prior_run.trace is None:
! 390                 raise HTTPException(
  391                     status_code=400,
  392                     detail="Cannot continue run: no trace available from the prior run.",
  393                 )
  394             prior_trace = prior_run.trace

Lines 425-436

  425         )
  426 
  427         input = request.plaintext_input
  428         if task.input_schema() is not None:
! 429             input = request.structured_input
  430 
  431         if input is None:
! 432             raise HTTPException(
  433                 status_code=400,
  434                 detail="No input provided. Ensure your provided the proper format (plaintext or structured).",
  435             )

Lines 437-453

  437         # Continue from prior run if task_run_id is provided
  438         prior_trace = None
  439         prior_run = None
  440         if request.task_run_id is not None:
! 441             _, prior_run = task_and_run_from_id(
  442                 project_id, task_id, request.task_run_id
  443             )
! 444             if prior_run.trace is None:
! 445                 raise HTTPException(
  446                     status_code=400,
  447                     detail="Cannot continue run: no trace available from the prior run.",
  448                 )
! 449             prior_trace = prior_run.trace
  450 
  451         stream_result = adapter.invoke_ai_sdk_stream(
  452             input,
  453             prior_trace=prior_trace,

Lines 458-466

  458             async for event in stream_result:
  459                 if isinstance(event, AiSdkStreamEvent):
  460                     yield f"data: {event.model_dump()}\n\n"
  461                 else:
! 462                     yield f"data: {event}\n\n"
  463             yield "data: [DONE]\n\n"
  464 
  465         return StreamingResponse(
  466             stream_generator(),


Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces conversation continuation and streaming capabilities across the application. The frontend now features a "Continue Conversation" button and a UI to manage conversation state, loading prior runs, and displaying their traces. The backend includes new API endpoints for OpenAI-style and AI SDK-style streaming, and the existing /run endpoint is enhanced to accept a task_run_id for continuing conversations. A new run_task helper function unifies task execution, supporting synchronous and streaming modes, and handles the prior_trace for conversational context. An improvement opportunity was identified in the run_task helper to provide a more informative error message when a specified task_run_id is not found, by including the actual ID in the error message.

Comment on lines +78 to +83
# Look up by ID
task_run = datamodel.TaskRun.from_id_and_parent_path(
task_run, kiln_task.path
)
if task_run is None:
raise ValueError(f"TaskRun not found: {task_run}")
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The error message for a not-found TaskRun can be improved. Currently, if a task_run ID is passed as a string and not found, the task_run variable is reassigned to None, and the error message becomes TaskRun not found: None. It would be more helpful to show the ID that was not found.

You can store the ID in a separate variable before looking it up to provide a more informative error message.

Suggested change
# Look up by ID
task_run = datamodel.TaskRun.from_id_and_parent_path(
task_run, kiln_task.path
)
if task_run is None:
raise ValueError(f"TaskRun not found: {task_run}")
# Look up by ID
task_run_id = task_run
task_run = datamodel.TaskRun.from_id_and_parent_path(
task_run_id, kiln_task.path
)
if task_run is None:
raise ValueError(f"TaskRun not found: {task_run_id}")

@leonardmq leonardmq marked this pull request as draft March 17, 2026 11:49
@leonardmq leonardmq changed the title hack: multiturn UI (wip) WIP: multiturn UI Mar 17, 2026
Base automatically changed from leonard/kil-461-feat-nesting-task-runs-into-each-other to leonard/kil-447-feat-stream-multiturn-ai-sdk-openai-protocols March 17, 2026 13:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant