crabcode 0.1.4__py3-none-any.whl → 0.1.6__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 (145) hide show
  1. {crabcode-0.1.4.dist-info → crabcode-0.1.6.dist-info}/METADATA +14 -1
  2. crabcode-0.1.6.dist-info/RECORD +203 -0
  3. {crabcode-0.1.4.dist-info → crabcode-0.1.6.dist-info}/WHEEL +1 -1
  4. crabcode_cli/app.py +289 -9
  5. crabcode_cli/banner.py +11 -14
  6. crabcode_cli/computer_use.py +286 -0
  7. crabcode_cli/model_manager.py +649 -0
  8. crabcode_cli/model_picker.py +168 -0
  9. crabcode_cli/pipe.py +13 -1
  10. crabcode_cli/repl.py +1320 -224
  11. crabcode_cli/session_picker.py +239 -0
  12. crabcode_core/_version.py +1 -1
  13. crabcode_core/_windows_process.py +68 -0
  14. crabcode_core/agent_manager.py +70 -3
  15. crabcode_core/api/anthropic_adapter.py +141 -20
  16. crabcode_core/api/azure_adapter.py +2 -1
  17. crabcode_core/api/base.py +100 -2
  18. crabcode_core/api/codex_adapter.py +627 -47
  19. crabcode_core/api/error_logging.py +132 -0
  20. crabcode_core/api/model_info.py +105 -0
  21. crabcode_core/api/network.py +62 -0
  22. crabcode_core/api/openai_adapter.py +63 -29
  23. crabcode_core/command_line.py +18 -0
  24. crabcode_core/compact/compact.py +50 -42
  25. crabcode_core/compact/context_tokens.py +165 -0
  26. crabcode_core/computer_use_mode.py +38 -0
  27. crabcode_core/computer_use_observation.py +144 -0
  28. crabcode_core/config/claudemd.py +8 -4
  29. crabcode_core/config/manager.py +88 -9
  30. crabcode_core/config/model_catalog.py +256 -0
  31. crabcode_core/events.py +783 -81
  32. crabcode_core/file_lock.py +81 -0
  33. crabcode_core/filesystem.py +22 -0
  34. crabcode_core/hooks/manager.py +17 -6
  35. crabcode_core/image_io.py +111 -0
  36. crabcode_core/io_worker.py +211 -0
  37. crabcode_core/logging_utils.py +65 -5
  38. crabcode_core/lsp/client.py +49 -20
  39. crabcode_core/lsp/diagnostics.py +23 -3
  40. crabcode_core/lsp/manager.py +2 -1
  41. crabcode_core/mcp/client.py +2 -1
  42. crabcode_core/mcp/config.py +4 -3
  43. crabcode_core/path_validation.py +34 -0
  44. crabcode_core/paths.py +24 -0
  45. crabcode_core/peer/runtime.py +60 -38
  46. crabcode_core/permissions/ai_reviewer.py +10 -2
  47. crabcode_core/permissions/manager.py +30 -7
  48. crabcode_core/prompts/blocks.py +10 -0
  49. crabcode_core/prompts/context.py +18 -9
  50. crabcode_core/prompts/library.py +92 -0
  51. crabcode_core/prompts/profile.py +14 -1
  52. crabcode_core/prompts/system.py +111 -286
  53. crabcode_core/prompts/templates.py +34 -5
  54. crabcode_core/query/computer_use_history.py +83 -0
  55. crabcode_core/query/loop.py +1038 -185
  56. crabcode_core/query/retry.py +116 -0
  57. crabcode_core/schedule/__init__.py +10 -2
  58. crabcode_core/schedule/manager.py +631 -0
  59. crabcode_core/schedule/store.py +218 -9
  60. crabcode_core/schedule/timing.py +287 -0
  61. crabcode_core/session/meta_db.py +190 -21
  62. crabcode_core/session/storage.py +624 -172
  63. crabcode_core/skills/context.py +23 -0
  64. crabcode_core/skills/loader.py +5 -3
  65. crabcode_core/snapshot/snapshot.py +17 -3
  66. crabcode_core/snapshot/tracker.py +118 -9
  67. crabcode_core/subprocess_utils.py +260 -0
  68. crabcode_core/team/inbox.py +48 -101
  69. crabcode_core/team/manager.py +3 -2
  70. crabcode_core/team/message_bus.py +47 -104
  71. crabcode_core/text_io.py +52 -0
  72. crabcode_core/tools/__init__.py +26 -0
  73. crabcode_core/tools/_input_schema.py +130 -0
  74. crabcode_core/tools/apply_patch.py +587 -0
  75. crabcode_core/tools/bash.py +46 -33
  76. crabcode_core/tools/browser.py +19 -3
  77. crabcode_core/tools/checkpoint.py +14 -2
  78. crabcode_core/tools/computer_use.py +599 -0
  79. crabcode_core/tools/diff_utils.py +5 -2
  80. crabcode_core/tools/file_edit.py +44 -5
  81. crabcode_core/tools/file_read.py +41 -8
  82. crabcode_core/tools/file_write.py +25 -4
  83. crabcode_core/tools/glob.py +8 -3
  84. crabcode_core/tools/grep.py +107 -20
  85. crabcode_core/tools/image.py +173 -0
  86. crabcode_core/tools/image_generate.py +115 -0
  87. crabcode_core/tools/lint.py +17 -8
  88. crabcode_core/tools/loading.py +187 -0
  89. crabcode_core/tools/memory.py +3 -3
  90. crabcode_core/tools/monitor.py +12 -26
  91. crabcode_core/tools/schedule.py +142 -71
  92. crabcode_core/tools/skill.py +2 -20
  93. crabcode_core/tools/tool_search.py +64 -0
  94. crabcode_core/tools/web_search.py +137 -13
  95. crabcode_core/turn_details.py +64 -0
  96. crabcode_core/types/__init__.py +6 -0
  97. crabcode_core/types/config.py +215 -3
  98. crabcode_core/types/event.py +64 -0
  99. crabcode_core/types/message.py +15 -0
  100. crabcode_core/types/tool.py +49 -0
  101. crabcode_core/usage.py +289 -0
  102. crabcode_debugger/adapters.py +7 -1
  103. crabcode_debugger/dap.py +88 -15
  104. crabcode_debugger/memory.py +157 -42
  105. crabcode_debugger/process.py +52 -17
  106. crabcode_debugger/runtime.py +40 -5
  107. crabcode_debugger/sessions.py +112 -68
  108. crabcode_debugger/tool.py +79 -8
  109. crabcode_gateway/__init__.py +12 -1
  110. crabcode_gateway/acp/agent.py +59 -17
  111. crabcode_gateway/acp/types.py +10 -2
  112. crabcode_gateway/auth.py +139 -0
  113. crabcode_gateway/computer_use.py +364 -0
  114. crabcode_gateway/document_engine.py +637 -0
  115. crabcode_gateway/document_worker.py +301 -0
  116. crabcode_gateway/event_bus.py +23 -12
  117. crabcode_gateway/grpc/server.py +36 -7
  118. crabcode_gateway/middleware.py +79 -17
  119. crabcode_gateway/protocol.py +17 -0
  120. crabcode_gateway/routes/agent.py +161 -10
  121. crabcode_gateway/routes/auth.py +150 -0
  122. crabcode_gateway/routes/computer_use.py +101 -0
  123. crabcode_gateway/routes/config.py +1359 -42
  124. crabcode_gateway/routes/document.py +1810 -0
  125. crabcode_gateway/routes/event.py +2431 -167
  126. crabcode_gateway/routes/git_review.py +232 -0
  127. crabcode_gateway/routes/peer.py +78 -0
  128. crabcode_gateway/routes/schedule.py +300 -0
  129. crabcode_gateway/routes/session.py +880 -165
  130. crabcode_gateway/routes/snapshot.py +74 -32
  131. crabcode_gateway/routes/tasks.py +318 -0
  132. crabcode_gateway/routes/team.py +392 -0
  133. crabcode_gateway/routes/usage.py +49 -0
  134. crabcode_gateway/routes/workspace.py +299 -0
  135. crabcode_gateway/safe_file.py +63 -0
  136. crabcode_gateway/schemas.py +1172 -8
  137. crabcode_gateway/server.py +147 -4
  138. crabcode_gateway/task_registry.py +75 -0
  139. crabcode_gateway/turn_details.py +60 -0
  140. crabcode_search/background.py +6 -9
  141. crabcode_search/indexer.py +10 -7
  142. crabcode_search/store.py +4 -4
  143. crabcode_search/tool.py +5 -1
  144. crabcode-0.1.4.dist-info/RECORD +0 -150
  145. {crabcode-0.1.4.dist-info → crabcode-0.1.6.dist-info}/entry_points.txt +0 -0
@@ -1,28 +1,35 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: crabcode
3
- Version: 0.1.4
3
+ Version: 0.1.6
4
4
  Summary: CrabCode - AI coding assistant in the terminal
5
5
  Requires-Python: >=3.10
6
6
  Requires-Dist: anthropic>=0.40.0
7
7
  Requires-Dist: httpx>=0.27.0
8
8
  Requires-Dist: mcp>=1.0.0
9
9
  Requires-Dist: openai>=1.50.0
10
+ Requires-Dist: pillow>=11.3.0
10
11
  Requires-Dist: prompt-toolkit>=3.0.0
11
12
  Requires-Dist: pydantic>=2.0.0
12
13
  Requires-Dist: rich>=13.0.0
13
14
  Requires-Dist: tiktoken>=0.7.0
14
15
  Requires-Dist: typer>=0.12.0
16
+ Requires-Dist: tzdata>=2024.1; sys_platform == 'win32'
15
17
  Requires-Dist: websockets>=12.0
16
18
  Provides-Extra: all
17
19
  Requires-Dist: agent-client-protocol>=0.9.0; extra == 'all'
18
20
  Requires-Dist: anthropic[bedrock]>=0.40.0; extra == 'all'
19
21
  Requires-Dist: anthropic[vertex]>=0.40.0; extra == 'all'
22
+ Requires-Dist: babeldoc==0.6.4; extra == 'all'
23
+ Requires-Dist: cryptography>=42.0.0; extra == 'all'
20
24
  Requires-Dist: fastapi>=0.115.0; extra == 'all'
21
25
  Requires-Dist: grpcio-health-checking>=1.65.0; extra == 'all'
22
26
  Requires-Dist: grpcio>=1.65.0; extra == 'all'
23
27
  Requires-Dist: httpx>=0.27.0; extra == 'all'
24
28
  Requires-Dist: modelscope>=1.10.0; extra == 'all'
25
29
  Requires-Dist: playwright>=1.48.0; extra == 'all'
30
+ Requires-Dist: pyjwt>=2.9.0; extra == 'all'
31
+ Requires-Dist: pypdf>=4.0.0; extra == 'all'
32
+ Requires-Dist: python-multipart>=0.0.9; extra == 'all'
26
33
  Requires-Dist: sentence-transformers>=2.0.0; extra == 'all'
27
34
  Requires-Dist: sse-starlette>=2.0.0; extra == 'all'
28
35
  Requires-Dist: tree-sitter-language-pack>=1.0.0; extra == 'all'
@@ -33,12 +40,18 @@ Requires-Dist: anthropic[bedrock]>=0.40.0; extra == 'bedrock'
33
40
  Provides-Extra: browser
34
41
  Requires-Dist: playwright>=1.48.0; extra == 'browser'
35
42
  Provides-Extra: debugger
43
+ Provides-Extra: document-translate
44
+ Requires-Dist: babeldoc==0.6.4; extra == 'document-translate'
36
45
  Provides-Extra: gateway
37
46
  Requires-Dist: agent-client-protocol>=0.9.0; extra == 'gateway'
47
+ Requires-Dist: cryptography>=42.0.0; extra == 'gateway'
38
48
  Requires-Dist: fastapi>=0.115.0; extra == 'gateway'
39
49
  Requires-Dist: grpcio-health-checking>=1.65.0; extra == 'gateway'
40
50
  Requires-Dist: grpcio>=1.65.0; extra == 'gateway'
41
51
  Requires-Dist: httpx>=0.27.0; extra == 'gateway'
52
+ Requires-Dist: pyjwt>=2.9.0; extra == 'gateway'
53
+ Requires-Dist: pypdf>=4.0.0; extra == 'gateway'
54
+ Requires-Dist: python-multipart>=0.0.9; extra == 'gateway'
42
55
  Requires-Dist: sse-starlette>=2.0.0; extra == 'gateway'
43
56
  Requires-Dist: uvicorn[standard]>=0.30.0; extra == 'gateway'
44
57
  Provides-Extra: search
@@ -0,0 +1,203 @@
1
+ crabcode_cli/__init__.py,sha256=vBL_d7W0Vt2kIaYI3iZ2yS7kZleJEQXTTlIBICm5GRY,136
2
+ crabcode_cli/__main__.py,sha256=ekwH_ayJ5YpefhbXSDj-IM9mS9YrCwWpoDIH92V6tjg,75
3
+ crabcode_cli/app.py,sha256=o7P9cQBTo7mY6OFDhaJVx39qdfj_Zqc2Qfku-z3eGSU,31579
4
+ crabcode_cli/banner.py,sha256=WlQPxVLLnzIE6xlP6gFbpCDYmDewzIwLtHKFLf9GC-I,1339
5
+ crabcode_cli/computer_use.py,sha256=n4N--P5i9-GBzcfsAbhM5J5ebPFt0P2_shbaHq1ZpyU,13570
6
+ crabcode_cli/model_manager.py,sha256=vEoD3JVyWGAnIoUAe4jspPA8dt5d3pvbRNQ_A0Ank6o,21459
7
+ crabcode_cli/model_picker.py,sha256=ghxsVySXy9WZVJLVb3ElTf9D2sWeT6lidcPWB0gX-_Y,8352
8
+ crabcode_cli/pipe.py,sha256=hIOqrkUNbm3jXXz7NRX-HlbbWb3uPlWZwO6UUpIhtvg,5431
9
+ crabcode_cli/repl.py,sha256=Bs_gBAa4cIyMjX0no_QEm9Ow68vghpIQE43_z-sVMq4,191906
10
+ crabcode_cli/session_picker.py,sha256=Pett41MV4xcg6vDR4Rbq8C0bh40u-GVF_cjQldNQIoQ,10307
11
+ crabcode_cli/render/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
+ crabcode_cli/render/messages.py,sha256=n9OsbLIAU3FyO9gwGMMJld7zq-71N0caz9ecmE2kIjo,568
13
+ crabcode_core/__init__.py,sha256=ArpgEg5xC3iR4DRT0HBg7DwU3K-r1MnmDOHpIb1b0E4,142
14
+ crabcode_core/_version.py,sha256=Dt9sZjC9UYWEhBzyy8qd6c9WoL9oj_Ct2KhDhWrK14E,82
15
+ crabcode_core/_windows_process.py,sha256=PjRQqZfLSHdvexANQYHZDQNxyu2s1Yaxt1YNlawwNIU,2949
16
+ crabcode_core/agent_manager.py,sha256=Wu7kHfA5_zSTHYLemqOD85deblcwDdtvnZVE4rmq-Vc,71475
17
+ crabcode_core/command_line.py,sha256=MWbAF4QUDVdwGM8cKoHYnIgr8yOgqk3Y_0ndt9f-t6Y,544
18
+ crabcode_core/computer_use_mode.py,sha256=_MZYkJisk2swSTDJToatIvmwifNXk_7AJY3pD3s62d0,1559
19
+ crabcode_core/computer_use_observation.py,sha256=mYTZJnUPnSK0rWkNKvd0NBYmEV0nKhJMGpA30GuXQIQ,6919
20
+ crabcode_core/events.py,sha256=3Et5UIg_vUaV2zidd3IwaH_JgMq7oSIln-su21Mcs-w,211356
21
+ crabcode_core/file_lock.py,sha256=MubMAy749yVzxBCsF1n3SaqQU3jtWqeb6yasZKFLOPU,3075
22
+ crabcode_core/filesystem.py,sha256=savLKfRLqSKyjiA-IftP9ZAL4t7fIarYPJ0QbyECmiA,695
23
+ crabcode_core/goal.py,sha256=PCpU9dyKpLcsKXvt4zigPvRSloKf64FUY4z5mUmqLWs,5231
24
+ crabcode_core/image_io.py,sha256=o0fJDBpuB73mGfU1alAaYtTaU7wvtXIbq8CCJvSAKr4,5006
25
+ crabcode_core/io_worker.py,sha256=Z0mnr3qfWH8xZm4xavX5StryqGAO3mKXScrg1VYseA0,8253
26
+ crabcode_core/logging_utils.py,sha256=2Br_7gbl5U-lylYeJwGfHU2MJAi-pr7jqsaK2--BYnE,5722
27
+ crabcode_core/path_validation.py,sha256=pssxal6fTjK3lgUD8a5KzeEhebroDW-QT3Ko3IbxVP4,1419
28
+ crabcode_core/paths.py,sha256=_jimGLpqF1yIiq4GJ2tFcS6xt0oB8cggSeVjSatQB9A,868
29
+ crabcode_core/subprocess_utils.py,sha256=BIgrTc4wcvx7eJopyU0lKgvixuN7mny7IuqrtNAu1c4,9893
30
+ crabcode_core/text_io.py,sha256=RwZUE-XCO9FcfoH0zDsF26BMuL4PpviEpZ5GJKB4hXI,1386
31
+ crabcode_core/turn_details.py,sha256=Km_qHTGz2OhnrRFJP9kuO02AcX1q-uTmR010vIh4WBE,2503
32
+ crabcode_core/usage.py,sha256=vNydrtitdH3Q690k-3x738LhKiJsXGcMw-ruOEL0csU,16307
33
+ crabcode_core/utf8_sanitize.py,sha256=RRTGgwA9jqK-HLR1WUSFwgG4xJn7ZukTDu7M6Oi3fHI,936
34
+ crabcode_core/api/__init__.py,sha256=IXs4hLgC4cT85TLdmS4KgtPKYDytadkwvrDyBshr5ag,674
35
+ crabcode_core/api/anthropic_adapter.py,sha256=VrQPYxAkd1hyq0GzOC-YQYp7GWJC43DDOAAXEmnoYZw,26432
36
+ crabcode_core/api/azure_adapter.py,sha256=pzh_4oq-Oqn8hmIU4orldtK9U_R_yONqc5BmoZHCiUE,2441
37
+ crabcode_core/api/base.py,sha256=2fAiYazrzbk5kb4oKARClnePT4IVn9cF2tgxxoeKbP4,8579
38
+ crabcode_core/api/codex_adapter.py,sha256=pgX8rzfdotUMQNDHWPiSW9QbmFrv0-MqPJ130ayCfNc,54775
39
+ crabcode_core/api/error_logging.py,sha256=2GMD8naR-Tk9Eki_i2GJQShAWGVvt6XZATs8SLXRR8Q,5326
40
+ crabcode_core/api/gemini_adapter.py,sha256=RVk3zlLPqDtzG8w5psu4aSoFyFLua5qQx3subqz-5DQ,1130
41
+ crabcode_core/api/model_info.py,sha256=xovzBB52FxkS7mFweltYYRtxiIHWVh13F9iel6xEt2c,8367
42
+ crabcode_core/api/network.py,sha256=108VR8Ix67bklhZoV2FIPNtQ_jrI7JXUjS9A98p81-I,2438
43
+ crabcode_core/api/ollama_adapter.py,sha256=ZpTg11zOUGFE0J88qBXL7AvxDQU5PjWg2wWvm4uxUvY,1158
44
+ crabcode_core/api/openai_adapter.py,sha256=HRrsmoc01qEo49hXU2VBbEZiMgUPvwXxgBtx3s_0NHo,12303
45
+ crabcode_core/api/registry.py,sha256=tCVRE74bMUn9ukCbGp3bDtSOYZ6_EmsNfdVnnkGN6k4,2413
46
+ crabcode_core/compact/__init__.py,sha256=9445RwiG5BI8b6mrXMcNkcPLs5NH3RSKFxDrXsgmmK8,395
47
+ crabcode_core/compact/compact.py,sha256=_5BjLhPJA7WkvQzBAor7d9QXF9Nluui7bZTtBNvPLpY,19580
48
+ crabcode_core/compact/context_tokens.py,sha256=ZOLoNFmwj_caf5_NIHDnoBM6ja0k0GLP1fykfi3rZmE,7473
49
+ crabcode_core/config/__init__.py,sha256=wbSnNVCqj673phu2pvIFz-f5HM5bLvH-FdD9b01HNRA,84
50
+ crabcode_core/config/claudemd.py,sha256=jl7HN7k-kJryOTGcJ7vEsP3_iw_TVKsq_Rx9VCMGKbA,2268
51
+ crabcode_core/config/manager.py,sha256=MqGYczrKUqFdl216ZVeEZ7-hseMA9QXM-lhr3eKaIb8,8497
52
+ crabcode_core/config/model_catalog.py,sha256=Vjhy3FbNsRTwvwH5x9aiZMCSEYD0e3_2SoxAmyfxwrg,8928
53
+ crabcode_core/hooks/__init__.py,sha256=wfOnbLuJqtLezKYWYmBTAE9qG-eaG7wSfgx1-kS7N64,165
54
+ crabcode_core/hooks/manager.py,sha256=bVbe08EAGbY-pNxgkTFzonOEP4kE49Z8Ly9gIq-mv2U,10072
55
+ crabcode_core/lsp/__init__.py,sha256=np9EYVvOi94ZFxLWW_kD13AfwaIhN0Vcp8-pHaLDn6c,189
56
+ crabcode_core/lsp/client.py,sha256=QQM3EuWxEz5ipnpalCzTC4P2kfnknVM3iOizm6Tdkv0,28043
57
+ crabcode_core/lsp/diagnostics.py,sha256=r2n2_BSIf5_MLjI8aEa27o7jq82VIpNn4tzJGbFL44Q,4971
58
+ crabcode_core/lsp/manager.py,sha256=LXK16-PwxnPZnjNoYLAew471QvG-gs5uKfgLCKieogY,19049
59
+ crabcode_core/mcp/__init__.py,sha256=axvOgOWHjpKs7WFEkf8Za_4mm_oNe0tYyD94dAMnWTE,182
60
+ crabcode_core/mcp/client.py,sha256=xXTWDgTCoFyj3T09zCctBF81IfSbtZw1Ds7qsSa13vY,5348
61
+ crabcode_core/mcp/config.py,sha256=iPPazGYrgJN7HBatO7YhiZ4i-Zo9lKinrqplkGUU0RI,2044
62
+ crabcode_core/peer/__init__.py,sha256=eXhG-X0ZT5KgV3BKVXYEB7tQDG2SM3Igdb0-7OPtY2k,234
63
+ crabcode_core/peer/runtime.py,sha256=j5sp2L5keQn-iDJvQsI8ZRQV4BMeb-5bAPIXkSkjqWg,20919
64
+ crabcode_core/permissions/__init__.py,sha256=grH8A95Lr5L-gsXOIkb-J6RldRdaktMEvKUcZize9r0,198
65
+ crabcode_core/permissions/ai_reviewer.py,sha256=2yJSSm40VzJpCZ2xvB0bVtohgLKy8ojkVCc84fUEu5Q,7663
66
+ crabcode_core/permissions/manager.py,sha256=c-69BmpwlMscpI1SuDmqMGKeKJTD8PJh4-992X-fXzc,7126
67
+ crabcode_core/plan/__init__.py,sha256=co_SEC__Z3OtijC9hxdVWIcdUBsUVsJnQ-LkxJfpAL8,169
68
+ crabcode_core/plan/executor.py,sha256=k9PmjAfmgZklYys5oUQW5xUD7Tc2JoB-gIcQEkIli7c,10442
69
+ crabcode_core/plan/types.py,sha256=pPfcdu40sTbxr8uBNAEguZR1GzvSFYDIL40HL_bU_io,5733
70
+ crabcode_core/prompts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
71
+ crabcode_core/prompts/blocks.py,sha256=pZZQ20oMNhy33osEwwwUtV3P0N3rtTZE4hRE8_rjvHY,438
72
+ crabcode_core/prompts/context.py,sha256=TBRVd0MzPKPTejgKIyBlzVJRkFguZnYZ2VX5Je_VJbg,8034
73
+ crabcode_core/prompts/library.py,sha256=-qqmSGYn-6xEN1u-E6BdH4eU3gfUDkrrMnS-Yaf7hSY,3089
74
+ crabcode_core/prompts/profile.py,sha256=YHdciNJQYnd55ampreJIRAzlmAyH5TthWYQtuijpd7M,2677
75
+ crabcode_core/prompts/system.py,sha256=a1Fha6d88TUCmk-oDBZWD4jA16wcSVBwS5xLhfsFFyw,18439
76
+ crabcode_core/prompts/templates.py,sha256=aJ2NcYdi44PqQEZ76ddvvd3cOw94TvDviTZlCF4ZB7c,3656
77
+ crabcode_core/query/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
78
+ crabcode_core/query/computer_use_history.py,sha256=-dEi8KcsROBXBzYd0MchJ43aCND7ZVTV_JUY1jiaHVI,4245
79
+ crabcode_core/query/loop.py,sha256=CWX0bdDgfkKsF9KIzGW5qgTbOBguJtu1hNsyciFkxAI,100471
80
+ crabcode_core/query/retry.py,sha256=dw9crwRe98aPSOy-8nkHWpb4c79m6FwvUBIVUO0xVgk,3847
81
+ crabcode_core/schedule/__init__.py,sha256=HMMnVlsG6sMiqufW3g-TSpH614evs1LQ2j2sbBjZpyk,387
82
+ crabcode_core/schedule/manager.py,sha256=M7bxOggqyqy1SBiWs8M0FDF6vnArldMm-M8gPu0mycs,24484
83
+ crabcode_core/schedule/models.py,sha256=T3Z7wapFCkuE_ZeIDK2Clq8WGThKs88ENjXklT1_LE8,7847
84
+ crabcode_core/schedule/store.py,sha256=iykmcpdTjcAQusobYvt1pQKZLz-x52UasiD0tH20ezk,20504
85
+ crabcode_core/schedule/timing.py,sha256=Belm63_XYo9nVrFUc8Njgp5rQ7ROPrQxAa_BXczdXe8,8881
86
+ crabcode_core/session/__init__.py,sha256=0E_Flt_OkcFVkxbRTDVxot3TrUZ23T5qspIJqlYnwtE,441
87
+ crabcode_core/session/export.py,sha256=pF_nT60XaqmeTxGgiLnGPnW-SeOFscI1V8qCCqOhlOE,4521
88
+ crabcode_core/session/meta_db.py,sha256=jyEM6NDh1dwdMSfkpPk_jDNZH4qw-wEXq6w6OcbTSpI,27593
89
+ crabcode_core/session/storage.py,sha256=LHd-GyUVZTGb_0TZIXBh0q-LJrwcA1DgD5rVhoyqImI,87867
90
+ crabcode_core/session/title_gen.py,sha256=TrIqrWRSScZjVGOaG3h4zl7PhxPMD-86zLIYcVdElP4,1507
91
+ crabcode_core/skills/__init__.py,sha256=2A99hK6_T53EPy-hcYYu4FobhUAZjLL-O7ObIyG3yuQ,296
92
+ crabcode_core/skills/context.py,sha256=emD4JSloR-CKOusGp8YS_pRlnCGWjTgYXyI5J0rBNWY,918
93
+ crabcode_core/skills/loader.py,sha256=vdmQZHKnxav0Eo2oym6rDBRxAZo5ADknQYEFeKUQVm4,7198
94
+ crabcode_core/skills/matcher.py,sha256=gPt-nYz9YmUK_Pb3KjivrYl6izDSBiYo3HlrDhxcggs,7066
95
+ crabcode_core/snapshot/__init__.py,sha256=ACgq5C5_ChCXTW8UJWzhWz8vAJLw5MKtNyt9F1fYKQk,418
96
+ crabcode_core/snapshot/snapshot.py,sha256=djOUndI3kM3yFCYVUhXo6gwGbGX2P2tXT9WOk7xZw_U,17573
97
+ crabcode_core/snapshot/tracker.py,sha256=Dng7P4DNMpgLbgLfNCPA8koO8mRA9LNIfBD8RdaS4HM,12062
98
+ crabcode_core/team/__init__.py,sha256=llNqc6kSc5ng3WI1_-ABFe9RXc189A3MMXb1awKB4Ko,502
99
+ crabcode_core/team/bridge.py,sha256=JMBjN33rWwrqLdzsTb4liP6Sc9I86u2JNqneWaaei60,2065
100
+ crabcode_core/team/inbox.py,sha256=GSlWJ_kxtKrpQjmUTGZ1whwV9VTJpgq4eLEre32fEqU,9377
101
+ crabcode_core/team/manager.py,sha256=Firfamc4KNP3hfduYq4XRdQnThGQN6MVehGPwJEtu_A,74244
102
+ crabcode_core/team/message_bus.py,sha256=Ti_trfYvMhUkXh6_qYI-G0r54lQtclWu0dxOZR95wSg,35258
103
+ crabcode_core/team/models.py,sha256=QHICKRNpGK6Gc3pMb_3TY6CvFLEtLm-jF9R4HKGIhQo,5653
104
+ crabcode_core/team/recovery.py,sha256=77vA3dE9IuY16n-Qh0gtuKCbmc7C1l-Mb-hiMBXpD0c,6790
105
+ crabcode_core/tools/__init__.py,sha256=xw8IBjneZOs0F47G9WFuwn8Uqg3tN-AoQwfvka_U7h0,3716
106
+ crabcode_core/tools/_input_helpers.py,sha256=d7sketqhc2kWodNeuUVfiD40-GnKArsrmxGxfjtXEAE,1298
107
+ crabcode_core/tools/_input_schema.py,sha256=uV7zEBlw1W1V3qp-dyJb-Zz7G12oDrkEeV2vL3vV-hk,3874
108
+ crabcode_core/tools/agent.py,sha256=KLIPgm1JsYcGY3fMR0Gj4L3m5YepBXJ66ape1f9ykPo,16520
109
+ crabcode_core/tools/apply_patch.py,sha256=9vdvdRM1gEq-dXV-TEezgThk5kRseghCrwhKaW67pWU,21094
110
+ crabcode_core/tools/ask_user.py,sha256=6CjWaX6f-3RWPyBSSWq4r5m63vRT_wu5_dflAbvE2fY,4466
111
+ crabcode_core/tools/bash.py,sha256=aVEsD_BSYVL5iRQtj-e1g6pSjrANDxBzF7xA0dDH00Y,6120
112
+ crabcode_core/tools/browser.py,sha256=Xjb6a9_ib3QRbzjZkoL3fs7S0IRvW_MqSWqaK__9Xm0,29059
113
+ crabcode_core/tools/checklist.py,sha256=fZCHi1ft_Yo1bXMBcG-wMdZOFdPQZGOdeHdwYboBDkE,9265
114
+ crabcode_core/tools/checkpoint.py,sha256=4icrUzfAjaUeAMiXEcd6GptXdvx3xbavJiW3moXBNCk,2989
115
+ crabcode_core/tools/computer_use.py,sha256=CJU2meH0r6Kx9zPqfdJOzOhoN8pNOvY2UpSGZwmjAO4,34808
116
+ crabcode_core/tools/diff_utils.py,sha256=g8dABs1PTie1sly3fuuFt31TCzdFWmwluaNlvyvOUW0,3688
117
+ crabcode_core/tools/file_edit.py,sha256=ZUqNcLTLzeNjM_YmoZ3X5Ec6lxBYw3B12vmlz--H9NA,8977
118
+ crabcode_core/tools/file_read.py,sha256=uY6M6NhSDV2Pvv3CwZdH9vCkTaohl5MDL8pttmU5m48,7171
119
+ crabcode_core/tools/file_write.py,sha256=iz9H8jLbVJbeFITm7DHxvX6UjLuv_esJdDXNdmHz-kk,5727
120
+ crabcode_core/tools/glob.py,sha256=nWlH2GE_ouL8oo4tH2xBIEBcqJ3Bci9OTIcjh1OGgoM,4101
121
+ crabcode_core/tools/goal.py,sha256=N_63Yhs-TtfhYW26gV2-MCeA8B2D3M44Cz9v7Iys5zc,4640
122
+ crabcode_core/tools/grep.py,sha256=i0ff6163JgjxjJ_wmImbLOFrmyWrE8JMPckVe46wPC0,8488
123
+ crabcode_core/tools/image.py,sha256=HY3QQq21zqk4FtJ0RlPoFB-kfaMauyJmLEyGaurgz3Q,7814
124
+ crabcode_core/tools/image_generate.py,sha256=clY_1hr2nuRDntHPTDho1aZf3BAr1vgcuWO6fqE8PzM,5776
125
+ crabcode_core/tools/lint.py,sha256=ztrI5rnIn0x8o4gdcEHG5uk6pa5x22mpv8R3p1-lOTA,13346
126
+ crabcode_core/tools/loading.py,sha256=iRyfa75ykr_WdrRSk1M0d7IOCjIbNeuPT342-6wUmqA,8814
127
+ crabcode_core/tools/memory.py,sha256=sjQGytmUXyfb-gNyhAY8FUlACH2EOE_-J2hhZZFabKs,17433
128
+ crabcode_core/tools/monitor.py,sha256=rhGVmjQF7ixjpN9fAsoUZBK3lSg3tsAFr9UmKEYza8o,24536
129
+ crabcode_core/tools/peer.py,sha256=6epsy3AiQBzdt71VQst_tSIU2T3YRs7IO7Y3Ahq4ryc,3848
130
+ crabcode_core/tools/revert.py,sha256=xFIplwG7KV_YjMhhCEKr_cu2LYXt-jkvvewrnlk-rmw,3393
131
+ crabcode_core/tools/schedule.py,sha256=5had7iFGpphblAzLzhl3lB7C-UUePNKccrlyMq_6bIw,25335
132
+ crabcode_core/tools/skill.py,sha256=dfnGXQHD8uYu4Y-rYPyAXJ3Vme1GuqqhWjQ-YpJVz2k,3805
133
+ crabcode_core/tools/switch_mode.py,sha256=emWTDFFzkyZwPr6ZZtG-cGVqOpmYrWCZCmjtW-wg698,9258
134
+ crabcode_core/tools/team.py,sha256=njjxjbLnnaO4RZNSqieQyFzhdMij9nZiku0zYEugOiU,12671
135
+ crabcode_core/tools/tool_search.py,sha256=3ZgSCXXaE6oe6Z39UGo4ksFZAn08DDIkonSoPjPocCM,3059
136
+ crabcode_core/tools/web_search.py,sha256=Z1_J1f6qfFUJkSRsPxwckhNdDmpxE-DxHY6rWvqO4zE,16826
137
+ crabcode_core/types/__init__.py,sha256=VcgkTG2z8bRrh4MUzh9SshaZDFF9DZIpRiWXwdhX3F4,1936
138
+ crabcode_core/types/config.py,sha256=hK5NGi28_-Wt_OAllm__ZXJm8GcRJGWkgXA9v2sXmuU,16768
139
+ crabcode_core/types/event.py,sha256=kpw9btsntRQiT86mLWldYOolZwJJrur6FpU2NGQXfBE,7888
140
+ crabcode_core/types/message.py,sha256=D1gxH-7uPOBehJTJrHc4FQY-F6HSNjfSk_YSSwCaKO8,7493
141
+ crabcode_core/types/tool.py,sha256=mRgca2IB1sL3ys1h3YJVvpwIbS9rV1cQ1J6N6BFFKl0,7630
142
+ crabcode_debugger/__init__.py,sha256=5CHIc3Q7gUDiKLiWhglAiya65OE2qe0z-SfaBUkXG1Q,152
143
+ crabcode_debugger/adapters.py,sha256=OIOdup-HxkfsKtKddu18KOIttWaJLZ-xorEz8mmOxY4,11976
144
+ crabcode_debugger/dap.py,sha256=sxMOTSknE1Bj8PqqqQEn9rdp7T5wqHiTEkL0cssxsUo,10686
145
+ crabcode_debugger/memory.py,sha256=4bsI8C7rhgFOzV7FwYoLCreuiEIEKcVTwN4Qqr5YPuw,68889
146
+ crabcode_debugger/process.py,sha256=Q7Ij8fpxOgkTgJGFjPol18jidRe0XF5wGRq6niuwfdQ,25605
147
+ crabcode_debugger/runtime.py,sha256=weuFQ6T6uOWRyX7ngZvYcfgd3cVyvNKL0Sr4YfcRjXw,1471
148
+ crabcode_debugger/sessions.py,sha256=06MGeLXhH6air2QDtcrLRWLOQx8EHc_a0c4eGeiYKWE,15396
149
+ crabcode_debugger/tool.py,sha256=NM-jGFjgsvQD-DLfk8pmtW44h79pIIpSt0hqCVxRk14,33813
150
+ crabcode_gateway/__init__.py,sha256=QQRtmZFDCcpqB0G1VnPT9rR6f55HZuvwZKc4zYfPbj4,412
151
+ crabcode_gateway/adapter.py,sha256=jlFzke-V4LfgA20QDQuOMSVWmrrt9QYM1n8Mee_d3lQ,842
152
+ crabcode_gateway/auth.py,sha256=OAIjy3uSgIOO0jqLK69kOU5PR_bgSId-xoCbLwj-c38,4605
153
+ crabcode_gateway/computer_use.py,sha256=vMZ7AGNCpMgBw7ZD96PsGKyr1QGVgfzdsP_Dxmv3mfs,16283
154
+ crabcode_gateway/document_engine.py,sha256=cSOkxPa5aqPdhoJJWCVN-3osok6n1Gcabi_EJRyfxIQ,25354
155
+ crabcode_gateway/document_worker.py,sha256=HtV92f02QpBPxlrhT4_ZNFgC8mR94OAKiBhxOmkjey8,11445
156
+ crabcode_gateway/event_bus.py,sha256=lWLCeoKkJ9fhDT_Kwc_esokDsbeRkPi5hsK87kPxRRY,26181
157
+ crabcode_gateway/middleware.py,sha256=bn0pUJHWINc_28ZgZ6e7i-AarkqhfQZMaxbknAVU5UA,11293
158
+ crabcode_gateway/protocol.py,sha256=psXRNQjkfwliXZdETlo1qsGM0IcE_OIUarCLnSNuq6o,466
159
+ crabcode_gateway/safe_file.py,sha256=uOdkxWdZNQ5RJ2jJ9urnIRiF_2uAP8Dkj8wR08vbDaU,2108
160
+ crabcode_gateway/schemas.py,sha256=dpW66eWgeYEw_wUls-JavmvPnHKiCyFHNYEBWMulPcM,55935
161
+ crabcode_gateway/server.py,sha256=ShCrO1Zw-Ed37HfUYihyOToJasGJjL7Kzy1BFA4CJ64,20408
162
+ crabcode_gateway/session_registry.py,sha256=HhvLvlGDx0EgmGwjk2zHCCtWURmNDZHHmpBjroX35fk,1214
163
+ crabcode_gateway/task_registry.py,sha256=Ij8USxQ13ockqhoZ286hn8jXckFeLglNSgwgcnQ5tX4,26461
164
+ crabcode_gateway/turn_details.py,sha256=Ao4I3W8PBjZM6ZlW6Wh3OedaqaSClu0db-gK-lnHCks,2680
165
+ crabcode_gateway/acp/__init__.py,sha256=PJUCdGBi_ud--LoWxbYbzO7gAgdFCzY_UKeB3JhUvUA,352
166
+ crabcode_gateway/acp/agent.py,sha256=E1osH5zuCS95fDMDbzYGWFNEo0r1hkAoj63h8EzJVeE,61178
167
+ crabcode_gateway/acp/session.py,sha256=rbN1EcCQw2-LEr-bbW3x0TVmeL5ZGeEaSfBX6LEmjws,4049
168
+ crabcode_gateway/acp/transport.py,sha256=IWU3ih_9heY-EH-AhbprAtpcaj8ZvtWMMS76CAX82QA,1119
169
+ crabcode_gateway/acp/types.py,sha256=Pfg4QdbboTPft_p5eAc-vj3dkpTroFpDEZBgwmZ4k3U,2855
170
+ crabcode_gateway/grpc/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
171
+ crabcode_gateway/grpc/crabcode_pb2.py,sha256=olmqo0HbLHO22PdKWpCMKmCtG9eUBM4iiHwDc1DwXLc,8102
172
+ crabcode_gateway/grpc/crabcode_pb2_grpc.py,sha256=NDrpxgGsd5tqe5mT9_Fr15V72RbegfOb6eXzNf5t16s,20996
173
+ crabcode_gateway/grpc/server.py,sha256=8S3-QoayWuT149gZX8zLsj6blZ_mZpAEmkOTQJdT4Cw,30524
174
+ crabcode_gateway/grpc/proto/crabcode.proto,sha256=VqN5CKiRBQ3OPBL25g2bT1Bt10olVXcmGJqq3tKkUW8,4099
175
+ crabcode_gateway/routes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
176
+ crabcode_gateway/routes/agent.py,sha256=ZI97BVRMPgwpv45IqWFoESO_Khr0uFfy6J-tDojNWOU,13955
177
+ crabcode_gateway/routes/auth.py,sha256=kIynPq7LUBlKwS--1Qp1hJHpLqebB5Unt1qAI8V_dUI,4945
178
+ crabcode_gateway/routes/computer_use.py,sha256=_NtMi3zciudhDRcha53fXL3jECp6Oj5cWWvWKD_JLAY,4622
179
+ crabcode_gateway/routes/config.py,sha256=P4f_RwQoBV3fDpoHSeuuH9EtDtgWe8mgZbK72sULHoY,68334
180
+ crabcode_gateway/routes/document.py,sha256=j01jt88A29GF6fHYcX2AparZAOPsUrwllec9YGtFswg,78665
181
+ crabcode_gateway/routes/event.py,sha256=WOr1WHJ-5nCcpCWIkpIos2aAl2ASJUyYKSaLZ5bCRS0,155226
182
+ crabcode_gateway/routes/git_review.py,sha256=-fbMOWo8JKnHCMsKew3i02lTE7Ohj9w6ocgFKCsYeio,10460
183
+ crabcode_gateway/routes/health.py,sha256=GzR1RAGNmOPXEyUQNRE0ANJsbDMOQHQGNRhA3dRz87Y,293
184
+ crabcode_gateway/routes/peer.py,sha256=xwKtv2Dgfq1bSk3uLYZfTthFPPDnsBa6UY4HvnEt-wU,3166
185
+ crabcode_gateway/routes/permission.py,sha256=QL14Le9wgknpbBVp3YM54v2kTl75X9zvfWCVVB43e3s,3798
186
+ crabcode_gateway/routes/schedule.py,sha256=Z5q-lg_HqiZoQD52IrLjz4WT_7See7ggFXOQgOt4r6o,10248
187
+ crabcode_gateway/routes/session.py,sha256=OnjkSgadqDufXP-4LkVO2QRM9O4WB-TtchUZgiAaefM,59918
188
+ crabcode_gateway/routes/snapshot.py,sha256=K72ypSN9NfXhvrqgqg11RbwwMIZFFK6PeINFgkyBwQw,7883
189
+ crabcode_gateway/routes/tasks.py,sha256=0wjs-ovI-Ww2rikhxNLH6685QoDqXE3R58UJm4j-Zck,12171
190
+ crabcode_gateway/routes/team.py,sha256=kOGvzoFJJDXb8H-f_FNX8ZQxmp7jGA9f6cmMuowAtWw,13741
191
+ crabcode_gateway/routes/usage.py,sha256=o7iRnnW4nU5AwbDz6PqoOSmfZpjr-dzg1_lEK8FqXGg,2300
192
+ crabcode_gateway/routes/workspace.py,sha256=4dvgzGc09fUfzid3UcJK2SMP43O3IiaAcB33Nq_aPyU,11839
193
+ crabcode_search/__init__.py,sha256=Fw3-cySOi83Y6WSduXUTC62ANXA5lf7PX3kSnQoXEUs,272
194
+ crabcode_search/background.py,sha256=j_AAT_FvnGjordcQ8bv1cFmQTSBLZfNsYBhdb4v4Quc,11140
195
+ crabcode_search/chunker.py,sha256=gtpMWAjNBEAmr9cfhU5uOcuXZFDhEpNRubVbttaxT14,16148
196
+ crabcode_search/embedder.py,sha256=NlNuOHS7t4JvaWXkNU-T_xxnkjRxFrr3l57dlB5IRkc,16728
197
+ crabcode_search/indexer.py,sha256=bBL3OE6HMqdIRBCnI--XjaHl7_G3H4VO2d-RMKtjlkI,7745
198
+ crabcode_search/store.py,sha256=s1hsyRRGcAO_hdJli6M0C8rhkMW4tXj5ZVMPuCP3uhQ,8074
199
+ crabcode_search/tool.py,sha256=xJjAN3esvJIH3z7ILNQ1gQs5Ty5fu6u7CYX6P2WB_BY,10238
200
+ crabcode-0.1.6.dist-info/METADATA,sha256=KtN7VCKR2jNBJ7cevwN176mEmxExIYbcmlX8PQZsZC4,2799
201
+ crabcode-0.1.6.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
202
+ crabcode-0.1.6.dist-info/entry_points.txt,sha256=tpYKME-yDLFb2eqwryWJG-d-HW4dkvDbzwogRl2jays,52
203
+ crabcode-0.1.6.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: hatchling 1.32.0
2
+ Generator: hatchling 1.32.4
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
crabcode_cli/app.py CHANGED
@@ -16,9 +16,155 @@ app = typer.Typer(
16
16
  add_completion=False,
17
17
  )
18
18
 
19
+ document_engine_app = typer.Typer(
20
+ name="document-engine",
21
+ help="Manage the optional local high-fidelity PDF translation engine.",
22
+ add_completion=False,
23
+ )
24
+ app.add_typer(document_engine_app, name="document-engine")
25
+
26
+ computer_use_app = typer.Typer(
27
+ name="computer-use",
28
+ help="Manage the shared native Computer Use component (automatically used by the CLI).",
29
+ add_completion=False,
30
+ )
31
+ app.add_typer(computer_use_app, name="computer-use")
32
+
19
33
  logger = get_logger(__name__)
20
34
 
21
35
 
36
+ def _configure_utf8_stdio() -> None:
37
+ """Use UTF-8 for terminal and protocol streams on every platform."""
38
+ for stream in (sys.stdin, sys.stdout, sys.stderr):
39
+ reconfigure = getattr(stream, "reconfigure", None)
40
+ if callable(reconfigure):
41
+ reconfigure(encoding="utf-8", errors="replace")
42
+
43
+
44
+ def _computer_use_command(*, permissions: bool = False, json_output: bool = False,
45
+ permission_kind: str | None = None) -> None:
46
+ import json
47
+
48
+ from crabcode_cli.computer_use import ComputerUseError, NativeClient
49
+
50
+ async def run() -> dict:
51
+ client = NativeClient()
52
+ await client.start()
53
+ if permissions:
54
+ if permission_kind:
55
+ await client.request("permissions", {"kind": permission_kind}, timeout=10)
56
+ else:
57
+ await client.request("permissions", timeout=10)
58
+ caps = await client.request("capabilities", timeout=25)
59
+ return {"installed": True, "path": str(client.state_dir), **caps}
60
+
61
+ try:
62
+ status = asyncio.run(run())
63
+ except ComputerUseError as exc:
64
+ if json_output:
65
+ typer.echo(json.dumps({"status": "unavailable", "detail": str(exc)}, ensure_ascii=False))
66
+ else:
67
+ typer.echo(str(exc), err=True)
68
+ raise typer.Exit(1) from exc
69
+ if json_output:
70
+ typer.echo(json.dumps(status, ensure_ascii=False))
71
+ else:
72
+ typer.echo(f"Computer Use: {status['path']}")
73
+ for key, label in (("gui_available", "图形桌面"), ("capture_available", "截图"),
74
+ ("input_available", "输入"), ("ax_available", "辅助功能树")):
75
+ typer.echo(f" {label}: {'可用' if status.get(key) else '不可用'}")
76
+ if not status.get("capture_available") or not status.get("input_available"):
77
+ typer.echo("请检查图形会话及系统权限;macOS 请为 Crab Computer Use 开启录屏和辅助功能。")
78
+
79
+
80
+ @computer_use_app.command("status")
81
+ def computer_use_status_cmd(
82
+ json_output: bool = typer.Option(False, "--json", help="Print capabilities as JSON"),
83
+ ) -> None:
84
+ """Start the installed component and check its current capabilities."""
85
+ _computer_use_command(json_output=json_output)
86
+
87
+
88
+ @computer_use_app.command("permissions")
89
+ def computer_use_permissions_cmd(
90
+ screen_recording: bool = typer.Option(False, "--screen-recording", help="Open Screen Recording with the draggable app card"),
91
+ accessibility: bool = typer.Option(False, "--accessibility", help="Open Accessibility with the draggable app card"),
92
+ ) -> None:
93
+ """Open the macOS permission settings and recording drag guide."""
94
+ if screen_recording and accessibility:
95
+ raise typer.BadParameter("Choose one permission pane")
96
+ kind = "screen_recording" if screen_recording else "accessibility" if accessibility else None
97
+ _computer_use_command(permissions=True, permission_kind=kind)
98
+
99
+
100
+ @document_engine_app.command("status")
101
+ def document_engine_status_cmd(
102
+ json_output: bool = typer.Option(False, "--json", help="Print machine-readable JSON"),
103
+ ) -> None:
104
+ """Show the optional BabelDOC engine status."""
105
+ import json
106
+
107
+ from crabcode_gateway.document_engine import document_engine_status
108
+
109
+ status = document_engine_status()
110
+ if json_output:
111
+ typer.echo(json.dumps(status, ensure_ascii=False))
112
+ else:
113
+ typer.echo(f"{status['status']}: {status['detail']}")
114
+
115
+
116
+ @document_engine_app.command("install")
117
+ def document_engine_install_cmd(
118
+ bundle: Optional[str] = typer.Option(
119
+ None,
120
+ "--bundle",
121
+ help="Use an offline bundle path or URL instead of the official BabelDOC source",
122
+ ),
123
+ json_output: bool = typer.Option(False, "--json", help="Print machine-readable JSON"),
124
+ ) -> None:
125
+ """Install BabelDOC from its official source, or use an offline bundle."""
126
+ import json
127
+
128
+ from crabcode_gateway.document_engine import install_document_engine
129
+
130
+ def progress(message: str) -> None:
131
+ # Keep stdout as a single machine-readable result in JSON mode while
132
+ # still allowing desktop callers to stream installation progress.
133
+ typer.echo(message, err=json_output)
134
+
135
+ try:
136
+ status = install_document_engine(bundle, progress=progress)
137
+ except Exception as exc:
138
+ if json_output:
139
+ typer.echo(json.dumps({"status": "error", "detail": str(exc)}, ensure_ascii=False))
140
+ else:
141
+ typer.echo(f"安装失败:{exc}", err=True)
142
+ raise typer.Exit(1) from exc
143
+ if json_output:
144
+ typer.echo(json.dumps(status, ensure_ascii=False))
145
+ else:
146
+ typer.echo(status["detail"])
147
+
148
+
149
+ @document_engine_app.command("remove")
150
+ def document_engine_remove_cmd(
151
+ yes: bool = typer.Option(False, "--yes", help="Remove without confirmation"),
152
+ json_output: bool = typer.Option(False, "--json", help="Print machine-readable JSON"),
153
+ ) -> None:
154
+ """Remove the managed engine without touching translated project PDFs."""
155
+ import json
156
+
157
+ from crabcode_gateway.document_engine import remove_document_engine
158
+
159
+ if not yes and not typer.confirm("删除本地高精度 PDF 引擎?已生成的译后 PDF 会保留。"):
160
+ raise typer.Abort()
161
+ status = remove_document_engine()
162
+ if json_output:
163
+ typer.echo(json.dumps(status, ensure_ascii=False))
164
+ else:
165
+ typer.echo(status["detail"])
166
+
167
+
22
168
  @app.command()
23
169
  def main(
24
170
  prompt: Optional[str] = typer.Argument(None, help="Prompt to send (pipe mode)"),
@@ -31,10 +177,11 @@ def main(
31
177
  cwd: Optional[str] = typer.Option(None, "--cwd", help="Working directory"),
32
178
  resume: Optional[str] = typer.Option(None, "-r", "--resume", help="Resume a session by ID"),
33
179
  continue_last: bool = typer.Option(False, "-c", "--continue", help="Continue most recent session"),
180
+ yolo: bool = typer.Option(False, "--yolo", help="Enable Full Access for this run (skip tool permission prompts)"),
34
181
  image: Optional[list[str]] = typer.Option(None, "-i", "--image", help="Image file(s) to attach (repeatable)"),
35
182
  ) -> None:
36
183
  """CrabCode — AI coding assistant in the terminal."""
37
- from crabcode_core.types.config import ApiConfig, CrabCodeSettings
184
+ from crabcode_core.types.config import CrabCodeSettings
38
185
 
39
186
  work_dir = cwd or os.getcwd()
40
187
 
@@ -131,6 +278,10 @@ def main(
131
278
  err=True,
132
279
  )
133
280
 
281
+ if yolo:
282
+ settings.permissions.default_mode = "run_everything"
283
+ explicit_settings.permissions.default_mode = "run_everything"
284
+
134
285
  settings._crabcode_explicit_settings = explicit_settings
135
286
 
136
287
  # Read image files into base64 attachments
@@ -289,18 +440,115 @@ def sessions_export(
289
440
  """Export a session transcript to Markdown or JSON."""
290
441
  work_dir = cwd or os.getcwd()
291
442
  from crabcode_core.session.export import export_json, export_markdown
443
+
444
+ try:
445
+ resolved_id, resolved_cwd = _resolve_export_session(session_id, work_dir)
446
+ except ValueError as exc:
447
+ typer.echo(f"Error: {exc}", err=True)
448
+ raise typer.Exit(1) from exc
449
+ if fmt not in {"md", "json"}:
450
+ typer.echo("Error: --format must be 'md' or 'json'", err=True)
451
+ raise typer.Exit(1)
292
452
  if fmt == "json":
293
- content = export_json(session_id, work_dir)
453
+ content = export_json(resolved_id, resolved_cwd)
294
454
  ext = ".json"
295
455
  else:
296
- content = export_markdown(session_id, work_dir)
456
+ content = export_markdown(resolved_id, resolved_cwd)
297
457
  ext = ".md"
298
- out_path = output or os.path.join(work_dir, f"{session_id[:8]}{ext}")
458
+ out_path = output or os.path.join(work_dir, f"{resolved_id[:8]}{ext}")
299
459
  with open(out_path, "w", encoding="utf-8") as f:
300
460
  f.write(content)
301
461
  typer.echo(f"Exported to {out_path}")
302
462
 
303
463
 
464
+ @sessions_app.command("fork")
465
+ def sessions_fork(
466
+ session_id: str = typer.Argument(..., help="Source session ID (full or prefix)"),
467
+ message_uuid: str = typer.Argument(..., help="Assistant message UUID (full or unique prefix)"),
468
+ cwd: Optional[str] = typer.Option(None, "--cwd", help="Working directory used for local session lookup"),
469
+ title: Optional[str] = typer.Option(None, "--title", help="Title for the forked session"),
470
+ ) -> None:
471
+ """Fork a session at an assistant reply."""
472
+ work_dir = cwd or os.getcwd()
473
+ from crabcode_core.session.storage import SessionStorage
474
+
475
+ try:
476
+ resolved_id, resolved_cwd = _resolve_export_session(session_id, work_dir)
477
+ source = SessionStorage(resolved_cwd, resolved_id)
478
+ messages = source.load_messages()
479
+ selector = str(message_uuid or "").strip()
480
+ if not selector:
481
+ raise ValueError("assistant message UUID is required")
482
+ assistant_ids = [
483
+ str(message.get("uuid") or "")
484
+ for message in messages
485
+ if message.get("type") == "assistant" and message.get("uuid")
486
+ ]
487
+ matches = [value for value in assistant_ids if value == selector or value.startswith(selector)]
488
+ if len(matches) != 1:
489
+ if not matches:
490
+ raise ValueError(f"assistant message not found: {selector}")
491
+ raise ValueError(f"assistant message selector is ambiguous: {selector}")
492
+ forked = SessionStorage.fork_from(
493
+ resolved_cwd,
494
+ resolved_id,
495
+ matches[0],
496
+ title=title,
497
+ )
498
+ except (OSError, ValueError) as exc:
499
+ typer.echo(f"Error: {exc}", err=True)
500
+ raise typer.Exit(1) from exc
501
+
502
+ typer.echo(
503
+ f"Forked session {resolved_id[:8]}… at {matches[0][:8]}… "
504
+ f"into {forked.session_id}"
505
+ )
506
+
507
+
508
+ def _resolve_export_session(selector: str, cwd: str) -> tuple[str, str]:
509
+ """Resolve an export selector without silently producing an empty file."""
510
+ from crabcode_core.session.meta_db import SessionMetaStore
511
+ from crabcode_core.session.storage import SessionStorage, get_transcript_path
512
+
513
+ value = str(selector or "").strip()
514
+ if not value:
515
+ raise ValueError("session ID is required")
516
+
517
+ work_dir = os.path.abspath(cwd)
518
+ local_ids = [
519
+ str(row.get("session_id") or "")
520
+ for row in SessionStorage.list_sessions(work_dir)
521
+ if row.get("session_id")
522
+ ]
523
+ if value in local_ids:
524
+ return value, work_dir
525
+ local_matches = [session_id for session_id in local_ids if session_id.startswith(value)]
526
+ if len(local_matches) == 1:
527
+ return local_matches[0], work_dir
528
+ if len(local_matches) > 1:
529
+ raise ValueError(f"session selector is ambiguous: {value}")
530
+
531
+ store = SessionMetaStore()
532
+ try:
533
+ exact = store.get(value)
534
+ if exact is not None:
535
+ return value, str(exact.get("cwd") or work_dir)
536
+ matches = store.find_active_by_prefix(value, limit=2)
537
+ finally:
538
+ store.close()
539
+ if len(matches) == 1:
540
+ return str(matches[0]["id"]), str(matches[0].get("cwd") or work_dir)
541
+ if len(matches) > 1:
542
+ raise ValueError(f"session selector is ambiguous: {value}")
543
+
544
+ try:
545
+ if get_transcript_path(work_dir, value).exists():
546
+ return value, work_dir
547
+ except (TypeError, ValueError):
548
+ pass
549
+ raise ValueError(f"session not found: {value}")
550
+
551
+
304
552
  @sessions_app.command("prune")
305
553
  def sessions_prune(
306
554
  days: int = typer.Option(30, "--days", "-d", help="Archive sessions older than N days"),
@@ -346,13 +594,23 @@ def gateway(
346
594
  port: int = typer.Option(4096, "--port", "-p", help="HTTP port"),
347
595
  grpc_port: Optional[int] = typer.Option(None, "--grpc-port", help="gRPC port (optional)"),
348
596
  host: str = typer.Option("127.0.0.1", "--host", help="Bind address"),
349
- password: Optional[str] = typer.Option(None, "--password", help="Basic Auth password"),
597
+ password: Optional[str] = typer.Option(None, "--password", help="Gateway password"),
598
+ security_mode: Optional[str] = typer.Option(None, "--security-mode", help="none, password, publickey, or mixed"),
599
+ password_hash: Optional[str] = typer.Option(None, "--password-hash", help="PBKDF2 password hash"),
600
+ authorized_keys: Optional[str] = typer.Option(None, "--authorized-keys", help="OpenSSH authorized_keys path"),
601
+ jwt_secret: Optional[str] = typer.Option(None, "--jwt-secret", help="JWT signing secret"),
350
602
  cors: Optional[str] = typer.Option(None, "--cors", help="Allowed CORS origin"),
351
603
  log_level: str = typer.Option("info", "--log-level", help="Log level"),
352
604
  ) -> None:
353
605
  """Start the CrabCode HTTP/gRPC gateway server."""
606
+ if os.name == "nt":
607
+ from crabcode_core._windows_process import attach_process_tree_job
608
+
609
+ # The handle stays open until Gateway exits, including a forced kill
610
+ # by Desktop/VS Code. All subsequently spawned descendants are owned.
611
+ attach_process_tree_job()
354
612
  from crabcode_core.logging_utils import configure_logging
355
- from crabcode_core.types.config import CrabCodeSettings, LoggingSettings
613
+ from crabcode_core.types.config import LoggingSettings
356
614
 
357
615
  log_settings = LoggingSettings(level=log_level.upper())
358
616
  configure_logging(os.getcwd(), log_settings)
@@ -361,11 +619,32 @@ def gateway(
361
619
 
362
620
  from crabcode_gateway.server import run_server
363
621
 
622
+ from crabcode_core.config.manager import ConfigManager
623
+ overrides = {
624
+ key: value
625
+ for key, value in {
626
+ "mode": security_mode,
627
+ "password": password,
628
+ "password_hash": password_hash,
629
+ "authorized_keys": authorized_keys,
630
+ "jwt_secret": jwt_secret,
631
+ }.items()
632
+ if value is not None
633
+ }
634
+ if password is not None and security_mode is None:
635
+ overrides["mode"] = "password"
636
+ configured = ConfigManager(cwd=os.getcwd()).load_gateway_security(overrides)
637
+
364
638
  run_server(
365
639
  host=host,
366
640
  port=port,
367
641
  grpc_port=grpc_port,
368
- password=password,
642
+ password=configured.password,
643
+ security_mode=configured.mode,
644
+ password_hash=configured.password_hash,
645
+ authorized_keys_path=configured.authorized_keys,
646
+ jwt_secret=configured.jwt_secret,
647
+ token_ttl_seconds=configured.token_ttl_seconds,
369
648
  cors_origins=cors_origins,
370
649
  log_level=log_level,
371
650
  )
@@ -403,7 +682,7 @@ def acp_cmd(
403
682
  import asyncio
404
683
 
405
684
  from crabcode_core.logging_utils import configure_logging
406
- from crabcode_core.types.config import CrabCodeSettings, LoggingSettings
685
+ from crabcode_core.types.config import LoggingSettings
407
686
 
408
687
  work_dir = cwd or os.getcwd()
409
688
  log_settings = LoggingSettings(level=log_level.upper())
@@ -479,7 +758,8 @@ def stats(
479
758
 
480
759
 
481
760
  def entry() -> None:
482
- known_subcommands = {"main", "sessions", "stats", "gateway", "acp"}
761
+ _configure_utf8_stdio()
762
+ known_subcommands = {"main", "sessions", "stats", "gateway", "acp", "document-engine", "computer-use"}
483
763
  args = sys.argv[1:]
484
764
  # Preserve root --help so users can still discover all subcommands.
485
765
  if args and args[0] in ("--help", "-h"):