# Review Comment

- **Author:** coderabbitai[bot]
- **File:** `packages/providers/fal/image-to-video/fal_image_to_video/models/base.py`
- **Line:** 31
- **Date:** 2026-02-06
- **Comment ID:** 2772276380
- **URL:** https://github.com/donghaozhang/video-agent-skill/pull/19#discussion_r2772276380

---

_⚠️ Potential issue_ | _🟠 Major_

<details>
<summary>🧩 Analysis chain</summary>

🏁 Script executed:

```shell
#!/bin/bash
# Check for dict pricing in image_to_video registry entries and estimate_cost implementations
cd packages/providers/fal/image-to-video

# First, check the file structure
echo "=== File structure ==="
find . -name "*.py" | head -20

# Look for estimate_cost method
echo "=== Searching for estimate_cost ==="
rg -n --type=py 'def estimate_cost' -C3

# Check base.py to see the full implementation context
echo "=== Checking base.py ==="
cat -n fal_image_to_video/models/base.py | head -80
```

Repository: donghaozhang/video-agent-skill

Length of output: 9520

---

🏁 Script executed:

```shell
# Check the registry for pricing structure
python3 - <<'PYTHON'
import sys
import pathlib

# Try to locate and examine the registry
registry_paths = [
    "packages/core/ai_content_pipeline",
    ".",
]

for path in registry_paths:
    p = pathlib.Path(path).resolve()
    if (p / "ai_content_pipeline" / "registry.py").exists():
        print(f"Found registry at: {p}")
        sys.path.insert(0, str(p))
        try:
            from ai_content_pipeline.registry import ModelRegistry
            # Get image_to_video models
            models = [m for m in ModelRegistry._models.values() if "image_to_video" in m.categories]
            print(f"\nFound {len(models)} image_to_video models")
            for m in models[:5]:  # Show first 5
                print(f"  {m.provider_key}: pricing type = {type(m.pricing).__name__}, value = {m.pricing}")
        except Exception as e:
            print(f"Error loading registry: {e}")
        break
else:
    print("Could not find registry module")
PYTHON
```

Repository: donghaozhang/video-agent-skill

Length of output: 534

---

🏁 Script executed:

```shell
cd packages/providers/fal/image-to-video

# Check kling_o3.py for the specific models
echo "=== Checking kling_o3.py for Kling3Standard and Kling3Pro ==="
rg -n 'class Kling3Standard|class Kling3Pro|def estimate_cost' fal_image_to_video/models/kling_o3.py -B2 -A10

# Check if these models are in the __init__.py
echo -e "\n=== Checking models/__init__.py ==="
cat fal_image_to_video/models/__init__.py
```

Repository: donghaozhang/video-agent-skill

Length of output: 2930

---

🏁 Script executed:

```shell
# Look for how these registry keys map to classes
python3 - <<'PYTHON'
import sys
import pathlib

sys.path.insert(0, str(pathlib.Path("packages/core/ai_content_pipeline").resolve()))
from ai_content_pipeline.registry import ModelRegistry

# Find which models map to kling_3_standard and kling_3_pro
target_keys = ["kling_3_standard", "kling_3_pro"]
for key in target_keys:
    model = ModelRegistry.get_by_provider_key(key)
    if model:
        print(f"\n{key}:")
        print(f"  Provider: {model.provider}")
        print(f"  Pricing: {model.pricing}")
        print(f"  Endpoint: {model.endpoint}")
PYTHON
```

Repository: donghaozhang/video-agent-skill

Length of output: 483

---

🏁 Script executed:

```shell
cd packages/providers/fal/image-to-video

# Check kling.py for KlingV3StandardModel and KlingV3ProModel
echo "=== Checking kling.py for V3 models ==="
rg -n 'class KlingV3StandardModel|class KlingV3ProModel' fal_image_to_video/models/kling.py -A100 | head -150
```

Repository: donghaozhang/video-agent-skill

Length of output: 6841

---

🏁 Script executed:

```shell
cd packages/providers/fal/image-to-video

# Search for estimate_cost in KlingV3StandardModel and KlingV3ProModel
echo "=== Searching for estimate_cost in KlingV3StandardModel and KlingV3ProModel ==="
rg -n 'def estimate_cost' fal_image_to_video/models/kling.py -A15
```

Repository: donghaozhang/video-agent-skill

Length of output: 1594

---



</details>

**Guard against dict-based pricing in `estimate_cost`.**

Registry models can have tiered pricing as dicts (e.g., `kling_3_standard` and `kling_3_pro` with `{'cost_no_audio': ..., 'cost_with_audio': ..., 'cost_voice_control': ...}`). Since `price_per_second` is assigned directly from registry pricing at line 31, the base `estimate_cost` method will crash with a `TypeError` when attempting to multiply a dict by an int. While current models with dict pricing override `estimate_cost`, the base class should include a defensive check.

<details>
<summary>Suggested guard in <code>estimate_cost</code></summary>

```diff
 def estimate_cost(self, duration: int, **kwargs) -> float:
     """Estimate cost for generation."""
+    if isinstance(self.price_per_second, dict):
+        raise TypeError("Tiered pricing requires a model-specific estimate_cost override.")
     return self.price_per_second * duration
```
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
In `@packages/providers/fal/image-to-video/fal_image_to_video/models/base.py`
around lines 28 - 31, The base estimate_cost method must guard against
self.price_per_second being a dict (since ModelRegistry definitions can provide
tiered pricing); inside estimate_cost check if isinstance(self.price_per_second,
dict) and then select the correct numeric price key (e.g., 'cost_with_audio'
when audio is True, otherwise 'cost_no_audio'), falling back to a sensible
numeric key or raising a clear ValueError if no numeric key is present; use that
numeric value for the cost calculation and keep using self._definition and
price_per_second names to locate the logic.
```

</details>

<!-- fingerprinting:phantom:poseidon:eagle -->

<!-- This is an auto-generated comment by CodeRabbit -->
