ltcai 6.7.0 → 7.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 +29 -31
- package/docs/CHANGELOG.md +48 -0
- package/frontend/src/App.tsx +80 -0
- package/frontend/src/api/client.ts +11 -0
- package/frontend/src/components/AdminAccessGate.tsx +70 -0
- package/frontend/src/components/BrainConversation.tsx +232 -8
- package/frontend/src/components/FeedbackState.tsx +45 -0
- package/frontend/src/components/WorkspaceProfileSwitcher.tsx +176 -0
- package/frontend/src/components/onboarding/AnalysisScreen.tsx +20 -12
- package/frontend/src/components/onboarding/InstallScreen.tsx +55 -0
- package/frontend/src/components/onboarding/RecommendationScreen.tsx +55 -5
- package/frontend/src/components/onboarding/recommendationModel.ts +59 -2
- package/frontend/src/features/brain/BrainConversation.tsx +382 -7
- package/frontend/src/features/brain/BrainGraphLayer.tsx +258 -25
- package/frontend/src/features/brain/BrainHome.tsx +300 -1
- package/frontend/src/features/brain/brainData.ts +25 -1
- package/frontend/src/features/brain/graphLayout.ts +12 -1
- package/frontend/src/features/brain/types.ts +54 -0
- package/frontend/src/i18n.ts +374 -0
- package/frontend/src/store/appStore.ts +15 -0
- package/frontend/src/styles.css +1383 -41
- package/lattice_brain/__init__.py +1 -1
- package/lattice_brain/runtime/multi_agent.py +1 -1
- package/latticeai/__init__.py +1 -1
- package/latticeai/api/workspace.py +59 -0
- package/latticeai/core/marketplace.py +1 -1
- package/latticeai/core/workspace_os.py +1 -1
- package/package.json +1 -1
- package/scripts/brain_quality_eval.py +118 -0
- 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 +28 -28
- package/static/app/assets/Act-BHEb8bAM.js +2 -0
- package/static/app/assets/{Act-DGN37eR4.js.map → Act-BHEb8bAM.js.map} +1 -1
- package/static/app/assets/Brain-yvR7xkrV.js +322 -0
- package/static/app/assets/Brain-yvR7xkrV.js.map +1 -0
- package/static/app/assets/Capture-BrAmsSEH.js +2 -0
- package/static/app/assets/Capture-BrAmsSEH.js.map +1 -0
- package/static/app/assets/Library-BOVzYfxI.js +2 -0
- package/static/app/assets/{Library-BbagRFyd.js.map → Library-BOVzYfxI.js.map} +1 -1
- package/static/app/assets/System-D4WaN4kj.js +2 -0
- package/static/app/assets/System-D4WaN4kj.js.map +1 -0
- package/static/app/assets/index-BOB-W1FZ.js +17 -0
- package/static/app/assets/index-BOB-W1FZ.js.map +1 -0
- package/static/app/assets/index-DvLsGy-z.css +2 -0
- package/static/app/assets/primitives-C3_BfUb8.js +2 -0
- package/static/app/assets/primitives-C3_BfUb8.js.map +1 -0
- package/static/app/assets/textarea-CbvhHvzg.js +2 -0
- package/static/app/assets/{textarea-C2PLu6_O.js.map → textarea-CbvhHvzg.js.map} +1 -1
- package/static/app/index.html +2 -2
- package/static/app/assets/Act-DGN37eR4.js +0 -2
- package/static/app/assets/Brain-HDcIwPHW.js +0 -322
- package/static/app/assets/Brain-HDcIwPHW.js.map +0 -1
- package/static/app/assets/Capture--eZfb_Ex.js +0 -2
- package/static/app/assets/Capture--eZfb_Ex.js.map +0 -1
- package/static/app/assets/Library-BbagRFyd.js +0 -2
- package/static/app/assets/System-C6pd3Mp_.js +0 -2
- package/static/app/assets/System-C6pd3Mp_.js.map +0 -1
- package/static/app/assets/index-C950aES_.js +0 -17
- package/static/app/assets/index-C950aES_.js.map +0 -1
- package/static/app/assets/index-ztppMg0c.css +0 -2
- package/static/app/assets/primitives-Bcm5lZRu.js +0 -2
- package/static/app/assets/primitives-Bcm5lZRu.js.map +0 -1
- package/static/app/assets/textarea-C2PLu6_O.js +0 -2
|
@@ -19,7 +19,7 @@ from datetime import datetime
|
|
|
19
19
|
from typing import Any, Callable, Dict, List, Optional
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-
MULTI_AGENT_VERSION = "
|
|
22
|
+
MULTI_AGENT_VERSION = "7.1.0"
|
|
23
23
|
|
|
24
24
|
AGENT_ROLES = ("researcher", "planner", "executor", "reviewer", "release")
|
|
25
25
|
CORE_PIPELINE = ("planner", "executor", "reviewer")
|
package/latticeai/__init__.py
CHANGED
|
@@ -99,6 +99,25 @@ class WorkspaceVSCodeRequest(BaseModel):
|
|
|
99
99
|
content: str = ""
|
|
100
100
|
selection: str = ""
|
|
101
101
|
prompt: str = ""
|
|
102
|
+
extension_version: str = ""
|
|
103
|
+
workspace_folder: str = ""
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
class WorkspaceVSCodeStatusRequest(BaseModel):
|
|
107
|
+
status: str = "connected"
|
|
108
|
+
index_status: str = "unknown"
|
|
109
|
+
workspace_folder: str = ""
|
|
110
|
+
extension_version: str = ""
|
|
111
|
+
active_file: str = ""
|
|
112
|
+
detail: str = ""
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
_VSCODE_STATUS: Dict[str, object] = {
|
|
116
|
+
"connected": False,
|
|
117
|
+
"status": "offline",
|
|
118
|
+
"index_status": "unknown",
|
|
119
|
+
"last_seen_ms": 0,
|
|
120
|
+
}
|
|
102
121
|
|
|
103
122
|
|
|
104
123
|
class WorkspaceCreateRequest(BaseModel):
|
|
@@ -630,9 +649,49 @@ def create_workspace_router(context: AppContext) -> APIRouter:
|
|
|
630
649
|
|
|
631
650
|
# ── VS Code workflow bridge ───────────────────────────────────────────
|
|
632
651
|
|
|
652
|
+
@router.get("/workspace/vscode/status")
|
|
653
|
+
async def workspace_vscode_status(request: Request):
|
|
654
|
+
require_user(request)
|
|
655
|
+
last_seen = int(_VSCODE_STATUS.get("last_seen_ms") or 0)
|
|
656
|
+
now_ms = int(datetime.utcnow().timestamp() * 1000)
|
|
657
|
+
connected = last_seen > 0 and (now_ms - last_seen) < 60000
|
|
658
|
+
return {
|
|
659
|
+
**_VSCODE_STATUS,
|
|
660
|
+
"connected": connected,
|
|
661
|
+
"status": _VSCODE_STATUS.get("status") if connected else "offline",
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
@router.post("/workspace/vscode/status")
|
|
665
|
+
async def workspace_vscode_status_update(req: WorkspaceVSCodeStatusRequest, request: Request):
|
|
666
|
+
current_user = require_user(request)
|
|
667
|
+
now_ms = int(datetime.utcnow().timestamp() * 1000)
|
|
668
|
+
_VSCODE_STATUS.update({
|
|
669
|
+
"connected": True,
|
|
670
|
+
"status": req.status or "connected",
|
|
671
|
+
"index_status": req.index_status or "unknown",
|
|
672
|
+
"workspace_folder": req.workspace_folder,
|
|
673
|
+
"extension_version": req.extension_version,
|
|
674
|
+
"active_file": req.active_file,
|
|
675
|
+
"detail": req.detail,
|
|
676
|
+
"last_seen_ms": now_ms,
|
|
677
|
+
"user_email": current_user,
|
|
678
|
+
})
|
|
679
|
+
return {"status": "ok", **_VSCODE_STATUS}
|
|
680
|
+
|
|
633
681
|
@router.post("/workspace/vscode/send")
|
|
634
682
|
async def workspace_vscode_send(req: WorkspaceVSCodeRequest, request: Request):
|
|
635
683
|
current_user = require_user(request)
|
|
684
|
+
now_ms = int(datetime.utcnow().timestamp() * 1000)
|
|
685
|
+
_VSCODE_STATUS.update({
|
|
686
|
+
"connected": True,
|
|
687
|
+
"status": "synced",
|
|
688
|
+
"index_status": "synced",
|
|
689
|
+
"workspace_folder": req.workspace_folder,
|
|
690
|
+
"extension_version": req.extension_version,
|
|
691
|
+
"active_file": req.file_path or "",
|
|
692
|
+
"last_seen_ms": now_ms,
|
|
693
|
+
"user_email": current_user,
|
|
694
|
+
})
|
|
636
695
|
content = req.selection or req.content or req.prompt
|
|
637
696
|
workflow = WORKSPACE_OS.create_workflow(
|
|
638
697
|
name=f"VS Code: {req.action}",
|
|
@@ -19,7 +19,7 @@ from pathlib import Path
|
|
|
19
19
|
from typing import Any, Callable, Dict, Iterable, List, Optional
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-
WORKSPACE_OS_VERSION = "
|
|
22
|
+
WORKSPACE_OS_VERSION = "7.1.0"
|
|
23
23
|
|
|
24
24
|
# Workspace types separate single-user Personal workspaces from shared
|
|
25
25
|
# Organization workspaces. Both keep the same local-first JSON store; the type
|
package/package.json
CHANGED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Deterministic Brain recall/KG quality gate for CI.
|
|
3
|
+
|
|
4
|
+
This is intentionally small and fixture-driven. It guards the product promise
|
|
5
|
+
that the first Brain loop can save context, recall it with source evidence, and
|
|
6
|
+
show model-independent proof without relying on a live model.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import sys
|
|
12
|
+
import tempfile
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
|
|
15
|
+
from latticeai.services.memory_service import MemoryService
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class _EvalStore:
|
|
19
|
+
def __init__(self) -> None:
|
|
20
|
+
self.rows = [
|
|
21
|
+
{
|
|
22
|
+
"id": "decision:pricing",
|
|
23
|
+
"kind": "decision",
|
|
24
|
+
"content": "Use local-first memory as the product wedge for early access customers.",
|
|
25
|
+
"workspace_id": "personal",
|
|
26
|
+
"tags": ["strategy"],
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"id": "note:first-loop",
|
|
30
|
+
"kind": "note",
|
|
31
|
+
"content": "The first five minute loop is add source, ask question, see Brain proof.",
|
|
32
|
+
"workspace_id": "personal",
|
|
33
|
+
"tags": ["onboarding"],
|
|
34
|
+
},
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
def list_memories(self, user_email=None, kind=None, workspace_id=None):
|
|
38
|
+
rows = [row for row in self.rows if kind is None or row["kind"] == kind]
|
|
39
|
+
if workspace_id is not None:
|
|
40
|
+
rows = [row for row in rows if (row.get("workspace_id") or "personal") == workspace_id]
|
|
41
|
+
return {"memories": rows}
|
|
42
|
+
|
|
43
|
+
def list_memory_snapshots(self, workspace_id=None, limit=50):
|
|
44
|
+
return {"snapshots": [{"snapshot_id": "eval-snapshot"}]}
|
|
45
|
+
|
|
46
|
+
def search_memories(self, q, user_email=None, limit=20, workspace_id=None):
|
|
47
|
+
terms = {term for term in (q or "").lower().split() if len(term) > 2}
|
|
48
|
+
rows = [
|
|
49
|
+
row for row in self.rows
|
|
50
|
+
if (workspace_id is None or (row.get("workspace_id") or "personal") == workspace_id)
|
|
51
|
+
and terms.intersection(row["content"].lower().split())
|
|
52
|
+
]
|
|
53
|
+
return {"memories": rows[:limit]}
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class _EvalGraph:
|
|
57
|
+
def stats(self):
|
|
58
|
+
return {"nodes": {"Document": 1, "Decision": 1, "Topic": 1}, "edges": {"mentions": 2}}
|
|
59
|
+
|
|
60
|
+
def index_status(self):
|
|
61
|
+
return {"vector_counts": {"node": 3, "chunk": 2}}
|
|
62
|
+
|
|
63
|
+
def search(self, q, limit=20):
|
|
64
|
+
return {
|
|
65
|
+
"matches": [
|
|
66
|
+
{
|
|
67
|
+
"id": "doc:first-loop",
|
|
68
|
+
"type": "Document",
|
|
69
|
+
"title": "First Brain Loop",
|
|
70
|
+
"summary": "Users add a source, ask a question, and see proof with citations.",
|
|
71
|
+
"score": 0.94,
|
|
72
|
+
"metadata": {"source": "eval:first-loop.md", "workspace_id": "personal"},
|
|
73
|
+
}
|
|
74
|
+
][:limit]
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def _fail(message: str) -> int:
|
|
79
|
+
print(f"brain-quality-eval: FAIL: {message}", file=sys.stderr)
|
|
80
|
+
return 1
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def main() -> int:
|
|
84
|
+
with tempfile.TemporaryDirectory() as tmp:
|
|
85
|
+
service = MemoryService(
|
|
86
|
+
store=_EvalStore(),
|
|
87
|
+
data_dir=Path(tmp),
|
|
88
|
+
knowledge_graph=_EvalGraph(),
|
|
89
|
+
enable_graph=True,
|
|
90
|
+
)
|
|
91
|
+
proof = service.brain_proof(
|
|
92
|
+
recall_query="first five minute Brain proof",
|
|
93
|
+
user_email="eval@example.com",
|
|
94
|
+
workspace_id="personal",
|
|
95
|
+
active_model="eval-model-a",
|
|
96
|
+
limit=4,
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
recall_items = proof.get("recall", {}).get("items", [])
|
|
100
|
+
if proof.get("model_continuity", {}).get("proven") is not True:
|
|
101
|
+
return _fail("model continuity proof must be true when durable evidence exists")
|
|
102
|
+
if proof.get("claims", {}).get("keeps_context_across_models") is not True:
|
|
103
|
+
return _fail("model-independent context claim must be backed by durable evidence")
|
|
104
|
+
if not recall_items:
|
|
105
|
+
return _fail("recall must return at least one memory or KG item")
|
|
106
|
+
if not any(str(item.get("source") or "").lower() in {"workspace", "graph"} for item in recall_items):
|
|
107
|
+
return _fail("recall items must expose a source for citation UI")
|
|
108
|
+
if proof.get("proofs", {}).get("graph_concepts", 0) < 1:
|
|
109
|
+
return _fail("KG concepts must be counted in Brain proof")
|
|
110
|
+
if proof.get("proofs", {}).get("vector_items", 0) < 1:
|
|
111
|
+
return _fail("vector items must be counted in Brain proof")
|
|
112
|
+
|
|
113
|
+
print("brain-quality-eval: OK")
|
|
114
|
+
return 0
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
if __name__ == "__main__":
|
|
118
|
+
raise SystemExit(main())
|
package/src-tauri/Cargo.lock
CHANGED
package/src-tauri/Cargo.toml
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "
|
|
2
|
+
"version": "7.1.0",
|
|
3
3
|
"generated_at": "vite",
|
|
4
4
|
"entrypoints": {
|
|
5
5
|
"app": "/static/app/index.html"
|
|
6
6
|
},
|
|
7
7
|
"assets": {
|
|
8
8
|
"../node_modules/@tauri-apps/api/core.js": "/static/app/assets/core-CwxXejkd.js",
|
|
9
|
-
"_primitives-
|
|
10
|
-
"_textarea-
|
|
11
|
-
"index.html": "/static/app/assets/index-
|
|
12
|
-
"assets/index-
|
|
13
|
-
"src/pages/Act.tsx": "/static/app/assets/Act-
|
|
14
|
-
"src/pages/Brain.tsx": "/static/app/assets/Brain-
|
|
15
|
-
"src/pages/Capture.tsx": "/static/app/assets/Capture
|
|
16
|
-
"src/pages/Library.tsx": "/static/app/assets/Library-
|
|
17
|
-
"src/pages/System.tsx": "/static/app/assets/System-
|
|
9
|
+
"_primitives-C3_BfUb8.js": "/static/app/assets/primitives-C3_BfUb8.js",
|
|
10
|
+
"_textarea-CbvhHvzg.js": "/static/app/assets/textarea-CbvhHvzg.js",
|
|
11
|
+
"index.html": "/static/app/assets/index-BOB-W1FZ.js",
|
|
12
|
+
"assets/index-DvLsGy-z.css": "/static/app/assets/index-DvLsGy-z.css",
|
|
13
|
+
"src/pages/Act.tsx": "/static/app/assets/Act-BHEb8bAM.js",
|
|
14
|
+
"src/pages/Brain.tsx": "/static/app/assets/Brain-yvR7xkrV.js",
|
|
15
|
+
"src/pages/Capture.tsx": "/static/app/assets/Capture-BrAmsSEH.js",
|
|
16
|
+
"src/pages/Library.tsx": "/static/app/assets/Library-BOVzYfxI.js",
|
|
17
|
+
"src/pages/System.tsx": "/static/app/assets/System-D4WaN4kj.js"
|
|
18
18
|
},
|
|
19
19
|
"vite": {
|
|
20
20
|
"../node_modules/@tauri-apps/api/core.js": {
|
|
@@ -23,22 +23,22 @@
|
|
|
23
23
|
"src": "../node_modules/@tauri-apps/api/core.js",
|
|
24
24
|
"isDynamicEntry": true
|
|
25
25
|
},
|
|
26
|
-
"_primitives-
|
|
27
|
-
"file": "assets/primitives-
|
|
26
|
+
"_primitives-C3_BfUb8.js": {
|
|
27
|
+
"file": "assets/primitives-C3_BfUb8.js",
|
|
28
28
|
"name": "primitives",
|
|
29
29
|
"imports": [
|
|
30
30
|
"index.html"
|
|
31
31
|
]
|
|
32
32
|
},
|
|
33
|
-
"_textarea-
|
|
34
|
-
"file": "assets/textarea-
|
|
33
|
+
"_textarea-CbvhHvzg.js": {
|
|
34
|
+
"file": "assets/textarea-CbvhHvzg.js",
|
|
35
35
|
"name": "textarea",
|
|
36
36
|
"imports": [
|
|
37
37
|
"index.html"
|
|
38
38
|
]
|
|
39
39
|
},
|
|
40
40
|
"index.html": {
|
|
41
|
-
"file": "assets/index-
|
|
41
|
+
"file": "assets/index-BOB-W1FZ.js",
|
|
42
42
|
"name": "index",
|
|
43
43
|
"src": "index.html",
|
|
44
44
|
"isEntry": true,
|
|
@@ -51,59 +51,59 @@
|
|
|
51
51
|
"src/pages/System.tsx"
|
|
52
52
|
],
|
|
53
53
|
"css": [
|
|
54
|
-
"assets/index-
|
|
54
|
+
"assets/index-DvLsGy-z.css"
|
|
55
55
|
]
|
|
56
56
|
},
|
|
57
57
|
"src/pages/Act.tsx": {
|
|
58
|
-
"file": "assets/Act-
|
|
58
|
+
"file": "assets/Act-BHEb8bAM.js",
|
|
59
59
|
"name": "Act",
|
|
60
60
|
"src": "src/pages/Act.tsx",
|
|
61
61
|
"isDynamicEntry": true,
|
|
62
62
|
"imports": [
|
|
63
63
|
"index.html",
|
|
64
|
-
"_primitives-
|
|
65
|
-
"_textarea-
|
|
64
|
+
"_primitives-C3_BfUb8.js",
|
|
65
|
+
"_textarea-CbvhHvzg.js"
|
|
66
66
|
]
|
|
67
67
|
},
|
|
68
68
|
"src/pages/Brain.tsx": {
|
|
69
|
-
"file": "assets/Brain-
|
|
69
|
+
"file": "assets/Brain-yvR7xkrV.js",
|
|
70
70
|
"name": "Brain",
|
|
71
71
|
"src": "src/pages/Brain.tsx",
|
|
72
72
|
"isDynamicEntry": true,
|
|
73
73
|
"imports": [
|
|
74
74
|
"index.html",
|
|
75
|
-
"_primitives-
|
|
76
|
-
"_textarea-
|
|
75
|
+
"_primitives-C3_BfUb8.js",
|
|
76
|
+
"_textarea-CbvhHvzg.js"
|
|
77
77
|
]
|
|
78
78
|
},
|
|
79
79
|
"src/pages/Capture.tsx": {
|
|
80
|
-
"file": "assets/Capture
|
|
80
|
+
"file": "assets/Capture-BrAmsSEH.js",
|
|
81
81
|
"name": "Capture",
|
|
82
82
|
"src": "src/pages/Capture.tsx",
|
|
83
83
|
"isDynamicEntry": true,
|
|
84
84
|
"imports": [
|
|
85
85
|
"index.html",
|
|
86
|
-
"_primitives-
|
|
86
|
+
"_primitives-C3_BfUb8.js"
|
|
87
87
|
]
|
|
88
88
|
},
|
|
89
89
|
"src/pages/Library.tsx": {
|
|
90
|
-
"file": "assets/Library-
|
|
90
|
+
"file": "assets/Library-BOVzYfxI.js",
|
|
91
91
|
"name": "Library",
|
|
92
92
|
"src": "src/pages/Library.tsx",
|
|
93
93
|
"isDynamicEntry": true,
|
|
94
94
|
"imports": [
|
|
95
95
|
"index.html",
|
|
96
|
-
"_primitives-
|
|
96
|
+
"_primitives-C3_BfUb8.js"
|
|
97
97
|
]
|
|
98
98
|
},
|
|
99
99
|
"src/pages/System.tsx": {
|
|
100
|
-
"file": "assets/System-
|
|
100
|
+
"file": "assets/System-D4WaN4kj.js",
|
|
101
101
|
"name": "System",
|
|
102
102
|
"src": "src/pages/System.tsx",
|
|
103
103
|
"isDynamicEntry": true,
|
|
104
104
|
"imports": [
|
|
105
105
|
"index.html",
|
|
106
|
-
"_primitives-
|
|
106
|
+
"_primitives-C3_BfUb8.js"
|
|
107
107
|
]
|
|
108
108
|
}
|
|
109
109
|
}
|