aline-ai 0.6.2__py3-none-any.whl → 0.6.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.
- {aline_ai-0.6.2.dist-info → aline_ai-0.6.4.dist-info}/METADATA +1 -1
- {aline_ai-0.6.2.dist-info → aline_ai-0.6.4.dist-info}/RECORD +38 -37
- realign/__init__.py +1 -1
- realign/adapters/__init__.py +0 -3
- realign/adapters/codex.py +14 -9
- realign/cli.py +42 -236
- realign/codex_detector.py +72 -32
- realign/codex_home.py +85 -0
- realign/codex_terminal_linker.py +172 -0
- realign/commands/__init__.py +2 -2
- realign/commands/add.py +89 -9
- realign/commands/doctor.py +495 -0
- realign/commands/export_shares.py +154 -226
- realign/commands/init.py +66 -4
- realign/commands/watcher.py +30 -80
- realign/config.py +9 -46
- realign/dashboard/app.py +7 -11
- realign/dashboard/screens/event_detail.py +0 -3
- realign/dashboard/screens/session_detail.py +0 -1
- realign/dashboard/tmux_manager.py +129 -4
- realign/dashboard/widgets/config_panel.py +175 -241
- realign/dashboard/widgets/events_table.py +71 -128
- realign/dashboard/widgets/sessions_table.py +77 -136
- realign/dashboard/widgets/terminal_panel.py +349 -27
- realign/dashboard/widgets/watcher_panel.py +0 -2
- realign/db/sqlite_db.py +77 -2
- realign/events/event_summarizer.py +76 -35
- realign/events/session_summarizer.py +73 -32
- realign/hooks.py +334 -647
- realign/llm_client.py +201 -520
- realign/triggers/__init__.py +0 -2
- realign/triggers/next_turn_trigger.py +4 -5
- realign/triggers/registry.py +1 -4
- realign/watcher_core.py +53 -35
- realign/adapters/antigravity.py +0 -159
- realign/triggers/antigravity_trigger.py +0 -140
- {aline_ai-0.6.2.dist-info → aline_ai-0.6.4.dist-info}/WHEEL +0 -0
- {aline_ai-0.6.2.dist-info → aline_ai-0.6.4.dist-info}/entry_points.txt +0 -0
- {aline_ai-0.6.2.dist-info → aline_ai-0.6.4.dist-info}/licenses/LICENSE +0 -0
- {aline_ai-0.6.2.dist-info → aline_ai-0.6.4.dist-info}/top_level.txt +0 -0
|
@@ -1,27 +1,28 @@
|
|
|
1
|
-
aline_ai-0.6.
|
|
2
|
-
realign/__init__.py,sha256=
|
|
1
|
+
aline_ai-0.6.4.dist-info/licenses/LICENSE,sha256=H8wTqV5IF1oHw_HbBtS1PSDU8G_q81yblEIL_JfV8Vo,1077
|
|
2
|
+
realign/__init__.py,sha256=rnvZkVu_IlHB3KpP9LQEl-T4lLSwL0cvZOT9ycHF13o,1623
|
|
3
3
|
realign/auth.py,sha256=d_1yvCwluN5iIrdgjtuSKpOYAksDzrzNgntKacLVJrw,16583
|
|
4
4
|
realign/claude_detector.py,sha256=ZLSJacMo6zzQclXByABKA70UNpstxqIv3fPGqdpA934,2792
|
|
5
|
-
realign/cli.py,sha256=
|
|
6
|
-
realign/codex_detector.py,sha256=
|
|
7
|
-
realign/
|
|
5
|
+
realign/cli.py,sha256=HZ_1Rm50z1oszCwvPAZcAdPt0Gl-dj0S0NMLy2sWu_4,35665
|
|
6
|
+
realign/codex_detector.py,sha256=xTpYgMfUwL6UL76xeHl8xF2ZBPHdjwmgXmbmZkvHA0A,5523
|
|
7
|
+
realign/codex_home.py,sha256=gAAosBDru4jfz0QCn12A2bZEC_lZxytpOAzk7GOXTpI,2512
|
|
8
|
+
realign/codex_terminal_linker.py,sha256=9cDUHhN7MhCIUOfb-3kApPY-l6s91jq2qq_WI0ccexY,5926
|
|
9
|
+
realign/config.py,sha256=Znfs43AjiK90LGWnArDPWyrE859sdZQAPIb0KAcU3Ig,9252
|
|
8
10
|
realign/context.py,sha256=8hzgNOg-7_eMW22wt7OM5H9IsmMveKXCv0epG7E0G7w,13917
|
|
9
11
|
realign/file_lock.py,sha256=kLNm1Rra4TCrTMyPM5fwjVascq-CUz2Bzh9HHKtCKOE,3444
|
|
10
|
-
realign/hooks.py,sha256=
|
|
11
|
-
realign/llm_client.py,sha256=
|
|
12
|
+
realign/hooks.py,sha256=wSSIjS5x9w7fm9LUcL63Lf7bglEfb75dHFja_znKDDQ,65134
|
|
13
|
+
realign/llm_client.py,sha256=QqMPDFE-aXm7oz0QAkB90CN0Qn0uz7JOxpWbUUlHNgU,11141
|
|
12
14
|
realign/logging_config.py,sha256=LCAigKFhTj86PSJm4-kUl3Ag9h_GENh3x2iPnMv7qUI,4871
|
|
13
15
|
realign/mcp_server.py,sha256=LWiQ2qukYoNLsoV2ID2f0vF9jkJlBvB587HpM5jymgE,10193
|
|
14
16
|
realign/mcp_watcher.py,sha256=aK4jWStv7CoCroS4tXFHgZ_y_-q4QDjrpWgm4DxcEj4,1260
|
|
15
17
|
realign/redactor.py,sha256=Zsoi5HfYak2yPmck20JArhm-1cPSB78IdkBJiNVXfrc,17096
|
|
16
|
-
realign/watcher_core.py,sha256=
|
|
18
|
+
realign/watcher_core.py,sha256=0XCoA5giuie-Ytc_tlPTVbZH8EFRPmODu7DUYRhRBGo,108598
|
|
17
19
|
realign/watcher_daemon.py,sha256=OHUQ9P1LlagKJHfrf6uRnzO-zDtBRXIxt8ydMFHf5S8,3475
|
|
18
20
|
realign/worker_core.py,sha256=TXioUVJlOO-8EgmKssCTLIyuh0aaupRLb1sh9s3kSuc,10194
|
|
19
21
|
realign/worker_daemon.py,sha256=X7Xyjw_u6m6KG4E84nx0HpDFw4cWMv8ja1G8btc9PiM,3957
|
|
20
|
-
realign/adapters/__init__.py,sha256=
|
|
21
|
-
realign/adapters/antigravity.py,sha256=geaYxAEswpgsVtERqsQ1OwvPFsy5tRkyjx2yQ-Uq9nM,5461
|
|
22
|
+
realign/adapters/__init__.py,sha256=alkJr7DRn_CrJecSJRjRJOHHnkz9EnZ5TnsU8n1Bb0k,719
|
|
22
23
|
realign/adapters/base.py,sha256=2IdAZKGjg5gPB3YLf_8r3V4XAdbK7fHpj06GjjsYEFY,7409
|
|
23
24
|
realign/adapters/claude.py,sha256=ksTRwC5Z8AzUcB21LFjx6DETP08cv__fjgBzm-TeZdI,5444
|
|
24
|
-
realign/adapters/codex.py,sha256=
|
|
25
|
+
realign/adapters/codex.py,sha256=VJgmrRzOO5a6GNG6xL7gJwzcvA2CBmHdilYkj0qffBw,2233
|
|
25
26
|
realign/adapters/gemini.py,sha256=NvtXQPWUtEY-DaAAMvLGvQW4FalTG-g0pD514HYnzF0,2540
|
|
26
27
|
realign/adapters/registry.py,sha256=yM6nf9nGTJ1vaK2Uixp-VacseK7PmxZkCdKedmWI8MA,3255
|
|
27
28
|
realign/claude_hooks/__init__.py,sha256=MT9c8TWjLO23xDCM-uBBMy_mOThNd7O-AgN_Khn30qs,594
|
|
@@ -32,44 +33,45 @@ realign/claude_hooks/stop_hook_installer.py,sha256=uyqKOqpix7CQP64ERBvvh7viSPp_w
|
|
|
32
33
|
realign/claude_hooks/terminal_state.py,sha256=i8B6b_2_9ttPEemp7SrGdFRJSa-vm5lc7YSTRTvAWNg,5397
|
|
33
34
|
realign/claude_hooks/user_prompt_submit_hook.py,sha256=kMrmhAVtfV41oTX7JZcq2HPXjgQQ5gX26iOJoHJkfqA,10474
|
|
34
35
|
realign/claude_hooks/user_prompt_submit_hook_installer.py,sha256=2xLF8yZcE7Iwib9gU-xCkA1NWxNH9Nc5CFKPYK7rtXw,5371
|
|
35
|
-
realign/commands/__init__.py,sha256=
|
|
36
|
-
realign/commands/add.py,sha256=
|
|
36
|
+
realign/commands/__init__.py,sha256=WVaVT1orM2Z0PYaG3X6tkKb_t2v3n_3siCadh1qd_QA,107
|
|
37
|
+
realign/commands/add.py,sha256=_Xzt9P15mwndA3JvBBVrki8tn9Cc0UP6SiLwM4RS8Nc,27232
|
|
37
38
|
realign/commands/auth.py,sha256=QrPukpP-ogYEDSwztV0NOYI-HDgn5fPxlCQ1-e2n7gU,11082
|
|
38
39
|
realign/commands/config.py,sha256=nYnu_h2pk7GODcrzrV04K51D-s7v06FlRXHJ0HJ-gvU,6732
|
|
39
40
|
realign/commands/context.py,sha256=pM2KfZHVkB-ou4nBhFvKSwnYliLBzwN3zerLyBAbhfE,7095
|
|
40
|
-
realign/commands/
|
|
41
|
+
realign/commands/doctor.py,sha256=CpS8feMMuV2VvqzSCLal7yWDVSQHan5VbC2LbkLHB5Y,18173
|
|
42
|
+
realign/commands/export_shares.py,sha256=WNOR7FBE2om9qPO_28edZKhs94lyUAcbRgP_kNaDi5M,132574
|
|
41
43
|
realign/commands/import_shares.py,sha256=HiswLlYHqR0dR3wgB7Rs54_WownqahIs5IdyJOHuot8,25572
|
|
42
|
-
realign/commands/init.py,sha256=
|
|
44
|
+
realign/commands/init.py,sha256=6rBr1LVIrQLbUH_UvoDhkF1qXmMh2xkjNWCYAUz5Tho,35274
|
|
43
45
|
realign/commands/restore.py,sha256=s2BxQZHxQw9r12NzRVsK20KlGafy5AIoSjWMo5PcnHY,11173
|
|
44
46
|
realign/commands/search.py,sha256=QJrC0hln9sCDFxXbpo0nPGMHXrud18qA5QfRyD0z6fQ,25926
|
|
45
47
|
realign/commands/upgrade.py,sha256=L3PLOUIN5qAQTbkfoVtSsIbbzEezA_xjjk9F1GMVfjw,12781
|
|
46
|
-
realign/commands/watcher.py,sha256=
|
|
48
|
+
realign/commands/watcher.py,sha256=4WTThIgr-Z5guKh_JqGDcPmerr97XiHrVaaijmckHsA,134350
|
|
47
49
|
realign/commands/worker.py,sha256=jTu7Pj60nTnn7SsH3oNCNnO6zl4TIFCJVNSC1OoQ_0o,23363
|
|
48
50
|
realign/dashboard/__init__.py,sha256=QZkHTsGityH8UkF8rmvA3xW7dMXNe0swEWr443qfgCM,128
|
|
49
|
-
realign/dashboard/app.py,sha256=
|
|
51
|
+
realign/dashboard/app.py,sha256=xCYICKoEsvPli8SCUgfPkInCQp6VDrymnVoRhOizYwY,15872
|
|
50
52
|
realign/dashboard/layout.py,sha256=sZxmFj6QTbkois9MHTvBEMMcnaRVehCDqugdbiFx10k,9072
|
|
51
53
|
realign/dashboard/terminal_backend.py,sha256=MlDfwtqhftyQK6jDNizQGFjAWIo5Bx2TDpSnP3MCZVM,3375
|
|
52
|
-
realign/dashboard/tmux_manager.py,sha256=
|
|
54
|
+
realign/dashboard/tmux_manager.py,sha256=1DqMLdgE1m_MHABAilPpfizawk8D8c9QMVmnJ7Au4sg,30963
|
|
53
55
|
realign/dashboard/backends/__init__.py,sha256=POROX7YKtukYZcLB1pi_kO0sSEpuO3y-hwmF3WIN1Kk,163
|
|
54
56
|
realign/dashboard/backends/iterm2.py,sha256=XYYJT5lrrp4pW_MyEqPZYkRI0qyKUwJlezwMidgnsHc,21390
|
|
55
57
|
realign/dashboard/backends/kitty.py,sha256=5jdkR1f2PwB8a4SnS3EG6uOQ2XU-PB7-cpKBfIJq3hU,12066
|
|
56
58
|
realign/dashboard/screens/__init__.py,sha256=US6sAmQs5VVkH2tFkH_z0WDT4H8cVhLL-JckfSR1yQY,446
|
|
57
59
|
realign/dashboard/screens/create_agent.py,sha256=06uiQYvz-Xvn4Xm689o3tdhzb2HQ0gdzAA1WHVEwziM,11706
|
|
58
60
|
realign/dashboard/screens/create_event.py,sha256=oiQY1zKpUYnQU-5fQLeuZH9BV5NClE5B5XZIVBYG5A8,5506
|
|
59
|
-
realign/dashboard/screens/event_detail.py,sha256=
|
|
61
|
+
realign/dashboard/screens/event_detail.py,sha256=Fcm1CPAJkrNzolnFyIAzLeE_-NAoqdjQ0dLW0YyyER8,20842
|
|
60
62
|
realign/dashboard/screens/help_screen.py,sha256=Icrcvbgyz49R2tBiu8vBZ4CLm6iYclv_-FTa2pCFRRQ,3398
|
|
61
|
-
realign/dashboard/screens/session_detail.py,sha256=
|
|
63
|
+
realign/dashboard/screens/session_detail.py,sha256=TBkHqSHyMxsLB2QdZq9m1EoiH8oRVDbPrjt-a8I9sHs,9561
|
|
62
64
|
realign/dashboard/screens/share_import.py,sha256=hl2x0yGVycsoUI76AmdZTAV-br3Q6191g5xHHrZ8hOA,6318
|
|
63
65
|
realign/dashboard/styles/dashboard.tcss,sha256=ewonevBGLN-dfSsgxUk4VBCPchtxY4rx_vj1u6Ox2Fw,3454
|
|
64
66
|
realign/dashboard/widgets/__init__.py,sha256=3Pf2_K9obrertgv_psfxradgkI9RXlmjoXYQH7oBKm0,583
|
|
65
|
-
realign/dashboard/widgets/config_panel.py,sha256=
|
|
66
|
-
realign/dashboard/widgets/events_table.py,sha256=
|
|
67
|
+
realign/dashboard/widgets/config_panel.py,sha256=v9wQIsH9CK7Q6HFz-C14IQ1SYBcJL3RjhV_ngTk0KH0,15723
|
|
68
|
+
realign/dashboard/widgets/events_table.py,sha256=MKB1G1_xdQCujEhmMz_GKI4hs-PeEiqGEAH7Y3ZGanE,30852
|
|
67
69
|
realign/dashboard/widgets/header.py,sha256=0HHCFXX7F3C6HII-WDwOJwWkJrajmKPWmdoMWyOkn9E,1587
|
|
68
70
|
realign/dashboard/widgets/openable_table.py,sha256=GeJPDEYp0kRHShqvmPMzAePpYXRZHUNqcWNnxqsqxjA,1963
|
|
69
71
|
realign/dashboard/widgets/search_panel.py,sha256=ZNJDfwDSxUFnCeltYQYsQsPJ6t4HDeNWpENoTOoBdVM,8951
|
|
70
|
-
realign/dashboard/widgets/sessions_table.py,sha256=
|
|
71
|
-
realign/dashboard/widgets/terminal_panel.py,sha256=
|
|
72
|
-
realign/dashboard/widgets/watcher_panel.py,sha256=
|
|
72
|
+
realign/dashboard/widgets/sessions_table.py,sha256=oMkYhQ55pUGOGYxEXM5P37mpGYA350BK8Rb8fVq9AS4,34008
|
|
73
|
+
realign/dashboard/widgets/terminal_panel.py,sha256=VM0eyE8VDldhrc130JjSvCkkcpr5Io0Gx16i5cbdJgM,57854
|
|
74
|
+
realign/dashboard/widgets/watcher_panel.py,sha256=emVY1-aot9Dnf5UI9yyNeEmp4d2Gb-lrC28DjkeLjKA,19575
|
|
73
75
|
realign/dashboard/widgets/worker_panel.py,sha256=F_jKWABuCNmjQgeeuCr4KnFRKdY4CLTNcEXMYwsNaSk,18691
|
|
74
76
|
realign/db/__init__.py,sha256=65LsNdsq_rkwNC1eg1OAr3HC0ORXtelOh0I8MhNGr-g,3288
|
|
75
77
|
realign/db/base.py,sha256=5baEwoGR5X2SyQXkXuyeUP2zelcuQardVouD2S-qils,13703
|
|
@@ -77,27 +79,26 @@ realign/db/locks.py,sha256=yzCiPJZ4eOQX-Q4mXB6s76U2U7lXAzIBBy1t59w-AVU,1698
|
|
|
77
79
|
realign/db/migrate_agents.py,sha256=cDeVUzKW950dJ0lV74QObHuONqKwErSrXI5akU2vBmQ,9633
|
|
78
80
|
realign/db/migration.py,sha256=af1QFEfIh_qX0pFyXzm5gWFVbQn0sKOUNLSJHlr__FU,13405
|
|
79
81
|
realign/db/schema.py,sha256=YHj5PGZWbCl0VG0epnMF_Ofg3jRiLHq6SLHCi1q34eQ,30181
|
|
80
|
-
realign/db/sqlite_db.py,sha256=
|
|
82
|
+
realign/db/sqlite_db.py,sha256=nihEZ71wg1BXiVG1QU488ed9Q-ZasoVKYVS4j20hhtY,107223
|
|
81
83
|
realign/events/__init__.py,sha256=IM-NxF4Zk2hYFD07k4WrfNRuuiC9ihGjf4GBpJhjd2E,35
|
|
82
84
|
realign/events/debouncer.py,sha256=U3Q7dYpnMsAgWsW_E_IbSC4lrdEoi6H_SFLGLOAazs4,3062
|
|
83
|
-
realign/events/event_summarizer.py,sha256=
|
|
84
|
-
realign/events/session_summarizer.py,sha256=
|
|
85
|
+
realign/events/event_summarizer.py,sha256=jJtWM8UWtsG4KGdzYicMqcTxrncWzGNEQs5vdBJPyew,10185
|
|
86
|
+
realign/events/session_summarizer.py,sha256=EzFFjgcUEAqm1IJuxOAPx74GTUIStyXTvQ9maZ-V10U,12888
|
|
85
87
|
realign/models/event.py,sha256=ypz74D4l6U2U0RhgL8fzEhiq7iQjhHybmAdLUNDY7P4,5521
|
|
86
88
|
realign/prompts/__init__.py,sha256=PpYR7f-T96fd-QyNYJDRS1U6h9O0rIt_SMsREy9i3aA,443
|
|
87
89
|
realign/prompts/presets.py,sha256=h9oEy0XP4JQ4DCnp8HN_FfF0LmI-yOV6xWJLknIghJ8,7256
|
|
88
90
|
realign/tracker/__init__.py,sha256=Apd-xxomkiOjSIthseqZpVQ8l0yT4nkaErsUyA1ptIE,161
|
|
89
|
-
realign/triggers/__init__.py,sha256=
|
|
90
|
-
realign/triggers/antigravity_trigger.py,sha256=sj9OKu2TihNlgOAd2B9XLy5wfJpY5VfJSast7Krl4bg,5195
|
|
91
|
+
realign/triggers/__init__.py,sha256=EUMWFX6CNJbXw3rrB1C7jn3QF0QgzbsLIZLiMcMZOo4,596
|
|
91
92
|
realign/triggers/base.py,sha256=Q72nlPMnCB3SP14gd4hm6AjS0mVyq5lbtlLUxSxAvrY,4148
|
|
92
93
|
realign/triggers/claude_trigger.py,sha256=-LY2sR-FTEXlCBx8SOI6TxP5-RI2BtlfzqvLeT5U3mw,20065
|
|
93
94
|
realign/triggers/codex_trigger.py,sha256=X8WNphoav86XNd05SJBoxpHySlFtEYCrjsEF-b6pw8M,13967
|
|
94
95
|
realign/triggers/gemini_trigger.py,sha256=878GDjxuJ8WCXEBbCLSN2k2l_3BSGzvykhZi3gfIOqw,7939
|
|
95
|
-
realign/triggers/next_turn_trigger.py,sha256
|
|
96
|
-
realign/triggers/registry.py,sha256=
|
|
96
|
+
realign/triggers/next_turn_trigger.py,sha256=-x80_I-WmIjXXzQHEPBykgx_GQW6oKaLDQx3dnPl53s,4194
|
|
97
|
+
realign/triggers/registry.py,sha256=dkIjSd8Bg-hF0nxaO2Fi2K-0Zipqv6vVjc-HYSrA_fY,3656
|
|
97
98
|
realign/triggers/turn_status.py,sha256=wAZEhXDAmDoX5F-ohWfSnZZ0eA6DAJ9svSPiSv_f6sg,6041
|
|
98
99
|
realign/triggers/turn_summary.py,sha256=f3hEUshgv9skJ9AbfWpoYs417lsv_HK2A_vpPjgryO4,4467
|
|
99
|
-
aline_ai-0.6.
|
|
100
|
-
aline_ai-0.6.
|
|
101
|
-
aline_ai-0.6.
|
|
102
|
-
aline_ai-0.6.
|
|
103
|
-
aline_ai-0.6.
|
|
100
|
+
aline_ai-0.6.4.dist-info/METADATA,sha256=NkBV9ESnpMtnqqp3cn6XcEYhJUjtSMndUS5QIpYP5oY,1597
|
|
101
|
+
aline_ai-0.6.4.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
102
|
+
aline_ai-0.6.4.dist-info/entry_points.txt,sha256=TvYELpMoWsUTcQdMV8tBHxCbEf_LbK4sESqK3r8PM6Y,78
|
|
103
|
+
aline_ai-0.6.4.dist-info/top_level.txt,sha256=yIL3s2xv9nf1GwD5n71Aq_JEIV4AfzCIDNKBzewuRm4,8
|
|
104
|
+
aline_ai-0.6.4.dist-info/RECORD,,
|
realign/__init__.py
CHANGED
realign/adapters/__init__.py
CHANGED
|
@@ -11,14 +11,12 @@ from .registry import AdapterRegistry, get_adapter_registry
|
|
|
11
11
|
from .claude import ClaudeAdapter
|
|
12
12
|
from .codex import CodexAdapter
|
|
13
13
|
from .gemini import GeminiAdapter
|
|
14
|
-
from .antigravity import AntigravityAdapter
|
|
15
14
|
|
|
16
15
|
# Register all built-in adapters
|
|
17
16
|
registry = get_adapter_registry()
|
|
18
17
|
registry.register(ClaudeAdapter)
|
|
19
18
|
registry.register(CodexAdapter)
|
|
20
19
|
registry.register(GeminiAdapter)
|
|
21
|
-
registry.register(AntigravityAdapter)
|
|
22
20
|
|
|
23
21
|
__all__ = [
|
|
24
22
|
"SessionAdapter",
|
|
@@ -27,5 +25,4 @@ __all__ = [
|
|
|
27
25
|
"ClaudeAdapter",
|
|
28
26
|
"CodexAdapter",
|
|
29
27
|
"GeminiAdapter",
|
|
30
|
-
"AntigravityAdapter",
|
|
31
28
|
]
|
realign/adapters/codex.py
CHANGED
|
@@ -21,17 +21,22 @@ class CodexAdapter(SessionAdapter):
|
|
|
21
21
|
|
|
22
22
|
def discover_sessions(self) -> List[Path]:
|
|
23
23
|
"""Find all Codex sessions."""
|
|
24
|
-
sessions = []
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
if not codex_sessions_base.exists():
|
|
28
|
-
return sessions
|
|
29
|
-
|
|
30
|
-
# Find all session files recursively
|
|
24
|
+
sessions: list[Path] = []
|
|
25
|
+
roots: list[Path] = []
|
|
31
26
|
try:
|
|
32
|
-
|
|
27
|
+
from ..codex_detector import _codex_session_roots # type: ignore[attr-defined]
|
|
28
|
+
|
|
29
|
+
roots = _codex_session_roots()
|
|
33
30
|
except Exception:
|
|
34
|
-
|
|
31
|
+
roots = [Path.home() / ".codex" / "sessions"]
|
|
32
|
+
|
|
33
|
+
for root in roots:
|
|
34
|
+
if not root.exists():
|
|
35
|
+
continue
|
|
36
|
+
try:
|
|
37
|
+
sessions.extend(root.rglob("rollout-*.jsonl"))
|
|
38
|
+
except Exception:
|
|
39
|
+
continue
|
|
35
40
|
|
|
36
41
|
return sessions
|
|
37
42
|
|
realign/cli.py
CHANGED
|
@@ -7,7 +7,19 @@ from typing import Optional
|
|
|
7
7
|
from rich.console import Console
|
|
8
8
|
from rich.syntax import Syntax
|
|
9
9
|
|
|
10
|
-
from .commands import
|
|
10
|
+
from .commands import (
|
|
11
|
+
init,
|
|
12
|
+
config,
|
|
13
|
+
watcher,
|
|
14
|
+
worker,
|
|
15
|
+
export_shares,
|
|
16
|
+
search,
|
|
17
|
+
upgrade,
|
|
18
|
+
restore,
|
|
19
|
+
add,
|
|
20
|
+
auth,
|
|
21
|
+
doctor,
|
|
22
|
+
)
|
|
11
23
|
|
|
12
24
|
app = typer.Typer(
|
|
13
25
|
name="realign",
|
|
@@ -33,6 +45,22 @@ def main(
|
|
|
33
45
|
ctx.obj["dev"] = dev
|
|
34
46
|
|
|
35
47
|
if ctx.invoked_subcommand is None:
|
|
48
|
+
def _needs_global_init() -> bool:
|
|
49
|
+
config_path = Path.home() / ".aline" / "config.yaml"
|
|
50
|
+
if not config_path.exists():
|
|
51
|
+
return True
|
|
52
|
+
try:
|
|
53
|
+
from .config import ReAlignConfig
|
|
54
|
+
|
|
55
|
+
cfg = ReAlignConfig.load(config_path)
|
|
56
|
+
db_path = Path(cfg.sqlite_db_path).expanduser()
|
|
57
|
+
if not db_path.exists():
|
|
58
|
+
return True
|
|
59
|
+
except Exception:
|
|
60
|
+
return True
|
|
61
|
+
prompts_dir = Path.home() / ".aline" / "prompts"
|
|
62
|
+
return not prompts_dir.exists()
|
|
63
|
+
|
|
36
64
|
# Check login status before launching dashboard
|
|
37
65
|
from .auth import is_logged_in, get_current_user
|
|
38
66
|
|
|
@@ -53,6 +81,17 @@ def main(
|
|
|
53
81
|
|
|
54
82
|
console.print() # Add spacing before dashboard launch
|
|
55
83
|
|
|
84
|
+
# First run after install/upgrade: ensure global artifacts exist.
|
|
85
|
+
if _needs_global_init():
|
|
86
|
+
console.print("[dim]First run detected. Running 'aline init'...[/dim]\n")
|
|
87
|
+
try:
|
|
88
|
+
from .commands import init as init_cmd
|
|
89
|
+
|
|
90
|
+
init_cmd.init_command(force=False, start_watcher=None)
|
|
91
|
+
except typer.Exit as e:
|
|
92
|
+
if getattr(e, "exit_code", 1) != 0:
|
|
93
|
+
raise
|
|
94
|
+
|
|
56
95
|
# Check for updates before launching dashboard
|
|
57
96
|
from .commands.upgrade import check_and_prompt_update
|
|
58
97
|
|
|
@@ -95,6 +134,7 @@ def main(
|
|
|
95
134
|
app.command(name="init")(init.init_command)
|
|
96
135
|
app.command(name="config")(config.config_command)
|
|
97
136
|
app.command(name="upgrade")(upgrade.upgrade_command)
|
|
137
|
+
app.command(name="doctor")(doctor.doctor_command)
|
|
98
138
|
|
|
99
139
|
|
|
100
140
|
# Auth commands
|
|
@@ -119,239 +159,6 @@ def whoami_cli():
|
|
|
119
159
|
raise typer.Exit(code=exit_code)
|
|
120
160
|
|
|
121
161
|
|
|
122
|
-
@app.command(name="doctor")
|
|
123
|
-
def doctor_cli(
|
|
124
|
-
no_restart: bool = typer.Option(False, "--no-restart", help="Only clear cache, don't restart daemons"),
|
|
125
|
-
verbose: bool = typer.Option(False, "--verbose", "-v", help="Show detailed output"),
|
|
126
|
-
):
|
|
127
|
-
"""
|
|
128
|
-
Fix common issues after code updates.
|
|
129
|
-
|
|
130
|
-
This command:
|
|
131
|
-
- Clears Python bytecode cache (.pyc files)
|
|
132
|
-
- Updates Claude Code hooks (Stop, UserPromptSubmit, PermissionRequest)
|
|
133
|
-
- Updates skills to latest version
|
|
134
|
-
- Ensures watcher daemon is running (restarts if running, starts if not)
|
|
135
|
-
- Ensures worker daemon is running (restarts if running, starts if not)
|
|
136
|
-
|
|
137
|
-
Run this after pulling new code to ensure everything uses the latest version.
|
|
138
|
-
"""
|
|
139
|
-
import shutil
|
|
140
|
-
import subprocess
|
|
141
|
-
import signal
|
|
142
|
-
import time
|
|
143
|
-
|
|
144
|
-
# Find the project root (where src/realign is)
|
|
145
|
-
project_root = Path(__file__).parent.parent.parent
|
|
146
|
-
|
|
147
|
-
# 1. Clear Python cache
|
|
148
|
-
console.print("[bold]1. Clearing Python cache...[/bold]")
|
|
149
|
-
pyc_count = 0
|
|
150
|
-
pycache_count = 0
|
|
151
|
-
|
|
152
|
-
for pyc_file in project_root.rglob("*.pyc"):
|
|
153
|
-
try:
|
|
154
|
-
pyc_file.unlink()
|
|
155
|
-
pyc_count += 1
|
|
156
|
-
if verbose:
|
|
157
|
-
console.print(f" [dim]Removed: {pyc_file}[/dim]")
|
|
158
|
-
except Exception as e:
|
|
159
|
-
if verbose:
|
|
160
|
-
console.print(f" [yellow]Failed to remove {pyc_file}: {e}[/yellow]")
|
|
161
|
-
|
|
162
|
-
for pycache_dir in project_root.rglob("__pycache__"):
|
|
163
|
-
if pycache_dir.is_dir():
|
|
164
|
-
try:
|
|
165
|
-
shutil.rmtree(pycache_dir)
|
|
166
|
-
pycache_count += 1
|
|
167
|
-
if verbose:
|
|
168
|
-
console.print(f" [dim]Removed: {pycache_dir}[/dim]")
|
|
169
|
-
except Exception as e:
|
|
170
|
-
if verbose:
|
|
171
|
-
console.print(f" [yellow]Failed to remove {pycache_dir}: {e}[/yellow]")
|
|
172
|
-
|
|
173
|
-
console.print(f" [green]✓[/green] Cleared {pyc_count} .pyc files, {pycache_count} __pycache__ directories")
|
|
174
|
-
|
|
175
|
-
# 2. Update Claude Code hooks
|
|
176
|
-
console.print("\n[bold]2. Updating Claude Code hooks...[/bold]")
|
|
177
|
-
hooks_updated = []
|
|
178
|
-
hooks_failed = []
|
|
179
|
-
|
|
180
|
-
# Stop hook
|
|
181
|
-
try:
|
|
182
|
-
from .claude_hooks.stop_hook_installer import install_stop_hook, get_settings_path
|
|
183
|
-
if install_stop_hook(get_settings_path(), quiet=True, force=True):
|
|
184
|
-
hooks_updated.append("Stop")
|
|
185
|
-
if verbose:
|
|
186
|
-
console.print(" [dim]Stop hook updated[/dim]")
|
|
187
|
-
else:
|
|
188
|
-
hooks_failed.append("Stop")
|
|
189
|
-
except Exception as e:
|
|
190
|
-
hooks_failed.append("Stop")
|
|
191
|
-
if verbose:
|
|
192
|
-
console.print(f" [yellow]Stop hook failed: {e}[/yellow]")
|
|
193
|
-
|
|
194
|
-
# UserPromptSubmit hook
|
|
195
|
-
try:
|
|
196
|
-
from .claude_hooks.user_prompt_submit_hook_installer import install_user_prompt_submit_hook, get_settings_path as get_submit_settings_path
|
|
197
|
-
if install_user_prompt_submit_hook(get_submit_settings_path(), quiet=True, force=True):
|
|
198
|
-
hooks_updated.append("UserPromptSubmit")
|
|
199
|
-
if verbose:
|
|
200
|
-
console.print(" [dim]UserPromptSubmit hook updated[/dim]")
|
|
201
|
-
else:
|
|
202
|
-
hooks_failed.append("UserPromptSubmit")
|
|
203
|
-
except Exception as e:
|
|
204
|
-
hooks_failed.append("UserPromptSubmit")
|
|
205
|
-
if verbose:
|
|
206
|
-
console.print(f" [yellow]UserPromptSubmit hook failed: {e}[/yellow]")
|
|
207
|
-
|
|
208
|
-
# PermissionRequest hook
|
|
209
|
-
try:
|
|
210
|
-
from .claude_hooks.permission_request_hook_installer import install_permission_request_hook, get_settings_path as get_permission_settings_path
|
|
211
|
-
if install_permission_request_hook(get_permission_settings_path(), quiet=True, force=True):
|
|
212
|
-
hooks_updated.append("PermissionRequest")
|
|
213
|
-
if verbose:
|
|
214
|
-
console.print(" [dim]PermissionRequest hook updated[/dim]")
|
|
215
|
-
else:
|
|
216
|
-
hooks_failed.append("PermissionRequest")
|
|
217
|
-
except Exception as e:
|
|
218
|
-
hooks_failed.append("PermissionRequest")
|
|
219
|
-
if verbose:
|
|
220
|
-
console.print(f" [yellow]PermissionRequest hook failed: {e}[/yellow]")
|
|
221
|
-
|
|
222
|
-
if hooks_updated:
|
|
223
|
-
console.print(f" [green]✓[/green] Updated hooks: {', '.join(hooks_updated)}")
|
|
224
|
-
if hooks_failed:
|
|
225
|
-
console.print(f" [yellow]![/yellow] Failed hooks: {', '.join(hooks_failed)}")
|
|
226
|
-
|
|
227
|
-
# 3. Update skills
|
|
228
|
-
console.print("\n[bold]3. Updating skills...[/bold]")
|
|
229
|
-
try:
|
|
230
|
-
from .commands.add import add_skills_command
|
|
231
|
-
# Capture output by redirecting - use force=True to update
|
|
232
|
-
import io
|
|
233
|
-
import contextlib
|
|
234
|
-
|
|
235
|
-
stdout_capture = io.StringIO()
|
|
236
|
-
with contextlib.redirect_stdout(stdout_capture):
|
|
237
|
-
add_skills_command(force=True)
|
|
238
|
-
|
|
239
|
-
output = stdout_capture.getvalue()
|
|
240
|
-
# Count updated skills from output
|
|
241
|
-
updated_count = output.count("✓")
|
|
242
|
-
if updated_count > 0:
|
|
243
|
-
console.print(f" [green]✓[/green] Updated {updated_count} skill(s)")
|
|
244
|
-
else:
|
|
245
|
-
console.print(" [green]✓[/green] Skills are up to date")
|
|
246
|
-
if verbose and output.strip():
|
|
247
|
-
for line in output.strip().split("\n"):
|
|
248
|
-
console.print(f" [dim]{line}[/dim]")
|
|
249
|
-
except Exception as e:
|
|
250
|
-
console.print(f" [yellow]![/yellow] Failed to update skills: {e}")
|
|
251
|
-
|
|
252
|
-
if no_restart:
|
|
253
|
-
console.print("\n[dim]Skipping daemon restart (--no-restart)[/dim]")
|
|
254
|
-
console.print("\n[green]Done![/green] Aline is ready with the latest code.")
|
|
255
|
-
raise typer.Exit(code=0)
|
|
256
|
-
|
|
257
|
-
# 4. Restart watcher daemon
|
|
258
|
-
console.print("\n[bold]4. Checking watcher daemon...[/bold]")
|
|
259
|
-
pid_file = Path.home() / ".aline" / ".logs" / "watcher.pid"
|
|
260
|
-
watcher_was_running = False
|
|
261
|
-
|
|
262
|
-
if pid_file.exists():
|
|
263
|
-
try:
|
|
264
|
-
pid = int(pid_file.read_text().strip())
|
|
265
|
-
# Check if process is running
|
|
266
|
-
try:
|
|
267
|
-
import os
|
|
268
|
-
os.kill(pid, 0) # Signal 0 just checks if process exists
|
|
269
|
-
watcher_was_running = True
|
|
270
|
-
console.print(f" [dim]Found watcher daemon (PID {pid}), stopping...[/dim]")
|
|
271
|
-
os.kill(pid, signal.SIGTERM)
|
|
272
|
-
time.sleep(1)
|
|
273
|
-
# Force kill if still running
|
|
274
|
-
try:
|
|
275
|
-
os.kill(pid, 0)
|
|
276
|
-
os.kill(pid, signal.SIGKILL)
|
|
277
|
-
time.sleep(0.5)
|
|
278
|
-
except ProcessLookupError:
|
|
279
|
-
pass
|
|
280
|
-
except ProcessLookupError:
|
|
281
|
-
console.print(" [dim]Watcher daemon not running (stale PID file)[/dim]")
|
|
282
|
-
except Exception as e:
|
|
283
|
-
if verbose:
|
|
284
|
-
console.print(f" [yellow]Error checking watcher: {e}[/yellow]")
|
|
285
|
-
|
|
286
|
-
if watcher_was_running:
|
|
287
|
-
console.print(" [dim]Starting watcher daemon...[/dim]")
|
|
288
|
-
else:
|
|
289
|
-
console.print(" [dim]Watcher daemon was not running, starting...[/dim]")
|
|
290
|
-
try:
|
|
291
|
-
subprocess.Popen(
|
|
292
|
-
["python", "-m", "src.realign.watcher_daemon"],
|
|
293
|
-
stdout=subprocess.DEVNULL,
|
|
294
|
-
stderr=subprocess.DEVNULL,
|
|
295
|
-
start_new_session=True,
|
|
296
|
-
cwd=str(project_root),
|
|
297
|
-
)
|
|
298
|
-
time.sleep(2)
|
|
299
|
-
action = "restarted" if watcher_was_running else "started"
|
|
300
|
-
console.print(f" [green]✓[/green] Watcher daemon {action}")
|
|
301
|
-
except Exception as e:
|
|
302
|
-
action = "restart" if watcher_was_running else "start"
|
|
303
|
-
console.print(f" [red]✗[/red] Failed to {action} watcher: {e}")
|
|
304
|
-
|
|
305
|
-
# 5. Restart worker daemon
|
|
306
|
-
console.print("\n[bold]5. Checking worker daemon...[/bold]")
|
|
307
|
-
worker_pid_file = Path.home() / ".aline" / ".logs" / "worker.pid"
|
|
308
|
-
worker_was_running = False
|
|
309
|
-
|
|
310
|
-
if worker_pid_file.exists():
|
|
311
|
-
try:
|
|
312
|
-
pid = int(worker_pid_file.read_text().strip())
|
|
313
|
-
try:
|
|
314
|
-
import os
|
|
315
|
-
os.kill(pid, 0)
|
|
316
|
-
worker_was_running = True
|
|
317
|
-
console.print(f" [dim]Found worker daemon (PID {pid}), stopping...[/dim]")
|
|
318
|
-
os.kill(pid, signal.SIGTERM)
|
|
319
|
-
time.sleep(1)
|
|
320
|
-
try:
|
|
321
|
-
os.kill(pid, 0)
|
|
322
|
-
os.kill(pid, signal.SIGKILL)
|
|
323
|
-
time.sleep(0.5)
|
|
324
|
-
except ProcessLookupError:
|
|
325
|
-
pass
|
|
326
|
-
except ProcessLookupError:
|
|
327
|
-
console.print(" [dim]Worker daemon not running (stale PID file)[/dim]")
|
|
328
|
-
except Exception as e:
|
|
329
|
-
if verbose:
|
|
330
|
-
console.print(f" [yellow]Error checking worker: {e}[/yellow]")
|
|
331
|
-
|
|
332
|
-
if worker_was_running:
|
|
333
|
-
console.print(" [dim]Starting worker daemon...[/dim]")
|
|
334
|
-
else:
|
|
335
|
-
console.print(" [dim]Worker daemon was not running, starting...[/dim]")
|
|
336
|
-
try:
|
|
337
|
-
subprocess.Popen(
|
|
338
|
-
["python", "-m", "src.realign.worker_daemon"],
|
|
339
|
-
stdout=subprocess.DEVNULL,
|
|
340
|
-
stderr=subprocess.DEVNULL,
|
|
341
|
-
start_new_session=True,
|
|
342
|
-
cwd=str(project_root),
|
|
343
|
-
)
|
|
344
|
-
time.sleep(2)
|
|
345
|
-
action = "restarted" if worker_was_running else "started"
|
|
346
|
-
console.print(f" [green]✓[/green] Worker daemon {action}")
|
|
347
|
-
except Exception as e:
|
|
348
|
-
action = "restart" if worker_was_running else "start"
|
|
349
|
-
console.print(f" [red]✗[/red] Failed to {action} worker: {e}")
|
|
350
|
-
|
|
351
|
-
console.print("\n[green]Done![/green] Aline is ready with the latest code.")
|
|
352
|
-
raise typer.Exit(code=0)
|
|
353
|
-
|
|
354
|
-
|
|
355
162
|
@app.command(name="search")
|
|
356
163
|
def search_cli(
|
|
357
164
|
query: str = typer.Argument(..., help="Search query (keywords or regex pattern)"),
|
|
@@ -445,7 +252,7 @@ app.add_typer(add_app, name="add")
|
|
|
445
252
|
@add_app.command(name="tmux")
|
|
446
253
|
def add_tmux_cli():
|
|
447
254
|
"""Install tmux via Homebrew and set up Aline tmux clipboard bindings."""
|
|
448
|
-
exit_code = add.add_tmux_command()
|
|
255
|
+
exit_code = add.add_tmux_command(install_brew=True)
|
|
449
256
|
raise typer.Exit(code=exit_code)
|
|
450
257
|
|
|
451
258
|
|
|
@@ -828,7 +635,6 @@ def watcher_event_revise_slack_cli(
|
|
|
828
635
|
exit_code = watcher.watcher_event_revise_slack_command(
|
|
829
636
|
input_json=input_json,
|
|
830
637
|
instruction=instruction,
|
|
831
|
-
provider=provider,
|
|
832
638
|
json_output=json_output,
|
|
833
639
|
)
|
|
834
640
|
raise typer.Exit(code=exit_code)
|