Files
aircontext/scripts/cmd_now.py
2026-05-18 11:45:08 +08:00

74 lines
2.5 KiB
Python

#!/usr/bin/env python3
"""Backend for /aircontext-now — force a compaction synchronously."""
from __future__ import annotations
import argparse
import json
import os
import sys
from pathlib import Path
_HERE = Path(__file__).resolve().parent
sys.path.insert(0, str(_HERE))
from core.compactor import run as run_compactor # noqa: E402
from core.state import StateFile # noqa: E402
def _find_transcript(project: Path, session_id: str) -> Path | None:
"""Locate the JSONL transcript for the given session.
Claude Code stores transcripts under
~/.claude/projects/<encoded-cwd>/sessions/<session-id>.jsonl
The cwd encoding replaces path separators with `-`. We search defensively.
"""
home = Path.home() / ".claude" / "projects"
if not home.exists():
return None
encoded = str(project).replace(os.sep, "-").replace(":", "")
# Try direct match first
candidate = home / encoded / "sessions" / f"{session_id}.jsonl"
if candidate.exists():
return candidate
# Fall back: scan for the session id under any project directory
for p in home.glob(f"*/sessions/{session_id}.jsonl"):
return p
return None
def main() -> int:
p = argparse.ArgumentParser()
p.add_argument("--session-id", required=True)
args = p.parse_args()
project = Path(os.environ.get("CLAUDE_PROJECT_DIR", os.getcwd()))
air = project / "AirContext"
if not (air / "config.yaml").exists():
print("AirContext not initialised. Run /aircontext-init first.")
return 1
transcript = _find_transcript(project, args.session_id)
if not transcript:
print(f"Could not locate transcript for session {args.session_id}.")
return 1
state = StateFile(air / "state.json")
# Force one-shot regardless of cooldown
state.update(last_compaction_unix=0)
print(f"Compacting transcript: {transcript}")
rc = run_compactor(project, transcript, args.session_id)
snap = state.read()
if rc == 0 and snap.get("compaction_ready"):
print("Compaction prepared. The wrapper will restart claude shortly.")
print("If you launched claude directly (without `aircontext`), exit and "
f"run: claude --resume {args.session_id}")
elif rc == 0:
print("Compactor returned success but no compaction was applied "
"(see compactor.log for reason — likely chain too short or paused).")
else:
print(f"Compactor failed with exit code {rc}. See AirContext/snapshots/compactor.log")
return rc
if __name__ == "__main__":
sys.exit(main())