imp part 3

This commit is contained in:
IGNY8 VPS (Salman)
2025-12-30 10:28:24 +00:00
parent 885158e152
commit 51950c7ce1
5 changed files with 129 additions and 14 deletions

View File

@@ -246,8 +246,21 @@ Stage 7: Generate images → Review queue
| **Usage** | ✅ Active | `/account/usage` |
| **AI Models** | ✅ Active (Admin) | `/settings/integration` |
| **Help** | ✅ Active | `/help` |
| **Linker** | ⏸️ Disabled | Internal linking (available, disabled by default) |
| **Optimizer** | ⏸️ Disabled | Content optimization (available, disabled by default) |
| **SiteBuilder** | ❌ Deprecated | Removed - was for site structure generation |
| **Linker** | ⏸️ Phase 2 | Internal linking suggestions (disabled by default) |
| **Optimizer** | ⏸️ Phase 2 | Content optimization (disabled by default) |
### Module Status Details
| Module | Status | Notes |
|--------|--------|-------|
| **SiteBuilder** | ❌ Deprecated | Code exists but feature is removed. Marked for cleanup. |
| **Linker** | ⏸️ Phase 2 | Feature flag: `linker_enabled`. Available but disabled by default. |
| **Optimizer** | ⏸️ Phase 2 | Feature flag: `optimizer_enabled`. Available but disabled by default. |
To enable Phase 2 modules, update via Django Admin:
- `GlobalModuleSettings` (pk=1) for platform-wide settings
- `ModuleEnableSettings` for per-account settings
---

View File

@@ -591,7 +591,11 @@ class AICore:
image_url = image_data.get('url')
revised_prompt = image_data.get('revised_prompt')
cost = IMAGE_MODEL_RATES.get(model, 0.040) * n
# Use ModelRegistry for image cost (with fallback to constants)
from igny8_core.ai.model_registry import ModelRegistry
cost = float(ModelRegistry.calculate_cost(model, num_images=n))
if cost == 0:
cost = IMAGE_MODEL_RATES.get(model, 0.040) * n
print(f"[AI][{function_name}] Step 5: Image generated successfully")
print(f"[AI][{function_name}] Step 6: Cost: ${cost:.4f}")
print(f"[AI][{function_name}][Success] Image generation completed")
@@ -827,15 +831,24 @@ class AICore:
}
def calculate_cost(self, model: str, input_tokens: int, output_tokens: int, model_type: str = 'text') -> float:
"""Calculate cost for API call"""
"""Calculate cost for API call using ModelRegistry with fallback to constants"""
from igny8_core.ai.model_registry import ModelRegistry
if model_type == 'text':
rates = MODEL_RATES.get(model, {'input': 2.00, 'output': 8.00})
input_cost = (input_tokens / 1_000_000) * rates['input']
output_cost = (output_tokens / 1_000_000) * rates['output']
return input_cost + output_cost
cost = float(ModelRegistry.calculate_cost(model, input_tokens=input_tokens, output_tokens=output_tokens))
if cost == 0:
# Fallback to constants
rates = MODEL_RATES.get(model, {'input': 2.00, 'output': 8.00})
input_cost = (input_tokens / 1_000_000) * rates['input']
output_cost = (output_tokens / 1_000_000) * rates['output']
return input_cost + output_cost
return cost
elif model_type == 'image':
rate = IMAGE_MODEL_RATES.get(model, 0.040)
return rate * 1
cost = float(ModelRegistry.calculate_cost(model, num_images=1))
if cost == 0:
rate = IMAGE_MODEL_RATES.get(model, 0.040)
return rate * 1
return cost
return 0.0
# Legacy method names for backward compatibility

View File

@@ -1,6 +1,9 @@
from django.db import models
from igny8_core.auth.models import SiteSectorBaseModel, SeedKeyword
from igny8_core.common.soft_delete import SoftDeletableModel, SoftDeleteManager
import logging
logger = logging.getLogger(__name__)
class Clusters(SoftDeletableModel, SiteSectorBaseModel):
@@ -40,6 +43,27 @@ class Clusters(SoftDeletableModel, SiteSectorBaseModel):
def __str__(self):
return self.name
def soft_delete(self, user=None, reason=None, retention_days=None):
"""
Override soft_delete to cascade status reset to related Keywords.
When a cluster is deleted, its keywords should:
- Have their cluster FK set to NULL (handled by SET_NULL)
- Have their status reset to 'new' (orphaned keywords)
"""
# Reset related keywords status to 'new' and clear cluster FK
keywords_count = self.keywords.filter(is_deleted=False).update(
cluster=None,
status='new'
)
logger.info(
f"[Clusters.soft_delete] Cluster {self.id} '{self.name}' cascade: "
f"reset {keywords_count} keywords to status='new'"
)
# Call parent soft_delete
super().soft_delete(user=user, reason=reason, retention_days=retention_days)
class Keywords(SoftDeletableModel, SiteSectorBaseModel):
"""

View File

@@ -146,5 +146,70 @@ Before implementing any UI element:
---
**Last Updated**: Current Session
## 📝 Typography Scale
Typography tokens are defined in `index.css` and should be used consistently:
### Title Sizes (for page/section headings)
| Token | Size | Line Height | Use Case |
|-------|------|-------------|----------|
| `--text-title-2xl` | 72px | 90px | Hero sections only |
| `--text-title-xl` | 60px | 72px | Landing page headings |
| `--text-title-lg` | 48px | 60px | Major section headers |
| `--text-title-md` | 36px | 44px | Page titles |
| `--text-title-sm` | 30px | 38px | Section subtitles |
### Theme Sizes (for body text)
| Token | Size | Line Height | Use Case |
|-------|------|-------------|----------|
| `--text-theme-xl` | 20px | 30px | Large body text, intro paragraphs |
| `--text-theme-sm` | 14px | 20px | Standard body text, menu items |
| `--text-theme-xs` | 12px | 18px | Small text, labels, captions |
### Usage in Tailwind
```tsx
// Use Tailwind utilities mapped to tokens
<h1 className="text-title-md">Page Title</h1>
<p className="text-theme-sm">Body text</p>
<span className="text-theme-xs">Caption</span>
// Or use the custom utility classes
<h2 className="text-2xl font-semibold">Section Title</h2>
<p className="text-base">Body text</p>
```
### Font Weights
- `font-normal` (400) - Body text
- `font-medium` (500) - Labels, menu items
- `font-semibold` (600) - Headings, emphasis
- `font-bold` (700) - Strong emphasis
---
## 🎨 Module Colors
Module-specific colors are defined in `src/config/colors.config.ts`:
| Module | Primary Color | Usage |
|--------|---------------|-------|
| Keywords | `brand-500` (blue) | Icons, progress bars, badges |
| Clusters | `purple-500` | Icons, progress bars, badges |
| Ideas | `purple-600` | Icons, progress bars, badges |
| Tasks | `success-600` (green) | Icons, progress bars, badges |
| Content | `success-500` | Icons, progress bars, badges |
| Images | `purple-500` | Icons, progress bars, badges |
| Automation | `brand-500` | Pipeline cards |
| Billing | `warning-500` (amber) | Credit displays |
```tsx
import { MODULE_COLORS } from '@/config/colors.config';
// Use in components
<div className={MODULE_COLORS.keywords.bg}>Keywords Section</div>
<span className={MODULE_COLORS.clusters.text}>Cluster Label</span>
```
---
**Last Updated**: December 30, 2025
**Status**: Active Design System Rules

View File

@@ -175,7 +175,7 @@
}
@utility menu-item {
@apply relative flex items-center w-full gap-3 px-3.5 py-2.5 font-medium rounded-lg text-theme-sm;
@apply relative flex items-center w-full gap-3.5 px-4 py-3 font-medium rounded-lg text-theme-sm;
}
@utility menu-item-active {
@@ -188,7 +188,7 @@
/* Menu icon sizing - consistent across sidebar */
@utility menu-item-icon-size {
@apply w-5 h-5 flex-shrink-0;
@apply w-6 h-6 flex-shrink-0;
/* Force SVG icons to inherit parent size */
& svg {
@@ -207,7 +207,7 @@
/* Dropdown menu items - increased spacing */
@utility menu-dropdown-item {
@apply block px-3 py-2 text-theme-sm font-medium rounded-md transition-colors;
@apply block px-3.5 py-2.5 text-theme-sm font-medium rounded-md transition-colors;
}
@utility menu-dropdown-item-active {