ltcai 3.5.0 → 4.0.0

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 (181) hide show
  1. package/README.md +73 -35
  2. package/docs/CARRYOVER_AUDIT_v3.6.0.md +61 -0
  3. package/docs/CHANGELOG.md +32 -0
  4. package/docs/HANDOVER_v3.6.0.md +46 -0
  5. package/docs/RUNTIME_HOOK_COVERAGE_v3.6.0.md +49 -0
  6. package/docs/V4_BRAIN_ARCHITECTURE.md +322 -0
  7. package/docs/V4_DIGITAL_BRAIN_RECOVERY.md +509 -0
  8. package/docs/V4_IMPLEMENTATION_PLAN.md +470 -0
  9. package/docs/architecture.md +13 -12
  10. package/docs/kg-schema.md +102 -53
  11. package/docs/privacy.md +18 -2
  12. package/docs/security-model.md +17 -0
  13. package/kg_schema.py +139 -10
  14. package/knowledge_graph.py +874 -26
  15. package/knowledge_graph_api.py +11 -127
  16. package/latticeai/__init__.py +1 -1
  17. package/latticeai/api/admin.py +1 -1
  18. package/latticeai/api/agents.py +7 -1
  19. package/latticeai/api/auth.py +27 -4
  20. package/latticeai/api/browser.py +217 -0
  21. package/latticeai/api/chat.py +112 -76
  22. package/latticeai/api/health.py +1 -1
  23. package/latticeai/api/hooks.py +1 -1
  24. package/latticeai/api/knowledge_graph.py +146 -0
  25. package/latticeai/api/local_files.py +1 -1
  26. package/latticeai/api/mcp.py +23 -11
  27. package/latticeai/api/memory.py +1 -1
  28. package/latticeai/api/models.py +1 -1
  29. package/latticeai/api/network.py +81 -0
  30. package/latticeai/api/portability.py +93 -0
  31. package/latticeai/api/realtime.py +1 -1
  32. package/latticeai/api/search.py +26 -2
  33. package/latticeai/api/security_dashboard.py +2 -3
  34. package/latticeai/api/setup.py +2 -2
  35. package/latticeai/api/static_routes.py +2 -4
  36. package/latticeai/api/tools.py +3 -0
  37. package/latticeai/api/workflow_designer.py +46 -0
  38. package/latticeai/api/workspace.py +71 -49
  39. package/latticeai/app_factory.py +1710 -0
  40. package/latticeai/brain/__init__.py +18 -0
  41. package/latticeai/brain/context.py +213 -0
  42. package/latticeai/brain/conversations.py +236 -0
  43. package/latticeai/brain/identity.py +175 -0
  44. package/latticeai/brain/memory.py +102 -0
  45. package/latticeai/brain/network.py +205 -0
  46. package/latticeai/core/agent.py +31 -7
  47. package/latticeai/core/audit.py +0 -7
  48. package/latticeai/core/config.py +1 -1
  49. package/latticeai/core/context_builder.py +1 -2
  50. package/latticeai/core/enterprise.py +1 -1
  51. package/latticeai/core/graph_curator.py +2 -2
  52. package/latticeai/core/marketplace.py +1 -1
  53. package/latticeai/core/mcp_registry.py +791 -0
  54. package/latticeai/core/model_compat.py +1 -1
  55. package/latticeai/core/model_resolution.py +0 -1
  56. package/latticeai/core/multi_agent.py +238 -4
  57. package/latticeai/core/security.py +1 -1
  58. package/latticeai/core/sessions.py +37 -7
  59. package/latticeai/core/workflow_engine.py +114 -2
  60. package/latticeai/core/workspace_os.py +58 -10
  61. package/latticeai/models/__init__.py +7 -0
  62. package/latticeai/models/router.py +779 -0
  63. package/latticeai/server_app.py +29 -1504
  64. package/latticeai/services/agent_runtime.py +1 -0
  65. package/latticeai/services/app_context.py +75 -14
  66. package/latticeai/services/ingestion.py +318 -0
  67. package/latticeai/services/kg_portability.py +207 -0
  68. package/latticeai/services/memory_service.py +39 -11
  69. package/latticeai/services/model_runtime.py +2 -5
  70. package/latticeai/services/platform_runtime.py +100 -23
  71. package/latticeai/services/search_service.py +17 -8
  72. package/latticeai/services/tool_dispatch.py +12 -2
  73. package/latticeai/services/triggers.py +241 -0
  74. package/latticeai/services/upload_service.py +37 -12
  75. package/latticeai/services/workspace_service.py +31 -0
  76. package/llm_router.py +29 -772
  77. package/ltcai_cli.py +1 -2
  78. package/mcp_registry.py +25 -788
  79. package/p_reinforce.py +124 -14
  80. package/package.json +11 -8
  81. package/scripts/build_vsix.mjs +72 -0
  82. package/scripts/bump_version.py +99 -0
  83. package/scripts/generate_diagrams.py +0 -1
  84. package/scripts/lint_v3.mjs +82 -18
  85. package/scripts/validate_release_artifacts.py +0 -1
  86. package/scripts/wheel_smoke.py +142 -0
  87. package/server.py +11 -7
  88. package/setup_wizard.py +1142 -0
  89. package/static/account.html +2 -4
  90. package/static/admin.html +3 -5
  91. package/static/chat.html +3 -6
  92. package/static/graph.html +2 -4
  93. package/static/sw.js +81 -52
  94. package/static/v3/asset-manifest.json +20 -19
  95. package/static/v3/css/{lattice.base.e4cdd05d.css → lattice.base.49deefb5.css} +1 -1
  96. package/static/v3/css/lattice.base.css +1 -1
  97. package/static/v3/css/{lattice.components.9b49d614.css → lattice.components.cde18231.css} +1 -1
  98. package/static/v3/css/lattice.components.css +1 -1
  99. package/static/v3/css/{lattice.shell.8fcc9d33.css → lattice.shell.29d36d85.css} +1 -1
  100. package/static/v3/css/lattice.shell.css +1 -1
  101. package/static/v3/css/{lattice.tokens.e7018963.css → lattice.tokens.304cbc40.css} +3 -0
  102. package/static/v3/css/lattice.tokens.css +3 -0
  103. package/static/v3/css/{lattice.views.22f69117.css → lattice.views.0a18b6c5.css} +2 -2
  104. package/static/v3/css/lattice.views.css +2 -2
  105. package/static/v3/index.html +3 -4
  106. package/static/v3/js/{app.d086489d.js → app.356e6452.js} +1 -1
  107. package/static/v3/js/core/{api.12b568ad.js → api.7a308b89.js} +39 -1
  108. package/static/v3/js/core/api.js +38 -0
  109. package/static/v3/js/core/{routes.d214b399.js → routes.7222343d.js} +22 -22
  110. package/static/v3/js/core/routes.js +22 -22
  111. package/static/v3/js/core/{shell.d05266f5.js → shell.a1657f20.js} +4 -4
  112. package/static/v3/js/core/shell.js +1 -1
  113. package/static/v3/js/core/{store.34ebd5e6.js → store.204a08b2.js} +1 -1
  114. package/static/v3/js/core/store.js +1 -1
  115. package/static/v3/js/views/graph-canvas.17c15d65.js +509 -0
  116. package/static/v3/js/views/graph-canvas.js +509 -0
  117. package/static/v3/js/views/{hybrid-search.b22b97e0.js → hybrid-search.2fb63ed9.js} +1 -2
  118. package/static/v3/js/views/hybrid-search.js +1 -2
  119. package/static/v3/js/views/knowledge-graph.5e40cbeb.js +509 -0
  120. package/static/v3/js/views/knowledge-graph.js +326 -54
  121. package/static/vendor/chart.umd.min.js +20 -0
  122. package/static/vendor/fonts/inter-latin-300-normal.woff2 +0 -0
  123. package/static/vendor/fonts/inter-latin-400-normal.woff2 +0 -0
  124. package/static/vendor/fonts/inter-latin-500-normal.woff2 +0 -0
  125. package/static/vendor/fonts/inter-latin-600-normal.woff2 +0 -0
  126. package/static/vendor/fonts/inter-latin-700-normal.woff2 +0 -0
  127. package/static/vendor/fonts/inter-latin-800-normal.woff2 +0 -0
  128. package/static/vendor/fonts/inter.css +44 -0
  129. package/static/vendor/icons/tabler-icons.min.css +4 -0
  130. package/static/vendor/icons/tabler-icons.woff2 +0 -0
  131. package/static/vendor/marked.min.js +69 -0
  132. package/static/workspace.html +2 -2
  133. package/telegram_bot.py +1 -2
  134. package/tools/commands.py +4 -2
  135. package/tools/computer.py +1 -1
  136. package/tools/documents.py +1 -3
  137. package/tools/filesystem.py +0 -4
  138. package/tools/knowledge.py +1 -3
  139. package/tools/network.py +1 -3
  140. package/codex_telegram_bot.py +0 -195
  141. package/docs/assets/v3.4.0/agent-run.png +0 -0
  142. package/docs/assets/v3.4.0/agents.png +0 -0
  143. package/docs/assets/v3.4.0/before/chat-before.png +0 -0
  144. package/docs/assets/v3.4.0/before/files-before.png +0 -0
  145. package/docs/assets/v3.4.0/chat.png +0 -0
  146. package/docs/assets/v3.4.0/connect-folder.png +0 -0
  147. package/docs/assets/v3.4.0/files.png +0 -0
  148. package/docs/assets/v3.4.0/home.png +0 -0
  149. package/docs/assets/v3.4.0/hooks-dispatch.png +0 -0
  150. package/docs/assets/v3.4.0/knowledge-graph.png +0 -0
  151. package/docs/assets/v3.4.0/local-agent.png +0 -0
  152. package/docs/assets/v3.4.0/memory.png +0 -0
  153. package/docs/assets/v3.4.0/settings.png +0 -0
  154. package/docs/assets/v3.4.0/vision-input.png +0 -0
  155. package/docs/assets/v3.4.0/workflows.png +0 -0
  156. package/docs/assets/v3.4.1/e2e_runtime_log.txt +0 -42
  157. package/docs/assets/v3.4.1/hooks-dispatch.png +0 -0
  158. package/docs/assets/v3.4.1/local-agent.png +0 -0
  159. package/docs/images/admin-dashboard.png +0 -0
  160. package/docs/images/architecture.png +0 -0
  161. package/docs/images/enterprise.png +0 -0
  162. package/docs/images/graph.png +0 -0
  163. package/docs/images/hero.gif +0 -0
  164. package/docs/images/knowledge-graph.png +0 -0
  165. package/docs/images/lattice-ai-demo.gif +0 -0
  166. package/docs/images/lattice-ai-hero.png +0 -0
  167. package/docs/images/logo.svg +0 -33
  168. package/docs/images/mobile-responsive.png +0 -0
  169. package/docs/images/model-recommendation.png +0 -0
  170. package/docs/images/onboarding.png +0 -0
  171. package/docs/images/organization.png +0 -0
  172. package/docs/images/pipeline.png +0 -0
  173. package/docs/images/screenshot-admin.png +0 -0
  174. package/docs/images/screenshot-chat.png +0 -0
  175. package/docs/images/screenshot-graph.png +0 -0
  176. package/docs/images/skills.png +0 -0
  177. package/docs/images/workspace-dark.png +0 -0
  178. package/docs/images/workspace-light.png +0 -0
  179. package/docs/images/workspace.png +0 -0
  180. package/requirements.txt +0 -16
  181. package/static/v3/js/views/knowledge-graph.a14ea7e7.js +0 -237
@@ -0,0 +1,142 @@
1
+ #!/usr/bin/env python3
2
+ """Installed-wheel smoke test.
3
+
4
+ Builds the wheel, installs it into a *fresh* venv, and verifies — from a
5
+ non-repo working directory — that every module the wheel ships actually
6
+ imports and that the FastAPI app boots and answers ``/health``. This kills the
7
+ class of "works only with ``pip install -e .`` from the repo root" failures
8
+ (e.g. the v3.x wheels that omitted the root ``setup.py`` wizard module while
9
+ ``latticeai.server_app`` imported it).
10
+
11
+ Usage:
12
+ python scripts/wheel_smoke.py # build + install + import + /health
13
+ python scripts/wheel_smoke.py --wheel dist/ltcai-X.Y.Z-py3-none-any.whl
14
+ python scripts/wheel_smoke.py --skip-health # imports only
15
+
16
+ The build step prefers ``python -m build --wheel`` and falls back to
17
+ ``pip wheel . --no-deps`` when the ``build`` package is unavailable.
18
+ Exit code is non-zero on any failure so CI can gate on it.
19
+ """
20
+
21
+ from __future__ import annotations
22
+
23
+ import argparse
24
+ import os
25
+ import subprocess
26
+ import sys
27
+ import tempfile
28
+ import venv
29
+ from pathlib import Path
30
+
31
+ REPO_ROOT = Path(__file__).resolve().parents[1]
32
+
33
+ # Every importable module the wheel ships (pyproject py-modules + packages).
34
+ WHEEL_MODULES = [
35
+ "setup_wizard",
36
+ "latticeai",
37
+ "latticeai.server_app",
38
+ "latticeai.app_factory",
39
+ "latticeai.models.router",
40
+ "latticeai.core.mcp_registry",
41
+ "latticeai.api.knowledge_graph",
42
+ "ltcai_cli",
43
+ "auto_setup",
44
+ "server",
45
+ "mcp_registry",
46
+ "kg_schema",
47
+ "knowledge_graph",
48
+ "knowledge_graph_api",
49
+ "local_knowledge_api",
50
+ "llm_router",
51
+ "p_reinforce",
52
+ "telegram_bot",
53
+ "tools",
54
+ ]
55
+
56
+ IMPORT_CHECK = (
57
+ "import importlib\n"
58
+ + "".join(f"importlib.import_module({mod!r})\n" for mod in WHEEL_MODULES)
59
+ + f"print('wheel imports ok: {len(WHEEL_MODULES)} modules')\n"
60
+ )
61
+
62
+ HEALTH_CHECK = """
63
+ from fastapi.testclient import TestClient
64
+ from latticeai.app_factory import create_app
65
+
66
+ app = create_app()
67
+ response = TestClient(app).get("/health")
68
+ assert response.status_code == 200, f"/health returned {response.status_code}"
69
+ payload = response.json()
70
+ assert "version" in payload, f"/health payload missing version: {payload}"
71
+ print("health ok:", payload.get("version"))
72
+ """
73
+
74
+
75
+ def run(cmd: list[str], **kwargs) -> None:
76
+ print("+", " ".join(str(c) for c in cmd), flush=True)
77
+ subprocess.run(cmd, check=True, **kwargs)
78
+
79
+
80
+ def build_wheel(out_dir: Path) -> Path:
81
+ try:
82
+ import build # noqa: F401 — probe only
83
+ run([sys.executable, "-m", "build", "--wheel", "--outdir", str(out_dir)], cwd=REPO_ROOT)
84
+ except ImportError:
85
+ print("'build' package unavailable; falling back to pip wheel --no-deps", flush=True)
86
+ run(
87
+ [sys.executable, "-m", "pip", "wheel", str(REPO_ROOT), "--no-deps", "-w", str(out_dir)],
88
+ cwd=REPO_ROOT,
89
+ )
90
+ wheels = sorted(out_dir.glob("ltcai-*.whl"))
91
+ if not wheels:
92
+ raise SystemExit(f"no wheel produced in {out_dir}")
93
+ return wheels[-1]
94
+
95
+
96
+ def main() -> int:
97
+ parser = argparse.ArgumentParser(description=__doc__)
98
+ parser.add_argument("--wheel", type=Path, default=None, help="use an existing wheel instead of building")
99
+ parser.add_argument("--skip-health", action="store_true", help="run import checks only (no app boot)")
100
+ args = parser.parse_args()
101
+
102
+ with tempfile.TemporaryDirectory(prefix="ltcai-wheel-smoke-") as tmp:
103
+ tmp_path = Path(tmp)
104
+
105
+ wheel = args.wheel.resolve() if args.wheel else build_wheel(tmp_path / "dist")
106
+ print(f"wheel under test: {wheel}", flush=True)
107
+
108
+ venv_dir = tmp_path / "venv"
109
+ venv.EnvBuilder(with_pip=True, clear=True).create(venv_dir)
110
+ bin_dir = "Scripts" if os.name == "nt" else "bin"
111
+ python = venv_dir / bin_dir / ("python.exe" if os.name == "nt" else "python")
112
+
113
+ run([str(python), "-m", "pip", "install", "--quiet", str(wheel)])
114
+
115
+ # A cwd that is NOT the repo: imports must resolve from site-packages,
116
+ # never from checkout-relative files.
117
+ work_dir = tmp_path / "non-repo-cwd"
118
+ work_dir.mkdir()
119
+ # Sandbox all user-data writes so the smoke test never touches ~/.ltcai.
120
+ env = {
121
+ **os.environ,
122
+ "HOME": str(tmp_path / "home"),
123
+ "LATTICEAI_DATA_DIR": str(tmp_path / "home" / ".ltcai"),
124
+ "LATTICEAI_AGENT_ROOT": str(tmp_path / "home" / "agent_workspace"),
125
+ "LATTICEAI_BRAIN_DIR": str(tmp_path / "home" / ".ltcai-brain"),
126
+ "LATTICEAI_ENABLE_TELEGRAM": "false",
127
+ "LATTICEAI_AUTOLOAD_MODELS": "false",
128
+ "PYTHONPATH": "",
129
+ }
130
+ (tmp_path / "home").mkdir()
131
+
132
+ run([str(python), "-c", IMPORT_CHECK], cwd=work_dir, env=env)
133
+
134
+ if not args.skip_health:
135
+ run([str(python), "-c", HEALTH_CHECK], cwd=work_dir, env=env)
136
+
137
+ print("wheel smoke test passed")
138
+ return 0
139
+
140
+
141
+ if __name__ == "__main__":
142
+ raise SystemExit(main())
package/server.py CHANGED
@@ -1,21 +1,25 @@
1
1
  """Thin compatibility entrypoint for the Lattice AI FastAPI app.
2
2
 
3
- The application assembly and route wiring live in ``latticeai.server_app``.
4
- This module keeps the historical ``server:app`` import path used by uvicorn,
5
- Docker, CLI scripts, and older tests.
3
+ The application is built by ``latticeai.app_factory.create_app``; this module
4
+ keeps the historical ``server:app`` import path used by uvicorn, Docker, CLI
5
+ scripts, and older tests. Attribute access is proxied lazily so that simply
6
+ importing ``server`` performs no construction — ``uvicorn server:app`` (or
7
+ ``from server import app``) triggers the factory on first access.
6
8
  """
7
9
 
8
10
  from __future__ import annotations
9
11
 
12
+ from typing import Any, List
13
+
10
14
  from latticeai import server_app as _server_app
11
15
 
12
16
 
13
- for _name in dir(_server_app):
14
- if not _name.startswith("__"):
15
- globals()[_name] = getattr(_server_app, _name)
17
+ def __getattr__(name: str) -> Any:
18
+ return getattr(_server_app, name)
16
19
 
17
20
 
18
- app = _server_app.app
21
+ def __dir__() -> List[str]:
22
+ return sorted(set(globals()) | set(dir(_server_app)))
19
23
 
20
24
 
21
25
  def main() -> None: