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.
- package/README.md +20 -41
- package/docs/CHANGELOG.md +38 -874
- package/docs/DEVELOPMENT.md +26 -3
- package/docs/LEGACY_COMPATIBILITY.md +3 -1
- package/docs/TRUST_MODEL.md +26 -26
- package/docs/WHY_LATTICE.md +28 -25
- package/docs/kg-schema.md +6 -4
- package/lattice_brain/__init__.py +1 -1
- package/lattice_brain/graph/schema.py +6 -0
- package/lattice_brain/runtime/multi_agent.py +1 -1
- package/latticeai/__init__.py +1 -1
- package/latticeai/api/computer_use.py +2 -0
- package/latticeai/api/memory.py +13 -0
- package/latticeai/app_factory.py +30 -28
- package/latticeai/brain/__init__.py +1 -1
- package/latticeai/core/config.py +10 -0
- package/latticeai/core/marketplace.py +1 -1
- package/latticeai/core/tool_registry.py +10 -0
- package/latticeai/core/workspace_graph_trace.py +132 -0
- package/latticeai/core/workspace_memory.py +75 -0
- package/latticeai/core/workspace_os.py +135 -1283
- package/latticeai/core/workspace_os_utils.py +132 -0
- package/latticeai/core/workspace_permissions.py +99 -0
- package/latticeai/core/workspace_plugins.py +97 -0
- package/latticeai/core/workspace_runs.py +612 -0
- package/latticeai/core/workspace_skills.py +114 -0
- package/latticeai/core/workspace_snapshots.py +195 -0
- package/latticeai/core/workspace_timeline.py +107 -0
- package/latticeai/runtime/audit_runtime.py +64 -0
- package/latticeai/runtime/config_runtime.py +4 -0
- package/latticeai/runtime/sso_runtime.py +52 -0
- package/latticeai/services/architecture_readiness.py +3 -3
- package/latticeai/services/memory_service.py +215 -7
- package/latticeai/services/model_capability_registry.py +68 -0
- package/latticeai/services/model_engines.py +603 -0
- package/latticeai/services/model_loading.py +482 -0
- package/latticeai/services/model_recommendation.py +5 -0
- package/latticeai/services/model_runtime.py +141 -866
- package/latticeai/services/product_readiness.py +19 -18
- package/package.json +1 -1
- 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-BOO66G-c.js → Act-D9jIknFd.js} +1 -1
- package/static/app/assets/{Brain-C6lEYiD7.js → Brain-CFOtWbPN.js} +1 -1
- package/static/app/assets/{Capture-TATXBRDw.js → Capture-Q4WYzwr5.js} +1 -1
- package/static/app/assets/{Library-DK4FIp8a.js → Library-C5Q2yWee.js} +1 -1
- package/static/app/assets/{System-Bgs6Ql7x.js → System-BLbjdr1_.js} +1 -1
- package/static/app/assets/index-BqammyNu.js +16 -0
- package/static/app/assets/index-ty1iGgZu.css +2 -0
- package/static/app/assets/{primitives-B70WOra0.js → primitives-Br8uSfZ4.js} +1 -1
- package/static/app/assets/{textarea-Czrd9gwM.js → textarea-BnhNs1_X.js} +1 -1
- package/static/app/index.html +2 -2
- package/static/sw.js +1 -1
- package/tools/__init__.py +2 -1
- package/tools/computer.py +21 -0
- package/docs/CARRYOVER_AUDIT_v3.6.0.md +0 -61
- package/docs/HANDOVER_v3.6.0.md +0 -46
- package/docs/RUNTIME_HOOK_COVERAGE_v3.5.0.md +0 -56
- package/docs/RUNTIME_HOOK_COVERAGE_v3.6.0.md +0 -49
- package/docs/V2_ARCHITECTURE.md +0 -561
- package/docs/V3_2_AUDIT.md +0 -82
- package/docs/V3_BACKEND_ARCHITECTURE.md +0 -138
- package/docs/V3_FRONTEND.md +0 -146
- package/docs/V4_1_FRONTEND_ARCHITECTURE_REVIEW.md +0 -65
- package/docs/V4_1_FRONTEND_MIGRATION_REPORT.md +0 -70
- package/docs/V4_1_VALIDATION_REPORT.md +0 -47
- package/docs/V4_2_BRAIN_CORE_ARCHITECTURE.md +0 -97
- package/docs/V4_2_STORAGE_MIGRATION_REPORT.md +0 -91
- package/docs/V4_2_VALIDATION_REPORT.md +0 -89
- package/docs/V4_3_2_DEADCODE_AUDIT_REPORT.md +0 -174
- package/docs/V4_3_2_DOCUMENTATION_CLEANUP_REPORT.md +0 -81
- package/docs/V4_3_2_GITHUB_VERCEL_CHECK_REPORT.md +0 -75
- package/docs/V4_3_2_GRAPH_UX_REPORT.md +0 -48
- package/docs/V4_3_2_INDEPENDENT_AUDIT_PACKAGE.md +0 -209
- package/docs/V4_3_2_PRODUCT_POLISH_REPORT.md +0 -57
- package/docs/V4_3_2_SELF_AUDIT_REPORT.md +0 -63
- package/docs/V4_3_2_VALIDATION_REPORT.md +0 -97
- package/docs/V4_3_3_VALIDATION_REPORT.md +0 -46
- package/docs/V4_3_PORTABILITY_ARCHITECTURE.md +0 -69
- package/docs/V4_3_PRIVACY_AUDIT.md +0 -60
- package/docs/V4_3_PRODUCT_HARDENING_REPORT.md +0 -53
- package/docs/V4_3_VALIDATION_REPORT.md +0 -58
- package/docs/V4_4_0_EXTRACTION_REPORT.md +0 -239
- package/docs/V4_5_0_GEMMA_RUNTIME_COMPATIBILITY_REPORT.md +0 -49
- package/docs/V4_5_0_GRAPH_UX_REPORT.md +0 -34
- package/docs/V4_5_0_MODEL_RUNTIME_UX_REPORT.md +0 -40
- package/docs/V4_5_0_ONBOARDING_REPORT.md +0 -31
- package/docs/V4_5_0_PRODUCT_EXPERIENCE_RECOVERY_REPORT.md +0 -49
- package/docs/V4_5_0_VALIDATION_REPORT.md +0 -60
- package/docs/V4_5_1_GRAPH_EXPERIENCE_REPORT.md +0 -33
- package/docs/V4_5_1_MODEL_EXPERIENCE_REPORT.md +0 -37
- package/docs/V4_5_1_NAVIGATION_REPORT.md +0 -37
- package/docs/V4_5_1_ONBOARDING_REPORT.md +0 -29
- package/docs/V4_5_1_PRODUCT_REIMAGINING_REPORT.md +0 -61
- package/docs/V4_5_1_RC_ARTIFACTS.md +0 -44
- package/docs/V4_5_1_UX_REPORT.md +0 -45
- package/docs/V4_5_1_VALIDATION_REPORT.md +0 -55
- package/docs/V4_5_1_VISUAL_DESIGN_REPORT.md +0 -30
- package/docs/V4_6_0_LIVING_BRAIN_EXPERIENCE_REPORT.md +0 -72
- package/docs/V4_6_1_RELEASE_REFRESH_REPORT.md +0 -42
- package/docs/V4_7_0_ADMIN_SEPARATION_REPORT.md +0 -42
- package/docs/V4_7_1_ADMIN_OPERATIONS_REPORT.md +0 -49
- package/docs/V4_7_2_INTUITIVE_BRAIN_UX_REPORT.md +0 -62
- package/docs/V4_BRAIN_ARCHITECTURE.md +0 -322
- package/docs/V4_DIGITAL_BRAIN_RECOVERY.md +0 -555
- package/docs/V4_IMPLEMENTATION_PLAN.md +0 -470
- package/static/app/assets/index-Bvv79nre.js +0 -16
- package/static/app/assets/index-Dslqglia.css +0 -2
package/docs/DEVELOPMENT.md
CHANGED
|
@@ -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
|
|
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
|
-
|
|
82
|
-
|
|
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
|
|
package/docs/TRUST_MODEL.md
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
# Lattice AI Trust Model
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
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
|
|
14
|
+
Local data can include:
|
|
13
15
|
|
|
14
|
-
-
|
|
15
|
-
- conversations and
|
|
16
|
-
- Knowledge Graph nodes, edges, provenance, and
|
|
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
|
-
|
|
24
|
-
action or configuration:
|
|
25
|
+
External communication requires configuration plus a user/admin action:
|
|
25
26
|
|
|
26
|
-
- model
|
|
27
|
-
-
|
|
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
|
|
30
|
+
- Brain Network peer actions after pairing;
|
|
30
31
|
- Docker/Postgres setup after opt-in scale configuration;
|
|
31
|
-
- update checks only when
|
|
32
|
-
- remote
|
|
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
|
|
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
|
|
49
|
+
- archive tampering, unsupported archive versions, or path traversal.
|
|
50
50
|
|
|
51
|
-
##
|
|
51
|
+
## Product Boundary
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
|
|
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
|
|
58
|
+
## Known Limits
|
|
59
59
|
|
|
60
|
-
- Local files are only as protected as the user's machine, account, backups,
|
|
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
|
-
|
package/docs/WHY_LATTICE.md
CHANGED
|
@@ -1,51 +1,54 @@
|
|
|
1
1
|
# Why Lattice AI Exists
|
|
2
2
|
|
|
3
|
-
|
|
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
|
|
8
|
-
|
|
9
|
-
|
|
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
|
|
15
|
-
material. That
|
|
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
|
|
20
|
+
- documents and notes stay disconnected from conversations;
|
|
19
21
|
- switching models often means losing useful context;
|
|
20
|
-
- graph
|
|
21
|
-
- cloud-only products make
|
|
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
|
|
26
|
-
|
|
27
|
-
|
|
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
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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
|
|
39
|
-
-
|
|
40
|
-
- Prepare
|
|
41
|
-
- Preserve context when moving
|
|
42
|
-
- Export or
|
|
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
|
|
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
|
|
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
|
-
경로는 타입 페어를 거부하지 않는다.
|
|
85
|
+
경로는 타입 페어를 거부하지 않는다. 현재 쓰기 정규화는 *타입 어휘* 를
|
|
84
86
|
강제한다: `_upsert_edge` 가 모든 엣지 타입을 canonical `EdgeType` 값으로
|
|
85
87
|
정규화하므로 자유 문자열 타입은 더 이상 생성되지 않는다.
|
|
86
88
|
|
|
87
89
|
---
|
|
88
90
|
|
|
89
|
-
##
|
|
91
|
+
## Current Knowledge Graph First 엔티티/관계
|
|
90
92
|
|
|
91
|
-
|
|
93
|
+
8.2.0 은 "모든 데이터 소스가 Knowledge Graph 로 수렴한다"는 원칙을 1급 스키마로
|
|
92
94
|
승격한다. 아래 타입은 **추가형(additive)**이다 — 기존 enum/legacy 매핑을 깨지 않고
|
|
93
95
|
`from_legacy` 가 무손실로 정규화하며, 알 수 없는 타입은 여전히 `CONCEPT`/`MENTIONS` 로
|
|
94
96
|
폴백한다. 스키마는 **확장 가능**하게 유지한다: 새 도메인 엔티티는 enum 멤버 1개 +
|
|
@@ -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.
|
|
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")
|
package/latticeai/__init__.py
CHANGED
|
@@ -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.
|
package/latticeai/api/memory.py
CHANGED
|
@@ -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)
|
package/latticeai/app_factory.py
CHANGED
|
@@ -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
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
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
|
-
|
|
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()
|
package/latticeai/core/config.py
CHANGED
|
@@ -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", ""),
|
|
@@ -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
|
|