Skip to content

Commit 6a7f0ab

Browse files
✨ Implement consolidated-based index generation with growth tracking
🔧 New Features: - generate_index_from_consolidated.py: Generates index directly from consolidated_prompts.json - Growth tracking with visual sparkline charts showing library growth over time - Consistent data source eliminates discrepancies between individual JSON parsing and consolidated data 📊 Improvements: - Index now shows current count: 892 valid prompts from 944 total files - Growth metrics displayed at top of index with trend visualization - Updated main update script to use new consolidated-based generator - GitHub workflow now tracks growth_history.json 🎯 Benefits: - Single source of truth: consolidated_prompts.json - Automatic growth tracking for API consumers - Better consistency between consolidation and index - Visual growth trends in repository
1 parent caf5a0b commit 6a7f0ab

File tree

8 files changed

+2077
-1792
lines changed

8 files changed

+2077
-1792
lines changed

.github/workflows/auto_update_index.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ jobs:
4545
# Check if there are changes to commit
4646
if git status --porcelain | grep -q .; then
4747
git add index.md consolidated_prompts.json README.md
48-
git add index_metadata.json consolidated_prompts.metadata.json
48+
git add index_metadata.json consolidated_prompts.metadata.json growth_history.json
4949
git commit -m "🤖 Auto-update: Library indices updated - $(date +'%Y-%m-%d %H:%M UTC')"
5050
git push
5151
echo "✅ Changes committed and pushed successfully!"

README.md

Lines changed: 897 additions & 893 deletions
Large diffs are not rendered by default.

consolidated_prompts.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
{
22
"metadata": {
3-
"generated_at": "2025-08-03T19:30:44.563542",
3+
"generated_at": "2025-08-03T19:43:53.614872",
44
"total_prompts": 944,
55
"source_directory": "../system-prompts/json",
66
"files_processed": 944,
7-
"files_added": 7,
7+
"files_added": 0,
88
"files_updated": 0,
99
"files_removed": 0,
1010
"force_rebuild": false

consolidated_prompts.metadata.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -945,6 +945,6 @@
945945
"SRPBreakdownUtility_170725.json": "4bc1b058a20064e451b2e5e498dde176",
946946
"SocialMediaQuoteTemplater_280725.json": "3fc729f39fb25f01630888a4e19d078d"
947947
},
948-
"last_update": "2025-08-03T19:30:44.563537",
948+
"last_update": "2025-08-03T19:43:53.614860",
949949
"total_files": 944
950950
}

growth_history.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"entries": [
3+
{
4+
"date": "2025-08-03",
5+
"count": 892,
6+
"updated": "2025-08-03T19:43:53.702802"
7+
}
8+
]
9+
}

index.md

Lines changed: 895 additions & 893 deletions
Large diffs are not rendered by default.
Lines changed: 269 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,269 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Generate markdown index table from consolidated prompts JSON file.
4+
5+
This script creates an index.md file from the consolidated_prompts.json file,
6+
ensuring consistency and tracking growth metrics over time.
7+
"""
8+
9+
import json
10+
import os
11+
import argparse
12+
from pathlib import Path
13+
from datetime import datetime
14+
import hashlib
15+
16+
17+
def load_growth_history(history_file):
18+
"""Load existing growth history."""
19+
if os.path.exists(history_file):
20+
with open(history_file, 'r', encoding='utf-8') as f:
21+
return json.load(f)
22+
return {"entries": []}
23+
24+
25+
def save_growth_history(history_file, history):
26+
"""Save growth history."""
27+
with open(history_file, 'w', encoding='utf-8') as f:
28+
json.dump(history, f, indent=2, default=str)
29+
30+
31+
def update_growth_history(history_file, prompt_count):
32+
"""Update growth history with current count."""
33+
history = load_growth_history(history_file)
34+
current_date = datetime.now().strftime('%Y-%m-%d')
35+
36+
# Check if we already have an entry for today
37+
today_entry = None
38+
for entry in history["entries"]:
39+
if entry["date"] == current_date:
40+
today_entry = entry
41+
break
42+
43+
if today_entry:
44+
# Update today's count
45+
today_entry["count"] = prompt_count
46+
today_entry["updated"] = datetime.now().isoformat()
47+
else:
48+
# Add new entry
49+
history["entries"].append({
50+
"date": current_date,
51+
"count": prompt_count,
52+
"updated": datetime.now().isoformat()
53+
})
54+
55+
# Keep only last 365 days
56+
history["entries"] = history["entries"][-365:]
57+
58+
save_growth_history(history_file, history)
59+
return history
60+
61+
62+
def generate_growth_chart(history):
63+
"""Generate a simple text-based growth chart."""
64+
if len(history["entries"]) < 2:
65+
return "📈 Growth tracking started - check back soon for trends!"
66+
67+
entries = history["entries"]
68+
latest = entries[-1]
69+
previous = entries[-2] if len(entries) > 1 else entries[0]
70+
71+
# Calculate growth
72+
growth = latest["count"] - previous["count"]
73+
growth_sign = "📈" if growth > 0 else "📊" if growth == 0 else "📉"
74+
75+
# Get some historical points
76+
chart_data = []
77+
if len(entries) >= 30:
78+
# Show last 30 days
79+
chart_data = entries[-30:]
80+
period = "30 days"
81+
elif len(entries) >= 7:
82+
# Show last 7 days
83+
chart_data = entries[-7:]
84+
period = "7 days"
85+
else:
86+
chart_data = entries
87+
period = f"{len(entries)} days"
88+
89+
# Simple sparkline-style representation
90+
counts = [entry["count"] for entry in chart_data]
91+
min_count = min(counts)
92+
max_count = max(counts)
93+
94+
if max_count == min_count:
95+
sparkline = "▬" * len(counts)
96+
else:
97+
# Normalize to 0-7 range for simple bar chart
98+
normalized = []
99+
for count in counts:
100+
norm = int(((count - min_count) / (max_count - min_count)) * 7)
101+
normalized.append(norm)
102+
103+
# Convert to simple bar chart
104+
bars = ["▁", "▂", "▃", "▄", "▅", "▆", "▇", "█"]
105+
sparkline = "".join(bars[n] for n in normalized)
106+
107+
return f"""📊 **Growth Metrics** ({period}): {sparkline}
108+
- Current: **{latest['count']} prompts**
109+
- Change: {growth_sign} **{abs(growth)} prompts** since {previous['date']}
110+
- Range: {min_count} - {max_count} prompts"""
111+
112+
113+
def generate_index_from_consolidated(consolidated_file, output_file=None, growth_history_file=None):
114+
"""Generate markdown index table from consolidated JSON file."""
115+
116+
# Load consolidated prompts
117+
try:
118+
with open(consolidated_file, 'r', encoding='utf-8') as f:
119+
consolidated_data = json.load(f)
120+
except Exception as e:
121+
print(f"❌ Error loading consolidated file: {e}")
122+
return None
123+
124+
# Handle different consolidated file structures
125+
if isinstance(consolidated_data, list):
126+
# Old format: direct list of prompts
127+
prompts_data = consolidated_data
128+
elif isinstance(consolidated_data, dict) and 'prompts' in consolidated_data:
129+
# New format: object with metadata and prompts
130+
prompts_data = consolidated_data['prompts']
131+
else:
132+
print(f"❌ Error: Unexpected consolidated file structure: {type(consolidated_data)}")
133+
print(f"Available keys: {list(consolidated_data.keys()) if isinstance(consolidated_data, dict) else 'Not a dict'}")
134+
return None
135+
136+
if not isinstance(prompts_data, list):
137+
print(f"❌ Error: Expected list of prompts, got {type(prompts_data)}")
138+
return None
139+
140+
# Filter valid prompts (those with required fields)
141+
valid_prompts = []
142+
for prompt in prompts_data:
143+
if isinstance(prompt, dict):
144+
agent_name = (prompt.get('agentname') or prompt.get('agent-name', '')).strip()
145+
description = (prompt.get('description') or prompt.get('agent-description', '')).strip()
146+
147+
if agent_name and description:
148+
# Create relative link to JSON file
149+
filename = prompt.get('filename', '')
150+
if filename:
151+
relative_link = f"system-prompts/json/{filename}"
152+
else:
153+
# Fallback: try to construct filename from agent name
154+
safe_name = agent_name.replace(' ', '').replace('/', '_').replace('\\', '_')
155+
relative_link = f"system-prompts/json/{safe_name}.json"
156+
157+
# Get ChatGPT link if available
158+
chatgpt_link = prompt.get('chatgptlink') or prompt.get('chatgpt-url', '')
159+
160+
valid_prompts.append({
161+
'agent_name': agent_name,
162+
'description': description,
163+
'link': relative_link,
164+
'chatgpt_link': chatgpt_link
165+
})
166+
167+
# Sort prompts alphabetically by agent name
168+
valid_prompts.sort(key=lambda x: x['agent_name'].lower())
169+
170+
# Update growth history
171+
if growth_history_file:
172+
history = update_growth_history(growth_history_file, len(valid_prompts))
173+
growth_chart = generate_growth_chart(history)
174+
else:
175+
growth_chart = f"📊 **{len(valid_prompts)} system prompts** available"
176+
177+
# Generate markdown content
178+
current_date = datetime.now().strftime('%Y-%m-%d')
179+
current_time = datetime.now().strftime('%H:%M UTC')
180+
181+
markdown_content = f"""# System Prompt Library Index
182+
183+
{growth_chart}
184+
185+
*Last updated: {current_date} at {current_time} | Generated from consolidated_prompts.json*
186+
187+
| Agent Name | Description | CustomGPT |
188+
|------------|-------------|----------|
189+
"""
190+
191+
for prompt in valid_prompts:
192+
# Escape pipe characters in content to avoid breaking the table
193+
agent_name = prompt['agent_name'].replace('|', '\\|')
194+
description = prompt['description'].replace('|', '\\|')
195+
196+
# Truncate description if too long
197+
if len(description) > 150:
198+
description = description[:147] + "..."
199+
200+
# Create agent name with link to JSON file
201+
agent_name_with_link = f"[{agent_name}]({prompt['link']})"
202+
203+
# Add CustomGPT badge if available
204+
customgpt_column = ""
205+
if prompt['chatgpt_link']:
206+
customgpt_column = f"[![CustomGPT](https://img.shields.io/badge/CustomGPT-Available-green)]({prompt['chatgpt_link']})"
207+
208+
markdown_content += f"| {agent_name_with_link} | {description} | {customgpt_column} |\n"
209+
210+
# Write the index file
211+
with open(output_file, 'w', encoding='utf-8') as f:
212+
f.write(markdown_content)
213+
214+
print(f"\n✅ Index generated successfully from consolidated file!")
215+
print(f"📊 Total valid prompts: {len(valid_prompts)}")
216+
print(f"📁 Output file: {output_file}")
217+
print(f"📈 Growth tracking: {'enabled' if growth_history_file else 'disabled'}")
218+
219+
return output_file
220+
221+
222+
def main():
223+
"""Main function with command line argument parsing."""
224+
script_dir = Path(__file__).parent
225+
repo_root = script_dir.parent
226+
227+
parser = argparse.ArgumentParser(
228+
description="Generate markdown index table from consolidated prompts JSON file"
229+
)
230+
parser.add_argument(
231+
"--consolidated-file",
232+
default=str(repo_root / "consolidated_prompts.json"),
233+
help="Consolidated prompts JSON file (default: ../consolidated_prompts.json)"
234+
)
235+
parser.add_argument(
236+
"--output",
237+
default=str(repo_root / "index.md"),
238+
help="Output file name (default: ../index.md)"
239+
)
240+
parser.add_argument(
241+
"--growth-history",
242+
default=str(repo_root / "growth_history.json"),
243+
help="Growth history file (default: ../growth_history.json)"
244+
)
245+
parser.add_argument(
246+
"--no-growth-tracking",
247+
action="store_true",
248+
help="Disable growth tracking"
249+
)
250+
251+
args = parser.parse_args()
252+
253+
# Check if consolidated file exists
254+
if not os.path.exists(args.consolidated_file):
255+
print(f"❌ Error: Consolidated file '{args.consolidated_file}' not found!")
256+
return 1
257+
258+
growth_file = None if args.no_growth_tracking else args.growth_history
259+
260+
try:
261+
generate_index_from_consolidated(args.consolidated_file, args.output, growth_file)
262+
return 0
263+
except Exception as e:
264+
print(f"❌ Error generating index: {e}")
265+
return 1
266+
267+
268+
if __name__ == "__main__":
269+
exit(main())

scripts/update_all.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22
"""
33
Master script to update both JSON consolidation and markdown index.
44
5-
This script runs consolidate_prompts.py, generate_index.py, and update_readme.py in sequence,
5+
This script runs consolidate_prompts.py, generate_index_from_consolidated.py, and update_readme.py in sequence,
66
providing a single command to update all library indices and embed the index in the README.
7+
The index is now generated from the consolidated JSON file for consistency and includes growth tracking.
78
"""
89

910
import subprocess
@@ -104,7 +105,7 @@ def main():
104105
# Update markdown index
105106
if not args.json_only:
106107
total_tasks += 1
107-
markdown_command = ["python3", "generate_index.py"]
108+
markdown_command = ["python3", "generate_index_from_consolidated.py"]
108109

109110
if args.force_rebuild:
110111
markdown_command.append("--force-rebuild")

0 commit comments

Comments
 (0)