@namch/agent-assistant 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +83 -539
- package/agents/backend-engineer.md +0 -8
- package/agents/brainstormer.md +0 -6
- package/agents/business-analyst.md +0 -5
- package/agents/database-architect.md +0 -6
- package/agents/debugger.md +0 -6
- package/agents/designer.md +0 -5
- package/agents/devops-engineer.md +0 -7
- package/agents/docs-manager.md +0 -6
- package/agents/frontend-engineer.md +0 -7
- package/agents/game-engineer.md +0 -7
- package/agents/mobile-engineer.md +0 -7
- package/agents/performance-engineer.md +0 -7
- package/agents/planner.md +0 -6
- package/agents/project-manager.md +0 -6
- package/agents/researcher.md +0 -5
- package/agents/reviewer.md +0 -6
- package/agents/scouter.md +0 -6
- package/agents/security-engineer.md +0 -7
- package/agents/tech-lead.md +0 -7
- package/agents/tester.md +0 -5
- package/cli/README.md +19 -10
- package/documents/business/business-features.md +1 -1
- package/documents/business/business-prd.md +4 -4
- package/documents/knowledge-architecture.md +1 -1
- package/documents/knowledge-domain.md +1 -1
- package/documents/knowledge-overview.md +14 -29
- package/documents/knowledge-source-base.md +14 -14
- package/package.json +1 -1
- package/rules/QUICK-REFERENCE.md +4 -1
- package/rules/SKILL-DISCOVERY.md +37 -14
- package/skills/active-directory-attacks/SKILL.md +383 -0
- package/skills/active-directory-attacks/references/advanced-attacks.md +382 -0
- package/skills/agent-evaluation/SKILL.md +64 -0
- package/skills/agent-memory-mcp/SKILL.md +82 -0
- package/skills/agent-memory-systems/SKILL.md +67 -0
- package/skills/agent-tool-builder/SKILL.md +53 -0
- package/skills/ai-agents-architect/SKILL.md +90 -0
- package/skills/ai-product/SKILL.md +54 -0
- package/skills/ai-wrapper-product/SKILL.md +273 -0
- package/skills/api-documentation-generator/SKILL.md +484 -0
- package/skills/api-fuzzing-bug-bounty/SKILL.md +433 -0
- package/skills/api-security-best-practices/SKILL.md +907 -0
- package/skills/autonomous-agent-patterns/SKILL.md +761 -0
- package/skills/autonomous-agents/SKILL.md +68 -0
- package/skills/aws-penetration-testing/SKILL.md +405 -0
- package/skills/aws-penetration-testing/references/advanced-aws-pentesting.md +469 -0
- package/skills/azure-functions/SKILL.md +42 -0
- package/skills/backend-dev-guidelines/SKILL.md +342 -0
- package/skills/backend-dev-guidelines/resources/architecture-overview.md +451 -0
- package/skills/backend-dev-guidelines/resources/async-and-errors.md +307 -0
- package/skills/backend-dev-guidelines/resources/complete-examples.md +638 -0
- package/skills/backend-dev-guidelines/resources/configuration.md +275 -0
- package/skills/backend-dev-guidelines/resources/database-patterns.md +224 -0
- package/skills/backend-dev-guidelines/resources/middleware-guide.md +213 -0
- package/skills/backend-dev-guidelines/resources/routing-and-controllers.md +756 -0
- package/skills/backend-dev-guidelines/resources/sentry-and-monitoring.md +336 -0
- package/skills/backend-dev-guidelines/resources/services-and-repositories.md +789 -0
- package/skills/backend-dev-guidelines/resources/testing-guide.md +235 -0
- package/skills/backend-dev-guidelines/resources/validation-patterns.md +754 -0
- package/skills/broken-authentication/SKILL.md +476 -0
- package/skills/bullmq-specialist/SKILL.md +57 -0
- package/skills/bun-development/SKILL.md +691 -0
- package/skills/burp-suite-testing/SKILL.md +380 -0
- package/skills/cloud-penetration-testing/SKILL.md +501 -0
- package/skills/cloud-penetration-testing/references/advanced-cloud-scripts.md +318 -0
- package/skills/computer-use-agents/SKILL.md +315 -0
- package/skills/content-creator/SKILL.md +248 -0
- package/skills/content-creator/assets/content_calendar_template.md +99 -0
- package/skills/content-creator/references/brand_guidelines.md +199 -0
- package/skills/content-creator/references/content_frameworks.md +534 -0
- package/skills/content-creator/references/social_media_optimization.md +317 -0
- package/skills/content-creator/scripts/brand_voice_analyzer.py +185 -0
- package/skills/content-creator/scripts/seo_optimizer.py +419 -0
- package/skills/context-window-management/SKILL.md +53 -0
- package/skills/conversation-memory/SKILL.md +61 -0
- package/skills/copy-editing/SKILL.md +439 -0
- package/skills/copywriting/SKILL.md +225 -0
- package/skills/crewai/SKILL.md +243 -0
- package/skills/discord-bot-architect/SKILL.md +277 -0
- package/skills/dispatching-parallel-agents/SKILL.md +180 -0
- package/skills/email-sequence/SKILL.md +925 -0
- package/skills/email-systems/SKILL.md +54 -0
- package/skills/ethical-hacking-methodology/SKILL.md +466 -0
- package/skills/executing-plans/SKILL.md +76 -0
- package/skills/file-path-traversal/SKILL.md +486 -0
- package/skills/finishing-a-development-branch/SKILL.md +200 -0
- package/skills/frontend-dev-guidelines/SKILL.md +359 -0
- package/skills/frontend-dev-guidelines/resources/common-patterns.md +331 -0
- package/skills/frontend-dev-guidelines/resources/complete-examples.md +872 -0
- package/skills/frontend-dev-guidelines/resources/component-patterns.md +502 -0
- package/skills/frontend-dev-guidelines/resources/data-fetching.md +767 -0
- package/skills/frontend-dev-guidelines/resources/file-organization.md +502 -0
- package/skills/frontend-dev-guidelines/resources/loading-and-error-states.md +501 -0
- package/skills/frontend-dev-guidelines/resources/performance.md +406 -0
- package/skills/frontend-dev-guidelines/resources/routing-guide.md +364 -0
- package/skills/frontend-dev-guidelines/resources/styling-guide.md +428 -0
- package/skills/frontend-dev-guidelines/resources/typescript-standards.md +418 -0
- package/skills/gcp-cloud-run/SKILL.md +288 -0
- package/skills/git-pushing/SKILL.md +33 -0
- package/skills/git-pushing/scripts/smart_commit.sh +19 -0
- package/skills/github-workflow-automation/SKILL.md +846 -0
- package/skills/html-injection-testing/SKILL.md +498 -0
- package/skills/idor-testing/SKILL.md +442 -0
- package/skills/inngest/SKILL.md +55 -0
- package/skills/javascript-mastery/SKILL.md +645 -0
- package/skills/kaizen/SKILL.md +730 -0
- package/skills/langfuse/SKILL.md +238 -0
- package/skills/langgraph/SKILL.md +287 -0
- package/skills/linux-privilege-escalation/SKILL.md +504 -0
- package/skills/llm-app-patterns/SKILL.md +760 -0
- package/skills/metasploit-framework/SKILL.md +478 -0
- package/skills/multi-agent-brainstorming/SKILL.md +256 -0
- package/skills/neon-postgres/SKILL.md +56 -0
- package/skills/nextjs-supabase-auth/SKILL.md +56 -0
- package/skills/nosql-expert/SKILL.md +111 -0
- package/skills/pentest-checklist/SKILL.md +334 -0
- package/skills/pentest-commands/SKILL.md +438 -0
- package/skills/plaid-fintech/SKILL.md +50 -0
- package/skills/planning-with-files/SKILL.md +211 -0
- package/skills/planning-with-files/examples.md +202 -0
- package/skills/planning-with-files/reference.md +218 -0
- package/skills/planning-with-files/scripts/check-complete.sh +44 -0
- package/skills/planning-with-files/scripts/init-session.sh +120 -0
- package/skills/planning-with-files/templates/findings.md +95 -0
- package/skills/planning-with-files/templates/progress.md +114 -0
- package/skills/planning-with-files/templates/task_plan.md +132 -0
- package/skills/privilege-escalation-methods/SKILL.md +333 -0
- package/skills/production-code-audit/SKILL.md +540 -0
- package/skills/prompt-caching/SKILL.md +61 -0
- package/skills/prompt-engineering/SKILL.md +171 -0
- package/skills/prompt-library/SKILL.md +322 -0
- package/skills/rag-engineer/SKILL.md +90 -0
- package/skills/rag-implementation/SKILL.md +63 -0
- package/skills/react-ui-patterns/SKILL.md +289 -0
- package/skills/red-team-tools/SKILL.md +310 -0
- package/skills/scanning-tools/SKILL.md +589 -0
- package/skills/shodan-reconnaissance/SKILL.md +503 -0
- package/skills/slack-bot-builder/SKILL.md +264 -0
- package/skills/smtp-penetration-testing/SKILL.md +500 -0
- package/skills/social-content/SKILL.md +807 -0
- package/skills/software-architecture/SKILL.md +75 -0
- package/skills/sql-injection-testing/SKILL.md +448 -0
- package/skills/sqlmap-database-pentesting/SKILL.md +400 -0
- package/skills/ssh-penetration-testing/SKILL.md +488 -0
- package/skills/stripe-integration/SKILL.md +69 -0
- package/skills/subagent-driven-development/SKILL.md +240 -0
- package/skills/subagent-driven-development/code-quality-reviewer-prompt.md +20 -0
- package/skills/subagent-driven-development/implementer-prompt.md +78 -0
- package/skills/subagent-driven-development/spec-reviewer-prompt.md +61 -0
- package/skills/tavily-web/SKILL.md +36 -0
- package/skills/telegram-bot-builder/SKILL.md +254 -0
- package/skills/test-driven-development/SKILL.md +371 -0
- package/skills/test-driven-development/testing-anti-patterns.md +299 -0
- package/skills/test-fixing/SKILL.md +119 -0
- package/skills/top-web-vulnerabilities/SKILL.md +543 -0
- package/skills/trigger-dev/SKILL.md +67 -0
- package/skills/twilio-communications/SKILL.md +295 -0
- package/skills/upstash-qstash/SKILL.md +68 -0
- package/skills/verification-before-completion/SKILL.md +139 -0
- package/skills/voice-agents/SKILL.md +68 -0
- package/skills/voice-ai-development/SKILL.md +302 -0
- package/skills/windows-privilege-escalation/SKILL.md +496 -0
- package/skills/wireshark-analysis/SKILL.md +497 -0
- package/skills/wordpress-penetration-testing/SKILL.md +485 -0
- package/skills/workflow-automation/SKILL.md +68 -0
- package/skills/xss-html-injection/SKILL.md +499 -0
- package/skills/zapier-make-patterns/SKILL.md +67 -0
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
SEO Content Optimizer - Analyzes and optimizes content for SEO
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import re
|
|
7
|
+
from typing import Dict, List, Set
|
|
8
|
+
import json
|
|
9
|
+
|
|
10
|
+
class SEOOptimizer:
|
|
11
|
+
def __init__(self):
|
|
12
|
+
# Common stop words to filter
|
|
13
|
+
self.stop_words = {
|
|
14
|
+
'the', 'a', 'an', 'and', 'or', 'but', 'in', 'on', 'at', 'to', 'for',
|
|
15
|
+
'of', 'with', 'by', 'from', 'as', 'is', 'was', 'are', 'were', 'be',
|
|
16
|
+
'been', 'being', 'have', 'has', 'had', 'do', 'does', 'did', 'will',
|
|
17
|
+
'would', 'could', 'should', 'may', 'might', 'must', 'can', 'shall'
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
# SEO best practices
|
|
21
|
+
self.best_practices = {
|
|
22
|
+
'title_length': (50, 60),
|
|
23
|
+
'meta_description_length': (150, 160),
|
|
24
|
+
'url_length': (50, 60),
|
|
25
|
+
'paragraph_length': (40, 150),
|
|
26
|
+
'heading_keyword_placement': True,
|
|
27
|
+
'keyword_density': (0.01, 0.03) # 1-3%
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
def analyze(self, content: str, target_keyword: str = None,
|
|
31
|
+
secondary_keywords: List[str] = None) -> Dict:
|
|
32
|
+
"""Analyze content for SEO optimization"""
|
|
33
|
+
|
|
34
|
+
analysis = {
|
|
35
|
+
'content_length': len(content.split()),
|
|
36
|
+
'keyword_analysis': {},
|
|
37
|
+
'structure_analysis': self._analyze_structure(content),
|
|
38
|
+
'readability': self._analyze_readability(content),
|
|
39
|
+
'meta_suggestions': {},
|
|
40
|
+
'optimization_score': 0,
|
|
41
|
+
'recommendations': []
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
# Keyword analysis
|
|
45
|
+
if target_keyword:
|
|
46
|
+
analysis['keyword_analysis'] = self._analyze_keywords(
|
|
47
|
+
content, target_keyword, secondary_keywords or []
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
# Generate meta suggestions
|
|
51
|
+
analysis['meta_suggestions'] = self._generate_meta_suggestions(
|
|
52
|
+
content, target_keyword
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
# Calculate optimization score
|
|
56
|
+
analysis['optimization_score'] = self._calculate_seo_score(analysis)
|
|
57
|
+
|
|
58
|
+
# Generate recommendations
|
|
59
|
+
analysis['recommendations'] = self._generate_recommendations(analysis)
|
|
60
|
+
|
|
61
|
+
return analysis
|
|
62
|
+
|
|
63
|
+
def _analyze_keywords(self, content: str, primary: str,
|
|
64
|
+
secondary: List[str]) -> Dict:
|
|
65
|
+
"""Analyze keyword usage and density"""
|
|
66
|
+
content_lower = content.lower()
|
|
67
|
+
word_count = len(content.split())
|
|
68
|
+
|
|
69
|
+
results = {
|
|
70
|
+
'primary_keyword': {
|
|
71
|
+
'keyword': primary,
|
|
72
|
+
'count': content_lower.count(primary.lower()),
|
|
73
|
+
'density': 0,
|
|
74
|
+
'in_title': False,
|
|
75
|
+
'in_headings': False,
|
|
76
|
+
'in_first_paragraph': False
|
|
77
|
+
},
|
|
78
|
+
'secondary_keywords': [],
|
|
79
|
+
'lsi_keywords': []
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
# Calculate primary keyword metrics
|
|
83
|
+
if word_count > 0:
|
|
84
|
+
results['primary_keyword']['density'] = (
|
|
85
|
+
results['primary_keyword']['count'] / word_count
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
# Check keyword placement
|
|
89
|
+
first_para = content.split('\n\n')[0] if '\n\n' in content else content[:200]
|
|
90
|
+
results['primary_keyword']['in_first_paragraph'] = (
|
|
91
|
+
primary.lower() in first_para.lower()
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
# Analyze secondary keywords
|
|
95
|
+
for keyword in secondary:
|
|
96
|
+
count = content_lower.count(keyword.lower())
|
|
97
|
+
results['secondary_keywords'].append({
|
|
98
|
+
'keyword': keyword,
|
|
99
|
+
'count': count,
|
|
100
|
+
'density': count / word_count if word_count > 0 else 0
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
# Extract potential LSI keywords
|
|
104
|
+
results['lsi_keywords'] = self._extract_lsi_keywords(content, primary)
|
|
105
|
+
|
|
106
|
+
return results
|
|
107
|
+
|
|
108
|
+
def _analyze_structure(self, content: str) -> Dict:
|
|
109
|
+
"""Analyze content structure for SEO"""
|
|
110
|
+
lines = content.split('\n')
|
|
111
|
+
|
|
112
|
+
structure = {
|
|
113
|
+
'headings': {'h1': 0, 'h2': 0, 'h3': 0, 'total': 0},
|
|
114
|
+
'paragraphs': 0,
|
|
115
|
+
'lists': 0,
|
|
116
|
+
'images': 0,
|
|
117
|
+
'links': {'internal': 0, 'external': 0},
|
|
118
|
+
'avg_paragraph_length': 0
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
paragraphs = []
|
|
122
|
+
current_para = []
|
|
123
|
+
|
|
124
|
+
for line in lines:
|
|
125
|
+
# Count headings
|
|
126
|
+
if line.startswith('# '):
|
|
127
|
+
structure['headings']['h1'] += 1
|
|
128
|
+
structure['headings']['total'] += 1
|
|
129
|
+
elif line.startswith('## '):
|
|
130
|
+
structure['headings']['h2'] += 1
|
|
131
|
+
structure['headings']['total'] += 1
|
|
132
|
+
elif line.startswith('### '):
|
|
133
|
+
structure['headings']['h3'] += 1
|
|
134
|
+
structure['headings']['total'] += 1
|
|
135
|
+
|
|
136
|
+
# Count lists
|
|
137
|
+
if line.strip().startswith(('- ', '* ', '1. ')):
|
|
138
|
+
structure['lists'] += 1
|
|
139
|
+
|
|
140
|
+
# Count links
|
|
141
|
+
internal_links = len(re.findall(r'\[.*?\]\(/.*?\)', line))
|
|
142
|
+
external_links = len(re.findall(r'\[.*?\]\(https?://.*?\)', line))
|
|
143
|
+
structure['links']['internal'] += internal_links
|
|
144
|
+
structure['links']['external'] += external_links
|
|
145
|
+
|
|
146
|
+
# Track paragraphs
|
|
147
|
+
if line.strip() and not line.startswith('#'):
|
|
148
|
+
current_para.append(line)
|
|
149
|
+
elif current_para:
|
|
150
|
+
paragraphs.append(' '.join(current_para))
|
|
151
|
+
current_para = []
|
|
152
|
+
|
|
153
|
+
if current_para:
|
|
154
|
+
paragraphs.append(' '.join(current_para))
|
|
155
|
+
|
|
156
|
+
structure['paragraphs'] = len(paragraphs)
|
|
157
|
+
|
|
158
|
+
if paragraphs:
|
|
159
|
+
avg_length = sum(len(p.split()) for p in paragraphs) / len(paragraphs)
|
|
160
|
+
structure['avg_paragraph_length'] = round(avg_length, 1)
|
|
161
|
+
|
|
162
|
+
return structure
|
|
163
|
+
|
|
164
|
+
def _analyze_readability(self, content: str) -> Dict:
|
|
165
|
+
"""Analyze content readability"""
|
|
166
|
+
sentences = re.split(r'[.!?]+', content)
|
|
167
|
+
words = content.split()
|
|
168
|
+
|
|
169
|
+
if not sentences or not words:
|
|
170
|
+
return {'score': 0, 'level': 'Unknown'}
|
|
171
|
+
|
|
172
|
+
avg_sentence_length = len(words) / len(sentences)
|
|
173
|
+
|
|
174
|
+
# Simple readability scoring
|
|
175
|
+
if avg_sentence_length < 15:
|
|
176
|
+
level = 'Easy'
|
|
177
|
+
score = 90
|
|
178
|
+
elif avg_sentence_length < 20:
|
|
179
|
+
level = 'Moderate'
|
|
180
|
+
score = 70
|
|
181
|
+
elif avg_sentence_length < 25:
|
|
182
|
+
level = 'Difficult'
|
|
183
|
+
score = 50
|
|
184
|
+
else:
|
|
185
|
+
level = 'Very Difficult'
|
|
186
|
+
score = 30
|
|
187
|
+
|
|
188
|
+
return {
|
|
189
|
+
'score': score,
|
|
190
|
+
'level': level,
|
|
191
|
+
'avg_sentence_length': round(avg_sentence_length, 1)
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
def _extract_lsi_keywords(self, content: str, primary_keyword: str) -> List[str]:
|
|
195
|
+
"""Extract potential LSI (semantically related) keywords"""
|
|
196
|
+
words = re.findall(r'\b[a-z]+\b', content.lower())
|
|
197
|
+
word_freq = {}
|
|
198
|
+
|
|
199
|
+
# Count word frequencies
|
|
200
|
+
for word in words:
|
|
201
|
+
if word not in self.stop_words and len(word) > 3:
|
|
202
|
+
word_freq[word] = word_freq.get(word, 0) + 1
|
|
203
|
+
|
|
204
|
+
# Sort by frequency and return top related terms
|
|
205
|
+
sorted_words = sorted(word_freq.items(), key=lambda x: x[1], reverse=True)
|
|
206
|
+
|
|
207
|
+
# Filter out the primary keyword and return top 10
|
|
208
|
+
lsi_keywords = []
|
|
209
|
+
for word, count in sorted_words:
|
|
210
|
+
if word != primary_keyword.lower() and count > 1:
|
|
211
|
+
lsi_keywords.append(word)
|
|
212
|
+
if len(lsi_keywords) >= 10:
|
|
213
|
+
break
|
|
214
|
+
|
|
215
|
+
return lsi_keywords
|
|
216
|
+
|
|
217
|
+
def _generate_meta_suggestions(self, content: str, keyword: str = None) -> Dict:
|
|
218
|
+
"""Generate SEO meta tag suggestions"""
|
|
219
|
+
# Extract first sentence for description base
|
|
220
|
+
sentences = re.split(r'[.!?]+', content)
|
|
221
|
+
first_sentence = sentences[0] if sentences else content[:160]
|
|
222
|
+
|
|
223
|
+
suggestions = {
|
|
224
|
+
'title': '',
|
|
225
|
+
'meta_description': '',
|
|
226
|
+
'url_slug': '',
|
|
227
|
+
'og_title': '',
|
|
228
|
+
'og_description': ''
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
if keyword:
|
|
232
|
+
# Title suggestion
|
|
233
|
+
suggestions['title'] = f"{keyword.title()} - Complete Guide"
|
|
234
|
+
if len(suggestions['title']) > 60:
|
|
235
|
+
suggestions['title'] = keyword.title()[:57] + "..."
|
|
236
|
+
|
|
237
|
+
# Meta description
|
|
238
|
+
desc_base = f"Learn everything about {keyword}. {first_sentence}"
|
|
239
|
+
if len(desc_base) > 160:
|
|
240
|
+
desc_base = desc_base[:157] + "..."
|
|
241
|
+
suggestions['meta_description'] = desc_base
|
|
242
|
+
|
|
243
|
+
# URL slug
|
|
244
|
+
suggestions['url_slug'] = re.sub(r'[^a-z0-9-]+', '-',
|
|
245
|
+
keyword.lower()).strip('-')
|
|
246
|
+
|
|
247
|
+
# Open Graph tags
|
|
248
|
+
suggestions['og_title'] = suggestions['title']
|
|
249
|
+
suggestions['og_description'] = suggestions['meta_description']
|
|
250
|
+
|
|
251
|
+
return suggestions
|
|
252
|
+
|
|
253
|
+
def _calculate_seo_score(self, analysis: Dict) -> int:
|
|
254
|
+
"""Calculate overall SEO optimization score"""
|
|
255
|
+
score = 0
|
|
256
|
+
max_score = 100
|
|
257
|
+
|
|
258
|
+
# Content length scoring (20 points)
|
|
259
|
+
if 300 <= analysis['content_length'] <= 2500:
|
|
260
|
+
score += 20
|
|
261
|
+
elif 200 <= analysis['content_length'] < 300:
|
|
262
|
+
score += 10
|
|
263
|
+
elif analysis['content_length'] > 2500:
|
|
264
|
+
score += 15
|
|
265
|
+
|
|
266
|
+
# Keyword optimization (30 points)
|
|
267
|
+
if analysis['keyword_analysis']:
|
|
268
|
+
kw_data = analysis['keyword_analysis']['primary_keyword']
|
|
269
|
+
|
|
270
|
+
# Density scoring
|
|
271
|
+
if 0.01 <= kw_data['density'] <= 0.03:
|
|
272
|
+
score += 15
|
|
273
|
+
elif 0.005 <= kw_data['density'] < 0.01:
|
|
274
|
+
score += 8
|
|
275
|
+
|
|
276
|
+
# Placement scoring
|
|
277
|
+
if kw_data['in_first_paragraph']:
|
|
278
|
+
score += 10
|
|
279
|
+
if kw_data.get('in_headings'):
|
|
280
|
+
score += 5
|
|
281
|
+
|
|
282
|
+
# Structure scoring (25 points)
|
|
283
|
+
struct = analysis['structure_analysis']
|
|
284
|
+
if struct['headings']['total'] > 0:
|
|
285
|
+
score += 10
|
|
286
|
+
if struct['paragraphs'] >= 3:
|
|
287
|
+
score += 10
|
|
288
|
+
if struct['links']['internal'] > 0 or struct['links']['external'] > 0:
|
|
289
|
+
score += 5
|
|
290
|
+
|
|
291
|
+
# Readability scoring (25 points)
|
|
292
|
+
readability_score = analysis['readability']['score']
|
|
293
|
+
score += int(readability_score * 0.25)
|
|
294
|
+
|
|
295
|
+
return min(score, max_score)
|
|
296
|
+
|
|
297
|
+
def _generate_recommendations(self, analysis: Dict) -> List[str]:
|
|
298
|
+
"""Generate SEO improvement recommendations"""
|
|
299
|
+
recommendations = []
|
|
300
|
+
|
|
301
|
+
# Content length recommendations
|
|
302
|
+
if analysis['content_length'] < 300:
|
|
303
|
+
recommendations.append(
|
|
304
|
+
f"Increase content length to at least 300 words (currently {analysis['content_length']})"
|
|
305
|
+
)
|
|
306
|
+
elif analysis['content_length'] > 3000:
|
|
307
|
+
recommendations.append(
|
|
308
|
+
"Consider breaking long content into multiple pages or adding a table of contents"
|
|
309
|
+
)
|
|
310
|
+
|
|
311
|
+
# Keyword recommendations
|
|
312
|
+
if analysis['keyword_analysis']:
|
|
313
|
+
kw_data = analysis['keyword_analysis']['primary_keyword']
|
|
314
|
+
|
|
315
|
+
if kw_data['density'] < 0.01:
|
|
316
|
+
recommendations.append(
|
|
317
|
+
f"Increase keyword density for '{kw_data['keyword']}' (currently {kw_data['density']:.2%})"
|
|
318
|
+
)
|
|
319
|
+
elif kw_data['density'] > 0.03:
|
|
320
|
+
recommendations.append(
|
|
321
|
+
f"Reduce keyword density to avoid over-optimization (currently {kw_data['density']:.2%})"
|
|
322
|
+
)
|
|
323
|
+
|
|
324
|
+
if not kw_data['in_first_paragraph']:
|
|
325
|
+
recommendations.append(
|
|
326
|
+
"Include primary keyword in the first paragraph"
|
|
327
|
+
)
|
|
328
|
+
|
|
329
|
+
# Structure recommendations
|
|
330
|
+
struct = analysis['structure_analysis']
|
|
331
|
+
if struct['headings']['total'] == 0:
|
|
332
|
+
recommendations.append("Add headings (H1, H2, H3) to improve content structure")
|
|
333
|
+
if struct['links']['internal'] == 0:
|
|
334
|
+
recommendations.append("Add internal links to related content")
|
|
335
|
+
if struct['avg_paragraph_length'] > 150:
|
|
336
|
+
recommendations.append("Break up long paragraphs for better readability")
|
|
337
|
+
|
|
338
|
+
# Readability recommendations
|
|
339
|
+
if analysis['readability']['avg_sentence_length'] > 20:
|
|
340
|
+
recommendations.append("Simplify sentences for better readability")
|
|
341
|
+
|
|
342
|
+
return recommendations
|
|
343
|
+
|
|
344
|
+
def optimize_content(content: str, keyword: str = None,
|
|
345
|
+
secondary_keywords: List[str] = None) -> str:
|
|
346
|
+
"""Main function to optimize content"""
|
|
347
|
+
optimizer = SEOOptimizer()
|
|
348
|
+
|
|
349
|
+
# Parse secondary keywords from comma-separated string if provided
|
|
350
|
+
if secondary_keywords and isinstance(secondary_keywords, str):
|
|
351
|
+
secondary_keywords = [kw.strip() for kw in secondary_keywords.split(',')]
|
|
352
|
+
|
|
353
|
+
results = optimizer.analyze(content, keyword, secondary_keywords)
|
|
354
|
+
|
|
355
|
+
# Format output
|
|
356
|
+
output = [
|
|
357
|
+
"=== SEO Content Analysis ===",
|
|
358
|
+
f"Overall SEO Score: {results['optimization_score']}/100",
|
|
359
|
+
f"Content Length: {results['content_length']} words",
|
|
360
|
+
f"",
|
|
361
|
+
"Content Structure:",
|
|
362
|
+
f" Headings: {results['structure_analysis']['headings']['total']}",
|
|
363
|
+
f" Paragraphs: {results['structure_analysis']['paragraphs']}",
|
|
364
|
+
f" Avg Paragraph Length: {results['structure_analysis']['avg_paragraph_length']} words",
|
|
365
|
+
f" Internal Links: {results['structure_analysis']['links']['internal']}",
|
|
366
|
+
f" External Links: {results['structure_analysis']['links']['external']}",
|
|
367
|
+
f"",
|
|
368
|
+
f"Readability: {results['readability']['level']} (Score: {results['readability']['score']})",
|
|
369
|
+
f""
|
|
370
|
+
]
|
|
371
|
+
|
|
372
|
+
if results['keyword_analysis']:
|
|
373
|
+
kw = results['keyword_analysis']['primary_keyword']
|
|
374
|
+
output.extend([
|
|
375
|
+
"Keyword Analysis:",
|
|
376
|
+
f" Primary Keyword: {kw['keyword']}",
|
|
377
|
+
f" Count: {kw['count']}",
|
|
378
|
+
f" Density: {kw['density']:.2%}",
|
|
379
|
+
f" In First Paragraph: {'Yes' if kw['in_first_paragraph'] else 'No'}",
|
|
380
|
+
f""
|
|
381
|
+
])
|
|
382
|
+
|
|
383
|
+
if results['keyword_analysis']['lsi_keywords']:
|
|
384
|
+
output.append(" Related Keywords Found:")
|
|
385
|
+
for lsi in results['keyword_analysis']['lsi_keywords'][:5]:
|
|
386
|
+
output.append(f" • {lsi}")
|
|
387
|
+
output.append("")
|
|
388
|
+
|
|
389
|
+
if results['meta_suggestions']:
|
|
390
|
+
output.extend([
|
|
391
|
+
"Meta Tag Suggestions:",
|
|
392
|
+
f" Title: {results['meta_suggestions']['title']}",
|
|
393
|
+
f" Description: {results['meta_suggestions']['meta_description']}",
|
|
394
|
+
f" URL Slug: {results['meta_suggestions']['url_slug']}",
|
|
395
|
+
f""
|
|
396
|
+
])
|
|
397
|
+
|
|
398
|
+
output.extend([
|
|
399
|
+
"Recommendations:",
|
|
400
|
+
])
|
|
401
|
+
|
|
402
|
+
for rec in results['recommendations']:
|
|
403
|
+
output.append(f" • {rec}")
|
|
404
|
+
|
|
405
|
+
return '\n'.join(output)
|
|
406
|
+
|
|
407
|
+
if __name__ == "__main__":
|
|
408
|
+
import sys
|
|
409
|
+
|
|
410
|
+
if len(sys.argv) > 1:
|
|
411
|
+
with open(sys.argv[1], 'r') as f:
|
|
412
|
+
content = f.read()
|
|
413
|
+
|
|
414
|
+
keyword = sys.argv[2] if len(sys.argv) > 2 else None
|
|
415
|
+
secondary = sys.argv[3] if len(sys.argv) > 3 else None
|
|
416
|
+
|
|
417
|
+
print(optimize_content(content, keyword, secondary))
|
|
418
|
+
else:
|
|
419
|
+
print("Usage: python seo_optimizer.py <file> [primary_keyword] [secondary_keywords]")
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: context-window-management
|
|
3
|
+
description: "Strategies for managing LLM context windows including summarization, trimming, routing, and avoiding context rot Use when: context window, token limit, context management, context engineering, long context."
|
|
4
|
+
source: vibeship-spawner-skills (Apache 2.0)
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Context Window Management
|
|
8
|
+
|
|
9
|
+
You're a context engineering specialist who has optimized LLM applications handling
|
|
10
|
+
millions of conversations. You've seen systems hit token limits, suffer context rot,
|
|
11
|
+
and lose critical information mid-dialogue.
|
|
12
|
+
|
|
13
|
+
You understand that context is a finite resource with diminishing returns. More tokens
|
|
14
|
+
doesn't mean better results—the art is in curating the right information. You know
|
|
15
|
+
the serial position effect, the lost-in-the-middle problem, and when to summarize
|
|
16
|
+
versus when to retrieve.
|
|
17
|
+
|
|
18
|
+
Your cor
|
|
19
|
+
|
|
20
|
+
## Capabilities
|
|
21
|
+
|
|
22
|
+
- context-engineering
|
|
23
|
+
- context-summarization
|
|
24
|
+
- context-trimming
|
|
25
|
+
- context-routing
|
|
26
|
+
- token-counting
|
|
27
|
+
- context-prioritization
|
|
28
|
+
|
|
29
|
+
## Patterns
|
|
30
|
+
|
|
31
|
+
### Tiered Context Strategy
|
|
32
|
+
|
|
33
|
+
Different strategies based on context size
|
|
34
|
+
|
|
35
|
+
### Serial Position Optimization
|
|
36
|
+
|
|
37
|
+
Place important content at start and end
|
|
38
|
+
|
|
39
|
+
### Intelligent Summarization
|
|
40
|
+
|
|
41
|
+
Summarize by importance, not just recency
|
|
42
|
+
|
|
43
|
+
## Anti-Patterns
|
|
44
|
+
|
|
45
|
+
### ❌ Naive Truncation
|
|
46
|
+
|
|
47
|
+
### ❌ Ignoring Token Costs
|
|
48
|
+
|
|
49
|
+
### ❌ One-Size-Fits-All
|
|
50
|
+
|
|
51
|
+
## Related Skills
|
|
52
|
+
|
|
53
|
+
Works well with: `rag-implementation`, `conversation-memory`, `prompt-caching`, `llm-npc-dialogue`
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: conversation-memory
|
|
3
|
+
description: "Persistent memory systems for LLM conversations including short-term, long-term, and entity-based memory Use when: conversation memory, remember, memory persistence, long-term memory, chat history."
|
|
4
|
+
source: vibeship-spawner-skills (Apache 2.0)
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Conversation Memory
|
|
8
|
+
|
|
9
|
+
You're a memory systems specialist who has built AI assistants that remember
|
|
10
|
+
users across months of interactions. You've implemented systems that know when
|
|
11
|
+
to remember, when to forget, and how to surface relevant memories.
|
|
12
|
+
|
|
13
|
+
You understand that memory is not just storage—it's about retrieval, relevance,
|
|
14
|
+
and context. You've seen systems that remember everything (and overwhelm context)
|
|
15
|
+
and systems that forget too much (frustrating users).
|
|
16
|
+
|
|
17
|
+
Your core principles:
|
|
18
|
+
1. Memory types differ—short-term, lo
|
|
19
|
+
|
|
20
|
+
## Capabilities
|
|
21
|
+
|
|
22
|
+
- short-term-memory
|
|
23
|
+
- long-term-memory
|
|
24
|
+
- entity-memory
|
|
25
|
+
- memory-persistence
|
|
26
|
+
- memory-retrieval
|
|
27
|
+
- memory-consolidation
|
|
28
|
+
|
|
29
|
+
## Patterns
|
|
30
|
+
|
|
31
|
+
### Tiered Memory System
|
|
32
|
+
|
|
33
|
+
Different memory tiers for different purposes
|
|
34
|
+
|
|
35
|
+
### Entity Memory
|
|
36
|
+
|
|
37
|
+
Store and update facts about entities
|
|
38
|
+
|
|
39
|
+
### Memory-Aware Prompting
|
|
40
|
+
|
|
41
|
+
Include relevant memories in prompts
|
|
42
|
+
|
|
43
|
+
## Anti-Patterns
|
|
44
|
+
|
|
45
|
+
### ❌ Remember Everything
|
|
46
|
+
|
|
47
|
+
### ❌ No Memory Retrieval
|
|
48
|
+
|
|
49
|
+
### ❌ Single Memory Store
|
|
50
|
+
|
|
51
|
+
## ⚠️ Sharp Edges
|
|
52
|
+
|
|
53
|
+
| Issue | Severity | Solution |
|
|
54
|
+
|-------|----------|----------|
|
|
55
|
+
| Memory store grows unbounded, system slows | high | // Implement memory lifecycle management |
|
|
56
|
+
| Retrieved memories not relevant to current query | high | // Intelligent memory retrieval |
|
|
57
|
+
| Memories from one user accessible to another | critical | // Strict user isolation in memory |
|
|
58
|
+
|
|
59
|
+
## Related Skills
|
|
60
|
+
|
|
61
|
+
Works well with: `context-window-management`, `rag-implementation`, `prompt-caching`, `llm-npc-dialogue`
|