2026-10-24 11:45:40 +04:00

103 lines
4.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Команды sdlc-hub: init (настройки из config.example.json), serve (HTTP), mcp [модуль] (stdio), tokens,
agent publish (версия агента для самообновления) и подкоманды модулей (jira: import)."""
import argparse
import json
import sys
from . import db, paths, registry, settings
from .paths import secure_dir
def main(argv=None) -> int:
ap = argparse.ArgumentParser(prog="sdlc-hub", description="SDLC-хаб: ядро и модули")
sub = ap.add_subparsers(dest="cmd", required=True)
p = sub.add_parser("init", help="перенести настройки проекта из config.example.json, создать токены")
p.add_argument("--config", required=True)
p.add_argument("--force", action="store_true")
p = sub.add_parser("serve", help="запустить HTTP API")
p.add_argument("--host", default="0.0.0.0")
p.add_argument("--port", type=int)
p = sub.add_parser("mcp", help="MCP-сервер модуля по stdio ")
p.add_argument("module", nargs="?", default=None, help="имя модуля (jira, wiki); без модуля или неизвестный — код 2")
p.add_argument("--project", help="метка проекта, к которому привязана сессия")
for m in registry.modules():
if m.cli_register:
m.cli_register(sub)
sub.add_parser("tokens", help="показать токены клиента и агентов")
p = sub.add_parser("agent", help="версия агента для самообновления")
agent_sub = p.add_subparsers(dest="agent_cmd", required=True)
p = agent_sub.add_parser("publish", help="опубликовать agent.py (версия только вверх)")
p.add_argument("--module", default=registry.DEFAULT_AGENT, help=f"модуль агента (по умолчанию {registry.DEFAULT_AGENT})")
p.add_argument("path")
args = ap.parse_args(argv)
if args.cmd == "agent":
from . import release
names = [m.name for m in registry.agent_modules()]
if args.module not in names:
print(f"неизвестный модуль {args.module}; модули с агентами: {', '.join(names)}", file=sys.stderr)
return 2
try:
secure_dir(paths.release_root())
release.migrate_layout(paths.release_root()) # прежняя раскладка release/ до проверки «только вверх»
m = release.publish(release.module_dir(paths.release_root(), args.module), args.path)
except release.PublishError as e:
print(e, file=sys.stderr)
return 1
print(f"опубликована v{m['version']}, sha256 {m['sha256'][:12]}…, {m['size']} байт")
return 0
if args.cmd == "serve":
from . import api
hub = api.Hub(paths.db_path())
conn = hub.conn()
port = args.port or int(settings.get(conn, "port") or 8790)
conn.close()
api.serve(hub, args.host, port)
return 0
if args.cmd == "mcp":
from . import mcp
return mcp.run(args.module, args.project)
for m in registry.modules():
if m.cli_run:
rc = m.cli_run(args)
if rc is not None:
return rc
conn = db.connect(paths.db_path())
settings.ensure_defaults(conn)
try:
if args.cmd == "init":
with open(args.config, encoding="utf-8") as f:
cfg = json.load(f)
lines: list[str] = []
try:
for m in registry.modules():
if m.on_init:
lines += m.on_init(conn, cfg, args.force)
except RuntimeError as e:
print(e, file=sys.stderr)
return 1
for line in lines:
print(line)
_print_tokens(conn)
return 0
if args.cmd == "tokens":
_print_tokens(conn)
return 0
finally:
conn.close()
return 2
def _print_tokens(conn) -> None:
tok = settings.tokens(conn)
print(f"клиентский токен: {tok['client']}")
for m in registry.agent_modules():
print(f"агент {m.name}: {tok['agents'][m.name]}")
print(f"база: {paths.db_path()}")
if __name__ == "__main__":
sys.exit(main())