ltcai 3.0.1 → 3.1.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 +27 -20
- package/docs/CHANGELOG.md +37 -0
- package/docs/V3_FRONTEND.md +20 -17
- package/latticeai/__init__.py +1 -1
- package/latticeai/api/auth.py +4 -1
- package/latticeai/api/search.py +4 -0
- package/latticeai/core/config.py +2 -0
- package/latticeai/core/embedding_providers.py +123 -0
- package/latticeai/core/workspace_os.py +1 -1
- package/latticeai/server_app.py +22 -6
- package/package.json +9 -4
- package/scripts/build_v3_assets.mjs +164 -0
- package/scripts/capture/README.md +28 -0
- package/scripts/capture/capture_enterprise.js +8 -0
- package/scripts/capture/capture_graph.js +8 -0
- package/scripts/capture/capture_onboarding.js +8 -0
- package/scripts/capture/capture_page.js +43 -0
- package/scripts/capture/capture_release_media.js +125 -0
- package/scripts/capture/capture_skills.js +8 -0
- package/scripts/capture/capture_workspace.js +8 -0
- package/scripts/generate_diagrams.py +513 -0
- package/scripts/lint_v3.mjs +33 -0
- package/scripts/release-0.3.1.sh +105 -0
- package/scripts/take_screenshots.js +69 -0
- package/scripts/validate_release_artifacts.py +167 -0
- package/static/account.html +9 -9
- package/static/activity.html +4 -4
- package/static/admin.html +8 -8
- package/static/agents.html +4 -4
- package/static/chat.html +9 -9
- package/static/css/tokens.5a595671.css +260 -0
- package/static/css/tokens.css +1 -1
- package/static/graph.html +9 -9
- package/static/plugins.html +4 -4
- package/static/sw.js +3 -1
- package/static/v3/asset-manifest.json +47 -0
- package/static/v3/css/lattice.base.e4cdd05d.css +128 -0
- package/static/v3/css/lattice.components.011e988b.css +447 -0
- package/static/v3/css/lattice.components.css +2 -2
- package/static/v3/css/lattice.shell.4920f42d.css +407 -0
- package/static/v3/css/lattice.tokens.c597ff81.css +132 -0
- package/static/v3/css/lattice.views.3ee19d4e.css +277 -0
- package/static/v3/index.html +38 -9
- package/static/v3/js/app.46fb61d9.js +26 -0
- package/static/v3/js/core/api.22a41d42.js +344 -0
- package/static/v3/js/core/api.js +68 -51
- package/static/v3/js/core/components.4c83e0a9.js +222 -0
- package/static/v3/js/core/components.js +9 -2
- package/static/v3/js/core/dom.a2773eb0.js +148 -0
- package/static/v3/js/core/router.584570f2.js +37 -0
- package/static/v3/js/core/routes.f935dd50.js +78 -0
- package/static/v3/js/core/routes.js +6 -1
- package/static/v3/js/core/shell.1b6199d6.js +363 -0
- package/static/v3/js/core/store.34ebd5e6.js +113 -0
- package/static/v3/js/views/admin-audit.660a1fb1.js +185 -0
- package/static/v3/js/views/admin-audit.js +1 -1
- package/static/v3/js/views/admin-permissions.a7ae5f09.js +177 -0
- package/static/v3/js/views/admin-permissions.js +4 -5
- package/static/v3/js/views/admin-policies.3658fd86.js +102 -0
- package/static/v3/js/views/admin-policies.js +4 -5
- package/static/v3/js/views/admin-private-vpc.7d342d36.js +135 -0
- package/static/v3/js/views/admin-private-vpc.js +2 -5
- package/static/v3/js/views/admin-security.07c66b72.js +180 -0
- package/static/v3/js/views/admin-security.js +4 -5
- package/static/v3/js/views/admin-users.03bac88c.js +168 -0
- package/static/v3/js/views/admin-users.js +6 -6
- package/static/v3/js/views/agents.14e48bdd.js +193 -0
- package/static/v3/js/views/agents.js +1 -2
- package/static/v3/js/views/chat.718144ce.js +449 -0
- package/static/v3/js/views/chat.js +2 -3
- package/static/v3/js/views/files.4935197e.js +186 -0
- package/static/v3/js/views/files.js +27 -21
- package/static/v3/js/views/home.cdde3b32.js +119 -0
- package/static/v3/js/views/hybrid-search.b22b97e0.js +195 -0
- package/static/v3/js/views/hybrid-search.js +1 -1
- package/static/v3/js/views/knowledge-graph.a14ea7e7.js +237 -0
- package/static/v3/js/views/knowledge-graph.js +2 -3
- package/static/v3/js/views/models.a1ffa147.js +256 -0
- package/static/v3/js/views/models.js +17 -8
- package/static/v3/js/views/my-computer.1b2ff621.js +237 -0
- package/static/v3/js/views/my-computer.js +5 -5
- package/static/v3/js/views/pipeline.c522f1ce.js +157 -0
- package/static/v3/js/views/pipeline.js +3 -7
- package/static/v3/js/views/settings.4f777210.js +250 -0
- package/static/v3/js/views/settings.js +6 -14
- package/static/workflows.html +4 -4
- package/static/workspace.html +5 -5
- package/docs/images/tmp_frames/frame_00.png +0 -0
- package/docs/images/tmp_frames/frame_01.png +0 -0
- package/docs/images/tmp_frames/frame_02.png +0 -0
- package/docs/images/tmp_frames/frame_03.png +0 -0
- package/docs/images/tmp_frames/hero_00.png +0 -0
- package/docs/images/tmp_frames/hero_01.png +0 -0
- package/docs/images/tmp_frames/hero_02.png +0 -0
- package/docs/images/tmp_frames/hero_03.png +0 -0
- package/static/v3/js/core/fixtures.js +0 -171
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
[](https://www.npmjs.com/package/ltcai)
|
|
17
17
|
[](https://marketplace.visualstudio.com/items?itemName=parktaesoo.ltcai)
|
|
18
18
|
[](https://open-vsx.org/extension/parktaesoo/ltcai)
|
|
19
|
-
[](https://github.com/TaeSooPark-PTS/LatticeAI/releases/tag/v3.
|
|
19
|
+
[](https://github.com/TaeSooPark-PTS/LatticeAI/releases/tag/v3.1.0)
|
|
20
20
|
[](LICENSE)
|
|
21
21
|
[](https://www.python.org/)
|
|
22
22
|
[](https://marketplace.visualstudio.com/items?itemName=parktaesoo.ltcai)
|
|
@@ -49,7 +49,7 @@ Install the coding extension:
|
|
|
49
49
|
|
|
50
50
|
- [VS Code Marketplace: parktaesoo.ltcai](https://marketplace.visualstudio.com/items?itemName=parktaesoo.ltcai)
|
|
51
51
|
- [Open VSX: parktaesoo.ltcai](https://open-vsx.org/extension/parktaesoo/ltcai)
|
|
52
|
-
- [GitHub Release v3.
|
|
52
|
+
- [GitHub Release v3.1.0](https://github.com/TaeSooPark-PTS/LatticeAI/releases/tag/v3.1.0)
|
|
53
53
|
|
|
54
54
|
## Quick Start
|
|
55
55
|
|
|
@@ -88,8 +88,8 @@ place.
|
|
|
88
88
|
|
|
89
89
|
- **Primary app shell**: `/app` is the default product experience with Native
|
|
90
90
|
Chat, Knowledge Graph, Hybrid Search, Files, Pipeline, Agents, Models, My
|
|
91
|
-
Computer, Settings, and Admin areas.
|
|
92
|
-
|
|
91
|
+
Computer, Settings, and Admin areas. Classic pages remain compatibility
|
|
92
|
+
routes only; normal workflows stay in `/app`.
|
|
93
93
|
- **Local-first AI Workspace**: work starts on your machine, with local data and
|
|
94
94
|
workspace state by default.
|
|
95
95
|
- **AI Pipeline Platform**: plan, execute, review, retry, and replay work across
|
|
@@ -105,8 +105,8 @@ place.
|
|
|
105
105
|
Knowledge Graph and fused with keyword and graph signals.
|
|
106
106
|
- **Local Model Management**: choose current multimodal local models with source
|
|
107
107
|
disclosure, hardware-aware recommendations, and cloud fallback options.
|
|
108
|
-
- **
|
|
109
|
-
|
|
108
|
+
- **Community-first workspaces**: Personal and Organization workspaces ship in
|
|
109
|
+
the local product; enterprise SSO/SCIM/governance remain future extensions.
|
|
110
110
|
|
|
111
111
|
## Why Lattice AI?
|
|
112
112
|
|
|
@@ -122,10 +122,11 @@ and disconnected automations. Lattice AI keeps those parts together:
|
|
|
122
122
|
- multi-agent workflows leave behind replayable plans, reviews, retries, and
|
|
123
123
|
outcomes.
|
|
124
124
|
|
|
125
|
-
## v3.
|
|
125
|
+
## v3.1.0 Highlights
|
|
126
126
|
|
|
127
|
-
Lattice AI v3.
|
|
128
|
-
|
|
127
|
+
Lattice AI v3.1.0 completes the non-enterprise local-first workspace platform
|
|
128
|
+
around `/app`: Classic is retired from normal workflows, retrieval is wired
|
|
129
|
+
through a shared service layer, and browser assets are hash-manifested.
|
|
129
130
|
|
|
130
131
|
- Native v3 Chat lives inside `/app#/chat` and streams through the real
|
|
131
132
|
`POST /chat` backend while showing friendly setup guidance when no model is
|
|
@@ -134,11 +135,17 @@ backend retrieval stack together with the native frontend.
|
|
|
134
135
|
surfaces. Hybrid results show keyword, local vector, and graph scores.
|
|
135
136
|
- Personal and Organization workspaces, plus Basic / Advanced / Admin modes,
|
|
136
137
|
are built into the shell.
|
|
137
|
-
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
138
|
+
- Models can load/unload from the native Models view; Agents read the
|
|
139
|
+
AgentRuntime boundary with run health, history, events, replay, and stop
|
|
140
|
+
affordances.
|
|
141
|
+
- Production embedding profiles cover local `bge-m3`, `nomic-embed-text`,
|
|
142
|
+
`e5-large`, `gte-large`, Ollama `nomic-embed-text`, `mxbai-embed-large`,
|
|
143
|
+
BGE-M3-compatible providers, MLX, and OpenAI-compatible
|
|
144
|
+
`text-embedding-3-small` / `text-embedding-3-large`. Hash embeddings remain
|
|
145
|
+
fallback only.
|
|
146
|
+
- `/app` loads `static/v3/asset-manifest.json` and build-generated hashed
|
|
147
|
+
assets such as `app.<hash>.js` and `lattice.base.<hash>.css`; manual `?v=`
|
|
148
|
+
cache-busting is no longer used by runtime HTML.
|
|
142
149
|
|
|
143
150
|
## Screenshots
|
|
144
151
|
|
|
@@ -184,11 +191,10 @@ The v3 backend adds a local-first retrieval stack that combines the Knowledge
|
|
|
184
191
|
Graph, a SQLite vector index, and hybrid result fusion. It preserves existing
|
|
185
192
|
graph data while adding derived vector rows that can be rebuilt at any time.
|
|
186
193
|
|
|
187
|
-
Embedding status:
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
semantic embedding model.
|
|
191
|
-
OpenAI-compatible providers, and other local embedding runtimes.
|
|
194
|
+
Embedding status: production profiles are exposed through
|
|
195
|
+
`GET /api/embeddings/providers`, while `lattice-local-hash-v1` remains a
|
|
196
|
+
deterministic fallback for offline indexing and tests. It is never presented as
|
|
197
|
+
a production semantic embedding model.
|
|
192
198
|
|
|
193
199
|
Core API contracts:
|
|
194
200
|
|
|
@@ -259,7 +265,8 @@ Core areas:
|
|
|
259
265
|
|
|
260
266
|
| Version | Theme |
|
|
261
267
|
| --- | --- |
|
|
262
|
-
| **3.0
|
|
268
|
+
| **3.1.0** | Mainline platform completion — native `/app` workflows, Classic retired from normal paths, production embedding profiles, AgentRuntime/registries, hashed v3 assets |
|
|
269
|
+
| 3.0.1 | Release-blocker remediation — provider-backed embeddings (Hash/MLX/Ollama/OpenAI/Custom), unified AgentRuntime boundary, every v3 surface connected or clearly unavailable |
|
|
263
270
|
| 3.0.0 | v3 local-first AI workspace platform — `/app`, Native Chat, Knowledge Graph, Vector Index, Hybrid Search, workspace modes |
|
|
264
271
|
| 2.2.7 | Visual system stabilization — cohesive dark/light screens, crisp chat composer, dark graph canvas, Workspace OS polish |
|
|
265
272
|
| 2.2.6 | Token-native CSS foundation |
|
package/docs/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,42 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [3.1.0] - 2026-06-07
|
|
4
|
+
|
|
5
|
+
> v3.1 — Mainline Product Platform Completion. `/app` is now the full
|
|
6
|
+
> non-enterprise local-first workspace: Classic pages are compatibility routes,
|
|
7
|
+
> production embedding profiles are explicit, AgentRuntime and registries are
|
|
8
|
+
> the integration boundaries, and v3 runtime assets are hash-manifested.
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **Hashed asset pipeline** — `npm run build:assets` writes
|
|
13
|
+
`static/v3/asset-manifest.json`, hashed CSS/JS siblings, and import-rewritten
|
|
14
|
+
ES modules. `/app` reads the manifest and loads hashed assets automatically.
|
|
15
|
+
- **Production embedding profiles** — local `bge-m3`, `nomic-embed-text`,
|
|
16
|
+
`e5-large`, `gte-large`; Ollama `nomic-embed-text`, `mxbai-embed-large`,
|
|
17
|
+
BGE-M3-compatible providers; MLX Apple Silicon profiles; and
|
|
18
|
+
OpenAI-compatible `text-embedding-3-small` / `text-embedding-3-large`.
|
|
19
|
+
- **Native model lifecycle controls** — `/app#/models` now calls the real
|
|
20
|
+
`/models/load` and `/models/unload/{model_id}` endpoints.
|
|
21
|
+
|
|
22
|
+
### Changed
|
|
23
|
+
|
|
24
|
+
- **Classic retirement** — normal user workflows no longer link to Classic
|
|
25
|
+
Chat, Classic Runtime, or Classic Admin. Compatibility routes remain available
|
|
26
|
+
for rollback/debug.
|
|
27
|
+
- **Truthful unavailable states** — v3 fallback adapters return empty
|
|
28
|
+
unavailable payloads instead of sample data, fake counters, or fabricated
|
|
29
|
+
health.
|
|
30
|
+
- **Release metadata** — package, npm, VS Code extension, Workspace OS, docs,
|
|
31
|
+
and expected artifacts are aligned at `3.1.0`.
|
|
32
|
+
|
|
33
|
+
### Validation
|
|
34
|
+
|
|
35
|
+
- Release target: `npm run lint`, `npm run typecheck`, `npm run check:python`,
|
|
36
|
+
backend/integration tests, Playwright visual tests, `python -m build`,
|
|
37
|
+
`npm run build`, `npm pack`, VSIX package, and exact-version artifact
|
|
38
|
+
validation.
|
|
39
|
+
|
|
3
40
|
## [3.0.0] - 2026-06-07
|
|
4
41
|
|
|
5
42
|
> v3 — Local-first AI Workspace Platform. The hybrid-search
|
package/docs/V3_FRONTEND.md
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
> A token-native single-page workspace shell for Lattice AI v3. It ships as the
|
|
4
4
|
> primary product experience and calls the real v3 retrieval/chat APIs while
|
|
5
|
-
>
|
|
5
|
+
> rendering clear unavailable states for local services that are not running.
|
|
6
6
|
|
|
7
7
|
Entry point: **`/app`** (served by `latticeai/api/static_routes.py` →
|
|
8
8
|
`static/v3/index.html`). Login, auto-login after registration, SSO callback, and
|
|
9
9
|
the PWA manifest land on `/app`. The legacy multi-page screens (`/workspace`,
|
|
10
|
-
`/chat`, `/graph`, `/admin`, …) remain reachable
|
|
11
|
-
|
|
10
|
+
`/chat`, `/graph`, `/admin`, …) remain reachable only as compatibility/debug
|
|
11
|
+
routes; normal user workflows stay in `/app`.
|
|
12
12
|
|
|
13
13
|
---
|
|
14
14
|
|
|
@@ -49,6 +49,9 @@ Administration Users · Permissions · Audit Logs · Security · Policies · Pri
|
|
|
49
49
|
Token-native, layered on the existing **single color source**
|
|
50
50
|
(`static/css/tokens.css`, `data-lt-theme` light/dark). No legacy override layers
|
|
51
51
|
(`responsive.css` / `workspace.css` / `platform.css`) are loaded by v3.
|
|
52
|
+
Runtime assets are loaded through `static/v3/asset-manifest.json`; the build
|
|
53
|
+
step writes hashed CSS/JS siblings and `/app` reads the manifest instead of
|
|
54
|
+
using manual `?v=` query strings.
|
|
52
55
|
|
|
53
56
|
| File | Responsibility |
|
|
54
57
|
| --- | --- |
|
|
@@ -91,28 +94,27 @@ export async function render(ctx) { /* … */ return singleDomNode; }
|
|
|
91
94
|
## Integration contract
|
|
92
95
|
|
|
93
96
|
`core/api.js` is the only transport layer. Every call hits the **real** endpoint
|
|
94
|
-
first and
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
placeholder responses, so nothing fake is presented as backend output.
|
|
97
|
+
first and returns `{ ok, status, data, source }` where `source` is `"live"` or
|
|
98
|
+
`"unavailable"`. Unavailable responses carry empty data so primary surfaces do
|
|
99
|
+
not invent counters, sample graphs, fake health, or fake run history.
|
|
98
100
|
|
|
99
|
-
Live surfaces wired in v3.
|
|
101
|
+
Live surfaces wired in v3.1.0:
|
|
100
102
|
|
|
101
|
-
| Adapter | Endpoint |
|
|
103
|
+
| Adapter | Endpoint | Unavailable state |
|
|
102
104
|
| --- | --- | --- |
|
|
103
|
-
| `api.indexStatus()` | `GET /api/index/status` |
|
|
104
|
-
| `api.graph(params)` | `GET /api/graph` → `GET /knowledge-graph/graph` |
|
|
105
|
-
| `api.hybridSearch(q, opts)` | `POST /api/search/hybrid` |
|
|
106
|
-
| `api.streamChat(body)` | `POST /chat` SSE |
|
|
105
|
+
| `api.indexStatus()` | `GET /api/index/status` | empty retrieval status |
|
|
106
|
+
| `api.graph(params)` | `GET /api/graph` → `GET /knowledge-graph/graph` | empty graph |
|
|
107
|
+
| `api.hybridSearch(q, opts)` | `POST /api/search/hybrid` | empty results |
|
|
108
|
+
| `api.streamChat(body)` | `POST /chat` SSE | unavailable chat message |
|
|
107
109
|
|
|
108
110
|
No backend retrieval logic is implemented in the frontend — only transport,
|
|
109
111
|
normalization, clear provenance badges, and graceful fallback. When the live
|
|
110
112
|
chat backend reports `no_model_loaded`, v3 Chat shows a setup message instead of
|
|
111
|
-
falling back to
|
|
113
|
+
falling back to generated text.
|
|
112
114
|
|
|
113
|
-
Embedding disclosure:
|
|
114
|
-
`lattice-local-hash-v1
|
|
115
|
-
|
|
115
|
+
Embedding disclosure: production profiles are exposed for local/Ollama/MLX and
|
|
116
|
+
OpenAI-compatible providers. `lattice-local-hash-v1` remains a deterministic
|
|
117
|
+
fallback and is not presented as a production semantic embedding model.
|
|
116
118
|
|
|
117
119
|
---
|
|
118
120
|
|
|
@@ -131,6 +133,7 @@ focus rings, skip link, keyboard command palette (⌘K / Ctrl-K).
|
|
|
131
133
|
## Validation
|
|
132
134
|
|
|
133
135
|
- `npm run lint` (extended to cover `static/v3/**` via `scripts/lint_v3.mjs`).
|
|
136
|
+
- `npm run build:assets` (writes hashed v3 assets and `asset-manifest.json`).
|
|
134
137
|
- `npm run test:visual` (`tests/visual/v3.spec.js` against the mock server, which
|
|
135
138
|
serves `/app` and mocks the future API surfaces).
|
|
136
139
|
- Browser-rendered smoke checks of every route in light and dark themes.
|
package/latticeai/__init__.py
CHANGED
package/latticeai/api/auth.py
CHANGED
|
@@ -57,6 +57,7 @@ def create_auth_router(
|
|
|
57
57
|
public_sso_config: Callable[..., Dict],
|
|
58
58
|
open_registration: bool,
|
|
59
59
|
session_ttl: int,
|
|
60
|
+
require_auth: bool = True,
|
|
60
61
|
) -> APIRouter:
|
|
61
62
|
router = APIRouter()
|
|
62
63
|
|
|
@@ -221,7 +222,9 @@ def create_auth_router(
|
|
|
221
222
|
async def get_profile(request: Request):
|
|
222
223
|
email = require_user(request)
|
|
223
224
|
if not email:
|
|
224
|
-
|
|
225
|
+
if require_auth:
|
|
226
|
+
raise HTTPException(status_code=401, detail="인증이 필요합니다.")
|
|
227
|
+
return {"email": "", "name": "Local User", "nickname": "You", "role": "admin", "is_admin": True}
|
|
225
228
|
users = load_users()
|
|
226
229
|
user = users.get(email)
|
|
227
230
|
if not user:
|
package/latticeai/api/search.py
CHANGED
|
@@ -7,6 +7,7 @@ from typing import Any, Callable, Dict, Optional
|
|
|
7
7
|
from fastapi import APIRouter, HTTPException, Request
|
|
8
8
|
from pydantic import BaseModel, Field
|
|
9
9
|
|
|
10
|
+
from latticeai.core.embedding_providers import embedding_provider_profiles
|
|
10
11
|
from latticeai.services.search_service import DEFAULT_HYBRID_WEIGHTS, SearchService
|
|
11
12
|
|
|
12
13
|
|
|
@@ -213,9 +214,12 @@ def create_search_router(
|
|
|
213
214
|
async def embeddings_providers(request: Request) -> Dict[str, Any]:
|
|
214
215
|
require_user(request)
|
|
215
216
|
resolved = embedding_info() if embedding_info else {}
|
|
217
|
+
profiles = resolved.get("profiles") or embedding_provider_profiles()
|
|
216
218
|
return {
|
|
217
219
|
"active": resolved.get("active_provider"),
|
|
218
220
|
"requested": resolved.get("requested_provider"),
|
|
221
|
+
"profile": resolved.get("profile") or "",
|
|
222
|
+
"profiles": profiles,
|
|
219
223
|
"providers": [
|
|
220
224
|
{"id": "hash", "label": "Local hash (fallback)", "grade": "fallback",
|
|
221
225
|
"requires": [], "detail": "Deterministic offline vectors — always available."},
|
package/latticeai/core/config.py
CHANGED
|
@@ -95,6 +95,7 @@ class Config:
|
|
|
95
95
|
|
|
96
96
|
# ── embeddings (retrieval vector signal) ────────────────────────
|
|
97
97
|
embedding_provider: str
|
|
98
|
+
embedding_profile: str
|
|
98
99
|
embedding_model: str
|
|
99
100
|
embedding_base_url: str
|
|
100
101
|
embedding_api_key: str
|
|
@@ -174,6 +175,7 @@ class Config:
|
|
|
174
175
|
local_draft_model=_value(env, "LATTICEAI_LOCAL_DRAFT_MODEL", ""),
|
|
175
176
|
auto_read_chat_paths=_bool(env, "LATTICEAI_AUTO_READ_CHAT_PATHS", default=False),
|
|
176
177
|
embedding_provider=_value(env, "LATTICEAI_EMBEDDING_PROVIDER", "hash").strip().lower(),
|
|
178
|
+
embedding_profile=_value(env, "LATTICEAI_EMBEDDING_PROFILE", "").strip().lower(),
|
|
177
179
|
embedding_model=_value(env, "LATTICEAI_EMBEDDING_MODEL", ""),
|
|
178
180
|
embedding_base_url=_value(env, "LATTICEAI_EMBEDDING_BASE_URL", ""),
|
|
179
181
|
embedding_api_key=_value(env, "LATTICEAI_EMBEDDING_API_KEY", ""),
|
|
@@ -51,6 +51,7 @@ class EmbeddingUnavailable(RuntimeError):
|
|
|
51
51
|
# identity is stable before the first (possibly remote) call. A configured
|
|
52
52
|
# ``dim`` always wins; an unknown model falls back to a one-time live probe.
|
|
53
53
|
_KNOWN_DIMS = {
|
|
54
|
+
"bge-m3": 1024,
|
|
54
55
|
"nomic-embed-text": 768,
|
|
55
56
|
"mxbai-embed-large": 1024,
|
|
56
57
|
"all-minilm": 384,
|
|
@@ -61,12 +62,131 @@ _KNOWN_DIMS = {
|
|
|
61
62
|
"gte-small": 384,
|
|
62
63
|
"gte-base": 768,
|
|
63
64
|
"gte-large": 1024,
|
|
65
|
+
"e5-large": 1024,
|
|
66
|
+
"multilingual-e5-large": 1024,
|
|
64
67
|
"text-embedding-3-small": 1536,
|
|
65
68
|
"text-embedding-3-large": 3072,
|
|
66
69
|
"text-embedding-ada-002": 1536,
|
|
67
70
|
}
|
|
68
71
|
|
|
69
72
|
|
|
73
|
+
PRODUCTION_PROVIDER_PROFILES: Dict[str, Dict[str, Any]] = {
|
|
74
|
+
"local:bge-m3": {
|
|
75
|
+
"id": "local:bge-m3",
|
|
76
|
+
"provider": "mlx",
|
|
77
|
+
"model": "bge-m3",
|
|
78
|
+
"dimensions": 1024,
|
|
79
|
+
"grade": "production",
|
|
80
|
+
"family": "local",
|
|
81
|
+
"label": "BGE-M3 local",
|
|
82
|
+
"detail": "Multilingual semantic embeddings for local retrieval.",
|
|
83
|
+
},
|
|
84
|
+
"local:nomic-embed-text": {
|
|
85
|
+
"id": "local:nomic-embed-text",
|
|
86
|
+
"provider": "ollama",
|
|
87
|
+
"model": "nomic-embed-text",
|
|
88
|
+
"dimensions": 768,
|
|
89
|
+
"grade": "production",
|
|
90
|
+
"family": "local",
|
|
91
|
+
"label": "Nomic Embed Text local",
|
|
92
|
+
"detail": "General-purpose local semantic embeddings.",
|
|
93
|
+
},
|
|
94
|
+
"local:e5-large": {
|
|
95
|
+
"id": "local:e5-large",
|
|
96
|
+
"provider": "mlx",
|
|
97
|
+
"model": "e5-large",
|
|
98
|
+
"dimensions": 1024,
|
|
99
|
+
"grade": "production",
|
|
100
|
+
"family": "local",
|
|
101
|
+
"label": "E5 Large local",
|
|
102
|
+
"detail": "High-recall local retrieval profile.",
|
|
103
|
+
},
|
|
104
|
+
"local:gte-large": {
|
|
105
|
+
"id": "local:gte-large",
|
|
106
|
+
"provider": "mlx",
|
|
107
|
+
"model": "gte-large",
|
|
108
|
+
"dimensions": 1024,
|
|
109
|
+
"grade": "production",
|
|
110
|
+
"family": "local",
|
|
111
|
+
"label": "GTE Large local",
|
|
112
|
+
"detail": "Large local semantic embedding profile.",
|
|
113
|
+
},
|
|
114
|
+
"ollama:nomic-embed-text": {
|
|
115
|
+
"id": "ollama:nomic-embed-text",
|
|
116
|
+
"provider": "ollama",
|
|
117
|
+
"model": "nomic-embed-text",
|
|
118
|
+
"dimensions": 768,
|
|
119
|
+
"grade": "production",
|
|
120
|
+
"family": "ollama",
|
|
121
|
+
"label": "Ollama Nomic Embed Text",
|
|
122
|
+
"detail": "Production semantic embeddings through Ollama.",
|
|
123
|
+
},
|
|
124
|
+
"ollama:mxbai-embed-large": {
|
|
125
|
+
"id": "ollama:mxbai-embed-large",
|
|
126
|
+
"provider": "ollama",
|
|
127
|
+
"model": "mxbai-embed-large",
|
|
128
|
+
"dimensions": 1024,
|
|
129
|
+
"grade": "production",
|
|
130
|
+
"family": "ollama",
|
|
131
|
+
"label": "Ollama MXBAI Embed Large",
|
|
132
|
+
"detail": "High-quality local semantic embeddings through Ollama.",
|
|
133
|
+
},
|
|
134
|
+
"ollama:bge-m3": {
|
|
135
|
+
"id": "ollama:bge-m3",
|
|
136
|
+
"provider": "ollama",
|
|
137
|
+
"model": "bge-m3",
|
|
138
|
+
"dimensions": 1024,
|
|
139
|
+
"grade": "production",
|
|
140
|
+
"family": "ollama",
|
|
141
|
+
"label": "Ollama BGE-M3-compatible",
|
|
142
|
+
"detail": "BGE-M3-compatible providers exposed through Ollama.",
|
|
143
|
+
},
|
|
144
|
+
"mlx:bge-m3": {
|
|
145
|
+
"id": "mlx:bge-m3",
|
|
146
|
+
"provider": "mlx",
|
|
147
|
+
"model": "bge-m3",
|
|
148
|
+
"dimensions": 1024,
|
|
149
|
+
"grade": "production",
|
|
150
|
+
"family": "mlx",
|
|
151
|
+
"label": "MLX BGE-M3",
|
|
152
|
+
"detail": "Apple Silicon optimized local embeddings.",
|
|
153
|
+
},
|
|
154
|
+
"openai:text-embedding-3-small": {
|
|
155
|
+
"id": "openai:text-embedding-3-small",
|
|
156
|
+
"provider": "openai",
|
|
157
|
+
"model": "text-embedding-3-small",
|
|
158
|
+
"dimensions": 1536,
|
|
159
|
+
"grade": "production",
|
|
160
|
+
"family": "openai-compatible",
|
|
161
|
+
"label": "OpenAI-compatible small",
|
|
162
|
+
"detail": "OpenAI-compatible /v1/embeddings endpoint.",
|
|
163
|
+
},
|
|
164
|
+
"openai:text-embedding-3-large": {
|
|
165
|
+
"id": "openai:text-embedding-3-large",
|
|
166
|
+
"provider": "openai",
|
|
167
|
+
"model": "text-embedding-3-large",
|
|
168
|
+
"dimensions": 3072,
|
|
169
|
+
"grade": "production",
|
|
170
|
+
"family": "openai-compatible",
|
|
171
|
+
"label": "OpenAI-compatible large",
|
|
172
|
+
"detail": "Highest-dimensional OpenAI-compatible embedding profile.",
|
|
173
|
+
},
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def embedding_provider_profiles() -> List[Dict[str, Any]]:
|
|
178
|
+
return [dict(PRODUCTION_PROVIDER_PROFILES[key]) for key in sorted(PRODUCTION_PROVIDER_PROFILES)]
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def resolve_embedding_profile(profile: str) -> Dict[str, Any]:
|
|
182
|
+
if not profile:
|
|
183
|
+
return {}
|
|
184
|
+
key = str(profile).strip().lower()
|
|
185
|
+
if key in PRODUCTION_PROVIDER_PROFILES:
|
|
186
|
+
return dict(PRODUCTION_PROVIDER_PROFILES[key])
|
|
187
|
+
raise ValueError(f"unknown embedding profile: {profile!r}")
|
|
188
|
+
|
|
189
|
+
|
|
70
190
|
def _guess_dim(model: str, default: int) -> int:
|
|
71
191
|
key = str(model or "").split("/")[-1].strip().lower()
|
|
72
192
|
key = key.split(":")[0]
|
|
@@ -498,5 +618,8 @@ __all__ = [
|
|
|
498
618
|
"ResolvedEmbedder",
|
|
499
619
|
"build_embedding_provider",
|
|
500
620
|
"resolve_embedder",
|
|
621
|
+
"resolve_embedding_profile",
|
|
622
|
+
"embedding_provider_profiles",
|
|
623
|
+
"PRODUCTION_PROVIDER_PROFILES",
|
|
501
624
|
"PROVIDER_TYPES",
|
|
502
625
|
]
|
|
@@ -18,7 +18,7 @@ from pathlib import Path
|
|
|
18
18
|
from typing import Any, Callable, Dict, Iterable, List, Optional
|
|
19
19
|
|
|
20
20
|
|
|
21
|
-
WORKSPACE_OS_VERSION = "3.0
|
|
21
|
+
WORKSPACE_OS_VERSION = "3.1.0"
|
|
22
22
|
|
|
23
23
|
# Workspace types separate single-user Personal workspaces from shared
|
|
24
24
|
# Organization workspaces. Both keep the same local-first JSON store; the type
|
package/latticeai/server_app.py
CHANGED
|
@@ -73,7 +73,7 @@ from latticeai.services.workspace_service import WorkspaceService
|
|
|
73
73
|
from latticeai.services.model_service import ModelService
|
|
74
74
|
from latticeai.services.chat_service import ChatService
|
|
75
75
|
from latticeai.services.search_service import SearchService
|
|
76
|
-
from latticeai.core.embedding_providers import resolve_embedder
|
|
76
|
+
from latticeai.core.embedding_providers import resolve_embedder, resolve_embedding_profile
|
|
77
77
|
from latticeai.services.agent_runtime import AgentRuntime
|
|
78
78
|
from latticeai.services.model_runtime import (
|
|
79
79
|
CLOUD_VERIFY_TTL_SECONDS,
|
|
@@ -251,15 +251,26 @@ SSO_FILE = DATA_DIR / "sso_config.json"
|
|
|
251
251
|
# Resolve the configured embedding provider once at startup. Degrades to the
|
|
252
252
|
# offline hash fallback when the requested provider is unavailable, while
|
|
253
253
|
# recording the requested-vs-active provider for the Embeddings status surface.
|
|
254
|
+
try:
|
|
255
|
+
EMBEDDING_PROFILE = resolve_embedding_profile(CONFIG.embedding_profile)
|
|
256
|
+
except ValueError as exc:
|
|
257
|
+
logging.warning("Embedding profile ignored: %s", exc)
|
|
258
|
+
EMBEDDING_PROFILE = {}
|
|
259
|
+
_embedding_provider = CONFIG.embedding_provider
|
|
260
|
+
_embedding_model = CONFIG.embedding_model or str(EMBEDDING_PROFILE.get("model") or "")
|
|
261
|
+
_embedding_dim = CONFIG.embedding_dim or int(EMBEDDING_PROFILE.get("dimensions") or 0)
|
|
262
|
+
if CONFIG.embedding_profile and CONFIG.embedding_provider in {"", "hash", "local", "fallback"}:
|
|
263
|
+
_embedding_provider = str(EMBEDDING_PROFILE.get("provider") or CONFIG.embedding_provider)
|
|
264
|
+
|
|
254
265
|
EMBEDDER = resolve_embedder(
|
|
255
|
-
|
|
256
|
-
model=
|
|
266
|
+
_embedding_provider,
|
|
267
|
+
model=_embedding_model,
|
|
257
268
|
base_url=CONFIG.embedding_base_url,
|
|
258
269
|
api_key=CONFIG.embedding_api_key,
|
|
259
|
-
dim=
|
|
270
|
+
dim=_embedding_dim,
|
|
260
271
|
timeout=CONFIG.embedding_timeout,
|
|
261
272
|
extra={"target": CONFIG.embedding_custom_target},
|
|
262
|
-
probe=
|
|
273
|
+
probe=_embedding_provider not in {"", "hash", "local", "fallback"},
|
|
263
274
|
)
|
|
264
275
|
if EMBEDDER.fell_back:
|
|
265
276
|
logging.warning("Embedding provider %s unavailable: %s", EMBEDDER.requested, EMBEDDER.detail)
|
|
@@ -805,6 +816,8 @@ def _require_local_approval(
|
|
|
805
816
|
|
|
806
817
|
def require_admin(request: Request) -> tuple[str, Dict]:
|
|
807
818
|
users = load_users()
|
|
819
|
+
if not REQUIRE_AUTH:
|
|
820
|
+
return "", users
|
|
808
821
|
token = _extract_bearer_token(request)
|
|
809
822
|
if token:
|
|
810
823
|
email = get_session_email(token)
|
|
@@ -1100,6 +1113,7 @@ app.include_router(create_auth_router(
|
|
|
1100
1113
|
get_sso_settings=get_sso_settings, get_sso_discovery=_get_sso_discovery,
|
|
1101
1114
|
public_sso_config=public_sso_config,
|
|
1102
1115
|
open_registration=OPEN_REGISTRATION, session_ttl=_SESSION_TTL,
|
|
1116
|
+
require_auth=REQUIRE_AUTH,
|
|
1103
1117
|
))
|
|
1104
1118
|
|
|
1105
1119
|
def _graph_stats_safe():
|
|
@@ -1387,9 +1401,11 @@ app.include_router(create_chat_router(
|
|
|
1387
1401
|
))
|
|
1388
1402
|
|
|
1389
1403
|
def _embedding_info() -> dict:
|
|
1390
|
-
from latticeai.core.embedding_providers import PROVIDER_TYPES
|
|
1404
|
+
from latticeai.core.embedding_providers import PROVIDER_TYPES, embedding_provider_profiles
|
|
1391
1405
|
info = EMBEDDER.as_dict()
|
|
1392
1406
|
info["available_providers"] = list(PROVIDER_TYPES)
|
|
1407
|
+
info["profile"] = CONFIG.embedding_profile or ""
|
|
1408
|
+
info["profiles"] = embedding_provider_profiles()
|
|
1393
1409
|
return info
|
|
1394
1410
|
|
|
1395
1411
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ltcai",
|
|
3
|
-
"version": "3.0
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"description": "Lattice AI v3 local-first AI workspace platform with knowledge graph, vector index, hybrid search, agents, and workspace modes.",
|
|
5
5
|
"homepage": "https://github.com/TaeSooPark-PTS/LatticeAI#readme",
|
|
6
6
|
"repository": {
|
|
@@ -17,9 +17,10 @@
|
|
|
17
17
|
"scripts": {
|
|
18
18
|
"start": "LTCAI",
|
|
19
19
|
"dev": "python3 ltcai_cli.py --reload",
|
|
20
|
-
"build": "npm run build:python",
|
|
20
|
+
"build": "npm run build:assets && npm run build:python",
|
|
21
|
+
"build:assets": "node scripts/build_v3_assets.mjs",
|
|
21
22
|
"build:python": "python3 -m build",
|
|
22
|
-
"check:python": "python3 -m py_compile ltcai_cli.py server.py latticeai/server_app.py latticeai/api/chat.py latticeai/api/computer_use.py latticeai/api/deps.py latticeai/api/garden.py latticeai/api/local_files.py latticeai/api/permissions.py latticeai/api/setup.py latticeai/api/static_routes.py latticeai/api/tools.py latticeai/api/plugins.py latticeai/api/workflow_designer.py latticeai/api/agents.py latticeai/api/realtime.py latticeai/api/marketplace.py latticeai/api/search.py latticeai/services/search_service.py latticeai/core/local_embeddings.py latticeai/core/embedding_providers.py latticeai/services/agent_runtime.py latticeai/core/config.py latticeai/api/admin.py latticeai/services/app_context.py latticeai/services/model_runtime.py latticeai/services/model_catalog.py latticeai/services/model_recommendation.py latticeai/services/tool_dispatch.py latticeai/services/upload_service.py latticeai/core/tool_registry.py latticeai/core/enterprise.py latticeai/core/enterprise_admin.py latticeai/core/agent_prompts.py latticeai/core/workspace_os.py latticeai/core/plugins.py latticeai/core/marketplace.py latticeai/core/workflow_engine.py latticeai/core/multi_agent.py latticeai/core/realtime.py knowledge_graph.py knowledge_graph_api.py local_knowledge_api.py llm_router.py p_reinforce.py telegram_bot.py tools.py codex_telegram_bot.py",
|
|
23
|
+
"check:python": "python3 -m py_compile ltcai_cli.py server.py latticeai/server_app.py latticeai/api/auth.py latticeai/api/chat.py latticeai/api/computer_use.py latticeai/api/deps.py latticeai/api/garden.py latticeai/api/local_files.py latticeai/api/permissions.py latticeai/api/setup.py latticeai/api/static_routes.py latticeai/api/tools.py latticeai/api/plugins.py latticeai/api/workflow_designer.py latticeai/api/agents.py latticeai/api/realtime.py latticeai/api/marketplace.py latticeai/api/search.py latticeai/services/search_service.py latticeai/core/local_embeddings.py latticeai/core/embedding_providers.py latticeai/services/agent_runtime.py latticeai/core/config.py latticeai/api/admin.py latticeai/services/app_context.py latticeai/services/model_runtime.py latticeai/services/model_catalog.py latticeai/services/model_recommendation.py latticeai/services/tool_dispatch.py latticeai/services/upload_service.py latticeai/core/tool_registry.py latticeai/core/enterprise.py latticeai/core/enterprise_admin.py latticeai/core/agent_prompts.py latticeai/core/workspace_os.py latticeai/core/plugins.py latticeai/core/marketplace.py latticeai/core/workflow_engine.py latticeai/core/multi_agent.py latticeai/core/realtime.py knowledge_graph.py knowledge_graph_api.py local_knowledge_api.py llm_router.py p_reinforce.py telegram_bot.py tools.py codex_telegram_bot.py",
|
|
23
24
|
"lint": "node --check static/scripts/account.js && node --check static/scripts/admin.js && node --check static/scripts/chat.js && node --check static/scripts/graph.js && node --check static/scripts/platform.js && node --check static/scripts/ux.js && node --check static/scripts/workspace.js && node --check tests/visual/mock_server.cjs && node --check tests/visual/v3.spec.js && npm run lint:v3",
|
|
24
25
|
"lint:v3": "node scripts/lint_v3.mjs",
|
|
25
26
|
"typecheck": "cd vscode-extension && npm run build",
|
|
@@ -32,7 +33,7 @@
|
|
|
32
33
|
"capture:skills": "node scripts/capture/capture_skills.js",
|
|
33
34
|
"capture:enterprise": "node scripts/capture/capture_enterprise.js",
|
|
34
35
|
"capture:onboarding": "node scripts/capture/capture_onboarding.js",
|
|
35
|
-
"release:artifacts": "npm run build:python && npm pack && cd vscode-extension && npm run package:vsix",
|
|
36
|
+
"release:artifacts": "npm run build:assets && npm run build:python && npm pack && cd vscode-extension && npm run package:vsix",
|
|
36
37
|
"release:validate": "python3 scripts/validate_release_artifacts.py $npm_package_version --require-vsix --require-tgz",
|
|
37
38
|
"publish:npm": "npm pack && npm publish ltcai-$npm_package_version.tgz --access public",
|
|
38
39
|
"publish:pypi": "npm run build:python && python3 -m twine upload --skip-existing dist/ltcai-$npm_package_version.tar.gz dist/ltcai-$npm_package_version-py3-none-any.whl",
|
|
@@ -93,7 +94,11 @@
|
|
|
93
94
|
"static/v3/",
|
|
94
95
|
"static/icons/",
|
|
95
96
|
"plugins/",
|
|
97
|
+
"scripts/",
|
|
96
98
|
"docs/",
|
|
99
|
+
"!docs/images/tmp_frames/",
|
|
100
|
+
"!**/__pycache__/",
|
|
101
|
+
"!**/*.pyc",
|
|
97
102
|
"requirements.txt",
|
|
98
103
|
"README.md"
|
|
99
104
|
],
|