subcortex 0.3.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. subcortex/__init__.py +3 -0
  2. subcortex/__main__.py +3 -0
  3. subcortex/adapters/__init__.py +48 -0
  4. subcortex/adapters/base.py +230 -0
  5. subcortex/adapters/claude_family.py +133 -0
  6. subcortex/adapters/codex.py +87 -0
  7. subcortex/adapters/copilot.py +60 -0
  8. subcortex/adapters/cursor.py +36 -0
  9. subcortex/adapters/docker_agent.py +115 -0
  10. subcortex/adapters/gemini_family.py +60 -0
  11. subcortex/adapters/grok.py +98 -0
  12. subcortex/adapters/kimi_code.py +138 -0
  13. subcortex/adapters/letta_vibe.py +96 -0
  14. subcortex/adapters/openhands.py +153 -0
  15. subcortex/auth.py +59 -0
  16. subcortex/backends/__init__.py +23 -0
  17. subcortex/backends/base.py +22 -0
  18. subcortex/backends/jev.py +460 -0
  19. subcortex/backends/laya.py +149 -0
  20. subcortex/cli.py +809 -0
  21. subcortex/client.py +77 -0
  22. subcortex/config.py +263 -0
  23. subcortex/daemon.py +502 -0
  24. subcortex/evalset.py +241 -0
  25. subcortex/hook.py +254 -0
  26. subcortex/installers/__init__.py +62 -0
  27. subcortex/installers/amp.py +39 -0
  28. subcortex/installers/base.py +874 -0
  29. subcortex/installers/claude_family.py +229 -0
  30. subcortex/installers/codex.py +110 -0
  31. subcortex/installers/copilot.py +65 -0
  32. subcortex/installers/crush.py +36 -0
  33. subcortex/installers/cursor.py +79 -0
  34. subcortex/installers/gemini_family.py +83 -0
  35. subcortex/installers/goose.py +186 -0
  36. subcortex/installers/kimi_code.py +71 -0
  37. subcortex/installers/mcp_only.py +111 -0
  38. subcortex/installers/more_hooks.py +184 -0
  39. subcortex/installers/opencode.py +66 -0
  40. subcortex/installers/openhands.py +84 -0
  41. subcortex/installers/pi_cline.py +53 -0
  42. subcortex/ledger.py +92 -0
  43. subcortex/localhttp.py +59 -0
  44. subcortex/mcp_server.py +187 -0
  45. subcortex/metrics.py +56 -0
  46. subcortex/plugins/amp/subcortex.ts +258 -0
  47. subcortex/plugins/cline/subcortex.ts +340 -0
  48. subcortex/plugins/opencode/subcortex.ts +265 -0
  49. subcortex/plugins/pi/subcortex.ts +292 -0
  50. subcortex/policy.py +341 -0
  51. subcortex/presets.py +163 -0
  52. subcortex/provision.py +188 -0
  53. subcortex/service.py +149 -0
  54. subcortex/state.py +137 -0
  55. subcortex/transcript.py +211 -0
  56. subcortex/tuis.py +51 -0
  57. subcortex/ui.py +319 -0
  58. subcortex/verdicts.py +233 -0
  59. subcortex/wizard.py +474 -0
  60. subcortex-0.3.0.dist-info/METADATA +287 -0
  61. subcortex-0.3.0.dist-info/RECORD +64 -0
  62. subcortex-0.3.0.dist-info/WHEEL +5 -0
  63. subcortex-0.3.0.dist-info/entry_points.txt +3 -0
  64. subcortex-0.3.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,149 @@
1
+ """Laya backend: local typed-decision models.
2
+
3
+ Ported from laya-hermes (hermes_laya/backend.py), trimmed to the two backends
4
+ subcortex supports:
5
+
6
+ - ``mlx`` — ``pip install laya-mlx`` (Apple Silicon, macOS 14+)
7
+ - ``torch`` — ``pip install laya`` (upstream PyTorch, CUDA/CPU; everywhere else)
8
+
9
+ Model aliases: ``english`` (421M, 512 tok), ``multilingual`` (322M, 100+
10
+ languages, 1024 tok — default), ``typed-decisions`` (421M fine-tuned for
11
+ typed-decision workflows, 1024 tok).
12
+
13
+ Agents load lazily on first ``predict`` and are cached per (backend, alias).
14
+ """
15
+
16
+ from __future__ import annotations
17
+
18
+ import importlib
19
+ import importlib.util
20
+ import os
21
+ import platform
22
+ import sys
23
+ import threading
24
+ from typing import Any, Dict, Tuple
25
+
26
+ from ..config import venv_pip
27
+
28
+ _BACKENDS = ("mlx", "torch")
29
+ _MODULES = {"mlx": "laya_mlx", "torch": "laya"}
30
+ _PACKAGES = {"mlx": "laya-mlx", "torch": "laya"}
31
+
32
+ # alias -> per-backend Hugging Face checkpoint (torch uses repo + optional subfolder)
33
+ _CHECKPOINTS: Dict[str, Dict[str, Any]] = {
34
+ "english": {
35
+ "mlx": "aac6fef/laya-mlx",
36
+ "torch": ("convaiinnovations/laya", None),
37
+ },
38
+ "multilingual": {
39
+ "mlx": "aac6fef/laya-multilingual-mlx",
40
+ "torch": ("convaiinnovations/laya", "multilingual"),
41
+ },
42
+ "typed-decisions": {
43
+ "mlx": "aac6fef/laya-typed-decisions-mlx",
44
+ "torch": ("convaiinnovations/laya", "typed-decisions"),
45
+ },
46
+ }
47
+
48
+ DEFAULT_MODEL = "multilingual"
49
+
50
+
51
+ class BackendUnavailableError(RuntimeError):
52
+ """Raised when the laya backend package is not installed/importable."""
53
+
54
+
55
+ def _is_apple_silicon() -> bool:
56
+ return sys.platform == "darwin" and platform.machine() == "arm64"
57
+
58
+
59
+ def detect_backend() -> str:
60
+ """mlx on Apple Silicon, torch everywhere else."""
61
+ return "mlx" if _is_apple_silicon() else "torch"
62
+
63
+
64
+ def _module_available(module: str) -> bool:
65
+ try:
66
+ return importlib.util.find_spec(module) is not None
67
+ except (ImportError, ValueError):
68
+ return False
69
+
70
+
71
+ def _install_hint(package: str) -> str:
72
+ if venv_pip().exists():
73
+ return f"run: {venv_pip()} install {package}"
74
+ return f"run: {sys.executable} -m pip install {package}"
75
+
76
+
77
+ class LayaBackend:
78
+ name = "laya"
79
+
80
+ def __init__(self, config: Dict[str, Any]) -> None:
81
+ self.model = str(config.get("model") or DEFAULT_MODEL).strip().lower()
82
+ self._agents: Dict[Tuple[str, str], Any] = {}
83
+ self._lock = threading.Lock()
84
+ # The daemon serves requests on many threads, but a model is not safe to
85
+ # run concurrently (MLX shares one Metal queue; torch modules keep state).
86
+ self._predict_lock = threading.Lock()
87
+
88
+ # -- availability ---------------------------------------------------------
89
+
90
+ def available(self) -> Tuple[bool, str]:
91
+ backend = detect_backend()
92
+ module = _MODULES[backend]
93
+ if _module_available(module):
94
+ return True, f"laya backend {backend!r} available ({module}, model {self.model!r})"
95
+ package = _PACKAGES[backend]
96
+ return False, (
97
+ f"{module} is not installed for {sys.executable}. "
98
+ f"{_install_hint(package)}"
99
+ )
100
+
101
+ # -- lazy loading ---------------------------------------------------------
102
+
103
+ def _checkpoint(self, alias: str, backend: str) -> Any:
104
+ if alias not in _CHECKPOINTS:
105
+ raise ValueError(
106
+ f"Unknown laya model alias {alias!r}; valid: {', '.join(sorted(_CHECKPOINTS))}"
107
+ )
108
+ return _CHECKPOINTS[alias][backend]
109
+
110
+ def _load(self, alias: str) -> Any:
111
+ backend = detect_backend()
112
+ key = (backend, alias)
113
+ with self._lock:
114
+ if key in self._agents:
115
+ return self._agents[key]
116
+ module = _MODULES[backend]
117
+ if not _module_available(module):
118
+ raise BackendUnavailableError(
119
+ f"Laya backend {backend!r} is not available. "
120
+ f"{_install_hint(_PACKAGES[backend])}"
121
+ )
122
+ try:
123
+ if backend == "torch":
124
+ # Upstream laya deadlocks on import when TensorFlow is also installed.
125
+ os.environ.setdefault("USE_TF", "0")
126
+ mod = importlib.import_module(module)
127
+ except ImportError as exc:
128
+ raise BackendUnavailableError(
129
+ f"Laya backend {backend!r} failed to import ({exc}). "
130
+ f"{_install_hint(_PACKAGES[backend])}"
131
+ ) from exc
132
+ ref = self._checkpoint(alias, backend)
133
+ if backend == "mlx":
134
+ agent = mod.load(ref)
135
+ else: # torch
136
+ repo, subfolder = ref
137
+ agent = mod.load(repo, subfolder=subfolder) if subfolder else mod.load(repo)
138
+ self._agents[key] = agent
139
+ return agent
140
+
141
+ # -- inference ------------------------------------------------------------
142
+
143
+ def predict(self, state: Any, questions: Dict[str, Any]) -> Dict[str, Any]:
144
+ agent = self._load(self.model)
145
+ with self._predict_lock:
146
+ result = agent.predict(state, questions)
147
+ if not isinstance(result, dict):
148
+ result = {"answers": result}
149
+ return result