Skip to content

Conversation

@sfierro
Copy link
Contributor

@sfierro sfierro commented Jan 7, 2026

Not ready to merge until server sdk is updated

Summary by CodeRabbit

  • New Features

    • Copilot integration added with three new endpoints for spec clarification, refinement, and batch generation; app startup now wires the Copilot connection so endpoints are available at runtime.
  • Security / Authentication

    • Authenticated client support added with standardized base URL, headers, and timeouts for secure server communication.
  • Tests

    • Comprehensive unit tests covering Copilot endpoints, API key handling, success paths, and error scenarios (validation failures and missing responses).

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 7, 2026

Walkthrough

Wires a new Copilot FastAPI module into the desktop app startup, adds an authenticated Kiln client helper, and introduces comprehensive tests for both the Kiln client and Copilot endpoints. New endpoints handle payload mapping, async calls to Kiln Copilot, and explicit error responses.

Changes

Cohort / File(s) Summary
Desktop wiring
app/desktop/desktop_server.py
Import connect_copilot_api and invoke it during app startup after connect_tool_servers_api to register Copilot endpoints.
Kiln server client
app/desktop/studio_server/api_client/kiln_server_client.py
Add get_authenticated_client(api_key: str) -> AuthenticatedClient; extract _get_base_url and _get_common_headers; reuse helpers in existing client creation.
Kiln client tests
app/desktop/studio_server/api_client/test_kiln_server_client.py
New tests for get_authenticated_client: instance type, base URL env override, token, headers, and timeouts.
Copilot API implementation
app/desktop/studio_server/copilot_api.py
New module with Pydantic input models, _get_api_key() (401 if missing), and connect_copilot_api(app) registering /api/copilot/clarify_spec, /refine_spec, /generate_batch. Handlers build Kiln SDK requests, call async post methods, and handle None/validation errors and success serialization.
Copilot API tests
app/desktop/studio_server/test_copilot_api.py
New tests covering missing API key (401), success (mocked async client), and failure cases (None -> 500, HTTPValidationError -> 422) for all endpoints and flags like enable_scoring.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant FastAPI as "FastAPI App"
    participant Handler as "copilot_api handler"
    participant Config as "Config"
    participant KilnClient as "AuthenticatedClient"
    participant CopilotSvc as "Kiln Copilot Service"

    Client->>FastAPI: POST /api/copilot/{clarify|refine|generate} (payload)
    FastAPI->>Handler: route -> handler
    Handler->>Config: _get_api_key()
    Config-->>Handler: kiln_copilot_api_key
    Handler->>KilnClient: get_authenticated_client(api_key)
    KilnClient-->>Handler: AuthenticatedClient
    Handler->>Handler: map payload -> Kiln SDK request
    Handler->>CopilotSvc: <async> post method
    alt success
        CopilotSvc-->>Handler: Response (model objects)
        Handler->>Handler: serialize .to_dict()
        Handler-->>FastAPI: 200 JSON
        FastAPI-->>Client: 200 response
    else validation error (422)
        CopilotSvc-->>Handler: HTTPValidationError
        Handler-->>FastAPI: 422 JSON
        FastAPI-->>Client: 422 response
    else no response / unexpected
        CopilotSvc-->>Handler: None / unexpected type
        Handler-->>FastAPI: 500 JSON
        FastAPI-->>Client: 500 response
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • scosman
  • chiang-daniel

Poem

🐰
I hopped through code to plant a seed,
Three endpoints sprout to meet the need.
Keys fetched, async hops complete,
Tests cheer loud with drumbeat feet.
A joyful rabbit — integration sweet.

🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description is minimal and lacks required information. It does not include 'What does this PR do?', related issues, or CLA confirmation as specified in the template. Complete the PR description by adding a detailed explanation of what the PR does, linking related issues if applicable, confirming the CLA, and checking off the test and documentation checklists.
Docstring Coverage ⚠️ Warning Docstring coverage is 35.14% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Authenticated copilot client + 3 APIs' clearly and concisely summarizes the main changes: adding authenticated client support and three new API endpoints for copilot functionality.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

📜 Recent review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 385242a and 23811fd.

📒 Files selected for processing (1)
  • app/desktop/studio_server/copilot_api.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/desktop/studio_server/copilot_api.py

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

Summary of Changes

Hello @sfierro, 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 introduces the integration of the Kiln Copilot AI service into the desktop application. It achieves this by exposing three new API endpoints—clarify_spec, refine_spec, and generate_batch—through the desktop server. The changes also include the establishment of a secure, authenticated client for communication with the Kiln AI server and comprehensive testing to validate the reliability and proper functioning of these new features.

Highlights

  • Kiln Copilot API Integration: The desktop server now includes new API endpoints for clarify_spec, refine_spec, and generate_batch, enabling interaction with the Kiln Copilot service.
  • Authenticated Client for Kiln AI Server: A new get_authenticated_client function has been introduced to securely interact with the Kiln AI server using an API key, ensuring authenticated requests for Copilot features.
  • Comprehensive API Endpoint Testing: New unit tests have been added for the Copilot API endpoints, covering various scenarios including API key validation, successful responses, and error handling, ensuring robust functionality.

🧠 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.

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.

Copy link

@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 a new set of API endpoints to proxy requests to a Kiln Copilot service. It adds an authenticated client for this purpose, along with refactoring the existing client creation logic for better code reuse. The new endpoints are for clarifying a spec, refining a spec, and generating a batch of data. The changes are well-tested, including unit tests for the new client logic and integration tests for the new API endpoints.

My review focuses on improving the implementation of the new copilot_api.py file by leveraging more of Pydantic's features to reduce boilerplate code and improve maintainability. I've also suggested adding a couple of missing test cases to ensure full coverage of the error handling paths. Overall, this is a solid contribution.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In @app/desktop/studio_server/copilot_api.py:
- Around line 3-19: The imports for clarify_spec_v1_copilot_clarify_spec_post,
generate_batch_v1_copilot_generate_batch_post,
refine_spec_v1_copilot_refine_spec_post and the models ClarifySpecInput,
ClarifySpecOutput, GenerateBatchInput, GenerateBatchOutput, RefineSpecInput,
RefineSpecOutput are missing because the generated kiln_ai_server_client does
not include the copilot endpoints; regenerate the API client from the server
OpenAPI spec so the api.copilot module and those model classes are produced (or
update the client package/version to one that contains them), then update the
import block in copilot_api.py to reference the newly generated functions/models
(or remove/guard these imports if the copilot API is intentionally unavailable)
and run tests to confirm the new client code is importable and the referenced
symbols exist.

In @app/desktop/studio_server/test_copilot_api.py:
- Around line 4-13: The imports for ClarifySpecOutput, GenerateBatchOutput,
HTTPValidationError, and other copilot models are missing because the generated
API client lacks the copilot module; regenerate the client from the updated
OpenAPI spec so the kiln_ai_server_client.models package includes those model
classes, then update any import sites (e.g., the test that imports
ClarifySpecOutput/GenerateBatchOutput and the copilot_api.py implementation) to
use the newly generated module names, run the generation/build to publish the
updated package to your local environment, and re-run tests to verify imports
resolve.
🧹 Nitpick comments (3)
app/desktop/studio_server/test_copilot_api.py (2)

153-191: Consider adding validation error test for refine_spec.

The TestClarifySpec class includes a test_clarify_spec_validation_error test, but TestRefineSpec is missing the corresponding validation error test case. Consider adding it for consistency.


193-254: Consider adding validation error test for generate_batch.

Similarly, TestGenerateBatch is missing a validation error test case that would verify the 422 response handling. Consider adding it for test completeness.

app/desktop/studio_server/copilot_api.py (1)

70-72: Consider closing the authenticated client after use.

Each endpoint creates a new AuthenticatedClient but doesn't explicitly close it. The AuthenticatedClient class supports context manager usage (async with). While the underlying httpx client may be lazily created and garbage collected, explicitly closing it ensures proper resource cleanup, especially for the async client.

🔎 Proposed fix using async context manager
     @app.post("/api/copilot/clarify_spec")
     async def clarify_spec(input: ClarifySpecApiInput) -> dict[str, Any]:
         api_key = _get_api_key()
-        client = get_authenticated_client(api_key)
-
-        clarify_input = ClarifySpecInput(...)
-
-        result = await clarify_spec_v1_copilot_clarify_spec_post.asyncio(
-            client=client,
-            body=clarify_input,
-        )
+        async with get_authenticated_client(api_key) as client:
+            clarify_input = ClarifySpecInput(...)
+
+            result = await clarify_spec_v1_copilot_clarify_spec_post.asyncio(
+                client=client,
+                body=clarify_input,
+            )
+            # ... rest of handling

Also applies to: 109-111, 153-155

📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 60828b6 and 63a8e20.

📒 Files selected for processing (5)
  • app/desktop/desktop_server.py
  • app/desktop/studio_server/api_client/kiln_server_client.py
  • app/desktop/studio_server/api_client/test_kiln_server_client.py
  • app/desktop/studio_server/copilot_api.py
  • app/desktop/studio_server/test_copilot_api.py
🧰 Additional context used
📓 Path-based instructions (5)
**/*.py

📄 CodeRabbit inference engine (.cursor/rules/project.mdc)

**/*.py: Use asyncio for asynchronous operations in Python
Use Pydantic v2 (not v1) for data validation

**/*.py: Use Pydantic v2, not v1
Use asyncio for asynchronous operations in Python

Files:

  • app/desktop/studio_server/api_client/kiln_server_client.py
  • app/desktop/studio_server/api_client/test_kiln_server_client.py
  • app/desktop/studio_server/copilot_api.py
  • app/desktop/studio_server/test_copilot_api.py
  • app/desktop/desktop_server.py
app/desktop/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

Use Python 3.13 for the desktop application (app/desktop)

Files:

  • app/desktop/studio_server/api_client/kiln_server_client.py
  • app/desktop/studio_server/api_client/test_kiln_server_client.py
  • app/desktop/studio_server/copilot_api.py
  • app/desktop/studio_server/test_copilot_api.py
  • app/desktop/desktop_server.py
{libs/server,app/desktop/studio_server}/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

Use FastAPI for REST server implementation

Files:

  • app/desktop/studio_server/api_client/kiln_server_client.py
  • app/desktop/studio_server/api_client/test_kiln_server_client.py
  • app/desktop/studio_server/copilot_api.py
  • app/desktop/studio_server/test_copilot_api.py
**/*test*.py

📄 CodeRabbit inference engine (.cursor/rules/project.mdc)

Use pytest for testing Python code

Files:

  • app/desktop/studio_server/api_client/test_kiln_server_client.py
  • app/desktop/studio_server/test_copilot_api.py
**/test_*.py

📄 CodeRabbit inference engine (AGENTS.md)

Use pytest for testing in Python

Files:

  • app/desktop/studio_server/api_client/test_kiln_server_client.py
  • app/desktop/studio_server/test_copilot_api.py
🧬 Code graph analysis (4)
app/desktop/studio_server/api_client/kiln_server_client.py (1)
app/desktop/studio_server/api_client/kiln_ai_server_client/client.py (1)
  • AuthenticatedClient (140-282)
app/desktop/studio_server/api_client/test_kiln_server_client.py (2)
app/desktop/studio_server/api_client/kiln_ai_server_client/client.py (1)
  • AuthenticatedClient (140-282)
app/desktop/studio_server/api_client/kiln_server_client.py (1)
  • get_authenticated_client (43-50)
app/desktop/studio_server/test_copilot_api.py (1)
app/desktop/studio_server/copilot_api.py (1)
  • connect_copilot_api (68-189)
app/desktop/desktop_server.py (2)
app/desktop/studio_server/test_copilot_api.py (1)
  • app (20-23)
app/desktop/studio_server/copilot_api.py (1)
  • connect_copilot_api (68-189)
🪛 GitHub Actions: Build and Test
app/desktop/studio_server/copilot_api.py

[error] 3-3: ModuleNotFoundError: No module named 'app.desktop.studio_server.api_client.kiln_ai_server_client.api.copilot'.

app/desktop/studio_server/test_copilot_api.py

[error] 4-4: ImportError: cannot import name 'ClarifySpecOutput' from 'app.desktop.studio_server.api_client.kiln_ai_server_client.models'.

🪛 GitHub Actions: Check API Bindings
app/desktop/studio_server/copilot_api.py

[error] 3-3: ModuleNotFoundError: No module named 'app.desktop.studio_server.api_client.kiln_ai_server_client.api.copilot'

🪛 GitHub Actions: Coverage Report
app/desktop/studio_server/copilot_api.py

[error] 3-3: ModuleNotFoundError: No module named 'app.desktop.studio_server.api_client.kiln_ai_server_client.api.copilot'

app/desktop/studio_server/test_copilot_api.py

[error] 4-4: ImportError: cannot import name 'ClarifySpecOutput' from 'app.desktop.studio_server.api_client.kiln_ai_server_client.models'

🪛 GitHub Actions: Format and Lint
app/desktop/studio_server/copilot_api.py

[error] 3-3: ty: unresolved-import Cannot resolve imported module 'app.desktop.studio_server.api_client.kiln_ai_server_client.api.copilot'.


[error] 9-9: ty: unresolved-import Module 'app.desktop.studio_server.api_client.kiln_ai_server_client.models' has no member 'ClarifySpecInput'.


[error] 10-10: ty: unresolved-import Module 'app.desktop.studio_server.api_client.kiln_ai_server_client.models' has no member 'ClarifySpecOutput'.


[error] 11-11: ty: unresolved-import Module 'app.desktop.studio_server.api_client.kiln_ai_server_client.models' has no member 'ExampleWithFeedback'.


[error] 12-12: ty: unresolved-import Module 'app.desktop.studio_server.api_client.kiln_ai_server_client.models' has no member 'GenerateBatchInput'.


[error] 13-13: ty: unresolved-import Module 'app.desktop.studio_server.api_client.kiln_ai_server_client.models' has no member 'GenerateBatchOutput'.


[error] 14-14: ty: unresolved-import Module 'app.desktop.studio_server.api_client.kiln_ai_server_client.models' has no member 'HTTPValidationError'.


[error] 15-15: ty: unresolved-import Module 'app.desktop.studio_server.api_client.kiln_ai_server_client.models' has no member 'RefineSpecInput'.


[error] 16-16: ty: unresolved-import Module 'app.desktop.studio_server.api_client.kiln_ai_server_client.models' has no member 'RefineSpecOutput'.


[error] 17-17: ty: unresolved-import Module 'app.desktop.studio_server.api_client.kiln_ai_server_client.models' has no member 'SpecInfo'.


[error] 18-18: ty: unresolved-import Module 'app.desktop.studio_server.api_client.kiln_ai_server_client.models' has no member 'TaskInfo'.

🔇 Additional comments (5)
app/desktop/desktop_server.py (1)

17-17: LGTM! Copilot API wiring follows established patterns.

The import and registration of connect_copilot_api follows the same pattern as other API modules, and the placement before connect_dev_tools and connect_webhost is appropriate.

Note: This depends on resolving the import errors in copilot_api.py (see pipeline failures in that file).

Also applies to: 68-68

app/desktop/studio_server/api_client/test_kiln_server_client.py (1)

170-208: LGTM! Comprehensive test coverage for authenticated client.

The test class follows the same pattern as TestGetKilnServerClient and provides good coverage for:

  • Instance type verification
  • Base URL configuration with/without environment variable
  • Token assignment
  • Header configuration (User-Agent, Kiln-Desktop-App-Version)
  • Timeout configuration (read: 300s, connect: 30s)
app/desktop/studio_server/api_client/kiln_server_client.py (1)

21-50: LGTM! Well-structured refactoring with proper DRY application.

Good extraction of _get_base_url() and _get_common_headers() helpers, which are now shared between the unauthenticated and authenticated client factories. The get_authenticated_client function is properly configured with:

  • Environment-configurable base URL
  • Token-based authentication
  • Consistent headers
  • Appropriate timeout (300s read for long-running copilot operations, 30s connect)
app/desktop/studio_server/copilot_api.py (2)

28-55: LGTM! Pydantic input models are well-defined.

The input models use Pydantic v2 syntax correctly with BaseModel and Field for defaults. The use of dict[str, Any] for nested structures in RefineSpecApiInput is appropriate since these are passed through to from_dict() methods.


57-65: LGTM! API key validation is appropriate.

The _get_api_key helper properly returns 401 with a helpful message when the API key is not configured.

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.

2 participants