emdash-core 0.1.33__py3-none-any.whl → 0.1.60__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 (67) hide show
  1. emdash_core/agent/agents.py +93 -23
  2. emdash_core/agent/background.py +481 -0
  3. emdash_core/agent/hooks.py +419 -0
  4. emdash_core/agent/inprocess_subagent.py +114 -10
  5. emdash_core/agent/mcp/config.py +78 -2
  6. emdash_core/agent/prompts/main_agent.py +88 -1
  7. emdash_core/agent/prompts/plan_mode.py +65 -44
  8. emdash_core/agent/prompts/subagents.py +96 -8
  9. emdash_core/agent/prompts/workflow.py +215 -50
  10. emdash_core/agent/providers/models.py +1 -1
  11. emdash_core/agent/providers/openai_provider.py +10 -0
  12. emdash_core/agent/research/researcher.py +154 -45
  13. emdash_core/agent/runner/agent_runner.py +157 -19
  14. emdash_core/agent/runner/context.py +28 -9
  15. emdash_core/agent/runner/sdk_runner.py +29 -2
  16. emdash_core/agent/skills.py +81 -1
  17. emdash_core/agent/toolkit.py +87 -11
  18. emdash_core/agent/toolkits/__init__.py +117 -18
  19. emdash_core/agent/toolkits/base.py +87 -2
  20. emdash_core/agent/toolkits/explore.py +18 -0
  21. emdash_core/agent/toolkits/plan.py +18 -0
  22. emdash_core/agent/tools/__init__.py +2 -0
  23. emdash_core/agent/tools/coding.py +344 -52
  24. emdash_core/agent/tools/lsp.py +361 -0
  25. emdash_core/agent/tools/skill.py +21 -1
  26. emdash_core/agent/tools/task.py +27 -23
  27. emdash_core/agent/tools/task_output.py +262 -32
  28. emdash_core/agent/verifier/__init__.py +11 -0
  29. emdash_core/agent/verifier/manager.py +295 -0
  30. emdash_core/agent/verifier/models.py +97 -0
  31. emdash_core/{swarm/worktree_manager.py → agent/worktree.py} +19 -1
  32. emdash_core/api/agent.py +451 -5
  33. emdash_core/api/research.py +3 -3
  34. emdash_core/api/router.py +0 -4
  35. emdash_core/context/longevity.py +197 -0
  36. emdash_core/context/providers/explored_areas.py +83 -39
  37. emdash_core/context/reranker.py +35 -144
  38. emdash_core/context/simple_reranker.py +500 -0
  39. emdash_core/context/tool_relevance.py +84 -0
  40. emdash_core/core/config.py +8 -0
  41. emdash_core/graph/__init__.py +8 -1
  42. emdash_core/graph/connection.py +24 -3
  43. emdash_core/graph/writer.py +7 -1
  44. emdash_core/ingestion/repository.py +17 -198
  45. emdash_core/models/agent.py +14 -0
  46. emdash_core/server.py +1 -6
  47. emdash_core/sse/stream.py +16 -1
  48. emdash_core/utils/__init__.py +0 -2
  49. emdash_core/utils/git.py +103 -0
  50. emdash_core/utils/image.py +147 -160
  51. {emdash_core-0.1.33.dist-info → emdash_core-0.1.60.dist-info}/METADATA +7 -5
  52. {emdash_core-0.1.33.dist-info → emdash_core-0.1.60.dist-info}/RECORD +54 -58
  53. emdash_core/api/swarm.py +0 -223
  54. emdash_core/db/__init__.py +0 -67
  55. emdash_core/db/auth.py +0 -134
  56. emdash_core/db/models.py +0 -91
  57. emdash_core/db/provider.py +0 -222
  58. emdash_core/db/providers/__init__.py +0 -5
  59. emdash_core/db/providers/supabase.py +0 -452
  60. emdash_core/swarm/__init__.py +0 -17
  61. emdash_core/swarm/merge_agent.py +0 -383
  62. emdash_core/swarm/session_manager.py +0 -274
  63. emdash_core/swarm/swarm_runner.py +0 -226
  64. emdash_core/swarm/task_definition.py +0 -137
  65. emdash_core/swarm/worker_spawner.py +0 -319
  66. {emdash_core-0.1.33.dist-info → emdash_core-0.1.60.dist-info}/WHEEL +0 -0
  67. {emdash_core-0.1.33.dist-info → emdash_core-0.1.60.dist-info}/entry_points.txt +0 -0
@@ -1,27 +1,29 @@
1
1
  emdash_core/__init__.py,sha256=2VnFDN5zmKekKBa5rHZY9nz2Dhv2lB_O6dTcz-wyF8s,226
2
2
  emdash_core/agent/__init__.py,sha256=rGY5MXggrv6TLHqNMp3v1oDldL_KErvLIoHARimlNbk,1195
3
- emdash_core/agent/agents.py,sha256=CCsDJSl9Vwhitc71L9oQ6SO_qhhyumI7L07Osmgugcg,5825
3
+ emdash_core/agent/agents.py,sha256=r1ZnEgA5_LI4zonhrcbJ6LoUqRDFehSZG-fRXZxdkSM,8330
4
+ emdash_core/agent/background.py,sha256=4lXNW8NHkfZuOFmMAamYypNIcnuphu27Wy_JjNBOLIc,15367
4
5
  emdash_core/agent/code_reviewer.py,sha256=oUXcDbk773kwYtcCsUNEjb_ipS9rLeCKIv_IEUiUA9k,16467
5
6
  emdash_core/agent/compaction.py,sha256=_smuIjmzaiblr6viRFByQCekRzoZDTetcaXRLQol8CI,4102
6
7
  emdash_core/agent/context_manager.py,sha256=3HBQFRwsq1bBx6R7FQp7xFsiW0zPLPnOF-8Ox4Y6K44,3676
7
8
  emdash_core/agent/events.py,sha256=Qw6s6jzBFXIlsDNpPBiIwNB72tnjbAJNt6hhcblOslg,11930
8
9
  emdash_core/agent/handlers.py,sha256=3zo76GT3cTfYayK1qvP2NFo14AXHfA36X-yaa7Xm3T0,7135
9
- emdash_core/agent/inprocess_subagent.py,sha256=spYScY2T2ej_XCuNkQE1CDoyb5cutbLseC8PbX2gpwA,15877
10
+ emdash_core/agent/hooks.py,sha256=zpKsbcR5X0iZo65VULMsoE84nfdArwDz1uULlgbZATM,13635
11
+ emdash_core/agent/inprocess_subagent.py,sha256=lsW6DWrAt51PuyX1wMc_o86dA1h-CrLgsnsQHuRI-Kk,20652
10
12
  emdash_core/agent/mcp/__init__.py,sha256=qzQMJJOgOYVb6X2uyJxTIGgV5x35Dn7H3IglZxToX_c,1081
11
13
  emdash_core/agent/mcp/client.py,sha256=_ae6CWRnJfG_mcCcIYZJYbWjajpZC-WmZgsZsRaahco,9753
12
- emdash_core/agent/mcp/config.py,sha256=JrO7xIC3oSiFlxeTVynKm1pq2CrYdqzTsIJj9neSJLQ,9220
14
+ emdash_core/agent/mcp/config.py,sha256=Z48JK26qZvywfvD3m7wvtR6axz4zYA40FQhDAYeBntk,11584
13
15
  emdash_core/agent/mcp/manager.py,sha256=i4OIJyAwfBAw0E8fe6NIOvT-UTf1_hmDbEtIjtAhRjc,15382
14
16
  emdash_core/agent/mcp/tool_factory.py,sha256=jtQJ2TW7KdGVSg3fUp9-rm7MbHjiwWmy0yLfwr0H4qc,6410
15
17
  emdash_core/agent/prompts/__init__.py,sha256=BuCvF0XLJdhXSWNz0NoJI6dBnomLzRcfZxdBWmkh8tg,987
16
- emdash_core/agent/prompts/main_agent.py,sha256=d-OB18Kdw6H2CF8AUSvmFGDdI6-k_8P7nobyik37fQk,4828
17
- emdash_core/agent/prompts/plan_mode.py,sha256=xGtYv8rvdhQhFKSqZpG4byawEPjQGSFuqO14cZcGThI,8070
18
- emdash_core/agent/prompts/subagents.py,sha256=-hVDu465Rg_042YIr6Dkdy_rM-qzzjfrjQB9GqCoNv8,6946
19
- emdash_core/agent/prompts/workflow.py,sha256=ou5ilg7eg3E7A0AgvT70u4trO_enKzkUpgNc74qKbOE,12898
18
+ emdash_core/agent/prompts/main_agent.py,sha256=t5HtT4AzifBqO6lcR6oCar8qWPEUm1oMiVx2udAdfaw,7213
19
+ emdash_core/agent/prompts/plan_mode.py,sha256=u52k12bQiFlxnUnN9Rh-samMfS9TGQRmsoT0-QIvW8U,9351
20
+ emdash_core/agent/prompts/subagents.py,sha256=FDgWmSwAMq3AabdMWwTjP_17n9NjrQrdc8l7VSN__IY,9622
21
+ emdash_core/agent/prompts/workflow.py,sha256=2suHrohQdJO5PRUVrsVy46pp5Kb8OYwiz5vNEYZ6MmA,18362
20
22
  emdash_core/agent/providers/__init__.py,sha256=q58ektAl1zwuS3z36ctHfLB8XruYghT97aq_oj1T_G0,776
21
23
  emdash_core/agent/providers/base.py,sha256=m1Vuac2Gtr191YDkefG_3qD64iIT9Ps2WoZC1LWmfJU,4351
22
24
  emdash_core/agent/providers/factory.py,sha256=UgPVNQupa73dKugyG_JqFgVdj4y5YJIGbcGXEbzx_1c,3213
23
- emdash_core/agent/providers/models.py,sha256=0mkkqiXOQKV25GbqJvm-85mPiJx3Cb3jbn3KTV4NbU0,8710
24
- emdash_core/agent/providers/openai_provider.py,sha256=URUv4g7P_87yOuWNYPd9pZNlw3SuCdPe5bvX-I_2EW0,21037
25
+ emdash_core/agent/providers/models.py,sha256=Tyt175fU0fy1YDSHgFEjcH5ABgPJUzvH7xSh4N94t4A,8756
26
+ emdash_core/agent/providers/openai_provider.py,sha256=cS44BX1sUQ1mjkGJt9RpNHzgrfK7QQbjs9ELMrk3uMg,21580
25
27
  emdash_core/agent/providers/transformers_provider.py,sha256=USSzYIcZrcTAKDKwiNobYUDS024ZVZ34WAuYWGbs9Nk,7167
26
28
  emdash_core/agent/research/__init__.py,sha256=4LU9Skk3sxsDy8GzfOxCjNxxqaxOm94hV5cH-Nyqn7g,1992
27
29
  emdash_core/agent/research/agent.py,sha256=dGjSZL2rsuJmSRpa8060R5gIvX8rIj57Zs21LsBJ-1U,3819
@@ -29,50 +31,55 @@ emdash_core/agent/research/controller.py,sha256=fWR8dXW68PCPqspyEjeJolJtDOKwaxeo
29
31
  emdash_core/agent/research/critic.py,sha256=99PAP-Acr2AegDib0FOP3sgt1oHdKbiicONkkYyssf4,13317
30
32
  emdash_core/agent/research/macros.py,sha256=3EM-7_zbetCbd2QeyDwG6NOt3i_OTIWF1nY75nh-OT4,15152
31
33
  emdash_core/agent/research/planner.py,sha256=2TjWKqbLg-fv5bEfc6-g729v0kQ5vs7FT-VIhxTG4HM,14333
32
- emdash_core/agent/research/researcher.py,sha256=RIcLkah0LcD_QNP7FgU_MZeblLRiZQIOubHwvqdghtw,14305
34
+ emdash_core/agent/research/researcher.py,sha256=AMRMVUHPS_xEKDOeflFSQwXNcy7ArYLVM_tkmxLg7B8,18184
33
35
  emdash_core/agent/research/state.py,sha256=P44YUTUhMrAmt--xsj8Hi0SzbDmrLXKPEf83HF2mqZs,18010
34
36
  emdash_core/agent/research/synthesizer.py,sha256=j4UvH8JxUjo7RF-h69tpRERgN6pHSb8qNBOoKrH2Qro,19016
35
37
  emdash_core/agent/reviewer_profile.py,sha256=RkJ_Mk5vbp2U-e0UBWB-k59cHsTzLj0aro22KJVCbss,16075
36
38
  emdash_core/agent/rules.py,sha256=GVwfM6YlRxrPXLZ0h2cZFOx4l_mPPl0Bdwt8oxfMBLI,3014
37
39
  emdash_core/agent/runner/__init__.py,sha256=FK3FUSsdKImso-QATYam5OnQhpCCHyXnXYRtmoLdQ80,1384
38
- emdash_core/agent/runner/agent_runner.py,sha256=kDpiF7i5nxBMtJG9Y_ki0gfWBkS_eJzwEswZJr6zZFs,31706
39
- emdash_core/agent/runner/context.py,sha256=Yw2A2q1Uisgpye3n1rqYQFSmZRidvbxWnUJdvm_EgpI,14124
40
+ emdash_core/agent/runner/agent_runner.py,sha256=SohKzZaDUAaPhosXBN-Gg3CciWMalW_CnFclzxlwe7Y,37168
41
+ emdash_core/agent/runner/context.py,sha256=U8tLUtBWgU1yD3j8XDquDEQNEM70HcxkIMRAOsfJP8c,15099
40
42
  emdash_core/agent/runner/factory.py,sha256=SXtfgD4F8R8cUDR4Tt-3LPHSDjyJwkyEAbxflXgjkqc,3288
41
43
  emdash_core/agent/runner/plan.py,sha256=WMra-xpWeNJ0YtdnQMsd2aak5BhryrzUP_OtZMhlzeA,7336
42
- emdash_core/agent/runner/sdk_runner.py,sha256=KrlWLagZc_01jqYBHioqz2WIJqXmb3INyFnYuTQnBZA,10587
44
+ emdash_core/agent/runner/sdk_runner.py,sha256=c9NKQyeEpXCEa5-Tc6lWinDCfsEwWHlBb3LdTYSgQTc,11741
43
45
  emdash_core/agent/runner/utils.py,sha256=1feF3-rYA9x3Inh7pKdtPSGpMzNM5bBV5s6CJVCqqJQ,1826
44
46
  emdash_core/agent/session.py,sha256=Zr7m8IK4-J6CDIMmN2QiSqpDT_O2S-SXu3Qmy9w6dk8,8517
45
- emdash_core/agent/skills.py,sha256=0DPDmcSjG8J4LrUID90qH8MFBJ9OIFHS9CKH3jUl0Oc,10516
47
+ emdash_core/agent/skills.py,sha256=u3IH1y2D8no2E_LT4YS6ilfCQ_83pQZ4-ZcOScMBXb8,13665
46
48
  emdash_core/agent/spec_schema.py,sha256=tmTCrO4zKXkOblW6gRyrQ3_ZdYU-ehnLE8YmZbhPHWQ,1429
47
49
  emdash_core/agent/specification.py,sha256=b1nUQiGT4NiRv42hDkYAXVX_RtsKcHrf4Ae1dx0UVnc,19105
48
50
  emdash_core/agent/subagent.py,sha256=zIlhbHOCUEgYtYLYwiQ7dkSleqI60emyBA-5XLPaH_k,12150
49
51
  emdash_core/agent/subagent_prompts.py,sha256=pJJPXh4FlnE8bt9d-Ruquz6j8W-BS9pMCbXRqpgwq4g,407
50
- emdash_core/agent/toolkit.py,sha256=bNDBNlxYEKwD5KkIsrZ4505ITKrlxt-W99H9pS_12BY,19897
51
- emdash_core/agent/toolkits/__init__.py,sha256=HrWyA1M666V0UZ6P7YISnnQg4rblWbIFW_HcMKlHfK4,1814
52
- emdash_core/agent/toolkits/base.py,sha256=Z4IMrli7UMi7K3rWhqfph_5vv9Tdnc0M8iCQDgE_3lM,2587
53
- emdash_core/agent/toolkits/explore.py,sha256=ymyvLjIXy80h3lb4y_DZ06T0vADCal976qMW19J6N8A,1395
54
- emdash_core/agent/toolkits/plan.py,sha256=wUj98JI6l7TjWLgXnPfAsmqXDqe02EdQ1akJVMgC9vc,1666
55
- emdash_core/agent/tools/__init__.py,sha256=gJ8mAi4yg-jAYjq0UidDt1x8thkfxybX8RbOCoN6ZHc,2966
52
+ emdash_core/agent/toolkit.py,sha256=elQRVzKf8Z95M-zuPpEA3AmvLqHukD0d6Gc488Q6mN0,23080
53
+ emdash_core/agent/toolkits/__init__.py,sha256=HPU7krOJ2zIdKT7ykH-k9h3CBH2YOizxkMCIU8r-kNs,5050
54
+ emdash_core/agent/toolkits/base.py,sha256=rQNKsrIMvtyfa_8YprZ-Vo8Khmkl5TgHXapol1UXCp8,5634
55
+ emdash_core/agent/toolkits/explore.py,sha256=5_f6q7x_nf7SkHb1osqQTrss4V-aFmmwR-gBtbCKhO0,1937
56
+ emdash_core/agent/toolkits/plan.py,sha256=ExDlf4dEN_eu41G40pABAvghPUxCnVF35j6lGN7bjIE,2205
57
+ emdash_core/agent/tools/__init__.py,sha256=kh7fVcUt2dBBHNK46bhmrUrnwNJc5jHc7IV8pxj0Kb4,3004
56
58
  emdash_core/agent/tools/analytics.py,sha256=tEP_RWFpKGfFW_Yc5inMMjAkDFzpDQ77Ui_Ca7LQu60,14837
57
59
  emdash_core/agent/tools/base.py,sha256=3clLKgR7Og5eDijZJLEcpJS1YV8u1rW_pXr_iwHdxTo,3349
58
- emdash_core/agent/tools/coding.py,sha256=tGGfDzjQySkIhMWMcGxDbC_c2p_hJSOLAyUJ-FCJzxo,16573
60
+ emdash_core/agent/tools/coding.py,sha256=hw48My5DygGJyw3ti_jINB8J9jHFxfinvabMHfAIZPg,28216
59
61
  emdash_core/agent/tools/github_mcp.py,sha256=D4fu_z9j-rL8SHD8TA2tO-ED-8Q4QB_RHQoqsh7Bjy8,16870
60
62
  emdash_core/agent/tools/history.py,sha256=Zaers4Aul9-hrlMaGRcQHwfU2xb7yCjHFHSDtfMe3c4,423
63
+ emdash_core/agent/tools/lsp.py,sha256=8x3zhH9JYebqrLmuyjYU4Jti-pn0TQCFiCM7uONM92o,12480
61
64
  emdash_core/agent/tools/modes.py,sha256=g82igKjpBeC23HgYRgULCNbjCRZQ6C-rmMMbNEGNbEk,10587
62
65
  emdash_core/agent/tools/plan.py,sha256=RRvZsDHcvvDv6uyDSGhTYIoImZmI_7CCxCarkeSZjbQ,7922
63
66
  emdash_core/agent/tools/plan_write.py,sha256=o4EEHTUr1hRfH3WSjrh3-QTfaJuUhjsQ5bJNBPD_j5Q,4417
64
67
  emdash_core/agent/tools/search.py,sha256=aq5_jc8YT3R3oZtulgvKwmz1oljJom20NfF_q60o60Q,14353
65
- emdash_core/agent/tools/skill.py,sha256=B7IefgH2DndHXFOaozSnJkhLQj9VQHNJH7-0ovgVmS0,6124
68
+ emdash_core/agent/tools/skill.py,sha256=phrsvWXxNsXY8iQO_D32XD7LcdA6BBhirCgRMQYkiik,7025
66
69
  emdash_core/agent/tools/spec.py,sha256=R9Ib-1epCVrgbOB6C9qYkwvgut94x3P2g4_FM_tMd2M,10022
67
- emdash_core/agent/tools/task.py,sha256=BQLqSXULtQPRw5BFix6MdiNvfMFo0TqAa4momN_wQys,10719
68
- emdash_core/agent/tools/task_output.py,sha256=30EI8JAKBDw6gLmjF8bXAq00yMr-Qk14J7fv2kDVX1c,6421
70
+ emdash_core/agent/tools/task.py,sha256=kAogDNSyOVB_SJRcyYav0INJ3MzlSlwhmv-9ArRqsZc,11133
71
+ emdash_core/agent/tools/task_output.py,sha256=fKeNajN-KWw06u80bDsu0y3BzmU5thX2wV-oEInZ72s,13868
69
72
  emdash_core/agent/tools/tasks.py,sha256=VT-oLFKzswmKu02H1hc_ercJ1blbseCo0Q0qRBh0DjM,11844
70
73
  emdash_core/agent/tools/traversal.py,sha256=qQvHkledo_rT9q9kxk07pijY8XqkR4WWB5pFWVmG01I,20249
71
74
  emdash_core/agent/tools/web.py,sha256=cqm4eiiBzeGCOmQE---uT9zlgsQUX9WY_YYz7wQbK1U,5521
75
+ emdash_core/agent/verifier/__init__.py,sha256=iav1bDKP4P-6xnv0f9V__HAbKys2TFIkVrZ6DvQABBw,280
76
+ emdash_core/agent/verifier/manager.py,sha256=MfVD1aNQGndCXnjzUL6PzH3D1uGCItyVxKEfEidG60g,10089
77
+ emdash_core/agent/verifier/models.py,sha256=JlwMeCILnmDOpmUE3DECbYIDj_58rqo9yw9n_Z_RWq8,2832
78
+ emdash_core/agent/worktree.py,sha256=IHUiNZyrlnumRjZipzM04U61gnR4cf36Bf1jodNuFxg,8946
72
79
  emdash_core/analytics/__init__.py,sha256=5ky2djAly3-3lbQmUuNJlJTmBDaXjN2lOUw-OP2F1Zk,98
73
80
  emdash_core/analytics/engine.py,sha256=f1go7SNnSlM_sFUEvmHrD4PTY9G39REBC7w01xdh3as,47738
74
81
  emdash_core/api/__init__.py,sha256=L11AeV6gaCJjlZ8DU_q-lcuZYH9WV3BV4GYq8JF8BuI,92
75
- emdash_core/api/agent.py,sha256=nLkdqaJvgKyKQTg8EpMvMdbK23rbWgDdZROeyCC_v6k,26207
82
+ emdash_core/api/agent.py,sha256=-79xlAZB53iAwMgUK7ZJnrNGV4wcCcPKLjoFGcL2JA0,41644
76
83
  emdash_core/api/agents.py,sha256=kInkI6iGnQuRxz5wS9w_Owq-4iceUJgugIOrWGDLkGA,3673
77
84
  emdash_core/api/analyze.py,sha256=cR6wWzqSvp_5cNyUg0qACNF7DYdrcNkzhmRqgaqnd78,7593
78
85
  emdash_core/api/auth.py,sha256=vnhH_xcsoTDYrCDBDytlm0LOV9yDoar04NL5FZKI8JU,4832
@@ -85,14 +92,13 @@ emdash_core/api/index.py,sha256=7FtyfTvB6K5Yh1mQZ3qlYWQ492QqCA4aTBbdeZBdfb4,5269
85
92
  emdash_core/api/plan.py,sha256=k5b-nhSpo18Y-HI4RAqmabJWvLXTx9tt0cR3PNj9ewQ,3350
86
93
  emdash_core/api/projectmd.py,sha256=KJmLpiTNwXK75_ADdUIWl2OfPLZU-WQaffsV1I5F8ZY,6105
87
94
  emdash_core/api/query.py,sha256=90HuhYGRiPtolYMBdlYcgW8DV_SvYo0H2xZ_YUWVPRw,10188
88
- emdash_core/api/research.py,sha256=_r0BDkvzLRE2sF4yMQye9IqSeu9yBGlXAYdr-LAlnm8,3511
95
+ emdash_core/api/research.py,sha256=nOSu33me3_HrOYOBz08v4t2AZ-mZIoS26LWDuS-3iUI,3500
89
96
  emdash_core/api/review.py,sha256=zOGrwwThZP_himnFyBKCl4mo4gjniuEaWGNWqcKajb0,4766
90
- emdash_core/api/router.py,sha256=7dVshcIe4m_T-FlRTRvw1RB8U9-bLPef9GdI42ONMvI,1529
97
+ emdash_core/api/router.py,sha256=Q3jY-oV91KrK2pjKAwy5X8xIiV-tzMSb4I8GiJW6UMw,1463
91
98
  emdash_core/api/rules.py,sha256=BbIE_RKX8VGlUqxny0OK-tKoTK58bDBFXBf_1x3yN7g,3242
92
99
  emdash_core/api/search.py,sha256=qPVVTNRExbyG4Ri3X3F5uGpILhlvtH99dHBv7ZVkRIw,3696
93
100
  emdash_core/api/skills.py,sha256=8hF7IkM--aMMaNEaa16DoHl-8fBVx8oYCBnnqgsFkuE,6422
94
101
  emdash_core/api/spec.py,sha256=ub09u1mkqpcF-z0Q1YU9FAkJb0LDyV_eG0_KXYLFmuk,2912
95
- emdash_core/api/swarm.py,sha256=-CNY-NCVnwes0MlHV5yq_ZUie8pJxt0Fdg4g5R94dKo,6561
96
102
  emdash_core/api/tasks.py,sha256=kyrhSc46wfwM3csOT26Gsx9SNjKSTwC9BQ5qMqe1uaY,3160
97
103
  emdash_core/api/team.py,sha256=nHdsTIQ-ZDlpByNIVpSl4Ahf4q51A_HwQTnnmBq6agA,3308
98
104
  emdash_core/auth/__init__.py,sha256=NpcoEyqtqYwUTKKFwNGKgroPOGtXS5rUpH2D9t2_4TY,290
@@ -105,26 +111,23 @@ emdash_core/checkpoint/models.py,sha256=0xfpeNHmLgVVzMzSo-C1dm-1bEWBAZvFED_1Du-R
105
111
  emdash_core/checkpoint/storage.py,sha256=AKUwxeMA05hmxwdRPFivwqv0GWGYgCBlV4m9auzlxpk,5970
106
112
  emdash_core/config.py,sha256=i2M9iRxiZQiKlkc1I0goXwI7ac6ABEdku58u_mGbWbA,2216
107
113
  emdash_core/context/__init__.py,sha256=_6hqH8FtCi4Q3OpuC9zDPDEXuBitLxrY20CdookRTsY,1496
114
+ emdash_core/context/longevity.py,sha256=5i2cYxXXE3tDNer9ZQGvIXTetL1cIYVpJ9qnNkDvT1M,6123
108
115
  emdash_core/context/models.py,sha256=eQdjaea5M6iQ-9ZxJ5IVQgiQEPbZz81Xe2B186GuSYI,1304
109
116
  emdash_core/context/providers/__init__.py,sha256=cWokJwYatvihXoyhqM6BHbG4JQeImgWzyjLdj60BqS4,261
110
117
  emdash_core/context/providers/base.py,sha256=AtWkQcigXeG4rX6WcGkXGrML5QeRUusn2FPvy4nCzLA,2234
111
- emdash_core/context/providers/explored_areas.py,sha256=8sha0T-2IjfX6g25mh58XW1XrBhpH9d30dYMxmOJswk,7009
118
+ emdash_core/context/providers/explored_areas.py,sha256=8lB_mvtEQGuWx7x91bjMHFobgLiQk6vCPk31MeiUiLY,8760
112
119
  emdash_core/context/providers/touched_areas.py,sha256=BLnPkYsQSS9InW9rDUDTlOhoE6QldteWYxpMeU73if8,12858
113
120
  emdash_core/context/registry.py,sha256=p_F0APYsLTDbZbcNkVzw2ET0AMg5UdySUKstxML8jUA,2273
114
- emdash_core/context/reranker.py,sha256=xoajICW7yhxBtq6yJnFDzQXRl0_G8W-ACQyalZ72UbE,5944
121
+ emdash_core/context/reranker.py,sha256=r3CXpjl93JKXFg9RQ8lahCJF03y_nsniVlnr-m_strE,2832
115
122
  emdash_core/context/service.py,sha256=vTSCUoXdNGTTs0ZtMHInX3uG5Wbol-lpCXEn4ICNCDo,9438
116
123
  emdash_core/context/session.py,sha256=XqDELflx7TGosraTU3mBJcZLwD1Ihv2DtuFjeoxjF7A,12424
124
+ emdash_core/context/simple_reranker.py,sha256=0JqmXWvax40fDZwkpfM_gCtO9WaSVKji5Swi5PXUymw,15849
125
+ emdash_core/context/tool_relevance.py,sha256=otjbxR2QWXun8j2Yqy1HeG3ZdXjooSc21E7m4bnvdRo,2403
117
126
  emdash_core/core/__init__.py,sha256=KW97frnmqf5PWHIvYpdZN7aaAPaUXWfsLEEicdZ3g80,1987
118
- emdash_core/core/config.py,sha256=OLI-tbeI8KGzX9GzpL0YcjRJbN1TgCxlaVXSCfkfesU,16044
127
+ emdash_core/core/config.py,sha256=dgaZR8jmNtdzyVZGuLD124ReuVBq3VFYRle1EGKzn2k,16304
119
128
  emdash_core/core/exceptions.py,sha256=LA4bsgEmPJUKQiBmrMpbPT6Iatu4xQLdenGMceMD2Yk,1186
120
129
  emdash_core/core/models.py,sha256=U2achHuaaP9Qr2qZEqBvdzpbxNN2z-SJWjjGpBBiCu4,7810
121
130
  emdash_core/core/review_config.py,sha256=pP8d_0D6mzKg2iYLjrbF9XcI8FIPLwZa0onUDUTvgkM,1455
122
- emdash_core/db/__init__.py,sha256=hGJeI4MqisrE5adATeXZxB9I0GZOArPs7kw2jgOcs8Y,1478
123
- emdash_core/db/auth.py,sha256=pfIbbjbf4txhvdSMFFSdW1pEFxkP-Sc2fMY5X4KJAJ8,3999
124
- emdash_core/db/models.py,sha256=JdVmYC19DZ6yAOMgCRYCvd1QNTT1bS6knIXzNOjdYv8,2057
125
- emdash_core/db/provider.py,sha256=Ip99Lk8cSpRDvxYtnCTaYGAM3BYjHWzZKUD6PcqSs8I,6561
126
- emdash_core/db/providers/__init__.py,sha256=QxhyPLTJMeMcHY2aIgQB1ezEoCiP3D3sp5R3b5jZhO4,113
127
- emdash_core/db/providers/supabase.py,sha256=t2RWZbPiusPZT2JZm4J-0meF7fdGdhMe_jH51tz8xVo,16083
128
131
  emdash_core/embeddings/__init__.py,sha256=NnmjaDSVOxX_H9yGQxTlaoBa97HMY_8Lv1pmIFta-6M,635
129
132
  emdash_core/embeddings/indexer.py,sha256=_LNZyNP6mjSJTeCbsOfSzAHUqEZJQ1TO7EThGBSaUt0,19947
130
133
  emdash_core/embeddings/models.py,sha256=YLiJW7TFJ5roomw2AxAnB8SG4ywY33haJHXZsrU_rWs,6457
@@ -134,11 +137,11 @@ emdash_core/embeddings/providers/fireworks.py,sha256=WEJq1nzQIhECLzxgqnVHtOlkzDd
134
137
  emdash_core/embeddings/providers/openai.py,sha256=sMHk7uG3Xt7hPjtOGGPkSxaFBF15PN2azPp9eOGbJfU,3287
135
138
  emdash_core/embeddings/registry.py,sha256=me9G8xRCpA8XK2U84X-a2auie-VsOmVuQuPwMhQmLwc,5193
136
139
  emdash_core/embeddings/service.py,sha256=nvSpMsqzoEnZA7iwLHwTWMqR3YzeFnbGFrL1RmN9F38,6649
137
- emdash_core/graph/__init__.py,sha256=H8Ib_jH6Tu8EGKYw8pAaiFrmMMOvty7AMiOiypbKA4M,530
140
+ emdash_core/graph/__init__.py,sha256=FGa4qq-YBWngNxywQBlKwH4-G6BNsgw_IymVgcVn4QU,735
138
141
  emdash_core/graph/builder.py,sha256=INh81gubFgmow25eNm2Z139p9VAmZhRx9pyylOhJxgw,4531
139
- emdash_core/graph/connection.py,sha256=ZhMPQpPv_oQOUzdObfwswnuTivsYs90Mawi6DejbYI8,22113
142
+ emdash_core/graph/connection.py,sha256=zXHp9kqyF82nO6ONUaEvrk42QHaie_9x49nk6klxcQ0,22691
140
143
  emdash_core/graph/schema.py,sha256=sKjW1GS3tutpFNeXF7TVMA17iOMEdnyfLGG3hbEigXA,13281
141
- emdash_core/graph/writer.py,sha256=QleDLLB2PTj2cd3vFMrgZXZWk9-_sC1MZMFzFZHjFnE,26191
144
+ emdash_core/graph/writer.py,sha256=Dg4-tt2deLmk8i4nq37SXd1ByL6DNJ2SCXIRbJK0CZA,26358
142
145
  emdash_core/ingestion/__init__.py,sha256=hyGLUPT04C9RXj7zaJF_389-8KA6xQN8zCX8l2v_NZ0,276
143
146
  emdash_core/ingestion/change_detector.py,sha256=LOAODz_apk4ZRfAINz4lf2gCEq1zqQk0bkRnfRrn9oM,5312
144
147
  emdash_core/ingestion/git/__init__.py,sha256=WI754ZInqIQ1JW057Hym1qXUTejhsVdmZ-LTWHXSeLk,113
@@ -157,9 +160,9 @@ emdash_core/ingestion/parsers/python_parser.py,sha256=n4yc9FwE91DCjqI_BOM4EK2NR_
157
160
  emdash_core/ingestion/parsers/registry.py,sha256=fgq-dWfEUpACuWFCPxbcQYH4gQSYqDYJnvJXFNAwb8M,2074
158
161
  emdash_core/ingestion/parsers/ts_ast_parser.js,sha256=bvFEl97bzI-UItTvYkyT5D0rxXWqSGYlCF-Ph5FdMoI,9744
159
162
  emdash_core/ingestion/parsers/typescript_parser.py,sha256=UHEuKUwaEkrscZ7NEisBWcZxJ1Ltn7pUvsdTdccqMGY,10928
160
- emdash_core/ingestion/repository.py,sha256=ZyKw4NYTIgw35LbkYSsqwNmQoGkpVq06q0qm6lFMGGM,10287
163
+ emdash_core/ingestion/repository.py,sha256=oeHbIHhkomONtLKJWgqba7FKd_dYZHv2nT_JnYaP6dk,4828
161
164
  emdash_core/models/__init__.py,sha256=zTsIg4Sy2o2eTWGIpYP9rb_yFdR-DFZ1BSWF9DcrHqU,625
162
- emdash_core/models/agent.py,sha256=W0-5lVM7YxuMznWw90QkMs3vhkH-OZb22sBedbWMMwc,1817
165
+ emdash_core/models/agent.py,sha256=1h5iCS3066de8mO0iJIjHmlq_bHiHXARW6VWIDqvpJs,2326
163
166
  emdash_core/models/index.py,sha256=1dohTHOYvtOLmphGUELwgGH7DkMbhK_ykFn2_YmOtag,2207
164
167
  emdash_core/models/query.py,sha256=3ZRTUzZoBr9IRrniXNLq2egUkg3k5tb9BXyu4xPB2DY,3480
165
168
  emdash_core/planning/__init__.py,sha256=6db3V1maLCicMlRuG3JfGCnH84MxcdRrwBsGddlxVCg,267
@@ -170,17 +173,10 @@ emdash_core/planning/feature_expander.py,sha256=ADNv3qsbRqPtXKRVDSZIf4lcaf_hxdGc
170
173
  emdash_core/planning/llm_explainer.py,sha256=jJlgO5_u5_7TCl_6F-0qoJWtpeY3FTXnR5vvHcqa0Dc,7150
171
174
  emdash_core/planning/similarity.py,sha256=j3jiSWoTqlakHZGa-TxVJYknru7DzRaWlIOow2NG02o,18876
172
175
  emdash_core/planning/team_focus.py,sha256=fv3rCyh_8sHk4w_yjzuw36KlKPAJLPZPgVOo762aneU,32405
173
- emdash_core/server.py,sha256=W6x217nJcYLFaybatMiVxDtqkNH-HejZEBn5PLXGryc,5169
176
+ emdash_core/server.py,sha256=_VGLi0aOWxpsmc77tj9oQ8iQwToKjaWdC1cXPt60q0Y,4989
174
177
  emdash_core/skills/frontend-design/SKILL.md,sha256=fdqIqRS8J_pTH_9h5D-ZUdvYAqor9-xTl2FEYrDAOKA,4338
175
178
  emdash_core/sse/__init__.py,sha256=q6nfbsqvEX7uYTuLwRMb4E73hW-o_Cuv63APod_Kluw,129
176
- emdash_core/sse/stream.py,sha256=CNiXTrTBMNDV6ZMml5Q7XkrXD8-4EqV6kSSIsbcazJ4,5354
177
- emdash_core/swarm/__init__.py,sha256=EyL9U64ByQCCcL19ntwu2OU7labME3i3dSpSF25X6Mo,448
178
- emdash_core/swarm/merge_agent.py,sha256=Fp0rqdHsd0m0swoAApq46QuBNDw5ejDk4dRddc1cD-E,13038
179
- emdash_core/swarm/session_manager.py,sha256=RyLGpfXw-qFXJuQBP3Acw4w7LC_ZIhlPaDDkqjm-ycU,8999
180
- emdash_core/swarm/swarm_runner.py,sha256=em-omxFHp1OBQyuucN6OqnMEy4NVdispo059M_QAbBQ,6747
181
- emdash_core/swarm/task_definition.py,sha256=tplZCA9esV8RQELE45LKsGuasxXxc2Ina9tRFqxtgqU,4364
182
- emdash_core/swarm/worker_spawner.py,sha256=jTZo1CqAumef6wbX8evIacUS5prtr_otWzYa6Uo2N3k,10461
183
- emdash_core/swarm/worktree_manager.py,sha256=C5pk5g8dfi1luw6aecR8lu83CNVT3qdL_wEUMOGagns,8415
179
+ emdash_core/sse/stream.py,sha256=Vt4NPH__63w0eCuV0gg8dcVuUxw2vjw0bx3_ONmR9wI,5878
184
180
  emdash_core/templates/__init__.py,sha256=rVF1ZlAiFfFTzJKfANFHbifC7c2HoFTvDVxAuOoHur0,256
185
181
  emdash_core/templates/defaults/agent-builder.md.template,sha256=LLbd0IFEBT5Gw1LToDXoyT-EC4RHcGrENdterrPN3xk,2187
186
182
  emdash_core/templates/defaults/focus.md.template,sha256=wj9AIwbUaZ7ANZO1zx_ZUlZ7kg_NxqGwmmJSGLefWwg,3366
@@ -194,11 +190,11 @@ emdash_core/templates/defaults/reviewer.md.template,sha256=_RbULDB78fEuPA3DBbQfA
194
190
  emdash_core/templates/defaults/spec.md.template,sha256=0ftXTYyhftoTZsGkUXP5HgUOXeVmsVcG_VnjBAVjExU,1139
195
191
  emdash_core/templates/defaults/tasks.md.template,sha256=LMZ6PRek0_0s3o-i8zRP-hwipgp_8F2qNgwnLAI3v5w,2093
196
192
  emdash_core/templates/loader.py,sha256=G_6ITQqWSMYcgA_fgjKQsd_3BBNt-LuhQE8VyC2ouj0,9796
197
- emdash_core/utils/__init__.py,sha256=tQj81F7ZW61jsNg_R2bA9tDLdk0dc5kQswYWwZSqigU,956
198
- emdash_core/utils/git.py,sha256=j5kppemwAOWe4Bc5a9qUmYYfKqxyi9WLk5U9HgwkgO4,2336
199
- emdash_core/utils/image.py,sha256=K8uKDuhZqsJXwNDQ57Q3w2j0PQPyid_aEbiq66zy3p0,14607
193
+ emdash_core/utils/__init__.py,sha256=8SmXbLfHafDW5LxbDp5j0VTPa-dWo9_FH1XjdY4L9c8,898
194
+ emdash_core/utils/git.py,sha256=Qit9h35GZ5ZkP7E5_2JrJ4kNYrDcTgJryq-GMdtFDN4,5161
195
+ emdash_core/utils/image.py,sha256=7Qz2Cbe-3sPRaLsBTKxuf5MS8jzxjFn59TyyhKvGu2M,14566
200
196
  emdash_core/utils/logger.py,sha256=iLaMA5vkUvxCfWsvZ7WZSDQWv4Gh5gJHeYbAB6urDio,1473
201
- emdash_core-0.1.33.dist-info/METADATA,sha256=DzKymxf8EVFNST9WBtIHeLDIxbRaWWqXtRNgf2181kU,1386
202
- emdash_core-0.1.33.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
203
- emdash_core-0.1.33.dist-info/entry_points.txt,sha256=WgC9h0Bcsh0VaLfDv4hAKaY5krcT2Ati4UyoIJNavdk,105
204
- emdash_core-0.1.33.dist-info/RECORD,,
197
+ emdash_core-0.1.60.dist-info/METADATA,sha256=_GiCIcH6coX4j26WdHokzU2esYeI2izbRQ9MP_UWBLc,1504
198
+ emdash_core-0.1.60.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
199
+ emdash_core-0.1.60.dist-info/entry_points.txt,sha256=WgC9h0Bcsh0VaLfDv4hAKaY5krcT2Ati4UyoIJNavdk,105
200
+ emdash_core-0.1.60.dist-info/RECORD,,
emdash_core/api/swarm.py DELETED
@@ -1,223 +0,0 @@
1
- """Swarm (multi-agent) endpoints with SSE streaming."""
2
-
3
- import asyncio
4
- from concurrent.futures import ThreadPoolExecutor
5
- from typing import Optional
6
-
7
- from fastapi import APIRouter, HTTPException
8
- from fastapi.responses import StreamingResponse
9
- from pydantic import BaseModel, Field
10
-
11
- from ..sse.stream import SSEHandler, EventType
12
-
13
- router = APIRouter(prefix="/swarm", tags=["swarm"])
14
-
15
- _executor = ThreadPoolExecutor(max_workers=1)
16
-
17
-
18
- class SwarmRequest(BaseModel):
19
- """Request to run swarm."""
20
- tasks: list[str] = Field(..., description="List of tasks to run in parallel")
21
- model: Optional[str] = Field(default=None, description="LLM model")
22
- workers: int = Field(default=3, description="Number of parallel workers")
23
- timeout: int = Field(default=300, description="Timeout per task in seconds")
24
- base_branch: Optional[str] = Field(default=None, description="Base branch")
25
- auto_merge: bool = Field(default=True, description="Auto-merge completed branches")
26
- llm_merge: bool = Field(default=False, description="Use LLM for merge conflicts")
27
-
28
-
29
- class SwarmStatus(BaseModel):
30
- """Status of swarm execution."""
31
- is_running: bool
32
- tasks_total: int
33
- tasks_completed: int
34
- tasks_failed: int
35
- current_tasks: list[str]
36
-
37
-
38
- class SwarmSession(BaseModel):
39
- """An active swarm session."""
40
- id: str
41
- task: str
42
- status: str # running, completed, failed
43
- branch: Optional[str] = None
44
-
45
-
46
- def _run_swarm_sync(
47
- tasks: list[str],
48
- model: Optional[str],
49
- workers: int,
50
- sse_handler: SSEHandler,
51
- ):
52
- """Run swarm synchronously."""
53
- import sys
54
- from pathlib import Path
55
-
56
- repo_root = Path(__file__).parent.parent.parent.parent.parent
57
- if str(repo_root) not in sys.path:
58
- sys.path.insert(0, str(repo_root))
59
-
60
- try:
61
- from ..swarm.swarm_runner import SwarmRunner
62
- from ..agent.events import AgentEventEmitter
63
-
64
- class SSEBridge:
65
- def __init__(self, handler):
66
- self._handler = handler
67
-
68
- def handle(self, event):
69
- self._handler.handle(event)
70
-
71
- emitter = AgentEventEmitter(agent_name="Swarm")
72
- emitter.add_handler(SSEBridge(sse_handler))
73
-
74
- runner = SwarmRunner(
75
- repo_root=repo_root,
76
- model=model or "gpt-4o-mini",
77
- max_workers=workers,
78
- )
79
-
80
- sse_handler.emit(EventType.PROGRESS, {
81
- "step": f"Starting {len(tasks)} tasks with {workers} workers",
82
- "percent": 0,
83
- })
84
-
85
- state = runner.run(tasks)
86
-
87
- # Count results from swarm state
88
- from ..swarm.task_definition import TaskStatus
89
- completed = sum(1 for t in state.tasks if t.status == TaskStatus.COMPLETED)
90
- failed = sum(1 for t in state.tasks if t.status == TaskStatus.FAILED)
91
-
92
- sse_handler.emit(EventType.RESPONSE, {
93
- "completed": completed,
94
- "failed": failed,
95
- "results": [{"slug": t.slug, "status": t.status.value} for t in state.tasks],
96
- })
97
-
98
- except Exception as e:
99
- sse_handler.emit(EventType.ERROR, {"message": str(e)})
100
- finally:
101
- sse_handler.close()
102
-
103
-
104
- @router.post("/run")
105
- async def run_swarm(request: SwarmRequest):
106
- """Run multiple agents in parallel on separate tasks.
107
-
108
- Each task runs in its own git worktree branch.
109
- """
110
- if not request.tasks:
111
- raise HTTPException(status_code=400, detail="No tasks provided")
112
-
113
- sse_handler = SSEHandler(agent_name="Swarm")
114
-
115
- sse_handler.emit(EventType.SESSION_START, {
116
- "agent_name": "Swarm",
117
- "task_count": len(request.tasks),
118
- "workers": request.workers,
119
- })
120
-
121
- async def run():
122
- loop = asyncio.get_event_loop()
123
- await loop.run_in_executor(
124
- _executor,
125
- _run_swarm_sync,
126
- request.tasks,
127
- request.model,
128
- request.workers,
129
- sse_handler,
130
- )
131
-
132
- asyncio.create_task(run())
133
-
134
- return StreamingResponse(
135
- sse_handler,
136
- media_type="text/event-stream",
137
- headers={"Cache-Control": "no-cache", "Connection": "keep-alive"},
138
- )
139
-
140
-
141
- @router.get("/status", response_model=SwarmStatus)
142
- async def get_swarm_status():
143
- """Get status of current swarm execution."""
144
- # TODO: Implement actual status tracking
145
- return SwarmStatus(
146
- is_running=False,
147
- tasks_total=0,
148
- tasks_completed=0,
149
- tasks_failed=0,
150
- current_tasks=[],
151
- )
152
-
153
-
154
- @router.get("/sessions")
155
- async def get_swarm_sessions():
156
- """List active swarm sessions."""
157
- # TODO: Implement session tracking
158
- return {"sessions": []}
159
-
160
-
161
- @router.post("/cleanup")
162
- async def cleanup_swarm(force: bool = False):
163
- """Clean up all swarm worktrees and branches."""
164
- try:
165
- from pathlib import Path
166
- from ..swarm.swarm_runner import SwarmRunner
167
-
168
- repo_root = Path(__file__).parent.parent.parent.parent.parent
169
- runner = SwarmRunner.load(repo_root)
170
-
171
- if runner:
172
- cleaned = runner.cleanup()
173
- else:
174
- # No active swarm, just cleanup orphaned worktrees
175
- from ..swarm.worktree_manager import WorktreeManager
176
- manager = WorktreeManager(repo_root)
177
- cleaned = manager.cleanup_all()
178
-
179
- return {
180
- "success": True,
181
- "cleaned_worktrees": cleaned,
182
- }
183
- except Exception as e:
184
- raise HTTPException(status_code=500, detail=str(e))
185
-
186
-
187
- @router.post("/merge")
188
- async def merge_swarm_branches(
189
- llm_merge: bool = False,
190
- target: Optional[str] = None,
191
- ):
192
- """Merge all completed task branches."""
193
- try:
194
- from pathlib import Path
195
- from ..swarm.swarm_runner import SwarmRunner
196
-
197
- repo_root = Path(__file__).parent.parent.parent.parent.parent
198
- runner = SwarmRunner.load(repo_root)
199
-
200
- if not runner:
201
- return {
202
- "success": False,
203
- "error": "No active swarm found",
204
- "merged_branches": [],
205
- "conflicts": [],
206
- }
207
-
208
- results = runner.merge_completed(
209
- use_llm=llm_merge,
210
- target_branch=target,
211
- )
212
-
213
- merged = [r.task_id for r in results if r.success]
214
- failed = [{"task_id": r.task_id, "conflicts": r.conflicts, "error": r.error_message}
215
- for r in results if not r.success]
216
-
217
- return {
218
- "success": len(failed) == 0,
219
- "merged_tasks": merged,
220
- "failed": failed,
221
- }
222
- except Exception as e:
223
- raise HTTPException(status_code=500, detail=str(e))
@@ -1,67 +0,0 @@
1
- """Database layer for EmDash.
2
-
3
- Provides an abstraction over database backends with Supabase as the default implementation.
4
- """
5
-
6
- import os
7
- from typing import Optional
8
-
9
- from .models import (
10
- Feature,
11
- FeatureAssignee,
12
- FeaturePR,
13
- FeatureStatus,
14
- PRStatus,
15
- Project,
16
- TeamMember,
17
- )
18
- from .provider import DatabaseProvider
19
- from .providers.supabase import SupabaseProvider
20
- from .auth import AuthProvider, User, get_auth
21
-
22
- __all__ = [
23
- # Models
24
- "Feature",
25
- "FeatureAssignee",
26
- "FeaturePR",
27
- "FeatureStatus",
28
- "PRStatus",
29
- "Project",
30
- "TeamMember",
31
- "User",
32
- # Provider
33
- "DatabaseProvider",
34
- "SupabaseProvider",
35
- # Auth
36
- "AuthProvider",
37
- "get_auth",
38
- # Factory
39
- "get_provider",
40
- ]
41
-
42
- _provider_instance: Optional[DatabaseProvider] = None
43
-
44
-
45
- def get_provider() -> DatabaseProvider:
46
- """Get the configured database provider instance.
47
-
48
- Returns a singleton instance of the database provider.
49
- Currently only supports Supabase.
50
-
51
- Returns:
52
- DatabaseProvider instance
53
-
54
- Raises:
55
- ValueError: If required environment variables are not set
56
- """
57
- global _provider_instance
58
-
59
- if _provider_instance is None:
60
- provider_type = os.getenv("EMDASH_DB_PROVIDER", "supabase")
61
-
62
- if provider_type == "supabase":
63
- _provider_instance = SupabaseProvider()
64
- else:
65
- raise ValueError(f"Unknown database provider: {provider_type}")
66
-
67
- return _provider_instance
emdash_core/db/auth.py DELETED
@@ -1,134 +0,0 @@
1
- """Supabase authentication with GitHub OAuth."""
2
-
3
- import os
4
- from dataclasses import dataclass
5
- from typing import Optional
6
-
7
- from supabase import create_client, Client
8
-
9
-
10
- @dataclass
11
- class User:
12
- """Authenticated user from Supabase Auth."""
13
-
14
- id: str
15
- email: Optional[str]
16
- github_handle: Optional[str]
17
- avatar_url: Optional[str]
18
- access_token: Optional[str] = None
19
-
20
-
21
- class AuthProvider:
22
- """Handle Supabase authentication with GitHub OAuth."""
23
-
24
- def __init__(self, url: Optional[str] = None, key: Optional[str] = None):
25
- self.url = url or os.getenv("SUPABASE_URL")
26
- self.key = key or os.getenv("SUPABASE_KEY")
27
-
28
- if not self.url or not self.key:
29
- raise ValueError("SUPABASE_URL and SUPABASE_KEY must be set")
30
-
31
- self.client: Client = create_client(self.url, self.key)
32
-
33
- def get_github_login_url(self, redirect_to: Optional[str] = None) -> str:
34
- """Get the GitHub OAuth login URL.
35
-
36
- Args:
37
- redirect_to: URL to redirect after login (for web apps)
38
-
39
- Returns:
40
- GitHub OAuth URL to redirect user to
41
- """
42
- options = {}
43
- if redirect_to:
44
- options["redirect_to"] = redirect_to
45
-
46
- response = self.client.auth.sign_in_with_oauth(
47
- {"provider": "github", "options": options}
48
- )
49
- return response.url
50
-
51
- def sign_in_with_github_token(self, access_token: str) -> Optional[User]:
52
- """Sign in with an existing GitHub access token.
53
-
54
- Args:
55
- access_token: GitHub OAuth access token
56
-
57
- Returns:
58
- User if successful, None otherwise
59
- """
60
- try:
61
- response = self.client.auth.sign_in_with_id_token(
62
- {"provider": "github", "token": access_token}
63
- )
64
- return self._session_to_user(response)
65
- except Exception:
66
- return None
67
-
68
- def get_session(self) -> Optional[User]:
69
- """Get the current authenticated user from session.
70
-
71
- Returns:
72
- User if authenticated, None otherwise
73
- """
74
- try:
75
- response = self.client.auth.get_session()
76
- if response and response.user:
77
- return self._response_to_user(response)
78
- return None
79
- except Exception:
80
- return None
81
-
82
- def sign_out(self) -> bool:
83
- """Sign out the current user.
84
-
85
- Returns:
86
- True if successful
87
- """
88
- try:
89
- self.client.auth.sign_out()
90
- return True
91
- except Exception:
92
- return False
93
-
94
- def _session_to_user(self, session) -> Optional[User]:
95
- """Convert Supabase session to User model."""
96
- if not session or not session.user:
97
- return None
98
-
99
- user_meta = session.user.user_metadata or {}
100
-
101
- return User(
102
- id=session.user.id,
103
- email=session.user.email,
104
- github_handle=user_meta.get("user_name") or user_meta.get("preferred_username"),
105
- avatar_url=user_meta.get("avatar_url"),
106
- access_token=session.access_token if hasattr(session, "access_token") else None,
107
- )
108
-
109
- def _response_to_user(self, response) -> Optional[User]:
110
- """Convert Supabase auth response to User model."""
111
- if not response or not response.user:
112
- return None
113
-
114
- user_meta = response.user.user_metadata or {}
115
-
116
- return User(
117
- id=response.user.id,
118
- email=response.user.email,
119
- github_handle=user_meta.get("user_name") or user_meta.get("preferred_username"),
120
- avatar_url=user_meta.get("avatar_url"),
121
- access_token=response.session.access_token if response.session else None,
122
- )
123
-
124
-
125
- # Singleton instance
126
- _auth_instance: Optional[AuthProvider] = None
127
-
128
-
129
- def get_auth() -> AuthProvider:
130
- """Get the auth provider instance."""
131
- global _auth_instance
132
- if _auth_instance is None:
133
- _auth_instance = AuthProvider()
134
- return _auth_instance