ltcai 3.3.0 → 3.4.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 +85 -66
- package/docs/CHANGELOG.md +36 -0
- package/docs/architecture.md +2 -1
- package/docs/assets/v3.4.0/agent-run.png +0 -0
- package/docs/assets/v3.4.0/agents.png +0 -0
- package/docs/assets/v3.4.0/before/chat-before.png +0 -0
- package/docs/assets/v3.4.0/before/files-before.png +0 -0
- package/docs/assets/v3.4.0/chat.png +0 -0
- package/docs/assets/v3.4.0/connect-folder.png +0 -0
- package/docs/assets/v3.4.0/files.png +0 -0
- package/docs/assets/v3.4.0/home.png +0 -0
- package/docs/assets/v3.4.0/hooks-dispatch.png +0 -0
- package/docs/assets/v3.4.0/knowledge-graph.png +0 -0
- package/docs/assets/v3.4.0/local-agent.png +0 -0
- package/docs/assets/v3.4.0/memory.png +0 -0
- package/docs/assets/v3.4.0/settings.png +0 -0
- package/docs/assets/v3.4.0/vision-input.png +0 -0
- package/docs/assets/v3.4.0/workflows.png +0 -0
- package/knowledge_graph.py +45 -0
- package/knowledge_graph_api.py +10 -0
- package/latticeai/__init__.py +1 -1
- package/latticeai/api/agents.py +3 -0
- package/latticeai/api/hooks.py +39 -0
- package/latticeai/api/local_files.py +41 -0
- package/latticeai/api/models.py +36 -1
- package/latticeai/api/tools.py +16 -1
- package/latticeai/api/workflow_designer.py +2 -1
- package/latticeai/core/hooks.py +398 -2
- package/latticeai/core/marketplace.py +1 -1
- package/latticeai/core/multi_agent.py +1 -1
- package/latticeai/core/workflow_engine.py +21 -1
- package/latticeai/core/workspace_os.py +1 -1
- package/latticeai/server_app.py +40 -0
- package/latticeai/services/agent_runtime.py +46 -1
- package/latticeai/services/upload_service.py +17 -0
- package/package.json +1 -1
- package/scripts/capture/capture_v340.js +88 -0
- package/static/css/{tokens.8b8e31bd.css → tokens.3ba22e37.css} +109 -109
- package/static/css/tokens.css +109 -109
- package/static/v3/asset-manifest.json +24 -24
- package/static/v3/css/{lattice.components.011e988b.css → lattice.components.9b49d614.css} +57 -32
- package/static/v3/css/lattice.components.css +57 -32
- package/static/v3/css/{lattice.shell.4920f42d.css → lattice.shell.6ceea7c8.css} +75 -31
- package/static/v3/css/lattice.shell.css +75 -31
- package/static/v3/css/lattice.tokens.css +13 -13
- package/static/v3/css/{lattice.tokens.c597ff81.css → lattice.tokens.e7018963.css} +13 -13
- package/static/v3/css/{lattice.views.1d326beb.css → lattice.views.22f69117.css} +93 -15
- package/static/v3/css/lattice.views.css +93 -15
- package/static/v3/js/{app.cf5bb712.js → app.c4acfdd8.js} +1 -1
- package/static/v3/js/core/{api.113660c5.js → api.12b568ad.js} +67 -0
- package/static/v3/js/core/api.js +67 -0
- package/static/v3/js/core/{components.4c83e0a9.js → components.35f02e4c.js} +8 -0
- package/static/v3/js/core/components.js +8 -0
- package/static/v3/js/core/{routes.07ad6696.js → routes.d214b399.js} +16 -12
- package/static/v3/js/core/routes.js +16 -12
- package/static/v3/js/core/{shell.9e707234.js → shell.80a6ad82.js} +37 -9
- package/static/v3/js/core/shell.js +34 -6
- package/static/v3/js/views/agents.014d0b74.js +541 -0
- package/static/v3/js/views/agents.js +305 -57
- package/static/v3/js/views/{chat.c48fd9e2.js → chat.e6dd7dd0.js} +161 -9
- package/static/v3/js/views/chat.js +161 -9
- package/static/v3/js/views/files.adad14c1.js +365 -0
- package/static/v3/js/views/files.js +212 -79
- package/static/v3/js/views/home.24f8b8ae.js +200 -0
- package/static/v3/js/views/home.js +96 -15
- package/static/v3/js/views/hooks.13845954.js +215 -0
- package/static/v3/js/views/hooks.js +117 -1
- package/static/v3/js/views/{my-computer.1b2ff621.js → my-computer.c3ef5283.js} +224 -1
- package/static/v3/js/views/my-computer.js +224 -1
- package/static/v3/js/views/{settings.c7b0cc05.js → settings.8631fa5e.js} +54 -0
- package/static/v3/js/views/settings.js +54 -0
- package/static/v3/js/views/agents.c373d48c.js +0 -293
- package/static/v3/js/views/files.8464634a.js +0 -232
- package/static/v3/js/views/home.cdde3b32.js +0 -119
- package/static/v3/js/views/hooks.f3edebca.js +0 -99
package/static/v3/js/core/api.js
CHANGED
|
@@ -440,6 +440,73 @@ export const api = {
|
|
|
440
440
|
mcpClaudeServers() { return withFallback("/mcp/claude-code-servers", {}, { servers: [] }); },
|
|
441
441
|
mcpCustom() { return withFallback("/mcp/custom", {}, { custom: [] }); },
|
|
442
442
|
mcpRecommend(query, limit = 6) { return raw("/mcp/recommend", { method: "POST", body: { query, limit } }); },
|
|
443
|
+
|
|
444
|
+
/* ── v3.4 Platform Completion ───────────────────────────────────────────
|
|
445
|
+
* Uploaded documents in Files, Connect Folder + Folder Watch over the real
|
|
446
|
+
* on-device runtime, the Local Agent status, and Hooks dispatch/run-log.
|
|
447
|
+
* All endpoints are real (latticeai/api + knowledge_graph_api); fallback-safe. */
|
|
448
|
+
|
|
449
|
+
/** GET /knowledge-graph/documents — uploaded + indexed docs with index state. */
|
|
450
|
+
async documents(limit = 200) {
|
|
451
|
+
const res = await raw(`/knowledge-graph/documents?limit=${encodeURIComponent(limit)}`);
|
|
452
|
+
if (res.ok && res.data && Array.isArray(res.data.documents)) {
|
|
453
|
+
return { ok: true, status: res.status, data: res.data.documents, source: "live", total: res.data.total };
|
|
454
|
+
}
|
|
455
|
+
return { ok: false, status: res.status, data: [], source: "unavailable", error: res.error };
|
|
456
|
+
},
|
|
457
|
+
|
|
458
|
+
// Local Agent (the on-device Lattice runtime: real GET /api/local-agent/status)
|
|
459
|
+
async localAgent() {
|
|
460
|
+
const res = await raw("/api/local-agent/status");
|
|
461
|
+
if (res.ok && res.data && res.data.agent) {
|
|
462
|
+
return { ok: true, status: res.status, data: res.data, source: "live" };
|
|
463
|
+
}
|
|
464
|
+
return {
|
|
465
|
+
ok: false, status: res.status, source: "unavailable",
|
|
466
|
+
data: { agent: { online: false }, health: {}, folders: { connected: 0, watching: 0 }, watch: { available: false, active: {} }, sources: [] },
|
|
467
|
+
};
|
|
468
|
+
},
|
|
469
|
+
|
|
470
|
+
// Connect Folder + Folder Watch (real backend: /knowledge-graph/local/*)
|
|
471
|
+
localRoots() { return withFallback("/knowledge-graph/local/roots", {}, { roots: [] }); },
|
|
472
|
+
async localSources() {
|
|
473
|
+
const res = await raw("/knowledge-graph/local/sources");
|
|
474
|
+
if (res.ok && res.data && Array.isArray(res.data.sources)) {
|
|
475
|
+
return { ok: true, status: res.status, data: res.data, source: "live" };
|
|
476
|
+
}
|
|
477
|
+
return { ok: false, status: res.status, data: { sources: [], watch: { available: false, active: {} } }, source: "unavailable" };
|
|
478
|
+
},
|
|
479
|
+
localWatchStatus() { return raw("/knowledge-graph/local/watch/status"); },
|
|
480
|
+
localWatchStop(source_id) { return raw("/knowledge-graph/local/watch/stop", { method: "POST", body: { source_id } }); },
|
|
481
|
+
approvePermission(token) { return raw(`/permissions/approve/${encodeURIComponent(token)}`, { method: "POST" }); },
|
|
482
|
+
indexFolder(path, opts = {}) {
|
|
483
|
+
return raw("/knowledge-graph/local/index", { method: "POST", body: { path, ...opts } });
|
|
484
|
+
},
|
|
485
|
+
/** One-call Connect Folder: request → self-approve (the click is the consent)
|
|
486
|
+
* → index (+ optional watch). Returns { ok, data, error }. */
|
|
487
|
+
async connectFolder(path, { watch = true, includeOcr = false } = {}) {
|
|
488
|
+
const probe = await raw("/knowledge-graph/local/index", { method: "POST", body: { path, approved: false } });
|
|
489
|
+
const token = probe.data && probe.data.approval_token;
|
|
490
|
+
if (!token) {
|
|
491
|
+
const detail = (probe.data && (probe.data.detail || probe.data.error)) || "the runtime did not return an approval token";
|
|
492
|
+
return { ok: false, error: detail, status: probe.status };
|
|
493
|
+
}
|
|
494
|
+
const approved = await raw(`/permissions/approve/${encodeURIComponent(token)}`, { method: "POST" });
|
|
495
|
+
if (!approved.ok) {
|
|
496
|
+
const detail = (approved.data && (approved.data.detail || approved.data.error)) || "approval failed";
|
|
497
|
+
return { ok: false, error: detail, status: approved.status };
|
|
498
|
+
}
|
|
499
|
+
const res = await raw("/knowledge-graph/local/index", {
|
|
500
|
+
method: "POST",
|
|
501
|
+
body: { path, approved: true, approval_token: token, watch_enabled: watch, include_ocr: includeOcr, consent: { approved: true, source: "files-ui" } },
|
|
502
|
+
});
|
|
503
|
+
if (res.ok && res.data && !res.data.detail) return { ok: true, data: res.data, status: res.status };
|
|
504
|
+
return { ok: false, error: (res.data && (res.data.detail || res.data.error)) || "indexing failed", status: res.status, data: res.data };
|
|
505
|
+
},
|
|
506
|
+
|
|
507
|
+
// Hooks dispatch (real backend: POST /api/hooks/run + GET /api/hooks/runs)
|
|
508
|
+
hookRun(body) { return raw("/api/hooks/run", { method: "POST", body }); },
|
|
509
|
+
hookRuns(limit = 50, kind) { return withFallback(`/api/hooks/runs?limit=${encodeURIComponent(limit)}${kind ? "&kind=" + encodeURIComponent(kind) : ""}`, {}, { runs: [], total: 0 }); },
|
|
443
510
|
};
|
|
444
511
|
|
|
445
512
|
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
@@ -70,6 +70,14 @@ const STATE_VARIANT = {
|
|
|
70
70
|
ready: "ok", active: "ok", indexed: "ok", loaded: "ok", ok: "ok", available: "info",
|
|
71
71
|
idle: "", standby: "", pending: "warn", indexing: "warn", building: "warn",
|
|
72
72
|
failed: "err", error: "err", disabled: "err", not_configured: "",
|
|
73
|
+
// v3.4.0 platform-completion states (Files / Folder Watch / Local Agent /
|
|
74
|
+
// Agent runs / Hook dispatch). Keep these honest: amber for in-progress,
|
|
75
|
+
// green for healthy/active, red for blocked/failed, neutral for inert.
|
|
76
|
+
ingested: "warn", ingesting: "warn", watching: "ok", watched: "ok",
|
|
77
|
+
connected: "ok", online: "ok", offline: "err", synced: "ok",
|
|
78
|
+
queued: "warn", running: "warn", retrying: "warn", retried_ok: "ok",
|
|
79
|
+
rejected: "err", cancelled: "", stopped: "", blocked: "err",
|
|
80
|
+
advisory: "warn", skipped: "", complete: "ok", partial: "warn",
|
|
73
81
|
};
|
|
74
82
|
export function statePill(state) {
|
|
75
83
|
return pill(String(state || "unknown"), STATE_VARIANT[String(state).toLowerCase()] ?? "", { dot: true });
|
|
@@ -70,6 +70,14 @@ const STATE_VARIANT = {
|
|
|
70
70
|
ready: "ok", active: "ok", indexed: "ok", loaded: "ok", ok: "ok", available: "info",
|
|
71
71
|
idle: "", standby: "", pending: "warn", indexing: "warn", building: "warn",
|
|
72
72
|
failed: "err", error: "err", disabled: "err", not_configured: "",
|
|
73
|
+
// v3.4.0 platform-completion states (Files / Folder Watch / Local Agent /
|
|
74
|
+
// Agent runs / Hook dispatch). Keep these honest: amber for in-progress,
|
|
75
|
+
// green for healthy/active, red for blocked/failed, neutral for inert.
|
|
76
|
+
ingested: "warn", ingesting: "warn", watching: "ok", watched: "ok",
|
|
77
|
+
connected: "ok", online: "ok", offline: "err", synced: "ok",
|
|
78
|
+
queued: "warn", running: "warn", retrying: "warn", retried_ok: "ok",
|
|
79
|
+
rejected: "err", cancelled: "", stopped: "", blocked: "err",
|
|
80
|
+
advisory: "warn", skipped: "", complete: "ok", partial: "warn",
|
|
73
81
|
};
|
|
74
82
|
export function statePill(state) {
|
|
75
83
|
return pill(String(state || "unknown"), STATE_VARIANT[String(state).toLowerCase()] ?? "", { dot: true });
|
|
@@ -11,8 +11,8 @@ export const MODE_RANK = { basic: 0, advanced: 1, admin: 2 };
|
|
|
11
11
|
/** Nav groups in display order. */
|
|
12
12
|
export const GROUPS = [
|
|
13
13
|
{ id: "workspace", label: "Workspace" },
|
|
14
|
-
{ id: "retrieval", label: "Retrieval" },
|
|
15
14
|
{ id: "data", label: "Data" },
|
|
15
|
+
{ id: "retrieval", label: "Retrieval" },
|
|
16
16
|
{ id: "compute", label: "Compute" },
|
|
17
17
|
{ id: "platform", label: "Platform" },
|
|
18
18
|
{ id: "system", label: "System" },
|
|
@@ -28,32 +28,35 @@ export const ROUTES = [
|
|
|
28
28
|
{ key: "home", label: "Home", icon: "layout-dashboard", group: "workspace", minMode: "basic", view: "home", title: "Home", desc: "Your local-first AI workspace at a glance." },
|
|
29
29
|
{ key: "chat", label: "Chat", icon: "message-2", group: "workspace", minMode: "basic", view: "chat", title: "Chat", desc: "Grounded conversation over your indexed workspace." },
|
|
30
30
|
|
|
31
|
-
// Retrieval (the product identity)
|
|
32
|
-
{ key: "knowledge-graph", label: "Knowledge Graph", icon: "chart-dots-3", group: "retrieval", minMode: "basic", view: "knowledge-graph", title: "Knowledge Graph", desc: "Entities and relations extracted from your workspace." },
|
|
33
|
-
{ key: "hybrid-search", label: "Hybrid Search", icon: "arrows-join", group: "retrieval", minMode: "basic", view: "hybrid-search", title: "Hybrid Search", desc: "Graph structure fused with vector similarity." },
|
|
34
|
-
{ key: "memory", label: "Memory", icon: "brain", group: "retrieval", minMode: "basic", view: "memory", title: "Memory", desc: "Long-term workspace, project, agent, and conversation memory." },
|
|
35
|
-
|
|
36
31
|
// Data
|
|
37
32
|
{ key: "files", label: "Files", icon: "folders", group: "data", minMode: "basic", view: "files", title: "Files", desc: "Connected sources and indexed documents." },
|
|
38
|
-
|
|
33
|
+
|
|
34
|
+
// Retrieval (the product identity)
|
|
35
|
+
{ key: "hybrid-search", label: "Search", icon: "arrows-join", group: "retrieval", minMode: "basic", view: "hybrid-search", title: "Hybrid Search", desc: "Graph structure fused with vector similarity." },
|
|
36
|
+
{ key: "knowledge-graph", label: "Knowledge", icon: "chart-dots-3", group: "retrieval", minMode: "basic", view: "knowledge-graph", title: "Knowledge Graph", desc: "Entities and relations extracted from your workspace." },
|
|
37
|
+
{ key: "memory", label: "Memory", icon: "brain", group: "retrieval", minMode: "basic", view: "memory", title: "Memory", desc: "Long-term workspace, project, agent, and conversation memory." },
|
|
39
38
|
|
|
40
39
|
// Compute
|
|
40
|
+
{ key: "models", label: "Models", icon: "cpu", group: "compute", minMode: "basic", view: "models", title: "Models", desc: "Local MLX models and embeddings." },
|
|
41
41
|
{ key: "agents", label: "Agents", icon: "robot", group: "compute", minMode: "advanced", view: "agents", title: "Agents", desc: "Multi-agent roles, runs, and handoffs." },
|
|
42
42
|
{ key: "workflows", label: "Workflows", icon: "sitemap", group: "compute", minMode: "advanced", view: "workflows", title: "Workflow Agents", desc: "Trigger → agent chain → tools → memory → result." },
|
|
43
|
-
{ key: "planning", label: "Planning", icon: "target-arrow", group: "compute", minMode: "advanced", view: "planning", title: "Autonomous Planning", desc: "Goal → plan → execute → review → replan." },
|
|
44
|
-
{ key: "models", label: "Models", icon: "cpu", group: "compute", minMode: "basic", view: "models", title: "Models", desc: "Local MLX models and embeddings." },
|
|
45
|
-
{ key: "my-computer", label: "My Computer", icon: "device-desktop-analytics", group: "compute", minMode: "advanced", view: "my-computer", title: "My Computer", desc: "Local hardware, memory, and runtime." },
|
|
46
43
|
|
|
47
44
|
// Platform (the agent ecosystem)
|
|
48
|
-
{ key: "marketplace", label: "Marketplace", icon: "building-store", group: "platform", minMode: "advanced", view: "marketplace", title: "Marketplace", desc: "Agent templates, agents, plugins, and skills." },
|
|
49
45
|
{ key: "skills", label: "Skills", icon: "puzzle", group: "platform", minMode: "advanced", view: "skills", title: "Skills", desc: "Install, enable, and manage skills." },
|
|
50
46
|
{ key: "hooks", label: "Hooks", icon: "webhook", group: "platform", minMode: "advanced", view: "hooks", title: "Hooks", desc: "Lifecycle hooks across runs, tools, and workflows." },
|
|
51
|
-
{ key: "tools", label: "Tools", icon: "tools", group: "platform", minMode: "advanced", view: "tools", title: "Tool Registry", desc: "Local, workspace, and MCP tools with governance." },
|
|
52
47
|
{ key: "mcp", label: "MCP", icon: "plug-connected", group: "platform", minMode: "advanced", view: "mcp", title: "MCP Manager", desc: "Connected MCP servers, available tools, and health." },
|
|
53
48
|
|
|
54
49
|
// System
|
|
55
50
|
{ key: "settings", label: "Settings", icon: "settings", group: "system", minMode: "basic", view: "settings", title: "Settings", desc: "Appearance, workspace, and integrations." },
|
|
56
51
|
|
|
52
|
+
// Deep-linkable legacy/experimental surfaces. They remain renderable for
|
|
53
|
+
// compatibility, but are not promoted in the production navigation.
|
|
54
|
+
{ key: "pipeline", label: "Pipeline", icon: "git-branch", group: "data", minMode: "advanced", view: "pipeline", title: "Pipeline", desc: "Ingest, embed, and graph-build flows.", hidden: true },
|
|
55
|
+
{ key: "planning", label: "Planning", icon: "target-arrow", group: "compute", minMode: "advanced", view: "planning", title: "Autonomous Planning", desc: "Goal → plan → execute → review → replan.", hidden: true },
|
|
56
|
+
{ key: "my-computer", label: "My Computer", icon: "device-desktop-analytics", group: "compute", minMode: "advanced", view: "my-computer", title: "My Computer", desc: "Local hardware, memory, and runtime.", hidden: true },
|
|
57
|
+
{ key: "marketplace", label: "Marketplace", icon: "building-store", group: "platform", minMode: "advanced", view: "marketplace", title: "Marketplace", desc: "Agent templates, agents, plugins, and skills.", hidden: true },
|
|
58
|
+
{ key: "tools", label: "Tools", icon: "tools", group: "platform", minMode: "advanced", view: "tools", title: "Tool Registry", desc: "Local, workspace, and MCP tools with governance.", hidden: true },
|
|
59
|
+
|
|
57
60
|
// Admin
|
|
58
61
|
{ key: "admin/users", label: "Users", icon: "users", group: "admin", minMode: "admin", view: "admin-users", title: "Users", desc: "Workspace members and access.", admin: true },
|
|
59
62
|
{ key: "admin/permissions", label: "Permissions", icon: "key", group: "admin", minMode: "admin", view: "admin-permissions", title: "Permissions", desc: "Roles and capability mapping.", admin: true },
|
|
@@ -69,6 +72,7 @@ export const ROUTE_BY_KEY = Object.fromEntries(ROUTES.map((r) => [r.key, r]));
|
|
|
69
72
|
export function visibleRoutes(mode) {
|
|
70
73
|
const rank = MODE_RANK[mode] ?? 0;
|
|
71
74
|
return ROUTES.filter((r) => {
|
|
75
|
+
if (r.hidden) return false;
|
|
72
76
|
if (r.admin) return mode === "admin";
|
|
73
77
|
return (MODE_RANK[r.minMode] ?? 0) <= rank;
|
|
74
78
|
});
|
|
@@ -11,8 +11,8 @@ export const MODE_RANK = { basic: 0, advanced: 1, admin: 2 };
|
|
|
11
11
|
/** Nav groups in display order. */
|
|
12
12
|
export const GROUPS = [
|
|
13
13
|
{ id: "workspace", label: "Workspace" },
|
|
14
|
-
{ id: "retrieval", label: "Retrieval" },
|
|
15
14
|
{ id: "data", label: "Data" },
|
|
15
|
+
{ id: "retrieval", label: "Retrieval" },
|
|
16
16
|
{ id: "compute", label: "Compute" },
|
|
17
17
|
{ id: "platform", label: "Platform" },
|
|
18
18
|
{ id: "system", label: "System" },
|
|
@@ -28,32 +28,35 @@ export const ROUTES = [
|
|
|
28
28
|
{ key: "home", label: "Home", icon: "layout-dashboard", group: "workspace", minMode: "basic", view: "home", title: "Home", desc: "Your local-first AI workspace at a glance." },
|
|
29
29
|
{ key: "chat", label: "Chat", icon: "message-2", group: "workspace", minMode: "basic", view: "chat", title: "Chat", desc: "Grounded conversation over your indexed workspace." },
|
|
30
30
|
|
|
31
|
-
// Retrieval (the product identity)
|
|
32
|
-
{ key: "knowledge-graph", label: "Knowledge Graph", icon: "chart-dots-3", group: "retrieval", minMode: "basic", view: "knowledge-graph", title: "Knowledge Graph", desc: "Entities and relations extracted from your workspace." },
|
|
33
|
-
{ key: "hybrid-search", label: "Hybrid Search", icon: "arrows-join", group: "retrieval", minMode: "basic", view: "hybrid-search", title: "Hybrid Search", desc: "Graph structure fused with vector similarity." },
|
|
34
|
-
{ key: "memory", label: "Memory", icon: "brain", group: "retrieval", minMode: "basic", view: "memory", title: "Memory", desc: "Long-term workspace, project, agent, and conversation memory." },
|
|
35
|
-
|
|
36
31
|
// Data
|
|
37
32
|
{ key: "files", label: "Files", icon: "folders", group: "data", minMode: "basic", view: "files", title: "Files", desc: "Connected sources and indexed documents." },
|
|
38
|
-
|
|
33
|
+
|
|
34
|
+
// Retrieval (the product identity)
|
|
35
|
+
{ key: "hybrid-search", label: "Search", icon: "arrows-join", group: "retrieval", minMode: "basic", view: "hybrid-search", title: "Hybrid Search", desc: "Graph structure fused with vector similarity." },
|
|
36
|
+
{ key: "knowledge-graph", label: "Knowledge", icon: "chart-dots-3", group: "retrieval", minMode: "basic", view: "knowledge-graph", title: "Knowledge Graph", desc: "Entities and relations extracted from your workspace." },
|
|
37
|
+
{ key: "memory", label: "Memory", icon: "brain", group: "retrieval", minMode: "basic", view: "memory", title: "Memory", desc: "Long-term workspace, project, agent, and conversation memory." },
|
|
39
38
|
|
|
40
39
|
// Compute
|
|
40
|
+
{ key: "models", label: "Models", icon: "cpu", group: "compute", minMode: "basic", view: "models", title: "Models", desc: "Local MLX models and embeddings." },
|
|
41
41
|
{ key: "agents", label: "Agents", icon: "robot", group: "compute", minMode: "advanced", view: "agents", title: "Agents", desc: "Multi-agent roles, runs, and handoffs." },
|
|
42
42
|
{ key: "workflows", label: "Workflows", icon: "sitemap", group: "compute", minMode: "advanced", view: "workflows", title: "Workflow Agents", desc: "Trigger → agent chain → tools → memory → result." },
|
|
43
|
-
{ key: "planning", label: "Planning", icon: "target-arrow", group: "compute", minMode: "advanced", view: "planning", title: "Autonomous Planning", desc: "Goal → plan → execute → review → replan." },
|
|
44
|
-
{ key: "models", label: "Models", icon: "cpu", group: "compute", minMode: "basic", view: "models", title: "Models", desc: "Local MLX models and embeddings." },
|
|
45
|
-
{ key: "my-computer", label: "My Computer", icon: "device-desktop-analytics", group: "compute", minMode: "advanced", view: "my-computer", title: "My Computer", desc: "Local hardware, memory, and runtime." },
|
|
46
43
|
|
|
47
44
|
// Platform (the agent ecosystem)
|
|
48
|
-
{ key: "marketplace", label: "Marketplace", icon: "building-store", group: "platform", minMode: "advanced", view: "marketplace", title: "Marketplace", desc: "Agent templates, agents, plugins, and skills." },
|
|
49
45
|
{ key: "skills", label: "Skills", icon: "puzzle", group: "platform", minMode: "advanced", view: "skills", title: "Skills", desc: "Install, enable, and manage skills." },
|
|
50
46
|
{ key: "hooks", label: "Hooks", icon: "webhook", group: "platform", minMode: "advanced", view: "hooks", title: "Hooks", desc: "Lifecycle hooks across runs, tools, and workflows." },
|
|
51
|
-
{ key: "tools", label: "Tools", icon: "tools", group: "platform", minMode: "advanced", view: "tools", title: "Tool Registry", desc: "Local, workspace, and MCP tools with governance." },
|
|
52
47
|
{ key: "mcp", label: "MCP", icon: "plug-connected", group: "platform", minMode: "advanced", view: "mcp", title: "MCP Manager", desc: "Connected MCP servers, available tools, and health." },
|
|
53
48
|
|
|
54
49
|
// System
|
|
55
50
|
{ key: "settings", label: "Settings", icon: "settings", group: "system", minMode: "basic", view: "settings", title: "Settings", desc: "Appearance, workspace, and integrations." },
|
|
56
51
|
|
|
52
|
+
// Deep-linkable legacy/experimental surfaces. They remain renderable for
|
|
53
|
+
// compatibility, but are not promoted in the production navigation.
|
|
54
|
+
{ key: "pipeline", label: "Pipeline", icon: "git-branch", group: "data", minMode: "advanced", view: "pipeline", title: "Pipeline", desc: "Ingest, embed, and graph-build flows.", hidden: true },
|
|
55
|
+
{ key: "planning", label: "Planning", icon: "target-arrow", group: "compute", minMode: "advanced", view: "planning", title: "Autonomous Planning", desc: "Goal → plan → execute → review → replan.", hidden: true },
|
|
56
|
+
{ key: "my-computer", label: "My Computer", icon: "device-desktop-analytics", group: "compute", minMode: "advanced", view: "my-computer", title: "My Computer", desc: "Local hardware, memory, and runtime.", hidden: true },
|
|
57
|
+
{ key: "marketplace", label: "Marketplace", icon: "building-store", group: "platform", minMode: "advanced", view: "marketplace", title: "Marketplace", desc: "Agent templates, agents, plugins, and skills.", hidden: true },
|
|
58
|
+
{ key: "tools", label: "Tools", icon: "tools", group: "platform", minMode: "advanced", view: "tools", title: "Tool Registry", desc: "Local, workspace, and MCP tools with governance.", hidden: true },
|
|
59
|
+
|
|
57
60
|
// Admin
|
|
58
61
|
{ key: "admin/users", label: "Users", icon: "users", group: "admin", minMode: "admin", view: "admin-users", title: "Users", desc: "Workspace members and access.", admin: true },
|
|
59
62
|
{ key: "admin/permissions", label: "Permissions", icon: "key", group: "admin", minMode: "admin", view: "admin-permissions", title: "Permissions", desc: "Roles and capability mapping.", admin: true },
|
|
@@ -69,6 +72,7 @@ export const ROUTE_BY_KEY = Object.fromEntries(ROUTES.map((r) => [r.key, r]));
|
|
|
69
72
|
export function visibleRoutes(mode) {
|
|
70
73
|
const rank = MODE_RANK[mode] ?? 0;
|
|
71
74
|
return ROUTES.filter((r) => {
|
|
75
|
+
if (r.hidden) return false;
|
|
72
76
|
if (r.admin) return mode === "admin";
|
|
73
77
|
return (MODE_RANK[r.minMode] ?? 0) <= rank;
|
|
74
78
|
});
|
|
@@ -7,10 +7,10 @@
|
|
|
7
7
|
|
|
8
8
|
import { h, icon, $, $$ } from "./dom.a2773eb0.js";
|
|
9
9
|
import { store } from "./store.34ebd5e6.js";
|
|
10
|
-
import { api } from "./api.
|
|
11
|
-
import * as c from "./components.
|
|
10
|
+
import { api } from "./api.12b568ad.js";
|
|
11
|
+
import * as c from "./components.35f02e4c.js";
|
|
12
12
|
import { createRouter } from "./router.584570f2.js";
|
|
13
|
-
import { GROUPS, ROUTES, ROUTE_BY_KEY, MODE_RANK, visibleRoutes, loadView } from "./routes.
|
|
13
|
+
import { GROUPS, ROUTES, ROUTE_BY_KEY, MODE_RANK, visibleRoutes, loadView } from "./routes.d214b399.js";
|
|
14
14
|
|
|
15
15
|
const MODES = [
|
|
16
16
|
{ key: "basic", label: "Basic", icon: "circle" },
|
|
@@ -49,14 +49,17 @@ function buildRail() {
|
|
|
49
49
|
return h("aside.lt3-rail", { id: "lt3-rail", "aria-label": "Primary" },
|
|
50
50
|
h("div.lt3-rail__brand",
|
|
51
51
|
h("div.lt3-rail__logo", { html: latticeMark() }),
|
|
52
|
-
h("div.lt3-rail__word", h("b", "Lattice AI"), h("small", "
|
|
52
|
+
h("div.lt3-rail__word", h("b", "Lattice AI"), h("small", "Private runtime")),
|
|
53
53
|
h("button.lt3-iconbtn.lt3-iconbtn--sm.lt3-rail__close", { "aria-label": "Close menu", on: { click: closeDrawer } }, icon("x")),
|
|
54
54
|
),
|
|
55
55
|
h("div.lt3-rail__scope", { id: "lt3-scope" }),
|
|
56
56
|
h("nav.lt3-rail__nav", { id: "lt3-nav", "aria-label": "Sections" }),
|
|
57
57
|
h("div.lt3-rail__foot",
|
|
58
|
-
h("
|
|
59
|
-
h("
|
|
58
|
+
h("div.lt3-rail__status", { id: "lt3-rail-status" }),
|
|
59
|
+
h("div.lt3-rail__foot-row",
|
|
60
|
+
h("button.lt3-rail__user", { id: "lt3-user", "aria-label": "Account", on: { click: () => router.navigate("settings") } }),
|
|
61
|
+
h("button.lt3-iconbtn", { id: "lt3-theme", "aria-label": "Toggle theme", title: "Toggle theme", on: { click: () => store.toggleTheme() } }, icon("moon")),
|
|
62
|
+
),
|
|
60
63
|
),
|
|
61
64
|
);
|
|
62
65
|
}
|
|
@@ -82,10 +85,14 @@ function navItem(route) {
|
|
|
82
85
|
return h("a.lt3-navitem", {
|
|
83
86
|
href: "#/" + route.key,
|
|
84
87
|
dataset: { key: route.key },
|
|
88
|
+
title: route.title || route.label,
|
|
85
89
|
on: { click: () => closeDrawer() },
|
|
86
90
|
},
|
|
87
91
|
icon(route.icon),
|
|
88
|
-
h("span.lt3-
|
|
92
|
+
h("span.lt3-navitem__copy",
|
|
93
|
+
h("span.lt3-navitem__label", route.label),
|
|
94
|
+
route.desc ? h("span.lt3-navitem__meta", route.desc) : null,
|
|
95
|
+
),
|
|
89
96
|
route.key === "hybrid-search" ? h("span.lt3-navitem__dot", { style: { background: "var(--lt3-pillar-hybrid)" } }) : null,
|
|
90
97
|
);
|
|
91
98
|
}
|
|
@@ -161,6 +168,23 @@ function renderCrumbs() {
|
|
|
161
168
|
|
|
162
169
|
function renderIndexChip() {
|
|
163
170
|
els.idxchip.replaceChildren(c.indexChip(store.get().indexStatus));
|
|
171
|
+
renderRailStatus();
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function renderRailStatus() {
|
|
175
|
+
if (!els.railStatus) return;
|
|
176
|
+
const status = store.get().indexStatus;
|
|
177
|
+
const pipes = status?.pipelines || {};
|
|
178
|
+
const keys = ["knowledge_graph", "vector_index", "hybrid"];
|
|
179
|
+
const ready = keys.filter((key) => String(pipes[key]?.state || "").toLowerCase() === "ready").length;
|
|
180
|
+
const unavailable = !Object.keys(pipes).length;
|
|
181
|
+
els.railStatus.replaceChildren(
|
|
182
|
+
h("div.lt3-rail__status-top",
|
|
183
|
+
h("span.lt3-rail__status-dot", { dataset: { state: unavailable ? "pending" : ready === keys.length ? "ready" : "partial" } }),
|
|
184
|
+
h("span", unavailable ? "Local index pending" : `${ready}/${keys.length} retrieval signals ready`),
|
|
185
|
+
),
|
|
186
|
+
h("div.lt3-rail__status-sub", unavailable ? "Start backend to sync live state" : "Graph · vector · hybrid"),
|
|
187
|
+
);
|
|
164
188
|
}
|
|
165
189
|
|
|
166
190
|
/* ── View rendering ─────────────────────────────────────────────────────── */
|
|
@@ -240,8 +264,10 @@ function closeDrawer() { delete els.root.dataset.drawer; }
|
|
|
240
264
|
|
|
241
265
|
/* ── Command palette ────────────────────────────────────────────────────── */
|
|
242
266
|
function paletteItems() {
|
|
243
|
-
const
|
|
244
|
-
|
|
267
|
+
const mode = store.get().mode;
|
|
268
|
+
const currentRoutes = visibleRoutes(mode);
|
|
269
|
+
const nav = currentRoutes.map((r) => ({
|
|
270
|
+
group: "Go to", label: r.title || r.label, icon: r.icon, hint: r.label === r.title ? r.group : r.label,
|
|
245
271
|
run: () => router.navigate(r.key),
|
|
246
272
|
}));
|
|
247
273
|
const actions = [
|
|
@@ -340,6 +366,7 @@ function cacheEls(root) {
|
|
|
340
366
|
theme: $("#lt3-theme", root),
|
|
341
367
|
crumbs: $("#lt3-crumbs", root),
|
|
342
368
|
idxchip: $("#lt3-idxchip", root),
|
|
369
|
+
railStatus: $("#lt3-rail-status", root),
|
|
343
370
|
outlet: $("#lt3-outlet", root),
|
|
344
371
|
view: $("#lt3-view", root),
|
|
345
372
|
};
|
|
@@ -349,6 +376,7 @@ function cacheEls(root) {
|
|
|
349
376
|
renderMode();
|
|
350
377
|
updateThemeIcon();
|
|
351
378
|
renderIndexChip();
|
|
379
|
+
renderRailStatus();
|
|
352
380
|
}
|
|
353
381
|
|
|
354
382
|
function latticeMark() {
|
|
@@ -49,14 +49,17 @@ function buildRail() {
|
|
|
49
49
|
return h("aside.lt3-rail", { id: "lt3-rail", "aria-label": "Primary" },
|
|
50
50
|
h("div.lt3-rail__brand",
|
|
51
51
|
h("div.lt3-rail__logo", { html: latticeMark() }),
|
|
52
|
-
h("div.lt3-rail__word", h("b", "Lattice AI"), h("small", "
|
|
52
|
+
h("div.lt3-rail__word", h("b", "Lattice AI"), h("small", "Private runtime")),
|
|
53
53
|
h("button.lt3-iconbtn.lt3-iconbtn--sm.lt3-rail__close", { "aria-label": "Close menu", on: { click: closeDrawer } }, icon("x")),
|
|
54
54
|
),
|
|
55
55
|
h("div.lt3-rail__scope", { id: "lt3-scope" }),
|
|
56
56
|
h("nav.lt3-rail__nav", { id: "lt3-nav", "aria-label": "Sections" }),
|
|
57
57
|
h("div.lt3-rail__foot",
|
|
58
|
-
h("
|
|
59
|
-
h("
|
|
58
|
+
h("div.lt3-rail__status", { id: "lt3-rail-status" }),
|
|
59
|
+
h("div.lt3-rail__foot-row",
|
|
60
|
+
h("button.lt3-rail__user", { id: "lt3-user", "aria-label": "Account", on: { click: () => router.navigate("settings") } }),
|
|
61
|
+
h("button.lt3-iconbtn", { id: "lt3-theme", "aria-label": "Toggle theme", title: "Toggle theme", on: { click: () => store.toggleTheme() } }, icon("moon")),
|
|
62
|
+
),
|
|
60
63
|
),
|
|
61
64
|
);
|
|
62
65
|
}
|
|
@@ -82,10 +85,14 @@ function navItem(route) {
|
|
|
82
85
|
return h("a.lt3-navitem", {
|
|
83
86
|
href: "#/" + route.key,
|
|
84
87
|
dataset: { key: route.key },
|
|
88
|
+
title: route.title || route.label,
|
|
85
89
|
on: { click: () => closeDrawer() },
|
|
86
90
|
},
|
|
87
91
|
icon(route.icon),
|
|
88
|
-
h("span.lt3-
|
|
92
|
+
h("span.lt3-navitem__copy",
|
|
93
|
+
h("span.lt3-navitem__label", route.label),
|
|
94
|
+
route.desc ? h("span.lt3-navitem__meta", route.desc) : null,
|
|
95
|
+
),
|
|
89
96
|
route.key === "hybrid-search" ? h("span.lt3-navitem__dot", { style: { background: "var(--lt3-pillar-hybrid)" } }) : null,
|
|
90
97
|
);
|
|
91
98
|
}
|
|
@@ -161,6 +168,23 @@ function renderCrumbs() {
|
|
|
161
168
|
|
|
162
169
|
function renderIndexChip() {
|
|
163
170
|
els.idxchip.replaceChildren(c.indexChip(store.get().indexStatus));
|
|
171
|
+
renderRailStatus();
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function renderRailStatus() {
|
|
175
|
+
if (!els.railStatus) return;
|
|
176
|
+
const status = store.get().indexStatus;
|
|
177
|
+
const pipes = status?.pipelines || {};
|
|
178
|
+
const keys = ["knowledge_graph", "vector_index", "hybrid"];
|
|
179
|
+
const ready = keys.filter((key) => String(pipes[key]?.state || "").toLowerCase() === "ready").length;
|
|
180
|
+
const unavailable = !Object.keys(pipes).length;
|
|
181
|
+
els.railStatus.replaceChildren(
|
|
182
|
+
h("div.lt3-rail__status-top",
|
|
183
|
+
h("span.lt3-rail__status-dot", { dataset: { state: unavailable ? "pending" : ready === keys.length ? "ready" : "partial" } }),
|
|
184
|
+
h("span", unavailable ? "Local index pending" : `${ready}/${keys.length} retrieval signals ready`),
|
|
185
|
+
),
|
|
186
|
+
h("div.lt3-rail__status-sub", unavailable ? "Start backend to sync live state" : "Graph · vector · hybrid"),
|
|
187
|
+
);
|
|
164
188
|
}
|
|
165
189
|
|
|
166
190
|
/* ── View rendering ─────────────────────────────────────────────────────── */
|
|
@@ -240,8 +264,10 @@ function closeDrawer() { delete els.root.dataset.drawer; }
|
|
|
240
264
|
|
|
241
265
|
/* ── Command palette ────────────────────────────────────────────────────── */
|
|
242
266
|
function paletteItems() {
|
|
243
|
-
const
|
|
244
|
-
|
|
267
|
+
const mode = store.get().mode;
|
|
268
|
+
const currentRoutes = visibleRoutes(mode);
|
|
269
|
+
const nav = currentRoutes.map((r) => ({
|
|
270
|
+
group: "Go to", label: r.title || r.label, icon: r.icon, hint: r.label === r.title ? r.group : r.label,
|
|
245
271
|
run: () => router.navigate(r.key),
|
|
246
272
|
}));
|
|
247
273
|
const actions = [
|
|
@@ -340,6 +366,7 @@ function cacheEls(root) {
|
|
|
340
366
|
theme: $("#lt3-theme", root),
|
|
341
367
|
crumbs: $("#lt3-crumbs", root),
|
|
342
368
|
idxchip: $("#lt3-idxchip", root),
|
|
369
|
+
railStatus: $("#lt3-rail-status", root),
|
|
343
370
|
outlet: $("#lt3-outlet", root),
|
|
344
371
|
view: $("#lt3-view", root),
|
|
345
372
|
};
|
|
@@ -349,6 +376,7 @@ function cacheEls(root) {
|
|
|
349
376
|
renderMode();
|
|
350
377
|
updateThemeIcon();
|
|
351
378
|
renderIndexChip();
|
|
379
|
+
renderRailStatus();
|
|
352
380
|
}
|
|
353
381
|
|
|
354
382
|
function latticeMark() {
|