Support Assistent persona packs via git and local sync.

Replace assistent-personas overlay seed with assistent-extensions SFTP and an assistent: section in extensions.yaml so personalities install like other extensions without private URLs in the public repo.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Leonid Pershin
2026-08-23 08:28:31 +03:00
co-authored by Cursor
parent b24c1b5d4b
commit 20ae7bd83a
25 changed files with 258 additions and 206 deletions
+25 -14
View File
@@ -118,6 +118,12 @@ if personas_root.is_dir():
for d in sorted(personas_root.iterdir()):
if d.is_dir():
persona_ids.append(d.name)
pack_root = overlay / "extensions"
pack_dirs = []
if pack_root.is_dir():
for d in sorted(pack_root.iterdir()):
if d.is_dir():
pack_dirs.append(d.name)
base_json = {}
base_path = overlay / "_base" / "assistant.json"
if base_path.is_file():
@@ -186,6 +192,7 @@ print(json.dumps({
"exists": overlay.is_dir(),
"entries": sorted(x.name for x in overlay.iterdir())[:50] if overlay.is_dir() else [],
"persona_ids": persona_ids,
"pack_dirs": pack_dirs,
"default_persona": base_json.get("default_persona") if isinstance(base_json, dict) else None,
"num_ctx": base_json.get("num_ctx") if isinstance(base_json, dict) else None,
"embed_model": base_json.get("embed_model") if isinstance(base_json, dict) else None,
@@ -610,30 +617,31 @@ def collect_assistent_overlay(cfg: Config, *, fs: dict[str, Any] | None = None)
if not fs.get("ok"):
return fs
overlay = fs.get("overlay") or {}
local_ids: list[str] = []
local_packs: list[str] = []
try:
from gpu_rent.paths import assistent_personas_dir
from gpu_rent.paths import assistent_extensions_dir
pdir = assistent_personas_dir()
pdir = assistent_extensions_dir()
if pdir.is_dir():
local_ids = sorted(
x.name for x in pdir.iterdir() if x.is_dir() and not x.name.startswith("_")
local_packs = sorted(
x.name for x in pdir.iterdir() if x.is_dir() and not x.name.startswith(".")
)
except Exception:
pass
remote_ids = list(overlay.get("persona_ids") or [])
missing_on_vm = sorted(set(local_ids) - set(remote_ids))
remote_packs = list(overlay.get("pack_dirs") or [])
missing_on_vm = sorted(set(local_packs) - set(remote_packs))
hints: list[str] = []
if local_ids and missing_on_vm:
if local_packs and missing_on_vm:
hints.append(
f"локальные personas не на VM: {', '.join(missing_on_vm[:8])} — gpu-rent seed-personas"
f"локальные packs не на VM: {', '.join(missing_on_vm[:8])} — gpu-rent seed-personas"
)
if not overlay.get("exists"):
hints.append("нет /mnt/swarm_data/Assistent — seed ещё не писал overlay (bundled personas ок)")
return {
"ok": True,
"overlay": overlay,
"local_persona_ids": local_ids,
"local_pack_dirs": local_packs,
"local_persona_ids": local_packs, # back-compat for older clients
"missing_on_vm": missing_on_vm,
"hints": hints,
}
@@ -1034,16 +1042,17 @@ def _ollama_chat_smoke_ssh(cfg: Config, *, model: str) -> dict[str, Any]:
def _local_assistent_bits(cfg: Config) -> dict[str, Any]:
local: dict[str, Any] = {}
try:
from gpu_rent.paths import assistent_personas_dir
from gpu_rent.paths import assistent_extensions_dir
pdir = assistent_personas_dir()
local["personas_dir"] = {
pdir = assistent_extensions_dir()
local["extensions_dir"] = {
"path": str(pdir),
"exists": pdir.is_dir(),
"entries": sorted(x.name for x in pdir.iterdir())[:40] if pdir.is_dir() else [],
}
local["personas_dir"] = local["extensions_dir"] # back-compat
except Exception as exc:
local["personas_dir"] = {"error": str(exc)[:120]}
local["extensions_dir"] = {"error": str(exc)[:120]}
try:
from gpu_rent.manifests import parse_extensions, repo_dirname
@@ -1051,9 +1060,11 @@ def _local_assistent_bits(cfg: Config) -> dict[str, Any]:
has = any(
"assistent" in repo_dirname(r).lower() or "assistent" in (r.url or "").lower()
for r in repos
if r.kind == "swarmui"
)
local["extensions_yaml"] = {
"has_swarm_assistent": has,
"assistent_packs": sum(1 for r in repos if r.kind == "assistent"),
"manifest": str(cfg.extensions_manifest),
}
except Exception as exc: