@rotifer/playground 0.5.0-alpha.2 → 0.7.0
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/CHANGELOG.md +159 -15
- package/LICENSE +1 -1
- package/README.md +51 -23
- package/README.zh.md +54 -25
- package/dist/cloud/auth.d.ts +7 -1
- package/dist/cloud/auth.d.ts.map +1 -1
- package/dist/cloud/auth.js +65 -1
- package/dist/cloud/auth.js.map +1 -1
- package/dist/cloud/client.d.ts +4 -1
- package/dist/cloud/client.d.ts.map +1 -1
- package/dist/cloud/client.js +9 -2
- package/dist/cloud/client.js.map +1 -1
- package/dist/cloud/types.d.ts +3 -1
- package/dist/cloud/types.d.ts.map +1 -1
- package/dist/cloud/types.js.map +1 -1
- package/dist/commands/agent-create.d.ts.map +1 -1
- package/dist/commands/agent-create.js +66 -3
- package/dist/commands/agent-create.js.map +1 -1
- package/dist/commands/agent-run.d.ts.map +1 -1
- package/dist/commands/agent-run.js +296 -32
- package/dist/commands/agent-run.js.map +1 -1
- package/dist/commands/arena-submit.d.ts.map +1 -1
- package/dist/commands/arena-submit.js +45 -17
- package/dist/commands/arena-submit.js.map +1 -1
- package/dist/commands/compile.d.ts.map +1 -1
- package/dist/commands/compile.js +9 -3
- package/dist/commands/compile.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +13 -3
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/login.d.ts.map +1 -1
- package/dist/commands/login.js +23 -16
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/network.js +4 -4
- package/dist/commands/network.js.map +1 -1
- package/dist/commands/publish.d.ts.map +1 -1
- package/dist/commands/publish.js +162 -44
- package/dist/commands/publish.js.map +1 -1
- package/dist/commands/test.d.ts.map +1 -1
- package/dist/commands/test.js +209 -23
- package/dist/commands/test.js.map +1 -1
- package/dist/commands/wrap.d.ts.map +1 -1
- package/dist/commands/wrap.js +17 -1
- package/dist/commands/wrap.js.map +1 -1
- package/dist/index.js +0 -0
- package/dist/runtime/network-gateway.d.ts +53 -0
- package/dist/runtime/network-gateway.d.ts.map +1 -0
- package/dist/runtime/network-gateway.js +147 -0
- package/dist/runtime/network-gateway.js.map +1 -0
- package/dist/utils/binding.d.ts +25 -0
- package/dist/utils/binding.d.ts.map +1 -1
- package/dist/utils/binding.js.map +1 -1
- package/dist/utils/open-browser.d.ts +10 -0
- package/dist/utils/open-browser.d.ts.map +1 -0
- package/dist/utils/open-browser.js +23 -0
- package/dist/utils/open-browser.js.map +1 -0
- package/genes/academic-writer/.cloud-manifest.json +6 -0
- package/genes/academic-writer/.gene-manifest.json +8 -0
- package/genes/academic-writer/SKILL.md +274 -0
- package/genes/academic-writer/phenotype.json +28 -0
- package/genes/ai-components/.cloud-manifest.json +6 -0
- package/genes/ai-components/.gene-manifest.json +8 -0
- package/genes/ai-components/SKILL.md +381 -0
- package/genes/ai-components/phenotype.json +28 -0
- package/genes/algorithmic-art/.cloud-manifest.json +6 -0
- package/genes/algorithmic-art/.gene-manifest.json +8 -0
- package/genes/algorithmic-art/SKILL.md +405 -0
- package/genes/algorithmic-art/phenotype.json +28 -0
- package/genes/answer-synthesizer/.cloud-manifest.json +6 -0
- package/genes/answer-synthesizer/index.ts +194 -0
- package/genes/answer-synthesizer/phenotype.json +61 -0
- package/genes/api-designer/.cloud-manifest.json +6 -0
- package/genes/api-designer/.gene-manifest.json +8 -0
- package/genes/api-designer/SKILL.md +456 -0
- package/genes/api-designer/phenotype.json +28 -0
- package/genes/auto-coder/.cloud-manifest.json +6 -0
- package/genes/auto-coder/.gene-manifest.json +8 -0
- package/genes/auto-coder/SKILL.md +400 -0
- package/genes/auto-coder/phenotype.json +28 -0
- package/genes/auto-writer/.cloud-manifest.json +6 -0
- package/genes/auto-writer/.gene-manifest.json +8 -0
- package/genes/auto-writer/SKILL.md +361 -0
- package/genes/auto-writer/phenotype.json +28 -0
- package/genes/brand-personality/.cloud-manifest.json +6 -0
- package/genes/brand-personality/.gene-manifest.json +8 -0
- package/genes/brand-personality/SKILL.md +549 -0
- package/genes/brand-personality/phenotype.json +28 -0
- package/genes/business-writer/.cloud-manifest.json +6 -0
- package/genes/business-writer/.gene-manifest.json +8 -0
- package/genes/business-writer/SKILL.md +448 -0
- package/genes/business-writer/phenotype.json +28 -0
- package/genes/citation-manager/.cloud-manifest.json +6 -0
- package/genes/citation-manager/.gene-manifest.json +8 -0
- package/genes/citation-manager/SKILL.md +279 -0
- package/genes/citation-manager/index.ts +162 -0
- package/genes/citation-manager/package.json +1 -0
- package/genes/citation-manager/phenotype.json +50 -0
- package/genes/code-complexity/.cloud-manifest.json +6 -0
- package/genes/code-complexity/README.md +35 -0
- package/genes/code-complexity/index.ts +101 -0
- package/genes/code-complexity/phenotype.json +34 -0
- package/genes/copywriter/.cloud-manifest.json +6 -0
- package/genes/copywriter/.gene-manifest.json +8 -0
- package/genes/copywriter/SKILL.md +329 -0
- package/genes/copywriter/phenotype.json +28 -0
- package/genes/creative-writer/.cloud-manifest.json +6 -0
- package/genes/creative-writer/.gene-manifest.json +8 -0
- package/genes/creative-writer/SKILL.md +356 -0
- package/genes/creative-writer/phenotype.json +28 -0
- package/genes/data-modeler/.cloud-manifest.json +6 -0
- package/genes/data-modeler/.gene-manifest.json +8 -0
- package/genes/data-modeler/SKILL.md +486 -0
- package/genes/data-modeler/phenotype.json +28 -0
- package/genes/debugger/.cloud-manifest.json +6 -0
- package/genes/debugger/.gene-manifest.json +8 -0
- package/genes/debugger/SKILL.md +416 -0
- package/genes/debugger/phenotype.json +28 -0
- package/genes/design-tokens/.cloud-manifest.json +6 -0
- package/genes/design-tokens/.gene-manifest.json +8 -0
- package/genes/design-tokens/SKILL.md +222 -0
- package/genes/design-tokens/index.ts +128 -0
- package/genes/design-tokens/package.json +1 -0
- package/genes/design-tokens/phenotype.json +1 -0
- package/genes/devops-automator/.cloud-manifest.json +6 -0
- package/genes/devops-automator/.gene-manifest.json +8 -0
- package/genes/devops-automator/SKILL.md +490 -0
- package/genes/devops-automator/phenotype.json +28 -0
- package/genes/doc-coauthoring/.cloud-manifest.json +6 -0
- package/genes/doc-coauthoring/.gene-manifest.json +8 -0
- package/genes/doc-coauthoring/SKILL.md +375 -0
- package/genes/doc-coauthoring/phenotype.json +28 -0
- package/genes/doc-retrieval/.cloud-manifest.json +6 -0
- package/genes/doc-retrieval/index.ts +134 -0
- package/genes/doc-retrieval/phenotype.json +54 -0
- package/genes/docs-writer/.cloud-manifest.json +6 -0
- package/genes/docs-writer/.gene-manifest.json +8 -0
- package/genes/docs-writer/SKILL.md +492 -0
- package/genes/docs-writer/phenotype.json +28 -0
- package/genes/evolve-life/.cloud-manifest.json +6 -0
- package/genes/evolve-life/.compile-result.json +12 -0
- package/genes/evolve-life/README.md +52 -0
- package/genes/evolve-life/gene.ir.wasm +0 -0
- package/genes/evolve-life/gene.wasm +0 -0
- package/genes/evolve-life/index.ts +255 -0
- package/genes/evolve-life/phenotype.json +129 -0
- package/genes/evolve-life-bitwise/.cloud-manifest.json +6 -0
- package/genes/evolve-life-bitwise/.compile-result.json +12 -0
- package/genes/evolve-life-bitwise/gene.ir.wasm +0 -0
- package/genes/evolve-life-bitwise/gene.wasm +0 -0
- package/genes/evolve-life-bitwise/index.ts +273 -0
- package/genes/evolve-life-bitwise/phenotype.json +129 -0
- package/genes/evolve-life-sparse/.cloud-manifest.json +6 -0
- package/genes/evolve-life-sparse/.compile-result.json +12 -0
- package/genes/evolve-life-sparse/gene.ir.wasm +0 -0
- package/genes/evolve-life-sparse/gene.wasm +0 -0
- package/genes/evolve-life-sparse/index.ts +236 -0
- package/genes/evolve-life-sparse/phenotype.json +129 -0
- package/genes/fact-checker/.cloud-manifest.json +6 -0
- package/genes/fact-checker/.gene-manifest.json +8 -0
- package/genes/fact-checker/SKILL.md +373 -0
- package/genes/fact-checker/phenotype.json +28 -0
- package/genes/genesis-code-format/.cloud-manifest.json +6 -0
- package/genes/genesis-code-format/package.json +1 -0
- package/genes/genesis-code-format/phenotype.json +1 -0
- package/genes/genesis-file-read/.cloud-manifest.json +6 -0
- package/genes/genesis-file-read/index.ts +11 -1
- package/genes/genesis-file-read/package.json +1 -0
- package/genes/genesis-file-read/phenotype.json +1 -0
- package/genes/genesis-l0-constraint/.cloud-manifest.json +6 -0
- package/genes/genesis-l0-constraint/package.json +1 -0
- package/genes/genesis-l0-constraint/phenotype.json +1 -0
- package/genes/genesis-web-search/.cloud-manifest.json +2 -2
- package/genes/genesis-web-search/package.json +1 -0
- package/genes/genesis-web-search/phenotype.json +1 -0
- package/genes/genesis-web-search-lite/.cloud-manifest.json +6 -0
- package/genes/genesis-web-search-lite/package.json +1 -0
- package/genes/genesis-web-search-lite/phenotype.json +1 -0
- package/genes/git-workflow/.cloud-manifest.json +6 -0
- package/genes/git-workflow/.gene-manifest.json +8 -0
- package/genes/git-workflow/SKILL.md +407 -0
- package/genes/git-workflow/phenotype.json +28 -0
- package/genes/grammar-checker/.cloud-manifest.json +6 -0
- package/genes/grammar-checker/.gene-manifest.json +8 -0
- package/genes/grammar-checker/SKILL.md +194 -0
- package/genes/grammar-checker/index.ts +168 -0
- package/genes/grammar-checker/package.json +1 -0
- package/genes/grammar-checker/phenotype.json +52 -0
- package/genes/json-validator/.cloud-manifest.json +6 -0
- package/genes/json-validator/README.md +42 -0
- package/genes/json-validator/index.ts +112 -0
- package/genes/json-validator/phenotype.json +42 -0
- package/genes/license-advisor/.cloud-manifest.json +6 -0
- package/genes/license-advisor/.gene-manifest.json +8 -0
- package/genes/license-advisor/SKILL.md +117 -0
- package/genes/license-advisor/phenotype.json +28 -0
- package/genes/logic-architect/.cloud-manifest.json +6 -0
- package/genes/logic-architect/.gene-manifest.json +8 -0
- package/genes/logic-architect/SKILL.md +451 -0
- package/genes/logic-architect/phenotype.json +28 -0
- package/genes/markdown-formatter/.cloud-manifest.json +6 -0
- package/genes/markdown-formatter/README.md +34 -0
- package/genes/markdown-formatter/index.ts +86 -0
- package/genes/markdown-formatter/phenotype.json +32 -0
- package/genes/orch/.cloud-manifest.json +6 -0
- package/genes/orch/.gene-manifest.json +8 -0
- package/genes/orch/SKILL.md +504 -0
- package/genes/orch/phenotype.json +28 -0
- package/genes/particle-barneshut/.cloud-manifest.json +6 -0
- package/genes/particle-barneshut/.compile-result.json +12 -0
- package/genes/particle-barneshut/README.md +55 -0
- package/genes/particle-barneshut/gene.ir.wasm +0 -0
- package/genes/particle-barneshut/gene.wasm +0 -0
- package/genes/particle-barneshut/index.ts +486 -0
- package/genes/particle-barneshut/phenotype.json +137 -0
- package/genes/particle-brute/.cloud-manifest.json +6 -0
- package/genes/particle-brute/.compile-result.json +12 -0
- package/genes/particle-brute/README.md +55 -0
- package/genes/particle-brute/gene.ir.wasm +0 -0
- package/genes/particle-brute/gene.wasm +0 -0
- package/genes/particle-brute/index.ts +277 -0
- package/genes/particle-brute/phenotype.json +137 -0
- package/genes/particle-spatial/.cloud-manifest.json +6 -0
- package/genes/particle-spatial/.compile-result.json +12 -0
- package/genes/particle-spatial/README.md +53 -0
- package/genes/particle-spatial/gene.ir.wasm +0 -0
- package/genes/particle-spatial/gene.wasm +0 -0
- package/genes/particle-spatial/index.ts +352 -0
- package/genes/particle-spatial/phenotype.json +137 -0
- package/genes/performance-optimizer/.cloud-manifest.json +6 -0
- package/genes/performance-optimizer/.gene-manifest.json +8 -0
- package/genes/performance-optimizer/SKILL.md +480 -0
- package/genes/performance-optimizer/phenotype.json +28 -0
- package/genes/plagiarism-checker/.cloud-manifest.json +6 -0
- package/genes/plagiarism-checker/.gene-manifest.json +8 -0
- package/genes/plagiarism-checker/SKILL.md +342 -0
- package/genes/plagiarism-checker/phenotype.json +28 -0
- package/genes/product-manager/.cloud-manifest.json +6 -0
- package/genes/product-manager/.gene-manifest.json +8 -0
- package/genes/product-manager/SKILL.md +249 -0
- package/genes/product-manager/phenotype.json +28 -0
- package/genes/project-reviewer/.cloud-manifest.json +6 -0
- package/genes/project-reviewer/.gene-manifest.json +8 -0
- package/genes/project-reviewer/SKILL.md +312 -0
- package/genes/project-reviewer/phenotype.json +28 -0
- package/genes/prompt-engineer/.cloud-manifest.json +6 -0
- package/genes/prompt-engineer/.gene-manifest.json +8 -0
- package/genes/prompt-engineer/SKILL.md +411 -0
- package/genes/prompt-engineer/phenotype.json +28 -0
- package/genes/readability-analyzer/.cloud-manifest.json +6 -0
- package/genes/readability-analyzer/.gene-manifest.json +8 -0
- package/genes/readability-analyzer/SKILL.md +357 -0
- package/genes/readability-analyzer/index.ts +123 -0
- package/genes/readability-analyzer/package.json +1 -0
- package/genes/readability-analyzer/phenotype.json +35 -0
- package/genes/rotifer-protocol/SKILL.md +121 -0
- package/genes/security-auditor/.cloud-manifest.json +6 -0
- package/genes/security-auditor/.gene-manifest.json +8 -0
- package/genes/security-auditor/SKILL.md +494 -0
- package/genes/security-auditor/phenotype.json +28 -0
- package/genes/seo-optimizer/.cloud-manifest.json +6 -0
- package/genes/seo-optimizer/.gene-manifest.json +8 -0
- package/genes/seo-optimizer/SKILL.md +327 -0
- package/genes/seo-optimizer/index.ts +206 -0
- package/genes/seo-optimizer/package.json +1 -0
- package/genes/seo-optimizer/phenotype.json +1 -0
- package/genes/source-linker/.cloud-manifest.json +6 -0
- package/genes/source-linker/index.ts +88 -0
- package/genes/source-linker/phenotype.json +45 -0
- package/genes/style-optimizer/.cloud-manifest.json +6 -0
- package/genes/style-optimizer/.gene-manifest.json +8 -0
- package/genes/style-optimizer/SKILL.md +285 -0
- package/genes/style-optimizer/phenotype.json +28 -0
- package/genes/tech-lead/.cloud-manifest.json +6 -0
- package/genes/tech-lead/.gene-manifest.json +8 -0
- package/genes/tech-lead/SKILL.md +451 -0
- package/genes/tech-lead/phenotype.json +28 -0
- package/genes/test-wrap/.cloud-manifest.json +6 -0
- package/genes/test-wrap/.gene-manifest.json +8 -0
- package/genes/test-wrap/phenotype.json +28 -0
- package/genes/testing-strategist/.cloud-manifest.json +6 -0
- package/genes/testing-strategist/.gene-manifest.json +8 -0
- package/genes/testing-strategist/SKILL.md +500 -0
- package/genes/testing-strategist/phenotype.json +28 -0
- package/genes/text-summarizer/.cloud-manifest.json +6 -0
- package/genes/text-summarizer/README.md +34 -0
- package/genes/text-summarizer/index.ts +122 -0
- package/genes/text-summarizer/phenotype.json +32 -0
- package/genes/tone-analyzer/.cloud-manifest.json +6 -0
- package/genes/tone-analyzer/.gene-manifest.json +8 -0
- package/genes/tone-analyzer/SKILL.md +410 -0
- package/genes/tone-analyzer/phenotype.json +28 -0
- package/genes/translator/.cloud-manifest.json +6 -0
- package/genes/translator/.gene-manifest.json +8 -0
- package/genes/translator/SKILL.md +355 -0
- package/genes/translator/phenotype.json +28 -0
- package/genes/ui-components/.cloud-manifest.json +6 -0
- package/genes/ui-components/.gene-manifest.json +8 -0
- package/genes/ui-components/SKILL.md +467 -0
- package/genes/ui-components/phenotype.json +28 -0
- package/genes/uiux-designer/.cloud-manifest.json +6 -0
- package/genes/uiux-designer/.gene-manifest.json +8 -0
- package/genes/uiux-designer/SKILL.md +353 -0
- package/genes/uiux-designer/phenotype.json +28 -0
- package/genes/url-extractor/.cloud-manifest.json +6 -0
- package/genes/url-extractor/README.md +37 -0
- package/genes/url-extractor/index.ts +86 -0
- package/genes/url-extractor/phenotype.json +48 -0
- package/genes/ux-patterns/.cloud-manifest.json +6 -0
- package/genes/ux-patterns/.gene-manifest.json +8 -0
- package/genes/ux-patterns/SKILL.md +872 -0
- package/genes/ux-patterns/phenotype.json +28 -0
- package/genes/web3-components/.cloud-manifest.json +6 -0
- package/genes/web3-components/.gene-manifest.json +8 -0
- package/genes/web3-components/SKILL.md +390 -0
- package/genes/web3-components/phenotype.json +28 -0
- package/package.json +6 -5
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: seo-optimizer
|
|
3
|
+
description: Optimize content for search engines. Improve keyword usage, meta descriptions, headings, and content structure for better ranking. Use when creating web content, blog posts, or any content intended for search discovery.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# SEO Optimizer
|
|
7
|
+
|
|
8
|
+
**Goal**: Optimize content for search engine visibility and ranking.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## 1. Keyword Optimization
|
|
13
|
+
|
|
14
|
+
### Keyword Placement
|
|
15
|
+
|
|
16
|
+
```markdown
|
|
17
|
+
## Required Positions
|
|
18
|
+
|
|
19
|
+
1. Title tag - near the beginning
|
|
20
|
+
2. H1 heading - include primary keyword
|
|
21
|
+
3. First paragraph - within the first 100 words
|
|
22
|
+
4. Subheadings (H2/H3) - include related keywords
|
|
23
|
+
5. Conclusion - natural summary
|
|
24
|
+
|
|
25
|
+
## Keyword Density
|
|
26
|
+
|
|
27
|
+
- Primary keyword: 1-2%
|
|
28
|
+
- Related keywords: naturally distributed
|
|
29
|
+
- Avoid keyword stuffing
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Keyword Types
|
|
33
|
+
|
|
34
|
+
| Type | Example | Purpose |
|
|
35
|
+
|------|---------|---------|
|
|
36
|
+
| Short-tail | SEO | Brand awareness |
|
|
37
|
+
| Long-tail | how to optimize SEO | Targeted traffic |
|
|
38
|
+
| Question | what is SEO | FAQ content |
|
|
39
|
+
| Brand | company + product | Brand search |
|
|
40
|
+
|
|
41
|
+
### Keyword Research
|
|
42
|
+
|
|
43
|
+
```markdown
|
|
44
|
+
## Tools
|
|
45
|
+
|
|
46
|
+
- Google Keyword Planner
|
|
47
|
+
- Ahrefs
|
|
48
|
+
- SEMrush
|
|
49
|
+
- Google Trends
|
|
50
|
+
- Answer the Public
|
|
51
|
+
|
|
52
|
+
## Selection Criteria
|
|
53
|
+
|
|
54
|
+
1. Search volume: monthly search volume
|
|
55
|
+
2. Competition: optimization difficulty
|
|
56
|
+
3. Relevance: match with content
|
|
57
|
+
4. Commercial value: conversion potential
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## 2. Title Optimization
|
|
63
|
+
|
|
64
|
+
### Title Tag
|
|
65
|
+
|
|
66
|
+
```markdown
|
|
67
|
+
## Rules
|
|
68
|
+
|
|
69
|
+
- Length: 50-60 characters
|
|
70
|
+
- Include primary keyword
|
|
71
|
+
- Brand name at the end
|
|
72
|
+
- Compelling for clicks
|
|
73
|
+
|
|
74
|
+
## Formula
|
|
75
|
+
|
|
76
|
+
[Primary Keyword] - [Secondary Keyword/Value Prop] | [Brand]
|
|
77
|
+
|
|
78
|
+
## Examples
|
|
79
|
+
|
|
80
|
+
Good: Best Laptops 2025 - Top 10 Picks for Every Budget | TechReview
|
|
81
|
+
Bad: Home Page | Company Name
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### H1-H6 Structure
|
|
85
|
+
|
|
86
|
+
```markdown
|
|
87
|
+
## Hierarchy Rules
|
|
88
|
+
|
|
89
|
+
H1: Main page title (only 1 per page)
|
|
90
|
+
H2: Major sections
|
|
91
|
+
H3: Subsections
|
|
92
|
+
H4-H6: Further subdivisions
|
|
93
|
+
|
|
94
|
+
## Example
|
|
95
|
+
|
|
96
|
+
<h1>How to Learn Python Programming</h1>
|
|
97
|
+
<h2>Introduction to Python</h2>
|
|
98
|
+
<h2>Learning Path</h2>
|
|
99
|
+
<h3>Beginner Stage</h3>
|
|
100
|
+
<h3>Advanced Stage</h3>
|
|
101
|
+
<h2>Recommended Resources</h2>
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## 3. Meta Description
|
|
107
|
+
|
|
108
|
+
### Rules
|
|
109
|
+
|
|
110
|
+
```markdown
|
|
111
|
+
## Length
|
|
112
|
+
- Optimal: 150-160 characters
|
|
113
|
+
- Mobile: 120 characters
|
|
114
|
+
|
|
115
|
+
## Content Elements
|
|
116
|
+
1. Include primary keyword
|
|
117
|
+
2. Explain page value
|
|
118
|
+
3. Include call to action
|
|
119
|
+
4. Unique and compelling
|
|
120
|
+
|
|
121
|
+
## Template
|
|
122
|
+
|
|
123
|
+
[Problem/Pain point]? [Solution]. [Value statement]. [CTA]
|
|
124
|
+
|
|
125
|
+
## Example
|
|
126
|
+
|
|
127
|
+
Want to boost your website traffic? This article shares 10 practical SEO tips
|
|
128
|
+
to help you increase organic search traffic by 50% in 3 months. Read now!
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## 4. Content Optimization
|
|
134
|
+
|
|
135
|
+
### Content Structure
|
|
136
|
+
|
|
137
|
+
```markdown
|
|
138
|
+
## Ideal Structure
|
|
139
|
+
|
|
140
|
+
1. Introduction (include keyword)
|
|
141
|
+
2. Table of contents (anchor links)
|
|
142
|
+
3. Body (organized with subheadings)
|
|
143
|
+
4. Conclusion (keyword naturally included)
|
|
144
|
+
5. CTA (related links/actions)
|
|
145
|
+
|
|
146
|
+
## Content Length Guidelines
|
|
147
|
+
|
|
148
|
+
| Type | Recommended Words |
|
|
149
|
+
|------|-------------------|
|
|
150
|
+
| News | 300-500 |
|
|
151
|
+
| Blog post | 1000-2000 |
|
|
152
|
+
| In-depth article | 2000-4000 |
|
|
153
|
+
| Comprehensive guide | 4000+ |
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Readability for SEO
|
|
157
|
+
|
|
158
|
+
```markdown
|
|
159
|
+
## Recommendations
|
|
160
|
+
|
|
161
|
+
- Paragraphs: 3-5 sentences
|
|
162
|
+
- Sentences: 15-25 words
|
|
163
|
+
- Use bullet lists
|
|
164
|
+
- Add subheadings
|
|
165
|
+
- Adequate whitespace
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Multimedia Optimization
|
|
169
|
+
|
|
170
|
+
```markdown
|
|
171
|
+
## Image Optimization
|
|
172
|
+
|
|
173
|
+
1. File names: include keywords
|
|
174
|
+
Good: seo-optimization-tips.jpg
|
|
175
|
+
Bad: IMG_001.jpg
|
|
176
|
+
|
|
177
|
+
2. Alt text: describe image + keyword
|
|
178
|
+
Good: alt="SEO optimization tips infographic"
|
|
179
|
+
|
|
180
|
+
3. Compress images: reduce load time
|
|
181
|
+
|
|
182
|
+
4. Use WebP format
|
|
183
|
+
|
|
184
|
+
## Video Optimization
|
|
185
|
+
|
|
186
|
+
- Add captions/transcripts
|
|
187
|
+
- Optimize title and description
|
|
188
|
+
- Add timestamps
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## 5. Link Strategy
|
|
194
|
+
|
|
195
|
+
### Internal Links
|
|
196
|
+
|
|
197
|
+
```markdown
|
|
198
|
+
## Rules
|
|
199
|
+
|
|
200
|
+
1. Link related pages to each other
|
|
201
|
+
2. Anchor text includes keywords
|
|
202
|
+
3. Links are natural and valuable
|
|
203
|
+
4. Important pages receive more links
|
|
204
|
+
|
|
205
|
+
## Anchor Text Types
|
|
206
|
+
|
|
207
|
+
Good: Learn more about [SEO optimization tips]
|
|
208
|
+
Good: Check out our [SEO beginner's guide]
|
|
209
|
+
Bad: [Click here]
|
|
210
|
+
Bad: Excessive exact-match anchors
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### External Links
|
|
214
|
+
|
|
215
|
+
```markdown
|
|
216
|
+
## Principles
|
|
217
|
+
|
|
218
|
+
1. Link to authoritative websites
|
|
219
|
+
2. Add nofollow for ads/untrusted links
|
|
220
|
+
3. Open external links in new window
|
|
221
|
+
4. Regularly check for broken links
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## 6. Technical SEO
|
|
227
|
+
|
|
228
|
+
### URL Optimization
|
|
229
|
+
|
|
230
|
+
```markdown
|
|
231
|
+
## Rules
|
|
232
|
+
|
|
233
|
+
1. Include keywords
|
|
234
|
+
2. Keep short and clear
|
|
235
|
+
3. Use hyphens (-)
|
|
236
|
+
4. Avoid special characters
|
|
237
|
+
5. Use lowercase letters
|
|
238
|
+
|
|
239
|
+
## Examples
|
|
240
|
+
|
|
241
|
+
Good: /seo-optimization-guide
|
|
242
|
+
Bad: /page?id=12345&category=seo
|
|
243
|
+
Bad: /SEO_Optimization_Guide
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### Page Speed
|
|
247
|
+
|
|
248
|
+
```markdown
|
|
249
|
+
## Core Web Vitals
|
|
250
|
+
|
|
251
|
+
| Metric | Target | Description |
|
|
252
|
+
|--------|--------|-------------|
|
|
253
|
+
| LCP | <2.5s | Largest Contentful Paint |
|
|
254
|
+
| FID | <100ms | First Input Delay |
|
|
255
|
+
| CLS | <0.1 | Cumulative Layout Shift |
|
|
256
|
+
|
|
257
|
+
## Optimization Methods
|
|
258
|
+
|
|
259
|
+
1. Compress images
|
|
260
|
+
2. Enable caching
|
|
261
|
+
3. Reduce JavaScript
|
|
262
|
+
4. Use CDN
|
|
263
|
+
5. Optimize server response
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
## 7. Checklist
|
|
269
|
+
|
|
270
|
+
```markdown
|
|
271
|
+
## SEO Optimization Checklist
|
|
272
|
+
|
|
273
|
+
### Keywords
|
|
274
|
+
- [ ] Primary keyword identified
|
|
275
|
+
- [ ] Keyword appears in title
|
|
276
|
+
- [ ] Keyword appears in first paragraph
|
|
277
|
+
- [ ] Keyword density is moderate (1-3%)
|
|
278
|
+
|
|
279
|
+
### Meta Information
|
|
280
|
+
- [ ] Title tag optimized
|
|
281
|
+
- [ ] Meta description optimized
|
|
282
|
+
- [ ] H1-H6 hierarchy is correct
|
|
283
|
+
|
|
284
|
+
### Content
|
|
285
|
+
- [ ] Sufficient content length
|
|
286
|
+
- [ ] Clear structure
|
|
287
|
+
- [ ] Multimedia included
|
|
288
|
+
- [ ] Good readability
|
|
289
|
+
|
|
290
|
+
### Links
|
|
291
|
+
- [ ] Appropriate internal links
|
|
292
|
+
- [ ] Authoritative external links
|
|
293
|
+
- [ ] No broken links
|
|
294
|
+
|
|
295
|
+
### Technical
|
|
296
|
+
- [ ] URL optimized
|
|
297
|
+
- [ ] Images optimized
|
|
298
|
+
- [ ] Mobile-friendly
|
|
299
|
+
- [ ] Page speed meets targets
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
304
|
+
## Quick Reference
|
|
305
|
+
|
|
306
|
+
### SEO Writing Formulas
|
|
307
|
+
|
|
308
|
+
```markdown
|
|
309
|
+
1. Keyword + Number + Power word = Great title
|
|
310
|
+
Example: 7 SEO Tips to Double Your Traffic
|
|
311
|
+
|
|
312
|
+
2. Problem + Solution + Value = Great description
|
|
313
|
+
Example: Struggling with SEO? 10 practical tips to boost your rankings
|
|
314
|
+
|
|
315
|
+
3. Inverted pyramid = Great content
|
|
316
|
+
Conclusion → Arguments → Evidence
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
### Common Mistakes
|
|
320
|
+
|
|
321
|
+
| Mistake | Impact | Fix |
|
|
322
|
+
|---------|--------|-----|
|
|
323
|
+
| Keyword stuffing | Penalty | Use naturally |
|
|
324
|
+
| Thin content | Low ranking | Expand content |
|
|
325
|
+
| Missing H1 | Poor structure | Add H1 |
|
|
326
|
+
| No image alt | Poor accessibility | Add alt text |
|
|
327
|
+
| Broken links | Bad UX | Regular audits |
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
interface SEOInput {
|
|
2
|
+
content: string;
|
|
3
|
+
targetKeyword?: string;
|
|
4
|
+
url?: string;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
interface SEOIssue {
|
|
8
|
+
severity: "error" | "warning" | "info";
|
|
9
|
+
rule: string;
|
|
10
|
+
message: string;
|
|
11
|
+
suggestion: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
interface SEOOutput {
|
|
15
|
+
score: number;
|
|
16
|
+
issues: SEOIssue[];
|
|
17
|
+
keywordDensity: number;
|
|
18
|
+
wordCount: number;
|
|
19
|
+
headingStructure: {
|
|
20
|
+
h1Count: number;
|
|
21
|
+
h2Count: number;
|
|
22
|
+
h3Count: number;
|
|
23
|
+
hasProperHierarchy: boolean;
|
|
24
|
+
};
|
|
25
|
+
metaAnalysis: {
|
|
26
|
+
titleLength: number;
|
|
27
|
+
hasMetaDescription: boolean;
|
|
28
|
+
descriptionLength: number;
|
|
29
|
+
};
|
|
30
|
+
readabilityScore: number;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function countOccurrences(text: string, keyword: string): number {
|
|
34
|
+
if (!keyword) return 0;
|
|
35
|
+
const lower = text.toLowerCase();
|
|
36
|
+
const kw = keyword.toLowerCase();
|
|
37
|
+
let count = 0;
|
|
38
|
+
let pos = 0;
|
|
39
|
+
while ((pos = lower.indexOf(kw, pos)) !== -1) {
|
|
40
|
+
count++;
|
|
41
|
+
pos += kw.length;
|
|
42
|
+
}
|
|
43
|
+
return count;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function extractHeadings(content: string): { h1: string[]; h2: string[]; h3: string[] } {
|
|
47
|
+
const h1 = [...content.matchAll(/<h1[^>]*>(.*?)<\/h1>/gi)].map((m) => m[1]);
|
|
48
|
+
const h2 = [...content.matchAll(/<h2[^>]*>(.*?)<\/h2>/gi)].map((m) => m[1]);
|
|
49
|
+
const h3 = [...content.matchAll(/<h3[^>]*>(.*?)<\/h3>/gi)].map((m) => m[1]);
|
|
50
|
+
|
|
51
|
+
const mdH1 = [...content.matchAll(/^#\s+(.+)$/gm)].map((m) => m[1]);
|
|
52
|
+
const mdH2 = [...content.matchAll(/^##\s+(.+)$/gm)].map((m) => m[1]);
|
|
53
|
+
const mdH3 = [...content.matchAll(/^###\s+(.+)$/gm)].map((m) => m[1]);
|
|
54
|
+
|
|
55
|
+
return {
|
|
56
|
+
h1: [...h1, ...mdH1],
|
|
57
|
+
h2: [...h2, ...mdH2],
|
|
58
|
+
h3: [...h3, ...mdH3],
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function stripHTML(html: string): string {
|
|
63
|
+
return html.replace(/<[^>]*>/g, " ").replace(/\s+/g, " ").trim();
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function extractMeta(content: string): { title: string; description: string } {
|
|
67
|
+
const titleMatch = content.match(/<title[^>]*>(.*?)<\/title>/i);
|
|
68
|
+
const descMatch = content.match(/<meta\s+name=["']description["']\s+content=["'](.*?)["']/i);
|
|
69
|
+
return {
|
|
70
|
+
title: titleMatch ? titleMatch[1] : "",
|
|
71
|
+
description: descMatch ? descMatch[1] : "",
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function fleschKincaid(text: string): number {
|
|
76
|
+
const words = text.split(/\s+/).filter((w) => w.length > 0);
|
|
77
|
+
const sentences = text.split(/[.!?]+/).filter((s) => s.trim().length > 0);
|
|
78
|
+
if (words.length === 0 || sentences.length === 0) return 0;
|
|
79
|
+
|
|
80
|
+
let totalSyllables = 0;
|
|
81
|
+
for (const word of words) {
|
|
82
|
+
const clean = word.toLowerCase().replace(/[^a-z]/g, "");
|
|
83
|
+
const vowelGroups = clean.match(/[aeiouy]+/g);
|
|
84
|
+
totalSyllables += vowelGroups ? Math.max(vowelGroups.length, 1) : 1;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return Math.max(
|
|
88
|
+
0,
|
|
89
|
+
Math.min(100, 206.835 - 1.015 * (words.length / sentences.length) - 84.6 * (totalSyllables / words.length))
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* SEO Optimizer Gene
|
|
95
|
+
*
|
|
96
|
+
* Analyzes content for search engine optimization metrics.
|
|
97
|
+
* Checks keyword density, heading structure, meta tags, and readability.
|
|
98
|
+
*/
|
|
99
|
+
export async function express(input: SEOInput): Promise<SEOOutput> {
|
|
100
|
+
const content = (input.content || "").trim();
|
|
101
|
+
const keyword = (input.targetKeyword || "").trim();
|
|
102
|
+
const issues: SEOIssue[] = [];
|
|
103
|
+
|
|
104
|
+
if (!content) {
|
|
105
|
+
return {
|
|
106
|
+
score: 0,
|
|
107
|
+
issues: [{ severity: "error", rule: "no-content", message: "No content provided", suggestion: "Provide text or HTML content to analyze" }],
|
|
108
|
+
keywordDensity: 0,
|
|
109
|
+
wordCount: 0,
|
|
110
|
+
headingStructure: { h1Count: 0, h2Count: 0, h3Count: 0, hasProperHierarchy: false },
|
|
111
|
+
metaAnalysis: { titleLength: 0, hasMetaDescription: false, descriptionLength: 0 },
|
|
112
|
+
readabilityScore: 0,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const plainText = stripHTML(content);
|
|
117
|
+
const words = plainText.split(/\s+/).filter((w) => w.length > 0);
|
|
118
|
+
const wordCount = words.length;
|
|
119
|
+
|
|
120
|
+
// Word count analysis
|
|
121
|
+
if (wordCount < 300) {
|
|
122
|
+
issues.push({ severity: "warning", rule: "thin-content", message: `Content has only ${wordCount} words`, suggestion: "Aim for at least 300 words for better SEO" });
|
|
123
|
+
} else if (wordCount >= 1000) {
|
|
124
|
+
issues.push({ severity: "info", rule: "long-content", message: `Good content length: ${wordCount} words`, suggestion: "Long-form content tends to rank better" });
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Keyword analysis
|
|
128
|
+
let keywordDensity = 0;
|
|
129
|
+
if (keyword) {
|
|
130
|
+
const kwCount = countOccurrences(plainText, keyword);
|
|
131
|
+
keywordDensity = wordCount > 0 ? (kwCount / wordCount) * 100 : 0;
|
|
132
|
+
|
|
133
|
+
if (kwCount === 0) {
|
|
134
|
+
issues.push({ severity: "error", rule: "keyword-missing", message: `Target keyword "${keyword}" not found in content`, suggestion: "Include the target keyword naturally in your content" });
|
|
135
|
+
} else if (keywordDensity > 3) {
|
|
136
|
+
issues.push({ severity: "warning", rule: "keyword-stuffing", message: `Keyword density is ${keywordDensity.toFixed(1)}% (too high)`, suggestion: "Keep keyword density between 1-3% to avoid over-optimization" });
|
|
137
|
+
} else if (keywordDensity < 0.5) {
|
|
138
|
+
issues.push({ severity: "warning", rule: "keyword-low", message: `Keyword density is ${keywordDensity.toFixed(1)}% (too low)`, suggestion: "Include the keyword a few more times naturally" });
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Heading structure
|
|
143
|
+
const headings = extractHeadings(content);
|
|
144
|
+
const h1Count = headings.h1.length;
|
|
145
|
+
const h2Count = headings.h2.length;
|
|
146
|
+
const h3Count = headings.h3.length;
|
|
147
|
+
|
|
148
|
+
if (h1Count === 0) {
|
|
149
|
+
issues.push({ severity: "error", rule: "missing-h1", message: "No H1 heading found", suggestion: "Add exactly one H1 heading as the main title" });
|
|
150
|
+
} else if (h1Count > 1) {
|
|
151
|
+
issues.push({ severity: "warning", rule: "multiple-h1", message: `Found ${h1Count} H1 headings`, suggestion: "Use only one H1 heading per page" });
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (h2Count === 0 && wordCount > 300) {
|
|
155
|
+
issues.push({ severity: "warning", rule: "missing-h2", message: "No H2 headings found", suggestion: "Break content into sections with H2 headings" });
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const hasProperHierarchy = h1Count === 1 && (h2Count > 0 || wordCount < 300);
|
|
159
|
+
|
|
160
|
+
if (keyword && h1Count > 0) {
|
|
161
|
+
const h1HasKeyword = headings.h1.some((h) => h.toLowerCase().includes(keyword.toLowerCase()));
|
|
162
|
+
if (!h1HasKeyword) {
|
|
163
|
+
issues.push({ severity: "warning", rule: "keyword-not-in-h1", message: "Target keyword not found in H1", suggestion: "Include the target keyword in your main heading" });
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Meta analysis
|
|
168
|
+
const meta = extractMeta(content);
|
|
169
|
+
const titleLength = meta.title.length;
|
|
170
|
+
const hasMetaDescription = meta.description.length > 0;
|
|
171
|
+
const descriptionLength = meta.description.length;
|
|
172
|
+
|
|
173
|
+
if (titleLength > 0 && titleLength < 30) {
|
|
174
|
+
issues.push({ severity: "warning", rule: "title-short", message: `Title is too short (${titleLength} chars)`, suggestion: "Aim for 50-60 characters in the title" });
|
|
175
|
+
} else if (titleLength > 60) {
|
|
176
|
+
issues.push({ severity: "warning", rule: "title-long", message: `Title is too long (${titleLength} chars)`, suggestion: "Keep title under 60 characters to prevent truncation in search results" });
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if (hasMetaDescription && descriptionLength < 120) {
|
|
180
|
+
issues.push({ severity: "warning", rule: "description-short", message: `Meta description is short (${descriptionLength} chars)`, suggestion: "Aim for 150-160 characters" });
|
|
181
|
+
} else if (hasMetaDescription && descriptionLength > 160) {
|
|
182
|
+
issues.push({ severity: "warning", rule: "description-long", message: `Meta description is long (${descriptionLength} chars)`, suggestion: "Keep meta description under 160 characters" });
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Readability
|
|
186
|
+
const readabilityScore = Math.round(fleschKincaid(plainText) * 100) / 100;
|
|
187
|
+
|
|
188
|
+
if (readabilityScore < 30) {
|
|
189
|
+
issues.push({ severity: "warning", rule: "readability-low", message: `Readability score is low (${readabilityScore})`, suggestion: "Simplify sentences and use common words for better accessibility" });
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Score calculation
|
|
193
|
+
const errorCount = issues.filter((i) => i.severity === "error").length;
|
|
194
|
+
const warningCount = issues.filter((i) => i.severity === "warning").length;
|
|
195
|
+
const score = Math.max(0, Math.min(100, 100 - errorCount * 15 - warningCount * 5));
|
|
196
|
+
|
|
197
|
+
return {
|
|
198
|
+
score,
|
|
199
|
+
issues,
|
|
200
|
+
keywordDensity: Math.round(keywordDensity * 100) / 100,
|
|
201
|
+
wordCount,
|
|
202
|
+
headingStructure: { h1Count, h2Count, h3Count, hasProperHierarchy },
|
|
203
|
+
metaAnalysis: { titleLength, hasMetaDescription, descriptionLength },
|
|
204
|
+
readabilityScore,
|
|
205
|
+
};
|
|
206
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type":"module"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"domain":"content.seo","description":"Optimize content for search engines. Improve keyword usage, meta descriptions, headings, and content structure for better ranking. Use when creating web content, blog posts, or any content intended for search discovery.","inputSchema":{"type":"object","properties":{"content":{"type":"string","description":"Plain text or HTML content to analyze"},"targetKeyword":{"type":"string","description":"Target keyword for density and placement checks"},"url":{"type":"string","description":"Optional URL for context"}},"required":["content"]},"outputSchema":{"type":"object","properties":{"score":{"type":"number","description":"SEO score 0-100"},"issues":{"type":"array","items":{"type":"object","properties":{"severity":{"type":"string","enum":["error","warning","info"]},"rule":{"type":"string"},"message":{"type":"string"},"suggestion":{"type":"string"}},"required":["severity","rule","message","suggestion"]}},"keywordDensity":{"type":"number","description":"Keyword density percentage"},"wordCount":{"type":"number","description":"Total word count"},"headingStructure":{"type":"object","properties":{"h1Count":{"type":"number"},"h2Count":{"type":"number"},"h3Count":{"type":"number"},"hasProperHierarchy":{"type":"boolean"}},"required":["h1Count","h2Count","h3Count","hasProperHierarchy"]},"metaAnalysis":{"type":"object","properties":{"titleLength":{"type":"number"},"hasMetaDescription":{"type":"boolean"},"descriptionLength":{"type":"number"}},"required":["titleLength","hasMetaDescription","descriptionLength"]},"readabilityScore":{"type":"number","description":"Flesch-Kincaid reading ease 0-100"}},"required":["score","issues","keywordDensity","wordCount","headingStructure","metaAnalysis","readabilityScore"]},"dependencies":[],"version":"0.2.0","author":"rotifer-team","createdAt":1771939405686,"fidelity":"Native","transparency":"Open","source":"skill"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* source-linker Gene (Native)
|
|
3
|
+
*
|
|
4
|
+
* Maps raw source file paths (e.g. "docs/getting-started.md") to
|
|
5
|
+
* human-readable titles and browsable URLs on rotifer.dev.
|
|
6
|
+
*
|
|
7
|
+
* Pure mapping — no network calls, no external dependencies.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
interface SourceLinkerInput {
|
|
11
|
+
answer: string;
|
|
12
|
+
sources: string[];
|
|
13
|
+
confidence?: number;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
interface SourceLink {
|
|
17
|
+
title: string;
|
|
18
|
+
url: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
interface SourceLinkerOutput {
|
|
22
|
+
text: string;
|
|
23
|
+
links: SourceLink[];
|
|
24
|
+
confidence: number;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const BASE_URL = "https://rotifer.dev";
|
|
28
|
+
|
|
29
|
+
const TITLE_MAP: Record<string, string> = {
|
|
30
|
+
"docs/getting-started.md": "Getting Started",
|
|
31
|
+
"docs/getting-started.zh.md": "快速开始",
|
|
32
|
+
"docs/architecture-decisions.md": "Architecture Decisions",
|
|
33
|
+
"docs/cloud-binding-api.md": "Cloud Binding API",
|
|
34
|
+
"spec/rotifer-protocol-specification.md": "Protocol Specification",
|
|
35
|
+
"spec/rotifer-protocol-specification.zh.md": "协议规范",
|
|
36
|
+
"spec/rotifer-ir-specification.md": "IR Specification",
|
|
37
|
+
"spec/rotifer-ir-specification.zh.md": "IR 规范",
|
|
38
|
+
"README.md": "Rotifer Protocol Overview",
|
|
39
|
+
"README.zh.md": "轮虫协议概览",
|
|
40
|
+
"CONTRIBUTING.md": "Contributing Guide",
|
|
41
|
+
"CHANGELOG.md": "Changelog",
|
|
42
|
+
"FAQ.md": "FAQ",
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
function pathToTitle(source: string): string {
|
|
46
|
+
if (TITLE_MAP[source]) return TITLE_MAP[source];
|
|
47
|
+
|
|
48
|
+
const filename = source.split("/").pop() || source;
|
|
49
|
+
return filename
|
|
50
|
+
.replace(/\.(md|mdx|ts|json)$/, "")
|
|
51
|
+
.replace(/[-_]/g, " ")
|
|
52
|
+
.replace(/\b\w/g, (c) => c.toUpperCase());
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function pathToUrl(source: string): string {
|
|
56
|
+
const slug = source
|
|
57
|
+
.replace(/^(playground\/)?docs\//, "docs/")
|
|
58
|
+
.replace(/^(playground\/)?spec\//, "spec/")
|
|
59
|
+
.replace(/\.(md|mdx)$/, "")
|
|
60
|
+
.replace(/\.zh$/, "")
|
|
61
|
+
.replace(/\s+/g, "-")
|
|
62
|
+
.toLowerCase();
|
|
63
|
+
|
|
64
|
+
return `${BASE_URL}/${slug}`;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export async function express(input: SourceLinkerInput): Promise<SourceLinkerOutput> {
|
|
68
|
+
const sources = input.sources || [];
|
|
69
|
+
const seen = new Set<string>();
|
|
70
|
+
const links: SourceLink[] = [];
|
|
71
|
+
|
|
72
|
+
for (const source of sources) {
|
|
73
|
+
const normalized = source.trim();
|
|
74
|
+
if (!normalized || seen.has(normalized)) continue;
|
|
75
|
+
seen.add(normalized);
|
|
76
|
+
|
|
77
|
+
links.push({
|
|
78
|
+
title: pathToTitle(normalized),
|
|
79
|
+
url: pathToUrl(normalized),
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return {
|
|
84
|
+
text: input.answer || "",
|
|
85
|
+
links,
|
|
86
|
+
confidence: input.confidence ?? 0,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"domain": "content.linking",
|
|
3
|
+
"description": "Maps source file paths to human-readable titles and browsable URLs. Pure mapping logic, no network dependency.",
|
|
4
|
+
"inputSchema": {
|
|
5
|
+
"type": "object",
|
|
6
|
+
"properties": {
|
|
7
|
+
"answer": { "type": "string", "description": "The synthesized answer (passed through)" },
|
|
8
|
+
"sources": {
|
|
9
|
+
"type": "array",
|
|
10
|
+
"items": { "type": "string" },
|
|
11
|
+
"description": "Source file paths from answer-synthesizer"
|
|
12
|
+
},
|
|
13
|
+
"confidence": { "type": "number" }
|
|
14
|
+
},
|
|
15
|
+
"required": ["answer", "sources"]
|
|
16
|
+
},
|
|
17
|
+
"outputSchema": {
|
|
18
|
+
"type": "object",
|
|
19
|
+
"properties": {
|
|
20
|
+
"text": {
|
|
21
|
+
"type": "string",
|
|
22
|
+
"description": "The answer text (renamed for grammar-checker compatibility)"
|
|
23
|
+
},
|
|
24
|
+
"links": {
|
|
25
|
+
"type": "array",
|
|
26
|
+
"items": {
|
|
27
|
+
"type": "object",
|
|
28
|
+
"properties": {
|
|
29
|
+
"title": { "type": "string" },
|
|
30
|
+
"url": { "type": "string" }
|
|
31
|
+
},
|
|
32
|
+
"required": ["title", "url"]
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"confidence": { "type": "number" }
|
|
36
|
+
},
|
|
37
|
+
"required": ["text", "links"]
|
|
38
|
+
},
|
|
39
|
+
"dependencies": [],
|
|
40
|
+
"version": "0.1.0",
|
|
41
|
+
"author": "rotifer-team",
|
|
42
|
+
"createdAt": 1772236800000,
|
|
43
|
+
"fidelity": "Native",
|
|
44
|
+
"transparency": "Open"
|
|
45
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"geneId": "e21277e13eb1038c2070805ffd27baaff1c2cd3d3cb6aeae854ff604ecaf8ccc",
|
|
3
|
+
"name": "style-optimizer",
|
|
4
|
+
"domain": "content.style",
|
|
5
|
+
"fidelity": "Wrapped",
|
|
6
|
+
"wrappedAt": "2026-02-24T13:23:19.974Z",
|
|
7
|
+
"fromSkill": "../.cursor/skills/style-optimizer/SKILL.md"
|
|
8
|
+
}
|