enya-agent 0.1.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 (389) hide show
  1. package/.env.example +20 -0
  2. package/.github/workflows/ci.yml +70 -0
  3. package/.github/workflows/publish.yml +250 -0
  4. package/.gitmodules +3 -0
  5. package/Cargo.lock +3584 -0
  6. package/Cargo.toml +97 -0
  7. package/crates/enact/Cargo.toml +27 -0
  8. package/crates/enact/src/lib.rs +60 -0
  9. package/crates/enact-a2a/Cargo.toml +25 -0
  10. package/crates/enact-a2a/src/lib.rs +411 -0
  11. package/crates/enact-channels/Cargo.toml +64 -0
  12. package/crates/enact-channels/examples/README.md +80 -0
  13. package/crates/enact-channels/examples/channel_bot.rs +169 -0
  14. package/crates/enact-channels/examples/telegram-echo.rs +34 -0
  15. package/crates/enact-channels/examples/whatsapp-echo.rs +142 -0
  16. package/crates/enact-channels/src/config.rs +213 -0
  17. package/crates/enact-channels/src/lib.rs +25 -0
  18. package/crates/enact-channels/src/runtime.rs +237 -0
  19. package/crates/enact-channels/src/security/mod.rs +5 -0
  20. package/crates/enact-channels/src/security/pairing.rs +205 -0
  21. package/crates/enact-channels/src/teams.rs +601 -0
  22. package/crates/enact-channels/src/telegram.rs +2833 -0
  23. package/crates/enact-channels/src/traits.rs +200 -0
  24. package/crates/enact-channels/src/webhook.rs +262 -0
  25. package/crates/enact-channels/src/whatsapp.rs +310 -0
  26. package/crates/enact-cli/Cargo.toml +40 -0
  27. package/crates/enact-cli/src/commands/doctor.rs +62 -0
  28. package/crates/enact-cli/src/commands/mod.rs +3 -0
  29. package/crates/enact-cli/src/commands/run.rs +69 -0
  30. package/crates/enact-cli/src/commands/serve.rs +81 -0
  31. package/crates/enact-cli/src/config.rs +2 -0
  32. package/crates/enact-cli/src/main.rs +79 -0
  33. package/crates/enact-config/Cargo.toml +36 -0
  34. package/crates/enact-config/ENV_VAR_MAPPING.md +135 -0
  35. package/crates/enact-config/QUICK_REFERENCE.md +92 -0
  36. package/crates/enact-config/README.md +107 -0
  37. package/crates/enact-config/TESTING.md +161 -0
  38. package/crates/enact-config/examples/test-env-vars.rs +100 -0
  39. package/crates/enact-config/src/config.rs +399 -0
  40. package/crates/enact-config/src/encrypted_store.rs +211 -0
  41. package/crates/enact-config/src/lib.rs +298 -0
  42. package/crates/enact-config/src/secrets.rs +149 -0
  43. package/crates/enact-config/src/sync.rs +260 -0
  44. package/crates/enact-config/test-env-vars.sh +34 -0
  45. package/crates/enact-config/tests/README.md +99 -0
  46. package/crates/enact-config/tests/config_integration_test.rs +202 -0
  47. package/crates/enact-config/tests/security_test.rs +140 -0
  48. package/crates/enact-context/Cargo.toml +41 -0
  49. package/crates/enact-context/src/budget.rs +314 -0
  50. package/crates/enact-context/src/calibrator.rs +535 -0
  51. package/crates/enact-context/src/compactor.rs +392 -0
  52. package/crates/enact-context/src/condenser.rs +826 -0
  53. package/crates/enact-context/src/lib.rs +94 -0
  54. package/crates/enact-context/src/segment.rs +238 -0
  55. package/crates/enact-context/src/step_context.rs +645 -0
  56. package/crates/enact-context/src/token_counter.rs +148 -0
  57. package/crates/enact-context/src/window.rs +372 -0
  58. package/crates/enact-core/Cargo.toml +42 -0
  59. package/crates/enact-core/README.md +98 -0
  60. package/crates/enact-core/src/background/executor.rs +524 -0
  61. package/crates/enact-core/src/background/mod.rs +48 -0
  62. package/crates/enact-core/src/background/target_binding.rs +390 -0
  63. package/crates/enact-core/src/background/trigger.rs +511 -0
  64. package/crates/enact-core/src/callable/callable.rs +152 -0
  65. package/crates/enact-core/src/callable/composite.rs +817 -0
  66. package/crates/enact-core/src/callable/graph.rs +104 -0
  67. package/crates/enact-core/src/callable/llm.rs +211 -0
  68. package/crates/enact-core/src/callable/mod.rs +64 -0
  69. package/crates/enact-core/src/callable/registry.rs +206 -0
  70. package/crates/enact-core/src/context/execution_context.rs +757 -0
  71. package/crates/enact-core/src/context/invocation.rs +99 -0
  72. package/crates/enact-core/src/context/mod.rs +50 -0
  73. package/crates/enact-core/src/context/tenant.rs +175 -0
  74. package/crates/enact-core/src/context/trace.rs +127 -0
  75. package/crates/enact-core/src/flow/conditional.rs +293 -0
  76. package/crates/enact-core/src/flow/mod.rs +43 -0
  77. package/crates/enact-core/src/flow/parallel.rs +437 -0
  78. package/crates/enact-core/src/flow/repeat.rs +534 -0
  79. package/crates/enact-core/src/flow/sequential.rs +248 -0
  80. package/crates/enact-core/src/graph/checkpoint.rs +79 -0
  81. package/crates/enact-core/src/graph/checkpoint_store.rs +76 -0
  82. package/crates/enact-core/src/graph/compiled.rs +189 -0
  83. package/crates/enact-core/src/graph/edge.rs +59 -0
  84. package/crates/enact-core/src/graph/graph_schema.rs +218 -0
  85. package/crates/enact-core/src/graph/loader.rs +155 -0
  86. package/crates/enact-core/src/graph/mod.rs +18 -0
  87. package/crates/enact-core/src/graph/node/function.rs +49 -0
  88. package/crates/enact-core/src/graph/node/mod.rs +48 -0
  89. package/crates/enact-core/src/graph/schema.rs +62 -0
  90. package/crates/enact-core/src/inbox/message.rs +405 -0
  91. package/crates/enact-core/src/inbox/mod.rs +31 -0
  92. package/crates/enact-core/src/inbox/store.rs +355 -0
  93. package/crates/enact-core/src/kernel/artifact/filesystem.rs +546 -0
  94. package/crates/enact-core/src/kernel/artifact/metadata.rs +283 -0
  95. package/crates/enact-core/src/kernel/artifact/mod.rs +27 -0
  96. package/crates/enact-core/src/kernel/artifact/store.rs +427 -0
  97. package/crates/enact-core/src/kernel/enforcement.rs +1315 -0
  98. package/crates/enact-core/src/kernel/error.rs +1200 -0
  99. package/crates/enact-core/src/kernel/event.rs +1394 -0
  100. package/crates/enact-core/src/kernel/execution_model.rs +831 -0
  101. package/crates/enact-core/src/kernel/execution_state.rs +189 -0
  102. package/crates/enact-core/src/kernel/execution_strategy.rs +117 -0
  103. package/crates/enact-core/src/kernel/ids.rs +2086 -0
  104. package/crates/enact-core/src/kernel/interrupt.rs +125 -0
  105. package/crates/enact-core/src/kernel/kernel.rs +1283 -0
  106. package/crates/enact-core/src/kernel/mod.rs +205 -0
  107. package/crates/enact-core/src/kernel/persistence/event_store.rs +270 -0
  108. package/crates/enact-core/src/kernel/persistence/message_store.rs +908 -0
  109. package/crates/enact-core/src/kernel/persistence/mod.rs +102 -0
  110. package/crates/enact-core/src/kernel/persistence/state_store.rs +228 -0
  111. package/crates/enact-core/src/kernel/persistence/vector_store.rs +299 -0
  112. package/crates/enact-core/src/kernel/reducer.rs +808 -0
  113. package/crates/enact-core/src/kernel/replay.rs +153 -0
  114. package/crates/enact-core/src/lib.rs +413 -0
  115. package/crates/enact-core/src/memory/episodic.rs +0 -0
  116. package/crates/enact-core/src/memory/mod.rs +6 -0
  117. package/crates/enact-core/src/memory/semantic.rs +0 -0
  118. package/crates/enact-core/src/memory/trait.rs +0 -0
  119. package/crates/enact-core/src/memory/vector_db.rs +0 -0
  120. package/crates/enact-core/src/memory/working.rs +0 -0
  121. package/crates/enact-core/src/policy/execution_policy.rs +292 -0
  122. package/crates/enact-core/src/policy/filters.rs +458 -0
  123. package/crates/enact-core/src/policy/input_processor.rs +407 -0
  124. package/crates/enact-core/src/policy/long_running.rs +134 -0
  125. package/crates/enact-core/src/policy/mod.rs +193 -0
  126. package/crates/enact-core/src/policy/pii_input.rs +274 -0
  127. package/crates/enact-core/src/policy/tenant_policy.rs +453 -0
  128. package/crates/enact-core/src/policy/tool_policy.rs +407 -0
  129. package/crates/enact-core/src/providers/mod.rs +63 -0
  130. package/crates/enact-core/src/providers/trait.rs +292 -0
  131. package/crates/enact-core/src/runner/callbacks.rs +6 -0
  132. package/crates/enact-core/src/runner/execution_runner.rs +476 -0
  133. package/crates/enact-core/src/runner/loop.rs +117 -0
  134. package/crates/enact-core/src/runner/mod.rs +58 -0
  135. package/crates/enact-core/src/runner/protected_runner.rs +280 -0
  136. package/crates/enact-core/src/signal/inmemory.rs +231 -0
  137. package/crates/enact-core/src/signal/mod.rs +108 -0
  138. package/crates/enact-core/src/streaming/event_logger.rs +195 -0
  139. package/crates/enact-core/src/streaming/event_stream.rs +1423 -0
  140. package/crates/enact-core/src/streaming/mod.rs +108 -0
  141. package/crates/enact-core/src/streaming/pause_cancel.rs +0 -0
  142. package/crates/enact-core/src/streaming/protected_emitter.rs +173 -0
  143. package/crates/enact-core/src/streaming/protection/context.rs +136 -0
  144. package/crates/enact-core/src/streaming/protection/encryption.rs +289 -0
  145. package/crates/enact-core/src/streaming/protection/mod.rs +43 -0
  146. package/crates/enact-core/src/streaming/protection/pii_protection.rs +243 -0
  147. package/crates/enact-core/src/streaming/protection/processor.rs +166 -0
  148. package/crates/enact-core/src/streaming/sse.rs +0 -0
  149. package/crates/enact-core/src/telemetry/exporter.rs +0 -0
  150. package/crates/enact-core/src/telemetry/init.rs +0 -0
  151. package/crates/enact-core/src/telemetry/mod.rs +49 -0
  152. package/crates/enact-core/src/telemetry/spans.rs +245 -0
  153. package/crates/enact-core/src/tool/agent_tool.rs +177 -0
  154. package/crates/enact-core/src/tool/browser/mod.rs +0 -0
  155. package/crates/enact-core/src/tool/browser/webdriver.rs +0 -0
  156. package/crates/enact-core/src/tool/cost.rs +247 -0
  157. package/crates/enact-core/src/tool/discovery.rs +0 -0
  158. package/crates/enact-core/src/tool/dispatcher.rs +347 -0
  159. package/crates/enact-core/src/tool/filesystem.rs +231 -0
  160. package/crates/enact-core/src/tool/function.rs +99 -0
  161. package/crates/enact-core/src/tool/git.rs +162 -0
  162. package/crates/enact-core/src/tool/http.rs +214 -0
  163. package/crates/enact-core/src/tool/mcp/client.rs +0 -0
  164. package/crates/enact-core/src/tool/mcp/mod.rs +0 -0
  165. package/crates/enact-core/src/tool/mod.rs +51 -0
  166. package/crates/enact-core/src/tool/reasoning/debugging.rs +0 -0
  167. package/crates/enact-core/src/tool/reasoning/mcts.rs +0 -0
  168. package/crates/enact-core/src/tool/reasoning/mod.rs +0 -0
  169. package/crates/enact-core/src/tool/reasoning/sequential.rs +0 -0
  170. package/crates/enact-core/src/tool/sandbox/dagger.rs +0 -0
  171. package/crates/enact-core/src/tool/sandbox/mod.rs +0 -0
  172. package/crates/enact-core/src/tool/shell.rs +147 -0
  173. package/crates/enact-core/src/tool/trait.rs +33 -0
  174. package/crates/enact-core/src/tool/web_search.rs +277 -0
  175. package/crates/enact-core/src/util/config.rs +0 -0
  176. package/crates/enact-core/src/util/errors.rs +0 -0
  177. package/crates/enact-core/src/util/mod.rs +6 -0
  178. package/crates/enact-core/tests/airgapped_e2e_test.rs +291 -0
  179. package/crates/enact-core/tests/e2e_agentic_loop.rs +119 -0
  180. package/crates/enact-core/tests/e2e_test.rs +259 -0
  181. package/crates/enact-core/tests/graph_test.rs +130 -0
  182. package/crates/enact-core/tests/stream_event_id_validation.rs +435 -0
  183. package/crates/enact-cron/Cargo.toml +28 -0
  184. package/crates/enact-cron/src/lib.rs +44 -0
  185. package/crates/enact-cron/src/schedule.rs +156 -0
  186. package/crates/enact-cron/src/store.rs +589 -0
  187. package/crates/enact-cron/src/types.rs +148 -0
  188. package/crates/enact-gateway/Cargo.toml +31 -0
  189. package/crates/enact-gateway/README.md +30 -0
  190. package/crates/enact-gateway/examples/whatsapp-gateway-runner-mock.rs +59 -0
  191. package/crates/enact-gateway/examples/whatsapp-gateway.rs +42 -0
  192. package/crates/enact-gateway/src/lib.rs +582 -0
  193. package/crates/enact-mcp/Cargo.toml +24 -0
  194. package/crates/enact-mcp/src/lib.rs +178 -0
  195. package/crates/enact-memory/Cargo.toml +25 -0
  196. package/crates/enact-memory/src/backend.rs +20 -0
  197. package/crates/enact-memory/src/chunker.rs +230 -0
  198. package/crates/enact-memory/src/embeddings.rs +221 -0
  199. package/crates/enact-memory/src/lib.rs +67 -0
  200. package/crates/enact-memory/src/markdown.rs +127 -0
  201. package/crates/enact-memory/src/none.rs +61 -0
  202. package/crates/enact-memory/src/sqlite.rs +276 -0
  203. package/crates/enact-memory/src/traits.rs +65 -0
  204. package/crates/enact-memory/src/vector.rs +198 -0
  205. package/crates/enact-oauth/Cargo.toml +27 -0
  206. package/crates/enact-oauth/src/lib.rs +584 -0
  207. package/crates/enact-observability/Cargo.toml +22 -0
  208. package/crates/enact-observability/src/lib.rs +197 -0
  209. package/crates/enact-providers/Cargo.toml +33 -0
  210. package/crates/enact-providers/examples/hello-agent.rs +33 -0
  211. package/crates/enact-providers/src/anthropic.rs +182 -0
  212. package/crates/enact-providers/src/azure.rs +96 -0
  213. package/crates/enact-providers/src/bridge.rs +221 -0
  214. package/crates/enact-providers/src/gemini.rs +227 -0
  215. package/crates/enact-providers/src/http.rs +78 -0
  216. package/crates/enact-providers/src/lib.rs +53 -0
  217. package/crates/enact-providers/src/openai_compatible.rs +167 -0
  218. package/crates/enact-providers/src/openrouter.rs +33 -0
  219. package/crates/enact-runner/Cargo.toml +24 -0
  220. package/crates/enact-runner/README.md +76 -0
  221. package/crates/enact-runner/src/compaction.rs +225 -0
  222. package/crates/enact-runner/src/config.rs +118 -0
  223. package/crates/enact-runner/src/lib.rs +63 -0
  224. package/crates/enact-runner/src/loop_driver.rs +414 -0
  225. package/crates/enact-runner/src/parser.rs +421 -0
  226. package/crates/enact-runner/src/retry.rs +262 -0
  227. package/crates/enact-runner/tests/integration.rs +278 -0
  228. package/crates/enact-security/Cargo.toml +22 -0
  229. package/crates/enact-security/src/audit.rs +375 -0
  230. package/crates/enact-security/src/lib.rs +37 -0
  231. package/crates/enact-security/src/policy.rs +406 -0
  232. package/crates/enact-skills/Cargo.toml +25 -0
  233. package/crates/enact-skills/src/lib.rs +506 -0
  234. package/crates/enact-tools/Cargo.toml +22 -0
  235. package/crates/enact-tools/src/file_read.rs +166 -0
  236. package/crates/enact-tools/src/file_write.rs +216 -0
  237. package/crates/enact-tools/src/git_operations.rs +513 -0
  238. package/crates/enact-tools/src/http_request.rs +417 -0
  239. package/crates/enact-tools/src/lib.rs +104 -0
  240. package/crates/enact-tools/src/security.rs +227 -0
  241. package/crates/enact-tools/src/shell.rs +191 -0
  242. package/crates/enact-tools/src/traits.rs +159 -0
  243. package/docs/Makefile +74 -0
  244. package/docs/config.toml +62 -0
  245. package/docs/content/_index.md +174 -0
  246. package/docs/content/a2a/_index.md +431 -0
  247. package/docs/content/api/_index.md +323 -0
  248. package/docs/content/channels/_index.md +160 -0
  249. package/docs/content/channels/teams.md +205 -0
  250. package/docs/content/channels/telegram.md +182 -0
  251. package/docs/content/channels/webhook.md +423 -0
  252. package/docs/content/channels/whatsapp.md +240 -0
  253. package/docs/content/cli/_index.md +261 -0
  254. package/docs/content/concepts/_index.md +273 -0
  255. package/docs/content/configuration/_index.md +241 -0
  256. package/docs/content/cron/_index.md +248 -0
  257. package/docs/content/developers/_index.md +278 -0
  258. package/docs/content/getting-started/_index.md +180 -0
  259. package/docs/content/installation/_index.md +186 -0
  260. package/docs/content/installation/uninstall.md +101 -0
  261. package/docs/content/installation/updating.md +120 -0
  262. package/docs/content/mcp/_index.md +215 -0
  263. package/docs/content/memory/_index.md +163 -0
  264. package/docs/content/oauth/_index.md +515 -0
  265. package/docs/content/providers/_index.md +206 -0
  266. package/docs/content/roadmap/_index.md +199 -0
  267. package/docs/content/security/_index.md +219 -0
  268. package/docs/content/skills/_index.md +228 -0
  269. package/docs/content/tools/_index.md +485 -0
  270. package/docs/content/troubleshooting/_index.md +259 -0
  271. package/docs/content/yaml-schema/_index.md +294 -0
  272. package/docs/static/giallo-dark.css +91 -0
  273. package/docs/static/giallo-light.css +91 -0
  274. package/docs/themes/tanuki/.github/workflows/deploy.yml +44 -0
  275. package/docs/themes/tanuki/LICENSE +21 -0
  276. package/docs/themes/tanuki/README.md +166 -0
  277. package/docs/themes/tanuki/examples/blog/config.toml +58 -0
  278. package/docs/themes/tanuki/examples/blog/content/_index.md +4 -0
  279. package/docs/themes/tanuki/examples/blog/content/about.md +33 -0
  280. package/docs/themes/tanuki/examples/blog/content/blog/_index.md +7 -0
  281. package/docs/themes/tanuki/examples/blog/content/blog/api-design-best-practices.md +245 -0
  282. package/docs/themes/tanuki/examples/blog/content/blog/building-accessible-websites.md +147 -0
  283. package/docs/themes/tanuki/examples/blog/content/blog/css-grid-vs-flexbox.md +165 -0
  284. package/docs/themes/tanuki/examples/blog/content/blog/customizing-catppuccin-colors.md +137 -0
  285. package/docs/themes/tanuki/examples/blog/content/blog/dark-mode-best-practices.md +82 -0
  286. package/docs/themes/tanuki/examples/blog/content/blog/docker-essentials.md +301 -0
  287. package/docs/themes/tanuki/examples/blog/content/blog/getting-started-with-zola.md +129 -0
  288. package/docs/themes/tanuki/examples/blog/content/blog/git-workflow-for-content.md +112 -0
  289. package/docs/themes/tanuki/examples/blog/content/blog/introduction-to-webassembly.md +183 -0
  290. package/docs/themes/tanuki/examples/blog/content/blog/modern-javascript-features.md +234 -0
  291. package/docs/themes/tanuki/examples/blog/content/blog/testing-strategies.md +311 -0
  292. package/docs/themes/tanuki/examples/blog/content/blog/typography-for-developers.md +104 -0
  293. package/docs/themes/tanuki/examples/blog/content/blog/welcome-to-tanuki.md +67 -0
  294. package/docs/themes/tanuki/examples/blog/content/blog/why-static-sites.md +85 -0
  295. package/docs/themes/tanuki/examples/blog/content/projects.md +64 -0
  296. package/docs/themes/tanuki/examples/book/config.toml +17 -0
  297. package/docs/themes/tanuki/examples/book/content/_index.md +12 -0
  298. package/docs/themes/tanuki/examples/book/content/chapter-1.md +90 -0
  299. package/docs/themes/tanuki/examples/book/content/chapter-2.md +143 -0
  300. package/docs/themes/tanuki/examples/book/content/chapter-3.md +217 -0
  301. package/docs/themes/tanuki/examples/book/content/chapter-4.md +224 -0
  302. package/docs/themes/tanuki/examples/book/content/chapter-5.md +297 -0
  303. package/docs/themes/tanuki/examples/book/content/print.md +6 -0
  304. package/docs/themes/tanuki/examples/docs/config.toml +28 -0
  305. package/docs/themes/tanuki/examples/docs/content/_index.md +20 -0
  306. package/docs/themes/tanuki/examples/docs/content/components.md +156 -0
  307. package/docs/themes/tanuki/examples/docs/content/configuration.md +94 -0
  308. package/docs/themes/tanuki/examples/docs/content/customization.md +202 -0
  309. package/docs/themes/tanuki/examples/docs/content/deployment.md +204 -0
  310. package/docs/themes/tanuki/examples/docs/content/installation.md +59 -0
  311. package/docs/themes/tanuki/examples/docs/content/print.md +6 -0
  312. package/docs/themes/tanuki/examples/docs/static/img/tanuki-icon.avif +0 -0
  313. package/docs/themes/tanuki/examples/index.html +2104 -0
  314. package/docs/themes/tanuki/mise.toml +108 -0
  315. package/docs/themes/tanuki/sass/base/_catppuccin.scss +164 -0
  316. package/docs/themes/tanuki/sass/base/_fonts.scss +64 -0
  317. package/docs/themes/tanuki/sass/base/_reset.scss +152 -0
  318. package/docs/themes/tanuki/sass/base/_typography.scss +523 -0
  319. package/docs/themes/tanuki/sass/components/_buttons.scss +209 -0
  320. package/docs/themes/tanuki/sass/components/_code.scss +457 -0
  321. package/docs/themes/tanuki/sass/components/_landing.scss +633 -0
  322. package/docs/themes/tanuki/sass/components/_layout.scss +294 -0
  323. package/docs/themes/tanuki/sass/components/_navigation.scss +1200 -0
  324. package/docs/themes/tanuki/sass/components/_print.scss +237 -0
  325. package/docs/themes/tanuki/sass/components/_search.scss +224 -0
  326. package/docs/themes/tanuki/sass/components/_sidebar.scss +473 -0
  327. package/docs/themes/tanuki/sass/components/_theme-toggle.scss +186 -0
  328. package/docs/themes/tanuki/sass/modes/_blog.scss +366 -0
  329. package/docs/themes/tanuki/sass/modes/_product.scss +875 -0
  330. package/docs/themes/tanuki/sass/modes/_raskell.scss +1696 -0
  331. package/docs/themes/tanuki/sass/patterns/_buttons.scss +183 -0
  332. package/docs/themes/tanuki/sass/patterns/_cards.scss +144 -0
  333. package/docs/themes/tanuki/sass/patterns/_index.scss +9 -0
  334. package/docs/themes/tanuki/sass/patterns/_lists.scss +259 -0
  335. package/docs/themes/tanuki/sass/patterns/_sections.scss +243 -0
  336. package/docs/themes/tanuki/sass/style.scss +47 -0
  337. package/docs/themes/tanuki/sass/tokens/_colors.scss +139 -0
  338. package/docs/themes/tanuki/sass/tokens/_spacing.scss +100 -0
  339. package/docs/themes/tanuki/sass/tokens/_typography.scss +186 -0
  340. package/docs/themes/tanuki/screenshot.png +0 -0
  341. package/docs/themes/tanuki/sentinel.kdl +59 -0
  342. package/docs/themes/tanuki/static/elasticlunr.min.js +10 -0
  343. package/docs/themes/tanuki/static/fonts/GEIST-LICENSE.txt +92 -0
  344. package/docs/themes/tanuki/static/fonts/Geist-Variable.woff2 +0 -0
  345. package/docs/themes/tanuki/static/fonts/GeistMono-Variable.woff2 +0 -0
  346. package/docs/themes/tanuki/static/img/tanuki-icon.avif +0 -0
  347. package/docs/themes/tanuki/static/img/tanuki-icon.png +0 -0
  348. package/docs/themes/tanuki/static/js/anchors.js +18 -0
  349. package/docs/themes/tanuki/static/js/app.js +274 -0
  350. package/docs/themes/tanuki/static/js/code.js +394 -0
  351. package/docs/themes/tanuki/static/js/navigation.js +778 -0
  352. package/docs/themes/tanuki/static/js/scroll-to-top.js +33 -0
  353. package/docs/themes/tanuki/static/js/search-raskell.js +240 -0
  354. package/docs/themes/tanuki/static/js/search.js +215 -0
  355. package/docs/themes/tanuki/static/js/theme.js +169 -0
  356. package/docs/themes/tanuki/static/syntax-dark.css +151 -0
  357. package/docs/themes/tanuki/static/syntax-light.css +151 -0
  358. package/docs/themes/tanuki/static/wasm/sentinel_playground_wasm.js +486 -0
  359. package/docs/themes/tanuki/static/wasm/sentinel_playground_wasm_bg.wasm +0 -0
  360. package/docs/themes/tanuki/templates/404.html +52 -0
  361. package/docs/themes/tanuki/templates/base.html +428 -0
  362. package/docs/themes/tanuki/templates/blog.html +66 -0
  363. package/docs/themes/tanuki/templates/home.html +108 -0
  364. package/docs/themes/tanuki/templates/index.html +178 -0
  365. package/docs/themes/tanuki/templates/landing.html +168 -0
  366. package/docs/themes/tanuki/templates/macros/nav.html +128 -0
  367. package/docs/themes/tanuki/templates/macros/posts.html +101 -0
  368. package/docs/themes/tanuki/templates/macros/ui.html +159 -0
  369. package/docs/themes/tanuki/templates/page.html +135 -0
  370. package/docs/themes/tanuki/templates/partials/footer.html +38 -0
  371. package/docs/themes/tanuki/templates/partials/header.html +366 -0
  372. package/docs/themes/tanuki/templates/partials/nav-buttons.html +55 -0
  373. package/docs/themes/tanuki/templates/partials/nav-overlay.html +81 -0
  374. package/docs/themes/tanuki/templates/partials/page-toc-panel.html +43 -0
  375. package/docs/themes/tanuki/templates/partials/search.html +52 -0
  376. package/docs/themes/tanuki/templates/partials/sidebar.html +107 -0
  377. package/docs/themes/tanuki/templates/partials/theme-toggle.html +35 -0
  378. package/docs/themes/tanuki/templates/partials/toc-overlay.html +146 -0
  379. package/docs/themes/tanuki/templates/partials/version-picker.html +38 -0
  380. package/docs/themes/tanuki/templates/print.html +244 -0
  381. package/docs/themes/tanuki/templates/section.html +186 -0
  382. package/docs/themes/tanuki/templates/taxonomy_list.html +18 -0
  383. package/docs/themes/tanuki/templates/taxonomy_single.html +31 -0
  384. package/docs/themes/tanuki/theme.toml +58 -0
  385. package/examples/hello-agent.rs +55 -0
  386. package/package.json +36 -0
  387. package/proto/config.proto +60 -0
  388. package/proto/events.proto +0 -0
  389. package/proto/runtime.proto +215 -0
@@ -0,0 +1,91 @@
1
+ /*
2
+ * theme "github-light" generated by giallo
3
+ */
4
+
5
+ .z-code {
6
+ color: #24292E;
7
+ background-color: #FFFFFF;
8
+ }
9
+
10
+ .z-hl {
11
+ background-color: #F6F8FA;
12
+ }
13
+
14
+ .giallo-ln {
15
+ color: #1B1F234D;
16
+ }
17
+
18
+ .z-comment { color: #6A737D; }
19
+ .z-constant { color: #005CC5; }
20
+ .z-entity { color: #6F42C1; }
21
+ .z-keyword { color: #D73A49; }
22
+ .z-storage { color: #D73A49; }
23
+ .z-string { color: #032F62; }
24
+ .z-support { color: #005CC5; }
25
+ .z-variable { color: #E36209; }
26
+ .z-carriage-return { color: #FAFBFC; background-color: #D73A49; font-style: italic;text-decoration: underline; }
27
+ .z-variable { color: #005CC5; }
28
+ .z-source { color: #032F62; }
29
+ .z-string.z-comment { color: #6A737D; }
30
+ .z-variable.z-language { color: #005CC5; }
31
+ .z-entity.z-name { color: #6F42C1; }
32
+ .z-storage.z-type { color: #D73A49; }
33
+ .z-meta.z-property-name { color: #005CC5; }
34
+ .z-variable.z-other { color: #24292E; }
35
+ .z-invalid.z-broken { color: #B31D28; font-style: italic; }
36
+ .z-invalid.z-deprecated { color: #B31D28; font-style: italic; }
37
+ .z-invalid.z-illegal { color: #B31D28; font-style: italic; }
38
+ .z-invalid.z-unimplemented { color: #B31D28; font-style: italic; }
39
+ .z-message.z-error { color: #B31D28; }
40
+ .z-source.z-regexp { color: #032F62; }
41
+ .z-string.z-regexp { color: #032F62; }
42
+ .z-support.z-constant { color: #005CC5; }
43
+ .z-support.z-variable { color: #005CC5; }
44
+ .z-meta.z-module-reference { color: #005CC5; }
45
+ .z-markup.z-heading { color: #005CC5; font-weight: bold; }
46
+ .z-markup.z-quote { color: #22863A; }
47
+ .z-markup.z-italic { color: #24292E; font-style: italic; }
48
+ .z-markup.z-bold { color: #24292E; font-weight: bold; }
49
+ .z-markup.z-underline { text-decoration: underline; }
50
+ .z-markup.z-strikethrough { text-decoration: line-through; }
51
+ .z-markup.z-deleted { color: #B31D28; background-color: #FFEEF0; }
52
+ .z-markup.z-inserted { color: #22863A; background-color: #F0FFF4; }
53
+ .z-markup.z-changed { color: #E36209; background-color: #FFEBDA; }
54
+ .z-markup.z-ignored { color: #F6F8FA; background-color: #005CC5; }
55
+ .z-markup.z-untracked { color: #F6F8FA; background-color: #005CC5; }
56
+ .z-meta.z-separator { color: #005CC5; font-weight: bold; }
57
+ .z-meta.z-output { color: #005CC5; }
58
+ .z-brackethighlighter.z-tag { color: #586069; }
59
+ .z-brackethighlighter.z-curly { color: #586069; }
60
+ .z-brackethighlighter.z-round { color: #586069; }
61
+ .z-brackethighlighter.z-square { color: #586069; }
62
+ .z-brackethighlighter.z-angle { color: #586069; }
63
+ .z-brackethighlighter.z-quote { color: #586069; }
64
+ .z-brackethighlighter.z-unmatched { color: #B31D28; }
65
+ .z-entity.z-name { color: #005CC5; font-weight: bold; }
66
+ .z-punctuation.z-definition.z-comment { color: #6A737D; }
67
+ .z-entity.z-name.z-constant { color: #005CC5; }
68
+ .z-variable.z-other.z-constant { color: #005CC5; }
69
+ .z-variable.z-other.z-enummember { color: #005CC5; }
70
+ .z-variable.z-parameter.z-function { color: #24292E; }
71
+ .z-entity.z-name.z-tag { color: #22863A; }
72
+ .z-storage.z-modifier.z-package { color: #24292E; }
73
+ .z-storage.z-modifier.z-import { color: #24292E; }
74
+ .z-storage.z-type.z-java { color: #24292E; }
75
+ .z-punctuation.z-definition.z-string { color: #032F62; }
76
+ .z-string.z-regexp.z-character-class { color: #032F62; }
77
+ .z-markup.z-inline.z-raw { color: #005CC5; }
78
+ .z-punctuation.z-definition.z-deleted { color: #B31D28; background-color: #FFEEF0; }
79
+ .z-punctuation.z-definition.z-inserted { color: #22863A; background-color: #F0FFF4; }
80
+ .z-punctuation.z-definition.z-changed { color: #E36209; background-color: #FFEBDA; }
81
+ .z-meta.z-diff.z-range { color: #6F42C1; font-weight: bold; }
82
+ .z-meta.z-diff.z-header { color: #005CC5; }
83
+ .z-string.z-other.z-link { color: #032F62; text-decoration: underline; }
84
+ .z-constant.z-character.z-escape { color: #032F62; }
85
+ .z-source.z-ruby.z-embedded { color: #032F62; }
86
+ .z-string.z-regexp.z-arbitrary-repitition { color: #032F62; }
87
+ .z-constant.z-character.z-escape { color: #22863A; font-weight: bold; }
88
+ .z-meta.z-diff.z-header.z-from-file { color: #B31D28; background-color: #FFEEF0; }
89
+ .z-meta.z-diff.z-header.z-to-file { color: #22863A; background-color: #F0FFF4; }
90
+ .z-constant.z-other.z-reference.z-link { color: #032F62; text-decoration: underline; }
91
+ .z-punctuation.z-definition.z-list.z-begin.z-markdown { color: #E36209; }
@@ -0,0 +1,44 @@
1
+ name: Deploy to GitHub Pages
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ workflow_dispatch:
7
+
8
+ permissions:
9
+ contents: read
10
+ pages: write
11
+ id-token: write
12
+
13
+ concurrency:
14
+ group: "pages"
15
+ cancel-in-progress: false
16
+
17
+ jobs:
18
+ build:
19
+ runs-on: ubuntu-latest
20
+ steps:
21
+ - name: Checkout
22
+ uses: actions/checkout@v4
23
+
24
+ - name: Install mise
25
+ uses: jdx/mise-action@v2
26
+
27
+ - name: Build all examples
28
+ run: mise run build
29
+
30
+ - name: Upload artifact
31
+ uses: actions/upload-pages-artifact@v3
32
+ with:
33
+ path: ./public
34
+
35
+ deploy:
36
+ environment:
37
+ name: github-pages
38
+ url: ${{ steps.deployment.outputs.page_url }}
39
+ runs-on: ubuntu-latest
40
+ needs: build
41
+ steps:
42
+ - name: Deploy to GitHub Pages
43
+ id: deployment
44
+ uses: actions/deploy-pages@v4
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Raffael Schneider / raskell.io
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,166 @@
1
+ <div align="center">
2
+
3
+ <h1 align="center">
4
+ <img src="static/img/tanuki-icon.png" alt="tanuki mascot" width="96" />
5
+ <br>
6
+ Tanuki
7
+ </h1>
8
+
9
+ <p align="center">
10
+ <em>An opinionated Zola theme for documentation, books, and blogs.</em><br>
11
+ <em>Beautiful, accessible, and thoughtfully designed.</em>
12
+ </p>
13
+
14
+ <p align="center">
15
+ <a href="https://www.getzola.org/">
16
+ <img alt="Zola" src="https://img.shields.io/badge/Zola-0.19+-000000?logo=zola&logoColor=white&style=for-the-badge">
17
+ </a>
18
+ <a href="https://catppuccin.com/">
19
+ <img alt="Catppuccin" src="https://img.shields.io/badge/Catppuccin-cba6f7?style=for-the-badge">
20
+ </a>
21
+ <a href="LICENSE">
22
+ <img alt="License" src="https://img.shields.io/badge/License-MIT-a6e3a1?style=for-the-badge">
23
+ </a>
24
+ </p>
25
+
26
+ <p align="center">
27
+ <a href="https://tanuki.raskell.io">Live Demo</a> •
28
+ <a href="https://tanuki.raskell.io/docs/">Documentation</a> •
29
+ <a href="https://tanuki.raskell.io/book/">Book Example</a> •
30
+ <a href="https://tanuki.raskell.io/blog/">Blog Example</a>
31
+ </p>
32
+
33
+ <hr />
34
+
35
+ </div>
36
+
37
+ ![Tanuki Theme](screenshot.png)
38
+
39
+ ## Features
40
+
41
+ - **Three Modes** — Documentation (with versioning), Book, and Blog layouts
42
+ - **Catppuccin Colors** — Soothing Mocha (dark) and Latte (light) palettes
43
+ - **Geist Typography** — Clean, readable variable fonts
44
+ - **Lucide Icons** — Crisp, consistent iconography
45
+ - **Resizable Sidebar** — Drag to resize, persists across sessions
46
+ - **Full-text Search** — Elasticlunr-powered instant search
47
+ - **Dark/Light Toggle** — Three-way toggle with system preference detection
48
+ - **Print Support** — Print all pages as a single document (docs/book modes)
49
+ - **Keyboard Navigation** — Arrow keys for prev/next, `/` for search
50
+ - **SEO & Accessibility** — JSON-LD structured data, ARIA landmarks, semantic HTML
51
+
52
+ ## Installation
53
+
54
+ ```bash
55
+ cd your-zola-site
56
+ git clone https://github.com/raskell-io/tanuki themes/tanuki
57
+ ```
58
+
59
+ Or as a git submodule:
60
+
61
+ ```bash
62
+ git submodule add https://github.com/raskell-io/tanuki themes/tanuki
63
+ ```
64
+
65
+ ## Quick Start
66
+
67
+ ### Documentation Mode
68
+
69
+ ```toml
70
+ base_url = "https://docs.example.com"
71
+ title = "My Project Docs"
72
+ theme = "tanuki"
73
+ build_search_index = true
74
+
75
+ [markdown]
76
+ highlight_code = true
77
+ highlight_theme = "css"
78
+
79
+ [extra]
80
+ mode = "docs"
81
+ github = "https://github.com/you/project"
82
+
83
+ # Optional: version picker
84
+ [extra.versions]
85
+ current = "2.0.0"
86
+ list = [
87
+ { version = "2.0.0", url = "/", label = "latest" },
88
+ { version = "1.0.0", url = "/v1/" },
89
+ ]
90
+ ```
91
+
92
+ ### Book Mode
93
+
94
+ ```toml
95
+ base_url = "https://book.example.com"
96
+ title = "The Complete Guide"
97
+ theme = "tanuki"
98
+ build_search_index = true
99
+
100
+ [markdown]
101
+ highlight_code = true
102
+ highlight_theme = "css"
103
+
104
+ [extra]
105
+ mode = "book"
106
+ github = "https://github.com/you/book"
107
+ ```
108
+
109
+ ### Blog Mode
110
+
111
+ ```toml
112
+ base_url = "https://blog.example.com"
113
+ title = "My Blog"
114
+ theme = "tanuki"
115
+ generate_feeds = true
116
+
117
+ taxonomies = [
118
+ { name = "tags", feed = true },
119
+ ]
120
+
121
+ [markdown]
122
+ highlight_code = true
123
+ highlight_theme = "css"
124
+
125
+ [extra]
126
+ mode = "blog"
127
+
128
+ [extra.hero]
129
+ title = "Welcome to my blog"
130
+ subtitle = "Thoughts on code and craft"
131
+
132
+ [[extra.nav]]
133
+ name = "Blog"
134
+ url = "/blog/"
135
+
136
+ [[extra.nav]]
137
+ name = "About"
138
+ url = "/about/"
139
+ ```
140
+
141
+ ## Keyboard Shortcuts
142
+
143
+ | Key | Action |
144
+ |-----|--------|
145
+ | `←` / `→` | Previous / Next page |
146
+ | `/` | Open search |
147
+ | `Esc` | Close overlays |
148
+
149
+ ## Browser Support
150
+
151
+ Modern browsers (Chrome 88+, Firefox 78+, Safari 14+, Edge 88+)
152
+
153
+ ## Credits
154
+
155
+ - [Catppuccin](https://catppuccin.com) — Color palette
156
+ - [Geist](https://vercel.com/font) — Typography
157
+ - [Lucide](https://lucide.dev) — Icons
158
+ - [Zola](https://www.getzola.org) — Static site generator
159
+
160
+ ## License
161
+
162
+ [MIT](LICENSE)
163
+
164
+ ---
165
+
166
+ <p align="center">Made with care by <a href="https://raskell.io">raskell.io</a></p>
@@ -0,0 +1,58 @@
1
+ # Tanuki Theme - Blog/Personal Site Example
2
+ base_url = "/tanuki/blog"
3
+ title = "Alex Chen"
4
+ description = "Software developer writing about web technologies, design, and the craft of building things."
5
+ theme = "tanuki"
6
+ compile_sass = true
7
+ build_search_index = true
8
+ generate_feeds = true
9
+ feed_filenames = ["rss.xml"]
10
+
11
+ taxonomies = [
12
+ { name = "tags", feed = true },
13
+ ]
14
+
15
+ [markdown]
16
+ highlight_code = true
17
+ highlight_theme = "base16-ocean-dark"
18
+
19
+ [extra]
20
+ mode = "blog"
21
+ show_theme_toggle = true
22
+ show_about_section = true
23
+
24
+ # Author info
25
+ [extra.author]
26
+ name = "Alex Chen"
27
+ bio = "Software developer and open source enthusiast."
28
+ # avatar = "images/avatar.jpg"
29
+
30
+ # Hero section
31
+ [extra.hero]
32
+ title = "Hey, I'm Alex"
33
+ subtitle = "I build things for the web and write about what I learn along the way."
34
+ [extra.hero.cta]
35
+ text = "Read the blog"
36
+ url = "/tanuki/blog/blog/"
37
+
38
+ # About preview on homepage
39
+ [extra.about]
40
+ summary = "I'm a software developer passionate about web technologies, developer experience, and building tools that make other developers' lives easier."
41
+
42
+ # Social links
43
+ [extra.social]
44
+ github = "https://github.com/username"
45
+ twitter = "https://twitter.com/username"
46
+
47
+ # Navigation
48
+ [[extra.nav]]
49
+ name = "Blog"
50
+ url = "/tanuki/blog/blog/"
51
+
52
+ [[extra.nav]]
53
+ name = "Projects"
54
+ url = "/tanuki/blog/projects/"
55
+
56
+ [[extra.nav]]
57
+ name = "About"
58
+ url = "/tanuki/blog/about/"
@@ -0,0 +1,4 @@
1
+ +++
2
+ title = "Home"
3
+ template = "home.html"
4
+ +++
@@ -0,0 +1,33 @@
1
+ +++
2
+ title = "About"
3
+ description = "A little bit about me and what I do."
4
+ template = "page.html"
5
+ path = "about"
6
+ +++
7
+
8
+ # About Me
9
+
10
+ Hey there! I'm a software developer passionate about building things for the web. I spend most of my time writing code, learning new technologies, and occasionally writing about what I've learned.
11
+
12
+ ## What I Do
13
+
14
+ By day, I work on web applications—everything from frontend interfaces to backend APIs. I particularly enjoy:
15
+
16
+ - **Frontend Development**: React, Vue, and modern CSS
17
+ - **Backend Systems**: Node.js, Rust, and databases
18
+ - **Developer Experience**: Tooling, automation, and workflows
19
+ - **Open Source**: Contributing to and maintaining projects
20
+
21
+ ## This Site
22
+
23
+ This site is built with [Zola](https://www.getzola.org/) and the Tanuki theme. It's where I share articles about web development, design patterns, and lessons learned along the way.
24
+
25
+ The source code is available on [GitHub](https://github.com/example/blog) if you're curious about how it's built.
26
+
27
+ ## Get in Touch
28
+
29
+ - **GitHub**: [@username](https://github.com/username)
30
+ - **Twitter**: [@username](https://twitter.com/username)
31
+ - **Email**: hello@example.com
32
+
33
+ Feel free to reach out if you want to chat about tech, have questions about my articles, or just want to say hi.
@@ -0,0 +1,7 @@
1
+ +++
2
+ title = "Blog"
3
+ description = "Thoughts on web development, design, and technology."
4
+ sort_by = "date"
5
+ template = "blog.html"
6
+ paginate_by = 10
7
+ +++
@@ -0,0 +1,245 @@
1
+ +++
2
+ title = "REST API Design Best Practices"
3
+ description = "Good API design makes the difference between a joy to use and a nightmare to integrate. Here's how to get it right."
4
+ date = 2024-12-22
5
+ [taxonomies]
6
+ tags = ["api", "rest", "backend"]
7
+ +++
8
+
9
+ # REST API Design Best Practices
10
+
11
+ Your API is a contract. Make it one developers actually want to sign.
12
+
13
+ ## Use Nouns, Not Verbs
14
+
15
+ The HTTP method is the verb. The URL is the noun.
16
+
17
+ ```
18
+ # Bad
19
+ GET /getUsers
20
+ POST /createUser
21
+ DELETE /deleteUser/123
22
+
23
+ # Good
24
+ GET /users
25
+ POST /users
26
+ DELETE /users/123
27
+ ```
28
+
29
+ ## Use Plural Resource Names
30
+
31
+ Consistency matters more than grammar debates:
32
+
33
+ ```
34
+ GET /users # List users
35
+ GET /users/123 # Get one user
36
+ POST /users # Create user
37
+ PUT /users/123 # Update user
38
+ DELETE /users/123 # Delete user
39
+ ```
40
+
41
+ ## Nest Related Resources
42
+
43
+ Show relationships through URL structure:
44
+
45
+ ```
46
+ GET /users/123/posts # Posts by user 123
47
+ GET /posts/456/comments # Comments on post 456
48
+ ```
49
+
50
+ But don't nest too deeply:
51
+
52
+ ```
53
+ # Too deep
54
+ GET /users/123/posts/456/comments/789/likes
55
+
56
+ # Better: use query params or separate endpoint
57
+ GET /likes?comment=789
58
+ ```
59
+
60
+ ## HTTP Status Codes
61
+
62
+ Use them correctly:
63
+
64
+ | Code | Meaning | When to Use |
65
+ |------|---------|-------------|
66
+ | 200 | OK | Successful GET, PUT, PATCH |
67
+ | 201 | Created | Successful POST |
68
+ | 204 | No Content | Successful DELETE |
69
+ | 400 | Bad Request | Invalid syntax, validation errors |
70
+ | 401 | Unauthorized | Missing/invalid authentication |
71
+ | 403 | Forbidden | Authenticated but not allowed |
72
+ | 404 | Not Found | Resource doesn't exist |
73
+ | 409 | Conflict | Duplicate resource, version conflict |
74
+ | 422 | Unprocessable | Valid syntax but semantic errors |
75
+ | 429 | Too Many Requests | Rate limit exceeded |
76
+ | 500 | Server Error | Something broke |
77
+
78
+ ## Consistent Error Format
79
+
80
+ Always return errors in the same shape:
81
+
82
+ ```json
83
+ {
84
+ "error": {
85
+ "code": "VALIDATION_ERROR",
86
+ "message": "Invalid input data",
87
+ "details": [
88
+ {
89
+ "field": "email",
90
+ "message": "Must be a valid email address"
91
+ },
92
+ {
93
+ "field": "age",
94
+ "message": "Must be at least 18"
95
+ }
96
+ ]
97
+ }
98
+ }
99
+ ```
100
+
101
+ ## Pagination
102
+
103
+ For any list endpoint, support pagination:
104
+
105
+ ```
106
+ GET /posts?page=2&limit=20
107
+ ```
108
+
109
+ Return pagination metadata:
110
+
111
+ ```json
112
+ {
113
+ "data": [...],
114
+ "pagination": {
115
+ "page": 2,
116
+ "limit": 20,
117
+ "total": 156,
118
+ "pages": 8
119
+ }
120
+ }
121
+ ```
122
+
123
+ Or use cursor-based pagination for large datasets:
124
+
125
+ ```
126
+ GET /posts?cursor=eyJpZCI6MTAwfQ&limit=20
127
+ ```
128
+
129
+ ## Filtering and Sorting
130
+
131
+ Use query parameters:
132
+
133
+ ```
134
+ GET /posts?status=published&author=123
135
+ GET /posts?sort=-created_at,title
136
+ GET /posts?created_after=2024-01-01
137
+ ```
138
+
139
+ The `-` prefix indicates descending order.
140
+
141
+ ## Partial Responses
142
+
143
+ Let clients request only what they need:
144
+
145
+ ```
146
+ GET /users/123?fields=id,name,email
147
+ ```
148
+
149
+ Response:
150
+
151
+ ```json
152
+ {
153
+ "id": 123,
154
+ "name": "Jane Doe",
155
+ "email": "jane@example.com"
156
+ }
157
+ ```
158
+
159
+ ## Versioning
160
+
161
+ Version your API from day one:
162
+
163
+ ```
164
+ # URL path (most common)
165
+ GET /v1/users
166
+
167
+ # Header
168
+ GET /users
169
+ Accept: application/vnd.api+json;version=1
170
+
171
+ # Query param (least preferred)
172
+ GET /users?version=1
173
+ ```
174
+
175
+ ## Rate Limiting Headers
176
+
177
+ Tell clients their limits:
178
+
179
+ ```
180
+ X-RateLimit-Limit: 1000
181
+ X-RateLimit-Remaining: 999
182
+ X-RateLimit-Reset: 1640995200
183
+ ```
184
+
185
+ ## HATEOAS (Hypermedia)
186
+
187
+ Include links for discoverability:
188
+
189
+ ```json
190
+ {
191
+ "id": 123,
192
+ "title": "API Design",
193
+ "links": {
194
+ "self": "/posts/123",
195
+ "author": "/users/456",
196
+ "comments": "/posts/123/comments"
197
+ }
198
+ }
199
+ ```
200
+
201
+ ## Idempotency
202
+
203
+ Make operations safe to retry:
204
+
205
+ ```
206
+ # Idempotent (safe to retry)
207
+ GET /users/123
208
+ PUT /users/123 # Full replacement
209
+ DELETE /users/123
210
+
211
+ # Not idempotent
212
+ POST /users # Creates new each time
213
+ ```
214
+
215
+ For non-idempotent operations, accept an idempotency key:
216
+
217
+ ```
218
+ POST /payments
219
+ Idempotency-Key: abc123
220
+
221
+ # Retrying with same key returns cached response
222
+ ```
223
+
224
+ ## Documentation
225
+
226
+ Good APIs have good docs:
227
+
228
+ - **OpenAPI/Swagger**: Machine-readable spec
229
+ - **Examples**: Show request/response pairs
230
+ - **Authentication**: Clear setup instructions
231
+ - **Errors**: Document all error codes
232
+ - **Changelog**: Track breaking changes
233
+
234
+ ## Quick Checklist
235
+
236
+ - [ ] Consistent naming conventions
237
+ - [ ] Proper HTTP status codes
238
+ - [ ] Structured error responses
239
+ - [ ] Pagination for lists
240
+ - [ ] Rate limiting
241
+ - [ ] API versioning
242
+ - [ ] Authentication documented
243
+ - [ ] OpenAPI specification
244
+
245
+ Good API design is invisible—developers just get things working without friction.