code-puppy-core-plugins 0.0.2__py3-none-any.whl

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 (313) hide show
  1. code_puppy_core_plugins/__init__.py +5 -0
  2. code_puppy_core_plugins/acp/README.md +266 -0
  3. code_puppy_core_plugins/acp/__init__.py +8 -0
  4. code_puppy_core_plugins/acp/agent.py +494 -0
  5. code_puppy_core_plugins/acp/bridge.py +309 -0
  6. code_puppy_core_plugins/acp/capabilities.py +73 -0
  7. code_puppy_core_plugins/acp/commands.py +116 -0
  8. code_puppy_core_plugins/acp/content.py +115 -0
  9. code_puppy_core_plugins/acp/io_delegation.py +231 -0
  10. code_puppy_core_plugins/acp/mcp_config.py +66 -0
  11. code_puppy_core_plugins/acp/permissions.py +159 -0
  12. code_puppy_core_plugins/acp/persistence.py +197 -0
  13. code_puppy_core_plugins/acp/register_callbacks.py +110 -0
  14. code_puppy_core_plugins/acp/replay.py +114 -0
  15. code_puppy_core_plugins/acp/session.py +329 -0
  16. code_puppy_core_plugins/acp/session_config.py +179 -0
  17. code_puppy_core_plugins/acp/state.py +135 -0
  18. code_puppy_core_plugins/agent_skills/__init__.py +22 -0
  19. code_puppy_core_plugins/agent_skills/config.py +208 -0
  20. code_puppy_core_plugins/agent_skills/discovery.py +337 -0
  21. code_puppy_core_plugins/agent_skills/downloader.py +392 -0
  22. code_puppy_core_plugins/agent_skills/enabled_skills.py +82 -0
  23. code_puppy_core_plugins/agent_skills/installer.py +22 -0
  24. code_puppy_core_plugins/agent_skills/metadata.py +219 -0
  25. code_puppy_core_plugins/agent_skills/prompt_builder.py +49 -0
  26. code_puppy_core_plugins/agent_skills/provider.py +52 -0
  27. code_puppy_core_plugins/agent_skills/register_callbacks.py +309 -0
  28. code_puppy_core_plugins/agent_skills/remote_catalog.py +322 -0
  29. code_puppy_core_plugins/agent_skills/skill_catalog.py +257 -0
  30. code_puppy_core_plugins/agent_skills/skill_commands.py +102 -0
  31. code_puppy_core_plugins/agent_skills/skills_install_menu.py +698 -0
  32. code_puppy_core_plugins/agent_skills/skills_menu.py +794 -0
  33. code_puppy_core_plugins/aws_bedrock/__init__.py +14 -0
  34. code_puppy_core_plugins/aws_bedrock/config.py +101 -0
  35. code_puppy_core_plugins/aws_bedrock/register_callbacks.py +243 -0
  36. code_puppy_core_plugins/aws_bedrock/utils.py +186 -0
  37. code_puppy_core_plugins/azure_foundry/README.md +238 -0
  38. code_puppy_core_plugins/azure_foundry/__init__.py +15 -0
  39. code_puppy_core_plugins/azure_foundry/config.py +126 -0
  40. code_puppy_core_plugins/azure_foundry/discovery.py +189 -0
  41. code_puppy_core_plugins/azure_foundry/register_callbacks.py +506 -0
  42. code_puppy_core_plugins/azure_foundry/token.py +182 -0
  43. code_puppy_core_plugins/azure_foundry/utils.py +375 -0
  44. code_puppy_core_plugins/btw/__init__.py +1 -0
  45. code_puppy_core_plugins/btw/inline_view.py +135 -0
  46. code_puppy_core_plugins/btw/register_callbacks.py +106 -0
  47. code_puppy_core_plugins/btw/side_query.py +91 -0
  48. code_puppy_core_plugins/chatgpt_oauth/IMAGEGEN_SKILL.md +83 -0
  49. code_puppy_core_plugins/chatgpt_oauth/__init__.py +8 -0
  50. code_puppy_core_plugins/chatgpt_oauth/config.py +52 -0
  51. code_puppy_core_plugins/chatgpt_oauth/image_generation.py +253 -0
  52. code_puppy_core_plugins/chatgpt_oauth/image_tool.py +70 -0
  53. code_puppy_core_plugins/chatgpt_oauth/oauth_flow.py +461 -0
  54. code_puppy_core_plugins/chatgpt_oauth/register_callbacks.py +288 -0
  55. code_puppy_core_plugins/chatgpt_oauth/test_plugin.py +663 -0
  56. code_puppy_core_plugins/chatgpt_oauth/usage.py +113 -0
  57. code_puppy_core_plugins/chatgpt_oauth/utils.py +534 -0
  58. code_puppy_core_plugins/claude_code_hooks/__init__.py +1 -0
  59. code_puppy_core_plugins/claude_code_hooks/config.py +137 -0
  60. code_puppy_core_plugins/claude_code_hooks/register_callbacks.py +383 -0
  61. code_puppy_core_plugins/claude_code_oauth/README.md +167 -0
  62. code_puppy_core_plugins/claude_code_oauth/SETUP.md +93 -0
  63. code_puppy_core_plugins/claude_code_oauth/__init__.py +25 -0
  64. code_puppy_core_plugins/claude_code_oauth/config.py +59 -0
  65. code_puppy_core_plugins/claude_code_oauth/fast_mode.py +122 -0
  66. code_puppy_core_plugins/claude_code_oauth/prompt_handler.py +64 -0
  67. code_puppy_core_plugins/claude_code_oauth/register_callbacks.py +719 -0
  68. code_puppy_core_plugins/claude_code_oauth/test_plugin.py +285 -0
  69. code_puppy_core_plugins/claude_code_oauth/token_refresh_heartbeat.py +240 -0
  70. code_puppy_core_plugins/claude_code_oauth/utils.py +663 -0
  71. code_puppy_core_plugins/code_puppy_agent/AGENTS_AND_TOOLS.md +155 -0
  72. code_puppy_core_plugins/code_puppy_agent/MODELS_AND_MCP.md +104 -0
  73. code_puppy_core_plugins/code_puppy_agent/PLUGINS_AND_CALLBACKS.md +147 -0
  74. code_puppy_core_plugins/code_puppy_agent/SESSIONS_AND_HISTORY.md +39 -0
  75. code_puppy_core_plugins/code_puppy_agent/SKILL.md +180 -0
  76. code_puppy_core_plugins/code_puppy_agent/SKILLS_SYSTEM.md +136 -0
  77. code_puppy_core_plugins/code_puppy_agent/SYSTEM_PROMPT_CONFIG_AND_I18N.md +160 -0
  78. code_puppy_core_plugins/code_puppy_agent/__init__.py +5 -0
  79. code_puppy_core_plugins/code_puppy_agent/register_callbacks.py +46 -0
  80. code_puppy_core_plugins/computer_use/NativeCapture.swift +123 -0
  81. code_puppy_core_plugins/computer_use/README.md +109 -0
  82. code_puppy_core_plugins/computer_use/__init__.py +1 -0
  83. code_puppy_core_plugins/computer_use/accessibility.py +163 -0
  84. code_puppy_core_plugins/computer_use/activation.py +75 -0
  85. code_puppy_core_plugins/computer_use/backend.py +584 -0
  86. code_puppy_core_plugins/computer_use/backend_types.py +5 -0
  87. code_puppy_core_plugins/computer_use/capture.py +110 -0
  88. code_puppy_core_plugins/computer_use/commands.py +62 -0
  89. code_puppy_core_plugins/computer_use/geometry.py +81 -0
  90. code_puppy_core_plugins/computer_use/inline_image.py +56 -0
  91. code_puppy_core_plugins/computer_use/keycodes.py +47 -0
  92. code_puppy_core_plugins/computer_use/policy.py +144 -0
  93. code_puppy_core_plugins/computer_use/register_callbacks.py +96 -0
  94. code_puppy_core_plugins/computer_use/safety.py +18 -0
  95. code_puppy_core_plugins/computer_use/settle.py +64 -0
  96. code_puppy_core_plugins/computer_use/state.py +86 -0
  97. code_puppy_core_plugins/computer_use/tools.py +469 -0
  98. code_puppy_core_plugins/context_indicator/__init__.py +14 -0
  99. code_puppy_core_plugins/context_indicator/register_callbacks.py +249 -0
  100. code_puppy_core_plugins/context_indicator/usage.py +40 -0
  101. code_puppy_core_plugins/copilot_auth/__init__.py +11 -0
  102. code_puppy_core_plugins/copilot_auth/config.py +93 -0
  103. code_puppy_core_plugins/copilot_auth/reasoning_client.py +409 -0
  104. code_puppy_core_plugins/copilot_auth/register_callbacks.py +460 -0
  105. code_puppy_core_plugins/copilot_auth/utils.py +587 -0
  106. code_puppy_core_plugins/customizable_commands/__init__.py +0 -0
  107. code_puppy_core_plugins/customizable_commands/register_callbacks.py +464 -0
  108. code_puppy_core_plugins/dbos_durable_exec/__init__.py +1 -0
  109. code_puppy_core_plugins/dbos_durable_exec/cancel.py +15 -0
  110. code_puppy_core_plugins/dbos_durable_exec/commands.py +31 -0
  111. code_puppy_core_plugins/dbos_durable_exec/config.py +31 -0
  112. code_puppy_core_plugins/dbos_durable_exec/lifecycle.py +83 -0
  113. code_puppy_core_plugins/dbos_durable_exec/register_callbacks.py +45 -0
  114. code_puppy_core_plugins/dbos_durable_exec/runtime.py +65 -0
  115. code_puppy_core_plugins/dbos_durable_exec/startup_lock.py +155 -0
  116. code_puppy_core_plugins/dbos_durable_exec/workflow_ids.py +16 -0
  117. code_puppy_core_plugins/dbos_durable_exec/wrapper.py +58 -0
  118. code_puppy_core_plugins/destructive_command_guard/AGENTS.md +79 -0
  119. code_puppy_core_plugins/destructive_command_guard/__init__.py +14 -0
  120. code_puppy_core_plugins/destructive_command_guard/detector.py +374 -0
  121. code_puppy_core_plugins/destructive_command_guard/register_callbacks.py +165 -0
  122. code_puppy_core_plugins/emoji_filter/__init__.py +12 -0
  123. code_puppy_core_plugins/emoji_filter/config.py +26 -0
  124. code_puppy_core_plugins/emoji_filter/register_callbacks.py +238 -0
  125. code_puppy_core_plugins/emoji_filter/stripper.py +45 -0
  126. code_puppy_core_plugins/empty_html_comment_filter/register_callbacks.py +116 -0
  127. code_puppy_core_plugins/example_custom_command/README.md +328 -0
  128. code_puppy_core_plugins/example_custom_command/register_callbacks.py +66 -0
  129. code_puppy_core_plugins/file_permission_handler/__init__.py +4 -0
  130. code_puppy_core_plugins/file_permission_handler/register_callbacks.py +575 -0
  131. code_puppy_core_plugins/flux_bootstrap/__init__.py +5 -0
  132. code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/_docs/README.md +173 -0
  133. code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/_docs/cheatsheet.md +86 -0
  134. code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/_docs/pipeline.md +167 -0
  135. code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/_docs/synopsis.md +392 -0
  136. code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/about.md +51 -0
  137. code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/address-feedback.md +129 -0
  138. code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/ask.md +211 -0
  139. code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/aug.md +181 -0
  140. code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/auto-pilot.md +71 -0
  141. code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/cheatsheet.md +16 -0
  142. code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/commit.md +103 -0
  143. code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/config.md +108 -0
  144. code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/create-pr.md +195 -0
  145. code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/exec.md +221 -0
  146. code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/new.md +151 -0
  147. code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/qa.md +208 -0
  148. code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/rebase.md +180 -0
  149. code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/review.md +304 -0
  150. code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/split.md +120 -0
  151. code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/squash-commits.md +179 -0
  152. code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/status.md +46 -0
  153. code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/tests.md +155 -0
  154. code_puppy_core_plugins/flux_bootstrap/bundled/scripts/flux_about.py +154 -0
  155. code_puppy_core_plugins/flux_bootstrap/bundled/scripts/flux_cheatsheet.py +248 -0
  156. code_puppy_core_plugins/flux_bootstrap/bundled/scripts/flux_status.py +345 -0
  157. code_puppy_core_plugins/flux_bootstrap/installer.py +256 -0
  158. code_puppy_core_plugins/flux_bootstrap/register_callbacks.py +71 -0
  159. code_puppy_core_plugins/force_push_guard/__init__.py +5 -0
  160. code_puppy_core_plugins/force_push_guard/detector.py +96 -0
  161. code_puppy_core_plugins/force_push_guard/register_callbacks.py +161 -0
  162. code_puppy_core_plugins/fork/__init__.py +7 -0
  163. code_puppy_core_plugins/fork/register_callbacks.py +445 -0
  164. code_puppy_core_plugins/frontend_emitter/__init__.py +25 -0
  165. code_puppy_core_plugins/frontend_emitter/emitter.py +249 -0
  166. code_puppy_core_plugins/frontend_emitter/register_callbacks.py +412 -0
  167. code_puppy_core_plugins/frontend_emitter/session_context.py +50 -0
  168. code_puppy_core_plugins/grok_oauth/__init__.py +6 -0
  169. code_puppy_core_plugins/grok_oauth/config.py +49 -0
  170. code_puppy_core_plugins/grok_oauth/oauth_flow.py +213 -0
  171. code_puppy_core_plugins/grok_oauth/register_callbacks.py +132 -0
  172. code_puppy_core_plugins/grok_oauth/utils.py +195 -0
  173. code_puppy_core_plugins/herdr/README.md +168 -0
  174. code_puppy_core_plugins/herdr/__init__.py +9 -0
  175. code_puppy_core_plugins/herdr/client.py +339 -0
  176. code_puppy_core_plugins/herdr/register_callbacks.py +140 -0
  177. code_puppy_core_plugins/herdr/reporter.py +212 -0
  178. code_puppy_core_plugins/herdr/smoke.py +143 -0
  179. code_puppy_core_plugins/herdr/sources.py +133 -0
  180. code_puppy_core_plugins/hook_creator/__init__.py +1 -0
  181. code_puppy_core_plugins/hook_creator/register_callbacks.py +33 -0
  182. code_puppy_core_plugins/hook_manager/__init__.py +1 -0
  183. code_puppy_core_plugins/hook_manager/config.py +290 -0
  184. code_puppy_core_plugins/hook_manager/hooks_menu.py +571 -0
  185. code_puppy_core_plugins/hook_manager/register_callbacks.py +227 -0
  186. code_puppy_core_plugins/meta_oauth/__init__.py +1 -0
  187. code_puppy_core_plugins/meta_oauth/config.py +55 -0
  188. code_puppy_core_plugins/meta_oauth/oauth_flow.py +109 -0
  189. code_puppy_core_plugins/meta_oauth/register_callbacks.py +154 -0
  190. code_puppy_core_plugins/meta_oauth/utils.py +252 -0
  191. code_puppy_core_plugins/namespace_skill_search/README.md +118 -0
  192. code_puppy_core_plugins/namespace_skill_search/__init__.py +15 -0
  193. code_puppy_core_plugins/namespace_skill_search/namespaces.py +125 -0
  194. code_puppy_core_plugins/namespace_skill_search/register_callbacks.py +99 -0
  195. code_puppy_core_plugins/namespace_skill_search/search_tool.py +158 -0
  196. code_puppy_core_plugins/no_tools/__init__.py +0 -0
  197. code_puppy_core_plugins/no_tools/register_callbacks.py +42 -0
  198. code_puppy_core_plugins/oauth_pasteback.py +110 -0
  199. code_puppy_core_plugins/oauth_puppy_html.py +194 -0
  200. code_puppy_core_plugins/obsidian_agent/README.md +52 -0
  201. code_puppy_core_plugins/obsidian_agent/__init__.py +8 -0
  202. code_puppy_core_plugins/obsidian_agent/agent_obsidian.py +147 -0
  203. code_puppy_core_plugins/obsidian_agent/register_callbacks.py +13 -0
  204. code_puppy_core_plugins/ollama/__init__.py +1 -0
  205. code_puppy_core_plugins/ollama/register_callbacks.py +127 -0
  206. code_puppy_core_plugins/ollama_setup/__init__.py +5 -0
  207. code_puppy_core_plugins/ollama_setup/completer.py +38 -0
  208. code_puppy_core_plugins/ollama_setup/register_callbacks.py +419 -0
  209. code_puppy_core_plugins/plugin_list/__init__.py +0 -0
  210. code_puppy_core_plugins/plugin_list/plugin_contributions.py +348 -0
  211. code_puppy_core_plugins/plugin_list/plugin_meta.py +67 -0
  212. code_puppy_core_plugins/plugin_list/plugin_text_utils.py +173 -0
  213. code_puppy_core_plugins/plugin_list/plugins_menu.py +455 -0
  214. code_puppy_core_plugins/plugin_list/plugins_menu_layout.py +194 -0
  215. code_puppy_core_plugins/plugin_list/plugins_menu_render.py +431 -0
  216. code_puppy_core_plugins/plugin_list/project_trust_flow.py +162 -0
  217. code_puppy_core_plugins/plugin_list/register_callbacks.py +281 -0
  218. code_puppy_core_plugins/pop_command/__init__.py +1 -0
  219. code_puppy_core_plugins/pop_command/register_callbacks.py +191 -0
  220. code_puppy_core_plugins/prompt_newline/__init__.py +13 -0
  221. code_puppy_core_plugins/prompt_newline/config.py +21 -0
  222. code_puppy_core_plugins/prompt_newline/register_callbacks.py +163 -0
  223. code_puppy_core_plugins/prune/__init__.py +1 -0
  224. code_puppy_core_plugins/prune/prune_menu.py +308 -0
  225. code_puppy_core_plugins/prune/prune_model.py +517 -0
  226. code_puppy_core_plugins/prune/prune_render.py +354 -0
  227. code_puppy_core_plugins/prune/register_callbacks.py +388 -0
  228. code_puppy_core_plugins/puppy_kennel/README.md +203 -0
  229. code_puppy_core_plugins/puppy_kennel/__init__.py +6 -0
  230. code_puppy_core_plugins/puppy_kennel/commands.py +206 -0
  231. code_puppy_core_plugins/puppy_kennel/config.py +36 -0
  232. code_puppy_core_plugins/puppy_kennel/kennel.py +368 -0
  233. code_puppy_core_plugins/puppy_kennel/packer.py +152 -0
  234. code_puppy_core_plugins/puppy_kennel/recorder.py +83 -0
  235. code_puppy_core_plugins/puppy_kennel/register_callbacks.py +109 -0
  236. code_puppy_core_plugins/puppy_kennel/retriever.py +28 -0
  237. code_puppy_core_plugins/puppy_kennel/schema.py +78 -0
  238. code_puppy_core_plugins/puppy_kennel/state.py +68 -0
  239. code_puppy_core_plugins/puppy_kennel/tools.py +449 -0
  240. code_puppy_core_plugins/puppy_kennel/wings.py +110 -0
  241. code_puppy_core_plugins/puppy_spinner/README.md +93 -0
  242. code_puppy_core_plugins/puppy_spinner/__init__.py +11 -0
  243. code_puppy_core_plugins/puppy_spinner/builtin_frames.py +172 -0
  244. code_puppy_core_plugins/puppy_spinner/commands.py +116 -0
  245. code_puppy_core_plugins/puppy_spinner/picker.py +379 -0
  246. code_puppy_core_plugins/puppy_spinner/register_callbacks.py +193 -0
  247. code_puppy_core_plugins/puppy_spinner/spinners.py +444 -0
  248. code_puppy_core_plugins/quick_resume/__init__.py +0 -0
  249. code_puppy_core_plugins/quick_resume/register_callbacks.py +77 -0
  250. code_puppy_core_plugins/review_pr/__init__.py +1 -0
  251. code_puppy_core_plugins/review_pr/register_callbacks.py +162 -0
  252. code_puppy_core_plugins/shell_safety/__init__.py +6 -0
  253. code_puppy_core_plugins/shell_safety/agent_shell_safety.py +69 -0
  254. code_puppy_core_plugins/shell_safety/command_cache.py +156 -0
  255. code_puppy_core_plugins/shell_safety/register_callbacks.py +203 -0
  256. code_puppy_core_plugins/stack_dump/__init__.py +1 -0
  257. code_puppy_core_plugins/stack_dump/register_callbacks.py +79 -0
  258. code_puppy_core_plugins/statusline/__init__.py +14 -0
  259. code_puppy_core_plugins/statusline/config.py +68 -0
  260. code_puppy_core_plugins/statusline/payload.py +138 -0
  261. code_puppy_core_plugins/statusline/prompt_patch.py +76 -0
  262. code_puppy_core_plugins/statusline/register_callbacks.py +45 -0
  263. code_puppy_core_plugins/statusline/runner.py +122 -0
  264. code_puppy_core_plugins/statusline/statusline_command.py +197 -0
  265. code_puppy_core_plugins/steer_queue/__init__.py +10 -0
  266. code_puppy_core_plugins/steer_queue/queue_menu.py +444 -0
  267. code_puppy_core_plugins/steer_queue/register_callbacks.py +138 -0
  268. code_puppy_core_plugins/subagent_panel/README.md +102 -0
  269. code_puppy_core_plugins/subagent_panel/__init__.py +24 -0
  270. code_puppy_core_plugins/subagent_panel/coalesce_patch.py +242 -0
  271. code_puppy_core_plugins/subagent_panel/panel_render.py +145 -0
  272. code_puppy_core_plugins/subagent_panel/register_callbacks.py +535 -0
  273. code_puppy_core_plugins/subagent_panel/resume_repaint.py +112 -0
  274. code_puppy_core_plugins/subagent_panel/state.py +231 -0
  275. code_puppy_core_plugins/switch_agent_resume/__init__.py +5 -0
  276. code_puppy_core_plugins/switch_agent_resume/register_callbacks.py +314 -0
  277. code_puppy_core_plugins/theme/README.md +86 -0
  278. code_puppy_core_plugins/theme/__init__.py +14 -0
  279. code_puppy_core_plugins/theme/bundled_palettes.py +346 -0
  280. code_puppy_core_plugins/theme/content_styles.py +146 -0
  281. code_puppy_core_plugins/theme/osc_palette.py +178 -0
  282. code_puppy_core_plugins/theme/picker.py +358 -0
  283. code_puppy_core_plugins/theme/prompt_toolkit_theme.py +113 -0
  284. code_puppy_core_plugins/theme/register_callbacks.py +348 -0
  285. code_puppy_core_plugins/theme/rich_themes.py +202 -0
  286. code_puppy_core_plugins/theme/themes.py +720 -0
  287. code_puppy_core_plugins/timestamp_heartbeat/__init__.py +1 -0
  288. code_puppy_core_plugins/timestamp_heartbeat/register_callbacks.py +114 -0
  289. code_puppy_core_plugins/token_ratio_learner/__init__.py +5 -0
  290. code_puppy_core_plugins/token_ratio_learner/ratios.py +208 -0
  291. code_puppy_core_plugins/token_ratio_learner/register_callbacks.py +213 -0
  292. code_puppy_core_plugins/universal_constructor/__init__.py +13 -0
  293. code_puppy_core_plugins/universal_constructor/models.py +138 -0
  294. code_puppy_core_plugins/universal_constructor/provider.py +62 -0
  295. code_puppy_core_plugins/universal_constructor/register_callbacks.py +75 -0
  296. code_puppy_core_plugins/universal_constructor/registry.py +302 -0
  297. code_puppy_core_plugins/universal_constructor/sandbox.py +584 -0
  298. code_puppy_core_plugins/wide_completion_menu/__init__.py +6 -0
  299. code_puppy_core_plugins/wide_completion_menu/register_callbacks.py +165 -0
  300. code_puppy_core_plugins/wiggum/__init__.py +1 -0
  301. code_puppy_core_plugins/wiggum/goal_runs.py +91 -0
  302. code_puppy_core_plugins/wiggum/judge.py +299 -0
  303. code_puppy_core_plugins/wiggum/judge_config.py +249 -0
  304. code_puppy_core_plugins/wiggum/judges_menu.py +814 -0
  305. code_puppy_core_plugins/wiggum/register_callbacks.py +569 -0
  306. code_puppy_core_plugins/wiggum/state.py +89 -0
  307. code_puppy_core_plugins/yolo_cli/__init__.py +1 -0
  308. code_puppy_core_plugins/yolo_cli/register_callbacks.py +41 -0
  309. code_puppy_core_plugins-0.0.2.dist-info/METADATA +64 -0
  310. code_puppy_core_plugins-0.0.2.dist-info/RECORD +313 -0
  311. code_puppy_core_plugins-0.0.2.dist-info/WHEEL +4 -0
  312. code_puppy_core_plugins-0.0.2.dist-info/entry_points.txt +55 -0
  313. code_puppy_core_plugins-0.0.2.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,62 @@
1
+ """Slash commands for explicit computer-use authorization."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import shlex
6
+
7
+ from code_puppy.messaging import emit_error, emit_info, emit_success, emit_warning
8
+
9
+ from .policy import policy_store
10
+
11
+
12
+ def command_help() -> list[tuple[str, str]]:
13
+ return [
14
+ (
15
+ "computer-use",
16
+ "Enable, disable, pause, or configure macOS Computer Use",
17
+ )
18
+ ]
19
+
20
+
21
+ def handle_command(command: str, name: str) -> bool | None:
22
+ if name != "computer-use":
23
+ return None
24
+ try:
25
+ tokens = shlex.split(command)
26
+ except ValueError as exc:
27
+ emit_error(f"Invalid /computer-use command: {exc}")
28
+ return True
29
+ subcommand = tokens[1].casefold() if len(tokens) > 1 else "status"
30
+ if subcommand == "status":
31
+ emit_info(f"Computer Use policy: {policy_store.status()}")
32
+ elif subcommand in {"enable", "disable"}:
33
+ enabled = subcommand == "enable"
34
+ policy_store.set_enabled(enabled)
35
+ if enabled:
36
+ emit_success(
37
+ "Computer Use enabled. It can now view and control allowed apps."
38
+ )
39
+ else:
40
+ emit_warning("Computer Use disabled in settings.")
41
+ elif subcommand == "pause":
42
+ policy_store.set_paused(True)
43
+ emit_warning("Computer Use paused immediately.")
44
+ elif subcommand == "resume":
45
+ policy_store.set_paused(False)
46
+ emit_success("Computer Use resumed.")
47
+ elif subcommand in {"allow", "deny"}:
48
+ if len(tokens) < 3:
49
+ emit_error("Usage: /computer-use allow|deny BUNDLE_ID")
50
+ return True
51
+ bundle_id = tokens[2]
52
+ if subcommand == "deny":
53
+ policy_store.deny(bundle_id)
54
+ emit_warning(f"Computer Use denied for {bundle_id}.")
55
+ else:
56
+ policy_store.allow(bundle_id)
57
+ emit_success(f"Computer Use allowed for {bundle_id}.")
58
+ else:
59
+ emit_error(
60
+ "Usage: /computer-use [status|enable|disable|pause|resume|allow|deny]"
61
+ )
62
+ return True
@@ -0,0 +1,81 @@
1
+ """Coordinate spaces used by macOS computer use."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass
6
+
7
+ from .backend_types import ComputerUseError
8
+
9
+
10
+ @dataclass(frozen=True)
11
+ class Rect:
12
+ x: float
13
+ y: float
14
+ width: float
15
+ height: float
16
+
17
+ def as_dict(self) -> dict[str, float]:
18
+ return {
19
+ "x": self.x,
20
+ "y": self.y,
21
+ "width": self.width,
22
+ "height": self.height,
23
+ }
24
+
25
+
26
+ @dataclass(frozen=True)
27
+ class CaptureGeometry:
28
+ """Mapping between screenshot pixels and global Quartz screen points.
29
+
30
+ ScreenCaptureKit and CGWindow bounds use a top-left global coordinate
31
+ system. AppKit uses bottom-left coordinates; callers that provide AppKit
32
+ coordinates must opt into the explicit conversion helper below.
33
+ """
34
+
35
+ window_points: Rect
36
+ image_width_pixels: int
37
+ image_height_pixels: int
38
+ backing_scale: float
39
+
40
+ def __post_init__(self) -> None:
41
+ if self.window_points.width <= 0 or self.window_points.height <= 0:
42
+ raise ComputerUseError("Window bounds must have positive dimensions.")
43
+ if self.image_width_pixels <= 0 or self.image_height_pixels <= 0:
44
+ raise ComputerUseError("Screenshot dimensions must be positive.")
45
+ if self.backing_scale <= 0:
46
+ raise ComputerUseError("Backing scale must be positive.")
47
+
48
+ def screenshot_to_quartz(self, x: float, y: float) -> tuple[float, float]:
49
+ if not (0 <= x < self.image_width_pixels):
50
+ raise ComputerUseError(
51
+ f"Screenshot x={x} is outside 0..{self.image_width_pixels - 1}."
52
+ )
53
+ if not (0 <= y < self.image_height_pixels):
54
+ raise ComputerUseError(
55
+ f"Screenshot y={y} is outside 0..{self.image_height_pixels - 1}."
56
+ )
57
+ return (
58
+ self.window_points.x
59
+ + (float(x) / self.image_width_pixels) * self.window_points.width,
60
+ self.window_points.y
61
+ + (float(y) / self.image_height_pixels) * self.window_points.height,
62
+ )
63
+
64
+ @staticmethod
65
+ def appkit_to_quartz(
66
+ x: float, y: float, display_points: Rect
67
+ ) -> tuple[float, float]:
68
+ """Convert bottom-left AppKit coordinates to top-left Quartz points."""
69
+ return x, display_points.y + display_points.height - (y - display_points.y)
70
+
71
+ def as_dict(self) -> dict[str, object]:
72
+ return {
73
+ "window_bounds_points": self.window_points.as_dict(),
74
+ "screenshot_size_pixels": {
75
+ "width": self.image_width_pixels,
76
+ "height": self.image_height_pixels,
77
+ },
78
+ "backing_scale": self.backing_scale,
79
+ "screenshot_coordinate_system": "top-left, window-local pixels",
80
+ "action_coordinate_system": "top-left, global Quartz points",
81
+ }
@@ -0,0 +1,56 @@
1
+ """Best-effort inline image display for modern terminals."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import base64
6
+ import os
7
+ import sys
8
+ from pathlib import Path
9
+
10
+
11
+ def _terminal_kind() -> str | None:
12
+ program = os.environ.get("TERM_PROGRAM", "").casefold()
13
+ term = os.environ.get("TERM", "").casefold()
14
+ if os.environ.get("ITERM_SESSION_ID") or program == "iterm.app":
15
+ return "iterm"
16
+ if (
17
+ program in {"ghostty", "wezterm"}
18
+ or os.environ.get("KITTY_WINDOW_ID")
19
+ or "ghostty" in term
20
+ or "kitty" in term
21
+ ):
22
+ return "kitty"
23
+ return None
24
+
25
+
26
+ def emit_inline_image(path: str | Path) -> bool:
27
+ """Render a PNG using iTerm2 or Kitty graphics escape sequences."""
28
+ image_path = Path(path)
29
+ kind = _terminal_kind()
30
+ if kind is None or not sys.stdout.isatty() or not image_path.is_file():
31
+ return False
32
+
33
+ try:
34
+ if kind == "iterm":
35
+ data = base64.b64encode(image_path.read_bytes()).decode("ascii")
36
+ name = base64.b64encode(image_path.name.encode()).decode("ascii")
37
+ sequence = (
38
+ f"\033]1337;File=name={name};inline=1;width=50%;"
39
+ f"preserveAspectRatio=1:{data}\a\n"
40
+ )
41
+ else:
42
+ encoded_path = base64.b64encode(str(image_path.resolve()).encode()).decode(
43
+ "ascii"
44
+ )
45
+ # Direct file transmission keeps the full screenshot out of the terminal
46
+ # stream; q=2 suppresses replies, c/r bound it to a compact PiP preview.
47
+ sequence = f"\033_Ga=T,t=f,f=100,q=2,c=64,r=22;{encoded_path}\033\\\n"
48
+
49
+ from code_puppy.messaging.run_ui import suspended_run_ui
50
+
51
+ with suspended_run_ui():
52
+ sys.stdout.write(sequence)
53
+ sys.stdout.flush()
54
+ except Exception:
55
+ return False
56
+ return True
@@ -0,0 +1,47 @@
1
+ """macOS virtual key codes for keys exposed by the computer-use tool."""
2
+
3
+ KEY_CODES = {
4
+ "return": 36,
5
+ "enter": 36,
6
+ "tab": 48,
7
+ "space": 49,
8
+ "delete": 51,
9
+ "escape": 53,
10
+ "left": 123,
11
+ "right": 124,
12
+ "down": 125,
13
+ "up": 126,
14
+ **dict(
15
+ zip(
16
+ "abcdefghijklmnopqrstuvwxyz",
17
+ (
18
+ 0,
19
+ 11,
20
+ 8,
21
+ 2,
22
+ 14,
23
+ 3,
24
+ 5,
25
+ 4,
26
+ 34,
27
+ 38,
28
+ 40,
29
+ 37,
30
+ 46,
31
+ 45,
32
+ 31,
33
+ 35,
34
+ 12,
35
+ 15,
36
+ 1,
37
+ 17,
38
+ 32,
39
+ 9,
40
+ 13,
41
+ 7,
42
+ 16,
43
+ 6,
44
+ ),
45
+ )
46
+ ),
47
+ }
@@ -0,0 +1,144 @@
1
+ """Persisted computer-use consent, explicit denials, and hard stops."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ import os
7
+ import threading
8
+ from pathlib import Path
9
+ from typing import Any
10
+
11
+ from code_puppy.config import CONFIG_DIR
12
+
13
+ from .backend_types import ComputerUseError
14
+
15
+ POLICY_PATH = Path(CONFIG_DIR) / "computer_use_policy.json"
16
+ SYSTEM_DENYLIST = {
17
+ "com.apple.loginwindow",
18
+ "com.apple.securityagent",
19
+ "com.apple.systempreferences",
20
+ "com.apple.systemsettings",
21
+ "com.apple.keychainaccess",
22
+ "com.apple.authorizationhost",
23
+ }
24
+
25
+
26
+ class PolicyStore:
27
+ def __init__(self, path: Path = POLICY_PATH) -> None:
28
+ self.path = path
29
+ self._paused = False
30
+ self._lock = threading.RLock()
31
+
32
+ def _load(self) -> dict[str, Any]:
33
+ if not self.path.is_file():
34
+ return {"enabled": None, "denied": []}
35
+ try:
36
+ payload = json.loads(self.path.read_text())
37
+ except (OSError, json.JSONDecodeError):
38
+ return {"enabled": None, "denied": []}
39
+ enabled = payload.get("enabled")
40
+ return {
41
+ "enabled": enabled if isinstance(enabled, bool) else None,
42
+ "denied": list(payload.get("denied", [])),
43
+ }
44
+
45
+ def _save(self, payload: dict[str, Any]) -> None:
46
+ self.path.parent.mkdir(parents=True, exist_ok=True, mode=0o700)
47
+ temporary = self.path.with_suffix(".tmp")
48
+ temporary.write_text(json.dumps(payload, indent=2, sort_keys=True))
49
+ os.chmod(temporary, 0o600)
50
+ temporary.replace(self.path)
51
+
52
+ def allow(self, bundle_id: str) -> None:
53
+ """Remove an explicit denial; all other applications are allowed."""
54
+ normalized = bundle_id.casefold()
55
+ if normalized in SYSTEM_DENYLIST:
56
+ raise ComputerUseError(
57
+ f"Computer Use is never allowed for security process {bundle_id}."
58
+ )
59
+ with self._lock:
60
+ payload = self._load()
61
+ denied = {str(item).casefold() for item in payload["denied"]}
62
+ denied.discard(normalized)
63
+ payload["denied"] = sorted(denied)
64
+ self._save(payload)
65
+
66
+ def deny(self, bundle_id: str) -> None:
67
+ normalized = bundle_id.casefold()
68
+ with self._lock:
69
+ payload = self._load()
70
+ denied = {str(item).casefold() for item in payload["denied"]}
71
+ denied.add(normalized)
72
+ payload["denied"] = sorted(denied)
73
+ self._save(payload)
74
+
75
+ def set_enabled(self, enabled: bool) -> None:
76
+ with self._lock:
77
+ payload = self._load()
78
+ payload["enabled"] = enabled
79
+ self._save(payload)
80
+
81
+ def set_paused(self, paused: bool) -> None:
82
+ with self._lock:
83
+ self._paused = paused
84
+
85
+ def is_enabled(self) -> bool:
86
+ """Return whether the user explicitly opted in to Computer Use."""
87
+ with self._lock:
88
+ return self._load()["enabled"] is True
89
+
90
+ def require_enabled(self) -> None:
91
+ with self._lock:
92
+ if self._paused:
93
+ raise ComputerUseError(
94
+ "Computer Use is paused by the emergency stop. Run "
95
+ "`/computer-use resume` after confirming it is safe."
96
+ )
97
+ payload = self._load()
98
+ if payload["enabled"] is None:
99
+ raise ComputerUseError(
100
+ "Computer Use needs your one-time permission before its first "
101
+ "use. It can view screenshots and control apps on this Mac. "
102
+ "Run `/computer-use enable` to allow it, or "
103
+ "`/computer-use disable` to keep it off. You can change this "
104
+ "setting later with the same commands."
105
+ )
106
+ if payload["enabled"] is False:
107
+ raise ComputerUseError(
108
+ "Computer Use is disabled in settings. Run "
109
+ "`/computer-use enable` to turn it on."
110
+ )
111
+
112
+ def require(self, bundle_id: str) -> None:
113
+ self.require_enabled()
114
+ normalized = bundle_id.casefold()
115
+ with self._lock:
116
+ if normalized in SYSTEM_DENYLIST:
117
+ raise ComputerUseError(
118
+ f"Computer Use is blocked for security process {bundle_id}."
119
+ )
120
+ payload = self._load()
121
+ denied = {str(item).casefold() for item in payload["denied"]}
122
+ if normalized in denied:
123
+ raise ComputerUseError(
124
+ f"Computer Use is denied for application {bundle_id}."
125
+ )
126
+
127
+ def status(self) -> dict[str, Any]:
128
+ with self._lock:
129
+ payload = self._load()
130
+ return {
131
+ "mode": (
132
+ "enabled"
133
+ if payload["enabled"] is True
134
+ else "disabled"
135
+ if payload["enabled"] is False
136
+ else "needs-first-use-consent"
137
+ ),
138
+ "paused": self._paused,
139
+ "denied": payload["denied"],
140
+ "system_denied": sorted(SYSTEM_DENYLIST),
141
+ }
142
+
143
+
144
+ policy_store = PolicyStore()
@@ -0,0 +1,96 @@
1
+ """Register the macOS computer-use tools as an optional builtin plugin."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import sys
6
+ from typing import Any
7
+
8
+ from code_puppy.callbacks import register_callback
9
+ from code_puppy.i18n import t
10
+ from code_puppy.messaging import emit_info
11
+
12
+ from .policy import policy_store
13
+
14
+ _TOOL_NAMES = (
15
+ "computer_get_app_state",
16
+ "computer_snapshot",
17
+ "computer_click",
18
+ "computer_set_value",
19
+ "computer_perform_action",
20
+ "computer_select_text",
21
+ "computer_press_key",
22
+ "computer_type_text",
23
+ "computer_scroll",
24
+ "computer_drag",
25
+ "computer_screenshot",
26
+ "computer_use_batch",
27
+ )
28
+
29
+
30
+ def _available() -> bool:
31
+ return sys.platform == "darwin"
32
+
33
+
34
+ def _enabled() -> bool:
35
+ return _available() and policy_store.is_enabled()
36
+
37
+
38
+ def _register_tools() -> list[dict[str, Any]]:
39
+ if not _enabled():
40
+ return []
41
+
42
+ from .tools import REGISTRARS
43
+
44
+ return [{"name": name, "register_func": REGISTRARS[name]} for name in _TOOL_NAMES]
45
+
46
+
47
+ def _register_agent_tools(agent_name: str | None = None) -> list[str]:
48
+ del agent_name
49
+ return list(_TOOL_NAMES) if _enabled() else []
50
+
51
+
52
+ def _load_prompt() -> str | None:
53
+ if not _enabled():
54
+ return None
55
+ return (
56
+ "macOS Computer Use requires persisted one-time user consent. If a tool "
57
+ "reports that consent is unset or disabled, show its exact slash command "
58
+ "to the user and do not work around it. Slash commands are not visible in "
59
+ "conversation history, so never repeat an old consent error from memory. "
60
+ "When the user repeats the request, always call the appropriate Computer "
61
+ "Use state tool again; the tool's current result is authoritative. Once "
62
+ "enabled, do not ask for per-application approval. Prefer "
63
+ "computer_get_app_state and element IDs over screen coordinates. Every "
64
+ "standalone mutation needs its current state_revision; guarded batches "
65
+ "return fresh state after deterministic UI settling. For pixel-based "
66
+ "focus-and-type workflows, use one guarded batch instead of guessing across "
67
+ "separate revisions. Verify the returned state and recover until the "
68
+ "requested outcome is visibly complete. Do not stop merely because the user "
69
+ "moves the pointer or types. The emergency stop and hard macOS "
70
+ "security-process denylist remain enforced."
71
+ )
72
+
73
+
74
+ def _startup() -> None:
75
+ if _available() and not policy_store.is_enabled():
76
+ emit_info(t("computer_use.startup.opt_in"))
77
+
78
+
79
+ def _custom_help():
80
+ from .commands import command_help
81
+
82
+ return command_help()
83
+
84
+
85
+ def _custom_command(command: str, name: str):
86
+ from .commands import handle_command
87
+
88
+ return handle_command(command, name)
89
+
90
+
91
+ register_callback("startup", _startup)
92
+ register_callback("register_tools", _register_tools)
93
+ register_callback("register_agent_tools", _register_agent_tools)
94
+ register_callback("load_prompt", _load_prompt)
95
+ register_callback("custom_command_help", _custom_help)
96
+ register_callback("custom_command", _custom_command)
@@ -0,0 +1,18 @@
1
+ """Shared policy and stale-state enforcement."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from .policy import policy_store
6
+ from .state import AppState, state_store
7
+
8
+
9
+ def require_safe_state(
10
+ revision: str,
11
+ *,
12
+ consume: bool = False,
13
+ ) -> AppState:
14
+ state = state_store.require(revision)
15
+ policy_store.require(state.bundle_id)
16
+ if consume:
17
+ return state_store.require(revision, consume=True)
18
+ return state
@@ -0,0 +1,64 @@
1
+ """Deterministic UI settling based on accessibility-state stability."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import hashlib
6
+ import json
7
+ import time
8
+ from typing import Any, Callable
9
+
10
+
11
+ def _fingerprint(snapshot: dict[str, Any]) -> str:
12
+ normalized = [
13
+ {
14
+ key: node.get(key)
15
+ for key in (
16
+ "role",
17
+ "title",
18
+ "description",
19
+ "value",
20
+ "enabled",
21
+ "focused",
22
+ "actions",
23
+ )
24
+ }
25
+ for node in snapshot.get("nodes", [])
26
+ ]
27
+ encoded = json.dumps(normalized, sort_keys=True, ensure_ascii=False).encode()
28
+ return hashlib.sha256(encoded).hexdigest()
29
+
30
+
31
+ def wait_for_ui_settle(
32
+ snapshotter: Callable[[str, int], dict[str, Any]],
33
+ app_name: str,
34
+ timeout: float = 3.0,
35
+ interval: float = 0.1,
36
+ stable_observations: int = 3,
37
+ ) -> dict[str, Any]:
38
+ """Return after the focused accessibility state repeats consecutively."""
39
+ deadline = time.monotonic() + max(0.1, timeout)
40
+ previous = None
41
+ stable = 0
42
+ observations = 0
43
+ while time.monotonic() < deadline:
44
+ snapshot = snapshotter(app_name, 120)
45
+ observations += 1
46
+ fingerprint = _fingerprint(snapshot)
47
+ if fingerprint == previous:
48
+ stable += 1
49
+ if stable >= stable_observations:
50
+ return {
51
+ "settled": True,
52
+ "observations": observations,
53
+ "fingerprint": fingerprint,
54
+ }
55
+ else:
56
+ previous = fingerprint
57
+ stable = 0
58
+ time.sleep(max(0.01, interval))
59
+ return {
60
+ "settled": False,
61
+ "observations": observations,
62
+ "fingerprint": previous,
63
+ "reason": "timeout",
64
+ }
@@ -0,0 +1,86 @@
1
+ """Revisioned computer-use state shared by snapshots and actions."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import threading
6
+ import time
7
+ import uuid
8
+ from dataclasses import dataclass, field
9
+ from typing import Any
10
+
11
+ from .backend_types import ComputerUseError
12
+ from .geometry import CaptureGeometry
13
+
14
+
15
+ @dataclass
16
+ class AppState:
17
+ revision: str
18
+ application: str
19
+ bundle_id: str
20
+ pid: int
21
+ window_id: int
22
+ window_title: str
23
+ geometry: CaptureGeometry
24
+ screenshot_path: str
25
+ elements: dict[int, Any] = field(repr=False)
26
+ created_at: float = field(default_factory=time.monotonic)
27
+ consumed: bool = False
28
+
29
+ def public_metadata(self) -> dict[str, Any]:
30
+ return {
31
+ "state_revision": self.revision,
32
+ "application": self.application,
33
+ "bundle_id": self.bundle_id,
34
+ "pid": self.pid,
35
+ "window_id": self.window_id,
36
+ "window_title": self.window_title,
37
+ "screenshot_path": self.screenshot_path,
38
+ **self.geometry.as_dict(),
39
+ }
40
+
41
+
42
+ class StateStore:
43
+ def __init__(self, max_age_seconds: float = 120.0) -> None:
44
+ self._state: AppState | None = None
45
+ self._lock = threading.RLock()
46
+ self.max_age_seconds = max_age_seconds
47
+
48
+ def create(self, **kwargs: Any) -> AppState:
49
+ state = AppState(revision=uuid.uuid4().hex, **kwargs)
50
+ with self._lock:
51
+ self._state = state
52
+ return state
53
+
54
+ def require(self, revision: str, *, consume: bool = False) -> AppState:
55
+ if not revision:
56
+ raise ComputerUseError(
57
+ "state_revision is required. Call computer_get_app_state first."
58
+ )
59
+ with self._lock:
60
+ state = self._state
61
+ if state is None or state.revision != revision:
62
+ raise ComputerUseError(
63
+ "Stale or unknown state_revision. Call computer_get_app_state again."
64
+ )
65
+ if time.monotonic() - state.created_at > self.max_age_seconds:
66
+ raise ComputerUseError(
67
+ "The app state expired. Call computer_get_app_state again."
68
+ )
69
+ if state.consumed:
70
+ raise ComputerUseError(
71
+ "The app state changed after an action. Fetch fresh app state."
72
+ )
73
+ if consume:
74
+ state.consumed = True
75
+ return state
76
+
77
+ def current(self) -> AppState | None:
78
+ with self._lock:
79
+ return self._state
80
+
81
+ def clear(self) -> None:
82
+ with self._lock:
83
+ self._state = None
84
+
85
+
86
+ state_store = StateStore()