chore: 문서를 작성할 때 한국어의 표현 작성 스킬 추가 및 1인칭 관점의 글 작성 검증 테스트 추가
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import abc
|
||||
import subprocess
|
||||
from dataclasses import dataclass, field
|
||||
from pathlib import Path
|
||||
from typing import Any, Sequence
|
||||
|
||||
from claridoc.models import ProviderSpec
|
||||
|
||||
|
||||
class ProviderError(RuntimeError):
|
||||
"""Base provider invocation error."""
|
||||
|
||||
|
||||
class ProviderUnavailable(ProviderError):
|
||||
"""Raised when a provider binary, SDK, or authentication surface is unavailable."""
|
||||
|
||||
|
||||
@dataclass(slots=True)
|
||||
class ProviderRequest:
|
||||
stage: str
|
||||
prompt: str
|
||||
workdir: Path
|
||||
metadata: dict[str, Any] = field(default_factory=dict)
|
||||
|
||||
|
||||
@dataclass(slots=True)
|
||||
class ProviderResponse:
|
||||
text: str
|
||||
provider: str
|
||||
model: str = ""
|
||||
command: list[str] = field(default_factory=list)
|
||||
metadata: dict[str, Any] = field(default_factory=dict)
|
||||
|
||||
|
||||
class Provider(abc.ABC):
|
||||
def __init__(self, spec: ProviderSpec):
|
||||
self.spec = spec
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
return self.spec.provider
|
||||
|
||||
@abc.abstractmethod
|
||||
def generate(self, request: ProviderRequest) -> ProviderResponse:
|
||||
raise NotImplementedError
|
||||
|
||||
@abc.abstractmethod
|
||||
def check(self) -> dict[str, Any]:
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
def run_command(
|
||||
command: Sequence[str],
|
||||
*,
|
||||
prompt: str,
|
||||
cwd: Path,
|
||||
timeout_seconds: int,
|
||||
env: dict[str, str] | None = None,
|
||||
) -> subprocess.CompletedProcess[str]:
|
||||
try:
|
||||
completed = subprocess.run(
|
||||
list(command),
|
||||
input=prompt,
|
||||
text=True,
|
||||
capture_output=True,
|
||||
cwd=cwd,
|
||||
timeout=timeout_seconds,
|
||||
check=False,
|
||||
env=env,
|
||||
)
|
||||
except FileNotFoundError as exc:
|
||||
raise ProviderUnavailable(f"provider executable not found: {command[0]}") from exc
|
||||
except subprocess.TimeoutExpired as exc:
|
||||
raise ProviderError(f"provider timed out after {timeout_seconds}s: {command[0]}") from exc
|
||||
if completed.returncode != 0:
|
||||
stderr = completed.stderr.strip()
|
||||
stdout = completed.stdout.strip()
|
||||
detail = stderr or stdout or "no diagnostic output"
|
||||
if len(detail) > 2000:
|
||||
detail = detail[-2000:]
|
||||
raise ProviderError(f"provider exited with code {completed.returncode}: {detail}")
|
||||
return completed
|
||||
Reference in New Issue
Block a user