feat(migrations): Rename indexes and update global integration settings fields for improved clarity and functionality

feat(admin): Add API monitoring, debug console, and system health templates for enhanced admin interface

docs: Add AI system cleanup summary and audit report detailing architecture, token management, and recommendations

docs: Introduce credits and tokens system guide outlining configuration, data flow, and monitoring strategies
This commit is contained in:
IGNY8 VPS (Salman)
2025-12-20 12:55:05 +00:00
parent eb6cba7920
commit 3283a83b42
51 changed files with 3578 additions and 5434 deletions

View File

@@ -5,6 +5,12 @@ from django.contrib import admin
from unfold.admin import ModelAdmin
from igny8_core.admin.base import AccountAdminMixin, Igny8ModelAdmin
from .models import AIPrompt, IntegrationSettings, AuthorProfile, Strategy
from .global_settings_models import (
GlobalIntegrationSettings,
GlobalAIPrompt,
GlobalAuthorProfile,
GlobalStrategy,
)
from django.contrib import messages
from import_export.admin import ExportMixin, ImportExportMixin
@@ -52,8 +58,8 @@ except ImportError:
@admin.register(AIPrompt)
class AIPromptAdmin(ImportExportMixin, AccountAdminMixin, Igny8ModelAdmin):
resource_class = AIPromptResource
list_display = ['id', 'prompt_type', 'account', 'is_active', 'updated_at']
list_filter = ['prompt_type', 'is_active', 'account']
list_display = ['id', 'prompt_type', 'account', 'is_customized', 'is_active', 'updated_at']
list_filter = ['prompt_type', 'is_active', 'is_customized', 'account']
search_fields = ['prompt_type']
readonly_fields = ['created_at', 'updated_at', 'default_prompt']
actions = [
@@ -64,10 +70,11 @@ class AIPromptAdmin(ImportExportMixin, AccountAdminMixin, Igny8ModelAdmin):
fieldsets = (
('Basic Info', {
'fields': ('account', 'prompt_type', 'is_active')
'fields': ('account', 'prompt_type', 'is_active', 'is_customized')
}),
('Prompt Content', {
'fields': ('prompt_value', 'default_prompt')
'fields': ('prompt_value', 'default_prompt'),
'description': 'Customize prompt_value or reset to default_prompt'
}),
('Timestamps', {
'fields': ('created_at', 'updated_at')
@@ -94,14 +101,14 @@ class AIPromptAdmin(ImportExportMixin, AccountAdminMixin, Igny8ModelAdmin):
bulk_deactivate.short_description = 'Deactivate selected prompts'
def bulk_reset_to_default(self, request, queryset):
"""Reset selected prompts to their global defaults"""
count = 0
for prompt in queryset:
if prompt.default_prompt:
prompt.prompt_value = prompt.default_prompt
prompt.save()
prompt.reset_to_default()
count += 1
self.message_user(request, f'{count} AI prompt(s) reset to default values.', messages.SUCCESS)
bulk_reset_to_default.short_description = 'Reset to default values'
self.message_user(request, f'{count} prompt(s) reset to default.', messages.SUCCESS)
bulk_reset_to_default.short_description = 'Reset selected prompts to global default'
class IntegrationSettingsResource(resources.ModelResource):
@@ -114,36 +121,42 @@ class IntegrationSettingsResource(resources.ModelResource):
@admin.register(IntegrationSettings)
class IntegrationSettingsAdmin(ExportMixin, AccountAdminMixin, Igny8ModelAdmin):
"""
Admin for per-account integration setting overrides.
IMPORTANT: This stores ONLY model selection and parameter overrides.
API keys come from GlobalIntegrationSettings and cannot be overridden.
Free plan users cannot create these - they must use global defaults.
"""
resource_class = IntegrationSettingsResource
list_display = ['id', 'integration_type', 'account', 'is_active', 'updated_at']
list_filter = ['integration_type', 'is_active', 'account']
search_fields = ['integration_type']
search_fields = ['integration_type', 'account__name']
readonly_fields = ['created_at', 'updated_at']
actions = [
'bulk_activate',
'bulk_deactivate',
'bulk_test_connection',
]
fieldsets = (
('Basic Info', {
'fields': ('account', 'integration_type', 'is_active')
}),
('Configuration', {
('Configuration Overrides', {
'fields': ('config',),
'description': 'JSON configuration containing API keys and settings. Example: {"apiKey": "sk-...", "model": "gpt-4.1", "enabled": true}'
'description': (
'JSON overrides for model/parameter selection. '
'Fields: model, temperature, max_tokens, image_size, image_quality, etc. '
'Leave null to use global defaults. '
'Example: {"model": "gpt-4", "temperature": 0.8, "max_tokens": 4000} '
'WARNING: NEVER store API keys here - they come from GlobalIntegrationSettings'
)
}),
('Timestamps', {
'fields': ('created_at', 'updated_at')
}),
)
def get_readonly_fields(self, request, obj=None):
"""Make config readonly when viewing to prevent accidental exposure"""
if obj: # Editing existing object
return self.readonly_fields + ['config']
return self.readonly_fields
def get_account_display(self, obj):
"""Safely get account name"""
try:
@@ -312,4 +325,119 @@ class StrategyAdmin(ImportExportMixin, AccountAdminMixin, Igny8ModelAdmin):
strategy_copy.save()
count += 1
self.message_user(request, f'{count} strategy/strategies cloned.', messages.SUCCESS)
bulk_clone.short_description = 'Clone selected strategies'
bulk_clone.short_description = 'Clone selected strategies'
# =============================================================================
# GLOBAL SETTINGS ADMIN - Platform-wide defaults
# =============================================================================
@admin.register(GlobalIntegrationSettings)
class GlobalIntegrationSettingsAdmin(Igny8ModelAdmin):
"""Admin for global integration settings (singleton)"""
list_display = ["id", "is_active", "last_updated", "updated_by"]
readonly_fields = ["last_updated"]
fieldsets = (
("OpenAI Settings", {
"fields": ("openai_api_key", "openai_model", "openai_temperature", "openai_max_tokens"),
"description": "Global OpenAI configuration used by all accounts (unless overridden)"
}),
("DALL-E Settings", {
"fields": ("dalle_api_key", "dalle_model", "dalle_size", "dalle_quality", "dalle_style"),
"description": "Global DALL-E image generation configuration"
}),
("Anthropic Settings", {
"fields": ("anthropic_api_key", "anthropic_model"),
"description": "Global Anthropic Claude configuration"
}),
("Runware Settings", {
"fields": ("runware_api_key",),
"description": "Global Runware image generation configuration"
}),
("Status", {
"fields": ("is_active", "last_updated", "updated_by")
}),
)
def has_add_permission(self, request):
"""Only allow one instance (singleton pattern)"""
return not GlobalIntegrationSettings.objects.exists()
def has_delete_permission(self, request, obj=None):
"""Dont allow deletion of singleton"""
return False
@admin.register(GlobalAIPrompt)
class GlobalAIPromptAdmin(ExportMixin, Igny8ModelAdmin):
"""Admin for global AI prompt templates"""
list_display = ["prompt_type", "version", "is_active", "last_updated"]
list_filter = ["is_active", "prompt_type", "version"]
search_fields = ["prompt_type", "description"]
readonly_fields = ["last_updated", "created_at"]
fieldsets = (
("Basic Info", {
"fields": ("prompt_type", "description", "is_active", "version")
}),
("Prompt Content", {
"fields": ("prompt_value", "variables"),
"description": "Variables should be a list of variable names used in the prompt"
}),
("Timestamps", {
"fields": ("created_at", "last_updated")
}),
)
actions = ["increment_version"]
def increment_version(self, request, queryset):
"""Increment version for selected prompts"""
for prompt in queryset:
prompt.version += 1
prompt.save()
self.message_user(request, f"{queryset.count()} prompt(s) version incremented.", messages.SUCCESS)
increment_version.short_description = "Increment version"
@admin.register(GlobalAuthorProfile)
class GlobalAuthorProfileAdmin(ImportExportMixin, Igny8ModelAdmin):
"""Admin for global author profile templates"""
list_display = ["name", "category", "tone", "language", "is_active", "created_at"]
list_filter = ["is_active", "category", "tone", "language"]
search_fields = ["name", "description"]
readonly_fields = ["created_at", "updated_at"]
fieldsets = (
("Basic Info", {
"fields": ("name", "description", "category", "is_active")
}),
("Writing Style", {
"fields": ("tone", "language", "structure_template")
}),
("Timestamps", {
"fields": ("created_at", "updated_at")
}),
)
@admin.register(GlobalStrategy)
class GlobalStrategyAdmin(ImportExportMixin, Igny8ModelAdmin):
"""Admin for global strategy templates"""
list_display = ["name", "category", "is_active", "created_at"]
list_filter = ["is_active", "category"]
search_fields = ["name", "description"]
readonly_fields = ["created_at", "updated_at"]
fieldsets = (
("Basic Info", {
"fields": ("name", "description", "category", "is_active")
}),
("Strategy Configuration", {
"fields": ("prompt_types", "section_logic")
}),
("Timestamps", {
"fields": ("created_at", "updated_at")
}),
)