Add registry improvements, tag filtering, and admin tools

Registry API improvements:
- Add /api/v1/me POST endpoint for profile updates
- Add /api/v1/me/password POST endpoint for password changes
- Fix visibility filtering on categories and tags endpoints to only
  show approved public tools
- Allow underscores in tool names for fabric pattern compatibility
- Fix sqlite3.Row access (use bracket notation instead of .get())

Web UI improvements:
- Add tag filter to /tools page with three-state buttons
  (include/exclude/neutral)
- Add mobile-friendly tag filter in responsive view
- Display tags on tool cards in the tools listing
- Add dashboard settings form handlers for profile and password

Admin improvements:
- Add scrutiny audit page for reviewing tool safety analysis
- Improve pending tools page with scrutiny report display
- Add scrutiny stats to admin dashboard

Fabric sync improvements:
- Add direct database publishing with scrutiny vetting
- Support auto-approve for tools passing scrutiny
- Improve error handling and logging
- Add source attribution for imported tools

Co-Authored-By: Claude Opus 4.5 <[email protected]>
This commit is contained in:
rob
2026-01-16 06:20:16 -04:00
co-authored by Claude Opus 4.5
parent 78025aac8e
commit 5e01a335c0
11 changed files with 1072 additions and 74 deletions
+83 -2
View File
@@ -91,6 +91,85 @@ def clean_prompt(prompt: str) -> str:
return prompt
def extract_description(system_prompt: str, pattern_name: str, max_length: int = 200) -> str:
"""Extract a meaningful description from the system prompt.
Looks for common patterns in Fabric prompts:
1. "# IDENTITY and PURPOSE" section - most common
2. "# IDENTITY" section
3. First paragraph after any title
4. First sentence of the prompt
"""
lines = system_prompt.strip().split('\n')
display_name = pattern_to_display_name(pattern_name)
# Look for IDENTITY and PURPOSE section
in_identity = False
identity_lines = []
for i, line in enumerate(lines):
line_lower = line.lower().strip()
# Check for identity section header
if 'identity' in line_lower and ('purpose' in line_lower or line_lower.startswith('#')):
in_identity = True
continue
# End of identity section (next header)
if in_identity and line.strip().startswith('#'):
break
# Skip filler lines in identity section
if in_identity:
stripped = line.strip()
if stripped and not stripped.lower().startswith((
'take a deep breath',
'think step by step',
'follow these steps',
'use the following'
)):
identity_lines.append(stripped)
if identity_lines:
# Use only the first meaningful line(s) that describe the identity
desc = identity_lines[0]
# Remove common filler phrases
desc = re.sub(r'^You are (an? )?', '', desc, flags=re.IGNORECASE)
desc = re.sub(r'^You\'re (an? )?', '', desc, flags=re.IGNORECASE)
desc = desc.strip()
if desc:
# Capitalize first letter
desc = desc[0].upper() + desc[1:] if len(desc) > 1 else desc.upper()
# Truncate if needed
if len(desc) > max_length:
desc = desc[:max_length-3].rsplit(' ', 1)[0] + '...'
return desc
# Fallback: Look for first meaningful paragraph
for line in lines:
line = line.strip()
# Skip headers, empty lines, and short lines
if line.startswith('#') or not line or len(line) < 20:
continue
# Skip common instruction patterns and metadata
line_lower = line.lower()
if line_lower.startswith((
'take a deep breath', 'think step by step', 'input:',
'title:', 'introduction'
)):
continue
# Found a content line - use it
desc = line
# Remove "Title:" prefix if present
desc = re.sub(r'^Title:\s*', '', desc, flags=re.IGNORECASE)
if len(desc) > max_length:
desc = desc[:max_length-3].rsplit(' ', 1)[0] + '...'
return desc
# Last fallback - generic description
return f"{display_name} - AI-powered tool from Fabric patterns"
def create_tool_config(
pattern_name: str,
system_prompt: str,
@@ -101,15 +180,17 @@ def create_tool_config(
cleaned_prompt = clean_prompt(system_prompt)
display_name = pattern_to_display_name(pattern_name)
category = get_category(pattern_name)
description = extract_description(system_prompt, pattern_name)
# Build the full prompt with input placeholder
full_prompt = f"{cleaned_prompt}\n\n{{input}}"
config = {
"name": pattern_name,
"description": f"{display_name} - imported from Fabric patterns",
"version": "1.0.0",
"description": description,
"version": "1.0.2",
"category": category,
"tags": ["fabric", "imported"],
# Attribution - marks this as an imported tool
"source": {