Align Coolify webapp with WinSCP share and remote output paths.

Resolve section text from OUTPUT_DIR by basename, add /api/search and richer /healthz, default mount to /mnt/.../Output, support --remote-root in processor.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-25 19:47:09 +03:00
parent 9613420d1d
commit a81d5794d4
9 changed files with 342 additions and 145 deletions

View File

@@ -842,6 +842,14 @@ def make_code(prefix: str, file_index: int, sec_index: int) -> str:
# Основна обработка
# ──────────────────────────────────────────────
def _db_output_path(local_path: Path, code: str, remote_root: Optional[str]) -> str:
"""Локален staging файл; в БД — сървърен път ако е зададен remote_root."""
if remote_root:
root = remote_root.replace("\\", "/").rstrip("/")
return f"{root}/{code}.txt"
return str(local_path)
def process_file(
path: Path,
file_index: int,
@@ -850,6 +858,7 @@ def process_file(
output_dir: Path,
prefix: str = "HLP",
force: bool = False,
remote_root: Optional[str] = None,
) -> int:
"""Обработва един файл. Връща броя записани секции (0 = пропуснат)."""
rel = str(path)
@@ -937,7 +946,7 @@ def process_file(
html_text=html_text,
)
# Записваме текста в изходна директория
# Локален staging; в БД — remote път (ако е зададен) за Coolify/API
out_path = output_dir / f"{code}.txt"
out_path.write_text(
f"КОД: {code}\nФАЙЛ: {rel}\nЗАГЛАВИЕ: {title}\nКЛЮЧОВИ ДУМИ: {keywords}\n"
@@ -946,7 +955,7 @@ def process_file(
encoding="utf-8"
)
db.insert_section(prefix, ps, str(out_path))
db.insert_section(prefix, ps, _db_output_path(out_path, code, remote_root))
saved += 1
log.debug(f" {code}: {title[:60]} ({len(image_rel_paths)} img)")
@@ -966,6 +975,7 @@ def process_directory(
prefix: str = "HLP",
force: bool = False,
purge_missing: bool = False,
remote_root: Optional[str] = None,
):
if not _PREFIX_RE.match(prefix):
raise ValueError(
@@ -991,13 +1001,17 @@ def process_directory(
if p.is_file() and p.suffix.lower() in extensions and not _under_output(p)
]
log.info(f"Prefix={prefix} Намерени {len(files)} файла в {input_dir}")
if remote_root:
log.info(f"DB output_path root: {remote_root.replace(chr(92), '/').rstrip('/')}")
current_paths = {str(p) for p in files}
total_sections = 0
try:
for idx, path in enumerate(sorted(files), 1):
n = process_file(path, idx, db, client, output_dir,
prefix=prefix, force=force)
n = process_file(
path, idx, db, client, output_dir,
prefix=prefix, force=force, remote_root=remote_root,
)
total_sections += n
if purge_missing:
@@ -1013,11 +1027,19 @@ def process_directory(
removed_files = 0
for op in disk_paths:
try:
code = Path(str(op).replace("\\", "/")).stem
local_txt = output_dir / f"{code}.txt"
if local_txt.exists():
local_txt.unlink()
removed_files += 1
opath = Path(op)
if opath.exists():
opath.unlink()
removed_files += 1
code = opath.stem
try:
if opath.resolve() != local_txt.resolve():
opath.unlink()
removed_files += 1
except Exception:
pass
for img in (output_dir / "images").glob(f"{code}_*"):
try:
img.unlink()
@@ -1040,14 +1062,14 @@ def process_directory(
def main():
parser = argparse.ArgumentParser(
description="Help-файл декомпозитор с SQL Server + Anthropic"
description="Help-файл декомпозитор с PostgreSQL + Anthropic"
)
parser.add_argument("input_dir", help="Входна директория с help-файлове")
parser.add_argument("output_dir", help="Изходна директория за текстови секции")
parser.add_argument(
"--conn",
default=os.getenv("HELP_DB_CONN"),
help="SQL Server connection string (или HELP_DB_CONN env var)"
help="Postgres libpq connection string (или HELP_DB_CONN env var)"
)
parser.add_argument(
"--api-key",
@@ -1071,12 +1093,20 @@ def main():
help="След обработката изтрива от БД и диска секциите за източници, "
"които вече не съществуват във входната директория (само в дадения prefix)"
)
parser.add_argument(
"--remote-root",
default=os.getenv("HELP_REMOTE_ROOT"),
help="Сървърен корен за output_path в БД "
"(напр. /mnt/mssql/share/RIP/RIP_Help_Source/Output). "
"Файловете се пишат локално; в БД се записва remote път. "
"Или env HELP_REMOTE_ROOT."
)
args = parser.parse_args()
if not args.api_key:
sys.exit("Грешка: липсва Anthropic API ключ (--api-key или ANTHROPIC_API_KEY).")
if not args.conn:
sys.exit("Грешка: липсва SQL Server connection string (--conn или HELP_DB_CONN).")
sys.exit("Грешка: липсва Postgres connection string (--conn или HELP_DB_CONN).")
process_directory(
input_dir=Path(args.input_dir),
@@ -1086,6 +1116,7 @@ def main():
prefix=args.prefix,
force=args.force,
purge_missing=args.purge_missing,
remote_root=args.remote_root,
)