alp-code 0.9.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.
Files changed (204) hide show
  1. package/CHANGELOG.md +770 -0
  2. package/LICENSE +21 -0
  3. package/README.md +295 -0
  4. package/alp.config.yaml +5 -0
  5. package/dist/src/agents/agent-definition.js +28 -0
  6. package/dist/src/agents/capability-catalog.js +33 -0
  7. package/dist/src/agents/compaction.js +36 -0
  8. package/dist/src/agents/errors.js +12 -0
  9. package/dist/src/agents/librarian.js +38 -0
  10. package/dist/src/agents/main.js +37 -0
  11. package/dist/src/agents/memory-grant.js +29 -0
  12. package/dist/src/agents/model-context.js +70 -0
  13. package/dist/src/agents/modes.js +134 -0
  14. package/dist/src/agents/oracle.js +36 -0
  15. package/dist/src/agents/read-thread.js +38 -0
  16. package/dist/src/agents/registry.js +238 -0
  17. package/dist/src/agents/render-identity.js +38 -0
  18. package/dist/src/agents/review.js +37 -0
  19. package/dist/src/agents/search.js +37 -0
  20. package/dist/src/agents/shared/house-rules.js +33 -0
  21. package/dist/src/agents/shared/principal.js +18 -0
  22. package/dist/src/agents/shared/voice.js +29 -0
  23. package/dist/src/agents/titling.js +32 -0
  24. package/dist/src/agents/types.js +15 -0
  25. package/dist/src/backend/execution-backend.js +2 -0
  26. package/dist/src/backend/local-execution-store.js +144 -0
  27. package/dist/src/backend/local-process-backend.js +533 -0
  28. package/dist/src/backend/local-supervisor.js +104 -0
  29. package/dist/src/cli/alp.js +380 -0
  30. package/dist/src/cli/commands/context.js +203 -0
  31. package/dist/src/cli/commands/delegate.js +136 -0
  32. package/dist/src/cli/commands/identity-sync.js +31 -0
  33. package/dist/src/cli/commands/init.js +184 -0
  34. package/dist/src/cli/commands/mode.js +22 -0
  35. package/dist/src/cli/commands/principal.js +114 -0
  36. package/dist/src/cli/commands/run-main.js +90 -0
  37. package/dist/src/cli/commands/runtime.js +21 -0
  38. package/dist/src/cli/mode-preference-store.js +62 -0
  39. package/dist/src/cli/mode-selector.js +178 -0
  40. package/dist/src/cli/update-check.js +77 -0
  41. package/dist/src/context/checkpoint.js +134 -0
  42. package/dist/src/context/compact-journal.js +153 -0
  43. package/dist/src/context/compact-payload.js +121 -0
  44. package/dist/src/context/continuity.js +70 -0
  45. package/dist/src/context/types.js +2 -0
  46. package/dist/src/delegation/backend-registry.js +40 -0
  47. package/dist/src/delegation/delegation-service.js +300 -0
  48. package/dist/src/delegation/types.js +12 -0
  49. package/dist/src/execution/execution-policy.js +96 -0
  50. package/dist/src/execution/execution-service.js +115 -0
  51. package/dist/src/execution/execution-store.js +78 -0
  52. package/dist/src/execution/identity-capsule.js +65 -0
  53. package/dist/src/execution/types.js +12 -0
  54. package/dist/src/hooks/execution-bridge.js +84 -0
  55. package/dist/src/index.js +4 -0
  56. package/dist/src/memory/adapters/markdown-file-store.js +257 -0
  57. package/dist/src/memory/adapters/memory-api-client.js +2 -0
  58. package/dist/src/memory/adapters/memory-path-mapper.js +76 -0
  59. package/dist/src/memory/adapters/remote-api-store.js +25 -0
  60. package/dist/src/memory/context-ranker.js +21 -0
  61. package/dist/src/memory/errors.js +58 -0
  62. package/dist/src/memory/memory-service.js +149 -0
  63. package/dist/src/memory/memory-store.js +2 -0
  64. package/dist/src/memory/types.js +2 -0
  65. package/dist/src/policy/capability-policy.js +29 -0
  66. package/dist/src/policy/delegation-policy.js +25 -0
  67. package/dist/src/policy/errors.js +10 -0
  68. package/dist/src/policy/invariants.js +31 -0
  69. package/dist/src/policy/memory-policy.js +22 -0
  70. package/dist/src/policy/policy-engine.js +85 -0
  71. package/dist/src/policy/types.js +8 -0
  72. package/dist/src/policy/workspace-policy.js +77 -0
  73. package/dist/src/principal/principal-profile-store.js +89 -0
  74. package/dist/src/runtime/adapter-files.js +147 -0
  75. package/dist/src/runtime/claude-adapter.js +177 -0
  76. package/dist/src/runtime/codex-adapter.js +169 -0
  77. package/dist/src/runtime/permission-rules.js +156 -0
  78. package/dist/src/runtime/render-session-context.js +124 -0
  79. package/dist/src/runtime/render-task-input.js +33 -0
  80. package/dist/src/runtime/runtime-adapter.js +2 -0
  81. package/dist/src/runtime/runtime-preference-store.js +66 -0
  82. package/dist/src/runtime/runtime-selector.js +178 -0
  83. package/dist/src/runtime/types.js +2 -0
  84. package/dist/src/runtime/windows-shim.js +57 -0
  85. package/dist/src/state-paths.js +49 -0
  86. package/dist/src/workflow/output-validator.js +27 -0
  87. package/dist/src/workflow/repair-policy.js +8 -0
  88. package/dist/src/workflow/types.js +22 -0
  89. package/dist/src/workflow/workflow-runner.js +81 -0
  90. package/hooks/compact-record.cjs +109 -0
  91. package/hooks/session-boot.cjs +112 -0
  92. package/hooks/session-end.cjs +34 -0
  93. package/package.json +48 -0
  94. package/scaffold/memory/INDEX.md +27 -0
  95. package/scaffold/memory/README.md +76 -0
  96. package/scaffold/memory/projects/INDEX.md +22 -0
  97. package/scaffold/memory/projects/PROTOCOL.md +128 -0
  98. package/scaffold/memory/projects/_template/PROJECT.md +45 -0
  99. package/scripts/alp.cjs +126 -0
  100. package/scripts/alp.ps1 +4 -0
  101. package/scripts/alp.sh +3 -0
  102. package/scripts/bootstrap.cjs +144 -0
  103. package/scripts/checkout-release.cjs +30 -0
  104. package/scripts/delegate.cjs +19 -0
  105. package/scripts/doctor.cjs +158 -0
  106. package/scripts/doctor.sh +3 -0
  107. package/scripts/ensure-state.cjs +22 -0
  108. package/scripts/lib/cli-link.cjs +375 -0
  109. package/scripts/lib/codex-role.cjs +18 -0
  110. package/scripts/lib/delegation/command-runner.cjs +108 -0
  111. package/scripts/lib/delegation/config.cjs +81 -0
  112. package/scripts/lib/install-paths.cjs +154 -0
  113. package/scripts/lib/release-manifest.cjs +42 -0
  114. package/scripts/lib/semver-lite.cjs +20 -0
  115. package/scripts/lib/state.cjs +274 -0
  116. package/scripts/lib/uninstall.cjs +252 -0
  117. package/scripts/lib/update-check-worker.cjs +21 -0
  118. package/scripts/lib/update.cjs +395 -0
  119. package/scripts/run-role.cjs +42 -0
  120. package/scripts/run-role.ps1 +4 -0
  121. package/scripts/run-role.sh +3 -0
  122. package/scripts/sync-project-index.sh +167 -0
  123. package/skills/agent-memory/SKILL.md +109 -0
  124. package/skills/alp-debug/SKILL.md +90 -0
  125. package/skills/alp-debug/references/defense-in-depth.md +118 -0
  126. package/skills/alp-debug/references/investigation-methodology.md +106 -0
  127. package/skills/alp-debug/references/log-and-ci-analysis.md +96 -0
  128. package/skills/alp-debug/references/performance-diagnostics.md +112 -0
  129. package/skills/alp-debug/references/reporting-standards.md +120 -0
  130. package/skills/alp-debug/references/root-cause-tracing.md +134 -0
  131. package/skills/alp-debug/references/systematic-debugging.md +93 -0
  132. package/skills/alp-debug/references/verification.md +86 -0
  133. package/skills/alp-debug/scripts/find-polluter.sh +63 -0
  134. package/skills/alp-debug/scripts/find-polluter.test.md +102 -0
  135. package/skills/alp-plan/SKILL.md +128 -0
  136. package/skills/alp-plan/references/archive-workflow.md +77 -0
  137. package/skills/alp-plan/references/codebase-understanding.md +55 -0
  138. package/skills/alp-plan/references/output-standards.md +96 -0
  139. package/skills/alp-plan/references/plan-organization.md +129 -0
  140. package/skills/alp-plan/references/red-team-personas.md +76 -0
  141. package/skills/alp-plan/references/red-team-workflow.md +81 -0
  142. package/skills/alp-plan/references/research-phase.md +57 -0
  143. package/skills/alp-plan/references/scope-challenge.md +82 -0
  144. package/skills/alp-plan/references/solution-design.md +76 -0
  145. package/skills/alp-plan/references/validate-question-framework.md +89 -0
  146. package/skills/alp-plan/references/validate-workflow.md +83 -0
  147. package/skills/alp-predict/SKILL.md +98 -0
  148. package/skills/alp-scenario/SKILL.md +86 -0
  149. package/skills/code-review/SKILL.md +111 -0
  150. package/skills/code-review/references/code-review-reception.md +114 -0
  151. package/skills/code-review/references/edge-case-scouting.md +78 -0
  152. package/skills/code-review/references/verification-before-completion.md +117 -0
  153. package/skills/delegation/SKILL.md +46 -0
  154. package/skills/docs-seeker/.env.example +15 -0
  155. package/skills/docs-seeker/SKILL.md +87 -0
  156. package/skills/docs-seeker/package.json +25 -0
  157. package/skills/docs-seeker/references/advanced.md +82 -0
  158. package/skills/docs-seeker/references/context7-patterns.md +68 -0
  159. package/skills/docs-seeker/references/errors.md +72 -0
  160. package/skills/docs-seeker/scripts/analyze-llms-txt.js +211 -0
  161. package/skills/docs-seeker/scripts/detect-topic.js +172 -0
  162. package/skills/docs-seeker/scripts/fetch-docs.js +213 -0
  163. package/skills/docs-seeker/scripts/tests/run-tests.js +72 -0
  164. package/skills/docs-seeker/scripts/tests/test-analyze-llms.js +119 -0
  165. package/skills/docs-seeker/scripts/tests/test-detect-topic.js +112 -0
  166. package/skills/docs-seeker/scripts/tests/test-fetch-docs.js +84 -0
  167. package/skills/docs-seeker/scripts/utils/env-loader.js +94 -0
  168. package/skills/docs-seeker/workflows/library-search.md +73 -0
  169. package/skills/docs-seeker/workflows/repo-analysis.md +90 -0
  170. package/skills/docs-seeker/workflows/topic-search.md +69 -0
  171. package/skills/git/SKILL.md +121 -0
  172. package/skills/git/references/branch-management.md +90 -0
  173. package/skills/git/references/commit-standards.md +82 -0
  174. package/skills/git/references/gh-cli-guide.md +132 -0
  175. package/skills/git/references/safety-protocols.md +86 -0
  176. package/skills/git/references/workflow-commit.md +89 -0
  177. package/skills/git/references/workflow-merge.md +63 -0
  178. package/skills/git/references/workflow-pr.md +70 -0
  179. package/skills/git/references/workflow-push.md +62 -0
  180. package/skills/gkg/SKILL.md +87 -0
  181. package/skills/gkg/references/cli-commands.md +92 -0
  182. package/skills/gkg/references/http-api.md +99 -0
  183. package/skills/gkg/references/language-support.md +54 -0
  184. package/skills/problem-solving/SKILL.md +86 -0
  185. package/skills/problem-solving/references/attribution.md +48 -0
  186. package/skills/problem-solving/references/collision-zone-thinking.md +71 -0
  187. package/skills/problem-solving/references/inversion-exercise.md +88 -0
  188. package/skills/problem-solving/references/meta-pattern-recognition.md +80 -0
  189. package/skills/problem-solving/references/scale-game.md +82 -0
  190. package/skills/problem-solving/references/simplification-cascades.md +83 -0
  191. package/skills/problem-solving/references/when-stuck.md +76 -0
  192. package/skills/repomix/SKILL.md +94 -0
  193. package/skills/repomix/references/configuration.md +134 -0
  194. package/skills/repomix/references/usage-patterns.md +106 -0
  195. package/skills/repomix/scripts/.coverage +0 -0
  196. package/skills/repomix/scripts/README.md +179 -0
  197. package/skills/repomix/scripts/repomix_batch.py +455 -0
  198. package/skills/repomix/scripts/repos.example.json +15 -0
  199. package/skills/repomix/scripts/requirements.txt +15 -0
  200. package/skills/repomix/scripts/tests/test_repomix_batch.py +531 -0
  201. package/skills/research/SKILL.md +107 -0
  202. package/skills/security-scan/SKILL.md +101 -0
  203. package/skills/security-scan/references/secret-patterns.md +75 -0
  204. package/skills/security-scan/references/vulnerability-patterns.md +136 -0
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "docs-seeker-scripts",
3
+ "version": "3.0.0",
4
+ "description": "Documentation discovery scripts for docs-seeker skill",
5
+ "private": true,
6
+ "scripts": {
7
+ "test": "node scripts/tests/run-tests.js",
8
+ "test:detect": "node scripts/tests/test-detect-topic.js",
9
+ "test:fetch": "node scripts/tests/test-fetch-docs.js",
10
+ "test:analyze": "node scripts/tests/test-analyze-llms.js"
11
+ },
12
+ "keywords": [
13
+ "documentation",
14
+ "llms.txt",
15
+ "context7",
16
+ "docs-discovery"
17
+ ],
18
+ "author": "AnhlpKit",
19
+ "license": "MIT",
20
+ "dependencies": {},
21
+ "devDependencies": {},
22
+ "engines": {
23
+ "node": ">=14.0.0"
24
+ }
25
+ }
@@ -0,0 +1,82 @@
1
+ # Ca khó
2
+
3
+ ## Tài liệu nhiều ngôn ngữ
4
+
5
+ 1. Xác định ngôn ngữ cần từ yêu cầu được giao.
6
+ 2. Tìm `llms.txt` theo ngôn ngữ: `llms-es.txt`, `llms-ja.txt`, `llms-vi.txt`.
7
+ 3. Không có thì dùng bản tiếng Anh.
8
+ 4. **Ghi rõ đã dùng bản ngôn ngữ nào** — bản dịch thường chậm hơn bản gốc vài phiên bản.
9
+
10
+ ## Tài liệu theo phiên bản
11
+
12
+ **Bản mới nhất** — dùng URL gốc, không cần chỉ định gì.
13
+
14
+ **Phiên bản cụ thể:**
15
+
16
+ ```
17
+ WebSearch: "{thư viện} v{phiên bản} llms.txt"
18
+ ```
19
+
20
+ Thử các đường: `/v2/llms.txt` · `/docs/v2/llms.txt` · `/{version}/llms.txt`
21
+
22
+ Với repo: `git checkout v{phiên bản}` hoặc `tags/{phiên bản}`.
23
+
24
+ **Luôn ghi phiên bản đã đọc.** Đây là chỗ sai âm thầm hay gặp nhất của cả skill: đọc tài
25
+ liệu v3 rồi trả lời cho project đang dùng v2. Tài liệu không có phiên bản gần như vô dụng
26
+ cho việc đánh giá của `research`.
27
+
28
+ ## Framework có nhiều plugin
29
+
30
+ Framework lõi + 50 plugin thì đừng tài liệu hoá hết.
31
+
32
+ 1. Đọc **lõi trước**.
33
+ 2. Hỏi lại xem cần plugin nào.
34
+ 3. Tìm riêng đúng plugin đó.
35
+ 4. Liệt kê tên các plugin có sẵn trong báo cáo, để bên đọc biết còn gì.
36
+
37
+ Đọc hết 50 plugin là phá ngân sách context của cả phiên để trả lời một câu hỏi về hai
38
+ plugin.
39
+
40
+ ## Tài liệu đang viết dở
41
+
42
+ **Dấu hiệu:** bản phát hành mới mà tài liệu chưa theo kịp · nhiều trang "coming soon" ·
43
+ issue trên GitHub đang xin tài liệu.
44
+
45
+ Cách làm:
46
+
47
+ 1. **Nói ngay ở đầu báo cáo** rằng tài liệu chưa đầy đủ.
48
+ 2. Kết hợp phần tài liệu có sẵn với đọc repo.
49
+ 3. Xem thư mục `tests/` và `examples/` — chúng thường chính xác hơn tài liệu vì chúng chạy.
50
+ 4. **Đánh dấu rõ phần nào là "suy ra từ code"**, không trộn lẫn với phần có tài liệu.
51
+ 5. Dẫn link issue liên quan để bên đọc theo dõi.
52
+
53
+ ## Nguồn mâu thuẫn nhau
54
+
55
+ 1. Xác định đâu là **nguồn sơ cấp chính thức**.
56
+ 2. Kiểm xem có phải khác phiên bản không — phần lớn mâu thuẫn là do đó.
57
+ 3. **Trình bày cả hai**, kèm ngữ cảnh của từng bên.
58
+ 4. Khuyến nghị bản chính thức mới nhất.
59
+ 5. Giải thích vì sao có mâu thuẫn.
60
+
61
+ Thứ tự ưu tiên nguồn:
62
+
63
+ ```
64
+ 1. Tài liệu chính thức, bản mới nhất
65
+ 2. Tài liệu chính thức, bản theo phiên bản
66
+ 3. README trên GitHub
67
+ 4. Tutorial cộng đồng
68
+ 5. Stack Overflow
69
+ ```
70
+
71
+ **Không chọn hộ bên giao việc khi mâu thuẫn là thật** (hai bên cùng đúng trong hai ngữ cảnh khác
72
+ nhau). Nêu cả hai, chỉ ra ngữ cảnh nào hợp với project. Đây là luật "đang tranh cãi" của
73
+ `research`.
74
+
75
+ ## Giới hạn tần suất API
76
+
77
+ - Đặt `CONTEXT7_API_KEY` vào biến môi trường — báo principal, **không tự tạo file `.env`
78
+ trong `skills/`** (thư mục đóng băng, CHARTER §8).
79
+ - Bị giới hạn thì giãn dần thời gian giữa các lần gọi, đừng gọi dồn.
80
+ - Nhớ kết quả đã lấy **trong phiên**, đừng gọi lại cùng một URL.
81
+ - Vẫn bị chặn → dừng, báo lại. Ngân sách 5 lượt của `research` không đủ để ngồi chờ
82
+ rate limit hồi.
@@ -0,0 +1,68 @@
1
+ # Mẫu URL context7.com
2
+
3
+ Tài liệu này để **hiểu script đang làm gì** và để gỡ khi script hỏng. Bình thường cứ chạy
4
+ script — đoán URL bằng tay thì sai là tốn một lượt trong ngân sách 5 lượt của `research`.
5
+
6
+ ## Ưu tiên 1 — URL theo chủ đề
7
+
8
+ ```
9
+ https://context7.com/{path}/llms.txt?topic={từ khoá}
10
+ ```
11
+
12
+ Trả về **chỉ tài liệu liên quan tới chủ đề**. Nhanh hơn nhiều lần, ít token hơn nhiều.
13
+
14
+ | Câu hỏi | URL |
15
+ |---|---|
16
+ | date picker của shadcn/ui | `context7.com/shadcn-ui/ui/llms.txt?topic=date` |
17
+ | caching của Next.js | `context7.com/vercel/next.js/llms.txt?topic=cache` |
18
+ | OAuth của Better Auth | `context7.com/better-auth/better-auth/llms.txt?topic=oauth` |
19
+ | nén của FFmpeg | `context7.com/websites/ffmpeg_doxygen_8_0/llms.txt?topic=compress` |
20
+
21
+ ## Ưu tiên 2 — URL cả thư viện
22
+
23
+ ```
24
+ https://context7.com/{org}/{repo}/llms.txt # repo GitHub
25
+ https://context7.com/websites/{đường-dẫn}/llms.txt # website
26
+ ```
27
+
28
+ Dùng khi câu hỏi rộng, hoặc URL theo chủ đề trả 404.
29
+
30
+ ## Ánh xạ tên đã biết
31
+
32
+ Tên thông dụng không trùng đường dẫn repo:
33
+
34
+ | Người ta gọi | Đường dẫn thật |
35
+ |---|---|
36
+ | `next.js`, `nextjs` | `vercel/next.js` |
37
+ | `astro` | `withastro/astro` |
38
+ | `remix` | `remix-run/remix` |
39
+ | `shadcn`, `shadcn/ui` | `shadcn-ui/ui` |
40
+ | `better-auth` | `better-auth/better-auth` |
41
+
42
+ ## Chuẩn hoá từ khoá chủ đề
43
+
44
+ - Viết thường.
45
+ - Bỏ ký tự đặc biệt.
46
+ - Chủ đề nhiều từ → lấy từ đầu.
47
+ - Tối đa 20 ký tự.
48
+
49
+ | Câu hỏi có | Từ khoá |
50
+ |---|---|
51
+ | "date picker" | `date` |
52
+ | "OAuth" | `oauth` |
53
+ | "Server-Side" | `server` |
54
+ | "caching strategies" | `caching` |
55
+
56
+ ## Dự phòng — site chính thức
57
+
58
+ **Chỉ dùng khi context7.com không truy cập được:**
59
+
60
+ ```
61
+ Astro: https://docs.astro.build/llms.txt
62
+ Next.js: https://nextjs.org/llms.txt
63
+ Remix: https://remix.run/llms.txt
64
+ SvelteKit: https://kit.svelte.dev/llms.txt
65
+ ```
66
+
67
+ Dùng đường dự phòng thì **ghi rõ trong báo cáo** — nguồn khác nhau có thể ở phiên bản khác
68
+ nhau, và `research` yêu cầu ghi phiên bản kèm ngày cho mọi nguồn.
@@ -0,0 +1,72 @@
1
+ # Lỗi và chuỗi dự phòng
2
+
3
+ ## Loại lỗi
4
+
5
+ | Lỗi | Nghĩa thường là |
6
+ |---|---|
7
+ | **404** | URL theo chủ đề không có · thư viện không có trên context7 · không có `llms.txt` |
8
+ | **Timeout** | mạng · repo lớn khi clone · API chậm |
9
+ | **Phản hồi hỏng** | `llms.txt` sai định dạng · nội dung rỗng · URL không hợp lệ |
10
+
11
+ **404 không có nghĩa là thư viện không tồn tại.** Nó chỉ nghĩa là context7 không có bản
12
+ index cho đường dẫn đó. Kiểm lại tên repo trong `context7-patterns.md` trước khi bỏ cuộc —
13
+ tên thông dụng thường khác đường dẫn repo (`next.js` → `vercel/next.js`).
14
+
15
+ ## Chuỗi dự phòng
16
+
17
+ ### Hỏi chủ đề cụ thể
18
+
19
+ ```
20
+ 1. URL theo chủ đề context7.com/{lib}/llms.txt?topic={từ khoá}
21
+ ↓ 404
22
+ 2. URL cả thư viện context7.com/{lib}/llms.txt
23
+ ↓ 404
24
+ 3. WebSearch "{lib} llms.txt site:{domain chính thức}"
25
+ ↓ không có
26
+ 4. Đọc thẳng repo workflows/repo-analysis.md
27
+ ```
28
+
29
+ ### Hỏi cả thư viện
30
+
31
+ ```
32
+ 1. context7.com/{lib}/llms.txt
33
+ ↓ 404
34
+ 2. WebSearch "{lib} llms.txt"
35
+ ↓ không có
36
+ 3. Đọc thẳng repo
37
+ ↓ không có repo
38
+ 4. Nguồn thứ cấp — và PHẢI ghi rõ là thứ cấp
39
+ ```
40
+
41
+ Bước 4 trong bản gốc là "chia cho nhiều Researcher agent" — không áp dụng khi loadout
42
+ không cho giao việc: tự gom nguồn thứ cấp, đối chiếu hai nguồn độc lập, và nói rõ trong
43
+ báo cáo rằng không có nguồn sơ cấp.
44
+
45
+ ## Timeout
46
+
47
+ | Thao tác | Giới hạn |
48
+ |---|---|
49
+ | `WebFetch` | 60s |
50
+ | clone repo | 5 phút |
51
+ | `repomix` | 10 phút |
52
+
53
+ **Hỏng thì bỏ, đừng thử lại cách vừa hỏng.** Chuyển sang bước dự phòng kế tiếp. Thử lại
54
+ cùng một URL 404 ba lần chỉ tốn ngân sách — `research` chỉ có 5 lượt.
55
+
56
+ ## Kết quả rỗng
57
+
58
+ `llms.txt` trả về 0 URL:
59
+
60
+ 1. **Ghi vào báo cáo** — rỗng là thông tin, không phải "không có gì để nói".
61
+ 2. Thử đọc thẳng repo.
62
+ 3. Kiểm site chính thức bằng tay.
63
+
64
+ Đừng để kết quả rỗng biến thành im lặng. Bên giao việc không phân biệt được "đã tìm và không có" với
65
+ "quên tìm" nếu bạn không nói.
66
+
67
+ ## Script hỏng
68
+
69
+ Script trong `scripts/` lỗi thì **sửa rồi chạy lại cho tới khi được** — đó là luật của repo.
70
+ Đừng bỏ script rồi tự dựng URL bằng tay: script có sẵn chuỗi fallback, làm tay là mất nó.
71
+
72
+ Sửa không được thì báo lại, kèm lỗi nguyên văn.
@@ -0,0 +1,211 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * llms.txt Analyzer Script
5
+ * Parses llms.txt content and categorizes URLs for optimal agent distribution
6
+ */
7
+
8
+ const { loadEnv } = require('./utils/env-loader');
9
+
10
+ // Load environment
11
+ const env = loadEnv();
12
+ const DEBUG = env.DEBUG === 'true';
13
+
14
+ /**
15
+ * URL priority categories
16
+ */
17
+ const PRIORITY_KEYWORDS = {
18
+ critical: [
19
+ 'getting-started', 'quick-start', 'quickstart', 'introduction', 'intro', 'overview',
20
+ 'installation', 'install', 'setup', 'basics', 'core-concepts', 'fundamentals',
21
+ ],
22
+ supplementary: [
23
+ 'advanced', 'internals', 'migration', 'migrate', 'troubleshooting', 'troubleshoot',
24
+ 'faq', 'frequently-asked', 'changelog', 'contributing', 'contribute',
25
+ ],
26
+ important: [
27
+ 'guide', 'tutorial', 'example', 'api-reference', 'api', 'reference',
28
+ 'configuration', 'config', 'routing', 'route', 'data-fetching', 'authentication', 'auth',
29
+ ],
30
+ };
31
+
32
+ /**
33
+ * Categorize URL by priority
34
+ * @param {string} url - Documentation URL
35
+ * @returns {string} Priority level (critical/important/supplementary)
36
+ */
37
+ function categorizeUrl(url) {
38
+ const urlLower = url.toLowerCase();
39
+
40
+ // Check in priority order: critical first, then supplementary, then important
41
+ // This ensures specific keywords (advanced, internals) are caught before generic ones
42
+ const priorities = ['critical', 'supplementary', 'important'];
43
+
44
+ for (const priority of priorities) {
45
+ const keywords = PRIORITY_KEYWORDS[priority];
46
+ for (const keyword of keywords) {
47
+ if (urlLower.includes(keyword)) {
48
+ return priority;
49
+ }
50
+ }
51
+ }
52
+
53
+ return 'important'; // Default
54
+ }
55
+
56
+ /**
57
+ * Parse llms.txt content to extract URLs
58
+ * @param {string} content - llms.txt content
59
+ * @returns {Array<string>} Array of URLs
60
+ */
61
+ function parseUrls(content) {
62
+ if (!content || typeof content !== 'string') {
63
+ return [];
64
+ }
65
+
66
+ const urls = [];
67
+ const lines = content.split('\n');
68
+
69
+ for (const line of lines) {
70
+ const trimmed = line.trim();
71
+
72
+ // Skip comments and empty lines
73
+ if (!trimmed || trimmed.startsWith('#')) continue;
74
+
75
+ // Extract URLs (look for http/https)
76
+ const urlMatch = trimmed.match(/https?:\/\/[^\s<>"]+/i);
77
+ if (urlMatch) {
78
+ urls.push(urlMatch[0]);
79
+ }
80
+ }
81
+
82
+ return urls;
83
+ }
84
+
85
+ /**
86
+ * Group URLs by priority
87
+ * @param {Array<string>} urls - Array of URLs
88
+ * @returns {Object} URLs grouped by priority
89
+ */
90
+ function groupByPriority(urls) {
91
+ const groups = {
92
+ critical: [],
93
+ important: [],
94
+ supplementary: [],
95
+ };
96
+
97
+ for (const url of urls) {
98
+ const priority = categorizeUrl(url);
99
+ groups[priority].push(url);
100
+ }
101
+
102
+ return groups;
103
+ }
104
+
105
+ /**
106
+ * Suggest optimal agent distribution
107
+ * @param {number} urlCount - Total number of URLs
108
+ * @returns {Object} Agent distribution suggestion
109
+ */
110
+ function suggestAgentDistribution(urlCount) {
111
+ if (urlCount <= 3) {
112
+ return {
113
+ agentCount: 1,
114
+ strategy: 'single',
115
+ urlsPerAgent: urlCount,
116
+ description: 'Single agent can handle all URLs',
117
+ };
118
+ } else if (urlCount <= 10) {
119
+ const agents = Math.min(Math.ceil(urlCount / 2), 5);
120
+ return {
121
+ agentCount: agents,
122
+ strategy: 'parallel',
123
+ urlsPerAgent: Math.ceil(urlCount / agents),
124
+ description: `Deploy ${agents} agents in parallel`,
125
+ };
126
+ } else if (urlCount <= 20) {
127
+ return {
128
+ agentCount: 7,
129
+ strategy: 'parallel',
130
+ urlsPerAgent: Math.ceil(urlCount / 7),
131
+ description: 'Deploy 7 agents with balanced workload',
132
+ };
133
+ } else {
134
+ return {
135
+ agentCount: 7,
136
+ strategy: 'phased',
137
+ urlsPerAgent: Math.ceil(urlCount / 7),
138
+ phases: 2,
139
+ description: 'Use two-phase approach: critical first, then important',
140
+ };
141
+ }
142
+ }
143
+
144
+ /**
145
+ * Analyze llms.txt content
146
+ * @param {string} content - llms.txt content
147
+ * @returns {Object} Analysis result
148
+ */
149
+ function analyzeLlmsTxt(content) {
150
+ const urls = parseUrls(content);
151
+ const grouped = groupByPriority(urls);
152
+ const distribution = suggestAgentDistribution(urls.length);
153
+
154
+ return {
155
+ totalUrls: urls.length,
156
+ urls,
157
+ grouped,
158
+ distribution,
159
+ summary: {
160
+ critical: grouped.critical.length,
161
+ important: grouped.important.length,
162
+ supplementary: grouped.supplementary.length,
163
+ },
164
+ };
165
+ }
166
+
167
+ /**
168
+ * CLI entry point
169
+ */
170
+ function main() {
171
+ const args = process.argv.slice(2);
172
+
173
+ if (args.length === 0) {
174
+ console.error('Usage: node analyze-llms-txt.js <content-file-or-stdin>');
175
+ console.error('Or pipe content: cat llms.txt | node analyze-llms-txt.js');
176
+ process.exit(1);
177
+ }
178
+
179
+ const fs = require('fs');
180
+ let content;
181
+
182
+ if (args[0] === '-') {
183
+ // Read from stdin
184
+ content = fs.readFileSync(0, 'utf8');
185
+ } else {
186
+ // Read from file
187
+ const filePath = args[0];
188
+ if (!fs.existsSync(filePath)) {
189
+ console.error(`Error: File not found: ${filePath}`);
190
+ process.exit(1);
191
+ }
192
+ content = fs.readFileSync(filePath, 'utf8');
193
+ }
194
+
195
+ const result = analyzeLlmsTxt(content);
196
+ console.log(JSON.stringify(result, null, 2));
197
+ process.exit(0);
198
+ }
199
+
200
+ // Run if called directly
201
+ if (require.main === module) {
202
+ main();
203
+ }
204
+
205
+ module.exports = {
206
+ analyzeLlmsTxt,
207
+ parseUrls,
208
+ groupByPriority,
209
+ categorizeUrl,
210
+ suggestAgentDistribution,
211
+ };
@@ -0,0 +1,172 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Topic Detection Script
5
+ * Analyzes user queries to extract library name and topic keywords
6
+ * Returns null for general queries, topic info for specific queries
7
+ */
8
+
9
+ const { loadEnv } = require('./utils/env-loader');
10
+
11
+ // Load environment
12
+ const env = loadEnv();
13
+ const DEBUG = env.DEBUG === 'true';
14
+
15
+ /**
16
+ * Topic-specific query patterns
17
+ */
18
+ const TOPIC_PATTERNS = [
19
+ // "How do I use X in Y?"
20
+ /how (?:do i|to|can i) (?:use|implement|add|setup|configure) (?:the )?(.+?) (?:in|with|for) (.+)/i,
21
+
22
+ // "Y X strategies/patterns" - e.g., "Next.js caching strategies"
23
+ /(.+?) (.+?) (?:strategies|patterns|techniques|methods|approaches)/i,
24
+
25
+ // "X Y documentation" or "Y X docs"
26
+ /(.+?) (.+?) (?:documentation|docs|guide|tutorial)/i,
27
+
28
+ // "Using X with Y"
29
+ /using (.+?) (?:with|in|for) (.+)/i,
30
+
31
+ // "Y X guide/implementation/setup"
32
+ /(.+?) (.+?) (?:guide|implementation|setup|configuration)/i,
33
+
34
+ // "Implement X in Y"
35
+ /implement(?:ing)? (.+?) (?:in|with|for|using) (.+)/i,
36
+ ];
37
+
38
+ /**
39
+ * General library query patterns (non-topic specific)
40
+ */
41
+ const GENERAL_PATTERNS = [
42
+ /(?:documentation|docs) for (.+)/i,
43
+ /(.+?) (?:getting started|quick ?start|introduction)/i,
44
+ /(?:how to use|learn) (.+)/i,
45
+ /(.+?) (?:api reference|overview|basics)/i,
46
+ ];
47
+
48
+ /**
49
+ * Normalize topic keyword
50
+ * @param {string} topic - Raw topic string
51
+ * @returns {string} Normalized topic keyword
52
+ */
53
+ function normalizeTopic(topic) {
54
+ return topic
55
+ .toLowerCase()
56
+ .trim()
57
+ .replace(/[^a-z0-9\s-]/g, '') // Remove special chars
58
+ .replace(/\s+/g, '-') // Replace spaces with hyphens
59
+ .split('-')[0] // Take first word for multi-word topics
60
+ .slice(0, 20); // Limit length
61
+ }
62
+
63
+ /**
64
+ * Normalize library name
65
+ * @param {string} library - Raw library string
66
+ * @returns {string} Normalized library name
67
+ */
68
+ function normalizeLibrary(library) {
69
+ return library
70
+ .toLowerCase()
71
+ .trim()
72
+ .replace(/[^a-z0-9\s\-\/\.]/g, '')
73
+ .replace(/\s+/g, '-');
74
+ }
75
+
76
+ /**
77
+ * Detect if query is topic-specific or general
78
+ * @param {string} query - User query
79
+ * @returns {Object|null} Topic info or null for general query
80
+ */
81
+ function detectTopic(query) {
82
+ if (!query || typeof query !== 'string') {
83
+ return null;
84
+ }
85
+
86
+ const trimmedQuery = query.trim();
87
+
88
+ // Check general patterns first
89
+ for (const pattern of GENERAL_PATTERNS) {
90
+ const match = trimmedQuery.match(pattern);
91
+ if (match) {
92
+ if (DEBUG) console.error('[DEBUG] Matched general pattern, no topic');
93
+ return null;
94
+ }
95
+ }
96
+
97
+ // Check topic-specific patterns
98
+ for (let i = 0; i < TOPIC_PATTERNS.length; i++) {
99
+ const pattern = TOPIC_PATTERNS[i];
100
+ const match = trimmedQuery.match(pattern);
101
+ if (match) {
102
+ const [, term1, term2] = match;
103
+
104
+ // Determine which is library and which is topic based on pattern
105
+ let topic, library;
106
+
107
+ // Pattern 0: "How do I use X in Y?" -> X is topic, Y is library
108
+ // Pattern 1: "Y X strategies" -> X is topic, Y is library
109
+ // Pattern 2-5: X is topic, Y is library in most cases
110
+
111
+ // For pattern 1 (strategies/patterns), term1 is library, term2 is topic
112
+ if (i === 1) {
113
+ topic = normalizeTopic(term2);
114
+ library = normalizeLibrary(term1);
115
+ } else {
116
+ // For other patterns, term1 is topic, term2 is library
117
+ topic = normalizeTopic(term1);
118
+ library = normalizeLibrary(term2);
119
+ }
120
+
121
+ if (DEBUG) {
122
+ console.error('[DEBUG] Matched topic pattern');
123
+ console.error('[DEBUG] Topic:', topic);
124
+ console.error('[DEBUG] Library:', library);
125
+ }
126
+
127
+ return {
128
+ query: trimmedQuery,
129
+ topic,
130
+ library,
131
+ isTopicSpecific: true,
132
+ };
133
+ }
134
+ }
135
+
136
+ if (DEBUG) console.error('[DEBUG] No pattern matched, treating as general');
137
+ return null;
138
+ }
139
+
140
+ /**
141
+ * CLI entry point
142
+ */
143
+ function main() {
144
+ const args = process.argv.slice(2);
145
+
146
+ if (args.length === 0) {
147
+ console.error('Usage: node detect-topic.js "<user query>"');
148
+ process.exit(1);
149
+ }
150
+
151
+ const query = args.join(' ');
152
+ const result = detectTopic(query);
153
+
154
+ if (result) {
155
+ console.log(JSON.stringify(result, null, 2));
156
+ process.exit(0);
157
+ } else {
158
+ console.log(JSON.stringify({ isTopicSpecific: false }, null, 2));
159
+ process.exit(0);
160
+ }
161
+ }
162
+
163
+ // Run if called directly
164
+ if (require.main === module) {
165
+ main();
166
+ }
167
+
168
+ module.exports = {
169
+ detectTopic,
170
+ normalizeTopic,
171
+ normalizeLibrary,
172
+ };