aline-ai 0.1.7__py3-none-any.whl → 0.1.9__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.1.7.dist-info → aline_ai-0.1.9.dist-info}/METADATA +1 -1
- {aline_ai-0.1.7.dist-info → aline_ai-0.1.9.dist-info}/RECORD +9 -9
- realign/__init__.py +1 -1
- realign/mcp_server.py +37 -1
- realign/mcp_watcher.py +89 -7
- {aline_ai-0.1.7.dist-info → aline_ai-0.1.9.dist-info}/WHEEL +0 -0
- {aline_ai-0.1.7.dist-info → aline_ai-0.1.9.dist-info}/entry_points.txt +0 -0
- {aline_ai-0.1.7.dist-info → aline_ai-0.1.9.dist-info}/licenses/LICENSE +0 -0
- {aline_ai-0.1.7.dist-info → aline_ai-0.1.9.dist-info}/top_level.txt +0 -0
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
aline_ai-0.1.
|
|
2
|
-
realign/__init__.py,sha256=
|
|
1
|
+
aline_ai-0.1.9.dist-info/licenses/LICENSE,sha256=H8wTqV5IF1oHw_HbBtS1PSDU8G_q81yblEIL_JfV8Vo,1077
|
|
2
|
+
realign/__init__.py,sha256=XAZn0QmHa9QpFynxcqvNBgMblMHb6ppHrHzvnAj8p1s,68
|
|
3
3
|
realign/claude_detector.py,sha256=NLxI0zJWcqNxNha9jAy9AslTMwHKakCc9yPGdkrbiFE,3028
|
|
4
4
|
realign/cli.py,sha256=bkwS329jMDEkrUEihXRN2DDyeTKE6HbAysoDxxskZ8g,941
|
|
5
5
|
realign/codex_detector.py,sha256=RI3JbZgebrhoqpRfTBMfclYCAISN7hZAHVW3bgftJpU,4428
|
|
6
6
|
realign/config.py,sha256=jarinbr0mA6e5DmgY19b_VpMnxk6SOYTwyvB9luq0ww,7207
|
|
7
7
|
realign/hooks.py,sha256=qhAeuln_62OgTq0vboZcUAuP2apOrNn58vSZqKwNmWQ,36456
|
|
8
8
|
realign/logging_config.py,sha256=KvkKktF-bkUu031y9vgUoHpsbnOw7ud25jhpzliNZwA,4929
|
|
9
|
-
realign/mcp_server.py,sha256=
|
|
10
|
-
realign/mcp_watcher.py,sha256=
|
|
9
|
+
realign/mcp_server.py,sha256=HGg0nW9_cJnW-22bSBwBONpid3Lq8UICyWyzOAny4OM,18963
|
|
10
|
+
realign/mcp_watcher.py,sha256=0bMD1Ah7hmmpozJzopnjFTDJrpq76jyTZaXat-Ropy0,19708
|
|
11
11
|
realign/redactor.py,sha256=uZvLKKGrRGJm-qM8S4XJyJK6i0CSSby_wbKiay7VGJw,8148
|
|
12
12
|
realign/commands/__init__.py,sha256=GG6IMw6fUBQAXGJDFJvOOQgv6pkiRSfMh8z3AYXTyRM,31
|
|
13
13
|
realign/commands/auto_commit.py,sha256=_DOw7nt9q3tD_Y3qDL9IFKAUG1hM4qH_xZ-9nyBc2Bc,7451
|
|
@@ -16,8 +16,8 @@ realign/commands/config.py,sha256=oarvn6UuGT8svd2h5_8M_ueV5QWOCUOn8SYoa4XYjs8,65
|
|
|
16
16
|
realign/commands/init.py,sha256=EpSzh2Dd2EmEQ_wo3vAsg6Uq7_YOlQWIpzIkZa_2y0A,11863
|
|
17
17
|
realign/commands/search.py,sha256=0CZaXll99wtd01MRiZk5NAblxgogc4RUAzMyJunvckE,18044
|
|
18
18
|
realign/commands/show.py,sha256=P1waa94-AKJr9XjagkE40OHMXzE6IwC74DpeDKqwsqw,16693
|
|
19
|
-
aline_ai-0.1.
|
|
20
|
-
aline_ai-0.1.
|
|
21
|
-
aline_ai-0.1.
|
|
22
|
-
aline_ai-0.1.
|
|
23
|
-
aline_ai-0.1.
|
|
19
|
+
aline_ai-0.1.9.dist-info/METADATA,sha256=H1PCZ5ZGFkeRCgZM7krMrVc9tRcMdBKwP4L25Sncj18,1398
|
|
20
|
+
aline_ai-0.1.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
21
|
+
aline_ai-0.1.9.dist-info/entry_points.txt,sha256=h-NocHDzSueXfsepHTIdRPNQzhNZQPAztJfldd-mQTE,202
|
|
22
|
+
aline_ai-0.1.9.dist-info/top_level.txt,sha256=yIL3s2xv9nf1GwD5n71Aq_JEIV4AfzCIDNKBzewuRm4,8
|
|
23
|
+
aline_ai-0.1.9.dist-info/RECORD,,
|
realign/__init__.py
CHANGED
realign/mcp_server.py
CHANGED
|
@@ -410,6 +410,22 @@ def _server_log(msg: str):
|
|
|
410
410
|
pass
|
|
411
411
|
|
|
412
412
|
|
|
413
|
+
# Log immediately when module is imported
|
|
414
|
+
_early_log_path = Path.home() / ".aline_mcp_startup.log"
|
|
415
|
+
try:
|
|
416
|
+
with open(_early_log_path, "a") as f:
|
|
417
|
+
from datetime import datetime
|
|
418
|
+
f.write(f"\n{'='*60}\n")
|
|
419
|
+
f.write(f"[{datetime.now()}] MCP SERVER MODULE LOADED\n")
|
|
420
|
+
f.write(f"Python: {sys.executable}\n")
|
|
421
|
+
f.write(f"CWD: {Path.cwd()}\n")
|
|
422
|
+
f.write(f"HOME: {Path.home()}\n")
|
|
423
|
+
f.write(f"Version: {__version__}\n")
|
|
424
|
+
f.write(f"{'='*60}\n")
|
|
425
|
+
except Exception as e:
|
|
426
|
+
print(f"[MCP Server] Early log failed: {e}", file=sys.stderr)
|
|
427
|
+
|
|
428
|
+
|
|
413
429
|
async def async_main():
|
|
414
430
|
"""Run the MCP server (async)."""
|
|
415
431
|
_server_log("Starting Aline MCP server...")
|
|
@@ -487,7 +503,27 @@ async def async_main():
|
|
|
487
503
|
|
|
488
504
|
def main():
|
|
489
505
|
"""Entry point for the MCP server command."""
|
|
490
|
-
|
|
506
|
+
# Log entry point
|
|
507
|
+
try:
|
|
508
|
+
with open(_early_log_path, "a") as f:
|
|
509
|
+
from datetime import datetime
|
|
510
|
+
f.write(f"[{datetime.now()}] main() called, starting asyncio.run\n")
|
|
511
|
+
except Exception:
|
|
512
|
+
pass
|
|
513
|
+
|
|
514
|
+
try:
|
|
515
|
+
asyncio.run(async_main())
|
|
516
|
+
except Exception as e:
|
|
517
|
+
# Log any exceptions
|
|
518
|
+
try:
|
|
519
|
+
with open(_early_log_path, "a") as f:
|
|
520
|
+
from datetime import datetime
|
|
521
|
+
import traceback
|
|
522
|
+
f.write(f"[{datetime.now()}] EXCEPTION in main: {e}\n")
|
|
523
|
+
f.write(traceback.format_exc())
|
|
524
|
+
except Exception:
|
|
525
|
+
pass
|
|
526
|
+
raise
|
|
491
527
|
|
|
492
528
|
|
|
493
529
|
if __name__ == "__main__":
|
realign/mcp_watcher.py
CHANGED
|
@@ -261,29 +261,111 @@ class DialogueWatcher:
|
|
|
261
261
|
Extract the actual project path from a Claude session file's location.
|
|
262
262
|
|
|
263
263
|
Claude Code stores sessions in: ~/.claude/projects/-Users-username-path/session.jsonl
|
|
264
|
-
The directory name encodes the project path with dashes replacing slashes.
|
|
264
|
+
The directory name encodes the project path with dashes replacing both slashes and underscores.
|
|
265
|
+
This means we need to intelligently reconstruct the path by testing which separators work.
|
|
265
266
|
"""
|
|
266
267
|
try:
|
|
267
268
|
project_dir_name = session_file.parent.name
|
|
268
269
|
_log(f"Extracting project path from: {project_dir_name}")
|
|
269
270
|
|
|
270
271
|
if project_dir_name.startswith('-'):
|
|
271
|
-
#
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
_log(f"Candidate project path: {candidate_path}")
|
|
272
|
+
# Split into segments
|
|
273
|
+
segments = project_dir_name[1:].split('-')
|
|
274
|
+
_log(f"Path segments: {segments}")
|
|
275
275
|
|
|
276
|
-
|
|
276
|
+
# Try to reconstruct the path by checking which combinations exist
|
|
277
|
+
candidate_path = self._reconstruct_path_from_segments(segments)
|
|
278
|
+
|
|
279
|
+
if candidate_path and candidate_path.exists():
|
|
277
280
|
_log(f"Project path exists: {candidate_path}")
|
|
278
281
|
return candidate_path
|
|
279
282
|
else:
|
|
280
|
-
|
|
283
|
+
# Fallback: try simple replacement (for backward compatibility)
|
|
284
|
+
simple_path = Path('/' + project_dir_name[1:].replace('-', '/'))
|
|
285
|
+
if simple_path.exists():
|
|
286
|
+
_log(f"Project path exists (simple method): {simple_path}")
|
|
287
|
+
return simple_path
|
|
288
|
+
_log(f"WARNING: Could not find valid project path for: {project_dir_name}")
|
|
281
289
|
else:
|
|
282
290
|
_log(f"WARNING: Directory name doesn't start with '-': {project_dir_name}")
|
|
283
291
|
except Exception as e:
|
|
284
292
|
_log(f"Error extracting project path: {e}")
|
|
285
293
|
return None
|
|
286
294
|
|
|
295
|
+
def _reconstruct_path_from_segments(self, segments: list) -> Optional[Path]:
|
|
296
|
+
"""
|
|
297
|
+
Reconstruct a file path from encoded segments.
|
|
298
|
+
|
|
299
|
+
Claude Code encodes paths by replacing both '/' and '_' with '-'.
|
|
300
|
+
This method tries to find the correct path by testing which separators
|
|
301
|
+
produce valid paths.
|
|
302
|
+
|
|
303
|
+
Strategy:
|
|
304
|
+
1. Start from root '/'
|
|
305
|
+
2. Build path incrementally, checking if each partial path exists
|
|
306
|
+
3. When a segment doesn't match, try combining with next segment using '_' or '-'
|
|
307
|
+
"""
|
|
308
|
+
if not segments:
|
|
309
|
+
return None
|
|
310
|
+
|
|
311
|
+
current_path = Path('/')
|
|
312
|
+
i = 0
|
|
313
|
+
|
|
314
|
+
while i < len(segments):
|
|
315
|
+
segment = segments[i]
|
|
316
|
+
|
|
317
|
+
# Try direct match first (segment is a directory/file name)
|
|
318
|
+
test_path = current_path / segment
|
|
319
|
+
if test_path.exists():
|
|
320
|
+
current_path = test_path
|
|
321
|
+
i += 1
|
|
322
|
+
continue
|
|
323
|
+
|
|
324
|
+
# If direct match fails, try combining with next segments using '_' or '-'
|
|
325
|
+
found_match = False
|
|
326
|
+
for lookahead in range(1, min(10, len(segments) - i)): # Try up to 10 segments ahead
|
|
327
|
+
# Try combining segments with underscores
|
|
328
|
+
combined_underscore = '_'.join(segments[i:i+lookahead+1])
|
|
329
|
+
test_path_underscore = current_path / combined_underscore
|
|
330
|
+
|
|
331
|
+
# Try combining segments with hyphens
|
|
332
|
+
combined_hyphen = '-'.join(segments[i:i+lookahead+1])
|
|
333
|
+
test_path_hyphen = current_path / combined_hyphen
|
|
334
|
+
|
|
335
|
+
# Try mixed combinations for longer paths
|
|
336
|
+
if test_path_underscore.exists():
|
|
337
|
+
current_path = test_path_underscore
|
|
338
|
+
i += lookahead + 1
|
|
339
|
+
found_match = True
|
|
340
|
+
_log(f"Found match with underscores: {combined_underscore}")
|
|
341
|
+
break
|
|
342
|
+
elif test_path_hyphen.exists():
|
|
343
|
+
current_path = test_path_hyphen
|
|
344
|
+
i += lookahead + 1
|
|
345
|
+
found_match = True
|
|
346
|
+
_log(f"Found match with hyphens: {combined_hyphen}")
|
|
347
|
+
break
|
|
348
|
+
|
|
349
|
+
if not found_match:
|
|
350
|
+
# If no match found, this might be the final segment (file or non-existent dir)
|
|
351
|
+
# Just append remaining segments with '/' and check
|
|
352
|
+
remaining = '/'.join(segments[i:])
|
|
353
|
+
final_path = current_path / remaining
|
|
354
|
+
if final_path.exists():
|
|
355
|
+
return final_path
|
|
356
|
+
|
|
357
|
+
# Try treating remaining as underscore-joined
|
|
358
|
+
remaining_underscore = '_'.join(segments[i:])
|
|
359
|
+
final_path_underscore = current_path / remaining_underscore
|
|
360
|
+
if final_path_underscore.exists():
|
|
361
|
+
return final_path_underscore
|
|
362
|
+
|
|
363
|
+
# Nothing worked, return what we have
|
|
364
|
+
_log(f"Could not match segment '{segment}' at path {current_path}")
|
|
365
|
+
return None
|
|
366
|
+
|
|
367
|
+
return current_path if current_path != Path('/') else None
|
|
368
|
+
|
|
287
369
|
async def _do_commit(self, project_path: Path):
|
|
288
370
|
"""Perform the actual commit for a specific project."""
|
|
289
371
|
try:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|