File size: 5,555 Bytes
0ea40d5
2503583
0ea40d5
 
 
 
 
 
 
b5a0b96
0ea40d5
 
2c0a58f
 
b5a0b96
 
 
2c0a58f
 
 
 
0ea40d5
 
2503583
 
 
e547f9d
2503583
c473f37
2503583
 
2c0a58f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2503583
 
 
 
 
 
2c0a58f
2503583
 
 
 
 
 
 
 
 
 
c473f37
5f3014b
c473f37
5f3014b
c473f37
 
 
5f3014b
 
 
 
 
 
c473f37
 
 
5f3014b
c473f37
 
5f3014b
c473f37
5f3014b
 
c473f37
5f3014b
c473f37
5f3014b
c473f37
 
 
5f3014b
c473f37
 
2c0a58f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150

# ./storage.py

"""

Persistence Layer - Handles the "Save/Load" functionality using Hugging Face Dataset as a database

"""

import json
import os
from datetime import datetime
from huggingface_hub import HfApi, hf_hub_download


# --- CONFIGURATION ---
REPO_ID = "prashantmatlani/chathistorycoderg"
HISTORY_DIR = "./chathistory"

# Internal Session Authentication Toggle
_SESSION_UNLOCKED = False

# Initialize the API with your token
api = HfApi(token=os.getenv("HF_TOKEN"))

def get_secret_password():
    """Dynamically reads the environment secret to prevent cached empty variables at startup."""
    val = os.getenv("APP_PASSWORD")

    print(f"\nlen val: {len(val)}\n")

    return str(val).strip() if val is not None else ""

def verify_and_unlock(user_password_input):
    """Validates input credentials and flips the internal tracking state variable."""
    global _SESSION_UNLOCKED
    target_password = get_secret_password()
    clean_input = str(user_password_input).strip()
    
    # If no master environment password exists, unlock access automatically
    if not target_password:
        _SESSION_UNLOCKED = True
        return True
        
    if clean_input == target_password:
        _SESSION_UNLOCKED = True
        return True
        
    return False

def load_history(user_password=""):
    """Retrieves list of chat IDs from the Hub ONLY if the password matches the secret."""
    target_password = get_secret_password()
    clean_input = str(user_password).strip()

    # ====================================================================
    # 🔐 IF / ELSE SECURITY CONFIGURATION
    # ====================================================================
    
    # Condition 1: If the password field is left blank OR if it doesn't match the secret...
    if not clean_input or clean_input != target_password:
        print("[*] Security Guardrail: Invalid or empty password submitted. Bypassing history retrieval.")
        return []  # --> Then: No history loading
        
    # Condition 2: Otherwise (it matches perfectly), proceed to load history
    print("[+] Security Pass: Credentials verified. Loading environment histories...")
    
    try:
        # 1. Attempt to get rich metadata for chronological sorting
        repo_info = api.repo_info(repo_id=REPO_ID, repo_type="dataset", files_metadata=True)
        
        chat_files_meta = []
        if repo_info and hasattr(repo_info, 'siblings'):
            for f in repo_info.siblings:
                # Safe startswith check
                if f.rfind('chats/') == 0:  
                    filename_idx = f.rfind('/') + 1
                    chat_id = f[filename_idx:].replace(".json", "")
                    
                    # Safely extract last_modified timestamp if it exists
                    last_modified = getattr(f, 'last_modified', None)
                    chat_files_meta.append((chat_id, last_modified))
            
            # Sort by timestamp if available; otherwise fall back to string name
            chat_files_meta.sort(key=lambda x: x[1] if x[1] is not None else x[0], reverse=True)
            return [[item[0]] for item in chat_files_meta]

    except Exception as metadata_error:
        # Log the error so it's visible in your HF Space logs instead of swallowing it
        print(f"[!] Metadata fetch failed, switching to fallback string sort: {metadata_error}")
        
    # 2. Fallback Layer: If metadata calls fail, immediately run original working string method
    try:
        files = api.list_repo_files(repo_id=REPO_ID, repo_type="dataset")
        chat_files = [f.split("/")[-1].replace(".json", "") for f in files if f.startswith("chats/")]
        return [[f] for f in sorted(chat_files, reverse=True)]
    except Exception as fallback_error:
        print(f"[!!] Total storage access failure: {fallback_error}")
        return []

def save_chat(chat_id, history):
    """Saves chat to local subdirectory and syncs to Hugging Face Dataset."""
    if not os.path.exists(HISTORY_DIR):
        os.makedirs(HISTORY_DIR)
    
    if not chat_id:
        chat_id = datetime.now().strftime("%m%d%Y_%H%M%S")
    
    filename = f"{chat_id}.json"
    local_path = os.path.join(HISTORY_DIR, filename)
    
    with open(local_path, "w", encoding="utf-8") as f:
        json.dump(history, f, indent=4)
    
    try:
        api.upload_file(
            path_or_fileobj=local_path,
            path_in_repo=f"chats/{filename}",
            repo_id=REPO_ID,
            repo_type="dataset"
        )
    except Exception as e:
        print(f"Cloud Sync Warning: {e}")
        
    return chat_id

def get_chat_content(chat_id):
    """Loads a specific chat's content from the Hub or local cache."""
    filename = f"chats/{chat_id}.json"
    local_path = os.path.join(HISTORY_DIR, f"{chat_id}.json")
    
    try:
        if not os.path.exists(HISTORY_DIR):
            os.makedirs(HISTORY_DIR)
            
        downloaded_path = hf_hub_download(
            repo_id=REPO_ID, 
            repo_type="dataset", 
            filename=filename,
            token=os.getenv("HF_TOKEN")
        )
        with open(downloaded_path, "r", encoding="utf-8") as f:
            return json.load(f)
    except Exception:
        if os.path.exists(local_path):
            with open(local_path, "r", encoding="utf-8") as f:
                return json.load(f)
    return []