Files
gh-overlord-z-claudeshack/skills/oracle/scripts/query_knowledge.py
2025-11-30 08:46:50 +08:00

299 lines
8.3 KiB
Python
Executable File

#!/usr/bin/env python3
"""
Oracle Knowledge Query Script
Search and retrieve knowledge from the Oracle knowledge base.
Usage:
python query_knowledge.py "search term"
python query_knowledge.py --category patterns
python query_knowledge.py --priority critical
python query_knowledge.py --tags api,auth
python query_knowledge.py --recent 5
Examples:
python query_knowledge.py "authentication"
python query_knowledge.py --category gotchas --priority high
python query_knowledge.py --tags database --recent 10
"""
import os
import sys
import json
import argparse
from datetime import datetime
from pathlib import Path
def find_oracle_root():
"""Find the .oracle directory by walking up from current directory."""
current = Path.cwd()
while current != current.parent:
oracle_path = current / '.oracle'
if oracle_path.exists():
return oracle_path
current = current.parent
return None
def load_knowledge(oracle_path, category=None):
"""Load knowledge from specified category or all categories."""
knowledge_dir = oracle_path / 'knowledge'
all_knowledge = []
categories = [category] if category else ['patterns', 'preferences', 'gotchas', 'solutions', 'corrections']
for cat in categories:
file_path = knowledge_dir / f'{cat}.json'
if file_path.exists():
with open(file_path, 'r') as f:
entries = json.load(f)
for entry in entries:
entry['_category'] = cat
all_knowledge.append(entry)
return all_knowledge
def search_knowledge(knowledge, query=None, priority=None, tags=None):
"""Filter knowledge based on search criteria."""
results = knowledge
# Filter by query (search in title and content)
if query:
query_lower = query.lower()
results = [
entry for entry in results
if query_lower in entry.get('title', '').lower()
or query_lower in entry.get('content', '').lower()
or query_lower in str(entry.get('context', '')).lower()
]
# Filter by priority
if priority:
results = [entry for entry in results if entry.get('priority') == priority]
# Filter by tags
if tags:
tag_list = [t.strip() for t in tags.split(',')]
results = [
entry for entry in results
if any(tag in entry.get('tags', []) for tag in tag_list)
]
return results
def sort_knowledge(knowledge, sort_by='priority'):
"""Sort knowledge by various criteria."""
priority_order = {'critical': 0, 'high': 1, 'medium': 2, 'low': 3}
if sort_by == 'priority':
return sorted(knowledge, key=lambda x: priority_order.get(x.get('priority', 'low'), 3))
elif sort_by == 'recent':
return sorted(knowledge, key=lambda x: x.get('created', ''), reverse=True)
elif sort_by == 'used':
return sorted(knowledge, key=lambda x: x.get('use_count', 0), reverse=True)
else:
return knowledge
def format_entry(entry, compact=False):
"""Format a knowledge entry for display."""
if compact:
return f" [{entry['_category']}] {entry.get('title', 'Untitled')} (Priority: {entry.get('priority', 'N/A')})"
output = []
output.append("" * 70)
output.append(f" {entry.get('title', 'Untitled')}")
output.append(f" Category: {entry['_category']} | Priority: {entry.get('priority', 'N/A')}")
if entry.get('tags'):
output.append(f" Tags: {', '.join(entry['tags'])}")
output.append("")
output.append(f" {entry.get('content', 'No content')}")
if entry.get('context'):
output.append("")
output.append(f" Context: {entry['context']}")
if entry.get('examples'):
output.append("")
output.append(" Examples:")
for ex in entry['examples']:
output.append(f" - {ex}")
output.append("")
output.append(f" Created: {entry.get('created', 'Unknown')}")
output.append(f" Used: {entry.get('use_count', 0)} times")
if entry.get('learned_from'):
output.append(f" Source: {entry['learned_from']}")
return "\n".join(output)
def display_results(results, compact=False, limit=None):
"""Display search results."""
if not results:
print("[ERROR] No knowledge found matching your criteria.")
return
total = len(results)
display_count = min(limit, total) if limit else total
print(f"\n[SEARCH] Found {total} result(s)")
if limit and total > limit:
print(f" Showing first {display_count} results\n")
else:
print()
for i, entry in enumerate(results[:display_count], 1):
if compact:
print(format_entry(entry, compact=True))
else:
print(format_entry(entry, compact=False))
if i < display_count:
print()
def display_summary(oracle_path):
"""Display summary of knowledge base."""
index_path = oracle_path / 'index.json'
if not index_path.exists():
print("[WARNING] No index found. Knowledge base may be empty.")
return
with open(index_path, 'r') as f:
index = json.load(f)
print("="*70)
print("[INFO] Oracle Knowledge Base Summary")
print("="*70)
print(f"\nCreated: {index.get('created', 'Unknown')}")
print(f"Last Updated: {index.get('last_updated', 'Unknown')}")
print(f"Total Entries: {index.get('total_entries', 0)}")
print("\nEntries by Category:")
for category, count in index.get('categories', {}).items():
print(f" {category.capitalize()}: {count}")
print(f"\nSessions Recorded: {len(index.get('sessions', []))}")
print("="*70)
def main():
parser = argparse.ArgumentParser(
description='Query Oracle knowledge base',
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
Examples:
python query_knowledge.py "authentication"
python query_knowledge.py --category patterns
python query_knowledge.py --priority critical
python query_knowledge.py --tags api,database
python query_knowledge.py --recent 5
python query_knowledge.py --summary
"""
)
parser.add_argument(
'query',
nargs='?',
help='Search query (searches title, content, context)'
)
parser.add_argument(
'--category',
choices=['patterns', 'preferences', 'gotchas', 'solutions', 'corrections'],
help='Filter by category'
)
parser.add_argument(
'--priority',
choices=['critical', 'high', 'medium', 'low'],
help='Filter by priority'
)
parser.add_argument(
'--tags',
help='Filter by tags (comma-separated)'
)
parser.add_argument(
'--sort',
choices=['priority', 'recent', 'used'],
default='priority',
help='Sort results by (default: priority)'
)
parser.add_argument(
'--limit',
type=int,
help='Limit number of results'
)
parser.add_argument(
'--recent',
type=int,
metavar='N',
help='Show N most recent entries'
)
parser.add_argument(
'--compact',
action='store_true',
help='Display compact results'
)
parser.add_argument(
'--summary',
action='store_true',
help='Display knowledge base summary'
)
args = parser.parse_args()
# Find Oracle directory
oracle_path = find_oracle_root()
if not oracle_path:
print("[ERROR] Error: .oracle directory not found.")
print(" Run: python .claude/skills/oracle/scripts/init_oracle.py")
sys.exit(1)
# Display summary if requested
if args.summary:
display_summary(oracle_path)
sys.exit(0)
# Load knowledge
knowledge = load_knowledge(oracle_path, args.category)
if not knowledge:
print("[ERROR] No knowledge entries found.")
print(" Start recording sessions to build the knowledge base.")
sys.exit(0)
# Search and filter
results = search_knowledge(knowledge, args.query, args.priority, args.tags)
# Sort
if args.recent:
results = sort_knowledge(results, 'recent')
limit = args.recent
else:
results = sort_knowledge(results, args.sort)
limit = args.limit
# Display
display_results(results, args.compact, limit)
if __name__ == '__main__':
main()