File size: 4,312 Bytes
9328e91
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# HuggingFace Authentication Integration Notes

## Purpose
Allow users to save their Big RPG Scale entity databases to their own HuggingFace datasets (avoiding data collection concerns).

## Requirements
- Space-level OAuth configuration
- User authentication via `gr.LoginButton()`
- Save/load to user's own HF datasets

## README.md Changes Required
```yaml
---
title: GameConfigIdeaEditBrainstorm
hf_oauth: true
hf_oauth_scopes:
  - read-repos
  - write-repos
---
```

## Gradio OAuth Integration

### Login Button
```python
import gradio as gr

with gr.Blocks() as demo:
    gr.LoginButton(variant="huggingface", size="sm")
```

### Access User Profile
```python
def my_function(profile: gr.OAuthProfile | None):
    if profile:
        username = profile.username
        # Can now save to user's repos
    else:
        return "Please log in first"
```

### Access User Token
```python
def save_to_user_dataset(
    profile: gr.OAuthProfile | None,
    token: gr.OAuthToken | None,
    data: str
):
    if not profile or not token:
        return "Login required"

    # Use token.token for API calls
```

## Implementation Functions

### Save Database
```python
from huggingface_hub import HfApi, create_repo

def save_database_to_hf(
    db: EntityDatabase,
    profile: gr.OAuthProfile,
    token: gr.OAuthToken,
    dataset_name: str = "rpg-entity-database"
) -> str:
    username = profile.username
    repo_id = f"{username}/{dataset_name}"

    api = HfApi(token=token.token)

    # Create repo if needed
    create_repo(repo_id, repo_type="dataset", exist_ok=True, private=True)

    # Export and upload
    db_json = db.to_json()
    api.upload_file(
        path_or_fileobj=db_json.encode('utf-8'),
        path_in_repo="entity_database.json",
        repo_id=repo_id,
        repo_type="dataset"
    )

    return f"Saved to: https://huggingface.co/datasets/{repo_id}"
```

### Load Database
```python
from huggingface_hub import hf_hub_download

def load_database_from_hf(
    db: EntityDatabase,
    profile: gr.OAuthProfile,
    token: gr.OAuthToken,
    dataset_name: str = "rpg-entity-database"
) -> str:
    username = profile.username
    repo_id = f"{username}/{dataset_name}"

    file_path = hf_hub_download(
        repo_id=repo_id,
        filename="entity_database.json",
        repo_type="dataset",
        token=token.token
    )

    with open(file_path, 'r') as f:
        json_str = f.read()

    success, message = db.from_json(json_str)
    return message
```

## UI Integration

### Entity Database Tab Addition
```python
with gr.Row():
    login_btn = gr.LoginButton(variant="huggingface", size="sm")
    login_status = gr.Markdown("*Not logged in*")

with gr.Accordion("Cloud Save/Load (HuggingFace)", open=False):
    gr.Markdown("Save your entity database to your HuggingFace account.")

    hf_dataset_name = gr.Textbox(
        label="Dataset Name",
        value="rpg-entity-database"
    )

    with gr.Row():
        save_to_hf_btn = gr.Button("Save to HuggingFace", variant="primary")
        load_from_hf_btn = gr.Button("Load from HuggingFace")

    hf_status = gr.Markdown("")
```

## Graceful Degradation
- All local features work without login
- Show `gr.Info("Please log in...")` when save/load attempted without auth
- Display current login status prominently

## Alternative: CommitScheduler (Auto-Save)
For session logging (like D&D GM event logs):
```python
from huggingface_hub import CommitScheduler

scheduler = CommitScheduler(
    folder_path="./user_data",
    repo_id=f"{username}/game-sessions",
    token=token.token,
    private=True
)
```
- Runs background thread, pushes every ~1 minute
- Good for append-only data (logs, feedback)
- Not ideal for frequently-updated files

## Resources
- [Gradio OAuth Docs](https://huggingface.co/docs/hub/spaces-oauth)
- [Gradio OAuth Example Space](https://huggingface.co/spaces/gradio/oauth-example)
- [HuggingFace Hub Upload Guide](https://huggingface.co/docs/huggingface_hub/guides/upload)
- [Spaces Persistent Storage](https://huggingface.co/docs/hub/spaces-storage)

## TODO
- [ ] Test OAuth flow locally with `huggingface-cli login`
- [ ] Decide on dataset structure (single JSON vs multiple files)
- [ ] Consider versioning/backup strategy
- [ ] Investigate Space-level persistent storage options