ltcai 8.1.0 → 8.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.
Files changed (110) hide show
  1. package/README.md +20 -41
  2. package/docs/CHANGELOG.md +38 -874
  3. package/docs/DEVELOPMENT.md +26 -3
  4. package/docs/LEGACY_COMPATIBILITY.md +3 -1
  5. package/docs/TRUST_MODEL.md +26 -26
  6. package/docs/WHY_LATTICE.md +28 -25
  7. package/docs/kg-schema.md +6 -4
  8. package/lattice_brain/__init__.py +1 -1
  9. package/lattice_brain/graph/schema.py +6 -0
  10. package/lattice_brain/runtime/multi_agent.py +1 -1
  11. package/latticeai/__init__.py +1 -1
  12. package/latticeai/api/computer_use.py +2 -0
  13. package/latticeai/api/memory.py +13 -0
  14. package/latticeai/app_factory.py +30 -28
  15. package/latticeai/brain/__init__.py +1 -1
  16. package/latticeai/core/config.py +10 -0
  17. package/latticeai/core/marketplace.py +1 -1
  18. package/latticeai/core/tool_registry.py +10 -0
  19. package/latticeai/core/workspace_graph_trace.py +132 -0
  20. package/latticeai/core/workspace_memory.py +75 -0
  21. package/latticeai/core/workspace_os.py +135 -1283
  22. package/latticeai/core/workspace_os_utils.py +132 -0
  23. package/latticeai/core/workspace_permissions.py +99 -0
  24. package/latticeai/core/workspace_plugins.py +97 -0
  25. package/latticeai/core/workspace_runs.py +612 -0
  26. package/latticeai/core/workspace_skills.py +114 -0
  27. package/latticeai/core/workspace_snapshots.py +195 -0
  28. package/latticeai/core/workspace_timeline.py +107 -0
  29. package/latticeai/runtime/audit_runtime.py +64 -0
  30. package/latticeai/runtime/config_runtime.py +4 -0
  31. package/latticeai/runtime/sso_runtime.py +52 -0
  32. package/latticeai/services/architecture_readiness.py +3 -3
  33. package/latticeai/services/memory_service.py +215 -7
  34. package/latticeai/services/model_capability_registry.py +68 -0
  35. package/latticeai/services/model_engines.py +603 -0
  36. package/latticeai/services/model_loading.py +482 -0
  37. package/latticeai/services/model_recommendation.py +5 -0
  38. package/latticeai/services/model_runtime.py +141 -866
  39. package/latticeai/services/product_readiness.py +19 -18
  40. package/package.json +1 -1
  41. package/src-tauri/Cargo.lock +1 -1
  42. package/src-tauri/Cargo.toml +1 -1
  43. package/src-tauri/tauri.conf.json +1 -1
  44. package/static/app/asset-manifest.json +11 -11
  45. package/static/app/assets/{Act-BOO66G-c.js → Act-D9jIknFd.js} +1 -1
  46. package/static/app/assets/{Brain-C6lEYiD7.js → Brain-CFOtWbPN.js} +1 -1
  47. package/static/app/assets/{Capture-TATXBRDw.js → Capture-Q4WYzwr5.js} +1 -1
  48. package/static/app/assets/{Library-DK4FIp8a.js → Library-C5Q2yWee.js} +1 -1
  49. package/static/app/assets/{System-Bgs6Ql7x.js → System-BLbjdr1_.js} +1 -1
  50. package/static/app/assets/index-BqammyNu.js +16 -0
  51. package/static/app/assets/index-ty1iGgZu.css +2 -0
  52. package/static/app/assets/{primitives-B70WOra0.js → primitives-Br8uSfZ4.js} +1 -1
  53. package/static/app/assets/{textarea-Czrd9gwM.js → textarea-BnhNs1_X.js} +1 -1
  54. package/static/app/index.html +2 -2
  55. package/static/sw.js +1 -1
  56. package/tools/__init__.py +2 -1
  57. package/tools/computer.py +21 -0
  58. package/docs/CARRYOVER_AUDIT_v3.6.0.md +0 -61
  59. package/docs/HANDOVER_v3.6.0.md +0 -46
  60. package/docs/RUNTIME_HOOK_COVERAGE_v3.5.0.md +0 -56
  61. package/docs/RUNTIME_HOOK_COVERAGE_v3.6.0.md +0 -49
  62. package/docs/V2_ARCHITECTURE.md +0 -561
  63. package/docs/V3_2_AUDIT.md +0 -82
  64. package/docs/V3_BACKEND_ARCHITECTURE.md +0 -138
  65. package/docs/V3_FRONTEND.md +0 -146
  66. package/docs/V4_1_FRONTEND_ARCHITECTURE_REVIEW.md +0 -65
  67. package/docs/V4_1_FRONTEND_MIGRATION_REPORT.md +0 -70
  68. package/docs/V4_1_VALIDATION_REPORT.md +0 -47
  69. package/docs/V4_2_BRAIN_CORE_ARCHITECTURE.md +0 -97
  70. package/docs/V4_2_STORAGE_MIGRATION_REPORT.md +0 -91
  71. package/docs/V4_2_VALIDATION_REPORT.md +0 -89
  72. package/docs/V4_3_2_DEADCODE_AUDIT_REPORT.md +0 -174
  73. package/docs/V4_3_2_DOCUMENTATION_CLEANUP_REPORT.md +0 -81
  74. package/docs/V4_3_2_GITHUB_VERCEL_CHECK_REPORT.md +0 -75
  75. package/docs/V4_3_2_GRAPH_UX_REPORT.md +0 -48
  76. package/docs/V4_3_2_INDEPENDENT_AUDIT_PACKAGE.md +0 -209
  77. package/docs/V4_3_2_PRODUCT_POLISH_REPORT.md +0 -57
  78. package/docs/V4_3_2_SELF_AUDIT_REPORT.md +0 -63
  79. package/docs/V4_3_2_VALIDATION_REPORT.md +0 -97
  80. package/docs/V4_3_3_VALIDATION_REPORT.md +0 -46
  81. package/docs/V4_3_PORTABILITY_ARCHITECTURE.md +0 -69
  82. package/docs/V4_3_PRIVACY_AUDIT.md +0 -60
  83. package/docs/V4_3_PRODUCT_HARDENING_REPORT.md +0 -53
  84. package/docs/V4_3_VALIDATION_REPORT.md +0 -58
  85. package/docs/V4_4_0_EXTRACTION_REPORT.md +0 -239
  86. package/docs/V4_5_0_GEMMA_RUNTIME_COMPATIBILITY_REPORT.md +0 -49
  87. package/docs/V4_5_0_GRAPH_UX_REPORT.md +0 -34
  88. package/docs/V4_5_0_MODEL_RUNTIME_UX_REPORT.md +0 -40
  89. package/docs/V4_5_0_ONBOARDING_REPORT.md +0 -31
  90. package/docs/V4_5_0_PRODUCT_EXPERIENCE_RECOVERY_REPORT.md +0 -49
  91. package/docs/V4_5_0_VALIDATION_REPORT.md +0 -60
  92. package/docs/V4_5_1_GRAPH_EXPERIENCE_REPORT.md +0 -33
  93. package/docs/V4_5_1_MODEL_EXPERIENCE_REPORT.md +0 -37
  94. package/docs/V4_5_1_NAVIGATION_REPORT.md +0 -37
  95. package/docs/V4_5_1_ONBOARDING_REPORT.md +0 -29
  96. package/docs/V4_5_1_PRODUCT_REIMAGINING_REPORT.md +0 -61
  97. package/docs/V4_5_1_RC_ARTIFACTS.md +0 -44
  98. package/docs/V4_5_1_UX_REPORT.md +0 -45
  99. package/docs/V4_5_1_VALIDATION_REPORT.md +0 -55
  100. package/docs/V4_5_1_VISUAL_DESIGN_REPORT.md +0 -30
  101. package/docs/V4_6_0_LIVING_BRAIN_EXPERIENCE_REPORT.md +0 -72
  102. package/docs/V4_6_1_RELEASE_REFRESH_REPORT.md +0 -42
  103. package/docs/V4_7_0_ADMIN_SEPARATION_REPORT.md +0 -42
  104. package/docs/V4_7_1_ADMIN_OPERATIONS_REPORT.md +0 -49
  105. package/docs/V4_7_2_INTUITIVE_BRAIN_UX_REPORT.md +0 -62
  106. package/docs/V4_BRAIN_ARCHITECTURE.md +0 -322
  107. package/docs/V4_DIGITAL_BRAIN_RECOVERY.md +0 -555
  108. package/docs/V4_IMPLEMENTATION_PLAN.md +0 -470
  109. package/static/app/assets/index-Bvv79nre.js +0 -16
  110. package/static/app/assets/index-Dslqglia.css +0 -2
@@ -1,8 +1,11 @@
1
1
  # Lattice AI Development
2
2
 
3
+ Current release: **8.2.0 - Brain Brief**.
4
+
3
5
  This document is for contributors working on the local-first Digital Brain
4
6
  codebase. Product positioning and quick start stay in `README.md`; release
5
- history stays in `docs/CHANGELOG.md` and `RELEASE.md`.
7
+ history is intentionally limited to 7.0.0-8.2.0 in `docs/CHANGELOG.md` and
8
+ `RELEASE.md`.
6
9
 
7
10
  ## Product Contract
8
11
 
@@ -77,9 +80,21 @@ Runtime assembly seams live under `latticeai.runtime`:
77
80
  - `config_runtime.py` derives app config values from `Config`;
78
81
  - `security_runtime.py` applies trusted proxy/security-derived settings;
79
82
  - `brain_runtime.py` constructs Brain Core and conversation primitives.
83
+ - model/runtime, ToolRegistry/MCP, router, static asset, and lifespan seams
84
+ should continue moving out of monolithic app-factory helpers.
85
+
86
+ Future extraction should continue with AgentRuntime, ToolRegistry, config,
87
+ server decomposition, and Knowledge Graph stabilization in that order when
88
+ architectural debt is present.
89
+
90
+ ## Runtime Hook Coverage
80
91
 
81
- Future extraction should continue with router assembly, model runtime assembly,
82
- platform/hooks assembly, static asset serving, and lifespan/startup/shutdown.
92
+ Knowledge Graph ingestion paths must continue to pass through the shared
93
+ pre-tool/post-tool lifecycle:
94
+
95
+ - browser `read-url` ingestion dispatches `tool.kg_ingest.*` events;
96
+ - browser `ingest-current-tab` ingestion dispatches the same lifecycle;
97
+ - `IngestionPipeline` remains the common ingestion boundary behind those routes.
83
98
 
84
99
  ## Documentation Sync
85
100
 
@@ -96,3 +111,11 @@ For user-facing, API, runtime, release, or packaging changes, check:
96
111
 
97
112
  Release/publish examples must use exact target-version filenames. Do not
98
113
  document wildcard artifact upload commands.
114
+
115
+ For 8.2.0 release work, exact artifacts are:
116
+
117
+ - `dist/ltcai-8.2.0-py3-none-any.whl`
118
+ - `dist/ltcai-8.2.0.tar.gz`
119
+ - `ltcai-8.2.0.tgz`
120
+ - `dist/ltcai-8.2.0.vsix`
121
+ - `src-tauri/target/release/bundle/dmg/Lattice AI_8.2.0_aarch64.dmg`
@@ -1,10 +1,12 @@
1
1
  # Legacy Compatibility Map
2
2
 
3
+ Current release: **8.2.0 - Brain Brief**.
4
+
3
5
  Lattice AI is moving toward a smaller, modular architecture centered on
4
6
  `lattice_brain`, `latticeai.services`, `latticeai.api`, and `latticeai.runtime`.
5
7
  Some root-level modules remain packaged for compatibility with older imports,
6
8
  CLI entrypoints, or extension workflows. Their presence does not define the
7
- current architecture.
9
+ current 8.2.0 architecture.
8
10
 
9
11
  ## Current Policy
10
12
 
@@ -1,7 +1,9 @@
1
1
  # Lattice AI Trust Model
2
2
 
3
- Lattice AI's trust model is local-first, opt-in for external communication, and
4
- honest when something is unavailable.
3
+ Current release: **8.2.0 - Brain Brief**.
4
+
5
+ Lattice AI is local-first, explicit about external communication, and honest
6
+ when a capability is unavailable.
5
7
 
6
8
  ## Local By Default
7
9
 
@@ -9,58 +11,56 @@ By default, Lattice AI binds the API to `127.0.0.1`, stores Brain data under the
9
11
  local data directory, and does not send prompts, documents, graph content, or
10
12
  archives to Lattice-owned servers.
11
13
 
12
- Local data includes:
14
+ Local data can include:
13
15
 
14
- - local profile and sessions;
15
- - conversations and memory records;
16
- - Knowledge Graph nodes, edges, provenance, and search indexes;
17
- - uploaded document blobs;
16
+ - profile and session metadata;
17
+ - conversations, memories, decisions, and workflow history;
18
+ - Knowledge Graph nodes, edges, provenance, and indexes;
19
+ - uploaded document blobs and extracted text;
18
20
  - audit and admin operation logs;
19
21
  - backups and encrypted `.latticebrain` archives.
20
22
 
21
23
  ## Explicit External Paths
22
24
 
23
- Some features can contact third parties, but they require explicit user/admin
24
- action or configuration:
25
+ External communication requires configuration plus a user/admin action:
25
26
 
26
- - model downloads from model registries;
27
- - cloud model API calls after keys are configured and a cloud model is chosen;
27
+ - cloud model calls after keys are configured and a cloud model is selected;
28
+ - model downloads from registries after install consent;
28
29
  - Telegram bridge after the integration is enabled;
29
- - Brain Network peer actions after pairing/initiating network flows;
30
+ - Brain Network peer actions after pairing;
30
31
  - Docker/Postgres setup after opt-in scale configuration;
31
- - update checks only when update checking is enabled;
32
- - remote marketplace/registry refreshes only through explicit user actions.
32
+ - update checks only when enabled;
33
+ - marketplace or remote registry refreshes only when invoked.
33
34
 
34
35
  Token presence alone must not start external communication.
35
36
 
36
37
  ## Consent And Honesty Gates
37
38
 
38
- Lattice AI should fail closed or report unavailable state for:
39
+ Lattice AI should fail closed or show an unavailable state for:
39
40
 
40
41
  - no model loaded;
41
- - local model not installed;
42
- - installed model not loaded;
42
+ - local model not installed or not loaded;
43
43
  - missing cloud key;
44
44
  - deterministic/model-free preview;
45
45
  - dry-run versus real execution;
46
46
  - no graph/context evidence available;
47
47
  - unavailable external integration;
48
48
  - wrong archive passphrase;
49
- - archive path traversal or tampering.
49
+ - archive tampering, unsupported archive versions, or path traversal.
50
50
 
51
- ## Admin Boundary
51
+ ## Product Boundary
52
52
 
53
- The normal user product is Brain Chat, memory, topics, relationships, graph
54
- exploration, model state, and Brain ownership. Admin Console is for users,
53
+ Normal Brain use is conversation, memory, topics, relationships, model state,
54
+ source capture, and Knowledge Graph exploration. Admin Console is for users,
55
55
  roles, audit logs, security events, retention, and operations. Admin visibility
56
56
  does not mean secrets should appear in clear text.
57
57
 
58
- ## Known Limitations
58
+ ## Known Limits
59
59
 
60
- - Local files are only as protected as the user's machine, account, backups, and
61
- disk encryption.
62
- - Cloud model prompts follow the selected provider's policy.
60
+ - Local files are only as protected as the user's machine, OS account, backups,
61
+ and disk encryption.
62
+ - Cloud model prompts follow the selected provider's policy once the user
63
+ explicitly chooses that provider.
63
64
  - A local admin can inspect local files and process memory outside Lattice AI.
64
65
  - Marketplace and model registries are third-party services when explicitly
65
66
  contacted.
66
-
@@ -1,51 +1,54 @@
1
1
  # Why Lattice AI Exists
2
2
 
3
- **Lattice AI is a local-first Digital Brain that keeps your knowledge durable across any AI model.**
3
+ Current release: **8.2.0 - Brain Brief**.
4
+
5
+ **Lattice AI is a local-first Digital Brain that keeps your knowledge durable
6
+ across any AI model.**
4
7
 
5
8
  **모델은 바꿔도, 내 지식은 남는 로컬 AI 브레인.**
6
9
 
7
- AI models change quickly. A model you use today may be replaced next month, and
8
- the conversation history, project context, decisions, and sources you built
9
- around it can become scattered across tools. Lattice AI exists so the durable
10
- asset is not the model. The durable asset is your Brain.
10
+ AI models change quickly. A model you use today may be replaced tomorrow, and a
11
+ cloud chat history can become scattered across tools. Lattice AI exists so the
12
+ durable asset is not the model. The durable asset is your Brain.
11
13
 
12
14
  ## The Problem
13
15
 
14
- Most AI products begin with a model and treat your context as temporary prompt
15
- material. That works for short questions, but it fails for long-running work:
16
+ Most AI products start with a model and treat your context as temporary prompt
17
+ material. That breaks down for real work:
16
18
 
17
19
  - project decisions disappear into old chats;
18
- - documents and notes are disconnected from conversations;
20
+ - documents and notes stay disconnected from conversations;
19
21
  - switching models often means losing useful context;
20
- - graph or database tools expose implementation details before user value;
21
- - cloud-only products make it hard to inspect, back up, or move your knowledge.
22
+ - graph tools expose implementation detail before user value;
23
+ - cloud-only products make your knowledge hard to inspect, back up, or move.
22
24
 
23
25
  ## The Lattice Answer
24
26
 
25
- Lattice AI is a local-first private AI memory layer. It keeps conversations,
26
- documents, decisions, relationships, and project history in a Brain that belongs
27
- to the user. Models can be local, cloud, current, or future. The Brain remains.
27
+ Lattice AI keeps conversations, documents, memories, decisions, relationships,
28
+ and source provenance in a private local Brain. Models can be local, cloud,
29
+ current, or future. The Brain remains.
30
+
31
+ The graph matters, but it is not the product identity. The product identity is a
32
+ local-first Digital Brain: a place where the user can talk, add sources, watch
33
+ memory grow, and inspect the Knowledge Graph when they need proof.
28
34
 
29
- The graph is real, but it is not the product identity. Product category is
30
- local-first Digital Brain; core capability is a private AI memory layer; UX
31
- metaphor is the Living Brain. Users start with Brain
32
- Chat, memory, topics, relationships, ownership, backup, and graph exploration.
33
- Advanced admin logs, roles, hooks, workflows, Telegram, Brain Network, Docker,
34
- Postgres, and plugin details stay outside the normal user flow.
35
+ In 8.2.0 the first screen is intentionally not a dashboard. The living Brain,
36
+ conversation composer, and evidence-backed Brain Brief appear together so the
37
+ user immediately knows what matters and what to do next.
35
38
 
36
39
  ## Practical Reasons To Use It
37
40
 
38
- - Ask what the team decided last week and see the source.
39
- - Drop in documents and build a searchable personal memory.
40
- - Prepare for a meeting from past notes, project decisions, and files.
41
- - Preserve context when moving from one model to another.
42
- - Export or back up the Brain as an encrypted `.latticebrain` archive.
41
+ - Ask what the team decided and see the source.
42
+ - Add documents and build a searchable private memory.
43
+ - Prepare from old notes, project decisions, and files.
44
+ - Preserve context when moving between models.
45
+ - Export or restore the Brain as an encrypted `.latticebrain` archive.
43
46
  - Use Korean or English without changing the underlying Brain.
44
47
  - Avoid fake answers when no model or evidence is available.
45
48
 
46
49
  ## What Lattice AI Is Not
47
50
 
48
- - Not a hosted SaaS by default.
51
+ - Not hosted SaaS by default.
49
52
  - Not just a model launcher.
50
53
  - Not just a graph viewer.
51
54
  - Not a generic dashboard.
package/docs/kg-schema.md CHANGED
@@ -1,4 +1,6 @@
1
- # Knowledge Graph — v2 스키마
1
+ # Knowledge Graph Schema
2
+
3
+ Current release: **8.2.0 - Brain Brief**.
2
4
 
3
5
  명세 출처: `lattice_ai_full_spec.pptx` 슬라이드 20·21·22
4
6
  구현: `kg_schema.py`
@@ -80,15 +82,15 @@ Edge {
80
82
 
81
83
  **엔드포인트 룰은 권고 사항이다 (스키마 문서 기준).** 코드에는 엔드포인트 페어
82
84
  검증기가 존재하지 않는다 — `validate_endpoints` 는 구현된 적이 없으며, 쓰기
83
- 경로는 타입 페어를 거부하지 않는다. v4 쓰기 정규화는 *타입 어휘* 를
85
+ 경로는 타입 페어를 거부하지 않는다. 현재 쓰기 정규화는 *타입 어휘* 를
84
86
  강제한다: `_upsert_edge` 가 모든 엣지 타입을 canonical `EdgeType` 값으로
85
87
  정규화하므로 자유 문자열 타입은 더 이상 생성되지 않는다.
86
88
 
87
89
  ---
88
90
 
89
- ## v3.6.0 Knowledge Graph First 엔티티/관계
91
+ ## Current Knowledge Graph First 엔티티/관계
90
92
 
91
- v3.6.0 은 "모든 데이터 소스가 Knowledge Graph 로 수렴한다"는 원칙을 1급 스키마로
93
+ 8.2.0 은 "모든 데이터 소스가 Knowledge Graph 로 수렴한다"는 원칙을 1급 스키마로
92
94
  승격한다. 아래 타입은 **추가형(additive)**이다 — 기존 enum/legacy 매핑을 깨지 않고
93
95
  `from_legacy` 가 무손실로 정규화하며, 알 수 없는 타입은 여전히 `CONCEPT`/`MENTIONS` 로
94
96
  폴백한다. 스키마는 **확장 가능**하게 유지한다: 새 도메인 엔티티는 enum 멤버 1개 +
@@ -26,7 +26,7 @@ from .storage import (
26
26
  storage_from_env,
27
27
  )
28
28
 
29
- __version__ = "8.1.0"
29
+ __version__ = "8.2.0"
30
30
 
31
31
  __all__ = [
32
32
  "AgentRuntime",
@@ -56,6 +56,12 @@ KG_SCHEMA_V2_VERSION = 2
56
56
  EMBED_DIM = int(os.getenv("LATTICEAI_EMBED_DIM", "1024"))
57
57
 
58
58
 
59
+ def set_embed_dim(dim: int) -> None:
60
+ """Optional way for upper layers to override without direct module import at top level in lattice_brain."""
61
+ global EMBED_DIM
62
+ EMBED_DIM = int(dim) # lattice_brain isolation: no direct latticeai import; callers can pre-set env if using central Config
63
+
64
+
59
65
  # ── Node / Edge taxonomy (PPT 슬라이드 20·21) ──────────────────────────────
60
66
  class NodeType(str, Enum):
61
67
  """워크스페이스의 모든 ‘명사’.
@@ -21,7 +21,7 @@ from typing import Any, Callable, Dict, List, Optional
21
21
  from .contracts import multi_agent_contract
22
22
 
23
23
 
24
- MULTI_AGENT_VERSION = "8.1.0"
24
+ MULTI_AGENT_VERSION = "8.2.0"
25
25
 
26
26
  AGENT_ROLES = ("researcher", "planner", "executor", "reviewer", "release")
27
27
  CORE_PIPELINE = ("planner", "executor", "reviewer")
@@ -1,3 +1,3 @@
1
1
  """Lattice AI - modular server package."""
2
2
 
3
- __version__ = "8.1.0"
3
+ __version__ = "8.2.0"
@@ -42,12 +42,14 @@ Available actions:
42
42
  - computer_scroll: {"action":"computer_scroll","args":{"x":500,"y":300,"direction":"down","clicks":3}}
43
43
  - computer_move: {"action":"computer_move","args":{"x":500,"y":300}}
44
44
  - computer_drag: {"action":"computer_drag","args":{"x1":100,"y1":100,"x2":500,"y2":500}}
45
+ - vision_analyze: {"action":"vision_analyze","args":{"image_b64": "...", "prompt": "What do you see on screen?"}} — use after screenshot to let VLM describe/answer about the image (only when multimodal model loaded)
45
46
  - final: {"action":"final","message":"Korean summary of what was accomplished"}
46
47
 
47
48
  Rules:
48
49
  - Respond with exactly ONE JSON object. No markdown, no extra text.
49
50
  - Do not take screenshots for simple app launch, URL opening, keyboard shortcuts, or non-visual tasks.
50
51
  - Take a screenshot before coordinate-based clicks/drags or when the task explicitly asks you to inspect the screen.
52
+ - After screenshot, prefer vision_analyze (with good prompt) over raw b64 in next step when you need to understand what is on screen (especially with multimodal/VLM loaded).
51
53
  - After coordinate-based clicking or typing into an unknown focused field, take a screenshot only if verification is necessary.
52
54
  - Use coordinates relative to the screen (0,0 is top-left).
53
55
  - If a UI element is not visible, scroll or search for it first.
@@ -58,6 +58,19 @@ def create_memory_router(
58
58
  scope = gate_read(request)
59
59
  return service.brain_quality_summary(user_email=user, workspace_id=scope)
60
60
 
61
+ @router.get("/api/memory/brain-brief")
62
+ async def brain_brief(request: Request, q: str = "", limit: int = 3):
63
+ user = require_user(request)
64
+ scope = gate_read(request)
65
+ active_model = active_model_getter() if active_model_getter else ""
66
+ return service.brain_brief(
67
+ user_email=user,
68
+ workspace_id=scope,
69
+ active_model=active_model,
70
+ recall_query=q,
71
+ limit=limit,
72
+ )
73
+
61
74
  @router.get("/api/memory/brain-proof")
62
75
  async def brain_proof(request: Request, q: str = "", limit: int = 3):
63
76
  user = require_user(request)
@@ -44,6 +44,8 @@ from latticeai.runtime.platform_services_runtime import (
44
44
  from latticeai.runtime.platform_runtime_wiring import build_platform_automation_runtime
45
45
  from latticeai.runtime.persistence_runtime import build_persistence_runtime
46
46
  from latticeai.runtime.review_wiring import build_review_run_now_runner
47
+ from latticeai.runtime.sso_runtime import build_sso_runtime
48
+ from latticeai.runtime.audit_runtime import build_audit_runtime
47
49
  from latticeai.runtime.router_registration import (
48
50
  build_auth_admin_security_router_bundle,
49
51
  build_static_routes_bundle,
@@ -93,6 +95,7 @@ def _build(config: "Optional[Config]" = None) -> Dict[str, Any]:
93
95
 
94
96
  from latticeai.models.router import LLMRouter, normalize_branding
95
97
  from lattice_brain._kg_common import set_llm_router
98
+ from lattice_brain.graph.schema import set_embed_dim
96
99
  from latticeai.core.security import (
97
100
  hash_password,
98
101
  verify_password,
@@ -105,7 +108,6 @@ def _build(config: "Optional[Config]" = None) -> Dict[str, Any]:
105
108
  )
106
109
  from latticeai.core.audit import (
107
110
  get_audit_log as _get_audit_log,
108
- append_audit_event as _append_audit_event,
109
111
  classify_sensitive_message as _classify_sensitive_message,
110
112
  build_sensitivity_report as _build_sensitivity_report,
111
113
  build_admin_audit_report as _build_admin_audit_report,
@@ -249,29 +251,12 @@ def _build(config: "Optional[Config]" = None) -> Dict[str, Any]:
249
251
  SSO_CLIENT_SECRET = _security_runtime["SSO_CLIENT_SECRET"]
250
252
  SSO_REDIRECT_URI = _security_runtime["SSO_REDIRECT_URI"]
251
253
  SSO_PROVIDER_NAME = _security_runtime["SSO_PROVIDER_NAME"]
252
- _sso_discovery_cache: Optional[Dict] = None
253
- _sso_discovery_cache_url: str = ""
254
- _sso_states: Dict[str, float] = {} # state → timestamp (CSRF protection)
255
254
 
256
- async def _get_sso_discovery() -> Optional[Dict]:
257
- nonlocal _sso_discovery_cache, _sso_discovery_cache_url
258
- settings = get_sso_settings()
259
- discovery_url = settings.get("discovery_url", "")
260
- if _sso_discovery_cache and _sso_discovery_cache_url == discovery_url:
261
- return _sso_discovery_cache
262
- if not discovery_url:
263
- return None
264
- try:
265
- import httpx as _httpx
266
- async with _httpx.AsyncClient() as c:
267
- r = await c.get(discovery_url, timeout=10)
268
- r.raise_for_status()
269
- _sso_discovery_cache = r.json()
270
- _sso_discovery_cache_url = discovery_url
271
- except Exception as e:
272
- logging.warning("SSO discovery failed: %s", e)
273
- return None
274
- return _sso_discovery_cache
255
+ # SSO cache + discovery built after get_sso_settings is defined (see below)
256
+ _sso_discovery_cache = None
257
+ _sso_discovery_cache_url = ""
258
+ _sso_states: Dict[str, float] = {}
259
+ _get_sso_discovery = None # filled after def below
275
260
 
276
261
  # ── Password hashing — used directly from latticeai.core.security ──────────────
277
262
  # (hash_password / verify_password are imported above; no local wrapper needed)
@@ -355,6 +340,7 @@ def _build(config: "Optional[Config]" = None) -> Dict[str, Any]:
355
340
  extra={"target": CONFIG.embedding_custom_target},
356
341
  probe=_embedding_provider not in {"", "hash", "local", "fallback"},
357
342
  )
343
+ set_embed_dim(int(getattr(EMBEDDER, "dim", None) or _embedding_dim or 384))
358
344
  if EMBEDDER.fell_back:
359
345
  logging.warning("Embedding provider %s unavailable: %s", EMBEDDER.requested, EMBEDDER.detail)
360
346
  STORAGE_ENGINE = storage_from_env(os.environ, data_dir=DATA_DIR) if ENABLE_GRAPH else None
@@ -479,6 +465,17 @@ def _build(config: "Optional[Config]" = None) -> Dict[str, Any]:
479
465
  def get_sso_settings() -> Dict[str, object]:
480
466
  return load_sso_config()
481
467
 
468
+ # Build SSO runtime (cache + helper) now that get_sso_settings exists in scope.
469
+ if _get_sso_discovery is None:
470
+ _sso = build_sso_runtime(
471
+ get_sso_settings=get_sso_settings,
472
+ logging=logging,
473
+ )
474
+ _sso_discovery_cache = _sso["_sso_discovery_cache"]
475
+ _sso_discovery_cache_url = _sso["_sso_discovery_cache_url"]
476
+ _sso_states = _sso["_sso_states"]
477
+ _get_sso_discovery = _sso["_get_sso_discovery"]
478
+
482
479
  def public_sso_config(config: Optional[Dict[str, object]] = None) -> Dict[str, object]:
483
480
  cfg = config or get_sso_settings()
484
481
  return {
@@ -558,11 +555,7 @@ def _build(config: "Optional[Config]" = None) -> Dict[str, Any]:
558
555
 
559
556
  _history_lock = threading.Lock()
560
557
 
561
- def get_audit_log() -> List[Dict]:
562
- return _get_audit_log(AUDIT_FILE)
563
-
564
- def append_audit_event(event_type: str, **payload) -> None:
565
- _append_audit_event(AUDIT_FILE, event_type, **payload)
558
+ # audit build moved after redact_secret_text is defined (see below)
566
559
 
567
560
  def save_to_history(
568
561
  role: str,
@@ -634,6 +627,15 @@ def _build(config: "Optional[Config]" = None) -> Dict[str, Any]:
634
627
  def redact_secret_text(text: str) -> str:
635
628
  return _redact_secret_text(text)
636
629
 
630
+ # Build audit now that redact is available
631
+ _audit_rt = build_audit_runtime(
632
+ audit_file=AUDIT_FILE,
633
+ logging=logging,
634
+ redact_fn=redact_secret_text,
635
+ )
636
+ get_audit_log = _audit_rt["get_audit_log"]
637
+ append_audit_event = _audit_rt["append_audit_event"]
638
+
637
639
  def get_history():
638
640
  try:
639
641
  return CONVERSATIONS.history()
@@ -22,7 +22,7 @@ warnings.warn(
22
22
  "latticeai.brain is deprecated; import lattice_brain instead",
23
23
  DeprecationWarning,
24
24
  stacklevel=2,
25
- )
25
+ ) # one-time per import site in practice; shims remain for compat surface
26
26
 
27
27
  __all__ = [
28
28
  "AssembledContext",
@@ -26,6 +26,8 @@ from typing import List, Mapping, Optional
26
26
  from latticeai.core.security import host_is_loopback
27
27
 
28
28
 
29
+ __all__ = ["Config", "_value", "_str", "_bool", "_int"]
30
+
29
31
  def _value(env: Mapping[str, str], key: str, default: str = "") -> str:
30
32
  """Mirror the legacy ``env_value``: ``getenv(key) or default or ""`` (no strip)."""
31
33
  return env.get(key) or default or ""
@@ -68,6 +70,7 @@ class Config:
68
70
  host: str
69
71
  port: int
70
72
  network_exposed: bool
73
+ timezone: str
71
74
 
72
75
  # ── feature flags ───────────────────────────────────────────────
73
76
  enable_telegram: bool
@@ -93,6 +96,9 @@ class Config:
93
96
  local_model: str
94
97
  local_draft_model: str
95
98
  auto_read_chat_paths: bool
99
+ max_local_models: int
100
+ allow_model_downloads: bool
101
+ model_download_timeout: int
96
102
 
97
103
  # ── embeddings (retrieval vector signal) ────────────────────────
98
104
  embedding_provider: str
@@ -165,6 +171,7 @@ class Config:
165
171
  host=host,
166
172
  port=port,
167
173
  network_exposed=network_exposed,
174
+ timezone=_value(env, "LATTICE_TZ", "UTC") or "UTC",
168
175
  enable_telegram=_bool(env, "LATTICEAI_ENABLE_TELEGRAM", default=False),
169
176
  enable_graph=_bool(env, "LATTICEAI_ENABLE_GRAPH", default=True),
170
177
  autoload_models=_bool(env, "LATTICEAI_AUTOLOAD_MODELS", default=is_public),
@@ -184,6 +191,9 @@ class Config:
184
191
  local_model=local_model,
185
192
  local_draft_model=_value(env, "LATTICEAI_LOCAL_DRAFT_MODEL", ""),
186
193
  auto_read_chat_paths=_bool(env, "LATTICEAI_AUTO_READ_CHAT_PATHS", default=False),
194
+ max_local_models=_int(env, "LATTICEAI_MAX_LOCAL_MODELS", 1),
195
+ allow_model_downloads=_bool(env, "LATTICEAI_ALLOW_MODEL_DOWNLOADS", default=False),
196
+ model_download_timeout=_int(env, "LATTICEAI_MODEL_DOWNLOAD_TIMEOUT", 300),
187
197
  embedding_provider=_value(env, "LATTICEAI_EMBEDDING_PROVIDER", "hash").strip().lower(),
188
198
  embedding_profile=_value(env, "LATTICEAI_EMBEDDING_PROFILE", "").strip().lower(),
189
199
  embedding_model=_value(env, "LATTICEAI_EMBEDDING_MODEL", ""),
@@ -11,7 +11,7 @@ from copy import deepcopy
11
11
  from typing import Any, Dict, List, Optional
12
12
 
13
13
 
14
- MARKETPLACE_VERSION = "8.1.0"
14
+ MARKETPLACE_VERSION = "8.2.0"
15
15
  TEMPLATE_KINDS = ("plugin", "workflow", "agent")
16
16
 
17
17
 
@@ -9,6 +9,16 @@ effects at import time.
9
9
 
10
10
  from __future__ import annotations
11
11
 
12
+ __all__ = [
13
+ "ToolPolicy",
14
+ "ToolPermission",
15
+ "TOOL_CATALOG_BRIEF",
16
+ "FILE_CREATE_ACTIONS",
17
+ "LOCAL_WRITE_BLOCKED_PREFIXES",
18
+ "RISK_LEVEL_MAP",
19
+ "ToolRegistry",
20
+ ]
21
+
12
22
  from dataclasses import dataclass, field
13
23
  from typing import Any, Callable, Dict, Mapping, Optional, TypedDict
14
24