QQsci-skill/scripts/run_qqnote_with_qqsci_confi...

97 lines
3.0 KiB
Python

#!/usr/bin/env python3
"""Run QQnote scripts with QQsci config injected as environment variables."""
from __future__ import annotations
import argparse
import json
import os
import subprocess
import sys
from pathlib import Path
SCRIPT_MAP = {
"generate_zotero_ai_note": "generate_zotero_ai_note.py",
"summarize_zotero_table": "summarize_zotero_table.py",
"audit_zotero_ai_notes": "audit_zotero_ai_notes.py",
}
def skill_root() -> Path:
return Path(__file__).resolve().parents[1]
def load_json(path: Path) -> dict:
if not path.exists():
return {}
return json.loads(path.read_text(encoding="utf-8"))
def merged_config(root: Path) -> dict:
template = load_json(root / "config" / "config.template.json")
local = load_json(root / "config" / "config.local.json")
def merge(base: dict, override: dict) -> dict:
out = dict(base)
for key, value in override.items():
if isinstance(value, dict) and isinstance(out.get(key), dict):
out[key] = merge(out[key], value)
else:
out[key] = value
return out
return merge(template, local)
def set_if_present(env: dict[str, str], key: str, value: object) -> None:
if key in env and env[key]:
return
if value is None:
return
text = str(value)
if text:
env[key] = text
def build_env(config: dict) -> dict[str, str]:
env = os.environ.copy()
deepseek = config.get("deepseek") or {}
zotero = config.get("zotero") or {}
set_if_present(env, deepseek.get("env_api_key", "AWESOMEGPT_API_KEY"), deepseek.get("api_key"))
set_if_present(env, deepseek.get("env_base_url", "AWESOMEGPT_BASE_URL"), deepseek.get("base_url"))
set_if_present(env, deepseek.get("env_model", "AWESOMEGPT_MODEL"), deepseek.get("model"))
set_if_present(env, zotero.get("env_web_api_key", "ZOTERO_API_KEY"), zotero.get("web_api_key"))
set_if_present(env, zotero.get("env_user_id", "ZOTERO_USER_ID"), zotero.get("user_id"))
return env
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--script", required=True, choices=sorted(SCRIPT_MAP))
parser.add_argument("--qqnote-path", default="")
parser.add_argument("qqnote_args", nargs=argparse.REMAINDER)
args = parser.parse_args()
root = skill_root()
config = merged_config(root)
qqnote = Path(args.qqnote_path or (config.get("qqnote") or {}).get("skill_path") or "")
if not qqnote:
qqnote = Path.home() / ".codex" / "skills" / "QQnote-skill"
script = qqnote / "scripts" / SCRIPT_MAP[args.script]
if not script.exists():
print(f"QQnote script not found: {script}", file=sys.stderr)
return 2
extra_args = list(args.qqnote_args)
if extra_args and extra_args[0] == "--":
extra_args = extra_args[1:]
command = [sys.executable, str(script), *extra_args]
return subprocess.call(command, env=build_env(config))
if __name__ == "__main__":
raise SystemExit(main())