페르소나 소스팩 동기화 정리
This commit is contained in:
parent
6a81ec596c
commit
e8e08935ed
10 changed files with 1126 additions and 283 deletions
91
scripts/sync-persona-sources.py
Normal file
91
scripts/sync-persona-sources.py
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
"""Sync repo-managed persona/evaluator source packs into KB.
|
||||
|
||||
Default mode is a DB-backed dry run: compare repo source pack content hashes
|
||||
against active kb.document rows and report the versions that would be used.
|
||||
Use --apply to upsert kb.source rows and index changed documents.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import asyncio
|
||||
import dataclasses
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
|
||||
REPO_ROOT = Path(__file__).resolve().parents[1]
|
||||
API_ROOT = REPO_ROOT / "apps" / "api"
|
||||
if str(API_ROOT) not in sys.path:
|
||||
sys.path.insert(0, str(API_ROOT))
|
||||
|
||||
|
||||
from app.db import acquire, close_pool, init_pool # noqa: E402
|
||||
from app.services import source_pack_sync # noqa: E402
|
||||
|
||||
|
||||
def _to_payload(result: source_pack_sync.RepoSourcePackSyncResult) -> dict[str, Any]:
|
||||
return {
|
||||
"applied": result.applied,
|
||||
"sources_upserted": result.sources_upserted,
|
||||
"manifest_count": result.manifest_count,
|
||||
"chunks_indexed": result.chunks_indexed,
|
||||
"skipped_unchanged": result.skipped_unchanged,
|
||||
"embedded": result.embedded,
|
||||
"degraded": result.degraded,
|
||||
"items": [dataclasses.asdict(item) for item in result.items],
|
||||
}
|
||||
|
||||
|
||||
def _print_text(result: source_pack_sync.RepoSourcePackSyncResult) -> None:
|
||||
mode = "APPLY" if result.applied else "DRY-RUN"
|
||||
print(f"persona source pack sync: {mode}")
|
||||
print(f"manifest_count: {result.manifest_count}")
|
||||
print(f"sources_upserted: {result.sources_upserted}")
|
||||
print(f"chunks_indexed: {result.chunks_indexed}")
|
||||
print(f"skipped_unchanged: {result.skipped_unchanged}")
|
||||
for item in result.items:
|
||||
previous = "-" if item.previous_version is None else str(item.previous_version)
|
||||
action = "skip" if item.skipped_unchanged else ("apply" if result.applied else "would_apply")
|
||||
print(
|
||||
f"- {item.source_id} {action} v{previous}->v{item.new_version} "
|
||||
f"{item.content_hash[:12]} chunks={item.chunks_indexed}"
|
||||
)
|
||||
|
||||
|
||||
async def _main_async(args: argparse.Namespace) -> int:
|
||||
await init_pool()
|
||||
try:
|
||||
async with acquire(role="admin") as conn:
|
||||
result = await source_pack_sync.sync_repo_source_packs(conn, apply=bool(args.apply))
|
||||
finally:
|
||||
await close_pool()
|
||||
if args.json:
|
||||
print(json.dumps(_to_payload(result), ensure_ascii=False, indent=2, sort_keys=True))
|
||||
else:
|
||||
_print_text(result)
|
||||
return 0
|
||||
|
||||
|
||||
def parse_args(argv: list[str]) -> argparse.Namespace:
|
||||
parser = argparse.ArgumentParser(
|
||||
description=(
|
||||
"Compare or apply repo-managed persona/evaluator source packs. "
|
||||
"Dry-run is the default and reads DB state without writes; --apply "
|
||||
"upserts source rows and indexes changed document versions."
|
||||
)
|
||||
)
|
||||
parser.add_argument("--apply", action="store_true", help="write changed source packs into KB")
|
||||
parser.add_argument("--json", action="store_true", help="emit machine-readable JSON")
|
||||
return parser.parse_args(argv)
|
||||
|
||||
|
||||
def main(argv: list[str] | None = None) -> int:
|
||||
args = parse_args(list(argv if argv is not None else sys.argv[1:]))
|
||||
return asyncio.run(_main_async(args))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Loading…
Add table
Add a link
Reference in a new issue