Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
107137a
chore: re-vendor kiln_server SDK from dchiang/synthetic-user@1d57386
chiang-daniel Jun 1, 2026
c122022
feat(libs/core): add synthetic_user player module
chiang-daniel Jun 1, 2026
b3337da
chore: re-vendor SDK from kiln_server@acbd0ce
chiang-daniel Jun 1, 2026
bb002b9
feat(studio_server): SyntheticUserClient for /generate
chiang-daniel Jun 1, 2026
322d815
feat(libs/core/synthetic_user): tighten persona prompt opening
chiang-daniel Jun 1, 2026
ab74931
feat(studio_server): drive_case + run_cases_batch with local SU driver
chiang-daniel Jun 2, 2026
e5894cc
feat(studio_server): multiturn_sdg FastAPI routes for SU eval data
chiang-daniel Jun 2, 2026
edb27f0
refactor(studio_server/synthetic_user): driver loop polish from review
chiang-daniel Jun 2, 2026
fbc1e58
chore(studio_server/synthetic_user): mild review polish
chiang-daniel Jun 2, 2026
14304e7
refactor(studio_server/synthetic_user): decompose root input_source
chiang-daniel Jun 2, 2026
bdd7c4b
refactor(synthetic_user): thread SU driver cost into total_cost
chiang-daniel Jun 2, 2026
c3cd321
chore(synthetic_user): drop dead empty-string filter in _build_input_…
chiang-daniel Jun 2, 2026
54ee96f
refactor(synthetic_user): move runner + drive_loop into the kiln-ai SDK
chiang-daniel Jun 2, 2026
ec1bb72
fix(synthetic_user): filter tool-dispatch-only assistant turns before…
chiang-daniel Jun 2, 2026
edf3794
chore(synthetic_user): trim comments — fix inaccuracies, strip stale …
chiang-daniel Jun 3, 2026
d9a3517
Merge remote-tracking branch 'origin/leonard/kil-632-feat-multiturn-t…
chiang-daniel Jun 3, 2026
d032dcf
chore(web_ui): strip zero-width space from multiturn_composer comment
chiang-daniel Jun 3, 2026
42211db
feat(copilot): multi-turn save endpoint + classify-spec stub
chiang-daniel Jun 4, 2026
4cb609f
feat(specs-v2): mock-first eval builder UI (single-turn + multi-turn)
chiang-daniel Jun 4, 2026
70a4a3f
feat(specs-v2): wire real run_cases_batch SSE for multi-turn generation
chiang-daniel Jun 4, 2026
e4f09d3
fix(specs-v2): seed property_values.issue_description from Step 1 des…
chiang-daniel Jun 5, 2026
b4b72e1
fix(specs-v2): fall back to first run config when task has no default
chiang-daniel Jun 5, 2026
04c9b5c
feat(specs-v2): simpler Step 3 Refine UI for multi-turn evals
chiang-daniel Jun 5, 2026
714a5a9
feat(specs-v2): distinct Step 4 phase indicator for generate_cases call
chiang-daniel Jun 5, 2026
f35d2fc
fix(specs-v2): disable Save until all multi-turn chains are reviewed
chiang-daniel Jun 5, 2026
a43c827
fix(specs-v2): use a client-side default judge instead of clarify_spec
chiang-daniel Jun 5, 2026
ac4fd6c
feat(specs-v2): UI polish — width, titles, multi-turn name validator
chiang-daniel Jun 5, 2026
93657e1
feat(specs-v2): bug-bash-ready pass — URL move, Pro gate, guardrails,…
chiang-daniel Jun 9, 2026
a572714
fix(specs-v2): UI polish — width, alerts, abort plumbing, Step 1 cleanup
chiang-daniel Jun 9, 2026
33c9ba8
feat(specs-v2): paginated multi-turn review UI
chiang-daniel Jun 9, 2026
c8449e0
chore(agent_checks): add policy annotations for multiturn_sdg endpoints
chiang-daniel Jun 24, 2026
2ee9cdd
Merge pull request #1457 from Kiln-AI/dchiang/eval-builder-v2
chiang-daniel Jun 24, 2026
384fb36
fix(api_client): drop hardcoded multipart Content-Type from vendored SDK
chiang-daniel Jun 24, 2026
5e1d493
chore(agent_checks): add policy annotation for copilot classify_spec_…
chiang-daniel Jun 24, 2026
f8ac75d
Merge remote-tracking branch 'origin/leonard/kil-632-feat-multiturn-t…
chiang-daniel Jun 24, 2026
99774ed
fix(specs): unblock multi-turn tasks from reaching the v2 builder
chiang-daniel Jun 25, 2026
7e02c9a
feat(specs-v2): builder polish — v1 animations, manual-create link, C…
chiang-daniel Jun 25, 2026
3fb7849
feat(specs-v2): turn-level progress for multi-turn generation
chiang-daniel Jun 25, 2026
424b20d
feat(specs-v2): history-driven step navigation (back button + unsaved…
chiang-daniel Jun 26, 2026
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
2 changes: 2 additions & 0 deletions app/desktop/desktop_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
from app.desktop.studio_server.eval_api import connect_evals_api
from app.desktop.studio_server.finetune_api import connect_fine_tune_api
from app.desktop.studio_server.import_api import connect_import_api
from app.desktop.studio_server.multiturn_sdg_api import connect_multiturn_sdg_api
from app.desktop.studio_server.prompt_api import connect_prompt_api
from app.desktop.studio_server.prompt_optimization_job_api import (
connect_prompt_optimization_job_api,
Expand Down Expand Up @@ -142,6 +143,7 @@ def make_app(tk_root: tk.Tk | None = None):
connect_skill_api(app)
connect_prompt_optimization_job_api(app)
connect_copilot_api(app)
connect_multiturn_sdg_api(app)
connect_git_sync_api(app)
connect_agent_api(app)
connect_dev_tools(app)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Contains endpoint functions for accessing the API"""
Original file line number Diff line number Diff line change
@@ -0,0 +1,253 @@
from http import HTTPStatus
from typing import Any

import httpx

from ... import errors
from ...client import AuthenticatedClient, Client
from ...models.generate_synthetic_users_request import GenerateSyntheticUsersRequest
from ...models.generate_synthetic_users_response import GenerateSyntheticUsersResponse
from ...models.generate_v1_synthetic_user_generate_post_response_401 import (
GenerateV1SyntheticUserGeneratePostResponse401,
)
from ...models.generate_v1_synthetic_user_generate_post_response_500 import (
GenerateV1SyntheticUserGeneratePostResponse500,
)
from ...models.generate_v1_synthetic_user_generate_post_response_502 import (
GenerateV1SyntheticUserGeneratePostResponse502,
)
from ...models.http_validation_error import HTTPValidationError
from ...types import Response


def _get_kwargs(
*,
body: GenerateSyntheticUsersRequest,
) -> dict[str, Any]:
headers: dict[str, Any] = {}

_kwargs: dict[str, Any] = {
"method": "post",
"url": "/v1/synthetic_user/generate",
}

_kwargs["json"] = body.to_dict()

headers["Content-Type"] = "application/json"

_kwargs["headers"] = headers
return _kwargs


def _parse_response(
*, client: AuthenticatedClient | Client, response: httpx.Response
) -> (
GenerateSyntheticUsersResponse
| GenerateV1SyntheticUserGeneratePostResponse401
| GenerateV1SyntheticUserGeneratePostResponse500
| GenerateV1SyntheticUserGeneratePostResponse502
| HTTPValidationError
| None
):
if response.status_code == 200:
response_200 = GenerateSyntheticUsersResponse.from_dict(response.json())

return response_200

if response.status_code == 401:
response_401 = GenerateV1SyntheticUserGeneratePostResponse401.from_dict(response.json())

return response_401

if response.status_code == 422:
response_422 = HTTPValidationError.from_dict(response.json())

return response_422

if response.status_code == 500:
response_500 = GenerateV1SyntheticUserGeneratePostResponse500.from_dict(response.json())

return response_500

if response.status_code == 502:
response_502 = GenerateV1SyntheticUserGeneratePostResponse502.from_dict(response.json())

return response_502

if client.raise_on_unexpected_status:
raise errors.UnexpectedStatus(response.status_code, response.content)
else:
return None


def _build_response(
*, client: AuthenticatedClient | Client, response: httpx.Response
) -> Response[
GenerateSyntheticUsersResponse
| GenerateV1SyntheticUserGeneratePostResponse401
| GenerateV1SyntheticUserGeneratePostResponse500
| GenerateV1SyntheticUserGeneratePostResponse502
| HTTPValidationError
]:
return Response(
status_code=HTTPStatus(response.status_code),
content=response.content,
headers=response.headers,
parsed=_parse_response(client=client, response=response),
)


def sync_detailed(
*,
client: AuthenticatedClient,
body: GenerateSyntheticUsersRequest,
) -> Response[
GenerateSyntheticUsersResponse
| GenerateV1SyntheticUserGeneratePostResponse401
| GenerateV1SyntheticUserGeneratePostResponse500
| GenerateV1SyntheticUserGeneratePostResponse502
| HTTPValidationError
]:
"""Generate

Return `num_cases` synthetic-user cases for the authoring UX.

Args:
body (GenerateSyntheticUsersRequest): Request body for POST /v1/synthetic_user/generate.

Generates `num_cases` synthetic-user cases designed to probe
`target_specification` against the agent described by `target_task_prompt`,
across multi-turn conversations.

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Response[GenerateSyntheticUsersResponse | GenerateV1SyntheticUserGeneratePostResponse401 | GenerateV1SyntheticUserGeneratePostResponse500 | GenerateV1SyntheticUserGeneratePostResponse502 | HTTPValidationError]
"""

kwargs = _get_kwargs(
body=body,
)

response = client.get_httpx_client().request(
**kwargs,
)

return _build_response(client=client, response=response)


def sync(
*,
client: AuthenticatedClient,
body: GenerateSyntheticUsersRequest,
) -> (
GenerateSyntheticUsersResponse
| GenerateV1SyntheticUserGeneratePostResponse401
| GenerateV1SyntheticUserGeneratePostResponse500
| GenerateV1SyntheticUserGeneratePostResponse502
| HTTPValidationError
| None
):
"""Generate

Return `num_cases` synthetic-user cases for the authoring UX.

Args:
body (GenerateSyntheticUsersRequest): Request body for POST /v1/synthetic_user/generate.

Generates `num_cases` synthetic-user cases designed to probe
`target_specification` against the agent described by `target_task_prompt`,
across multi-turn conversations.

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
GenerateSyntheticUsersResponse | GenerateV1SyntheticUserGeneratePostResponse401 | GenerateV1SyntheticUserGeneratePostResponse500 | GenerateV1SyntheticUserGeneratePostResponse502 | HTTPValidationError
"""

return sync_detailed(
client=client,
body=body,
).parsed


async def asyncio_detailed(
*,
client: AuthenticatedClient,
body: GenerateSyntheticUsersRequest,
) -> Response[
GenerateSyntheticUsersResponse
| GenerateV1SyntheticUserGeneratePostResponse401
| GenerateV1SyntheticUserGeneratePostResponse500
| GenerateV1SyntheticUserGeneratePostResponse502
| HTTPValidationError
]:
"""Generate

Return `num_cases` synthetic-user cases for the authoring UX.

Args:
body (GenerateSyntheticUsersRequest): Request body for POST /v1/synthetic_user/generate.

Generates `num_cases` synthetic-user cases designed to probe
`target_specification` against the agent described by `target_task_prompt`,
across multi-turn conversations.

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Response[GenerateSyntheticUsersResponse | GenerateV1SyntheticUserGeneratePostResponse401 | GenerateV1SyntheticUserGeneratePostResponse500 | GenerateV1SyntheticUserGeneratePostResponse502 | HTTPValidationError]
"""

kwargs = _get_kwargs(
body=body,
)

response = await client.get_async_httpx_client().request(**kwargs)

return _build_response(client=client, response=response)


async def asyncio(
*,
client: AuthenticatedClient,
body: GenerateSyntheticUsersRequest,
) -> (
GenerateSyntheticUsersResponse
| GenerateV1SyntheticUserGeneratePostResponse401
| GenerateV1SyntheticUserGeneratePostResponse500
| GenerateV1SyntheticUserGeneratePostResponse502
| HTTPValidationError
| None
):
"""Generate

Return `num_cases` synthetic-user cases for the authoring UX.

Args:
body (GenerateSyntheticUsersRequest): Request body for POST /v1/synthetic_user/generate.

Generates `num_cases` synthetic-user cases designed to probe
`target_specification` against the agent described by `target_task_prompt`,
across multi-turn conversations.

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
GenerateSyntheticUsersResponse | GenerateV1SyntheticUserGeneratePostResponse401 | GenerateV1SyntheticUserGeneratePostResponse500 | GenerateV1SyntheticUserGeneratePostResponse502 | HTTPValidationError
"""

return (
await asyncio_detailed(
client=client,
body=body,
)
).parsed
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,14 @@
from .generate_batch_input import GenerateBatchInput
from .generate_batch_output import GenerateBatchOutput
from .generate_batch_output_data_by_topic import GenerateBatchOutputDataByTopic
from .generate_synthetic_users_request import GenerateSyntheticUsersRequest
from .generate_synthetic_users_response import GenerateSyntheticUsersResponse
from .generate_v1_synthetic_user_generate_post_response_401 import GenerateV1SyntheticUserGeneratePostResponse401
from .generate_v1_synthetic_user_generate_post_response_500 import GenerateV1SyntheticUserGeneratePostResponse500
from .generate_v1_synthetic_user_generate_post_response_502 import GenerateV1SyntheticUserGeneratePostResponse502
from .generate_v1_synthetic_user_generate_post_response_502_code import (
GenerateV1SyntheticUserGeneratePostResponse502Code,
)
from .get_session_v1_chat_sessions_session_id_get_response_400 import GetSessionV1ChatSessionsSessionIdGetResponse400
from .get_session_v1_chat_sessions_session_id_get_response_404 import GetSessionV1ChatSessionsSessionIdGetResponse404
from .get_session_v1_chat_sessions_session_id_get_response_426 import GetSessionV1ChatSessionsSessionIdGetResponse426
Expand Down Expand Up @@ -111,6 +119,7 @@
from .synthetic_data_generation_session_config_input import SyntheticDataGenerationSessionConfigInput
from .synthetic_data_generation_step_config import SyntheticDataGenerationStepConfig
from .synthetic_data_generation_step_config_input import SyntheticDataGenerationStepConfigInput
from .synthetic_user_case import SyntheticUserCase
from .task_info import TaskInfo
from .task_metadata import TaskMetadata
from .task_output import TaskOutput
Expand Down Expand Up @@ -167,6 +176,12 @@
"GenerateBatchInput",
"GenerateBatchOutput",
"GenerateBatchOutputDataByTopic",
"GenerateSyntheticUsersRequest",
"GenerateSyntheticUsersResponse",
"GenerateV1SyntheticUserGeneratePostResponse401",
"GenerateV1SyntheticUserGeneratePostResponse500",
"GenerateV1SyntheticUserGeneratePostResponse502",
"GenerateV1SyntheticUserGeneratePostResponse502Code",
"GetSessionV1ChatSessionsSessionIdGetResponse400",
"GetSessionV1ChatSessionsSessionIdGetResponse404",
"GetSessionV1ChatSessionsSessionIdGetResponse426",
Expand Down Expand Up @@ -223,6 +238,7 @@
"SyntheticDataGenerationSessionConfigInput",
"SyntheticDataGenerationStepConfig",
"SyntheticDataGenerationStepConfigInput",
"SyntheticUserCase",
"TaskInfo",
"TaskMetadata",
"TaskOutput",
Expand Down
Loading
Loading