mirror of
https://github.com/affaan-m/ECC.git
synced 2026-09-18 15:50:25 +02:00
* feat: bundle standalone taste distillation and application workflows * docs: fix imported taste skill markdown lint * docs: align Turkish agent catalog with taste skills * refactor: make ECC the canonical reusable video engine * fix: preserve video duration when applying image overlays * fix: preserve background colors in image compositing * fix: report best-effort duration targets and shortfalls * feat: ship verified Fusion presets with compatibility provenance * feat(tasteforge): preserve native edits in application bundles * feat(tasteforge): compile local preservation without hosted input * fix: update js-yaml to patched 4.3.2 * test: report bounded Stop wrapper failure diagnostics * fix(tasteforge): fail closed on unsafe output names, missing overlays and cadence - cli: default report and spec paths are derived from pack name and profile genre; require the manifest's name pattern before using either as a filename part so a traversal string cannot write outside cwd/out. - apply_local: a pack without cadence.json, or with no measured shots and no explicit mean_shot, raises instead of silently planning 1.0s shots and reporting a measured cadence. - legacy apply: a missing overlay aborts before any paid upload; forge() would have rejected it after every take was generated. - requirements-live: pin fal-client>=0.13.0, the first release whose subscribe() accepts client_timeout. Addresses the five P1 findings from the independent review of #3033. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015fxHRsydPqEcYngGbqkgt1 --------- Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
85 lines
2.8 KiB
Python
85 lines
2.8 KiB
Python
"""Optional provider adapters. There are none, by design.
|
|
|
|
The recovered TasteForge flow used Fal for vision distillation, image-to-3D,
|
|
reference-to-video generation, and hosted ffmpeg composition. In this
|
|
repeatable lane those become *optional adapters* that FAIL CLOSED:
|
|
|
|
* the default registry is empty;
|
|
* looking up a provider raises before any network-capable module is imported;
|
|
* even opting in requires BOTH an explicit runtime registration with
|
|
``authorize=True`` AND the ``TASTEFORGE_ALLOW_PROVIDERS`` environment flag,
|
|
and no adapter ships with this package.
|
|
|
|
Nothing in this module (or package) imports fal_client, urllib, sockets, or
|
|
any other network facility.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
from typing import Any, Callable
|
|
|
|
ALLOW_ENV = "TASTEFORGE_ALLOW_PROVIDERS"
|
|
|
|
_FAIL_CLOSED_MESSAGE = (
|
|
"provider {provider!r} is not available: provider generation in "
|
|
"TasteForge requires explicit separately authorized execution. This "
|
|
"package ships no provider adapters and performs no network calls; the "
|
|
"deterministic offline workflows (inspect/validate/interview/distill "
|
|
"dry-run/apply local/export) need no provider."
|
|
)
|
|
|
|
|
|
class ProviderNotAuthorizedError(RuntimeError):
|
|
"""Raised before any provider interaction when access is not authorized."""
|
|
|
|
|
|
AdapterFactory = Callable[[], Any]
|
|
|
|
|
|
def list_providers() -> list[str]:
|
|
"""Registered provider ids. Always empty in this lane."""
|
|
return sorted(_REGISTRY)
|
|
|
|
|
|
def get(provider: str) -> Any:
|
|
"""Return the adapter for ``provider`` or fail closed.
|
|
|
|
Fails closed - raising before any import or I/O - unless the provider was
|
|
explicitly registered with authorization AND the opt-in environment flag
|
|
is set. No provider is ever registered by this package.
|
|
"""
|
|
entry = _REGISTRY.get(provider)
|
|
if entry is None or not entry.get("authorized"):
|
|
raise ProviderNotAuthorizedError(_FAIL_CLOSED_MESSAGE.format(provider=provider))
|
|
if os.environ.get(ALLOW_ENV, "").strip().lower() not in {"1", "true", "yes", "on"}:
|
|
raise ProviderNotAuthorizedError(_FAIL_CLOSED_MESSAGE.format(provider=provider))
|
|
return entry["factory"]()
|
|
|
|
|
|
def register(
|
|
provider: str,
|
|
callable_factory: AdapterFactory,
|
|
*,
|
|
authorize: bool = False,
|
|
) -> None:
|
|
"""Register an adapter factory. Refuses silent authorization.
|
|
|
|
``authorize=True`` without the ``TASTEFORGE_ALLOW_PROVIDERS`` environment
|
|
flag is still a refusal: enabling a provider is a two-step deliberate act,
|
|
never a default.
|
|
"""
|
|
if not authorize:
|
|
raise ProviderNotAuthorizedError(
|
|
_FAIL_CLOSED_MESSAGE.format(provider=provider)
|
|
)
|
|
_REGISTRY[provider] = {"factory": callable_factory, "authorized": True}
|
|
|
|
|
|
def reset() -> None:
|
|
"""Clear the registry (test helper)."""
|
|
_REGISTRY.clear()
|
|
|
|
|
|
_REGISTRY: dict[str, dict[str, Any]] = {}
|