ltcai 7.1.0 → 7.3.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 +26 -19
- package/docs/CHANGELOG.md +41 -0
- package/docs/ROADMAP_RECOMMENDATIONS.md +55 -0
- package/frontend/src/api/client.ts +3 -0
- package/frontend/src/features/admin/AdminConsole.tsx +41 -1
- package/frontend/src/i18n.ts +24 -0
- package/frontend/src/styles.css +45 -0
- package/lattice_brain/__init__.py +1 -1
- package/lattice_brain/runtime/agent_runtime.py +62 -1
- package/lattice_brain/runtime/contracts.py +107 -0
- package/lattice_brain/runtime/multi_agent.py +6 -2
- package/latticeai/__init__.py +1 -1
- package/latticeai/api/agents.py +12 -0
- package/latticeai/api/tools.py +14 -0
- package/latticeai/core/agent.py +5 -0
- package/latticeai/core/marketplace.py +1 -1
- package/latticeai/core/tool_registry.py +47 -0
- package/latticeai/core/workspace_os.py +1 -1
- package/latticeai/services/tool_dispatch.py +14 -0
- package/package.json +1 -1
- package/scripts/brain_quality_eval.py +24 -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 +28 -28
- package/static/app/assets/{Act-BHEb8bAM.js → Act-Di4tRFWY.js} +2 -2
- package/static/app/assets/{Act-BHEb8bAM.js.map → Act-Di4tRFWY.js.map} +1 -1
- package/static/app/assets/{Brain-yvR7xkrV.js → Brain-BZB3Gy9w.js} +2 -2
- package/static/app/assets/{Brain-yvR7xkrV.js.map → Brain-BZB3Gy9w.js.map} +1 -1
- package/static/app/assets/{Capture-BrAmsSEH.js → Capture-tNyYWxnh.js} +2 -2
- package/static/app/assets/{Capture-BrAmsSEH.js.map → Capture-tNyYWxnh.js.map} +1 -1
- package/static/app/assets/{Library-BOVzYfxI.js → Library-DAtDDLdg.js} +2 -2
- package/static/app/assets/{Library-BOVzYfxI.js.map → Library-DAtDDLdg.js.map} +1 -1
- package/static/app/assets/{System-D4WaN4kj.js → System-DEu0xNUc.js} +2 -2
- package/static/app/assets/{System-D4WaN4kj.js.map → System-DEu0xNUc.js.map} +1 -1
- package/static/app/assets/{index-DvLsGy-z.css → index-Bi_bpigM.css} +1 -1
- package/static/app/assets/{index-BOB-W1FZ.js → index-COuGp7_5.js} +3 -3
- package/static/app/assets/index-COuGp7_5.js.map +1 -0
- package/static/app/assets/{primitives-C3_BfUb8.js → primitives-CdwcE--L.js} +2 -2
- package/static/app/assets/{primitives-C3_BfUb8.js.map → primitives-CdwcE--L.js.map} +1 -1
- package/static/app/assets/{textarea-CbvhHvzg.js → textarea-CqOdBPL1.js} +2 -2
- package/static/app/assets/{textarea-CbvhHvzg.js.map → textarea-CqOdBPL1.js.map} +1 -1
- package/static/app/index.html +2 -2
- package/static/app/assets/index-BOB-W1FZ.js.map +0 -1
package/latticeai/core/agent.py
CHANGED
|
@@ -30,6 +30,7 @@ from pathlib import Path
|
|
|
30
30
|
from typing import Any, Awaitable, Callable, Dict, FrozenSet, List, Optional
|
|
31
31
|
|
|
32
32
|
from lattice_brain.runtime.hooks import dispatch_tool
|
|
33
|
+
from lattice_brain.runtime.contracts import single_agent_contract
|
|
33
34
|
from tools import ToolError
|
|
34
35
|
|
|
35
36
|
|
|
@@ -142,6 +143,10 @@ class AgentRuntime:
|
|
|
142
143
|
def __init__(self, deps: AgentDeps) -> None:
|
|
143
144
|
self.deps = deps
|
|
144
145
|
|
|
146
|
+
def contract(self, ctx: AgentRunContext, req: Any, *, run_id: Optional[str] = None) -> Dict[str, Any]:
|
|
147
|
+
"""Expose the shared agent-run contract for the single-agent loop."""
|
|
148
|
+
return single_agent_contract(ctx=ctx, goal=getattr(req, "message", ""), run_id=run_id)
|
|
149
|
+
|
|
145
150
|
# ── PLAN ─────────────────────────────────────────────────────────
|
|
146
151
|
async def plan(
|
|
147
152
|
self, ctx: AgentRunContext, req: Any, lang_hint: str, current_user: str,
|
|
@@ -130,6 +130,7 @@ TOOL_GOVERNANCE: Dict[str, ToolPolicy] = {
|
|
|
130
130
|
"todo_read": _r(),
|
|
131
131
|
"local_list": _r(sandbox="home"),
|
|
132
132
|
"local_read": _r(sandbox="home"),
|
|
133
|
+
"read_document": _r(sandbox="home"),
|
|
133
134
|
"git_status": _rs(),
|
|
134
135
|
"git_diff": _rs(),
|
|
135
136
|
"git_log": _rs(),
|
|
@@ -189,6 +190,7 @@ MCP_TOOL_DESCRIPTIONS: Dict[str, str] = {
|
|
|
189
190
|
"clear_history": "Clear chat history to reduce context and speed up responses.",
|
|
190
191
|
"inspect_html": "Inspect local HTML structure and assets.",
|
|
191
192
|
"preview_url": "Return a server URL for a workspace file.",
|
|
193
|
+
"create_web_project": "Create a web project scaffold inside the workspace.",
|
|
192
194
|
"create_docx": "Create a Word DOCX document in the agent workspace.",
|
|
193
195
|
"create_xlsx": "Create an XLSX spreadsheet in the agent workspace.",
|
|
194
196
|
"create_pptx": "Create a PPTX presentation deck in the agent workspace.",
|
|
@@ -251,6 +253,51 @@ class ToolRegistry:
|
|
|
251
253
|
def registered_tools(self) -> frozenset[str]:
|
|
252
254
|
return frozenset(self.handlers)
|
|
253
255
|
|
|
256
|
+
def diagnostics(self) -> Dict[str, Any]:
|
|
257
|
+
"""Return registry drift checks without executing any tool.
|
|
258
|
+
|
|
259
|
+
This is intentionally derived from the live registry instance, not from
|
|
260
|
+
duplicated constants, so admin/runtime surfaces can prove whether the
|
|
261
|
+
dispatch, governance, and catalog projections are still aligned.
|
|
262
|
+
"""
|
|
263
|
+
|
|
264
|
+
registered = set(self.registered_tools())
|
|
265
|
+
governed = set(self.governance)
|
|
266
|
+
described = set(self.descriptions)
|
|
267
|
+
return {
|
|
268
|
+
"ready": not (governed - registered or registered - governed or registered - described),
|
|
269
|
+
"registered_tools": len(registered),
|
|
270
|
+
"governed_tools": len(governed),
|
|
271
|
+
"described_tools": len(described),
|
|
272
|
+
"governance_without_handler": sorted(governed - registered),
|
|
273
|
+
"handler_without_governance": sorted(registered - governed),
|
|
274
|
+
"handler_without_description": sorted(registered - described),
|
|
275
|
+
"description_without_handler": sorted(described - registered),
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
def manifest(self) -> Dict[str, Any]:
|
|
279
|
+
"""Serializable tool registry contract for runtime/admin inspection."""
|
|
280
|
+
|
|
281
|
+
tools = []
|
|
282
|
+
for name in sorted(self.registered_tools() | set(self.governance) | set(self.descriptions)):
|
|
283
|
+
policy = self.policy_for(name, {})
|
|
284
|
+
tools.append({
|
|
285
|
+
"name": name,
|
|
286
|
+
"registered": name in self.handlers,
|
|
287
|
+
"governed": name in self.governance,
|
|
288
|
+
"described": name in self.descriptions,
|
|
289
|
+
"description": self.descriptions.get(name, ""),
|
|
290
|
+
"policy": dict(policy),
|
|
291
|
+
"permission": dict(self.permission(name, {})),
|
|
292
|
+
})
|
|
293
|
+
diagnostics = self.diagnostics()
|
|
294
|
+
return {
|
|
295
|
+
"status": "ok" if diagnostics["ready"] else "degraded",
|
|
296
|
+
"catalog_brief": self.catalog_brief.strip(),
|
|
297
|
+
"diagnostics": diagnostics,
|
|
298
|
+
"tools": tools,
|
|
299
|
+
}
|
|
300
|
+
|
|
254
301
|
def execute(self, action: str, args: Dict[str, Any], *, error_cls: type[Exception]) -> Dict[str, Any]:
|
|
255
302
|
handler = self.handlers.get(action)
|
|
256
303
|
if handler is None:
|
|
@@ -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 = "7.
|
|
22
|
+
WORKSPACE_OS_VERSION = "7.3.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
|
|
@@ -90,6 +90,12 @@ class ToolDispatchService:
|
|
|
90
90
|
def permissions(self) -> list[ToolPermission]:
|
|
91
91
|
return self.registry.permissions()
|
|
92
92
|
|
|
93
|
+
def diagnostics(self) -> Dict[str, Any]:
|
|
94
|
+
return self.registry.diagnostics()
|
|
95
|
+
|
|
96
|
+
def manifest(self) -> Dict[str, Any]:
|
|
97
|
+
return self.registry.manifest()
|
|
98
|
+
|
|
93
99
|
def check_role(self, tool_name: str, current_user: str) -> None:
|
|
94
100
|
if tool_name not in self.registry.admin_only_tools:
|
|
95
101
|
return
|
|
@@ -131,6 +137,14 @@ def list_tool_permissions() -> list:
|
|
|
131
137
|
return DEFAULT_TOOL_DISPATCH_SERVICE.permissions()
|
|
132
138
|
|
|
133
139
|
|
|
140
|
+
def tool_registry_diagnostics() -> Dict[str, Any]:
|
|
141
|
+
return DEFAULT_TOOL_DISPATCH_SERVICE.diagnostics()
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def tool_registry_manifest() -> Dict[str, Any]:
|
|
145
|
+
return DEFAULT_TOOL_DISPATCH_SERVICE.manifest()
|
|
146
|
+
|
|
147
|
+
|
|
134
148
|
def check_tool_role(tool_name: str, current_user: str) -> None:
|
|
135
149
|
DEFAULT_TOOL_DISPATCH_SERVICE.check_role(tool_name, current_user)
|
|
136
150
|
|
package/package.json
CHANGED
|
@@ -12,6 +12,7 @@ import sys
|
|
|
12
12
|
import tempfile
|
|
13
13
|
from pathlib import Path
|
|
14
14
|
|
|
15
|
+
from lattice_brain.quality import RetrievalBenchmarkRunner
|
|
15
16
|
from latticeai.services.memory_service import MemoryService
|
|
16
17
|
|
|
17
18
|
|
|
@@ -110,7 +111,29 @@ def main() -> int:
|
|
|
110
111
|
if proof.get("proofs", {}).get("vector_items", 0) < 1:
|
|
111
112
|
return _fail("vector items must be counted in Brain proof")
|
|
112
113
|
|
|
113
|
-
|
|
114
|
+
benchmark = RetrievalBenchmarkRunner()
|
|
115
|
+
retrieval_metrics = benchmark.run_fixture(
|
|
116
|
+
"7.3.0-hybrid-recall-regression",
|
|
117
|
+
[
|
|
118
|
+
{
|
|
119
|
+
"query": "first five minute Brain proof",
|
|
120
|
+
"relevant": ["note:first-loop", "doc:first-loop"],
|
|
121
|
+
"retrieved": [item.get("id") for item in recall_items],
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
"query": "local-first memory product wedge",
|
|
125
|
+
"relevant": ["decision:pricing"],
|
|
126
|
+
"retrieved": ["decision:pricing", "note:first-loop"],
|
|
127
|
+
},
|
|
128
|
+
],
|
|
129
|
+
top_k=4,
|
|
130
|
+
)
|
|
131
|
+
if retrieval_metrics.get("recall@5", 0.0) < 0.75:
|
|
132
|
+
return _fail(f"hybrid recall regression below threshold: {retrieval_metrics}")
|
|
133
|
+
if retrieval_metrics.get("precision@5", 0.0) < 0.4:
|
|
134
|
+
return _fail(f"hybrid precision regression below threshold: {retrieval_metrics}")
|
|
135
|
+
|
|
136
|
+
print(f"brain-quality-eval: OK {retrieval_metrics}")
|
|
114
137
|
return 0
|
|
115
138
|
|
|
116
139
|
|
package/src-tauri/Cargo.lock
CHANGED
package/src-tauri/Cargo.toml
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "7.
|
|
2
|
+
"version": "7.3.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-CdwcE--L.js": "/static/app/assets/primitives-CdwcE--L.js",
|
|
10
|
+
"_textarea-CqOdBPL1.js": "/static/app/assets/textarea-CqOdBPL1.js",
|
|
11
|
+
"index.html": "/static/app/assets/index-COuGp7_5.js",
|
|
12
|
+
"assets/index-Bi_bpigM.css": "/static/app/assets/index-Bi_bpigM.css",
|
|
13
|
+
"src/pages/Act.tsx": "/static/app/assets/Act-Di4tRFWY.js",
|
|
14
|
+
"src/pages/Brain.tsx": "/static/app/assets/Brain-BZB3Gy9w.js",
|
|
15
|
+
"src/pages/Capture.tsx": "/static/app/assets/Capture-tNyYWxnh.js",
|
|
16
|
+
"src/pages/Library.tsx": "/static/app/assets/Library-DAtDDLdg.js",
|
|
17
|
+
"src/pages/System.tsx": "/static/app/assets/System-DEu0xNUc.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-CdwcE--L.js": {
|
|
27
|
+
"file": "assets/primitives-CdwcE--L.js",
|
|
28
28
|
"name": "primitives",
|
|
29
29
|
"imports": [
|
|
30
30
|
"index.html"
|
|
31
31
|
]
|
|
32
32
|
},
|
|
33
|
-
"_textarea-
|
|
34
|
-
"file": "assets/textarea-
|
|
33
|
+
"_textarea-CqOdBPL1.js": {
|
|
34
|
+
"file": "assets/textarea-CqOdBPL1.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-COuGp7_5.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-Bi_bpigM.css"
|
|
55
55
|
]
|
|
56
56
|
},
|
|
57
57
|
"src/pages/Act.tsx": {
|
|
58
|
-
"file": "assets/Act-
|
|
58
|
+
"file": "assets/Act-Di4tRFWY.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-CdwcE--L.js",
|
|
65
|
+
"_textarea-CqOdBPL1.js"
|
|
66
66
|
]
|
|
67
67
|
},
|
|
68
68
|
"src/pages/Brain.tsx": {
|
|
69
|
-
"file": "assets/Brain-
|
|
69
|
+
"file": "assets/Brain-BZB3Gy9w.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-CdwcE--L.js",
|
|
76
|
+
"_textarea-CqOdBPL1.js"
|
|
77
77
|
]
|
|
78
78
|
},
|
|
79
79
|
"src/pages/Capture.tsx": {
|
|
80
|
-
"file": "assets/Capture-
|
|
80
|
+
"file": "assets/Capture-tNyYWxnh.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-CdwcE--L.js"
|
|
87
87
|
]
|
|
88
88
|
},
|
|
89
89
|
"src/pages/Library.tsx": {
|
|
90
|
-
"file": "assets/Library-
|
|
90
|
+
"file": "assets/Library-DAtDDLdg.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-CdwcE--L.js"
|
|
97
97
|
]
|
|
98
98
|
},
|
|
99
99
|
"src/pages/System.tsx": {
|
|
100
|
-
"file": "assets/System-
|
|
100
|
+
"file": "assets/System-DEu0xNUc.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-CdwcE--L.js"
|
|
107
107
|
]
|
|
108
108
|
}
|
|
109
109
|
}
|