ltcai 3.0.1 → 3.2.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.
Files changed (123) hide show
  1. package/README.md +54 -21
  2. package/docs/CHANGELOG.md +90 -0
  3. package/docs/V3_2_AUDIT.md +82 -0
  4. package/docs/V3_FRONTEND.md +20 -17
  5. package/docs/architecture.md +6 -0
  6. package/latticeai/__init__.py +1 -1
  7. package/latticeai/api/agent_registry.py +103 -0
  8. package/latticeai/api/auth.py +4 -1
  9. package/latticeai/api/hooks.py +113 -0
  10. package/latticeai/api/marketplace.py +13 -0
  11. package/latticeai/api/memory.py +109 -0
  12. package/latticeai/api/search.py +4 -0
  13. package/latticeai/core/agent_registry.py +234 -0
  14. package/latticeai/core/config.py +2 -0
  15. package/latticeai/core/embedding_providers.py +123 -0
  16. package/latticeai/core/hooks.py +284 -0
  17. package/latticeai/core/marketplace.py +87 -2
  18. package/latticeai/core/multi_agent.py +1 -1
  19. package/latticeai/core/workspace_os.py +1 -1
  20. package/latticeai/server_app.py +63 -6
  21. package/latticeai/services/memory_service.py +324 -0
  22. package/package.json +9 -4
  23. package/scripts/build_v3_assets.mjs +164 -0
  24. package/scripts/capture/README.md +28 -0
  25. package/scripts/capture/capture_enterprise.js +8 -0
  26. package/scripts/capture/capture_graph.js +8 -0
  27. package/scripts/capture/capture_onboarding.js +8 -0
  28. package/scripts/capture/capture_page.js +43 -0
  29. package/scripts/capture/capture_release_media.js +125 -0
  30. package/scripts/capture/capture_skills.js +8 -0
  31. package/scripts/capture/capture_workspace.js +8 -0
  32. package/scripts/generate_diagrams.py +513 -0
  33. package/scripts/lint_v3.mjs +33 -0
  34. package/scripts/release-0.3.1.sh +105 -0
  35. package/scripts/take_screenshots.js +69 -0
  36. package/scripts/validate_release_artifacts.py +167 -0
  37. package/static/account.html +9 -9
  38. package/static/activity.html +4 -4
  39. package/static/admin.html +8 -8
  40. package/static/agents.html +4 -4
  41. package/static/chat.html +9 -9
  42. package/static/css/tokens.5a595671.css +260 -0
  43. package/static/css/tokens.css +1 -1
  44. package/static/graph.html +9 -9
  45. package/static/plugins.html +4 -4
  46. package/static/sw.js +3 -1
  47. package/static/v3/asset-manifest.json +55 -0
  48. package/static/v3/css/lattice.base.e4cdd05d.css +128 -0
  49. package/static/v3/css/lattice.components.011e988b.css +447 -0
  50. package/static/v3/css/lattice.components.css +2 -2
  51. package/static/v3/css/lattice.shell.4920f42d.css +407 -0
  52. package/static/v3/css/lattice.tokens.c597ff81.css +132 -0
  53. package/static/v3/css/lattice.views.3ee19d4e.css +277 -0
  54. package/static/v3/index.html +38 -9
  55. package/static/v3/js/app.a5adc0f3.js +26 -0
  56. package/static/v3/js/core/api.603b978f.js +408 -0
  57. package/static/v3/js/core/api.js +132 -51
  58. package/static/v3/js/core/components.4c83e0a9.js +222 -0
  59. package/static/v3/js/core/components.js +9 -2
  60. package/static/v3/js/core/dom.a2773eb0.js +148 -0
  61. package/static/v3/js/core/router.584570f2.js +37 -0
  62. package/static/v3/js/core/routes.07ad6696.js +89 -0
  63. package/static/v3/js/core/routes.js +17 -1
  64. package/static/v3/js/core/shell.ea0b9ae5.js +363 -0
  65. package/static/v3/js/core/store.34ebd5e6.js +113 -0
  66. package/static/v3/js/views/admin-audit.660a1fb1.js +185 -0
  67. package/static/v3/js/views/admin-audit.js +1 -1
  68. package/static/v3/js/views/admin-permissions.a7ae5f09.js +177 -0
  69. package/static/v3/js/views/admin-permissions.js +4 -5
  70. package/static/v3/js/views/admin-policies.3658fd86.js +102 -0
  71. package/static/v3/js/views/admin-policies.js +4 -5
  72. package/static/v3/js/views/admin-private-vpc.7d342d36.js +135 -0
  73. package/static/v3/js/views/admin-private-vpc.js +2 -5
  74. package/static/v3/js/views/admin-security.07c66b72.js +180 -0
  75. package/static/v3/js/views/admin-security.js +4 -5
  76. package/static/v3/js/views/admin-users.03bac88c.js +168 -0
  77. package/static/v3/js/views/admin-users.js +6 -6
  78. package/static/v3/js/views/agents.c373d48c.js +293 -0
  79. package/static/v3/js/views/agents.js +101 -2
  80. package/static/v3/js/views/chat.718144ce.js +449 -0
  81. package/static/v3/js/views/chat.js +2 -3
  82. package/static/v3/js/views/files.4935197e.js +186 -0
  83. package/static/v3/js/views/files.js +27 -21
  84. package/static/v3/js/views/home.cdde3b32.js +119 -0
  85. package/static/v3/js/views/hooks.f3edebca.js +99 -0
  86. package/static/v3/js/views/hooks.js +99 -0
  87. package/static/v3/js/views/hybrid-search.b22b97e0.js +195 -0
  88. package/static/v3/js/views/hybrid-search.js +1 -1
  89. package/static/v3/js/views/knowledge-graph.a14ea7e7.js +237 -0
  90. package/static/v3/js/views/knowledge-graph.js +2 -3
  91. package/static/v3/js/views/marketplace.ab0583d4.js +141 -0
  92. package/static/v3/js/views/marketplace.js +141 -0
  93. package/static/v3/js/views/mcp.99b5c6a7.js +114 -0
  94. package/static/v3/js/views/mcp.js +114 -0
  95. package/static/v3/js/views/memory.d2ed7a7c.js +146 -0
  96. package/static/v3/js/views/memory.js +146 -0
  97. package/static/v3/js/views/models.a1ffa147.js +256 -0
  98. package/static/v3/js/views/models.js +17 -8
  99. package/static/v3/js/views/my-computer.1b2ff621.js +237 -0
  100. package/static/v3/js/views/my-computer.js +5 -5
  101. package/static/v3/js/views/pipeline.c522f1ce.js +157 -0
  102. package/static/v3/js/views/pipeline.js +3 -7
  103. package/static/v3/js/views/planning.9ac3e313.js +153 -0
  104. package/static/v3/js/views/planning.js +153 -0
  105. package/static/v3/js/views/settings.4f777210.js +250 -0
  106. package/static/v3/js/views/settings.js +6 -14
  107. package/static/v3/js/views/skills.c6c2f965.js +109 -0
  108. package/static/v3/js/views/skills.js +109 -0
  109. package/static/v3/js/views/tools.e4f11276.js +108 -0
  110. package/static/v3/js/views/tools.js +108 -0
  111. package/static/v3/js/views/workflows.26c57290.js +128 -0
  112. package/static/v3/js/views/workflows.js +128 -0
  113. package/static/workflows.html +4 -4
  114. package/static/workspace.html +5 -5
  115. package/docs/images/tmp_frames/frame_00.png +0 -0
  116. package/docs/images/tmp_frames/frame_01.png +0 -0
  117. package/docs/images/tmp_frames/frame_02.png +0 -0
  118. package/docs/images/tmp_frames/frame_03.png +0 -0
  119. package/docs/images/tmp_frames/hero_00.png +0 -0
  120. package/docs/images/tmp_frames/hero_01.png +0 -0
  121. package/docs/images/tmp_frames/hero_02.png +0 -0
  122. package/docs/images/tmp_frames/hero_03.png +0 -0
  123. package/static/v3/js/core/fixtures.js +0 -171
@@ -0,0 +1,128 @@
1
+ /* ============================================================================
2
+ * View: Workflows — workflow-driven agent execution.
3
+ * Trigger → agent chain → tools → memory → result. Reads workflow definitions
4
+ * and runs from the real workflow designer backend; runs a definition and shows
5
+ * the run ledger with replay. Unavailable state is explicit.
6
+ * ========================================================================== */
7
+
8
+ const STAGES = ["Trigger", "Agent chain", "Tools", "Memory", "Result"];
9
+
10
+ export async function render(ctx) {
11
+ const { h, c } = ctx;
12
+ const defsHost = h("div", c.loading({ lines: 3, block: true }));
13
+ const runsHost = h("div", c.loading({ lines: 3 }));
14
+ const defsSrc = h("span", c.sourceBadge("pending"));
15
+ const runsSrc = h("span", c.sourceBadge("pending"));
16
+
17
+ const root = h("div.lt3-stack-6",
18
+ c.viewHeader({
19
+ eyebrow: "Compute",
20
+ title: "Workflow Agents",
21
+ sub: "Repeatable automation: a trigger fires an agent chain that calls tools, reads and writes memory, and produces a result.",
22
+ }),
23
+ stageLegend(ctx),
24
+ h("section", c.sectionHead("Workflow definitions", defsSrc), defsHost),
25
+ c.panel({
26
+ head: h("div.lt3-row", { style: { "justify-content": "space-between", width: "100%" } },
27
+ h("div", h("div.lt3-eyebrow", "Activity"), h("h3.lt3-panel__title", "Recent runs")), runsSrc),
28
+ children: runsHost,
29
+ }),
30
+ );
31
+
32
+ loadDefs();
33
+ loadRuns();
34
+ return root;
35
+
36
+ function stageLegend(ctx2) {
37
+ return h("div.lt3-cluster", { style: { gap: "var(--lt3-space-2)" } }, STAGES.map((s, i) =>
38
+ h("div.lt3-row-2", { style: { gap: "var(--lt3-space-2)" } }, c.pill(s, i === STAGES.length - 1 ? "warn" : "info"), i < STAGES.length - 1 ? c.icon("arrow-right") : null)));
39
+ }
40
+
41
+ async function loadDefs() {
42
+ const res = await ctx.api.workflowDefinitions();
43
+ defsSrc.replaceChildren(c.sourceBadge(res.source));
44
+ const defs = normalizeDefs(res.data);
45
+ if (!defs.length) {
46
+ defsHost.replaceChildren(c.emptyState({ icon: "sitemap", title: "No workflows yet", body: res.source === "live" ? "Create a workflow definition to automate an agent chain." : "Start the backend to load workflows." }));
47
+ return;
48
+ }
49
+ defsHost.replaceChildren(h("div.lt3-grid-auto", defs.map((w) => defCard(ctx, w))));
50
+ }
51
+
52
+ function defCard(ctx2, w) {
53
+ const nodes = w.nodes || (w.definition && w.definition.nodes) || [];
54
+ const triggers = nodes.filter((n) => n.type === "trigger").length || 1;
55
+ return c.card(h("div.lt3-stack-3",
56
+ h("div.lt3-row", { style: { "justify-content": "space-between", "align-items": "flex-start" } },
57
+ h("div", h("b", w.name || w.id), h("div.lt3-faint", { style: { "font-size": "var(--lt3-text-2xs)", "font-family": "var(--lt3-font-mono)" } }, w.id || "")),
58
+ c.pill(`${nodes.length || 0} nodes`),
59
+ ),
60
+ w.description ? h("p.lt3-muted", { style: { margin: 0, "font-size": "var(--lt3-text-sm)" } }, w.description) : null,
61
+ h("div.lt3-cluster", (nodes.slice(0, 6)).map((n) => h("span.lt3-chip", c.icon(nodeIcon(n.type)), n.name || n.type))),
62
+ h("div.lt3-row-2",
63
+ h("button.lt3-btn.lt3-btn--primary.lt3-btn--sm", { on: { click: () => runDef(ctx2, w) } }, c.icon("player-play"), "Run"),
64
+ h("span.lt3-faint", { style: { "font-size": "var(--lt3-text-2xs)" } }, `${triggers} trigger${triggers === 1 ? "" : "s"}`),
65
+ ),
66
+ ), { interactive: false });
67
+ }
68
+
69
+ async function runDef(ctx2, w) {
70
+ const res = await ctx2.api.runWorkflow(w.id, {});
71
+ ctx2.toast(res && res.ok ? `Ran ${w.name || w.id}` : "Run unavailable", res && res.ok ? "ok" : "err");
72
+ loadRuns();
73
+ }
74
+
75
+ async function loadRuns() {
76
+ const res = await ctx.api.workflowRuns();
77
+ runsSrc.replaceChildren(c.sourceBadge(res.source));
78
+ const runs = normalizeRuns(res.data);
79
+ if (!runs.length) {
80
+ runsHost.replaceChildren(c.emptyState({ icon: "history-off", title: "No runs yet", body: "Workflow runs will appear here once a workflow executes." }));
81
+ return;
82
+ }
83
+ runsHost.replaceChildren(c.table(
84
+ [
85
+ { key: "status", label: "Status", width: "1%", render: (r) => c.statePill(mapStatus(r.status)) },
86
+ { key: "name", label: "Workflow", render: (r) => h("b", { style: { "font-size": "var(--lt3-text-sm)" } }, r.workflow_name || r.workflow_id || r.id) },
87
+ { key: "when", label: "When", width: "1%", render: (r) => h("span.lt3-faint", { style: { "white-space": "nowrap", "font-size": "var(--lt3-text-2xs)" } }, fmtTime(r.created_at || r.started_at)) },
88
+ { key: "act", label: "", width: "1%", render: (r) => h("button.lt3-btn.lt3-btn--ghost.lt3-btn--sm", { on: { click: () => replay(ctx, r) } }, c.icon("player-track-next"), "Replay") },
89
+ ],
90
+ runs.slice(0, 20),
91
+ ));
92
+ }
93
+
94
+ async function replay(ctx2, r) {
95
+ const id = r.id || r.run_id;
96
+ const res = await ctx2.api.workflowReplay(id);
97
+ ctx2.toast(res && res.ok ? `Replay ready for ${id}` : "Replay unavailable", res && res.ok ? "ok" : "err");
98
+ }
99
+ }
100
+
101
+ function normalizeDefs(data) {
102
+ if (!data) return [];
103
+ if (Array.isArray(data.workflows)) return data.workflows;
104
+ if (Array.isArray(data.definitions)) return data.definitions;
105
+ if (Array.isArray(data)) return data;
106
+ return [];
107
+ }
108
+ function normalizeRuns(data) {
109
+ if (!data) return [];
110
+ if (Array.isArray(data.runs)) return data.runs;
111
+ if (Array.isArray(data)) return data;
112
+ return [];
113
+ }
114
+ function nodeIcon(type) {
115
+ return { trigger: "bolt", agent: "robot", plugin: "puzzle", tool: "tool", output: "flag", memory: "brain" }[type] || "point";
116
+ }
117
+ function mapStatus(s) {
118
+ const v = String(s || "").toLowerCase();
119
+ if (v === "ok" || v === "completed" || v === "success") return "ready";
120
+ if (v === "failed" || v === "error") return "failed";
121
+ if (v === "running") return "active";
122
+ return v || "idle";
123
+ }
124
+ function fmtTime(ts) {
125
+ if (!ts) return "—";
126
+ try { const d = new Date(ts); return Number.isNaN(d.getTime()) ? String(ts) : d.toLocaleString(undefined, { month: "short", day: "numeric", hour: "2-digit", minute: "2-digit" }); }
127
+ catch { return String(ts); }
128
+ }
@@ -4,10 +4,10 @@
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover, interactive-widget=resizes-content" />
6
6
  <title>Workflow Designer — Lattice AI</title>
7
- <script src="/static/scripts/ux.js?v=3.0.0"></script>
8
- <link rel="stylesheet" href="/static/css/tokens.css?v=3.0.0" />
9
- <link rel="stylesheet" href="/static/platform.css?v=3.0.0" />
10
- <link rel="stylesheet" href="/static/css/responsive.css?v=3.0.0" />
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
11
  </head>
12
12
  <body>
13
13
  <main>
@@ -4,14 +4,14 @@
4
4
  <meta charset="utf-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover, interactive-widget=resizes-content">
6
6
  <title>Lattice AI Workspace OS</title>
7
- <script src="/static/scripts/ux.js?v=3.0.0"></script>
7
+ <script src="/static/scripts/ux.js"></script>
8
8
  <link rel="manifest" href="/manifest.json">
9
9
  <link rel="icon" type="image/png" sizes="32x32" href="/icons/favicon-32.png">
10
10
  <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap">
11
11
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@tabler/icons-webfont@latest/tabler-icons.min.css">
12
- <link rel="stylesheet" href="/static/css/tokens.css?v=3.0.0">
13
- <link rel="stylesheet" href="/static/workspace.css?v=3.0.0">
14
- <link rel="stylesheet" href="/static/css/responsive.css?v=3.0.0">
12
+ <link rel="stylesheet" href="/static/css/tokens.css">
13
+ <link rel="stylesheet" href="/static/workspace.css">
14
+ <link rel="stylesheet" href="/static/css/responsive.css">
15
15
  </head>
16
16
  <body class="workspace-page">
17
17
  <div class="workspace-shell" data-workspace-mode="basic">
@@ -352,6 +352,6 @@
352
352
  </div>
353
353
 
354
354
  <div class="toast" id="toast"></div>
355
- <script src="/static/scripts/workspace.js?v=3.0.0"></script>
355
+ <script src="/static/scripts/workspace.js"></script>
356
356
  </body>
357
357
  </html>
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -1,171 +0,0 @@
1
- /* ============================================================================
2
- * Lattice AI v3 — Sample fixtures
3
- * Clearly-labeled SAMPLE data used ONLY as a graceful fallback when a backend
4
- * endpoint is not yet available. The UI always renders a "Sample data" badge
5
- * when these are used, so nothing here is presented as real backend output.
6
- * No backend logic is implemented — these are static shapes that mirror the
7
- * live API contracts so views remain usable during local setup.
8
- * ========================================================================== */
9
-
10
- export const INDEX_STATUS = {
11
- generated_at: null,
12
- pipelines: {
13
- knowledge_graph: { state: "ready", entities: 1284, relations: 3960, last_built: null, coverage: 0.91 },
14
- vector_index: { state: "ready", vectors: 48230, dimensions: 384, model: "lattice-local-hash-v1", coverage: 0.87 },
15
- hybrid: { state: "ready", strategy: "weighted-rank-fusion", weights: { keyword: 0.35, vector: 0.40, graph: 0.25 }, last_eval: null },
16
- },
17
- sources: [
18
- { id: "src-notes", label: "Workspace Notes", files: 312, state: "indexed", progress: 1 },
19
- { id: "src-repo", label: "Connected Repo", files: 1840, state: "indexed", progress: 1 },
20
- { id: "src-uploads", label: "Uploads", files: 96, state: "indexing", progress: 0.62 },
21
- ],
22
- };
23
-
24
- export const GRAPH = {
25
- nodes: [
26
- { id: "n:lattice", label: "Lattice AI", type: "Topic", weight: 0.98, x: 0.5, y: 0.46 },
27
- { id: "n:hybrid", label: "Hybrid Search", type: "Concept", weight: 0.86, x: 0.72, y: 0.30 },
28
- { id: "n:vector", label: "Vector Index", type: "Concept", weight: 0.84, x: 0.30, y: 0.28 },
29
- { id: "n:graph", label: "Knowledge Graph", type: "Concept", weight: 0.9, x: 0.5, y: 0.74 },
30
- { id: "n:embed", label: "lattice-local-hash-v1", type: "Model", weight: 0.6, x: 0.16, y: 0.5 },
31
- { id: "n:rrf", label: "Rank Fusion", type: "Method", weight: 0.58, x: 0.86, y: 0.54 },
32
- { id: "n:notes", label: "Workspace Notes", type: "File", weight: 0.52, x: 0.36, y: 0.9 },
33
- { id: "n:repo", label: "Connected Repo", type: "File", weight: 0.55, x: 0.66, y: 0.9 },
34
- ],
35
- edges: [
36
- { from: "n:lattice", to: "n:hybrid", type: "provides", weight: 1.0 },
37
- { from: "n:lattice", to: "n:graph", type: "builds", weight: 1.2 },
38
- { from: "n:lattice", to: "n:vector", type: "builds", weight: 1.1 },
39
- { from: "n:hybrid", to: "n:vector", type: "fuses", weight: 0.9 },
40
- { from: "n:hybrid", to: "n:graph", type: "fuses", weight: 0.9 },
41
- { from: "n:hybrid", to: "n:rrf", type: "uses", weight: 0.7 },
42
- { from: "n:vector", to: "n:embed", type: "uses", weight: 0.8 },
43
- { from: "n:graph", to: "n:notes", type: "from", weight: 0.6 },
44
- { from: "n:graph", to: "n:repo", type: "from", weight: 0.6 },
45
- ],
46
- };
47
-
48
- export const GRAPH_STATS = {
49
- nodes: { Topic: 1, Concept: 3, Model: 1, Method: 1, File: 2 },
50
- edges: { provides: 1, builds: 2, fuses: 2, uses: 2, from: 2 },
51
- total_nodes: 8,
52
- total_edges: 9,
53
- };
54
-
55
- export function hybridResults(query) {
56
- const q = (query || "retrieval").trim() || "retrieval";
57
- const base = [
58
- { id: "doc-1", title: "Hybrid retrieval design notes", path: "notes/retrieval.md", snippet: `…blends the knowledge graph and the vector field for "${q}", reconciling structure with semantic proximity…`, vector: 0.91, lexical: 0.64, graph: 0.78 },
59
- { id: "doc-2", title: "Vector index configuration", path: "config/index.yaml", snippet: `…embedding model and dimensions used to build the dense field that answers "${q}"…`, vector: 0.88, lexical: 0.41, graph: 0.35 },
60
- { id: "doc-3", title: "Graph entity: Rank Fusion", path: "graph://method/rrf", snippet: `…reciprocal-rank fusion merges ranked lists so a strong "${q}" signal in either modality surfaces…`, vector: 0.54, lexical: 0.33, graph: 0.95 },
61
- { id: "doc-4", title: "Workspace memory — decisions", path: "memory/decisions.md", snippet: `…prior decision relevant to "${q}", retrieved via graph adjacency from the active answer…`, vector: 0.49, lexical: 0.58, graph: 0.71 },
62
- { id: "doc-5", title: "Connected repo: README", path: "repo/README.md", snippet: `…lexical hit on "${q}" reinforced by neighboring entities in the knowledge graph…`, vector: 0.4, lexical: 0.82, graph: 0.4 },
63
- ];
64
- return base.map((r) => ({ ...r, score: Number((0.4 * r.vector + 0.35 * r.lexical + 0.25 * r.graph).toFixed(3)) }))
65
- .sort((a, b) => b.score - a.score);
66
- }
67
-
68
- export const WORKSPACE_OS = {
69
- version: "3.0.0",
70
- counts: { snapshots: 4, traces: 18, memories: 36, agent_runs: 12, workflows: 5, skills: 7, timeline: 24 },
71
- models: { current_model: "mlx-community/local-model-4bit", loaded_models: ["mlx-community/local-model-4bit"] },
72
- };
73
-
74
- export const MODELS = {
75
- current: "mlx-community/local-model-4bit",
76
- catalog: [
77
- { id: "mlx-community/local-model-4bit", name: "Local Model 4bit", family: "local", params: "12B", quant: "4bit", state: "loaded", context: 32768, recommended: true },
78
- { id: "mlx-community/reasoner-8bit", name: "Reasoner 8bit", family: "local", params: "8B", quant: "8bit", state: "available", context: 16384 },
79
- { id: "lattice-local-hash-v1", name: "lattice-local-hash-v1 (fallback vectors)", family: "embedding", params: "hash", quant: "local", state: "loaded", context: 384 },
80
- ],
81
- };
82
-
83
- export const AGENTS = [
84
- { id: "agent:planner", name: "Planner", role: "Decomposes goals into steps", state: "available", runs: 42, handoffs: ["agent:builder"] },
85
- { id: "agent:builder", name: "Builder", role: "Implements and edits files", state: "available", runs: 38, handoffs: ["agent:reviewer"] },
86
- { id: "agent:reviewer", name: "Reviewer", role: "Reviews diffs for risk", state: "idle", runs: 31, handoffs: [] },
87
- { id: "agent:retriever", name: "Retriever", role: "Runs hybrid search over the workspace", state: "available", runs: 57, handoffs: ["agent:planner"] },
88
- ];
89
-
90
- export const PIPELINES = [
91
- { id: "pl-ingest", name: "Ingest → Embed → Graph", state: "active", stages: ["Watch source", "Chunk", "Embed", "Extract entities", "Link graph"], last_run: null, throughput: "1.8k files/run" },
92
- { id: "pl-eval", name: "Retrieval Eval", state: "idle", stages: ["Sample queries", "Hybrid search", "Score fusion", "Report"], last_run: null, throughput: "120 q/run" },
93
- ];
94
-
95
- export const FILES = [
96
- { name: "retrieval.md", kind: "markdown", size: 4821, path: "notes/retrieval.md", indexed: true, updated: null },
97
- { name: "index.yaml", kind: "config", size: 932, path: "config/index.yaml", indexed: true, updated: null },
98
- { name: "decisions.md", kind: "markdown", size: 6210, path: "memory/decisions.md", indexed: true, updated: null },
99
- { name: "diagram.png", kind: "image", size: 184320, path: "assets/diagram.png", indexed: false, updated: null },
100
- { name: "dataset.csv", kind: "data", size: 51200, path: "data/dataset.csv", indexed: true, updated: null },
101
- ];
102
-
103
- export const SYSINFO = { cpu_pct: 28.4, ram_pct: 61.2, gpu_mem_pct: 44.0, gpu_mem_gb: 12.6 };
104
-
105
- export const CHAT = {
106
- conversations: [
107
- { id: "conv-hybrid", title: "How hybrid search ranks", updated_at: "2026-06-06T13:20:00", messages: [
108
- { role: "user", content: "How does hybrid search rank results?", timestamp: "2026-06-06T13:19:00" },
109
- { role: "assistant", content: "It fuses two signals: the vector index scores semantic similarity, while the knowledge graph scores structural proximity. Reciprocal-rank fusion merges the two ranked lists so a strong hit in either modality surfaces.", timestamp: "2026-06-06T13:20:00" },
110
- ] },
111
- { id: "conv-reindex", title: "Reindex the workspace", updated_at: "2026-06-06T11:05:00", messages: [
112
- { role: "user", content: "How do I rebuild the vector index?", timestamp: "2026-06-06T11:04:00" },
113
- { role: "assistant", content: "Trigger a rebuild from the Pipeline view, or call the index rebuild endpoint. The embedding model re-encodes every chunk and the graph is relinked.", timestamp: "2026-06-06T11:05:00" },
114
- ] },
115
- { id: "conv-entities", title: "Entities in retrieval.md", updated_at: "2026-06-05T18:40:00", messages: [
116
- { role: "user", content: "What entities were extracted from retrieval.md?", timestamp: "2026-06-05T18:39:00" },
117
- { role: "assistant", content: "Hybrid Search, Vector Index, and Rank Fusion, each linked back to Lattice AI in the knowledge graph.", timestamp: "2026-06-05T18:40:00" },
118
- ] },
119
- ],
120
- };
121
-
122
- /** Build a sample graph-RAG trace (mirrors the backend /chat trace shape). */
123
- export function sampleTrace(query) {
124
- return {
125
- question: query || "",
126
- confidence: 0.86,
127
- graph_nodes: GRAPH.nodes.slice(0, 4).map((n) => ({ id: n.id, title: n.label, type: n.type })),
128
- source_files: FILES.slice(0, 3).map((f) => ({ source: f.path })),
129
- vector_matches: [
130
- { path: "notes/retrieval.md", score: 0.91 },
131
- { path: "config/index.yaml", score: 0.78 },
132
- { path: "memory/decisions.md", score: 0.66 },
133
- ],
134
- };
135
- }
136
-
137
- export const ADMIN = {
138
- summary: { total_users: 6, active_users: 5, admin_users: 2, total_messages: 1284 },
139
- users: [
140
- { email: "owner@acme.dev", nickname: "Owner", role: "owner", disabled: false, last_seen: null },
141
- { email: "admin@acme.dev", nickname: "Admin", role: "admin", disabled: false, last_seen: null },
142
- { email: "ml@acme.dev", nickname: "ML Eng", role: "member", disabled: false, last_seen: null },
143
- { email: "guest@acme.dev", nickname: "Guest", role: "viewer", disabled: true, last_seen: null },
144
- ],
145
- roles: [
146
- { role: "owner", members: 1, caps: ["all"] },
147
- { role: "admin", members: 1, caps: ["users", "policies", "audit", "security"] },
148
- { role: "member", members: 3, caps: ["chat", "search", "files", "pipeline"] },
149
- { role: "viewer", members: 1, caps: ["chat", "search"] },
150
- ],
151
- audit: [
152
- { ts: null, actor: "admin@acme.dev", action: "policy.update", target: "local_file_access", severity: "informational" },
153
- { ts: null, actor: "ml@acme.dev", action: "search.hybrid", target: "q: retrieval design", severity: "informational" },
154
- { ts: null, actor: "owner@acme.dev", action: "user.invite", target: "guest@acme.dev", severity: "notice" },
155
- { ts: null, actor: "system", action: "index.rebuild", target: "vector_index", severity: "informational" },
156
- ],
157
- security: {
158
- risk_rate: 1.2,
159
- risky_messages: 3,
160
- compliant_messages: 1281,
161
- severity_counts: { high: 0, medium: 1, low: 2 },
162
- dlp_fields: [{ field: "email", hits: 4 }, { field: "api_key", hits: 1 }],
163
- },
164
- policies: [
165
- { id: "local_file_access", label: "Local file access", value: "Approval-token gated (per path/user/action)", enforced: true },
166
- { id: "package_install", label: "Package install", value: "Admin-only with audit trail", enforced: true },
167
- { id: "data_residency", label: "Data residency", value: "Single-tenant local storage (~/.ltcai)", enforced: true },
168
- { id: "model_egress", label: "Model egress", value: "Local-only (no external inference)", enforced: true },
169
- ],
170
- vpc: { provider: "local", region: "on-prem", vpn_status: "standby", peering_status: "not_configured", private_subnets: [], enabled: false },
171
- };