keryx-voice 0.2.0__tar.gz

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 (297) hide show
  1. keryx_voice-0.2.0/.gitignore +36 -0
  2. keryx_voice-0.2.0/.python-version +1 -0
  3. keryx_voice-0.2.0/CHANGELOG.md +206 -0
  4. keryx_voice-0.2.0/CLAUDE.md +738 -0
  5. keryx_voice-0.2.0/CODE_OF_CONDUCT.md +83 -0
  6. keryx_voice-0.2.0/CONTRIBUTING.md +162 -0
  7. keryx_voice-0.2.0/LICENSE +202 -0
  8. keryx_voice-0.2.0/PKG-INFO +231 -0
  9. keryx_voice-0.2.0/README.md +187 -0
  10. keryx_voice-0.2.0/SECURITY.md +452 -0
  11. keryx_voice-0.2.0/docs/agents.md +186 -0
  12. keryx_voice-0.2.0/docs/assets/README.md +15 -0
  13. keryx_voice-0.2.0/docs/assets/keryx-call-flow-dark.svg +135 -0
  14. keryx_voice-0.2.0/docs/assets/keryx-call-flow-light.svg +126 -0
  15. keryx_voice-0.2.0/docs/assets/keryx-incoming-call.jpg +0 -0
  16. keryx_voice-0.2.0/docs/assets/keryx-mark.svg +15 -0
  17. keryx_voice-0.2.0/docs/configuration.md +162 -0
  18. keryx_voice-0.2.0/docs/roadmap.md +35 -0
  19. keryx_voice-0.2.0/docs/tools.md +180 -0
  20. keryx_voice-0.2.0/install.sh +77 -0
  21. keryx_voice-0.2.0/pyproject.toml +168 -0
  22. keryx_voice-0.2.0/scripts/claude_hooks/keryx_approval.py +205 -0
  23. keryx_voice-0.2.0/scripts/dev.sh +44 -0
  24. keryx_voice-0.2.0/skills/keryx-custom-tools/SKILL.md +148 -0
  25. keryx_voice-0.2.0/skills/keryx-report-issue/SKILL.md +158 -0
  26. keryx_voice-0.2.0/skills/keryx-setup/SKILL.md +166 -0
  27. keryx_voice-0.2.0/src/keryx/__init__.py +3 -0
  28. keryx_voice-0.2.0/src/keryx/__main__.py +13 -0
  29. keryx_voice-0.2.0/src/keryx/agents/__init__.py +7 -0
  30. keryx_voice-0.2.0/src/keryx/agents/auth.py +116 -0
  31. keryx_voice-0.2.0/src/keryx/agents/base.py +494 -0
  32. keryx_voice-0.2.0/src/keryx/agents/claude.py +296 -0
  33. keryx_voice-0.2.0/src/keryx/agents/codex.py +575 -0
  34. keryx_voice-0.2.0/src/keryx/agents/registry.py +217 -0
  35. keryx_voice-0.2.0/src/keryx/agents/router.py +49 -0
  36. keryx_voice-0.2.0/src/keryx/agents/session.py +364 -0
  37. keryx_voice-0.2.0/src/keryx/app.py +184 -0
  38. keryx_voice-0.2.0/src/keryx/approvals/__init__.py +7 -0
  39. keryx_voice-0.2.0/src/keryx/approvals/broker.py +695 -0
  40. keryx_voice-0.2.0/src/keryx/approvals/hook_install.py +99 -0
  41. keryx_voice-0.2.0/src/keryx/approvals/models.py +154 -0
  42. keryx_voice-0.2.0/src/keryx/approvals/policy.py +572 -0
  43. keryx_voice-0.2.0/src/keryx/audio/__init__.py +1 -0
  44. keryx_voice-0.2.0/src/keryx/audio/util.py +138 -0
  45. keryx_voice-0.2.0/src/keryx/cli.py +1712 -0
  46. keryx_voice-0.2.0/src/keryx/config/__init__.py +91 -0
  47. keryx_voice-0.2.0/src/keryx/config/files.py +211 -0
  48. keryx_voice-0.2.0/src/keryx/config/permissions.py +162 -0
  49. keryx_voice-0.2.0/src/keryx/config/pin.py +175 -0
  50. keryx_voice-0.2.0/src/keryx/config/reference.py +104 -0
  51. keryx_voice-0.2.0/src/keryx/config/settings.py +1203 -0
  52. keryx_voice-0.2.0/src/keryx/config/store.py +328 -0
  53. keryx_voice-0.2.0/src/keryx/continuity/__init__.py +20 -0
  54. keryx_voice-0.2.0/src/keryx/continuity/briefing.py +223 -0
  55. keryx_voice-0.2.0/src/keryx/continuity/memory.py +388 -0
  56. keryx_voice-0.2.0/src/keryx/continuity/recall.py +226 -0
  57. keryx_voice-0.2.0/src/keryx/continuity/retention.py +167 -0
  58. keryx_voice-0.2.0/src/keryx/continuity/transcripts.py +172 -0
  59. keryx_voice-0.2.0/src/keryx/doctor.py +873 -0
  60. keryx_voice-0.2.0/src/keryx/events.py +121 -0
  61. keryx_voice-0.2.0/src/keryx/inline_waits.py +35 -0
  62. keryx_voice-0.2.0/src/keryx/install.py +105 -0
  63. keryx_voice-0.2.0/src/keryx/integrations/__init__.py +19 -0
  64. keryx_voice-0.2.0/src/keryx/integrations/billing.py +601 -0
  65. keryx_voice-0.2.0/src/keryx/integrations/cluster.py +718 -0
  66. keryx_voice-0.2.0/src/keryx/integrations/gmail.py +833 -0
  67. keryx_voice-0.2.0/src/keryx/integrations/slack.py +161 -0
  68. keryx_voice-0.2.0/src/keryx/integrations/web_search.py +99 -0
  69. keryx_voice-0.2.0/src/keryx/issues.py +112 -0
  70. keryx_voice-0.2.0/src/keryx/logging_util.py +18 -0
  71. keryx_voice-0.2.0/src/keryx/notify/__init__.py +4 -0
  72. keryx_voice-0.2.0/src/keryx/notify/callback.py +42 -0
  73. keryx_voice-0.2.0/src/keryx/notify/deliver.py +126 -0
  74. keryx_voice-0.2.0/src/keryx/notify/notifier.py +455 -0
  75. keryx_voice-0.2.0/src/keryx/notify/pin_alert.py +97 -0
  76. keryx_voice-0.2.0/src/keryx/notify/reports.py +36 -0
  77. keryx_voice-0.2.0/src/keryx/notify/twilio_out.py +196 -0
  78. keryx_voice-0.2.0/src/keryx/persona.py +38 -0
  79. keryx_voice-0.2.0/src/keryx/pin_guard.py +205 -0
  80. keryx_voice-0.2.0/src/keryx/plugins/__init__.py +525 -0
  81. keryx_voice-0.2.0/src/keryx/plugins/billing.py +110 -0
  82. keryx_voice-0.2.0/src/keryx/plugins/cluster.py +139 -0
  83. keryx_voice-0.2.0/src/keryx/plugins/email.py +107 -0
  84. keryx_voice-0.2.0/src/keryx/plugins/slack.py +129 -0
  85. keryx_voice-0.2.0/src/keryx/plugins/ssh_hosts.py +138 -0
  86. keryx_voice-0.2.0/src/keryx/plugins/templates/check_billing.py +11 -0
  87. keryx_voice-0.2.0/src/keryx/plugins/templates/check_billing.toml +25 -0
  88. keryx_voice-0.2.0/src/keryx/plugins/templates/check_email.py +11 -0
  89. keryx_voice-0.2.0/src/keryx/plugins/templates/check_email.toml +14 -0
  90. keryx_voice-0.2.0/src/keryx/plugins/templates/cluster_stats.py +11 -0
  91. keryx_voice-0.2.0/src/keryx/plugins/templates/cluster_stats.toml +22 -0
  92. keryx_voice-0.2.0/src/keryx/plugins/templates/send_to_slack.py +11 -0
  93. keryx_voice-0.2.0/src/keryx/plugins/templates/send_to_slack.toml +16 -0
  94. keryx_voice-0.2.0/src/keryx/projects.py +134 -0
  95. keryx_voice-0.2.0/src/keryx/prompts/__init__.py +364 -0
  96. keryx_voice-0.2.0/src/keryx/prompts/first_call.md +57 -0
  97. keryx_voice-0.2.0/src/keryx/prompts/memory_update.md +59 -0
  98. keryx_voice-0.2.0/src/keryx/prompts/setup_project_context.md +34 -0
  99. keryx_voice-0.2.0/src/keryx/prompts/subagent_custom_tools.md +8 -0
  100. keryx_voice-0.2.0/src/keryx/prompts/subagent_issues.md +10 -0
  101. keryx_voice-0.2.0/src/keryx/prompts/subagent_slack.md +7 -0
  102. keryx_voice-0.2.0/src/keryx/prompts/subagent_suffix.md +91 -0
  103. keryx_voice-0.2.0/src/keryx/prompts/voice_system.md +248 -0
  104. keryx_voice-0.2.0/src/keryx/py.typed +0 -0
  105. keryx_voice-0.2.0/src/keryx/realtime/__init__.py +4 -0
  106. keryx_voice-0.2.0/src/keryx/realtime/base.py +184 -0
  107. keryx_voice-0.2.0/src/keryx/realtime/openai.py +589 -0
  108. keryx_voice-0.2.0/src/keryx/restart/__init__.py +14 -0
  109. keryx_voice-0.2.0/src/keryx/restart/coordinator.py +714 -0
  110. keryx_voice-0.2.0/src/keryx/restart/health.py +64 -0
  111. keryx_voice-0.2.0/src/keryx/restart/logscan.py +183 -0
  112. keryx_voice-0.2.0/src/keryx/restart/service.py +317 -0
  113. keryx_voice-0.2.0/src/keryx/restart/store.py +134 -0
  114. keryx_voice-0.2.0/src/keryx/restart/version.py +126 -0
  115. keryx_voice-0.2.0/src/keryx/restart/watchdog.py +241 -0
  116. keryx_voice-0.2.0/src/keryx/server.py +312 -0
  117. keryx_voice-0.2.0/src/keryx/session.py +1240 -0
  118. keryx_voice-0.2.0/src/keryx/setup/__init__.py +7 -0
  119. keryx_voice-0.2.0/src/keryx/setup/agent_instructions.md +41 -0
  120. keryx_voice-0.2.0/src/keryx/setup/agents.py +325 -0
  121. keryx_voice-0.2.0/src/keryx/setup/auth.py +161 -0
  122. keryx_voice-0.2.0/src/keryx/setup/context.py +176 -0
  123. keryx_voice-0.2.0/src/keryx/setup/google.py +594 -0
  124. keryx_voice-0.2.0/src/keryx/setup/guides/__init__.py +1 -0
  125. keryx_voice-0.2.0/src/keryx/setup/guides/google.md +25 -0
  126. keryx_voice-0.2.0/src/keryx/setup/guides/tunnel.md +23 -0
  127. keryx_voice-0.2.0/src/keryx/setup/guides/twilio.md +16 -0
  128. keryx_voice-0.2.0/src/keryx/setup/issues.py +74 -0
  129. keryx_voice-0.2.0/src/keryx/setup/phone.py +169 -0
  130. keryx_voice-0.2.0/src/keryx/setup/plugins.py +273 -0
  131. keryx_voice-0.2.0/src/keryx/setup/profile.py +322 -0
  132. keryx_voice-0.2.0/src/keryx/setup/project_context.py +250 -0
  133. keryx_voice-0.2.0/src/keryx/setup/rewind.py +260 -0
  134. keryx_voice-0.2.0/src/keryx/setup/sections.py +355 -0
  135. keryx_voice-0.2.0/src/keryx/setup/service.py +282 -0
  136. keryx_voice-0.2.0/src/keryx/setup/ui.py +421 -0
  137. keryx_voice-0.2.0/src/keryx/setup/wizard.py +300 -0
  138. keryx_voice-0.2.0/src/keryx/skills.py +123 -0
  139. keryx_voice-0.2.0/src/keryx/stream_tokens.py +117 -0
  140. keryx_voice-0.2.0/src/keryx/tasks/__init__.py +4 -0
  141. keryx_voice-0.2.0/src/keryx/tasks/agent_runner.py +42 -0
  142. keryx_voice-0.2.0/src/keryx/tasks/manager.py +836 -0
  143. keryx_voice-0.2.0/src/keryx/tasks/models.py +259 -0
  144. keryx_voice-0.2.0/src/keryx/tasks/store.py +509 -0
  145. keryx_voice-0.2.0/src/keryx/tools/__init__.py +5 -0
  146. keryx_voice-0.2.0/src/keryx/tools/builtin.py +89 -0
  147. keryx_voice-0.2.0/src/keryx/tools/builtin_common.py +448 -0
  148. keryx_voice-0.2.0/src/keryx/tools/builtin_comms.py +48 -0
  149. keryx_voice-0.2.0/src/keryx/tools/builtin_restart.py +72 -0
  150. keryx_voice-0.2.0/src/keryx/tools/builtin_session.py +224 -0
  151. keryx_voice-0.2.0/src/keryx/tools/builtin_tasks.py +560 -0
  152. keryx_voice-0.2.0/src/keryx/tools/custom.py +274 -0
  153. keryx_voice-0.2.0/src/keryx/tools/registry.py +173 -0
  154. keryx_voice-0.2.0/src/keryx/transports/__init__.py +2 -0
  155. keryx_voice-0.2.0/src/keryx/transports/base.py +88 -0
  156. keryx_voice-0.2.0/src/keryx/transports/twilio_ws.py +280 -0
  157. keryx_voice-0.2.0/src/keryx/transports/wav.py +95 -0
  158. keryx_voice-0.2.0/src/keryx/trust.py +38 -0
  159. keryx_voice-0.2.0/tests/agents/__init__.py +0 -0
  160. keryx_voice-0.2.0/tests/agents/conftest.py +13 -0
  161. keryx_voice-0.2.0/tests/agents/fakes.py +64 -0
  162. keryx_voice-0.2.0/tests/agents/fixtures/README.md +43 -0
  163. keryx_voice-0.2.0/tests/agents/fixtures/codex_app_budget.jsonl +5 -0
  164. keryx_voice-0.2.0/tests/agents/fixtures/codex_app_failed.jsonl +7 -0
  165. keryx_voice-0.2.0/tests/agents/fixtures/codex_app_interrupted.jsonl +10 -0
  166. keryx_voice-0.2.0/tests/agents/fixtures/codex_app_run.jsonl +22 -0
  167. keryx_voice-0.2.0/tests/agents/fixtures/codex_app_steered.jsonl +16 -0
  168. keryx_voice-0.2.0/tests/agents/test_auth.py +75 -0
  169. keryx_voice-0.2.0/tests/agents/test_base.py +363 -0
  170. keryx_voice-0.2.0/tests/agents/test_claude.py +650 -0
  171. keryx_voice-0.2.0/tests/agents/test_codex.py +878 -0
  172. keryx_voice-0.2.0/tests/agents/test_registry.py +242 -0
  173. keryx_voice-0.2.0/tests/agents/test_router.py +57 -0
  174. keryx_voice-0.2.0/tests/agents/test_session.py +360 -0
  175. keryx_voice-0.2.0/tests/approvals/__init__.py +0 -0
  176. keryx_voice-0.2.0/tests/approvals/conftest.py +27 -0
  177. keryx_voice-0.2.0/tests/approvals/test_broker.py +727 -0
  178. keryx_voice-0.2.0/tests/approvals/test_hook.py +277 -0
  179. keryx_voice-0.2.0/tests/approvals/test_hook_install.py +123 -0
  180. keryx_voice-0.2.0/tests/approvals/test_policy.py +576 -0
  181. keryx_voice-0.2.0/tests/approvals/test_quiet_hours.py +77 -0
  182. keryx_voice-0.2.0/tests/approvals/test_session_keypad.py +421 -0
  183. keryx_voice-0.2.0/tests/approvals/test_tools.py +202 -0
  184. keryx_voice-0.2.0/tests/config/__init__.py +0 -0
  185. keryx_voice-0.2.0/tests/config/test_files.py +108 -0
  186. keryx_voice-0.2.0/tests/config/test_permissions.py +113 -0
  187. keryx_voice-0.2.0/tests/config/test_pin.py +51 -0
  188. keryx_voice-0.2.0/tests/config/test_store.py +313 -0
  189. keryx_voice-0.2.0/tests/conftest.py +190 -0
  190. keryx_voice-0.2.0/tests/continuity/__init__.py +0 -0
  191. keryx_voice-0.2.0/tests/continuity/test_briefing.py +218 -0
  192. keryx_voice-0.2.0/tests/continuity/test_memory.py +473 -0
  193. keryx_voice-0.2.0/tests/continuity/test_recall.py +269 -0
  194. keryx_voice-0.2.0/tests/continuity/test_retention.py +300 -0
  195. keryx_voice-0.2.0/tests/continuity/test_transcripts.py +182 -0
  196. keryx_voice-0.2.0/tests/fakes.py +238 -0
  197. keryx_voice-0.2.0/tests/fixtures/realtime/error_active_response.json +11 -0
  198. keryx_voice-0.2.0/tests/fixtures/realtime/error_invalid_api_key.json +11 -0
  199. keryx_voice-0.2.0/tests/fixtures/realtime/error_server_error.json +11 -0
  200. keryx_voice-0.2.0/tests/fixtures/realtime/error_truncate_already_shorter.json +11 -0
  201. keryx_voice-0.2.0/tests/fixtures/realtime/function_call_arguments_done.json +10 -0
  202. keryx_voice-0.2.0/tests/fixtures/realtime/function_call_arguments_done_invalid.json +10 -0
  203. keryx_voice-0.2.0/tests/fixtures/realtime/input_audio_transcription_completed.json +7 -0
  204. keryx_voice-0.2.0/tests/fixtures/realtime/rate_limits_updated.json +5 -0
  205. keryx_voice-0.2.0/tests/fixtures/realtime/response_created.json +5 -0
  206. keryx_voice-0.2.0/tests/fixtures/realtime/response_done.json +5 -0
  207. keryx_voice-0.2.0/tests/fixtures/realtime/response_output_audio_delta.json +9 -0
  208. keryx_voice-0.2.0/tests/fixtures/realtime/response_output_audio_transcript_done.json +9 -0
  209. keryx_voice-0.2.0/tests/fixtures/realtime/response_output_item_done_function_call.json +15 -0
  210. keryx_voice-0.2.0/tests/fixtures/realtime/session_created.json +5 -0
  211. keryx_voice-0.2.0/tests/fixtures/realtime/speech_started.json +6 -0
  212. keryx_voice-0.2.0/tests/fixtures/realtime/speech_stopped.json +6 -0
  213. keryx_voice-0.2.0/tests/integrations/__init__.py +0 -0
  214. keryx_voice-0.2.0/tests/integrations/test_billing.py +621 -0
  215. keryx_voice-0.2.0/tests/integrations/test_cluster.py +543 -0
  216. keryx_voice-0.2.0/tests/integrations/test_gmail.py +831 -0
  217. keryx_voice-0.2.0/tests/integrations/test_slack.py +193 -0
  218. keryx_voice-0.2.0/tests/integrations/test_web_search.py +70 -0
  219. keryx_voice-0.2.0/tests/notify/__init__.py +0 -0
  220. keryx_voice-0.2.0/tests/notify/test_deliver.py +185 -0
  221. keryx_voice-0.2.0/tests/notify/test_notifier.py +1114 -0
  222. keryx_voice-0.2.0/tests/notify/test_pin_alert.py +204 -0
  223. keryx_voice-0.2.0/tests/notify/test_twilio_out.py +302 -0
  224. keryx_voice-0.2.0/tests/plugins/__init__.py +0 -0
  225. keryx_voice-0.2.0/tests/plugins/conftest.py +16 -0
  226. keryx_voice-0.2.0/tests/plugins/helpers.py +72 -0
  227. keryx_voice-0.2.0/tests/plugins/test_billing.py +179 -0
  228. keryx_voice-0.2.0/tests/plugins/test_cluster.py +215 -0
  229. keryx_voice-0.2.0/tests/plugins/test_config.py +211 -0
  230. keryx_voice-0.2.0/tests/plugins/test_email.py +132 -0
  231. keryx_voice-0.2.0/tests/plugins/test_slack.py +235 -0
  232. keryx_voice-0.2.0/tests/plugins/test_ssh_hosts.py +143 -0
  233. keryx_voice-0.2.0/tests/realtime/__init__.py +0 -0
  234. keryx_voice-0.2.0/tests/realtime/fake_ws.py +90 -0
  235. keryx_voice-0.2.0/tests/realtime/test_openai_client.py +909 -0
  236. keryx_voice-0.2.0/tests/restart/__init__.py +0 -0
  237. keryx_voice-0.2.0/tests/restart/test_logscan.py +175 -0
  238. keryx_voice-0.2.0/tests/restart/test_restart.py +1882 -0
  239. keryx_voice-0.2.0/tests/restart/test_restart_watch.py +421 -0
  240. keryx_voice-0.2.0/tests/setup/__init__.py +0 -0
  241. keryx_voice-0.2.0/tests/setup/conftest.py +49 -0
  242. keryx_voice-0.2.0/tests/setup/fakes.py +235 -0
  243. keryx_voice-0.2.0/tests/setup/test_agents.py +312 -0
  244. keryx_voice-0.2.0/tests/setup/test_auth.py +145 -0
  245. keryx_voice-0.2.0/tests/setup/test_context.py +70 -0
  246. keryx_voice-0.2.0/tests/setup/test_gmail_signin.py +126 -0
  247. keryx_voice-0.2.0/tests/setup/test_google.py +344 -0
  248. keryx_voice-0.2.0/tests/setup/test_google_section.py +145 -0
  249. keryx_voice-0.2.0/tests/setup/test_issues_section.py +112 -0
  250. keryx_voice-0.2.0/tests/setup/test_phone.py +162 -0
  251. keryx_voice-0.2.0/tests/setup/test_plugins_section.py +344 -0
  252. keryx_voice-0.2.0/tests/setup/test_profile.py +244 -0
  253. keryx_voice-0.2.0/tests/setup/test_project_context.py +292 -0
  254. keryx_voice-0.2.0/tests/setup/test_rewind.py +270 -0
  255. keryx_voice-0.2.0/tests/setup/test_sections.py +426 -0
  256. keryx_voice-0.2.0/tests/setup/test_service.py +271 -0
  257. keryx_voice-0.2.0/tests/setup/test_ui.py +290 -0
  258. keryx_voice-0.2.0/tests/setup/test_wizard.py +254 -0
  259. keryx_voice-0.2.0/tests/tasks/__init__.py +0 -0
  260. keryx_voice-0.2.0/tests/tasks/test_manager.py +1158 -0
  261. keryx_voice-0.2.0/tests/tasks/test_models.py +287 -0
  262. keryx_voice-0.2.0/tests/tasks/test_store.py +695 -0
  263. keryx_voice-0.2.0/tests/test_app.py +191 -0
  264. keryx_voice-0.2.0/tests/test_audio_util.py +202 -0
  265. keryx_voice-0.2.0/tests/test_cli.py +1393 -0
  266. keryx_voice-0.2.0/tests/test_cli_config.py +504 -0
  267. keryx_voice-0.2.0/tests/test_config.py +846 -0
  268. keryx_voice-0.2.0/tests/test_custom_tools_skill.py +53 -0
  269. keryx_voice-0.2.0/tests/test_docs_sync.py +145 -0
  270. keryx_voice-0.2.0/tests/test_doctor.py +794 -0
  271. keryx_voice-0.2.0/tests/test_events.py +228 -0
  272. keryx_voice-0.2.0/tests/test_install.py +266 -0
  273. keryx_voice-0.2.0/tests/test_issues.py +153 -0
  274. keryx_voice-0.2.0/tests/test_logging_util.py +37 -0
  275. keryx_voice-0.2.0/tests/test_persona.py +65 -0
  276. keryx_voice-0.2.0/tests/test_pin_guard.py +269 -0
  277. keryx_voice-0.2.0/tests/test_projects.py +152 -0
  278. keryx_voice-0.2.0/tests/test_prompts.py +889 -0
  279. keryx_voice-0.2.0/tests/test_registry.py +183 -0
  280. keryx_voice-0.2.0/tests/test_report_issue_skill.py +69 -0
  281. keryx_voice-0.2.0/tests/test_reports.py +155 -0
  282. keryx_voice-0.2.0/tests/test_scripts.py +153 -0
  283. keryx_voice-0.2.0/tests/test_server.py +525 -0
  284. keryx_voice-0.2.0/tests/test_session.py +1121 -0
  285. keryx_voice-0.2.0/tests/test_session_pin.py +848 -0
  286. keryx_voice-0.2.0/tests/test_session_prepin.py +655 -0
  287. keryx_voice-0.2.0/tests/test_setup_skill.py +104 -0
  288. keryx_voice-0.2.0/tests/test_skills.py +88 -0
  289. keryx_voice-0.2.0/tests/test_stream_tokens.py +149 -0
  290. keryx_voice-0.2.0/tests/test_trust.py +80 -0
  291. keryx_voice-0.2.0/tests/tools/__init__.py +1 -0
  292. keryx_voice-0.2.0/tests/tools/test_builtin.py +1812 -0
  293. keryx_voice-0.2.0/tests/tools/test_custom.py +348 -0
  294. keryx_voice-0.2.0/tests/transports/__init__.py +0 -0
  295. keryx_voice-0.2.0/tests/transports/test_twilio_ws.py +342 -0
  296. keryx_voice-0.2.0/tests/transports/test_wav.py +103 -0
  297. keryx_voice-0.2.0/uv.lock +1195 -0
@@ -0,0 +1,36 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ .venv/
6
+ .pytest_cache/
7
+ .ruff_cache/
8
+ dist/
9
+ build/
10
+ .coverage
11
+ .coverage.*
12
+ coverage.xml
13
+ htmlcov/
14
+
15
+ # Secrets & local state
16
+ .env
17
+ .env.*
18
+ *.pem
19
+ credentials/
20
+ .secrets/
21
+ .jarvis/
22
+ .ngrok.log
23
+ .cloudflared.log
24
+
25
+ # SDD scratch
26
+ .superpowers/
27
+
28
+ # Local scratch and launcher
29
+ tmp/
30
+ .claude-launch.sh
31
+ .claude/
32
+
33
+ # OS / editors
34
+ .DS_Store
35
+ .idea/
36
+ .vscode/
@@ -0,0 +1 @@
1
+ 3.12
@@ -0,0 +1,206 @@
1
+ # Changelog
2
+
3
+ Notable changes, newest first. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
4
+ and versions follow [semantic versioning](https://semver.org/) over the command line and the
5
+ settings: a removed or renamed setting or command is a major bump, or a minor one while
6
+ the version starts with 0.
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [0.2.0] - 2026-11-09
11
+
12
+ Keryx installs with one line and no clone, and every command starts with `keryx`. An
13
+ installed service needs nothing done: the new commands write the same units the scripts did.
14
+
15
+ ### Added
16
+
17
+ - **A one-line install:**
18
+ `curl -fsSL https://raw.githubusercontent.com/wak31415/keryx/main/install.sh | sh`. It
19
+ installs the `keryx` command with both coding agents and starts `keryx setup`. It needs no
20
+ Python, uv or clone: it brings its own. Keryx is published on PyPI as `keryx-voice`, so a
21
+ tool of your own can have Keryx in its editor with `pip install keryx-voice`.
22
+ - **`keryx service install`** installs and starts the background service with its tunnel
23
+ (systemd on Linux, launchd on macOS), and **`keryx service uninstall`** removes them. The
24
+ last section of `keryx setup` runs it.
25
+ - **`keryx upgrade`** updates an installed Keryx and restarts the service onto the new
26
+ version. It checks that the new version starts before it restarts anything. You can also
27
+ ask for an upgrade on a call: Keryx installs it while you talk, restarts once the call
28
+ ends, and rings you back to say which version it is on. If nothing newer exists, it
29
+ tells you at once.
30
+ - **`keryx approvals --install-hook`** installs the approval bridge's hook into Claude Code,
31
+ and `--uninstall-hook` takes it out.
32
+
33
+ ### Removed
34
+
35
+ - `scripts/install-systemd.sh`, `scripts/install-launchd.sh`,
36
+ `scripts/install-claude-hook.sh` and `scripts/lib.sh`, replaced by the commands above.
37
+ `scripts/dev.sh` stays, for working on Keryx from a clone.
38
+ - `keryx migrate`, `keryx config import-env` and `keryx plugins install --from-settings`,
39
+ which moved settings from before 0.1.0, and the refusal to start beside a `.env` in the
40
+ working directory.
41
+ - `FAKE_AGENTS`, the old name of `DEMO_MODE`, and the hidden `serve` options
42
+ `--fake-agents` and `--no-wakeword`.
43
+
44
+ ## [0.1.2] - 2026-11-04
45
+
46
+ Fixes to how results reach you, finished tasks' reports on Slack, and updated dependencies.
47
+ Nothing to change on your side: no setting or command was renamed or removed.
48
+
49
+ ### Security
50
+
51
+ - **certifi 2026.10.18 drops the emSign root certificates** whose intermediate CA keys were
52
+ compromised (GHSA-6q48-6c7w-9gw2, critical). It is the certificate bundle that the HTTP
53
+ libraries under the OpenAI and Twilio clients trust by default.
54
+
55
+ ### Changed
56
+
57
+ - **A finished task's whole report is posted to your Slack DM.** While the `send_to_slack`
58
+ plugin is on, each report is posted under a line naming the task, with its headings,
59
+ tables and links rendered and no link previews. The request and the spoken summary are
60
+ left out, and a long report is no longer split mid-list. On a call, questions about a
61
+ finished task are answered from its report instead of starting new work. Messages sent
62
+ with `send_to_slack` render Markdown the same way.
63
+ - **Dependencies are updated.** The Codex agent runs on `openai-codex` 0.163.0 and its
64
+ bundled `codex` CLI. Twilio 9.12.0, websockets 17.2 and numpy 2.5.4 are updated
65
+ too.
66
+
67
+ ### Fixed
68
+
69
+ - **No call-back on top of the call you are already on.** If a task you asked to be called
70
+ back about finished while you had rung Keryx again, your phone rang mid-call with the same
71
+ result. The call-back now waits for that call to end. It does not ring at all if you gave
72
+ the PIN on that call after hearing the result, or if the result was marked as heard.
73
+ - **A result read out mid-call is recorded as heard.** It used to come back at the top of
74
+ the next call. The announcement replaced the assistant's instructions for that turn,
75
+ including the one that says to record it; it no longer does, and it now asks for the
76
+ record in the same turn.
77
+ - **A result you heard before giving the PIN is not told to you again after it.** Once the
78
+ PIN is in, it is recorded as heard instead of being repeated.
79
+ - **Asking about your email no longer misses the thread you meant because of one broad
80
+ word.** A search with alternatives now looks for each one separately, so newer mail
81
+ matching a common word cannot push out the thread you asked about, and the summary sees
82
+ more threads. When nothing matches, the assistant says what it searched for, so you can
83
+ correct a misheard name or word.
84
+ - **The assistant asks when part of a request comes through garbled.** If a phrase
85
+ transcribes as nonsense, it asks one short question about that part instead of acting on
86
+ it.
87
+ - **The restart watchdog starts on its own instead of through the whole app.** A code
88
+ change that breaks the import no longer silences the alert that Keryx never came back.
89
+ - **The installers work from a path with a space or a `%` in it.** The systemd units quote
90
+ the checkout and the `uv` and `cloudflared` paths, and the launchd plists escape every
91
+ value, so a checkout such as `~/My Projects/keryx` no longer leaves a unit that will not
92
+ start.
93
+
94
+ ## [0.1.1] - 2026-10-19
95
+
96
+ Fixes from an audit of 0.1.0, and updated dependencies. Nothing to change on your side: no
97
+ setting or command was renamed or removed.
98
+
99
+ ### Security
100
+
101
+ - **Dependencies with published advisories are updated.** aiohttp 3.14.4, multidict 6.9.1,
102
+ mcp 1.30.0, PyJWT 2.15.0 and urllib3 2.8.0 each fix one or more advisories. Keryx does
103
+ not import any of them; they come in through Twilio and the Claude Agent SDK.
104
+
105
+ - **Typing your PIN on an approval call can no longer approve anything.** When Keryx called
106
+ about a Claude Code prompt, a digit of your PIN typed after the keypad menu opened went to
107
+ the menu, so the PIN's first "1" could approve the request. Digits now reach the menu only
108
+ when no PIN entry is in progress, and the call no longer asks for the PIN first.
109
+ - **A line break in speech can no longer mark a call as authorized.** Transcript lines are
110
+ written on one line, so nobody can make the assistant say the marker that `recall` reads.
111
+ - **Hook-framework files are no longer approvable by phone.** A write to
112
+ `.pre-commit-config.yaml`, `.husky/` or any lefthook configuration is refused, as `.git`
113
+ already was: the `git commit` a keypad may approve next would run what is in them.
114
+ - **The service can no longer re-enable approval calls or delete transcripts.**
115
+ `keryx approvals --enable` and `keryx forget` now refuse when a subagent runs them.
116
+ Anyone can still switch approvals off.
117
+ - **A PIN said in pairs is now redacted from transcripts.** "Forty-two forty-two
118
+ forty-two" is replaced with `[PIN]` like single digits are. The transcript is also redacted
119
+ again before the memory update reads it, which covers the lines spoken before a first PIN
120
+ was set.
121
+
122
+ ### Changed
123
+
124
+ - **The coding agents' SDKs are updated.** The Codex agent runs on `openai-codex` 0.158.0
125
+ and its bundled `codex` CLI, and the Claude agent on `claude-agent-sdk` 0.2.160 and its
126
+ bundled Claude Code CLI.
127
+
128
+ ### Fixed
129
+
130
+ - **A follow-up's result is read out again.** A task re-run by `send_followup` is now owed
131
+ a call-back and a place in the next call's digest, instead of keeping the old "told"
132
+ stamp. Only a finished task can be marked as told.
133
+ - **A restart that waits too long now fails visibly.** It used to give up after 40 minutes
134
+ and clear its record, so `keryx restart --status` read as if nothing had happened and the
135
+ call-back never came. It now records the failure and tells you.
136
+ - **A crash no longer leaves a task "running" for ever.** At startup, Keryx marks any task
137
+ that was still running when it stopped as failed ("Keryx stopped while this was
138
+ running"), so it stops blocking restarts and follow-ups. You hear about it in your next
139
+ call.
140
+ - **A database upgrade that is interrupted no longer stops Keryx from starting.** The
141
+ `tasks.db` upgrade now runs in one transaction.
142
+ - **Two memory updates no longer overwrite each other.** When two calls end close
143
+ together, the second update now waits for the first, so neither call drops out of the
144
+ memory.
145
+ - **Anthropic spend for a workspace now counts only that workspace.** `check_billing` used
146
+ to read the whole organization's spend and report it as the workspace's, against the
147
+ workspace's budget.
148
+ - **The service can no longer lift a limit by setting it very high.** A limit it may tune,
149
+ such as `SUBAGENT_TIMEOUT_S`, is now refused above ten times its default. You can still
150
+ set any value yourself.
151
+
152
+ ## [0.1.0] - 2026-09-30
153
+
154
+ The first public release. You call a phone number and talk to your voice assistant, Lyra
155
+ by default. Keryx is the service behind it: it hands the work you ask for to a coding agent
156
+ on your machine, keeps that work running after you hang up, remembers what happened between
157
+ calls, and calls you when there's news.
158
+
159
+ ### Added
160
+
161
+ - **A voice assistant you can call.** A Twilio number puts you through to an assistant that
162
+ runs on the OpenAI Realtime API. It's called Lyra unless you choose another name, and
163
+ Jarvis is a second built-in persona with its own voice. It answers small questions itself,
164
+ with a web search when it needs one.
165
+ - **Tasks that keep running after you hang up.** Anything larger becomes a task for Claude
166
+ Code or Codex, in the project you name. In a later call, you can ask how a task is going,
167
+ add instructions, or cancel it. If both agents are set up, you can say which one to use.
168
+ - **Call-backs.** When a task finishes, or needs a decision from you, Keryx calls you and the
169
+ assistant tells you the result. If your Twilio account can send SMS, you can turn on texts
170
+ with a link to the written report. Texting is off by default.
171
+ - **Continuity between calls.** Each call starts with the results you haven't heard yet and
172
+ what the assistant remembers about you. Keryx updates that memory after every call in
173
+ which you gave the PIN. With the PIN, you can also ask about anything said in an earlier
174
+ call. Your first call is a short introduction, so the assistant can learn what you work on
175
+ and how you like to be answered.
176
+ - **Security for a phone line.** Keryx answers only your own numbers. A PIN of six to eight
177
+ digits guards everything that acts on your behalf, and wrong guesses count across calls
178
+ toward a lockout. You can set the PIN on the keypad during your first call. A call that
179
+ Keryx places to your own phone can answer the question it's calling about without the
180
+ PIN. [SECURITY.md](SECURITY.md) has the threat model.
181
+ - **The approval bridge.** If a Claude Code session on your screen stops to ask for
182
+ permission and you don't answer within five minutes, Keryx calls you, and you answer on
183
+ the keypad. Only routine, reversible commands can be approved by phone.
184
+ - **Keryx can grow during a call.** Ask for a new voice command, and a coding agent writes it
185
+ as a tool of your own, ready on the next call without a restart. A change to Keryx itself
186
+ ends with a restart and a call to confirm that the new code is running. If it doesn't
187
+ start, a watchdog calls you with a plain alert.
188
+ - **Plugins.** Slack, email, billing, and Slurm cluster status are optional voice tools
189
+ that you turn on in `keryx setup` or with `keryx plugins install`.
190
+ - **Bug reports and feature requests by voice.** If you turn it on, "that's a bug, report
191
+ it" files a GitHub issue on Keryx's repository with nothing personal in it. It's off by
192
+ default, and only you can turn it on.
193
+ - **Setup and upkeep from the command line.** `keryx setup` is a wizard that asks only for
194
+ what's still missing, and `keryx doctor` checks the whole setup. `keryx config`,
195
+ `keryx auth`, and `keryx tasks` cover settings, sign-ins, and what each task did and cost.
196
+ `keryx forget` and two retention settings delete old transcripts and tasks.
197
+ - **A demo mode.** `keryx serve --demo` lets you try the phone before a coding agent is set
198
+ up. Every task comes back with a sample answer, and no agent tokens are spent.
199
+ - **Linux and macOS.** Keryx runs as a systemd or launchd service, keeps its files in the
200
+ standard XDG directories, and stores secrets in files only you can read.
201
+
202
+ [Unreleased]: https://github.com/wak31415/keryx/compare/v0.2.0...HEAD
203
+ [0.2.0]: https://github.com/wak31415/keryx/compare/v0.1.2...v0.2.0
204
+ [0.1.2]: https://github.com/wak31415/keryx/compare/v0.1.1...v0.1.2
205
+ [0.1.1]: https://github.com/wak31415/keryx/compare/v0.1.0...v0.1.1
206
+ [0.1.0]: https://github.com/wak31415/keryx/releases/tag/v0.1.0