crabcode 0.1.3__py3-none-any.whl → 0.1.4__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 (87) hide show
  1. {crabcode-0.1.3.dist-info → crabcode-0.1.4.dist-info}/METADATA +4 -2
  2. crabcode-0.1.4.dist-info/RECORD +150 -0
  3. {crabcode-0.1.3.dist-info → crabcode-0.1.4.dist-info}/WHEEL +1 -1
  4. crabcode_cli/__init__.py +5 -1
  5. crabcode_cli/app.py +87 -37
  6. crabcode_cli/pipe.py +28 -11
  7. crabcode_cli/repl.py +1216 -158
  8. crabcode_core/__init__.py +5 -1
  9. crabcode_core/_version.py +3 -0
  10. crabcode_core/agent_manager.py +1222 -155
  11. crabcode_core/api/anthropic_adapter.py +239 -9
  12. crabcode_core/api/base.py +46 -1
  13. crabcode_core/api/codex_adapter.py +108 -23
  14. crabcode_core/api/model_info.py +88 -6
  15. crabcode_core/api/openai_adapter.py +34 -9
  16. crabcode_core/compact/__init__.py +11 -1
  17. crabcode_core/compact/compact.py +420 -133
  18. crabcode_core/events.py +3276 -233
  19. crabcode_core/goal.py +149 -0
  20. crabcode_core/hooks/manager.py +14 -2
  21. crabcode_core/peer/__init__.py +10 -0
  22. crabcode_core/peer/runtime.py +496 -0
  23. crabcode_core/permissions/__init__.py +6 -2
  24. crabcode_core/permissions/ai_reviewer.py +176 -0
  25. crabcode_core/permissions/manager.py +42 -3
  26. crabcode_core/plan/executor.py +48 -3
  27. crabcode_core/plan/types.py +16 -1
  28. crabcode_core/prompts/context.py +13 -9
  29. crabcode_core/prompts/system.py +54 -5
  30. crabcode_core/prompts/templates.py +2 -0
  31. crabcode_core/query/loop.py +721 -196
  32. crabcode_core/session/export.py +4 -4
  33. crabcode_core/session/meta_db.py +184 -15
  34. crabcode_core/session/storage.py +1186 -227
  35. crabcode_core/team/bridge.py +1 -1
  36. crabcode_core/team/inbox.py +224 -36
  37. crabcode_core/team/manager.py +1259 -177
  38. crabcode_core/team/message_bus.py +590 -77
  39. crabcode_core/team/models.py +4 -4
  40. crabcode_core/team/recovery.py +66 -24
  41. crabcode_core/tools/__init__.py +13 -2
  42. crabcode_core/tools/agent.py +114 -54
  43. crabcode_core/tools/bash.py +8 -2
  44. crabcode_core/tools/checkpoint.py +1 -1
  45. crabcode_core/tools/goal.py +134 -0
  46. crabcode_core/tools/grep.py +9 -0
  47. crabcode_core/tools/lint.py +9 -2
  48. crabcode_core/tools/memory.py +245 -28
  49. crabcode_core/tools/monitor.py +691 -0
  50. crabcode_core/tools/peer.py +103 -0
  51. crabcode_core/tools/revert.py +1 -1
  52. crabcode_core/tools/switch_mode.py +45 -3
  53. crabcode_core/tools/team.py +10 -5
  54. crabcode_core/types/__init__.py +6 -0
  55. crabcode_core/types/config.py +53 -4
  56. crabcode_core/types/event.py +31 -1
  57. crabcode_core/types/message.py +56 -0
  58. crabcode_core/types/tool.py +1 -0
  59. crabcode_debugger/__init__.py +5 -0
  60. crabcode_debugger/adapters.py +326 -0
  61. crabcode_debugger/dap.py +231 -0
  62. crabcode_debugger/memory.py +1691 -0
  63. crabcode_debugger/process.py +672 -0
  64. crabcode_debugger/runtime.py +23 -0
  65. crabcode_debugger/sessions.py +343 -0
  66. crabcode_debugger/tool.py +660 -0
  67. crabcode_gateway/__init__.py +5 -1
  68. crabcode_gateway/acp/agent.py +978 -74
  69. crabcode_gateway/event_bus.py +491 -31
  70. crabcode_gateway/grpc/crabcode_pb2.py +70 -0
  71. crabcode_gateway/grpc/crabcode_pb2_grpc.py +474 -0
  72. crabcode_gateway/grpc/proto/crabcode.proto +24 -2
  73. crabcode_gateway/grpc/server.py +472 -151
  74. crabcode_gateway/middleware.py +76 -31
  75. crabcode_gateway/routes/agent.py +165 -77
  76. crabcode_gateway/routes/config.py +239 -42
  77. crabcode_gateway/routes/event.py +1272 -91
  78. crabcode_gateway/routes/permission.py +71 -9
  79. crabcode_gateway/routes/session.py +538 -128
  80. crabcode_gateway/routes/snapshot.py +94 -12
  81. crabcode_gateway/schemas.py +94 -1
  82. crabcode_gateway/server.py +231 -46
  83. crabcode_gateway/session_registry.py +36 -0
  84. crabcode_gateway/task_registry.py +633 -0
  85. crabcode_search/tool.py +17 -1
  86. crabcode-0.1.3.dist-info/RECORD +0 -130
  87. {crabcode-0.1.3.dist-info → crabcode-0.1.4.dist-info}/entry_points.txt +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: crabcode
3
- Version: 0.1.3
3
+ Version: 0.1.4
4
4
  Summary: CrabCode - AI coding assistant in the terminal
5
5
  Requires-Python: >=3.10
6
6
  Requires-Dist: anthropic>=0.40.0
@@ -12,6 +12,7 @@ Requires-Dist: pydantic>=2.0.0
12
12
  Requires-Dist: rich>=13.0.0
13
13
  Requires-Dist: tiktoken>=0.7.0
14
14
  Requires-Dist: typer>=0.12.0
15
+ Requires-Dist: websockets>=12.0
15
16
  Provides-Extra: all
16
17
  Requires-Dist: agent-client-protocol>=0.9.0; extra == 'all'
17
18
  Requires-Dist: anthropic[bedrock]>=0.40.0; extra == 'all'
@@ -31,6 +32,7 @@ Provides-Extra: bedrock
31
32
  Requires-Dist: anthropic[bedrock]>=0.40.0; extra == 'bedrock'
32
33
  Provides-Extra: browser
33
34
  Requires-Dist: playwright>=1.48.0; extra == 'browser'
35
+ Provides-Extra: debugger
34
36
  Provides-Extra: gateway
35
37
  Requires-Dist: agent-client-protocol>=0.9.0; extra == 'gateway'
36
38
  Requires-Dist: fastapi>=0.115.0; extra == 'gateway'
@@ -0,0 +1,150 @@
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=73wS3ml-lIECzg_RZAv6SlqQE_-OjbeyxPgfWlLIPBU,20145
4
+ crabcode_cli/banner.py,sha256=K0ak6Ng4l85C3TWnh64ulvdF4ReJSRsaWe8DOjse3Zg,1403
5
+ crabcode_cli/pipe.py,sha256=gJHtr4_TZC2HDrninqi4NEd0oQ3q8buDobCsXwEE8yk,4987
6
+ crabcode_cli/repl.py,sha256=1MukugcpEmxdAmSsQAOx_rmp3iuWF-uJ9yDhGksroy0,142976
7
+ crabcode_cli/render/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
+ crabcode_cli/render/messages.py,sha256=n9OsbLIAU3FyO9gwGMMJld7zq-71N0caz9ecmE2kIjo,568
9
+ crabcode_core/__init__.py,sha256=ArpgEg5xC3iR4DRT0HBg7DwU3K-r1MnmDOHpIb1b0E4,142
10
+ crabcode_core/_version.py,sha256=8flt6lm7aDDwMiX7-CIhcvAg_n24OfeBLPnkgPs293c,82
11
+ crabcode_core/agent_manager.py,sha256=B1S26WARxPJXGwyvdu6bMplpg09Lk07j-UkIECPS8ho,68265
12
+ crabcode_core/events.py,sha256=4nwyox28aQ0N4ZyZqTAjMGgjmJIN1T5rUtqRO8eQHiY,178575
13
+ crabcode_core/goal.py,sha256=PCpU9dyKpLcsKXvt4zigPvRSloKf64FUY4z5mUmqLWs,5231
14
+ crabcode_core/logging_utils.py,sha256=H6E7lldUAeIeQzQooMl0MrQ07YlSO-tra_QlzxcOdks,3657
15
+ crabcode_core/utf8_sanitize.py,sha256=RRTGgwA9jqK-HLR1WUSFwgG4xJn7ZukTDu7M6Oi3fHI,936
16
+ crabcode_core/api/__init__.py,sha256=IXs4hLgC4cT85TLdmS4KgtPKYDytadkwvrDyBshr5ag,674
17
+ crabcode_core/api/anthropic_adapter.py,sha256=bstZMFrjPdhaUwv3DNhHZ_E0RN6m6d8E5UGjIQQ8W1Y,20620
18
+ crabcode_core/api/azure_adapter.py,sha256=zJ7q3Ni3sVwK3Bbju_nO8t8kPEA_bL6scVFC-XRPRh4,2360
19
+ crabcode_core/api/base.py,sha256=oe-oxLCrV_zKkQRGJsGay_nATCg62PajW185Ot7af3A,4254
20
+ crabcode_core/api/codex_adapter.py,sha256=Ra9RmTWbRFuJrJIkj3rG_vt_yUBHeecc4BvXuHMcCAI,29633
21
+ crabcode_core/api/gemini_adapter.py,sha256=RVk3zlLPqDtzG8w5psu4aSoFyFLua5qQx3subqz-5DQ,1130
22
+ crabcode_core/api/model_info.py,sha256=6Ob1D3Oc2LVEduuMBZWaApZcBSw-ENqHsTXwgouwxfk,4655
23
+ crabcode_core/api/ollama_adapter.py,sha256=ZpTg11zOUGFE0J88qBXL7AvxDQU5PjWg2wWvm4uxUvY,1158
24
+ crabcode_core/api/openai_adapter.py,sha256=m1m6yX9pqEY-2_4WjwHKTy5ViyYCkguc9G7Ddj6nkVw,10766
25
+ crabcode_core/api/registry.py,sha256=tCVRE74bMUn9ukCbGp3bDtSOYZ6_EmsNfdVnnkGN6k4,2413
26
+ crabcode_core/compact/__init__.py,sha256=9445RwiG5BI8b6mrXMcNkcPLs5NH3RSKFxDrXsgmmK8,395
27
+ crabcode_core/compact/compact.py,sha256=flA9o__I5Ga9H59DnKWZqAsAbx47qdtEANbqdak5aH4,18819
28
+ crabcode_core/config/__init__.py,sha256=wbSnNVCqj673phu2pvIFz-f5HM5bLvH-FdD9b01HNRA,84
29
+ crabcode_core/config/claudemd.py,sha256=eUJQRdbT3fP0lB6C-Yc2pVBt0u4Z0qBEamXtkOErJWw,1973
30
+ crabcode_core/config/manager.py,sha256=OJ1o-wBhk1NCI-09Vzv9lb1jOcB8fn9rda428CGlYjc,5263
31
+ crabcode_core/hooks/__init__.py,sha256=wfOnbLuJqtLezKYWYmBTAE9qG-eaG7wSfgx1-kS7N64,165
32
+ crabcode_core/hooks/manager.py,sha256=EyGC8hzHeNjLS2uQtBUlhjSqRAsVsVbXqRI3ThLBp_0,9713
33
+ crabcode_core/lsp/__init__.py,sha256=np9EYVvOi94ZFxLWW_kD13AfwaIhN0Vcp8-pHaLDn6c,189
34
+ crabcode_core/lsp/client.py,sha256=AdQ2hzryM4RrPDXdi168yV3kQCkb69O1B1-MNUIFWts,26699
35
+ crabcode_core/lsp/diagnostics.py,sha256=hcQq9MJY8HqMtKPKnRWfGK7GOgqmQAi2niaIKVUWNTI,4218
36
+ crabcode_core/lsp/manager.py,sha256=morGtndY0dE-O88u4LalOnnAl8KzOWmQHqnUTCphtfs,18969
37
+ crabcode_core/mcp/__init__.py,sha256=axvOgOWHjpKs7WFEkf8Za_4mm_oNe0tYyD94dAMnWTE,182
38
+ crabcode_core/mcp/client.py,sha256=3e7LQKq8kNyE2E6-wmSa_MpysgsznuPUS6sxWgp2RiA,5233
39
+ crabcode_core/mcp/config.py,sha256=DQZ39LX-smZ11oyqf-KnJvcqEriJF68Q6LewWn0hrdk,1955
40
+ crabcode_core/peer/__init__.py,sha256=eXhG-X0ZT5KgV3BKVXYEB7tQDG2SM3Igdb0-7OPtY2k,234
41
+ crabcode_core/peer/runtime.py,sha256=HO7ulJlhj4UHUmTCkkC1OyX_76tqA7GszUXWRmKwLaA,19654
42
+ crabcode_core/permissions/__init__.py,sha256=grH8A95Lr5L-gsXOIkb-J6RldRdaktMEvKUcZize9r0,198
43
+ crabcode_core/permissions/ai_reviewer.py,sha256=geE6lGKf6PUDnkNuVWc3TfXRsVqhM8YmAVxvhh7vp8M,7296
44
+ crabcode_core/permissions/manager.py,sha256=qetYavaXZWnQOUtFEkVkb4aehiKaIgKHScf7hsGwq2c,5907
45
+ crabcode_core/plan/__init__.py,sha256=co_SEC__Z3OtijC9hxdVWIcdUBsUVsJnQ-LkxJfpAL8,169
46
+ crabcode_core/plan/executor.py,sha256=k9PmjAfmgZklYys5oUQW5xUD7Tc2JoB-gIcQEkIli7c,10442
47
+ crabcode_core/plan/types.py,sha256=pPfcdu40sTbxr8uBNAEguZR1GzvSFYDIL40HL_bU_io,5733
48
+ crabcode_core/prompts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
49
+ crabcode_core/prompts/context.py,sha256=MK6OReA1lf-z7zIcBQQS3FJwLsybxadD50OnTz0iVu4,7410
50
+ crabcode_core/prompts/profile.py,sha256=MWxdrC0vVc6QfaRa5sgKEC8Gi_s61F9ZaxjoCTiiEPc,2088
51
+ crabcode_core/prompts/system.py,sha256=iM5JjFtnJ4ymnDwPOwplRvVKEPDzvv31r5k5RTNwhfk,35874
52
+ crabcode_core/prompts/templates.py,sha256=vRAlUbnvVdDWtHW122iC4oCtknFm1p7WFTEB_3SZhhA,2638
53
+ crabcode_core/query/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
54
+ crabcode_core/query/loop.py,sha256=R0fkF70wvOx-MCASFNjzik2wQYu0mWqHU4zKBKajeGs,62328
55
+ crabcode_core/schedule/__init__.py,sha256=Pf1VyLKpZuvtxkUyYmJv0m79vYfN9p542A26UTBS-0E,149
56
+ crabcode_core/schedule/models.py,sha256=T3Z7wapFCkuE_ZeIDK2Clq8WGThKs88ENjXklT1_LE8,7847
57
+ crabcode_core/schedule/store.py,sha256=3NL8xKgyDvndiuw3Zc32_rt6Bze3VmTbVd9_DM67MII,12455
58
+ crabcode_core/session/__init__.py,sha256=0E_Flt_OkcFVkxbRTDVxot3TrUZ23T5qspIJqlYnwtE,441
59
+ crabcode_core/session/export.py,sha256=pF_nT60XaqmeTxGgiLnGPnW-SeOFscI1V8qCCqOhlOE,4521
60
+ crabcode_core/session/meta_db.py,sha256=r-rZUEPsLQPhdYKhRIuo-y1hXuDm0YPiVoFKzIjVcto,20472
61
+ crabcode_core/session/storage.py,sha256=m0e0Jo_1Rh-PMUR6IW2QDm_m9P9E15aL0Ptx1nI7h-0,66401
62
+ crabcode_core/session/title_gen.py,sha256=TrIqrWRSScZjVGOaG3h4zl7PhxPMD-86zLIYcVdElP4,1507
63
+ crabcode_core/skills/__init__.py,sha256=2A99hK6_T53EPy-hcYYu4FobhUAZjLL-O7ObIyG3yuQ,296
64
+ crabcode_core/skills/loader.py,sha256=VbT3C84xQ3AOf96MTZmyk3J71Z06M2sGajaQKciBXME,7142
65
+ crabcode_core/skills/matcher.py,sha256=gPt-nYz9YmUK_Pb3KjivrYl6izDSBiYo3HlrDhxcggs,7066
66
+ crabcode_core/snapshot/__init__.py,sha256=ACgq5C5_ChCXTW8UJWzhWz8vAJLw5MKtNyt9F1fYKQk,418
67
+ crabcode_core/snapshot/snapshot.py,sha256=RPcywyzxUYlg1fFSVxUAvpJnLLlN0rXMN6rk-NaqwJQ,17101
68
+ crabcode_core/snapshot/tracker.py,sha256=7ykjcb32vAPqAczvMmCxyRjP4lxg74ctl7s_ItRE3WI,8392
69
+ crabcode_core/team/__init__.py,sha256=llNqc6kSc5ng3WI1_-ABFe9RXc189A3MMXb1awKB4Ko,502
70
+ crabcode_core/team/bridge.py,sha256=JMBjN33rWwrqLdzsTb4liP6Sc9I86u2JNqneWaaei60,2065
71
+ crabcode_core/team/inbox.py,sha256=_20DYi_Eyv-9ZX56hwGGOJTUgGPxCBOuks5CqztUCDw,11920
72
+ crabcode_core/team/manager.py,sha256=dxkzpMYXtkUTB2UpgubtWNM8VQKfop6ftKiHcJRYkKo,74202
73
+ crabcode_core/team/message_bus.py,sha256=vUKISSyfl645gV6JO3duSo3vH5g4JZMrdLlh5zXyPRI,37930
74
+ crabcode_core/team/models.py,sha256=QHICKRNpGK6Gc3pMb_3TY6CvFLEtLm-jF9R4HKGIhQo,5653
75
+ crabcode_core/team/recovery.py,sha256=77vA3dE9IuY16n-Qh0gtuKCbmc7C1l-Mb-hiMBXpD0c,6790
76
+ crabcode_core/tools/__init__.py,sha256=HksLLMIiccPPJnNGp8fdxHCSEpLsTv0YImzgcBsC7JA,2828
77
+ crabcode_core/tools/_input_helpers.py,sha256=d7sketqhc2kWodNeuUVfiD40-GnKArsrmxGxfjtXEAE,1298
78
+ crabcode_core/tools/agent.py,sha256=KLIPgm1JsYcGY3fMR0Gj4L3m5YepBXJ66ape1f9ykPo,16520
79
+ crabcode_core/tools/ask_user.py,sha256=6CjWaX6f-3RWPyBSSWq4r5m63vRT_wu5_dflAbvE2fY,4466
80
+ crabcode_core/tools/bash.py,sha256=KViz4KZzpcCIGkj5ZLx8aUpcA3xubHx00HZvzOdeLoE,5292
81
+ crabcode_core/tools/browser.py,sha256=3x8sRdZZetlO5uRpbWchmryLQ0EiUtTvScFPoR2GZnU,28267
82
+ crabcode_core/tools/checklist.py,sha256=fZCHi1ft_Yo1bXMBcG-wMdZOFdPQZGOdeHdwYboBDkE,9265
83
+ crabcode_core/tools/checkpoint.py,sha256=4xQpC4ehYEQdPNK5hCCNMvtiVZ7Tdi8sXUGiJTvhBM8,2581
84
+ crabcode_core/tools/diff_utils.py,sha256=IYuEe53zyvb1FAEIU0vcsEPQGCz1TZCyekMhJC5r0AE,3480
85
+ crabcode_core/tools/file_edit.py,sha256=SX9r0e7tBbAH-7xWMERaEqFQI9Fjb7L9AwfJiD8rtPU,7471
86
+ crabcode_core/tools/file_read.py,sha256=62sjx1wHNaaOF3XOAKubJ6jhT5V5XWUEnnLwhYqOsDw,5085
87
+ crabcode_core/tools/file_write.py,sha256=6iKg6kyrIcLGeyC2iwN8Z9WE1CDi7L90yFYU1O_GwzU,4829
88
+ crabcode_core/tools/glob.py,sha256=cB9DKE1r0dZqeojzxkfix4am4eI2bCqyDmgK5xc_wdY,3876
89
+ crabcode_core/tools/goal.py,sha256=N_63Yhs-TtfhYW26gV2-MCeA8B2D3M44Cz9v7Iys5zc,4640
90
+ crabcode_core/tools/grep.py,sha256=oX9dJG9HM915IFqHCCSsztdOxpaOV3KBT6JAft7TBWk,5657
91
+ crabcode_core/tools/lint.py,sha256=czOpZNajZsrTyI7AI8i149iw4T_inUnhoFJqv7oTUIw,12968
92
+ crabcode_core/tools/memory.py,sha256=PUktTd6E1khTKNfTjT0XeW8kPI7OtDOJoA2E0IWx1hA,17418
93
+ crabcode_core/tools/monitor.py,sha256=irc6mu85_L7vKeADRDltYqJDImsQByVu3-PZ93a8cOc,25071
94
+ crabcode_core/tools/peer.py,sha256=6epsy3AiQBzdt71VQst_tSIU2T3YRs7IO7Y3Ahq4ryc,3848
95
+ crabcode_core/tools/revert.py,sha256=xFIplwG7KV_YjMhhCEKr_cu2LYXt-jkvvewrnlk-rmw,3393
96
+ crabcode_core/tools/schedule.py,sha256=tfqCBRXM8kPzR7Mxyogly6Ui8kueqzGxaLalgyVRn3s,21954
97
+ crabcode_core/tools/skill.py,sha256=QdxSh4lRjBOR1J9ggU3_1sZtyETeYxXui9eBj-VFNk4,4763
98
+ crabcode_core/tools/switch_mode.py,sha256=emWTDFFzkyZwPr6ZZtG-cGVqOpmYrWCZCmjtW-wg698,9258
99
+ crabcode_core/tools/team.py,sha256=njjxjbLnnaO4RZNSqieQyFzhdMij9nZiku0zYEugOiU,12671
100
+ crabcode_core/tools/web_search.py,sha256=SmQLjPmvLCNeAM0i1nT4NtsNGrlJXqxoipvcQoJujX4,12009
101
+ crabcode_core/types/__init__.py,sha256=_ekOogt6SS_Iomt7MPz7gEmE0zjuN1VepG_qy5yHAOs,1810
102
+ crabcode_core/types/config.py,sha256=A9W45RROv7xLUtjtEoYkhr_tHU0oxN2oVXNy6LE905M,8194
103
+ crabcode_core/types/event.py,sha256=AdnWE-ij7V9Zanoxnt-vEces_ux2swfDPHmA_10iVNI,6196
104
+ crabcode_core/types/message.py,sha256=VFM38RwWqlVJE3yv7nRxw71fY638WyuYO8U2uObZgCw,6904
105
+ crabcode_core/types/tool.py,sha256=u4PZp8P2menfXx9fwDloN-TqGD38sz4xgtJcNaLG1lo,5232
106
+ crabcode_debugger/__init__.py,sha256=5CHIc3Q7gUDiKLiWhglAiya65OE2qe0z-SfaBUkXG1Q,152
107
+ crabcode_debugger/adapters.py,sha256=7qqjnD8NIgHctxU7mBbwwjAZKdfxPeFYkKFek_cSzbU,11788
108
+ crabcode_debugger/dap.py,sha256=5IPk58SFZO2wV3KXLb2P5Kl7MEvAUZaMUZD3HZ_CqbM,8136
109
+ crabcode_debugger/memory.py,sha256=IT8qS4Ki2eP6CdNZhkPSeNNxx_kNd272zfTq2HWPGhc,63763
110
+ crabcode_debugger/process.py,sha256=5Uhba-tn-rv9rJxo0xKNJ0eaKqa7BfRPmDTLSvwKXuQ,24504
111
+ crabcode_debugger/runtime.py,sha256=KOc-43rKd7OlddBlNj56CKNaZUrJQlPiYw5Vec_0b44,602
112
+ crabcode_debugger/sessions.py,sha256=9-LgUKbUMVZwZUVPcBIdgzhdTRDY4F4PBwdCh5MzYwM,13683
113
+ crabcode_debugger/tool.py,sha256=Gnrn2PycsLqO6u3Pvmibf8qQNVca6mN2e349_iiMlHI,30946
114
+ crabcode_gateway/__init__.py,sha256=Y2L2ObTs5aJvCjQ1rlGRDtSCbxnOM3-HtrBfJqbbhdA,157
115
+ crabcode_gateway/adapter.py,sha256=jlFzke-V4LfgA20QDQuOMSVWmrrt9QYM1n8Mee_d3lQ,842
116
+ crabcode_gateway/event_bus.py,sha256=g4MEZtOmw2nnkSpBeqnLcjwuobKOnKrPz6YiL0IbBmo,25396
117
+ crabcode_gateway/middleware.py,sha256=T-uQ7oxaH4FbIItjMsJnpHGwcD_6qFL1flcJ7ylYP9k,9193
118
+ crabcode_gateway/schemas.py,sha256=90vOzZuHl5oeZN9Msbxx5-G6fZyU7M4uZRSprruFDJc,18115
119
+ crabcode_gateway/server.py,sha256=SV7d855jDvo9YDLQuCnZwqMegeOj6gWen1b4F2JvYAk,14413
120
+ crabcode_gateway/session_registry.py,sha256=HhvLvlGDx0EgmGwjk2zHCCtWURmNDZHHmpBjroX35fk,1214
121
+ crabcode_gateway/task_registry.py,sha256=Bm03rLvUTq7LRPq1Tm80YPD1kooS91M08Mqn5ZnpNAg,23935
122
+ crabcode_gateway/acp/__init__.py,sha256=PJUCdGBi_ud--LoWxbYbzO7gAgdFCzY_UKeB3JhUvUA,352
123
+ crabcode_gateway/acp/agent.py,sha256=MQACBcrs-j-u1oaVjn4fPI9ycYPnhGOvFN6W1DYto8U,59233
124
+ crabcode_gateway/acp/session.py,sha256=rbN1EcCQw2-LEr-bbW3x0TVmeL5ZGeEaSfBX6LEmjws,4049
125
+ crabcode_gateway/acp/transport.py,sha256=IWU3ih_9heY-EH-AhbprAtpcaj8ZvtWMMS76CAX82QA,1119
126
+ crabcode_gateway/acp/types.py,sha256=_hGt2o7CnhfgC_lvOTtdc_Z1hk6y3WE3RCdJ0Qz0hws,2424
127
+ crabcode_gateway/grpc/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
128
+ crabcode_gateway/grpc/crabcode_pb2.py,sha256=olmqo0HbLHO22PdKWpCMKmCtG9eUBM4iiHwDc1DwXLc,8102
129
+ crabcode_gateway/grpc/crabcode_pb2_grpc.py,sha256=NDrpxgGsd5tqe5mT9_Fr15V72RbegfOb6eXzNf5t16s,20996
130
+ crabcode_gateway/grpc/server.py,sha256=2L5eHJDu-lxSbbvKnKkobjmFH4bxzfKEVitgfV_24Iw,29107
131
+ crabcode_gateway/grpc/proto/crabcode.proto,sha256=VqN5CKiRBQ3OPBL25g2bT1Bt10olVXcmGJqq3tKkUW8,4099
132
+ crabcode_gateway/routes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
133
+ crabcode_gateway/routes/agent.py,sha256=fbfA9cvxlsAJ2IMH1EJhYpuNLGAfyYgr--YZR5dBLrs,8280
134
+ crabcode_gateway/routes/config.py,sha256=tTOQeknFF4FAzCWcgZveU28Iktiajh62sXWh7kxw0jY,13553
135
+ crabcode_gateway/routes/event.py,sha256=p8mt87i91CAU4SaAundS1eqhtkeIBe5NUyGSVQoi2Bs,62901
136
+ crabcode_gateway/routes/health.py,sha256=GzR1RAGNmOPXEyUQNRE0ANJsbDMOQHQGNRhA3dRz87Y,293
137
+ crabcode_gateway/routes/permission.py,sha256=QL14Le9wgknpbBVp3YM54v2kTl75X9zvfWCVVB43e3s,3798
138
+ crabcode_gateway/routes/session.py,sha256=s7kSmd5arWn3ZL03isr0iijq4r_1ujraEhV5GYM4fXY,31446
139
+ crabcode_gateway/routes/snapshot.py,sha256=4pkZKoHHjDAXbnTatIC2Ma7s3I5SuMfRMhfLbNaSzmc,6268
140
+ crabcode_search/__init__.py,sha256=Fw3-cySOi83Y6WSduXUTC62ANXA5lf7PX3kSnQoXEUs,272
141
+ crabcode_search/background.py,sha256=urkJ6RV-aQvCRlaQr2n08S7NiY2sCDEjC-vOZw4vRl0,11098
142
+ crabcode_search/chunker.py,sha256=gtpMWAjNBEAmr9cfhU5uOcuXZFDhEpNRubVbttaxT14,16148
143
+ crabcode_search/embedder.py,sha256=NlNuOHS7t4JvaWXkNU-T_xxnkjRxFrr3l57dlB5IRkc,16728
144
+ crabcode_search/indexer.py,sha256=wNHrzB9oW8eRcKek6ZtXJdRB_HgFLj_1LhqqtG_tiDw,7522
145
+ crabcode_search/store.py,sha256=7E7fkQ25CgX0LlIp6wrgQNkVS9epUaqLpfoDA_V-BWg,8002
146
+ crabcode_search/tool.py,sha256=oGcQybm173Xe8Nho41RaXhx4jKMFD6l0-wQgUOEtizc,10034
147
+ crabcode-0.1.4.dist-info/METADATA,sha256=OjlglMWaZHHX8T-7sVaoQ9E9NegME3eDEMu4r7wWlV4,2164
148
+ crabcode-0.1.4.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
149
+ crabcode-0.1.4.dist-info/entry_points.txt,sha256=tpYKME-yDLFb2eqwryWJG-d-HW4dkvDbzwogRl2jays,52
150
+ crabcode-0.1.4.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: hatchling 1.29.0
2
+ Generator: hatchling 1.32.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
crabcode_cli/__init__.py CHANGED
@@ -1,3 +1,7 @@
1
1
  """CrabCode CLI - terminal frontend."""
2
2
 
3
- __version__ = "0.1.2"
3
+ from crabcode_core import VERSION
4
+
5
+ __version__ = VERSION
6
+
7
+ __all__ = ["VERSION", "__version__"]
crabcode_cli/app.py CHANGED
@@ -38,7 +38,23 @@ def main(
38
38
 
39
39
  work_dir = cwd or os.getcwd()
40
40
 
41
+ # Resolve cross-project resumes before loading project settings or creating
42
+ # any cwd-bound runtime resources. CoreSession also rebinds an already
43
+ # initialized session, but startup should take the correct project path
44
+ # from the outset.
45
+ if resume:
46
+ from crabcode_core.session.storage import SessionStorage
47
+
48
+ resolved_storage = SessionStorage.from_session_id(resume)
49
+ if resolved_storage is not None:
50
+ work_dir = resolved_storage.cwd
51
+
41
52
  settings = CrabCodeSettings()
53
+ # Keep CLI flags separate from project-file values. CoreSession needs
54
+ # this distinction when an interactive REPL later resumes a session from a
55
+ # different project; otherwise the first project's config is treated as a
56
+ # caller override and shadows the target project's settings.
57
+ explicit_settings = CrabCodeSettings()
42
58
 
43
59
  from crabcode_core.config.manager import ConfigManager
44
60
  file_settings = ConfigManager(cwd=work_dir).load()
@@ -52,26 +68,40 @@ def main(
52
68
  settings.api.base_url = file_settings.api.base_url
53
69
  if file_settings.api.api_key_env:
54
70
  settings.api.api_key_env = file_settings.api.api_key_env
71
+ if file_settings.api.codex_auth_path:
72
+ settings.api.codex_auth_path = file_settings.api.codex_auth_path
55
73
  if file_settings.api.http_headers:
56
74
  settings.api.http_headers = dict(file_settings.api.http_headers)
57
75
  if file_settings.api.format:
58
76
  settings.api.format = file_settings.api.format
59
77
  if not file_settings.api.thinking_enabled:
60
78
  settings.api.thinking_enabled = file_settings.api.thinking_enabled
79
+ if file_settings.api.pass_reasoning_content:
80
+ settings.api.pass_reasoning_content = file_settings.api.pass_reasoning_content
81
+ if file_settings.api.reasoning_effort is not None:
82
+ settings.api.reasoning_effort = file_settings.api.reasoning_effort
61
83
  if file_settings.api.max_tokens != 16384:
62
84
  settings.api.max_tokens = file_settings.api.max_tokens
85
+ if file_settings.api.extra_body:
86
+ settings.api.extra_body = dict(file_settings.api.extra_body)
63
87
  if file_settings.api.azure_endpoint:
64
88
  settings.api.azure_endpoint = file_settings.api.azure_endpoint
65
89
  if file_settings.api.azure_api_version:
66
90
  settings.api.azure_api_version = file_settings.api.azure_api_version
67
91
  if file_settings.api.azure_deployment:
68
92
  settings.api.azure_deployment = file_settings.api.azure_deployment
93
+ if file_settings.ultra_mode:
94
+ settings.ultra_mode = True
95
+ if file_settings.tool_call_timeout is not None:
96
+ settings.tool_call_timeout = file_settings.tool_call_timeout
69
97
 
70
98
  if file_settings.models:
71
99
  settings.models = {**file_settings.models, **settings.models}
72
100
  if file_settings.default_model and not settings.default_model:
73
101
  settings.default_model = file_settings.default_model
74
102
 
103
+ if file_settings.permissions.default_mode and not settings.permissions.default_mode:
104
+ settings.permissions.default_mode = file_settings.permissions.default_mode
75
105
  if file_settings.permissions.run_everything:
76
106
  settings.permissions.run_everything = True
77
107
  settings.logging = file_settings.logging.model_copy(deep=True)
@@ -80,16 +110,20 @@ def main(
80
110
 
81
111
  if model:
82
112
  settings.api.model = model
113
+ explicit_settings.api.model = model
83
114
  if provider:
84
115
  settings.api.provider = provider
116
+ explicit_settings.api.provider = provider
85
117
  if base_url:
86
118
  settings.api.base_url = base_url
119
+ explicit_settings.api.base_url = base_url
87
120
  if api_format:
88
121
  settings.api.format = api_format
122
+ explicit_settings.api.format = api_format
89
123
  if model_profile:
90
124
  if model_profile in file_settings.models:
91
- settings.models = file_settings.models
92
125
  settings.default_model = model_profile
126
+ explicit_settings.default_model = model_profile
93
127
  else:
94
128
  typer.echo(
95
129
  f"Warning: model profile '{model_profile}' not found in settings.models. "
@@ -97,6 +131,8 @@ def main(
97
131
  err=True,
98
132
  )
99
133
 
134
+ settings._crabcode_explicit_settings = explicit_settings
135
+
100
136
  # Read image files into base64 attachments
101
137
  image_attachments: list[dict[str, str]] | None = None
102
138
  if image:
@@ -191,8 +227,10 @@ def sessions_list(
191
227
  if all_projects:
192
228
  from crabcode_core.session.meta_db import SessionMetaStore
193
229
  store = SessionMetaStore()
194
- rows = store.list_recent(limit=limit)
195
- store.close()
230
+ try:
231
+ rows = store.list_recent(limit=limit)
232
+ finally:
233
+ store.close()
196
234
  else:
197
235
  from crabcode_core.session.storage import SessionStorage
198
236
  rows = SessionStorage.list_sessions(work_dir)[:limit]
@@ -271,26 +309,36 @@ def sessions_prune(
271
309
  """Archive old sessions and optionally delete their files."""
272
310
  from crabcode_core.session.meta_db import SessionMetaStore
273
311
  store = SessionMetaStore()
274
- archived = store.auto_archive(days=days)
275
- typer.echo(f"Archived {archived} session(s) older than {days} days.")
276
- if delete_files:
277
- purged = store.purge_archived()
278
- for entry in purged:
279
- sid = entry["id"]
280
- cwd = entry.get("cwd", "")
281
- if cwd:
282
- from crabcode_core.session.storage import get_transcript_path
283
- path = get_transcript_path(cwd, sid)
312
+ try:
313
+ archived = store.auto_archive(days=days)
314
+ typer.echo(f"Archived {archived} session(s) older than {days} days.")
315
+ if delete_files:
316
+ candidates = store.purge_archived(delete_rows=False)
317
+ purged = 0
318
+ failed: list[str] = []
319
+ for entry in candidates:
320
+ sid = entry["id"]
321
+ cwd = entry.get("cwd", "")
284
322
  try:
285
- if path.exists():
286
- path.unlink()
287
- except OSError:
288
- pass
289
- typer.echo(f"Purged {len(purged)} archived session(s) from database and disk.")
290
- else:
291
- purged = store.purge_archived()
292
- typer.echo(f"Purged {len(purged)} archived session(s) from database.")
293
- store.close()
323
+ if cwd:
324
+ from crabcode_core.session.storage import purge_session_artifacts
325
+
326
+ purge_session_artifacts(cwd, sid)
327
+ store.delete(sid)
328
+ purged += 1
329
+ except (OSError, ValueError):
330
+ # Retain the archived row so a later prune can retry and so
331
+ # the command never claims a failed disk deletion succeeded.
332
+ failed.append(sid)
333
+ typer.echo(f"Purged {purged} archived session(s) from database and disk.")
334
+ if failed:
335
+ typer.echo(
336
+ f"Failed to delete {len(failed)} session artifact set(s); "
337
+ "their archived database rows were retained for retry.",
338
+ err=True,
339
+ )
340
+ finally:
341
+ store.close()
294
342
 
295
343
 
296
344
  @app.command("gateway")
@@ -411,21 +459,23 @@ def stats(
411
459
  return f"{n / 1_000:.1f}k"
412
460
  return str(n)
413
461
 
414
- if project:
415
- p = store.stats_by_project(work_dir)
416
- typer.echo(f"Project: {work_dir}")
417
- typer.echo(f" Sessions: {p['total_sessions']} | Tokens: {_fmt_tok(p['total_tokens'])} | Messages: {p['total_messages']}")
418
- else:
419
- g = store.stats_global()
420
- p = store.stats_by_project(work_dir)
421
- models = store.stats_by_model(limit=5)
422
- typer.echo(f"Global: {g['total_sessions']} sessions | {_fmt_tok(g['total_tokens'])} tokens | {g['active_projects']} projects")
423
- typer.echo(f"This week: {g['week_sessions']} sessions | {_fmt_tok(g['week_tokens'])} tokens")
424
- typer.echo(f"This project: {p['total_sessions']} sessions | {_fmt_tok(p['total_tokens'])} tokens | {p['total_messages']} messages")
425
- if models:
426
- model_parts = [f"{m['model']} ({_fmt_tok(m['tokens'])})" for m in models]
427
- typer.echo(f"Top models: {', '.join(model_parts)}")
428
- store.close()
462
+ try:
463
+ if project:
464
+ p = store.stats_by_project(work_dir)
465
+ typer.echo(f"Project: {work_dir}")
466
+ typer.echo(f" Sessions: {p['total_sessions']} | Tokens: {_fmt_tok(p['total_tokens'])} | Messages: {p['total_messages']}")
467
+ else:
468
+ g = store.stats_global()
469
+ p = store.stats_by_project(work_dir)
470
+ models = store.stats_by_model(limit=5)
471
+ typer.echo(f"Global: {g['total_sessions']} sessions | {_fmt_tok(g['total_tokens'])} tokens | {g['active_projects']} projects")
472
+ typer.echo(f"This week: {g['week_sessions']} sessions | {_fmt_tok(g['week_tokens'])} tokens")
473
+ typer.echo(f"This project: {p['total_sessions']} sessions | {_fmt_tok(p['total_tokens'])} tokens | {p['total_messages']} messages")
474
+ if models:
475
+ model_parts = [f"{m['model']} ({_fmt_tok(m['tokens'])})" for m in models]
476
+ typer.echo(f"Top models: {', '.join(model_parts)}")
477
+ finally:
478
+ store.close()
429
479
 
430
480
 
431
481
  def entry() -> None:
crabcode_cli/pipe.py CHANGED
@@ -48,18 +48,35 @@ def _format_percent(percent: float) -> str:
48
48
  def _format_context_usage(event: TurnCompleteEvent) -> str | None:
49
49
  used = max(0, int(getattr(event, "context_used_tokens", 0) or 0))
50
50
  window = max(0, int(getattr(event, "context_window_tokens", 0) or 0))
51
- if not used and not window:
52
- return None
53
- if not window:
54
- return f"Context: {_format_token_count(used)} tokens used (window unknown)"
51
+ parts: list[str] = []
52
+ if window:
53
+ used_percent = max(0.0, float(getattr(event, "context_used_percent", 0.0) or 0.0))
54
+ remaining_percent = max(0.0, 100.0 - used_percent)
55
+ parts.append(
56
+ f"Context: {_format_percent(used_percent)} used "
57
+ f"({_format_percent(remaining_percent)} remaining) · "
58
+ f"{_format_token_count(used)} tokens used of {_format_token_count(window)}"
59
+ )
60
+ elif used:
61
+ parts.append(f"Context: {_format_token_count(used)} tokens used (window unknown)")
55
62
 
56
- used_percent = max(0.0, float(getattr(event, "context_used_percent", 0.0) or 0.0))
57
- remaining_percent = max(0.0, 100.0 - used_percent)
58
- return (
59
- f"Context: {_format_percent(used_percent)} used "
60
- f"({_format_percent(remaining_percent)} remaining) · "
61
- f"{_format_token_count(used)} tokens used of {_format_token_count(window)}"
62
- )
63
+ usage = event.usage
64
+ if "cache_read_tokens" in usage or "cache_write_tokens" in usage:
65
+ cache_read = max(0, int(usage.get("cache_read_tokens", 0) or 0))
66
+ cache_write = max(0, int(usage.get("cache_write_tokens", 0) or 0))
67
+ total_input = max(
68
+ 0,
69
+ int(usage.get("total_input_tokens", usage.get("input_tokens", 0)) or 0),
70
+ )
71
+ hit_rate = cache_read / total_input * 100 if total_input else 0.0
72
+ cache_parts = [
73
+ f"Cache: {_format_percent(hit_rate)} hit",
74
+ f"read {_format_token_count(cache_read)}",
75
+ ]
76
+ if "cache_write_tokens" in usage:
77
+ cache_parts.append(f"write {_format_token_count(cache_write)}")
78
+ parts.append(" · ".join(cache_parts))
79
+ return " · ".join(parts) or None
63
80
 
64
81
 
65
82
  async def run_pipe(