Initial commit
This commit is contained in:
298
skills/oracle/scripts/query_knowledge.py
Executable file
298
skills/oracle/scripts/query_knowledge.py
Executable file
@@ -0,0 +1,298 @@
|
||||
#!/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()
|
||||
Reference in New Issue
Block a user