ltcai 4.0.0 → 4.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.
Files changed (108) hide show
  1. package/README.md +37 -33
  2. package/docs/CHANGELOG.md +64 -0
  3. package/docs/REALTIME_COLLABORATION.md +3 -3
  4. package/docs/V3_FRONTEND.md +9 -8
  5. package/docs/V4_DIGITAL_BRAIN_RECOVERY.md +86 -43
  6. package/docs/kg-schema.md +6 -2
  7. package/docs/spec-vs-impl.md +10 -10
  8. package/kg_schema.py +2 -603
  9. package/knowledge_graph.py +37 -4958
  10. package/latticeai/__init__.py +1 -1
  11. package/latticeai/api/admin.py +15 -16
  12. package/latticeai/api/agents.py +13 -6
  13. package/latticeai/api/auth.py +19 -11
  14. package/latticeai/api/invitations.py +100 -0
  15. package/latticeai/api/knowledge_graph.py +4 -11
  16. package/latticeai/api/plugins.py +3 -6
  17. package/latticeai/api/realtime.py +4 -7
  18. package/latticeai/api/static_routes.py +9 -12
  19. package/latticeai/api/ui_redirects.py +26 -0
  20. package/latticeai/api/workflow_designer.py +39 -6
  21. package/latticeai/api/workspace.py +24 -10
  22. package/latticeai/app_factory.py +88 -17
  23. package/latticeai/brain/_kg_common.py +1123 -0
  24. package/latticeai/brain/discovery.py +1455 -0
  25. package/latticeai/brain/documents.py +218 -0
  26. package/latticeai/brain/ingest.py +644 -0
  27. package/latticeai/brain/projection.py +561 -0
  28. package/latticeai/brain/provenance.py +401 -0
  29. package/latticeai/brain/retrieval.py +1316 -0
  30. package/latticeai/brain/schema.py +640 -0
  31. package/latticeai/brain/store.py +216 -0
  32. package/latticeai/brain/write_master.py +225 -0
  33. package/latticeai/core/invitations.py +131 -0
  34. package/latticeai/core/marketplace.py +1 -1
  35. package/latticeai/core/multi_agent.py +1 -1
  36. package/latticeai/core/policy.py +54 -0
  37. package/latticeai/core/realtime.py +65 -44
  38. package/latticeai/core/sessions.py +31 -5
  39. package/latticeai/core/users.py +147 -0
  40. package/latticeai/core/workspace_os.py +420 -20
  41. package/latticeai/services/agent_runtime.py +242 -4
  42. package/latticeai/services/run_executor.py +328 -0
  43. package/latticeai/services/workspace_service.py +27 -19
  44. package/package.json +2 -14
  45. package/scripts/lint_v3.mjs +23 -0
  46. package/static/v3/asset-manifest.json +21 -14
  47. package/static/v3/js/{app.356e6452.js → app.c5c80c46.js} +1 -1
  48. package/static/v3/js/core/{api.7a308b89.js → api.ba0fbf14.js} +58 -1
  49. package/static/v3/js/core/api.js +57 -0
  50. package/static/v3/js/core/i18n.880e1fec.js +575 -0
  51. package/static/v3/js/core/i18n.js +575 -0
  52. package/static/v3/js/core/routes.37522821.js +101 -0
  53. package/static/v3/js/core/routes.js +71 -63
  54. package/static/v3/js/core/{shell.a1657f20.js → shell.e3f6bbfa.js} +67 -38
  55. package/static/v3/js/core/shell.js +65 -36
  56. package/static/v3/js/core/{store.204a08b2.js → store.7b2aa044.js} +10 -0
  57. package/static/v3/js/core/store.js +10 -0
  58. package/static/v3/js/views/account.eff40715.js +143 -0
  59. package/static/v3/js/views/account.js +143 -0
  60. package/static/v3/js/views/activity.0d271ef9.js +67 -0
  61. package/static/v3/js/views/activity.js +67 -0
  62. package/static/v3/js/views/{admin-users.03bac88c.js → admin-users.f7ac7b43.js} +4 -6
  63. package/static/v3/js/views/admin-users.js +4 -6
  64. package/static/v3/js/views/{agents.014d0b74.js → agents.17c5288d.js} +35 -12
  65. package/static/v3/js/views/agents.js +35 -12
  66. package/static/v3/js/views/{chat.e6dd7dd0.js → chat.e250e2cc.js} +23 -0
  67. package/static/v3/js/views/chat.js +23 -0
  68. package/static/v3/js/views/{knowledge-graph.5e40cbeb.js → knowledge-graph.4d09c537.js} +27 -7
  69. package/static/v3/js/views/knowledge-graph.js +27 -7
  70. package/static/v3/js/views/network.52a4f181.js +97 -0
  71. package/static/v3/js/views/network.js +97 -0
  72. package/static/v3/js/views/{planning.9ac3e313.js → planning.4876fd77.js} +26 -5
  73. package/static/v3/js/views/planning.js +26 -5
  74. package/static/v3/js/views/runs.b63b2afa.js +144 -0
  75. package/static/v3/js/views/runs.js +144 -0
  76. package/static/v3/js/views/{settings.8631fa5e.js → settings.b7140634.js} +7 -8
  77. package/static/v3/js/views/settings.js +7 -8
  78. package/static/v3/js/views/snapshots.6f5db095.js +135 -0
  79. package/static/v3/js/views/snapshots.js +135 -0
  80. package/static/v3/js/views/{workflows.26c57290.js → workflows.7752225a.js} +87 -2
  81. package/static/v3/js/views/workflows.js +87 -2
  82. package/static/v3/js/views/workspace-admin.c466029b.js +156 -0
  83. package/static/v3/js/views/workspace-admin.js +156 -0
  84. package/static/account.html +0 -113
  85. package/static/activity.html +0 -73
  86. package/static/admin.html +0 -486
  87. package/static/agents.html +0 -139
  88. package/static/chat.html +0 -841
  89. package/static/css/reference/account.css +0 -439
  90. package/static/css/reference/admin.css +0 -610
  91. package/static/css/reference/base.css +0 -1661
  92. package/static/css/reference/chat.css +0 -4623
  93. package/static/css/reference/graph.css +0 -1016
  94. package/static/css/responsive.css +0 -861
  95. package/static/graph.html +0 -122
  96. package/static/platform.css +0 -104
  97. package/static/plugins.html +0 -136
  98. package/static/scripts/account.js +0 -238
  99. package/static/scripts/admin.js +0 -1614
  100. package/static/scripts/chat.js +0 -5081
  101. package/static/scripts/graph.js +0 -1804
  102. package/static/scripts/platform.js +0 -64
  103. package/static/scripts/ux.js +0 -167
  104. package/static/scripts/workspace.js +0 -948
  105. package/static/v3/js/core/routes.7222343d.js +0 -93
  106. package/static/workflows.html +0 -146
  107. package/static/workspace.css +0 -1121
  108. package/static/workspace.html +0 -357
@@ -1,93 +0,0 @@
1
- /* ============================================================================
2
- * Lattice AI v3 — Information architecture (single source of truth)
3
- *
4
- * One declarative table drives the nav rail, the command palette, the router,
5
- * breadcrumbs, and lazy view loading. Mode gating (Basic < Advanced < Admin)
6
- * and the Admin section live here so the whole shell stays consistent.
7
- * ========================================================================== */
8
-
9
- export const MODE_RANK = { basic: 0, advanced: 1, admin: 2 };
10
-
11
- /** Nav groups in display order. */
12
- export const GROUPS = [
13
- { id: "brain", label: "Brain" },
14
- { id: "ask", label: "Ask" },
15
- { id: "capture", label: "Capture" },
16
- { id: "act", label: "Act" },
17
- { id: "library", label: "Library" },
18
- { id: "system", label: "System" },
19
- { id: "admin", label: "Administration", adminOnly: true },
20
- ];
21
-
22
- /**
23
- * Route table. `minMode` = lowest mode in which the item appears in the rail
24
- * (deep-links still resolve). `view` = module basename under js/views/.
25
- */
26
- export const ROUTES = [
27
- // Workspace
28
- { key: "home", label: "Overview", icon: "layout-dashboard", group: "system", minMode: "basic", view: "home", title: "Overview", desc: "Your digital brain at a glance." },
29
- { key: "chat", label: "Chat", icon: "message-2", group: "ask", minMode: "basic", view: "chat", title: "Chat", desc: "Grounded conversation over your brain — memories, knowledge, and notes assembled with provenance." },
30
-
31
- // Data
32
- { key: "files", label: "Files", icon: "folders", group: "capture", minMode: "basic", view: "files", title: "Files", desc: "Connected sources and indexed documents." },
33
-
34
- // Retrieval (the product identity)
35
- { key: "hybrid-search", label: "Search", icon: "arrows-join", group: "brain", minMode: "basic", view: "hybrid-search", title: "Hybrid Search", desc: "Graph structure fused with vector similarity." },
36
- { key: "knowledge-graph", label: "Knowledge Graph", icon: "chart-dots-3", group: "brain", minMode: "basic", view: "knowledge-graph", title: "Knowledge Graph", desc: "Your digital brain — every source converges here. Explore, ingest, and export." },
37
- { key: "memory", label: "Memory", icon: "brain", group: "brain", minMode: "basic", view: "memory", title: "Memory", desc: "Long-term workspace, project, agent, and conversation memory." },
38
-
39
- // Compute
40
- { key: "models", label: "Models", icon: "cpu", group: "library", minMode: "basic", view: "models", title: "Models", desc: "Local MLX models and embeddings." },
41
- { key: "agents", label: "Agents", icon: "robot", group: "act", minMode: "advanced", view: "agents", title: "Agents", desc: "Multi-agent roles, runs, and handoffs." },
42
- { key: "workflows", label: "Workflows", icon: "sitemap", group: "act", minMode: "advanced", view: "workflows", title: "Workflow Agents", desc: "Trigger → agent chain → tools → memory → result." },
43
-
44
- // Platform (the agent ecosystem)
45
- { key: "skills", label: "Skills", icon: "puzzle", group: "library", minMode: "advanced", view: "skills", title: "Skills", desc: "Install, enable, and manage skills." },
46
- { key: "hooks", label: "Hooks", icon: "webhook", group: "act", minMode: "advanced", view: "hooks", title: "Hooks", desc: "Lifecycle hooks across runs, tools, and workflows." },
47
- { key: "mcp", label: "MCP", icon: "plug-connected", group: "library", minMode: "advanced", view: "mcp", title: "MCP Manager", desc: "Connected MCP servers, available tools, and health." },
48
-
49
- // System
50
- { key: "settings", label: "Settings", icon: "settings", group: "system", minMode: "basic", view: "settings", title: "Settings", desc: "Appearance, workspace, and integrations." },
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: "capture", minMode: "advanced", view: "pipeline", title: "Pipeline", desc: "Ingest, embed, and graph-build flows.", hidden: true },
55
- { key: "planning", label: "Planning", icon: "target-arrow", group: "act", 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: "system", 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: "library", minMode: "advanced", view: "marketplace", title: "Marketplace", desc: "Agent templates, agents, plugins, and skills.", hidden: true },
58
- { key: "tools", label: "Tools", icon: "tools", group: "act", minMode: "advanced", view: "tools", title: "Tool Registry", desc: "Local, workspace, and MCP tools with governance.", hidden: true },
59
-
60
- // Admin
61
- { key: "admin/users", label: "Users", icon: "users", group: "admin", minMode: "admin", view: "admin-users", title: "Users", desc: "Workspace members and access.", admin: true },
62
- { key: "admin/permissions", label: "Permissions", icon: "key", group: "admin", minMode: "admin", view: "admin-permissions", title: "Permissions", desc: "Roles and capability mapping.", admin: true },
63
- { key: "admin/audit", label: "Audit Logs", icon: "report-search", group: "admin", minMode: "admin", view: "admin-audit", title: "Audit Logs", desc: "Activity and access trail.", admin: true },
64
- { key: "admin/security", label: "Security", icon: "shield-check", group: "admin", minMode: "admin", view: "admin-security", title: "Security", desc: "Sensitive-data signals and DLP.", admin: true },
65
- { key: "admin/policies", label: "Policies", icon: "file-certificate", group: "admin", minMode: "admin", view: "admin-policies", title: "Policies", desc: "Governance and enforcement.", admin: true },
66
- { key: "admin/private-vpc", label: "Private VPC", icon: "cloud-lock", group: "admin", minMode: "admin", view: "admin-private-vpc", title: "Private VPC", desc: "Network isolation and peering.", admin: true },
67
- ];
68
-
69
- export const ROUTE_BY_KEY = Object.fromEntries(ROUTES.map((r) => [r.key, r]));
70
-
71
- /** Routes visible in the rail for a given mode. */
72
- export function visibleRoutes(mode) {
73
- const rank = MODE_RANK[mode] ?? 0;
74
- return ROUTES.filter((r) => {
75
- if (r.hidden) return false;
76
- if (r.admin) return mode === "admin";
77
- return (MODE_RANK[r.minMode] ?? 0) <= rank;
78
- });
79
- }
80
-
81
- /** Lazy-load a view module by basename. Cached. */
82
- const cache = new Map();
83
- function assetUrl(key, fallback) {
84
- const manifest = window.__LT_ASSET_MANIFEST__;
85
- return (manifest && manifest.assets && manifest.assets[key]) || fallback;
86
- }
87
-
88
- export async function loadView(view) {
89
- if (cache.has(view)) return cache.get(view);
90
- const mod = await import(assetUrl(`static/v3/js/views/${view}.js`, `../views/${view}.js`));
91
- cache.set(view, mod);
92
- return mod;
93
- }
@@ -1,146 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover, interactive-widget=resizes-content" />
6
- <title>Workflow Designer — Lattice AI</title>
7
- <script src="/static/scripts/ux.js"></script>
8
- <link rel="stylesheet" href="/static/css/tokens.css" />
9
- <link rel="stylesheet" href="/static/platform.css" />
10
- <link rel="stylesheet" href="/static/css/responsive.css" />
11
- </head>
12
- <body>
13
- <main>
14
- <h1>Workflow Designer</h1>
15
- <p class="sub">Compose triggers, tools, skills, plugins, agents, conditions, and outputs into runnable workflows.</p>
16
-
17
- <div class="row">
18
- <button id="newBtn">+ New from template</button>
19
- <button class="ghost" id="validateBtn">Validate</button>
20
- <button class="ghost" id="saveBtn">Save</button>
21
- <div class="spacer"></div>
22
- </div>
23
-
24
- <div class="section">
25
- <label>Workflow name</label>
26
- <input id="wfName" value="My workflow" />
27
- <label>Nodes (JSON) — trigger → … → output</label>
28
- <textarea id="wfNodes" spellcheck="false" style="min-height:240px"></textarea>
29
- <pre id="validateOut" style="display:none"></pre>
30
- </div>
31
-
32
- <div class="section">
33
- <h3>Saved workflows</h3>
34
- <div id="list" class="grid"><div class="empty">Loading…</div></div>
35
- </div>
36
-
37
- <div class="section">
38
- <h3>Run history</h3>
39
- <div id="runs"><div class="empty">No runs yet.</div></div>
40
- </div>
41
-
42
- <div class="section">
43
- <h3>Replay viewer</h3>
44
- <div id="replay"><div class="empty">Select a workflow run.</div></div>
45
- </div>
46
- </main>
47
-
48
- <script type="module">
49
- import { mountHeader, api, escapeHtml, badge, toast } from "/static/scripts/platform.js";
50
- mountHeader("/workflows");
51
-
52
- const TEMPLATE = [
53
- { id: "trigger", type: "trigger", name: "Manual start", config: { trigger: "manual" }, next: "review" },
54
- { id: "review", type: "agent", name: "Multi-agent review", config: { goal: "Review the latest workspace changes", roles: ["planner", "executor", "reviewer"] }, next: "decide" },
55
- { id: "decide", type: "condition", name: "Passed?", config: { left: "last_output", op: "truthy" }, branches: { true: "done", false: "done" } },
56
- { id: "done", type: "output", name: "Output", config: {}, next: null },
57
- ];
58
-
59
- function loadTemplate() {
60
- document.getElementById("wfName").value = "My workflow";
61
- document.getElementById("wfNodes").value = JSON.stringify(TEMPLATE, null, 2);
62
- }
63
-
64
- function readNodes() { return JSON.parse(document.getElementById("wfNodes").value); }
65
-
66
- document.getElementById("newBtn").addEventListener("click", loadTemplate);
67
-
68
- document.getElementById("validateBtn").addEventListener("click", async () => {
69
- const out = document.getElementById("validateOut");
70
- out.style.display = "block";
71
- try {
72
- const res = await api("/workflows/api/validate", { method: "POST", body: JSON.stringify({ name: document.getElementById("wfName").value, nodes: readNodes() }) });
73
- out.textContent = res.ok ? "✓ Valid workflow" : "Errors:\n" + res.errors.join("\n");
74
- } catch (err) { out.textContent = "Error: " + err.message; }
75
- });
76
-
77
- document.getElementById("saveBtn").addEventListener("click", async () => {
78
- try {
79
- await api("/workflows/api/definitions", { method: "POST", body: JSON.stringify({ name: document.getElementById("wfName").value, nodes: readNodes() }) });
80
- toast("Workflow saved"); await loadList();
81
- } catch (err) { toast(err.message); }
82
- });
83
-
84
- async function loadList() {
85
- const data = await api("/workflows/api/definitions");
86
- const list = document.getElementById("list");
87
- const items = data.workflows || [];
88
- if (!items.length) { list.innerHTML = `<div class="empty">No workflows yet.</div>`; return; }
89
- list.innerHTML = items.map((w) => `
90
- <div class="card">
91
- <h3>${escapeHtml(w.name)}</h3>
92
- <div class="meta">${(w.nodes||w.steps||[]).length} node(s) · ${escapeHtml(w.updated_at||w.created_at||"")}</div>
93
- <div class="row" style="margin-top:12px">
94
- <button data-run="${w.id}">Run</button>
95
- <a class="btn ghost" href="/workflows/api/export/${w.id}" target="_blank">Export</a>
96
- </div>
97
- </div>`).join("");
98
- }
99
-
100
- document.getElementById("list").addEventListener("click", async (e) => {
101
- const btn = e.target.closest("button[data-run]");
102
- if (!btn) return;
103
- btn.disabled = true;
104
- try {
105
- const res = await api(`/workflows/api/definitions/${btn.dataset.run}/run`, { method: "POST", body: JSON.stringify({ inputs: {} }) });
106
- toast(`Run ${res.result.status} · ${res.result.step_count} steps`);
107
- await loadRuns();
108
- } catch (err) { toast(err.message); } finally { btn.disabled = false; }
109
- });
110
-
111
- async function loadRuns() {
112
- const data = await api("/workflows/api/runs");
113
- const runs = data.runs || [];
114
- const box = document.getElementById("runs");
115
- if (!runs.length) { box.innerHTML = `<div class="empty">No runs yet.</div>`; return; }
116
- box.innerHTML = runs.map((r) => `
117
- <div class="card" style="margin-bottom:10px">
118
- <div class="row"><h3>${escapeHtml(r.name)}</h3><div class="spacer"></div>${badge(r.status)}</div>
119
- <div class="meta">${escapeHtml(r.created_at)} · ${ (r.timeline||[]).length } steps</div>
120
- <div class="row" style="margin-top:10px"><button class="ghost" data-replay="${r.id}">Replay</button></div>
121
- <pre>${escapeHtml(JSON.stringify(r.timeline, null, 2))}</pre>
122
- </div>`).join("");
123
- }
124
-
125
- document.getElementById("runs").addEventListener("click", async (e) => {
126
- const btn = e.target.closest("button[data-replay]");
127
- if (!btn) return;
128
- const out = document.getElementById("replay");
129
- out.innerHTML = `<div class="empty">Loading replay…</div>`;
130
- try {
131
- const data = await api(`/workflows/api/runs/${btn.dataset.replay}/replay`);
132
- const frames = data.replay.frames || [];
133
- out.innerHTML = frames.map((f) => `<div class="timeline-item">
134
- <div class="row"><strong>${escapeHtml(f.event)}</strong><div class="spacer"></div>${badge(f.decision || "event")}</div>
135
- <div class="t-meta">${escapeHtml(String(f.actor||""))} · ${escapeHtml(f.when||"")}</div>
136
- <pre>${escapeHtml(JSON.stringify({ why: f.why, input: f.input, output: f.output }, null, 2))}</pre>
137
- </div>`).join("") || `<div class="empty">No replay frames.</div>`;
138
- } catch (err) { out.innerHTML = `<div class="empty">${escapeHtml(err.message)}</div>`; }
139
- });
140
-
141
- loadTemplate();
142
- loadList().catch((e) => toast(e.message));
143
- loadRuns().catch(() => {});
144
- </script>
145
- </body>
146
- </html>