teeny refactor (#1753)

api.py keeps growing. it's not tied to the master, so should have it's
own top level folder.

## testing
ci, pytest
This commit is contained in:
Evan Quiney
2026-03-19 15:57:50 +00:00
committed by GitHub
parent 63f57fc193
commit 07598a3af1
37 changed files with 163 additions and 105 deletions
View File
@@ -4,7 +4,7 @@ import time
from collections.abc import AsyncGenerator
from typing import Any
from exo.shared.types.api import (
from exo.api.types import (
ChatCompletionChoice,
ChatCompletionMessage,
ChatCompletionMessageText,
@@ -5,14 +5,8 @@ import re
from collections.abc import AsyncGenerator
from typing import Any
from exo.shared.types.api import FinishReason, Usage
from exo.shared.types.chunks import (
ErrorChunk,
PrefillProgressChunk,
TokenChunk,
ToolCallChunk,
)
from exo.shared.types.claude_api import (
from exo.api.types import FinishReason, Usage
from exo.api.types.claude_api import (
ClaudeContentBlock,
ClaudeContentBlockDeltaEvent,
ClaudeContentBlockStartEvent,
@@ -35,6 +29,12 @@ from exo.shared.types.claude_api import (
ClaudeToolUseBlock,
ClaudeUsage,
)
from exo.shared.types.chunks import (
ErrorChunk,
PrefillProgressChunk,
TokenChunk,
ToolCallChunk,
)
from exo.shared.types.common import CommandId
from exo.shared.types.text_generation import InputMessage, TextGenerationTaskParams
@@ -4,14 +4,7 @@ import json
from collections.abc import AsyncGenerator
from typing import Any
from exo.shared.types.chunks import (
ErrorChunk,
PrefillProgressChunk,
TokenChunk,
ToolCallChunk,
)
from exo.shared.types.common import CommandId
from exo.shared.types.ollama_api import (
from exo.api.types.ollama_api import (
OllamaChatRequest,
OllamaChatResponse,
OllamaDoneReason,
@@ -21,6 +14,13 @@ from exo.shared.types.ollama_api import (
OllamaToolCall,
OllamaToolFunction,
)
from exo.shared.types.chunks import (
ErrorChunk,
PrefillProgressChunk,
TokenChunk,
ToolCallChunk,
)
from exo.shared.types.common import CommandId
from exo.shared.types.text_generation import InputMessage, TextGenerationTaskParams
@@ -4,15 +4,8 @@ from collections.abc import AsyncGenerator
from itertools import count
from typing import Any
from exo.shared.types.api import Usage
from exo.shared.types.chunks import (
ErrorChunk,
PrefillProgressChunk,
TokenChunk,
ToolCallChunk,
)
from exo.shared.types.common import CommandId
from exo.shared.types.openai_responses import (
from exo.api.types import Usage
from exo.api.types.openai_responses import (
FunctionCallInputItem,
ResponseCompletedEvent,
ResponseContentPart,
@@ -42,6 +35,13 @@ from exo.shared.types.openai_responses import (
ResponseTextDoneEvent,
ResponseUsage,
)
from exo.shared.types.chunks import (
ErrorChunk,
PrefillProgressChunk,
TokenChunk,
ToolCallChunk,
)
from exo.shared.types.common import CommandId
from exo.shared.types.text_generation import (
InputMessage,
TextGenerationTaskParams,
+48 -48
View File
@@ -21,17 +21,17 @@ from hypercorn.config import Config
from hypercorn.typing import ASGIFramework
from loguru import logger
from exo.master.adapters.chat_completions import (
from exo.api.adapters.chat_completions import (
chat_request_to_text_generation,
collect_chat_response,
generate_chat_stream,
)
from exo.master.adapters.claude import (
from exo.api.adapters.claude import (
claude_request_to_text_generation,
collect_claude_response,
generate_claude_stream,
)
from exo.master.adapters.ollama import (
from exo.api.adapters.ollama import (
collect_ollama_chat_response,
collect_ollama_generate_response,
generate_ollama_chat_stream,
@@ -39,34 +39,12 @@ from exo.master.adapters.ollama import (
ollama_generate_request_to_text_generation,
ollama_request_to_text_generation,
)
from exo.master.adapters.responses import (
from exo.api.adapters.responses import (
collect_responses_response,
generate_responses_stream,
responses_request_to_text_generation,
)
from exo.master.event_log import DiskEventLog
from exo.master.image_store import ImageStore
from exo.master.placement import place_instance as get_instance_placements
from exo.shared.apply import apply
from exo.shared.constants import (
DASHBOARD_DIR,
EXO_CACHE_HOME,
EXO_EVENT_LOG_DIR,
EXO_IMAGE_CACHE_DIR,
EXO_MAX_CHUNK_SIZE,
EXO_TRACING_CACHE_DIR,
)
from exo.shared.election import ElectionMessage
from exo.shared.logging import InterceptLogger
from exo.shared.models.model_cards import (
ModelCard,
ModelId,
delete_custom_card,
get_model_cards,
is_custom_card,
)
from exo.shared.tracing import TraceEvent, compute_stats, export_trace, load_trace_file
from exo.shared.types.api import (
from exo.api.types import (
AddCustomModelParams,
AdvancedImageParams,
BenchChatCompletionRequest,
@@ -114,6 +92,48 @@ from exo.shared.types.api import (
TraceStatsResponse,
normalize_image_size,
)
from exo.api.types.claude_api import (
ClaudeMessagesRequest,
ClaudeMessagesResponse,
)
from exo.api.types.ollama_api import (
OllamaChatRequest,
OllamaChatResponse,
OllamaGenerateRequest,
OllamaGenerateResponse,
OllamaModelDetails,
OllamaModelTag,
OllamaPsModel,
OllamaPsResponse,
OllamaShowRequest,
OllamaShowResponse,
OllamaTagsResponse,
)
from exo.api.types.openai_responses import (
ResponsesRequest,
ResponsesResponse,
)
from exo.master.image_store import ImageStore
from exo.master.placement import place_instance as get_instance_placements
from exo.shared.apply import apply
from exo.shared.constants import (
DASHBOARD_DIR,
EXO_CACHE_HOME,
EXO_EVENT_LOG_DIR,
EXO_IMAGE_CACHE_DIR,
EXO_MAX_CHUNK_SIZE,
EXO_TRACING_CACHE_DIR,
)
from exo.shared.election import ElectionMessage
from exo.shared.logging import InterceptLogger
from exo.shared.models.model_cards import (
ModelCard,
ModelId,
delete_custom_card,
get_model_cards,
is_custom_card,
)
from exo.shared.tracing import TraceEvent, compute_stats, export_trace, load_trace_file
from exo.shared.types.chunks import (
ErrorChunk,
ImageChunk,
@@ -122,10 +142,6 @@ from exo.shared.types.chunks import (
TokenChunk,
ToolCallChunk,
)
from exo.shared.types.claude_api import (
ClaudeMessagesRequest,
ClaudeMessagesResponse,
)
from exo.shared.types.commands import (
Command,
CreateInstance,
@@ -151,29 +167,13 @@ from exo.shared.types.events import (
TracesMerged,
)
from exo.shared.types.memory import Memory
from exo.shared.types.ollama_api import (
OllamaChatRequest,
OllamaChatResponse,
OllamaGenerateRequest,
OllamaGenerateResponse,
OllamaModelDetails,
OllamaModelTag,
OllamaPsModel,
OllamaPsResponse,
OllamaShowRequest,
OllamaShowResponse,
OllamaTagsResponse,
)
from exo.shared.types.openai_responses import (
ResponsesRequest,
ResponsesResponse,
)
from exo.shared.types.state import State
from exo.shared.types.worker.downloads import DownloadCompleted
from exo.shared.types.worker.instances import Instance, InstanceId, InstanceMeta
from exo.shared.types.worker.shards import Sharding
from exo.utils.banner import print_startup_banner
from exo.utils.channels import Receiver, Sender, channel
from exo.utils.disk_event_log import DiskEventLog
from exo.utils.power_sampler import PowerSampler
from exo.utils.task_group import TaskGroup
@@ -4,10 +4,11 @@ from typing import Any
from fastapi import FastAPI, HTTPException
from fastapi.testclient import TestClient
from exo.api.main import API
def test_http_exception_handler_formats_openai_style() -> None:
"""Test that HTTPException is converted to OpenAI-style error format."""
from exo.master.api import API
app = FastAPI()
@@ -5,12 +5,12 @@ from unittest.mock import AsyncMock, MagicMock
from fastapi import FastAPI
from fastapi.testclient import TestClient
from exo.api.main import API
from exo.shared.types.common import CommandId
def _make_api() -> Any:
"""Create a minimal API instance with cancel route and error handler."""
from exo.master.api import API
app = FastAPI()
api = object.__new__(API)
@@ -3,11 +3,11 @@
import pydantic
import pytest
from exo.master.adapters.claude import (
from exo.api.adapters.claude import (
claude_request_to_text_generation,
finish_reason_to_claude_stop_reason,
)
from exo.shared.types.claude_api import (
from exo.api.types.claude_api import (
ClaudeMessage,
ClaudeMessagesRequest,
ClaudeTextBlock,
@@ -4,12 +4,12 @@ import json
from collections.abc import AsyncGenerator
from typing import Any, cast
from exo.master.adapters.claude import (
from exo.api.adapters.claude import (
ClaudeMessagesResponse,
collect_claude_response,
generate_claude_stream,
)
from exo.shared.types.api import ToolCallItem
from exo.api.types import ToolCallItem
from exo.shared.types.chunks import ErrorChunk, TokenChunk, ToolCallChunk
from exo.shared.types.common import CommandId, ModelId
@@ -7,11 +7,11 @@ The responses adapter converts it to TextGenerationTaskParams for the pipeline.
import pydantic
import pytest
from exo.shared.types.common import ModelId
from exo.shared.types.openai_responses import (
from exo.api.types.openai_responses import (
ResponseInputMessage,
ResponsesRequest,
)
from exo.shared.types.common import ModelId
class TestResponsesRequestValidation:
+57
View File
@@ -0,0 +1,57 @@
from .api import AddCustomModelParams as AddCustomModelParams
from .api import AdvancedImageParams as AdvancedImageParams
from .api import BenchChatCompletionRequest as BenchChatCompletionRequest
from .api import BenchChatCompletionResponse as BenchChatCompletionResponse
from .api import BenchImageGenerationResponse as BenchImageGenerationResponse
from .api import BenchImageGenerationTaskParams as BenchImageGenerationTaskParams
from .api import CancelCommandResponse as CancelCommandResponse
from .api import ChatCompletionChoice as ChatCompletionChoice
from .api import ChatCompletionMessage as ChatCompletionMessage
from .api import ChatCompletionMessageText as ChatCompletionMessageText
from .api import ChatCompletionRequest as ChatCompletionRequest
from .api import ChatCompletionResponse as ChatCompletionResponse
from .api import CompletionTokensDetails as CompletionTokensDetails
from .api import CreateInstanceParams as CreateInstanceParams
from .api import CreateInstanceResponse as CreateInstanceResponse
from .api import DeleteDownloadResponse as DeleteDownloadResponse
from .api import DeleteInstanceResponse as DeleteInstanceResponse
from .api import DeleteTracesRequest as DeleteTracesRequest
from .api import DeleteTracesResponse as DeleteTracesResponse
from .api import ErrorInfo as ErrorInfo
from .api import ErrorResponse as ErrorResponse
from .api import FinishReason as FinishReason
from .api import GenerationStats as GenerationStats
from .api import HuggingFaceSearchResult as HuggingFaceSearchResult
from .api import ImageData as ImageData
from .api import ImageEditsTaskParams as ImageEditsTaskParams
from .api import ImageGenerationResponse as ImageGenerationResponse
from .api import ImageGenerationStats as ImageGenerationStats
from .api import ImageGenerationTaskParams as ImageGenerationTaskParams
from .api import ImageListItem as ImageListItem
from .api import ImageListResponse as ImageListResponse
from .api import ImageSize as ImageSize
from .api import Logprobs as Logprobs
from .api import LogprobsContentItem as LogprobsContentItem
from .api import ModelList as ModelList
from .api import ModelListModel as ModelListModel
from .api import NodePowerStats as NodePowerStats
from .api import PlaceInstanceParams as PlaceInstanceParams
from .api import PlacementPreview as PlacementPreview
from .api import PlacementPreviewResponse as PlacementPreviewResponse
from .api import PowerUsage as PowerUsage
from .api import PromptTokensDetails as PromptTokensDetails
from .api import StartDownloadParams as StartDownloadParams
from .api import StartDownloadResponse as StartDownloadResponse
from .api import StreamingChoiceResponse as StreamingChoiceResponse
from .api import ToolCall as ToolCall
from .api import ToolCallItem as ToolCallItem
from .api import TopLogprobItem as TopLogprobItem
from .api import TraceCategoryStats as TraceCategoryStats
from .api import TraceEventResponse as TraceEventResponse
from .api import TraceListItem as TraceListItem
from .api import TraceListResponse as TraceListResponse
from .api import TraceRankStats as TraceRankStats
from .api import TraceResponse as TraceResponse
from .api import TraceStatsResponse as TraceStatsResponse
from .api import Usage as Usage
from .api import normalize_image_size as normalize_image_size
+1 -1
View File
@@ -11,9 +11,9 @@ from loguru import logger
from pydantic import PositiveInt
import exo.routing.topics as topics
from exo.api.main import API
from exo.download.coordinator import DownloadCoordinator
from exo.download.impl_shard_downloader import exo_shard_downloader
from exo.master.api import API # TODO: should API be in master?
from exo.master.main import Master
from exo.routing.event_router import EventRouter
from exo.routing.router import Router, get_node_id_keypair
+1 -1
View File
@@ -3,7 +3,6 @@ from datetime import datetime, timedelta, timezone
import anyio
from loguru import logger
from exo.master.event_log import DiskEventLog
from exo.master.placement import (
add_instance_to_placements,
cancel_unnecessary_downloads,
@@ -61,6 +60,7 @@ from exo.shared.types.tasks import (
)
from exo.shared.types.worker.instances import InstanceId
from exo.utils.channels import Receiver, Sender
from exo.utils.disk_event_log import DiskEventLog
from exo.utils.event_buffer import MultiSourceBuffer
from exo.utils.task_group import TaskGroup
+4 -4
View File
@@ -1,18 +1,18 @@
from collections.abc import Generator
from typing import Any, Literal
from exo.shared.models.model_cards import ModelId
from exo.shared.types.api import (
from exo.api.types import (
FinishReason,
GenerationStats,
ImageGenerationStats,
ToolCallItem,
TopLogprobItem,
Usage,
)
from exo.shared.models.model_cards import ModelId
from exo.utils.pydantic_ext import TaggedModel
from .api import FinishReason
from .common import CommandId
from .worker.runner_response import ToolCallItem
class BaseChunk(TaggedModel):
+2 -2
View File
@@ -1,10 +1,10 @@
from pydantic import Field
from exo.shared.models.model_cards import ModelCard, ModelId
from exo.shared.types.api import (
from exo.api.types import (
ImageEditsTaskParams,
ImageGenerationTaskParams,
)
from exo.shared.models.model_cards import ModelCard, ModelId
from exo.shared.types.chunks import InputImageChunk
from exo.shared.types.common import CommandId, NodeId, SystemId
from exo.shared.types.text_generation import TextGenerationTaskParams
+1 -1
View File
@@ -2,7 +2,7 @@ from enum import Enum
from pydantic import Field
from exo.shared.types.api import (
from exo.api.types import (
ImageEditsTaskParams,
ImageGenerationTaskParams,
)
@@ -1,7 +1,7 @@
from collections.abc import Generator
from typing import Any, Literal
from exo.shared.types.api import (
from exo.api.types import (
FinishReason,
GenerationStats,
ImageGenerationStats,
+1 -1
View File
@@ -5,7 +5,7 @@ from typing import final
import anyio
from exo.shared.types.api import NodePowerStats, PowerUsage
from exo.api.types import NodePowerStats, PowerUsage
from exo.shared.types.common import NodeId
from exo.shared.types.profiling import SystemPerformanceProfile
@@ -2,8 +2,8 @@ from pathlib import Path
import pytest
from exo.master.event_log import DiskEventLog
from exo.shared.types.events import TestEvent
from exo.utils.disk_event_log import DiskEventLog
@pytest.fixture
+1 -1
View File
@@ -3,7 +3,7 @@ from collections.abc import Mapping
import anyio
import pytest
from exo.shared.types.api import PowerUsage
from exo.api.types import PowerUsage
from exo.shared.types.common import NodeId
from exo.shared.types.profiling import SystemPerformanceProfile
from exo.utils.power_sampler import PowerSampler
@@ -6,8 +6,8 @@ import mlx.core as mx
from mflux.models.common.config.config import Config
from PIL import Image
from exo.api.types import AdvancedImageParams
from exo.download.download_utils import build_model_path
from exo.shared.types.api import AdvancedImageParams
from exo.shared.types.worker.instances import BoundInstance
from exo.shared.types.worker.shards import CfgShardMetadata, PipelineShardMetadata
from exo.worker.engines.image.config import ImageModelConfig
+1 -1
View File
@@ -9,7 +9,7 @@ from typing import Generator, Literal
import mlx.core as mx
from PIL import Image
from exo.shared.types.api import (
from exo.api.types import (
AdvancedImageParams,
ImageEditsTaskParams,
ImageGenerationStats,
+1 -1
View File
@@ -4,7 +4,7 @@ from typing import Any
from mlx_lm.chat_templates import deepseek_v32
from exo.shared.types.api import ToolCallItem
from exo.api.types import ToolCallItem
BOS_TOKEN: str = deepseek_v32.bos_token
EOS_TOKEN: str = deepseek_v32.eos_token
@@ -10,7 +10,7 @@ from mlx_lm.models.cache import RotatingKVCache
from mlx_lm.sample_utils import make_logits_processors, make_sampler
from mlx_lm.tokenizer_utils import StreamingDetokenizer, TokenizerWrapper
from exo.shared.types.api import (
from exo.api.types import (
CompletionTokensDetails,
FinishReason,
GenerationStats,
@@ -13,7 +13,7 @@ from mlx_lm.models.cache import ArraysCache, RotatingKVCache
from mlx_lm.sample_utils import make_logits_processors, make_sampler
from mlx_lm.tokenizer_utils import TokenizerWrapper
from exo.shared.types.api import (
from exo.api.types import (
CompletionTokensDetails,
FinishReason,
GenerationStats,
+1 -1
View File
@@ -5,10 +5,10 @@ import anyio
from anyio import fail_after
from loguru import logger
from exo.api.types import ImageEditsTaskParams
from exo.download.download_utils import resolve_model_in_path
from exo.shared.apply import apply
from exo.shared.models.model_cards import ModelId
from exo.shared.types.api import ImageEditsTaskParams
from exo.shared.types.commands import (
ForwarderCommand,
ForwarderDownloadCommand,
+1 -1
View File
@@ -4,10 +4,10 @@ from typing import TYPE_CHECKING, Literal
import mlx.core as mx
from exo.api.types import ImageGenerationStats
from exo.shared.constants import EXO_MAX_CHUNK_SIZE, EXO_TRACING_ENABLED
from exo.shared.models.model_cards import ModelTask
from exo.shared.tracing import clear_trace_buffer, get_trace_buffer
from exo.shared.types.api import ImageGenerationStats
from exo.shared.types.chunks import ErrorChunk, ImageChunk
from exo.shared.types.common import CommandId, ModelId
from exo.shared.types.events import (
@@ -13,7 +13,7 @@ from openai_harmony import ( # pyright: ignore[reportMissingTypeStubs]
load_harmony_encoding,
)
from exo.shared.types.api import ToolCallItem
from exo.api.types import ToolCallItem
from exo.shared.types.common import ModelId
from exo.shared.types.mlx import Model
from exo.shared.types.worker.runner_response import GenerationResponse, ToolCallResponse
@@ -3,7 +3,7 @@ import math
from dataclasses import dataclass
from typing import Any, Callable
from exo.shared.types.api import ToolCallItem
from exo.api.types import ToolCallItem
@dataclass
@@ -1,6 +1,6 @@
from collections.abc import Generator
from exo.shared.types.api import FinishReason
from exo.api.types import FinishReason
from exo.shared.types.worker.runner_response import (
GenerationResponse,
ToolCallResponse,