@elizaos/skills 2.0.0-alpha.10

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 (291) hide show
  1. package/README.md +126 -0
  2. package/dist/formatter.d.ts +44 -0
  3. package/dist/formatter.d.ts.map +1 -0
  4. package/dist/formatter.js +182 -0
  5. package/dist/frontmatter.d.ts +39 -0
  6. package/dist/frontmatter.d.ts.map +1 -0
  7. package/dist/frontmatter.js +105 -0
  8. package/dist/index.d.ts +29 -0
  9. package/dist/index.d.ts.map +1 -0
  10. package/dist/index.js +31 -0
  11. package/dist/loader.d.ts +33 -0
  12. package/dist/loader.d.ts.map +1 -0
  13. package/dist/loader.js +362 -0
  14. package/dist/resolver.d.ts +18 -0
  15. package/dist/resolver.d.ts.map +1 -0
  16. package/dist/resolver.js +90 -0
  17. package/dist/types.d.ts +201 -0
  18. package/dist/types.d.ts.map +1 -0
  19. package/dist/types.js +1 -0
  20. package/package.json +57 -0
  21. package/skills/1password/SKILL.md +70 -0
  22. package/skills/1password/references/cli-examples.md +29 -0
  23. package/skills/1password/references/get-started.md +17 -0
  24. package/skills/apple-notes/SKILL.md +77 -0
  25. package/skills/apple-reminders/SKILL.md +96 -0
  26. package/skills/bear-notes/SKILL.md +107 -0
  27. package/skills/bird/SKILL.md +224 -0
  28. package/skills/blogwatcher/SKILL.md +69 -0
  29. package/skills/blucli/SKILL.md +47 -0
  30. package/skills/bluebubbles/SKILL.md +131 -0
  31. package/skills/camsnap/SKILL.md +45 -0
  32. package/skills/canvas/SKILL.md +203 -0
  33. package/skills/clawhub/SKILL.md +77 -0
  34. package/skills/coding-agent/SKILL.md +284 -0
  35. package/skills/discord/SKILL.md +578 -0
  36. package/skills/eightctl/SKILL.md +50 -0
  37. package/skills/food-order/SKILL.md +48 -0
  38. package/skills/gemini/SKILL.md +43 -0
  39. package/skills/gifgrep/SKILL.md +79 -0
  40. package/skills/github/SKILL.md +77 -0
  41. package/skills/gog/SKILL.md +116 -0
  42. package/skills/goplaces/SKILL.md +52 -0
  43. package/skills/healthcheck/SKILL.md +245 -0
  44. package/skills/himalaya/SKILL.md +257 -0
  45. package/skills/himalaya/references/configuration.md +184 -0
  46. package/skills/himalaya/references/message-composition.md +199 -0
  47. package/skills/imsg/SKILL.md +74 -0
  48. package/skills/local-places/SERVER_README.md +101 -0
  49. package/skills/local-places/SKILL.md +102 -0
  50. package/skills/local-places/pyproject.toml +21 -0
  51. package/skills/local-places/src/local_places/__init__.py +2 -0
  52. package/skills/local-places/src/local_places/google_places.py +314 -0
  53. package/skills/local-places/src/local_places/main.py +65 -0
  54. package/skills/local-places/src/local_places/schemas.py +107 -0
  55. package/skills/mcporter/SKILL.md +61 -0
  56. package/skills/model-usage/SKILL.md +69 -0
  57. package/skills/model-usage/references/codexbar-cli.md +33 -0
  58. package/skills/model-usage/scripts/model_usage.py +310 -0
  59. package/skills/nano-banana-pro/SKILL.md +58 -0
  60. package/skills/nano-banana-pro/scripts/generate_image.py +184 -0
  61. package/skills/nano-pdf/SKILL.md +38 -0
  62. package/skills/notion/SKILL.md +172 -0
  63. package/skills/obsidian/SKILL.md +81 -0
  64. package/skills/openai-image-gen/SKILL.md +89 -0
  65. package/skills/openai-image-gen/scripts/gen.py +240 -0
  66. package/skills/openai-whisper/SKILL.md +38 -0
  67. package/skills/openai-whisper-api/SKILL.md +52 -0
  68. package/skills/openai-whisper-api/scripts/transcribe.sh +85 -0
  69. package/skills/openhue/SKILL.md +51 -0
  70. package/skills/oracle/SKILL.md +125 -0
  71. package/skills/ordercli/SKILL.md +78 -0
  72. package/skills/peekaboo/SKILL.md +190 -0
  73. package/skills/sag/SKILL.md +87 -0
  74. package/skills/security-ask-questions-if-underspecified/.claude-plugin/plugin.json +10 -0
  75. package/skills/security-ask-questions-if-underspecified/README.md +24 -0
  76. package/skills/security-ask-questions-if-underspecified/SKILL.md +85 -0
  77. package/skills/security-ask-questions-if-underspecified/skills/ask-questions-if-underspecified/SKILL.md +85 -0
  78. package/skills/security-audit-context-building/.claude-plugin/plugin.json +10 -0
  79. package/skills/security-audit-context-building/README.md +58 -0
  80. package/skills/security-audit-context-building/SKILL.md +297 -0
  81. package/skills/security-audit-context-building/commands/audit-context.md +21 -0
  82. package/skills/security-audit-context-building/skills/audit-context-building/SKILL.md +297 -0
  83. package/skills/security-audit-context-building/skills/audit-context-building/resources/COMPLETENESS_CHECKLIST.md +47 -0
  84. package/skills/security-audit-context-building/skills/audit-context-building/resources/FUNCTION_MICRO_ANALYSIS_EXAMPLE.md +355 -0
  85. package/skills/security-audit-context-building/skills/audit-context-building/resources/OUTPUT_REQUIREMENTS.md +71 -0
  86. package/skills/security-building-secure-contracts/.claude-plugin/plugin.json +10 -0
  87. package/skills/security-building-secure-contracts/README.md +241 -0
  88. package/skills/security-building-secure-contracts/SKILL.md +67 -0
  89. package/skills/security-building-secure-contracts/skills/algorand-vulnerability-scanner/SKILL.md +284 -0
  90. package/skills/security-building-secure-contracts/skills/algorand-vulnerability-scanner/resources/VULNERABILITY_PATTERNS.md +405 -0
  91. package/skills/security-building-secure-contracts/skills/audit-prep-assistant/SKILL.md +409 -0
  92. package/skills/security-building-secure-contracts/skills/cairo-vulnerability-scanner/SKILL.md +329 -0
  93. package/skills/security-building-secure-contracts/skills/cairo-vulnerability-scanner/resources/VULNERABILITY_PATTERNS.md +722 -0
  94. package/skills/security-building-secure-contracts/skills/code-maturity-assessor/SKILL.md +218 -0
  95. package/skills/security-building-secure-contracts/skills/code-maturity-assessor/resources/ASSESSMENT_CRITERIA.md +355 -0
  96. package/skills/security-building-secure-contracts/skills/code-maturity-assessor/resources/EXAMPLE_REPORT.md +248 -0
  97. package/skills/security-building-secure-contracts/skills/code-maturity-assessor/resources/REPORT_FORMAT.md +33 -0
  98. package/skills/security-building-secure-contracts/skills/cosmos-vulnerability-scanner/SKILL.md +334 -0
  99. package/skills/security-building-secure-contracts/skills/cosmos-vulnerability-scanner/resources/VULNERABILITY_PATTERNS.md +740 -0
  100. package/skills/security-building-secure-contracts/skills/guidelines-advisor/SKILL.md +252 -0
  101. package/skills/security-building-secure-contracts/skills/guidelines-advisor/resources/ASSESSMENT_AREAS.md +329 -0
  102. package/skills/security-building-secure-contracts/skills/guidelines-advisor/resources/DELIVERABLES.md +118 -0
  103. package/skills/security-building-secure-contracts/skills/guidelines-advisor/resources/EXAMPLE_REPORT.md +298 -0
  104. package/skills/security-building-secure-contracts/skills/secure-workflow-guide/SKILL.md +161 -0
  105. package/skills/security-building-secure-contracts/skills/secure-workflow-guide/resources/EXAMPLE_REPORT.md +279 -0
  106. package/skills/security-building-secure-contracts/skills/secure-workflow-guide/resources/WORKFLOW_STEPS.md +132 -0
  107. package/skills/security-building-secure-contracts/skills/solana-vulnerability-scanner/SKILL.md +389 -0
  108. package/skills/security-building-secure-contracts/skills/solana-vulnerability-scanner/resources/VULNERABILITY_PATTERNS.md +669 -0
  109. package/skills/security-building-secure-contracts/skills/substrate-vulnerability-scanner/SKILL.md +298 -0
  110. package/skills/security-building-secure-contracts/skills/substrate-vulnerability-scanner/resources/VULNERABILITY_PATTERNS.md +791 -0
  111. package/skills/security-building-secure-contracts/skills/token-integration-analyzer/SKILL.md +362 -0
  112. package/skills/security-building-secure-contracts/skills/token-integration-analyzer/resources/ASSESSMENT_CATEGORIES.md +571 -0
  113. package/skills/security-building-secure-contracts/skills/token-integration-analyzer/resources/REPORT_TEMPLATES.md +141 -0
  114. package/skills/security-building-secure-contracts/skills/ton-vulnerability-scanner/SKILL.md +388 -0
  115. package/skills/security-building-secure-contracts/skills/ton-vulnerability-scanner/resources/VULNERABILITY_PATTERNS.md +595 -0
  116. package/skills/security-differential-review/.claude-plugin/plugin.json +10 -0
  117. package/skills/security-differential-review/README.md +109 -0
  118. package/skills/security-differential-review/SKILL.md +220 -0
  119. package/skills/security-differential-review/commands/diff-review.md +21 -0
  120. package/skills/security-differential-review/skills/differential-review/SKILL.md +220 -0
  121. package/skills/security-differential-review/skills/differential-review/adversarial.md +203 -0
  122. package/skills/security-differential-review/skills/differential-review/methodology.md +234 -0
  123. package/skills/security-differential-review/skills/differential-review/patterns.md +300 -0
  124. package/skills/security-differential-review/skills/differential-review/reporting.md +369 -0
  125. package/skills/security-entry-point-analyzer/.claude-plugin/plugin.json +10 -0
  126. package/skills/security-entry-point-analyzer/README.md +74 -0
  127. package/skills/security-entry-point-analyzer/SKILL.md +251 -0
  128. package/skills/security-entry-point-analyzer/commands/entry-points.md +18 -0
  129. package/skills/security-entry-point-analyzer/skills/entry-point-analyzer/SKILL.md +251 -0
  130. package/skills/security-entry-point-analyzer/skills/entry-point-analyzer/references/cosmwasm.md +182 -0
  131. package/skills/security-entry-point-analyzer/skills/entry-point-analyzer/references/move-aptos.md +107 -0
  132. package/skills/security-entry-point-analyzer/skills/entry-point-analyzer/references/move-sui.md +87 -0
  133. package/skills/security-entry-point-analyzer/skills/entry-point-analyzer/references/solana.md +155 -0
  134. package/skills/security-entry-point-analyzer/skills/entry-point-analyzer/references/solidity.md +135 -0
  135. package/skills/security-entry-point-analyzer/skills/entry-point-analyzer/references/ton.md +185 -0
  136. package/skills/security-entry-point-analyzer/skills/entry-point-analyzer/references/vyper.md +141 -0
  137. package/skills/security-fix-review/.claude-plugin/plugin.json +13 -0
  138. package/skills/security-fix-review/README.md +118 -0
  139. package/skills/security-fix-review/SKILL.md +264 -0
  140. package/skills/security-fix-review/commands/fix-review.md +24 -0
  141. package/skills/security-fix-review/skills/fix-review/SKILL.md +264 -0
  142. package/skills/security-fix-review/skills/fix-review/references/bug-detection.md +408 -0
  143. package/skills/security-fix-review/skills/fix-review/references/finding-matching.md +298 -0
  144. package/skills/security-fix-review/skills/fix-review/references/report-parsing.md +398 -0
  145. package/skills/security-insecure-defaults/.claude-plugin/plugin.json +10 -0
  146. package/skills/security-insecure-defaults/README.md +45 -0
  147. package/skills/security-insecure-defaults/SKILL.md +117 -0
  148. package/skills/security-insecure-defaults/skills/insecure-defaults/SKILL.md +117 -0
  149. package/skills/security-insecure-defaults/skills/insecure-defaults/references/examples.md +409 -0
  150. package/skills/security-modern-python/.claude-plugin/plugin.json +10 -0
  151. package/skills/security-modern-python/README.md +58 -0
  152. package/skills/security-modern-python/SKILL.md +333 -0
  153. package/skills/security-modern-python/hooks/hooks.json +16 -0
  154. package/skills/security-modern-python/hooks/intercept-legacy-python.bats +388 -0
  155. package/skills/security-modern-python/hooks/intercept-legacy-python.sh +109 -0
  156. package/skills/security-modern-python/hooks/test_helper.bash +75 -0
  157. package/skills/security-modern-python/skills/modern-python/SKILL.md +333 -0
  158. package/skills/security-modern-python/skills/modern-python/references/dependabot.md +43 -0
  159. package/skills/security-modern-python/skills/modern-python/references/migration-checklist.md +141 -0
  160. package/skills/security-modern-python/skills/modern-python/references/pep723-scripts.md +259 -0
  161. package/skills/security-modern-python/skills/modern-python/references/prek.md +211 -0
  162. package/skills/security-modern-python/skills/modern-python/references/pyproject.md +254 -0
  163. package/skills/security-modern-python/skills/modern-python/references/ruff-config.md +240 -0
  164. package/skills/security-modern-python/skills/modern-python/references/security-setup.md +255 -0
  165. package/skills/security-modern-python/skills/modern-python/references/testing.md +284 -0
  166. package/skills/security-modern-python/skills/modern-python/references/uv-commands.md +200 -0
  167. package/skills/security-modern-python/skills/modern-python/templates/dependabot.yml +36 -0
  168. package/skills/security-modern-python/skills/modern-python/templates/pre-commit-config.yaml +66 -0
  169. package/skills/security-property-based-testing/.claude-plugin/plugin.json +9 -0
  170. package/skills/security-property-based-testing/README.md +47 -0
  171. package/skills/security-property-based-testing/SKILL.md +109 -0
  172. package/skills/security-property-based-testing/skills/property-based-testing/README.md +88 -0
  173. package/skills/security-property-based-testing/skills/property-based-testing/SKILL.md +109 -0
  174. package/skills/security-property-based-testing/skills/property-based-testing/references/design.md +191 -0
  175. package/skills/security-property-based-testing/skills/property-based-testing/references/generating.md +200 -0
  176. package/skills/security-property-based-testing/skills/property-based-testing/references/libraries.md +130 -0
  177. package/skills/security-property-based-testing/skills/property-based-testing/references/refactoring.md +181 -0
  178. package/skills/security-property-based-testing/skills/property-based-testing/references/reviewing.md +209 -0
  179. package/skills/security-property-based-testing/skills/property-based-testing/references/strategies.md +124 -0
  180. package/skills/semgrep-rule-creator/.claude-plugin/plugin.json +8 -0
  181. package/skills/semgrep-rule-creator/README.md +43 -0
  182. package/skills/semgrep-rule-creator/SKILL.md +168 -0
  183. package/skills/semgrep-rule-creator/commands/semgrep-rule.md +26 -0
  184. package/skills/semgrep-rule-creator/skills/semgrep-rule-creator/SKILL.md +168 -0
  185. package/skills/semgrep-rule-creator/skills/semgrep-rule-creator/references/quick-reference.md +203 -0
  186. package/skills/semgrep-rule-creator/skills/semgrep-rule-creator/references/workflow.md +240 -0
  187. package/skills/session-logs/SKILL.md +115 -0
  188. package/skills/sharp-edges/.claude-plugin/plugin.json +10 -0
  189. package/skills/sharp-edges/README.md +48 -0
  190. package/skills/sharp-edges/SKILL.md +292 -0
  191. package/skills/sharp-edges/skills/sharp-edges/SKILL.md +292 -0
  192. package/skills/sharp-edges/skills/sharp-edges/references/auth-patterns.md +252 -0
  193. package/skills/sharp-edges/skills/sharp-edges/references/case-studies.md +274 -0
  194. package/skills/sharp-edges/skills/sharp-edges/references/config-patterns.md +333 -0
  195. package/skills/sharp-edges/skills/sharp-edges/references/crypto-apis.md +190 -0
  196. package/skills/sharp-edges/skills/sharp-edges/references/lang-c.md +205 -0
  197. package/skills/sharp-edges/skills/sharp-edges/references/lang-csharp.md +285 -0
  198. package/skills/sharp-edges/skills/sharp-edges/references/lang-go.md +270 -0
  199. package/skills/sharp-edges/skills/sharp-edges/references/lang-java.md +263 -0
  200. package/skills/sharp-edges/skills/sharp-edges/references/lang-javascript.md +269 -0
  201. package/skills/sharp-edges/skills/sharp-edges/references/lang-kotlin.md +265 -0
  202. package/skills/sharp-edges/skills/sharp-edges/references/lang-php.md +245 -0
  203. package/skills/sharp-edges/skills/sharp-edges/references/lang-python.md +274 -0
  204. package/skills/sharp-edges/skills/sharp-edges/references/lang-ruby.md +273 -0
  205. package/skills/sharp-edges/skills/sharp-edges/references/lang-rust.md +272 -0
  206. package/skills/sharp-edges/skills/sharp-edges/references/lang-swift.md +287 -0
  207. package/skills/sharp-edges/skills/sharp-edges/references/language-specific.md +588 -0
  208. package/skills/sherpa-onnx-tts/SKILL.md +103 -0
  209. package/skills/sherpa-onnx-tts/bin/sherpa-onnx-tts +178 -0
  210. package/skills/skill-creator/SKILL.md +370 -0
  211. package/skills/skill-creator/license.txt +202 -0
  212. package/skills/skill-creator/scripts/init_skill.py +378 -0
  213. package/skills/skill-creator/scripts/package_skill.py +111 -0
  214. package/skills/skill-creator/scripts/quick_validate.py +101 -0
  215. package/skills/slack/SKILL.md +144 -0
  216. package/skills/songsee/SKILL.md +49 -0
  217. package/skills/sonoscli/SKILL.md +46 -0
  218. package/skills/spec-to-code-compliance/.claude-plugin/plugin.json +10 -0
  219. package/skills/spec-to-code-compliance/README.md +67 -0
  220. package/skills/spec-to-code-compliance/SKILL.md +349 -0
  221. package/skills/spec-to-code-compliance/commands/spec-compliance.md +22 -0
  222. package/skills/spec-to-code-compliance/skills/spec-to-code-compliance/SKILL.md +349 -0
  223. package/skills/spec-to-code-compliance/skills/spec-to-code-compliance/resources/COMPLETENESS_CHECKLIST.md +69 -0
  224. package/skills/spec-to-code-compliance/skills/spec-to-code-compliance/resources/IR_EXAMPLES.md +417 -0
  225. package/skills/spec-to-code-compliance/skills/spec-to-code-compliance/resources/OUTPUT_REQUIREMENTS.md +105 -0
  226. package/skills/spotify-player/SKILL.md +64 -0
  227. package/skills/static-analysis/.claude-plugin/plugin.json +8 -0
  228. package/skills/static-analysis/README.md +59 -0
  229. package/skills/static-analysis/SKILL.md +91 -0
  230. package/skills/static-analysis/skills/codeql/SKILL.md +315 -0
  231. package/skills/static-analysis/skills/sarif-parsing/SKILL.md +479 -0
  232. package/skills/static-analysis/skills/sarif-parsing/resources/jq-queries.md +162 -0
  233. package/skills/static-analysis/skills/sarif-parsing/resources/sarif_helpers.py +331 -0
  234. package/skills/static-analysis/skills/semgrep/SKILL.md +337 -0
  235. package/skills/summarize/SKILL.md +87 -0
  236. package/skills/testing-handbook-skills/.claude-plugin/plugin.json +8 -0
  237. package/skills/testing-handbook-skills/README.md +241 -0
  238. package/skills/testing-handbook-skills/SKILL.md +104 -0
  239. package/skills/testing-handbook-skills/scripts/pyproject.toml +8 -0
  240. package/skills/testing-handbook-skills/scripts/validate-skills.py +657 -0
  241. package/skills/testing-handbook-skills/skills/address-sanitizer/SKILL.md +341 -0
  242. package/skills/testing-handbook-skills/skills/aflpp/SKILL.md +640 -0
  243. package/skills/testing-handbook-skills/skills/atheris/SKILL.md +515 -0
  244. package/skills/testing-handbook-skills/skills/cargo-fuzz/SKILL.md +454 -0
  245. package/skills/testing-handbook-skills/skills/codeql/SKILL.md +549 -0
  246. package/skills/testing-handbook-skills/skills/constant-time-testing/SKILL.md +507 -0
  247. package/skills/testing-handbook-skills/skills/coverage-analysis/SKILL.md +607 -0
  248. package/skills/testing-handbook-skills/skills/fuzzing-dictionary/SKILL.md +297 -0
  249. package/skills/testing-handbook-skills/skills/fuzzing-obstacles/SKILL.md +426 -0
  250. package/skills/testing-handbook-skills/skills/harness-writing/SKILL.md +614 -0
  251. package/skills/testing-handbook-skills/skills/libafl/SKILL.md +625 -0
  252. package/skills/testing-handbook-skills/skills/libfuzzer/SKILL.md +795 -0
  253. package/skills/testing-handbook-skills/skills/ossfuzz/SKILL.md +426 -0
  254. package/skills/testing-handbook-skills/skills/ruzzy/SKILL.md +443 -0
  255. package/skills/testing-handbook-skills/skills/semgrep/SKILL.md +601 -0
  256. package/skills/testing-handbook-skills/skills/testing-handbook-generator/SKILL.md +372 -0
  257. package/skills/testing-handbook-skills/skills/testing-handbook-generator/agent-prompt.md +280 -0
  258. package/skills/testing-handbook-skills/skills/testing-handbook-generator/discovery.md +452 -0
  259. package/skills/testing-handbook-skills/skills/testing-handbook-generator/templates/domain-skill.md +504 -0
  260. package/skills/testing-handbook-skills/skills/testing-handbook-generator/templates/fuzzer-skill.md +454 -0
  261. package/skills/testing-handbook-skills/skills/testing-handbook-generator/templates/technique-skill.md +527 -0
  262. package/skills/testing-handbook-skills/skills/testing-handbook-generator/templates/tool-skill.md +366 -0
  263. package/skills/testing-handbook-skills/skills/testing-handbook-generator/testing.md +482 -0
  264. package/skills/testing-handbook-skills/skills/wycheproof/SKILL.md +533 -0
  265. package/skills/things-mac/SKILL.md +86 -0
  266. package/skills/tmux/SKILL.md +135 -0
  267. package/skills/tmux/scripts/find-sessions.sh +112 -0
  268. package/skills/tmux/scripts/wait-for-text.sh +83 -0
  269. package/skills/trello/SKILL.md +95 -0
  270. package/skills/variant-analysis/.claude-plugin/plugin.json +8 -0
  271. package/skills/variant-analysis/README.md +41 -0
  272. package/skills/variant-analysis/SKILL.md +142 -0
  273. package/skills/variant-analysis/commands/variants.md +23 -0
  274. package/skills/variant-analysis/skills/variant-analysis/METHODOLOGY.md +327 -0
  275. package/skills/variant-analysis/skills/variant-analysis/SKILL.md +142 -0
  276. package/skills/variant-analysis/skills/variant-analysis/resources/codeql/cpp.ql +119 -0
  277. package/skills/variant-analysis/skills/variant-analysis/resources/codeql/go.ql +69 -0
  278. package/skills/variant-analysis/skills/variant-analysis/resources/codeql/java.ql +71 -0
  279. package/skills/variant-analysis/skills/variant-analysis/resources/codeql/javascript.ql +63 -0
  280. package/skills/variant-analysis/skills/variant-analysis/resources/codeql/python.ql +80 -0
  281. package/skills/variant-analysis/skills/variant-analysis/resources/semgrep/cpp.yaml +98 -0
  282. package/skills/variant-analysis/skills/variant-analysis/resources/semgrep/go.yaml +63 -0
  283. package/skills/variant-analysis/skills/variant-analysis/resources/semgrep/java.yaml +61 -0
  284. package/skills/variant-analysis/skills/variant-analysis/resources/semgrep/javascript.yaml +60 -0
  285. package/skills/variant-analysis/skills/variant-analysis/resources/semgrep/python.yaml +72 -0
  286. package/skills/variant-analysis/skills/variant-analysis/resources/variant-report-template.md +75 -0
  287. package/skills/video-frames/SKILL.md +46 -0
  288. package/skills/video-frames/scripts/frame.sh +81 -0
  289. package/skills/voice-call/SKILL.md +45 -0
  290. package/skills/wacli/SKILL.md +72 -0
  291. package/skills/weather/SKILL.md +54 -0
@@ -0,0 +1,101 @@
1
+ # Local Places
2
+
3
+ This repo is a fusion of two pieces:
4
+
5
+ - A FastAPI server that exposes endpoints for searching and resolving places via the Google Maps Places API.
6
+ - A companion agent skill that explains how to use the API and can call it to find places efficiently.
7
+
8
+ Together, the skill and server let an agent turn natural-language place queries into structured results quickly.
9
+
10
+ ## Run locally
11
+
12
+ ```bash
13
+ # copy skill definition into the relevant folder (where the agent looks for it)
14
+ # then run the server
15
+
16
+ uv venv
17
+ uv pip install -e ".[dev]"
18
+ uv run --env-file .env uvicorn local_places.main:app --host 0.0.0.0 --reload
19
+ ```
20
+
21
+ Open the API docs at http://127.0.0.1:8000/docs.
22
+
23
+ ## Places API
24
+
25
+ Set the Google Places API key before running:
26
+
27
+ ```bash
28
+ export GOOGLE_PLACES_API_KEY="your-key"
29
+ ```
30
+
31
+ Endpoints:
32
+
33
+ - `POST /places/search` (free-text query + filters)
34
+ - `GET /places/{place_id}` (place details)
35
+ - `POST /locations/resolve` (resolve a user-provided location string)
36
+
37
+ Example search request:
38
+
39
+ ```json
40
+ {
41
+ "query": "italian restaurant",
42
+ "filters": {
43
+ "types": ["restaurant"],
44
+ "open_now": true,
45
+ "min_rating": 4.0,
46
+ "price_levels": [1, 2]
47
+ },
48
+ "limit": 10
49
+ }
50
+ ```
51
+
52
+ Notes:
53
+
54
+ - `filters.types` supports a single type (mapped to Google `includedType`).
55
+
56
+ Example search request (curl):
57
+
58
+ ```bash
59
+ curl -X POST http://127.0.0.1:8000/places/search \
60
+ -H "Content-Type: application/json" \
61
+ -d '{
62
+ "query": "italian restaurant",
63
+ "location_bias": {
64
+ "lat": 40.8065,
65
+ "lng": -73.9719,
66
+ "radius_m": 3000
67
+ },
68
+ "filters": {
69
+ "types": ["restaurant"],
70
+ "open_now": true,
71
+ "min_rating": 4.0,
72
+ "price_levels": [1, 2, 3]
73
+ },
74
+ "limit": 10
75
+ }'
76
+ ```
77
+
78
+ Example resolve request (curl):
79
+
80
+ ```bash
81
+ curl -X POST http://127.0.0.1:8000/locations/resolve \
82
+ -H "Content-Type: application/json" \
83
+ -d '{
84
+ "location_text": "Riverside Park, New York",
85
+ "limit": 5
86
+ }'
87
+ ```
88
+
89
+ ## Test
90
+
91
+ ```bash
92
+ uv run pytest
93
+ ```
94
+
95
+ ## OpenAPI
96
+
97
+ Generate the OpenAPI schema:
98
+
99
+ ```bash
100
+ uv run python scripts/generate_openapi.py
101
+ ```
@@ -0,0 +1,102 @@
1
+ ---
2
+ name: local-places
3
+ description: Search for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
4
+ homepage: https://github.com/Hyaxia/local_places
5
+ metadata:
6
+ {
7
+ "otto":
8
+ {
9
+ "emoji": "📍",
10
+ "requires": { "bins": ["uv"], "env": ["GOOGLE_PLACES_API_KEY"] },
11
+ "primaryEnv": "GOOGLE_PLACES_API_KEY",
12
+ },
13
+ }
14
+ ---
15
+
16
+ # 📍 Local Places
17
+
18
+ _Find places, Go fast_
19
+
20
+ Search for nearby places using a local Google Places API proxy. Two-step flow: resolve location first, then search.
21
+
22
+ ## Setup
23
+
24
+ ```bash
25
+ cd {baseDir}
26
+ echo "GOOGLE_PLACES_API_KEY=your-key" > .env
27
+ uv venv && uv pip install -e ".[dev]"
28
+ uv run --env-file .env uvicorn local_places.main:app --host 127.0.0.1 --port 8000
29
+ ```
30
+
31
+ Requires `GOOGLE_PLACES_API_KEY` in `.env` or environment.
32
+
33
+ ## Quick Start
34
+
35
+ 1. **Check server:** `curl http://127.0.0.1:8000/ping`
36
+
37
+ 2. **Resolve location:**
38
+
39
+ ```bash
40
+ curl -X POST http://127.0.0.1:8000/locations/resolve \
41
+ -H "Content-Type: application/json" \
42
+ -d '{"location_text": "Soho, London", "limit": 5}'
43
+ ```
44
+
45
+ 3. **Search places:**
46
+
47
+ ```bash
48
+ curl -X POST http://127.0.0.1:8000/places/search \
49
+ -H "Content-Type: application/json" \
50
+ -d '{
51
+ "query": "coffee shop",
52
+ "location_bias": {"lat": 51.5137, "lng": -0.1366, "radius_m": 1000},
53
+ "filters": {"open_now": true, "min_rating": 4.0},
54
+ "limit": 10
55
+ }'
56
+ ```
57
+
58
+ 4. **Get details:**
59
+
60
+ ```bash
61
+ curl http://127.0.0.1:8000/places/{place_id}
62
+ ```
63
+
64
+ ## Conversation Flow
65
+
66
+ 1. If user says "near me" or gives vague location → resolve it first
67
+ 2. If multiple results → show numbered list, ask user to pick
68
+ 3. Ask for preferences: type, open now, rating, price level
69
+ 4. Search with `location_bias` from chosen location
70
+ 5. Present results with name, rating, address, open status
71
+ 6. Offer to fetch details or refine search
72
+
73
+ ## Filter Constraints
74
+
75
+ - `filters.types`: exactly ONE type (e.g., "restaurant", "cafe", "gym")
76
+ - `filters.price_levels`: integers 0-4 (0=free, 4=very expensive)
77
+ - `filters.min_rating`: 0-5 in 0.5 increments
78
+ - `filters.open_now`: boolean
79
+ - `limit`: 1-20 for search, 1-10 for resolve
80
+ - `location_bias.radius_m`: must be > 0
81
+
82
+ ## Response Format
83
+
84
+ ```json
85
+ {
86
+ "results": [
87
+ {
88
+ "place_id": "ChIJ...",
89
+ "name": "Coffee Shop",
90
+ "address": "123 Main St",
91
+ "location": { "lat": 51.5, "lng": -0.1 },
92
+ "rating": 4.6,
93
+ "price_level": 2,
94
+ "types": ["cafe", "food"],
95
+ "open_now": true
96
+ }
97
+ ],
98
+ "next_page_token": "..."
99
+ }
100
+ ```
101
+
102
+ Use `next_page_token` as `page_token` in next request for more results.
@@ -0,0 +1,21 @@
1
+ [project]
2
+ name = "my-api"
3
+ version = "0.1.0"
4
+ description = "FastAPI server"
5
+ readme = "README.md"
6
+ requires-python = ">=3.11"
7
+ dependencies = ["fastapi>=0.110.0", "httpx>=0.27.0", "uvicorn[standard]>=0.29.0"]
8
+
9
+ [project.optional-dependencies]
10
+ dev = ["pytest>=8.0.0"]
11
+
12
+ [build-system]
13
+ requires = ["hatchling"]
14
+ build-backend = "hatchling.build"
15
+
16
+ [tool.hatch.build.targets.wheel]
17
+ packages = ["src/local_places"]
18
+
19
+ [tool.pytest.ini_options]
20
+ addopts = "-q"
21
+ testpaths = ["tests"]
@@ -0,0 +1,2 @@
1
+ __all__ = ["__version__"]
2
+ __version__ = "0.1.0"
@@ -0,0 +1,314 @@
1
+ from __future__ import annotations
2
+
3
+ import logging
4
+ import os
5
+ from typing import Any
6
+
7
+ import httpx
8
+ from fastapi import HTTPException
9
+
10
+ from local_places.schemas import (
11
+ LatLng,
12
+ LocationResolveRequest,
13
+ LocationResolveResponse,
14
+ PlaceDetails,
15
+ PlaceSummary,
16
+ ResolvedLocation,
17
+ SearchRequest,
18
+ SearchResponse,
19
+ )
20
+
21
+ GOOGLE_PLACES_BASE_URL = os.getenv(
22
+ "GOOGLE_PLACES_BASE_URL", "https://places.googleapis.com/v1"
23
+ )
24
+ logger = logging.getLogger("local_places.google_places")
25
+
26
+ _PRICE_LEVEL_TO_ENUM = {
27
+ 0: "PRICE_LEVEL_FREE",
28
+ 1: "PRICE_LEVEL_INEXPENSIVE",
29
+ 2: "PRICE_LEVEL_MODERATE",
30
+ 3: "PRICE_LEVEL_EXPENSIVE",
31
+ 4: "PRICE_LEVEL_VERY_EXPENSIVE",
32
+ }
33
+ _ENUM_TO_PRICE_LEVEL = {value: key for key, value in _PRICE_LEVEL_TO_ENUM.items()}
34
+
35
+ _SEARCH_FIELD_MASK = (
36
+ "places.id,"
37
+ "places.displayName,"
38
+ "places.formattedAddress,"
39
+ "places.location,"
40
+ "places.rating,"
41
+ "places.priceLevel,"
42
+ "places.types,"
43
+ "places.currentOpeningHours,"
44
+ "nextPageToken"
45
+ )
46
+
47
+ _DETAILS_FIELD_MASK = (
48
+ "id,"
49
+ "displayName,"
50
+ "formattedAddress,"
51
+ "location,"
52
+ "rating,"
53
+ "priceLevel,"
54
+ "types,"
55
+ "regularOpeningHours,"
56
+ "currentOpeningHours,"
57
+ "nationalPhoneNumber,"
58
+ "websiteUri"
59
+ )
60
+
61
+ _RESOLVE_FIELD_MASK = (
62
+ "places.id,"
63
+ "places.displayName,"
64
+ "places.formattedAddress,"
65
+ "places.location,"
66
+ "places.types"
67
+ )
68
+
69
+
70
+ class _GoogleResponse:
71
+ def __init__(self, response: httpx.Response):
72
+ self.status_code = response.status_code
73
+ self._response = response
74
+
75
+ def json(self) -> dict[str, Any]:
76
+ return self._response.json()
77
+
78
+ @property
79
+ def text(self) -> str:
80
+ return self._response.text
81
+
82
+
83
+ def _api_headers(field_mask: str) -> dict[str, str]:
84
+ api_key = os.getenv("GOOGLE_PLACES_API_KEY")
85
+ if not api_key:
86
+ raise HTTPException(
87
+ status_code=500,
88
+ detail="GOOGLE_PLACES_API_KEY is not set.",
89
+ )
90
+ return {
91
+ "Content-Type": "application/json",
92
+ "X-Goog-Api-Key": api_key,
93
+ "X-Goog-FieldMask": field_mask,
94
+ }
95
+
96
+
97
+ def _request(
98
+ method: str, url: str, payload: dict[str, Any] | None, field_mask: str
99
+ ) -> _GoogleResponse:
100
+ try:
101
+ with httpx.Client(timeout=10.0) as client:
102
+ response = client.request(
103
+ method=method,
104
+ url=url,
105
+ headers=_api_headers(field_mask),
106
+ json=payload,
107
+ )
108
+ except httpx.HTTPError as exc:
109
+ raise HTTPException(status_code=502, detail="Google Places API unavailable.") from exc
110
+
111
+ return _GoogleResponse(response)
112
+
113
+
114
+ def _build_text_query(request: SearchRequest) -> str:
115
+ keyword = request.filters.keyword if request.filters else None
116
+ if keyword:
117
+ return f"{request.query} {keyword}".strip()
118
+ return request.query
119
+
120
+
121
+ def _build_search_body(request: SearchRequest) -> dict[str, Any]:
122
+ body: dict[str, Any] = {
123
+ "textQuery": _build_text_query(request),
124
+ "pageSize": request.limit,
125
+ }
126
+
127
+ if request.page_token:
128
+ body["pageToken"] = request.page_token
129
+
130
+ if request.location_bias:
131
+ body["locationBias"] = {
132
+ "circle": {
133
+ "center": {
134
+ "latitude": request.location_bias.lat,
135
+ "longitude": request.location_bias.lng,
136
+ },
137
+ "radius": request.location_bias.radius_m,
138
+ }
139
+ }
140
+
141
+ if request.filters:
142
+ filters = request.filters
143
+ if filters.types:
144
+ body["includedType"] = filters.types[0]
145
+ if filters.open_now is not None:
146
+ body["openNow"] = filters.open_now
147
+ if filters.min_rating is not None:
148
+ body["minRating"] = filters.min_rating
149
+ if filters.price_levels:
150
+ body["priceLevels"] = [
151
+ _PRICE_LEVEL_TO_ENUM[level] for level in filters.price_levels
152
+ ]
153
+
154
+ return body
155
+
156
+
157
+ def _parse_lat_lng(raw: dict[str, Any] | None) -> LatLng | None:
158
+ if not raw:
159
+ return None
160
+ latitude = raw.get("latitude")
161
+ longitude = raw.get("longitude")
162
+ if latitude is None or longitude is None:
163
+ return None
164
+ return LatLng(lat=latitude, lng=longitude)
165
+
166
+
167
+ def _parse_display_name(raw: dict[str, Any] | None) -> str | None:
168
+ if not raw:
169
+ return None
170
+ return raw.get("text")
171
+
172
+
173
+ def _parse_open_now(raw: dict[str, Any] | None) -> bool | None:
174
+ if not raw:
175
+ return None
176
+ return raw.get("openNow")
177
+
178
+
179
+ def _parse_hours(raw: dict[str, Any] | None) -> list[str] | None:
180
+ if not raw:
181
+ return None
182
+ return raw.get("weekdayDescriptions")
183
+
184
+
185
+ def _parse_price_level(raw: str | None) -> int | None:
186
+ if not raw:
187
+ return None
188
+ return _ENUM_TO_PRICE_LEVEL.get(raw)
189
+
190
+
191
+ def search_places(request: SearchRequest) -> SearchResponse:
192
+ url = f"{GOOGLE_PLACES_BASE_URL}/places:searchText"
193
+ response = _request("POST", url, _build_search_body(request), _SEARCH_FIELD_MASK)
194
+
195
+ if response.status_code >= 400:
196
+ logger.error(
197
+ "Google Places API error %s. response=%s",
198
+ response.status_code,
199
+ response.text,
200
+ )
201
+ raise HTTPException(
202
+ status_code=502,
203
+ detail=f"Google Places API error ({response.status_code}).",
204
+ )
205
+
206
+ try:
207
+ payload = response.json()
208
+ except ValueError as exc:
209
+ logger.error(
210
+ "Google Places API returned invalid JSON. response=%s",
211
+ response.text,
212
+ )
213
+ raise HTTPException(status_code=502, detail="Invalid Google response.") from exc
214
+
215
+ places = payload.get("places", [])
216
+ results = []
217
+ for place in places:
218
+ results.append(
219
+ PlaceSummary(
220
+ place_id=place.get("id", ""),
221
+ name=_parse_display_name(place.get("displayName")),
222
+ address=place.get("formattedAddress"),
223
+ location=_parse_lat_lng(place.get("location")),
224
+ rating=place.get("rating"),
225
+ price_level=_parse_price_level(place.get("priceLevel")),
226
+ types=place.get("types"),
227
+ open_now=_parse_open_now(place.get("currentOpeningHours")),
228
+ )
229
+ )
230
+
231
+ return SearchResponse(
232
+ results=results,
233
+ next_page_token=payload.get("nextPageToken"),
234
+ )
235
+
236
+
237
+ def get_place_details(place_id: str) -> PlaceDetails:
238
+ url = f"{GOOGLE_PLACES_BASE_URL}/places/{place_id}"
239
+ response = _request("GET", url, None, _DETAILS_FIELD_MASK)
240
+
241
+ if response.status_code >= 400:
242
+ logger.error(
243
+ "Google Places API error %s. response=%s",
244
+ response.status_code,
245
+ response.text,
246
+ )
247
+ raise HTTPException(
248
+ status_code=502,
249
+ detail=f"Google Places API error ({response.status_code}).",
250
+ )
251
+
252
+ try:
253
+ payload = response.json()
254
+ except ValueError as exc:
255
+ logger.error(
256
+ "Google Places API returned invalid JSON. response=%s",
257
+ response.text,
258
+ )
259
+ raise HTTPException(status_code=502, detail="Invalid Google response.") from exc
260
+
261
+ return PlaceDetails(
262
+ place_id=payload.get("id", place_id),
263
+ name=_parse_display_name(payload.get("displayName")),
264
+ address=payload.get("formattedAddress"),
265
+ location=_parse_lat_lng(payload.get("location")),
266
+ rating=payload.get("rating"),
267
+ price_level=_parse_price_level(payload.get("priceLevel")),
268
+ types=payload.get("types"),
269
+ phone=payload.get("nationalPhoneNumber"),
270
+ website=payload.get("websiteUri"),
271
+ hours=_parse_hours(payload.get("regularOpeningHours")),
272
+ open_now=_parse_open_now(payload.get("currentOpeningHours")),
273
+ )
274
+
275
+
276
+ def resolve_locations(request: LocationResolveRequest) -> LocationResolveResponse:
277
+ url = f"{GOOGLE_PLACES_BASE_URL}/places:searchText"
278
+ body = {"textQuery": request.location_text, "pageSize": request.limit}
279
+ response = _request("POST", url, body, _RESOLVE_FIELD_MASK)
280
+
281
+ if response.status_code >= 400:
282
+ logger.error(
283
+ "Google Places API error %s. response=%s",
284
+ response.status_code,
285
+ response.text,
286
+ )
287
+ raise HTTPException(
288
+ status_code=502,
289
+ detail=f"Google Places API error ({response.status_code}).",
290
+ )
291
+
292
+ try:
293
+ payload = response.json()
294
+ except ValueError as exc:
295
+ logger.error(
296
+ "Google Places API returned invalid JSON. response=%s",
297
+ response.text,
298
+ )
299
+ raise HTTPException(status_code=502, detail="Invalid Google response.") from exc
300
+
301
+ places = payload.get("places", [])
302
+ results = []
303
+ for place in places:
304
+ results.append(
305
+ ResolvedLocation(
306
+ place_id=place.get("id", ""),
307
+ name=_parse_display_name(place.get("displayName")),
308
+ address=place.get("formattedAddress"),
309
+ location=_parse_lat_lng(place.get("location")),
310
+ types=place.get("types"),
311
+ )
312
+ )
313
+
314
+ return LocationResolveResponse(results=results)
@@ -0,0 +1,65 @@
1
+ import logging
2
+ import os
3
+
4
+ from fastapi import FastAPI, Request
5
+ from fastapi.encoders import jsonable_encoder
6
+ from fastapi.exceptions import RequestValidationError
7
+ from fastapi.responses import JSONResponse
8
+
9
+ from local_places.google_places import get_place_details, resolve_locations, search_places
10
+ from local_places.schemas import (
11
+ LocationResolveRequest,
12
+ LocationResolveResponse,
13
+ PlaceDetails,
14
+ SearchRequest,
15
+ SearchResponse,
16
+ )
17
+
18
+ app = FastAPI(
19
+ title="My API",
20
+ servers=[{"url": os.getenv("OPENAPI_SERVER_URL", "http://maxims-macbook-air:8000")}],
21
+ )
22
+ logger = logging.getLogger("local_places.validation")
23
+
24
+
25
+ @app.get("/ping")
26
+ def ping() -> dict[str, str]:
27
+ return {"message": "pong"}
28
+
29
+
30
+ @app.exception_handler(RequestValidationError)
31
+ async def validation_exception_handler(
32
+ request: Request, exc: RequestValidationError
33
+ ) -> JSONResponse:
34
+ logger.error(
35
+ "Validation error on %s %s. body=%s errors=%s",
36
+ request.method,
37
+ request.url.path,
38
+ exc.body,
39
+ exc.errors(),
40
+ )
41
+ return JSONResponse(
42
+ status_code=422,
43
+ content=jsonable_encoder({"detail": exc.errors()}),
44
+ )
45
+
46
+
47
+ @app.post("/places/search", response_model=SearchResponse)
48
+ def places_search(request: SearchRequest) -> SearchResponse:
49
+ return search_places(request)
50
+
51
+
52
+ @app.get("/places/{place_id}", response_model=PlaceDetails)
53
+ def places_details(place_id: str) -> PlaceDetails:
54
+ return get_place_details(place_id)
55
+
56
+
57
+ @app.post("/locations/resolve", response_model=LocationResolveResponse)
58
+ def locations_resolve(request: LocationResolveRequest) -> LocationResolveResponse:
59
+ return resolve_locations(request)
60
+
61
+
62
+ if __name__ == "__main__":
63
+ import uvicorn
64
+
65
+ uvicorn.run("local_places.main:app", host="0.0.0.0", port=8000)