ltcai 9.0.0 → 9.2.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.
- package/README.md +88 -46
- package/auto_setup.py +7 -853
- package/desktop/electron/README.md +9 -0
- package/desktop/electron/main.cjs +5 -3
- package/docs/CHANGELOG.md +178 -2
- package/docs/COMMUNITY_AND_PLUGINS.md +4 -2
- package/docs/DEVELOPMENT.md +53 -14
- package/docs/LEGACY_COMPATIBILITY.md +4 -4
- package/docs/ONBOARDING.md +10 -2
- package/docs/OPERATIONS.md +8 -4
- package/docs/PRODUCT_DIRECTION_REVIEW.md +4 -0
- package/docs/TRUST_MODEL.md +5 -2
- package/docs/WHY_LATTICE.md +15 -10
- package/docs/WORKFLOW_DESIGNER.md +22 -0
- package/docs/kg-schema.md +13 -2
- package/docs/mcp-tools.md +17 -6
- package/docs/privacy.md +19 -3
- package/docs/public-deploy.md +32 -3
- package/docs/security-model.md +46 -11
- package/lattice_brain/__init__.py +1 -1
- package/lattice_brain/archive.py +1 -6
- package/lattice_brain/context.py +66 -9
- package/lattice_brain/graph/_kg_fsutil.py +1 -5
- package/lattice_brain/graph/discovery_index.py +174 -20
- package/lattice_brain/graph/documents.py +44 -9
- package/lattice_brain/graph/ingest.py +47 -20
- package/lattice_brain/graph/provenance.py +13 -6
- package/lattice_brain/graph/retrieval.py +140 -39
- package/lattice_brain/graph/retrieval_docgen.py +37 -4
- package/lattice_brain/ingestion.py +4 -7
- package/lattice_brain/portability.py +28 -14
- package/lattice_brain/runtime/agent_runtime.py +5 -9
- package/lattice_brain/runtime/hooks.py +30 -13
- package/lattice_brain/runtime/multi_agent.py +27 -8
- package/lattice_brain/runtime/statuses.py +10 -0
- package/lattice_brain/utils.py +20 -2
- package/lattice_brain/workflow.py +1 -5
- package/latticeai/__init__.py +1 -1
- package/latticeai/api/admin.py +1 -1
- package/latticeai/api/agent_registry.py +10 -8
- package/latticeai/api/agents.py +22 -3
- package/latticeai/api/auth.py +78 -16
- package/latticeai/api/browser.py +303 -34
- package/latticeai/api/chat.py +320 -850
- package/latticeai/api/chat_agent_http.py +356 -0
- package/latticeai/api/chat_contracts.py +54 -0
- package/latticeai/api/chat_documents.py +256 -0
- package/latticeai/api/chat_helpers.py +28 -1
- package/latticeai/api/chat_history.py +99 -0
- package/latticeai/api/chat_intents.py +316 -0
- package/latticeai/api/chat_stream.py +115 -0
- package/latticeai/api/computer_use.py +62 -9
- package/latticeai/api/health.py +9 -3
- package/latticeai/api/hooks.py +17 -6
- package/latticeai/api/knowledge_graph.py +78 -14
- package/latticeai/api/local_files.py +7 -2
- package/latticeai/api/mcp.py +102 -23
- package/latticeai/api/models.py +72 -33
- package/latticeai/api/network.py +5 -5
- package/latticeai/api/permissions.py +67 -26
- package/latticeai/api/plugins.py +21 -7
- package/latticeai/api/portability.py +5 -5
- package/latticeai/api/realtime.py +33 -5
- package/latticeai/api/setup.py +2 -2
- package/latticeai/api/static_routes.py +123 -24
- package/latticeai/api/tools.py +96 -14
- package/latticeai/api/workflow_designer.py +37 -0
- package/latticeai/api/workspace.py +2 -1
- package/latticeai/app_factory.py +110 -52
- package/latticeai/core/agent.py +50 -13
- package/latticeai/core/agent_prompts.py +5 -0
- package/latticeai/core/agent_registry.py +1 -5
- package/latticeai/core/config.py +23 -3
- package/latticeai/core/context_builder.py +21 -3
- package/latticeai/core/file_generation.py +451 -0
- package/latticeai/core/invitations.py +1 -4
- package/latticeai/core/io_utils.py +9 -1
- package/latticeai/core/legacy_compatibility.py +24 -3
- package/latticeai/core/marketplace.py +1 -1
- package/latticeai/core/plugins.py +15 -0
- package/latticeai/core/policy.py +1 -1
- package/latticeai/core/realtime.py +38 -15
- package/latticeai/core/sessions.py +7 -2
- package/latticeai/core/timeutil.py +10 -0
- package/latticeai/core/tool_registry.py +90 -18
- package/latticeai/core/users.py +1 -5
- package/latticeai/core/workspace_graph_trace.py +31 -5
- package/latticeai/core/workspace_memory.py +3 -1
- package/latticeai/core/workspace_os.py +18 -7
- package/latticeai/core/workspace_os_utils.py +0 -5
- package/latticeai/core/workspace_permissions.py +2 -1
- package/latticeai/core/workspace_plugins.py +1 -1
- package/latticeai/core/workspace_runs.py +14 -5
- package/latticeai/core/workspace_skills.py +1 -1
- package/latticeai/core/workspace_snapshots.py +2 -1
- package/latticeai/core/workspace_timeline.py +2 -1
- package/latticeai/integrations/telegram_bot.py +94 -43
- package/latticeai/models/router.py +130 -36
- package/latticeai/runtime/access_runtime.py +62 -4
- package/latticeai/runtime/automation_runtime.py +13 -7
- package/latticeai/runtime/brain_runtime.py +19 -7
- package/latticeai/runtime/chat_wiring.py +2 -0
- package/latticeai/runtime/config_runtime.py +58 -26
- package/latticeai/runtime/context_runtime.py +16 -4
- package/latticeai/runtime/hooks_runtime.py +1 -1
- package/latticeai/runtime/model_wiring.py +33 -5
- package/latticeai/runtime/namespace_runtime.py +62 -72
- package/latticeai/runtime/platform_runtime_wiring.py +4 -3
- package/latticeai/runtime/review_wiring.py +1 -1
- package/latticeai/runtime/router_registration.py +34 -1
- package/latticeai/runtime/security_runtime.py +110 -13
- package/latticeai/runtime/stages.py +27 -0
- package/latticeai/server_app.py +5 -1
- package/latticeai/services/architecture_readiness.py +74 -5
- package/latticeai/services/brain_automation.py +3 -26
- package/latticeai/services/chat_service.py +205 -15
- package/latticeai/services/local_knowledge.py +423 -0
- package/latticeai/services/memory_service.py +55 -21
- package/latticeai/services/model_engines.py +48 -33
- package/latticeai/services/model_errors.py +17 -0
- package/latticeai/services/model_loading.py +28 -25
- package/latticeai/services/model_runtime.py +228 -162
- package/latticeai/services/p_reinforce.py +22 -3
- package/latticeai/services/platform_runtime.py +83 -23
- package/latticeai/services/product_readiness.py +19 -17
- package/latticeai/services/review_queue.py +12 -0
- package/latticeai/services/router_context.py +1 -0
- package/latticeai/services/run_executor.py +4 -9
- package/latticeai/services/search_service.py +203 -28
- package/latticeai/services/tool_dispatch.py +28 -5
- package/latticeai/services/triggers.py +53 -4
- package/latticeai/services/upload_service.py +13 -2
- package/latticeai/setup/__init__.py +25 -0
- package/latticeai/setup/auto_setup.py +857 -0
- package/latticeai/setup/wizard.py +1264 -0
- package/latticeai/tools/__init__.py +278 -0
- package/{tools → latticeai/tools}/commands.py +67 -7
- package/{tools → latticeai/tools}/computer.py +1 -1
- package/{tools → latticeai/tools}/documents.py +1 -1
- package/{tools → latticeai/tools}/filesystem.py +3 -3
- package/latticeai/tools/knowledge.py +178 -0
- package/{tools → latticeai/tools}/local_files.py +1 -1
- package/{tools → latticeai/tools}/network.py +0 -1
- package/local_knowledge_api.py +4 -342
- package/package.json +22 -2
- package/scripts/brain_quality_eval.py +3 -1
- package/scripts/bump_version.py +3 -0
- package/scripts/capture_release_evidence.mjs +180 -0
- package/scripts/check_current_release_docs.mjs +142 -0
- package/scripts/check_i18n_literals.mjs +107 -31
- package/scripts/check_openapi_drift.mjs +56 -0
- package/scripts/export_openapi.py +67 -7
- package/scripts/i18n_literal_allowlist.json +22 -24
- package/scripts/run_integration_tests.mjs +72 -10
- package/scripts/validate_release_artifacts.py +49 -7
- package/scripts/wheel_smoke.py +5 -0
- package/setup_wizard.py +3 -1260
- package/src-tauri/Cargo.lock +1 -1
- package/src-tauri/Cargo.toml +1 -1
- package/src-tauri/tauri.conf.json +1 -1
- package/static/app/asset-manifest.json +11 -11
- package/static/app/assets/Act-C3dBrWE-.js +1 -0
- package/static/app/assets/Brain-DBYgdcjt.js +321 -0
- package/static/app/assets/Capture-Cf3hqRtN.js +1 -0
- package/static/app/assets/Library-CFfkNn3s.js +1 -0
- package/static/app/assets/System-BOurbT-v.js +1 -0
- package/static/app/assets/index-A3M9sElj.js +17 -0
- package/static/app/assets/index-Bmx9rzTc.css +2 -0
- package/static/app/assets/primitives-DcUUmhdC.js +1 -0
- package/static/app/assets/textarea-BklR6zN4.js +1 -0
- package/static/app/index.html +2 -2
- package/static/sw.js +1 -1
- package/tools/__init__.py +21 -269
- package/docs/CODE_REVIEW_2026-07-06.md +0 -764
- package/latticeai/runtime/app_context_runtime.py +0 -13
- package/latticeai/runtime/tail_wiring.py +0 -21
- package/scripts/com.pts.claudecode.discord.plist +0 -31
- package/scripts/pts-claudecode-discord-bridge.mjs +0 -207
- package/scripts/start-pts-claudecode-discord.sh +0 -51
- package/static/app/assets/Act-21lIXx2E.js +0 -1
- package/static/app/assets/Brain-BqUd5UJJ.js +0 -321
- package/static/app/assets/Capture-BA7Z2Q1u.js +0 -1
- package/static/app/assets/Library-bFMtyni3.js +0 -1
- package/static/app/assets/System-K6krGCqn.js +0 -1
- package/static/app/assets/index-C4R3ws30.js +0 -17
- package/static/app/assets/index-ChSeOB02.css +0 -2
- package/static/app/assets/primitives-sQU3it5I.js +0 -1
- package/static/app/assets/textarea-DK3Fd_lR.js +0 -1
- package/tools/knowledge.py +0 -95
|
@@ -2,39 +2,71 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
from
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from typing import TYPE_CHECKING, Any, Optional
|
|
7
|
+
|
|
8
|
+
from latticeai.runtime.stages import RuntimeStage
|
|
6
9
|
|
|
7
10
|
if TYPE_CHECKING:
|
|
8
11
|
from latticeai.core.config import Config
|
|
9
12
|
|
|
10
13
|
|
|
11
|
-
|
|
14
|
+
@dataclass(frozen=True)
|
|
15
|
+
class ConfigRuntime(RuntimeStage):
|
|
16
|
+
CONFIG: Any
|
|
17
|
+
APP_MODE: str
|
|
18
|
+
IS_PUBLIC_MODE: bool
|
|
19
|
+
DEFAULT_HOST: str
|
|
20
|
+
DEFAULT_PORT: int
|
|
21
|
+
NETWORK_EXPOSED: bool
|
|
22
|
+
ENABLE_TELEGRAM: bool
|
|
23
|
+
ENABLE_GRAPH: bool
|
|
24
|
+
AUTOLOAD_MODELS: bool
|
|
25
|
+
MODEL_IDLE_UNLOAD_SECONDS: int
|
|
26
|
+
ALLOW_LOCAL_MODELS: bool
|
|
27
|
+
REQUIRE_AUTH: bool
|
|
28
|
+
ALLOW_PLAINTEXT_API_KEYS: bool
|
|
29
|
+
CORS_ALLOW_NETWORK: bool
|
|
30
|
+
CORS_EXTRA_ORIGINS: Any
|
|
31
|
+
PUBLIC_MODEL: str
|
|
32
|
+
LOCAL_MODEL: str
|
|
33
|
+
LOCAL_DRAFT_MODEL: str
|
|
34
|
+
TIMEZONE: str
|
|
35
|
+
MAX_LOCAL_MODELS: int
|
|
36
|
+
ALLOW_MODEL_DOWNLOADS: bool
|
|
37
|
+
MODEL_DOWNLOAD_TIMEOUT: int
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def build_config_runtime(config: "Optional[Config]" = None) -> ConfigRuntime:
|
|
12
41
|
"""Build app configuration values without importing model/runtime code."""
|
|
13
42
|
|
|
14
43
|
from latticeai.core.config import Config
|
|
15
44
|
|
|
16
45
|
cfg = config if config is not None else Config.from_env()
|
|
17
|
-
return
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
46
|
+
return ConfigRuntime(
|
|
47
|
+
CONFIG=cfg,
|
|
48
|
+
APP_MODE=cfg.app_mode,
|
|
49
|
+
IS_PUBLIC_MODE=cfg.is_public,
|
|
50
|
+
DEFAULT_HOST=cfg.host,
|
|
51
|
+
DEFAULT_PORT=cfg.port,
|
|
52
|
+
NETWORK_EXPOSED=cfg.network_exposed,
|
|
53
|
+
ENABLE_TELEGRAM=cfg.enable_telegram,
|
|
54
|
+
ENABLE_GRAPH=cfg.enable_graph,
|
|
55
|
+
AUTOLOAD_MODELS=cfg.autoload_models,
|
|
56
|
+
MODEL_IDLE_UNLOAD_SECONDS=cfg.model_idle_unload_seconds,
|
|
57
|
+
ALLOW_LOCAL_MODELS=cfg.allow_local_models,
|
|
58
|
+
REQUIRE_AUTH=cfg.require_auth,
|
|
59
|
+
ALLOW_PLAINTEXT_API_KEYS=cfg.allow_plaintext_api_keys,
|
|
60
|
+
CORS_ALLOW_NETWORK=cfg.cors_allow_network,
|
|
61
|
+
CORS_EXTRA_ORIGINS=cfg.cors_extra_origins,
|
|
62
|
+
PUBLIC_MODEL=cfg.public_model,
|
|
63
|
+
LOCAL_MODEL=cfg.local_model,
|
|
64
|
+
LOCAL_DRAFT_MODEL=cfg.local_draft_model,
|
|
65
|
+
TIMEZONE=cfg.timezone,
|
|
66
|
+
MAX_LOCAL_MODELS=cfg.max_local_models,
|
|
67
|
+
ALLOW_MODEL_DOWNLOADS=cfg.allow_model_downloads,
|
|
68
|
+
MODEL_DOWNLOAD_TIMEOUT=cfg.model_download_timeout,
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
__all__ = ["ConfigRuntime", "build_config_runtime"]
|
|
@@ -23,16 +23,28 @@ def build_context_runtime(
|
|
|
23
23
|
search_service = SearchService(graph_store=graph_store)
|
|
24
24
|
brain_memory = BrainMemory(ingestion_pipeline)
|
|
25
25
|
|
|
26
|
-
def scoped_hybrid_search(q, user_email=None, **kw):
|
|
26
|
+
def scoped_hybrid_search(q, user_email=None, workspace_id=None, **kw):
|
|
27
27
|
allowed = None
|
|
28
|
-
if require_auth
|
|
29
|
-
|
|
28
|
+
if require_auth:
|
|
29
|
+
if workspace_id is not None:
|
|
30
|
+
allowed = {workspace_id}
|
|
31
|
+
elif user_email:
|
|
32
|
+
allowed = allowed_scopes_for_user(user_email)
|
|
30
33
|
return search_service.hybrid_search(q, allowed_workspaces=allowed, **kw)
|
|
31
34
|
|
|
35
|
+
def scoped_notes_context(q, user_email=None, workspace_id=None, **kw):
|
|
36
|
+
allowed = None
|
|
37
|
+
if require_auth:
|
|
38
|
+
if workspace_id is not None:
|
|
39
|
+
allowed = {workspace_id}
|
|
40
|
+
elif user_email:
|
|
41
|
+
allowed = allowed_scopes_for_user(user_email)
|
|
42
|
+
return gardener.get_relevant_context(q, allowed_workspaces=allowed, **kw)
|
|
43
|
+
|
|
32
44
|
context_assembler = ContextAssembler(
|
|
33
45
|
memory_recall=memory_service.recall,
|
|
34
46
|
hybrid_search=scoped_hybrid_search,
|
|
35
|
-
notes_context=
|
|
47
|
+
notes_context=scoped_notes_context,
|
|
36
48
|
)
|
|
37
49
|
|
|
38
50
|
return {
|
|
@@ -21,7 +21,7 @@ def build_hooks_runtime(
|
|
|
21
21
|
"""Construct the hooks registry and local-knowledge watcher behind one seam."""
|
|
22
22
|
|
|
23
23
|
from lattice_brain.runtime.hooks import HooksRegistry
|
|
24
|
-
from
|
|
24
|
+
from latticeai.services.local_knowledge import LocalKnowledgeWatcher
|
|
25
25
|
|
|
26
26
|
hooks_registry = HooksRegistry(data_dir / "hooks.json")
|
|
27
27
|
local_kg_watcher = (
|
|
@@ -2,14 +2,28 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
from dataclasses import dataclass
|
|
5
6
|
from typing import Any
|
|
6
7
|
|
|
7
8
|
from latticeai.runtime.platform_services_runtime import build_model_service
|
|
8
9
|
|
|
9
10
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
@dataclass(frozen=True)
|
|
12
|
+
class ModelRuntime:
|
|
13
|
+
"""Typed model-provider stage registered with the HTTP application."""
|
|
14
|
+
|
|
15
|
+
router: Any
|
|
16
|
+
runtime_service: Any
|
|
17
|
+
service: Any
|
|
18
|
+
runtime_features: Any
|
|
19
|
+
is_public: bool
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def configure_model_runtime_from_context(**kwargs: Any) -> Any:
|
|
23
|
+
"""Build and return an isolated model runtime from app-owned values."""
|
|
24
|
+
|
|
25
|
+
build_model_runtime = kwargs.pop("build_model_runtime")
|
|
26
|
+
return build_model_runtime(**kwargs)
|
|
13
27
|
|
|
14
28
|
|
|
15
29
|
def register_model_runtime_routers(
|
|
@@ -19,10 +33,11 @@ def register_model_runtime_routers(
|
|
|
19
33
|
create_models_router: Any,
|
|
20
34
|
register_health_and_model_routers: Any,
|
|
21
35
|
model_router: Any,
|
|
36
|
+
runtime_service: Any,
|
|
22
37
|
runtime_features: Any,
|
|
23
38
|
is_public_mode: bool,
|
|
24
39
|
**kwargs: Any,
|
|
25
|
-
) ->
|
|
40
|
+
) -> ModelRuntime:
|
|
26
41
|
model_service = build_model_service(
|
|
27
42
|
model_router=model_router,
|
|
28
43
|
runtime_features=runtime_features,
|
|
@@ -37,4 +52,17 @@ def register_model_runtime_routers(
|
|
|
37
52
|
is_public_mode=is_public_mode,
|
|
38
53
|
**kwargs,
|
|
39
54
|
)
|
|
40
|
-
return
|
|
55
|
+
return ModelRuntime(
|
|
56
|
+
router=model_router,
|
|
57
|
+
runtime_service=runtime_service,
|
|
58
|
+
service=model_service,
|
|
59
|
+
runtime_features=runtime_features,
|
|
60
|
+
is_public=is_public_mode,
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
__all__ = [
|
|
65
|
+
"ModelRuntime",
|
|
66
|
+
"configure_model_runtime_from_context",
|
|
67
|
+
"register_model_runtime_routers",
|
|
68
|
+
]
|
|
@@ -1,21 +1,19 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""Explicit runtime exports for the legacy :mod:`server_app` facade.
|
|
2
2
|
|
|
3
|
-
The
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
assembly scratch values do not leak into ``server_app.__getattr__``.
|
|
3
|
+
The composition root must never export ``locals()``. Every compatibility name
|
|
4
|
+
is selected here and every typed assembly stage remains available through the
|
|
5
|
+
``RuntimeBundle`` without leaking construction scratch state.
|
|
7
6
|
"""
|
|
8
7
|
|
|
9
8
|
from __future__ import annotations
|
|
10
9
|
|
|
11
|
-
from dataclasses import dataclass
|
|
12
|
-
from types import ModuleType
|
|
10
|
+
from dataclasses import dataclass
|
|
13
11
|
from typing import Any, Dict, Mapping
|
|
14
12
|
|
|
15
13
|
|
|
16
14
|
@dataclass(frozen=True)
|
|
17
15
|
class RuntimeBundle:
|
|
18
|
-
"""Typed
|
|
16
|
+
"""Typed application assembly result and its five explicit stages."""
|
|
19
17
|
|
|
20
18
|
app: Any
|
|
21
19
|
CONFIG: Any
|
|
@@ -29,26 +27,45 @@ class RuntimeBundle:
|
|
|
29
27
|
build_runtime: Any
|
|
30
28
|
get_shared_runtime: Any
|
|
31
29
|
create_app: Any
|
|
30
|
+
config_runtime: Any
|
|
31
|
+
security_runtime: Any
|
|
32
|
+
brain_runtime: Any
|
|
33
|
+
model_runtime: Any
|
|
34
|
+
router_bundle: Any
|
|
32
35
|
|
|
33
36
|
def as_legacy_dict(self) -> Dict[str, Any]:
|
|
34
|
-
return {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
37
|
+
return {
|
|
38
|
+
name: getattr(self, name)
|
|
39
|
+
for name in RUNTIME_BUNDLE_EXPORTS
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
@property
|
|
43
|
+
def stages(self) -> Dict[str, Any]:
|
|
44
|
+
return {
|
|
45
|
+
"config": self.config_runtime,
|
|
46
|
+
"security": self.security_runtime,
|
|
47
|
+
"brain": self.brain_runtime,
|
|
48
|
+
"models": self.model_runtime,
|
|
49
|
+
"routers": self.router_bundle,
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
RUNTIME_BUNDLE_EXPORTS = frozenset(
|
|
54
|
+
{
|
|
55
|
+
"app",
|
|
56
|
+
"CONFIG",
|
|
57
|
+
"KNOWLEDGE_GRAPH",
|
|
58
|
+
"INGESTION_PIPELINE",
|
|
59
|
+
"AGENT_RUNTIME",
|
|
60
|
+
"HOOKS_REGISTRY",
|
|
61
|
+
"REVIEW_QUEUE",
|
|
62
|
+
"AGENT_REGISTRY",
|
|
63
|
+
"model_router",
|
|
64
|
+
"build_runtime",
|
|
65
|
+
"get_shared_runtime",
|
|
66
|
+
"create_app",
|
|
67
|
+
}
|
|
68
|
+
)
|
|
52
69
|
|
|
53
70
|
LEGACY_UNDERSCORE_EXPORTS = {
|
|
54
71
|
"_LOCAL_WRITE_BLOCKED_PREFIXES",
|
|
@@ -102,72 +119,45 @@ LEGACY_PUBLIC_EXPORTS = {
|
|
|
102
119
|
}
|
|
103
120
|
|
|
104
121
|
|
|
105
|
-
def _is_internal_runtime_dict(name: str, value: Any) -> bool:
|
|
106
|
-
if not isinstance(value, dict):
|
|
107
|
-
return False
|
|
108
|
-
if name in {"_RUNTIME_BUNDLE"}:
|
|
109
|
-
return False
|
|
110
|
-
return (
|
|
111
|
-
name.endswith("_runtime")
|
|
112
|
-
or name.endswith("_router_bundle")
|
|
113
|
-
or name.endswith("_rt")
|
|
114
|
-
or name
|
|
115
|
-
in {
|
|
116
|
-
"_mcp_state",
|
|
117
|
-
"_garden_import",
|
|
118
|
-
"_foundation_router_bundle",
|
|
119
|
-
"_static_routes_bundle",
|
|
120
|
-
"_vpc_runtime",
|
|
121
|
-
"_sso_runtime",
|
|
122
|
-
"_security_runtime",
|
|
123
|
-
"_session_runtime",
|
|
124
|
-
"_config_runtime",
|
|
125
|
-
"_context_runtime",
|
|
126
|
-
"_brain_runtime",
|
|
127
|
-
"_hooks_runtime",
|
|
128
|
-
"_history_query_runtime",
|
|
129
|
-
"_persistence_runtime",
|
|
130
|
-
"_platform_automation_runtime",
|
|
131
|
-
"_user_key_runtime",
|
|
132
|
-
"_web_runtime",
|
|
133
|
-
}
|
|
134
|
-
)
|
|
135
|
-
|
|
136
|
-
|
|
137
122
|
def build_runtime_namespace(
|
|
138
|
-
|
|
139
|
-
*,
|
|
140
|
-
runtime_bundle: RuntimeBundle | Mapping[str, Any],
|
|
123
|
+
*, runtime_bundle: RuntimeBundle | Mapping[str, Any], legacy_exports: Mapping[str, Any]
|
|
141
124
|
) -> Dict[str, Any]:
|
|
142
|
-
"""Return
|
|
125
|
+
"""Return only explicit compatibility exports and typed bundle handles."""
|
|
143
126
|
legacy_bundle = (
|
|
144
127
|
runtime_bundle.as_legacy_dict()
|
|
145
128
|
if isinstance(runtime_bundle, RuntimeBundle)
|
|
146
129
|
else dict(runtime_bundle)
|
|
147
130
|
)
|
|
148
131
|
exported: Dict[str, Any] = dict(legacy_bundle)
|
|
149
|
-
allowed =
|
|
150
|
-
|
|
132
|
+
allowed = LEGACY_PUBLIC_EXPORTS | LEGACY_UNDERSCORE_EXPORTS
|
|
133
|
+
unexpected = set(legacy_exports) - allowed
|
|
134
|
+
if unexpected:
|
|
135
|
+
raise ValueError(f"unapproved runtime exports: {sorted(unexpected)}")
|
|
136
|
+
for name in sorted(allowed):
|
|
151
137
|
if name in exported:
|
|
152
138
|
continue
|
|
153
|
-
|
|
154
|
-
continue
|
|
155
|
-
value = local_namespace.get(name)
|
|
139
|
+
value = legacy_exports.get(name)
|
|
156
140
|
if value is None:
|
|
157
141
|
continue
|
|
158
|
-
if isinstance(value, ModuleType):
|
|
159
|
-
continue
|
|
160
|
-
if _is_internal_runtime_dict(name, value):
|
|
161
|
-
continue
|
|
162
142
|
exported[name] = value
|
|
163
143
|
exported["RUNTIME_BUNDLE"] = runtime_bundle
|
|
164
144
|
exported["_RUNTIME_BUNDLE"] = legacy_bundle
|
|
165
145
|
return exported
|
|
166
146
|
|
|
167
147
|
|
|
148
|
+
SERVER_APP_EXPORTS = frozenset(
|
|
149
|
+
RUNTIME_BUNDLE_EXPORTS
|
|
150
|
+
| LEGACY_PUBLIC_EXPORTS
|
|
151
|
+
| LEGACY_UNDERSCORE_EXPORTS
|
|
152
|
+
| {"RUNTIME_BUNDLE", "_RUNTIME_BUNDLE"}
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
|
|
168
156
|
__all__ = [
|
|
169
|
-
"INTERNAL_RUNTIME_NAMES",
|
|
170
157
|
"LEGACY_UNDERSCORE_EXPORTS",
|
|
158
|
+
"LEGACY_PUBLIC_EXPORTS",
|
|
159
|
+
"RUNTIME_BUNDLE_EXPORTS",
|
|
171
160
|
"RuntimeBundle",
|
|
161
|
+
"SERVER_APP_EXPORTS",
|
|
172
162
|
"build_runtime_namespace",
|
|
173
163
|
]
|
|
@@ -24,13 +24,13 @@ def build_platform_automation_runtime(
|
|
|
24
24
|
agent_registry: Any,
|
|
25
25
|
data_dir: Any,
|
|
26
26
|
append_audit_event: Callable[..., Any],
|
|
27
|
+
memory_service: Any = None,
|
|
27
28
|
tz_name: Optional[str] = None,
|
|
28
29
|
) -> Dict[str, Any]:
|
|
29
30
|
"""Build platform services, automation services, and hook bindings.
|
|
30
31
|
|
|
31
|
-
The returned names intentionally match the
|
|
32
|
-
|
|
33
|
-
``server_app`` compatibility surface.
|
|
32
|
+
The returned names intentionally match the explicit composition-root
|
|
33
|
+
bindings consumed by the typed application stages.
|
|
34
34
|
"""
|
|
35
35
|
from latticeai.runtime.automation_runtime import build_automation_runtime
|
|
36
36
|
from latticeai.services.platform_runtime import PlatformRuntime
|
|
@@ -65,6 +65,7 @@ def build_platform_automation_runtime(
|
|
|
65
65
|
llm_generate=_llm_generate_sync,
|
|
66
66
|
llm_available=lambda: bool(getattr(model_router, "current_model_id", None)),
|
|
67
67
|
agent_registry=agent_registry,
|
|
68
|
+
memory_recall=memory_service.recall if memory_service is not None else None,
|
|
68
69
|
)
|
|
69
70
|
|
|
70
71
|
automation_runtime = build_automation_runtime(
|
|
@@ -8,17 +8,33 @@ exact include order while creating a narrow seam for the later
|
|
|
8
8
|
|
|
9
9
|
from __future__ import annotations
|
|
10
10
|
|
|
11
|
+
from dataclasses import dataclass
|
|
11
12
|
from typing import Any
|
|
12
13
|
|
|
13
14
|
from latticeai.services.router_context import InteractionRouterContext
|
|
14
15
|
|
|
15
16
|
|
|
17
|
+
@dataclass(frozen=True)
|
|
18
|
+
class RouterBundle:
|
|
19
|
+
"""Final typed router stage after all domain routers are registered."""
|
|
20
|
+
|
|
21
|
+
app: Any
|
|
22
|
+
context: Any
|
|
23
|
+
route_count: int
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def build_router_bundle(app: Any, context: Any) -> RouterBundle:
|
|
27
|
+
return RouterBundle(app=app, context=context, route_count=len(getattr(app, "routes", ())))
|
|
28
|
+
|
|
29
|
+
|
|
16
30
|
def build_static_routes_bundle(
|
|
17
31
|
*,
|
|
18
32
|
create_static_routes_router: Any,
|
|
19
33
|
static_dir: Any,
|
|
20
34
|
invite_gate_enabled: bool,
|
|
21
35
|
invite_code: str,
|
|
36
|
+
invite_cookie_secret: str,
|
|
37
|
+
secure_cookies: bool,
|
|
22
38
|
app_mode: str,
|
|
23
39
|
model_router: Any,
|
|
24
40
|
require_user: Any,
|
|
@@ -29,6 +45,8 @@ def build_static_routes_bundle(
|
|
|
29
45
|
static_dir=static_dir,
|
|
30
46
|
invite_gate_enabled=invite_gate_enabled,
|
|
31
47
|
invite_code=invite_code,
|
|
48
|
+
invite_cookie_secret=invite_cookie_secret,
|
|
49
|
+
secure_cookies=secure_cookies,
|
|
32
50
|
app_mode=app_mode,
|
|
33
51
|
model_router=model_router,
|
|
34
52
|
require_user=require_user,
|
|
@@ -37,6 +55,7 @@ def build_static_routes_bundle(
|
|
|
37
55
|
"STATIC_ROUTES": static_routes,
|
|
38
56
|
"ui_file_response": static_routes.ui_file_response,
|
|
39
57
|
"local_sysinfo": static_routes.local_sysinfo,
|
|
58
|
+
"invite_authorized": static_routes.invite_authorized,
|
|
40
59
|
}
|
|
41
60
|
|
|
42
61
|
|
|
@@ -61,6 +80,8 @@ def build_auth_admin_security_router_bundle(
|
|
|
61
80
|
open_registration: bool,
|
|
62
81
|
session_ttl: int,
|
|
63
82
|
require_auth: bool,
|
|
83
|
+
secure_cookies: bool,
|
|
84
|
+
invite_authorized: Any,
|
|
64
85
|
ensure_identity: Any,
|
|
65
86
|
create_admin_router: Any,
|
|
66
87
|
require_admin: Any,
|
|
@@ -113,6 +134,9 @@ def build_auth_admin_security_router_bundle(
|
|
|
113
134
|
open_registration=open_registration,
|
|
114
135
|
session_ttl=session_ttl,
|
|
115
136
|
require_auth=require_auth,
|
|
137
|
+
secure_cookies=secure_cookies,
|
|
138
|
+
invite_gate_enabled=invite_gate_enabled,
|
|
139
|
+
invite_authorized=invite_authorized,
|
|
116
140
|
ensure_identity=ensure_identity,
|
|
117
141
|
)
|
|
118
142
|
|
|
@@ -290,8 +314,9 @@ def register_platform_feature_routers(
|
|
|
290
314
|
require_user=require_user,
|
|
291
315
|
require_admin=require_admin,
|
|
292
316
|
append_audit_event=append_audit_event,
|
|
317
|
+
gate_write=platform.gate_write,
|
|
293
318
|
register_skill=platform.register_plugin_skill,
|
|
294
|
-
plugin_runners_factory=
|
|
319
|
+
plugin_runners_factory=platform.plugin_capability_runners,
|
|
295
320
|
ui_file_response=ui_file_response,
|
|
296
321
|
static_dir=static_dir,
|
|
297
322
|
),
|
|
@@ -356,6 +381,7 @@ def register_health_and_model_routers(
|
|
|
356
381
|
create_models_router: Any,
|
|
357
382
|
model_router: Any,
|
|
358
383
|
require_user: Any,
|
|
384
|
+
require_admin: Any,
|
|
359
385
|
load_users: Any,
|
|
360
386
|
get_user_role: Any,
|
|
361
387
|
install_engine: Any,
|
|
@@ -391,6 +417,7 @@ def register_health_and_model_routers(
|
|
|
391
417
|
create_models_router(
|
|
392
418
|
model_router=model_router,
|
|
393
419
|
require_user=require_user,
|
|
420
|
+
require_admin=require_admin,
|
|
394
421
|
get_current_user=get_current_user,
|
|
395
422
|
load_users=load_users,
|
|
396
423
|
get_user_role=get_user_role,
|
|
@@ -469,6 +496,7 @@ def register_interaction_routers(
|
|
|
469
496
|
require_user = interaction_context.require_user
|
|
470
497
|
embedding_info = interaction_context.embedding_info
|
|
471
498
|
tool_context = interaction_context.tool_context
|
|
499
|
+
require_admin = tool_context.require_admin
|
|
472
500
|
get_current_user = tool_context.get_current_user
|
|
473
501
|
append_audit_event = tool_context.append_audit_event
|
|
474
502
|
hooks = interaction_context.hooks
|
|
@@ -515,11 +543,13 @@ def register_interaction_routers(
|
|
|
515
543
|
create_hooks_router(
|
|
516
544
|
registry=hooks,
|
|
517
545
|
require_user=require_user,
|
|
546
|
+
require_admin=require_admin,
|
|
518
547
|
append_audit_event=append_audit_event,
|
|
519
548
|
),
|
|
520
549
|
create_agent_registry_router(
|
|
521
550
|
registry=agent_registry,
|
|
522
551
|
require_user=require_user,
|
|
552
|
+
require_admin=require_admin,
|
|
523
553
|
append_audit_event=append_audit_event,
|
|
524
554
|
),
|
|
525
555
|
create_memory_router(
|
|
@@ -546,6 +576,7 @@ def register_review_and_brain_tail_routers(
|
|
|
546
576
|
append_audit_event: Any,
|
|
547
577
|
create_browser_router: Any,
|
|
548
578
|
ingestion_pipeline: Any,
|
|
579
|
+
workspace_service: Any,
|
|
549
580
|
create_portability_router: Any,
|
|
550
581
|
kg_portability: Any,
|
|
551
582
|
require_admin: Any,
|
|
@@ -573,6 +604,7 @@ def register_review_and_brain_tail_routers(
|
|
|
573
604
|
create_browser_router(
|
|
574
605
|
pipeline=ingestion_pipeline,
|
|
575
606
|
require_user=require_user,
|
|
607
|
+
workspace_service=workspace_service,
|
|
576
608
|
),
|
|
577
609
|
create_portability_router(
|
|
578
610
|
service=kg_portability,
|
|
@@ -591,6 +623,7 @@ def register_review_and_brain_tail_routers(
|
|
|
591
623
|
network=brain_network,
|
|
592
624
|
identity=device_identity,
|
|
593
625
|
require_user=require_user,
|
|
626
|
+
require_admin=require_admin,
|
|
594
627
|
),
|
|
595
628
|
create_garden_router(gardener=gardener, require_user=require_user),
|
|
596
629
|
create_setup_router(model_router=model_router, require_user=require_user),
|