scripts/generate-terminal-service-profiles.py
Rama main · réplica de lectura del repositorio original.
"""Generate the static terminal service-provider projection from core profiles."""
from __future__ import annotations
import argparse
import json
import os
import stat
import sys
import tempfile
from pathlib import Path
from flinttrade_core.llm_provider_profiles import LLM_PROVIDER_PROFILES
from flinttrade_core.news_provider_profiles import NEWS_PROVIDER_PROFILES
ROOT = Path(__file__).resolve().parents[1]
OUTPUT = ROOT / "packages" / "apps" / "terminal" / "src" / "generated" / "serviceProviders.ts"
HEADER = "// Generated by scripts/generate-terminal-service-profiles.py. Do not edit.\n\n"
def _llm_projection() -> list[dict[str, object]]:
return [
{
"apiKeyEnv": profile.api_key_env,
"authModes": list(profile.auth_modes),
"defaultHost": profile.default_host,
"defaultModel": profile.default_model,
"displayName": profile.display_name,
"endpointTemplate": profile.endpoint_template,
"managedRuntime": profile.managed_runtime,
"providerId": str(profile.provider_id),
"requiresHost": profile.requires_host,
"trustDestination": profile.trust_destination,
}
for profile in LLM_PROVIDER_PROFILES
]
def _news_projection() -> list[dict[str, object]]:
return [
{
"channels": [{"name": name, "url": url} for name, url in profile.channels],
"displayName": profile.display_name,
"providerId": profile.provider_id,
}
for profile in NEWS_PROVIDER_PROFILES
]
def render() -> str:
"""Render stable TypeScript literals from static core profile facts."""
llm_json = json.dumps(_llm_projection(), ensure_ascii=False, indent=2, sort_keys=True)
news_json = json.dumps(_news_projection(), ensure_ascii=False, indent=2, sort_keys=True)
return (
HEADER
+ f"export const LLM_PROVIDER_PROFILES = {llm_json} as const;\n\n"
+ 'export type LlmProviderId = (typeof LLM_PROVIDER_PROFILES)[number]["providerId"];\n\n'
+ f"export const NEWS_PUBLISHER_PROFILES = {news_json} as const;\n"
)
def _atomic_write(content: str, output: Path) -> None:
output.parent.mkdir(parents=True, exist_ok=True)
mode = stat.S_IMODE(output.stat().st_mode) if output.exists() else 0o644
descriptor, temporary_name = tempfile.mkstemp(prefix=f".{output.name}.", dir=output.parent)
temporary_path = Path(temporary_name)
try:
with os.fdopen(descriptor, "w", encoding="utf-8", newline="\n") as stream:
stream.write(content)
temporary_path.chmod(mode)
os.replace(temporary_path, output)
except BaseException:
temporary_path.unlink(missing_ok=True)
raise
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--check", action="store_true", help="fail when the checked-in output is stale")
parser.add_argument("--output", type=Path, default=OUTPUT, help="write or check a specific output path")
arguments = parser.parse_args()
rendered = render()
output = arguments.output
if arguments.check:
if not output.is_file() or output.read_text(encoding="utf-8") != rendered:
print(f"Generated terminal service profiles are stale: {output}", file=sys.stderr)
return 1
return 0
_atomic_write(rendered, output)
return 0
if __name__ == "__main__":
raise SystemExit(main())