ltcai 2.2.2 → 3.0.1
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 +66 -27
- package/codex_telegram_bot.py +6 -2
- package/docs/CHANGELOG.md +154 -0
- package/docs/V3_BACKEND_ARCHITECTURE.md +138 -0
- package/docs/V3_FRONTEND.md +136 -0
- package/knowledge_graph.py +649 -21
- package/latticeai/__init__.py +1 -1
- package/latticeai/api/admin.py +47 -0
- package/latticeai/api/agents.py +54 -31
- package/latticeai/api/auth.py +1 -1
- package/latticeai/api/chat.py +10 -2
- package/latticeai/api/search.py +236 -0
- package/latticeai/api/static_routes.py +21 -2
- package/latticeai/core/config.py +16 -0
- package/latticeai/core/embedding_providers.py +502 -0
- package/latticeai/core/local_embeddings.py +86 -0
- package/latticeai/core/logging_safety.py +62 -0
- package/latticeai/core/workspace_os.py +1 -1
- package/latticeai/server_app.py +49 -1
- package/latticeai/services/agent_runtime.py +245 -0
- package/latticeai/services/search_service.py +346 -0
- package/package.json +8 -4
- package/static/account.html +9 -4
- package/static/activity.html +4 -4
- package/static/admin.html +8 -3
- package/static/agents.html +4 -4
- package/static/chat.html +16 -11
- package/static/css/reference/account.css +439 -0
- package/static/css/reference/admin.css +610 -0
- package/static/css/reference/base.css +1658 -0
- package/static/{lattice-reference.css → css/reference/chat.css} +271 -3633
- package/static/css/reference/graph.css +1016 -0
- package/static/css/responsive.css +248 -1
- package/static/css/tokens.css +132 -126
- package/static/favicon.ico +0 -0
- package/static/graph.html +9 -4
- package/static/manifest.json +3 -3
- package/static/platform.css +1 -1
- package/static/plugins.html +4 -4
- package/static/scripts/account.js +4 -4
- package/static/scripts/chat.js +227 -77
- package/static/scripts/workspace.js +78 -0
- package/static/sw.js +5 -3
- package/static/v3/css/lattice.base.css +128 -0
- package/static/v3/css/lattice.components.css +447 -0
- package/static/v3/css/lattice.shell.css +407 -0
- package/static/v3/css/lattice.tokens.css +132 -0
- package/static/v3/css/lattice.views.css +277 -0
- package/static/v3/index.html +40 -0
- package/static/v3/js/app.js +26 -0
- package/static/v3/js/core/api.js +327 -0
- package/static/v3/js/core/components.js +215 -0
- package/static/v3/js/core/dom.js +148 -0
- package/static/v3/js/core/fixtures.js +171 -0
- package/static/v3/js/core/router.js +37 -0
- package/static/v3/js/core/routes.js +73 -0
- package/static/v3/js/core/shell.js +363 -0
- package/static/v3/js/core/store.js +113 -0
- package/static/v3/js/views/admin-audit.js +185 -0
- package/static/v3/js/views/admin-permissions.js +178 -0
- package/static/v3/js/views/admin-policies.js +103 -0
- package/static/v3/js/views/admin-private-vpc.js +138 -0
- package/static/v3/js/views/admin-security.js +181 -0
- package/static/v3/js/views/admin-users.js +168 -0
- package/static/v3/js/views/agents.js +194 -0
- package/static/v3/js/views/chat.js +450 -0
- package/static/v3/js/views/files.js +180 -0
- package/static/v3/js/views/home.js +119 -0
- package/static/v3/js/views/hybrid-search.js +195 -0
- package/static/v3/js/views/knowledge-graph.js +238 -0
- package/static/v3/js/views/models.js +247 -0
- package/static/v3/js/views/my-computer.js +237 -0
- package/static/v3/js/views/pipeline.js +161 -0
- package/static/v3/js/views/settings.js +258 -0
- package/static/workflows.html +4 -4
- package/static/workspace.css +408 -14
- package/static/workspace.html +43 -24
- package/telegram_bot.py +18 -14
|
@@ -15,6 +15,8 @@ const state = {
|
|
|
15
15
|
|
|
16
16
|
// Skills that match common workspace needs are surfaced under "Recommended".
|
|
17
17
|
const RECOMMENDED_SKILL_HINTS = ["code", "review", "doc", "test", "security", "research", "changelog", "refactor", "debug"];
|
|
18
|
+
const MODE_KEY = "ltcai_workspace_mode";
|
|
19
|
+
const LANG_KEY = "ltcai_lang";
|
|
18
20
|
|
|
19
21
|
function $(id) {
|
|
20
22
|
return document.getElementById(id);
|
|
@@ -51,6 +53,61 @@ function toast(message) {
|
|
|
51
53
|
node._timer = setTimeout(() => node.classList.remove("show"), 2200);
|
|
52
54
|
}
|
|
53
55
|
|
|
56
|
+
function adminAvailableForWorkspace(workspace) {
|
|
57
|
+
const storedAdmin = (() => {
|
|
58
|
+
try { return localStorage.getItem("ltcai_is_admin") === "true"; } catch { return false; }
|
|
59
|
+
})();
|
|
60
|
+
const role = String(workspace?.your_role || "").toLowerCase();
|
|
61
|
+
return storedAdmin || role === "owner" || role === "admin";
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function currentWorkspaceMode() {
|
|
65
|
+
try {
|
|
66
|
+
const mode = localStorage.getItem(MODE_KEY);
|
|
67
|
+
return ["basic", "advanced", "admin"].includes(mode) ? mode : "basic";
|
|
68
|
+
} catch {
|
|
69
|
+
return "basic";
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function applyWorkspaceMode(mode, { adminAvailable = false } = {}) {
|
|
74
|
+
if (mode === "admin" && !adminAvailable) mode = "basic";
|
|
75
|
+
const shell = document.querySelector(".workspace-shell");
|
|
76
|
+
if (shell) shell.dataset.workspaceMode = mode;
|
|
77
|
+
document.querySelectorAll("[data-workspace-mode]").forEach((button) => {
|
|
78
|
+
if (button.matches("button")) {
|
|
79
|
+
const active = button.dataset.workspaceMode === mode;
|
|
80
|
+
button.classList.toggle("active", active);
|
|
81
|
+
button.setAttribute("aria-selected", active ? "true" : "false");
|
|
82
|
+
button.disabled = button.dataset.workspaceMode === "admin" && !adminAvailable;
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
try { localStorage.setItem(MODE_KEY, mode); } catch {}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function updateWorkspaceChrome(activeWorkspace) {
|
|
89
|
+
const shell = document.querySelector(".workspace-shell");
|
|
90
|
+
const adminAvailable = adminAvailableForWorkspace(activeWorkspace);
|
|
91
|
+
if (shell) shell.dataset.adminAvailable = adminAvailable ? "true" : "false";
|
|
92
|
+
applyWorkspaceMode(currentWorkspaceMode(), { adminAvailable });
|
|
93
|
+
const lang = (() => {
|
|
94
|
+
try { return localStorage.getItem(LANG_KEY) || "en"; } catch { return "en"; }
|
|
95
|
+
})();
|
|
96
|
+
document.documentElement.lang = lang;
|
|
97
|
+
const langSelect = $("workspace-language");
|
|
98
|
+
if (langSelect) langSelect.value = lang;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
async function logoutWorkspace() {
|
|
102
|
+
try { await api("/logout", { method: "POST" }); } catch (_) {}
|
|
103
|
+
try {
|
|
104
|
+
localStorage.removeItem("ltcai_user_email");
|
|
105
|
+
localStorage.removeItem("ltcai_user_nickname");
|
|
106
|
+
localStorage.removeItem("ltcai_is_admin");
|
|
107
|
+
} catch (_) {}
|
|
108
|
+
window.location.href = "/account";
|
|
109
|
+
}
|
|
110
|
+
|
|
54
111
|
function renderMetrics(os) {
|
|
55
112
|
const counts = os?.counts || {};
|
|
56
113
|
const graph = os?.graph || {};
|
|
@@ -363,6 +420,7 @@ function renderWorkspaceRegistry(registry, edition) {
|
|
|
363
420
|
`).join("");
|
|
364
421
|
}
|
|
365
422
|
const active = workspaces.find((ws) => ws.workspace_id === state.activeWorkspace);
|
|
423
|
+
updateWorkspaceChrome(active);
|
|
366
424
|
const rolePill = $("workspace-role");
|
|
367
425
|
if (rolePill) rolePill.textContent = active ? (active.your_role || "—") : "";
|
|
368
426
|
if (edition) {
|
|
@@ -837,6 +895,26 @@ document.addEventListener("change", async (event) => {
|
|
|
837
895
|
});
|
|
838
896
|
|
|
839
897
|
document.addEventListener("DOMContentLoaded", () => {
|
|
898
|
+
document.querySelectorAll("[data-workspace-mode]").forEach((button) => {
|
|
899
|
+
if (!button.matches("button")) return;
|
|
900
|
+
button.addEventListener("click", () => {
|
|
901
|
+
const shell = document.querySelector(".workspace-shell");
|
|
902
|
+
const adminAvailable = shell?.dataset.adminAvailable === "true";
|
|
903
|
+
applyWorkspaceMode(button.dataset.workspaceMode, { adminAvailable });
|
|
904
|
+
});
|
|
905
|
+
});
|
|
906
|
+
const language = $("workspace-language");
|
|
907
|
+
if (language) {
|
|
908
|
+
language.value = (() => {
|
|
909
|
+
try { return localStorage.getItem(LANG_KEY) || "en"; } catch { return "en"; }
|
|
910
|
+
})();
|
|
911
|
+
language.addEventListener("change", () => {
|
|
912
|
+
try { localStorage.setItem(LANG_KEY, language.value); } catch (_) {}
|
|
913
|
+
document.documentElement.lang = language.value;
|
|
914
|
+
});
|
|
915
|
+
}
|
|
916
|
+
const logoutButton = $("workspace-logout");
|
|
917
|
+
if (logoutButton) logoutButton.addEventListener("click", () => logoutWorkspace());
|
|
840
918
|
$("refresh-btn").addEventListener("click", () => refreshAll().catch((err) => toast(err.message)));
|
|
841
919
|
$("snapshot-now").addEventListener("click", () => createSnapshot().catch((err) => toast(err.message)));
|
|
842
920
|
$("create-snapshot").addEventListener("click", () => createSnapshot().catch((err) => toast(err.message)));
|
package/static/sw.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
// Lattice AI Service Worker — enables PWA install on Android/iOS
|
|
2
2
|
// Strategy: network-first for API, cache-first for static assets.
|
|
3
|
-
const CACHE = "ltcai-
|
|
3
|
+
const CACHE = "ltcai-v226";
|
|
4
4
|
const STATIC = [
|
|
5
5
|
"/",
|
|
6
6
|
"/workspace",
|
|
7
|
-
"/static/lattice-reference.css",
|
|
8
|
-
"/static/workspace.css",
|
|
9
7
|
"/static/css/tokens.css",
|
|
8
|
+
"/static/css/reference/base.css",
|
|
9
|
+
"/static/css/reference/chat.css",
|
|
10
|
+
"/static/css/responsive.css",
|
|
11
|
+
"/static/workspace.css",
|
|
10
12
|
"/static/scripts/chat.js",
|
|
11
13
|
"/static/scripts/admin.js",
|
|
12
14
|
"/static/scripts/graph.js",
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/* ============================================================================
|
|
2
|
+
* Lattice AI v3 — Base layer (reset + element defaults + lattice backdrop)
|
|
3
|
+
* Token-native: no themed hex values, everything via var(--*).
|
|
4
|
+
* ========================================================================== */
|
|
5
|
+
|
|
6
|
+
*, *::before, *::after { box-sizing: border-box; }
|
|
7
|
+
|
|
8
|
+
html, body { height: 100%; }
|
|
9
|
+
|
|
10
|
+
body {
|
|
11
|
+
margin: 0;
|
|
12
|
+
font-family: var(--lt3-font-sans);
|
|
13
|
+
font-size: var(--lt3-text-md);
|
|
14
|
+
line-height: var(--lt3-leading-normal);
|
|
15
|
+
color: var(--text);
|
|
16
|
+
background: var(--bg);
|
|
17
|
+
-webkit-font-smoothing: antialiased;
|
|
18
|
+
text-rendering: optimizeLegibility;
|
|
19
|
+
overflow: hidden; /* shell owns scroll regions */
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/* The signature lattice backdrop — a faint structural mesh of nodes+edges.
|
|
23
|
+
Sits behind the whole app; reinforces the "lattice" identity without noise. */
|
|
24
|
+
.lt3-app::before {
|
|
25
|
+
content: "";
|
|
26
|
+
position: fixed;
|
|
27
|
+
inset: 0;
|
|
28
|
+
z-index: 0;
|
|
29
|
+
pointer-events: none;
|
|
30
|
+
background:
|
|
31
|
+
radial-gradient(circle at center, var(--lt3-mesh-node) 0.9px, transparent 1.1px),
|
|
32
|
+
linear-gradient(var(--lt3-mesh-line) 1px, transparent 1px),
|
|
33
|
+
linear-gradient(90deg, var(--lt3-mesh-line) 1px, transparent 1px),
|
|
34
|
+
var(--app-bg);
|
|
35
|
+
background-size:
|
|
36
|
+
var(--lt3-mesh-size) var(--lt3-mesh-size),
|
|
37
|
+
var(--lt3-mesh-size) var(--lt3-mesh-size),
|
|
38
|
+
var(--lt3-mesh-size) var(--lt3-mesh-size),
|
|
39
|
+
cover;
|
|
40
|
+
background-position: center;
|
|
41
|
+
mask-image: radial-gradient(ellipse 120% 90% at 50% -10%, #000 55%, transparent 100%);
|
|
42
|
+
opacity: 0.9;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
h1, h2, h3, h4, p, figure { margin: 0; }
|
|
46
|
+
|
|
47
|
+
a { color: inherit; text-decoration: none; }
|
|
48
|
+
|
|
49
|
+
button {
|
|
50
|
+
font: inherit;
|
|
51
|
+
color: inherit;
|
|
52
|
+
cursor: pointer;
|
|
53
|
+
border: none;
|
|
54
|
+
background: none;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
input, select, textarea { font: inherit; color: inherit; }
|
|
58
|
+
|
|
59
|
+
textarea { resize: vertical; }
|
|
60
|
+
|
|
61
|
+
img, svg { display: block; max-width: 100%; }
|
|
62
|
+
|
|
63
|
+
code, pre, kbd, samp { font-family: var(--lt3-font-mono); }
|
|
64
|
+
|
|
65
|
+
:root[data-lt-icons="fallback"] .ti {
|
|
66
|
+
display: inline-grid;
|
|
67
|
+
place-items: center;
|
|
68
|
+
min-width: 1em;
|
|
69
|
+
min-height: 1em;
|
|
70
|
+
font-family: var(--lt3-font-mono);
|
|
71
|
+
font-size: 0.72em;
|
|
72
|
+
font-style: normal;
|
|
73
|
+
font-weight: 800;
|
|
74
|
+
line-height: 1;
|
|
75
|
+
text-transform: uppercase;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
:root[data-lt-icons="fallback"] .ti::before {
|
|
79
|
+
content: attr(data-fallback);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
:focus-visible {
|
|
83
|
+
outline: 2px solid var(--focus-ring);
|
|
84
|
+
outline-offset: 2px;
|
|
85
|
+
border-radius: var(--lt3-radius-xs);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
::-webkit-scrollbar { width: 8px; height: 8px; }
|
|
89
|
+
::-webkit-scrollbar-track { background: transparent; }
|
|
90
|
+
::-webkit-scrollbar-thumb {
|
|
91
|
+
background: color-mix(in srgb, var(--border-strong) 60%, transparent);
|
|
92
|
+
border-radius: 99px;
|
|
93
|
+
border: 2px solid transparent;
|
|
94
|
+
background-clip: padding-box;
|
|
95
|
+
}
|
|
96
|
+
::-webkit-scrollbar-thumb:hover { background: var(--border-strong); background-clip: padding-box; }
|
|
97
|
+
|
|
98
|
+
/* Accessible visually-hidden utility */
|
|
99
|
+
.lt3-sr {
|
|
100
|
+
position: absolute !important;
|
|
101
|
+
width: 1px; height: 1px;
|
|
102
|
+
padding: 0; margin: -1px;
|
|
103
|
+
overflow: hidden; clip: rect(0,0,0,0);
|
|
104
|
+
white-space: nowrap; border: 0;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.lt3-skip {
|
|
108
|
+
position: fixed;
|
|
109
|
+
top: var(--lt3-space-3);
|
|
110
|
+
left: var(--lt3-space-3);
|
|
111
|
+
z-index: var(--lt3-z-toast);
|
|
112
|
+
padding: var(--lt3-space-2) var(--lt3-space-4);
|
|
113
|
+
background: var(--accent);
|
|
114
|
+
color: #fff;
|
|
115
|
+
border-radius: var(--lt3-radius-sm);
|
|
116
|
+
transform: translateY(-200%);
|
|
117
|
+
transition: transform var(--lt3-dur-2) var(--lt3-ease);
|
|
118
|
+
}
|
|
119
|
+
.lt3-skip:focus { transform: translateY(0); }
|
|
120
|
+
|
|
121
|
+
@media (prefers-reduced-motion: reduce) {
|
|
122
|
+
*, *::before, *::after {
|
|
123
|
+
animation-duration: 0.001ms !important;
|
|
124
|
+
animation-iteration-count: 1 !important;
|
|
125
|
+
transition-duration: 0.001ms !important;
|
|
126
|
+
scroll-behavior: auto !important;
|
|
127
|
+
}
|
|
128
|
+
}
|