ltcai 6.5.0 → 6.7.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 (56) hide show
  1. package/README.md +35 -35
  2. package/docs/CHANGELOG.md +59 -2
  3. package/frontend/openapi.json +65 -1
  4. package/frontend/src/App.tsx +78 -3
  5. package/frontend/src/api/client.ts +1 -0
  6. package/frontend/src/api/openapi.ts +86 -0
  7. package/frontend/src/features/brain/BrainComposer.tsx +20 -1
  8. package/frontend/src/features/brain/BrainConversation.tsx +57 -4
  9. package/frontend/src/features/brain/BrainHome.tsx +41 -1
  10. package/frontend/src/features/brain/BrainOverviewPanel.tsx +62 -1
  11. package/frontend/src/features/brain/brainData.ts +54 -1
  12. package/frontend/src/features/brain/types.ts +37 -0
  13. package/frontend/src/i18n.ts +54 -0
  14. package/frontend/src/routes.ts +31 -17
  15. package/frontend/src/styles.css +216 -0
  16. package/lattice_brain/__init__.py +1 -1
  17. package/lattice_brain/graph/ingest.py +41 -6
  18. package/lattice_brain/ingestion.py +1 -0
  19. package/lattice_brain/runtime/multi_agent.py +1 -1
  20. package/latticeai/__init__.py +1 -1
  21. package/latticeai/api/knowledge_graph.py +11 -0
  22. package/latticeai/api/memory.py +14 -0
  23. package/latticeai/app_factory.py +2 -0
  24. package/latticeai/core/marketplace.py +1 -1
  25. package/latticeai/core/workspace_os.py +1 -1
  26. package/latticeai/runtime/chat_wiring.py +2 -0
  27. package/latticeai/runtime/router_registration.py +3 -0
  28. package/latticeai/services/memory_service.py +122 -2
  29. package/latticeai/services/router_context.py +1 -0
  30. package/latticeai/services/upload_service.py +12 -0
  31. package/package.json +1 -1
  32. package/src-tauri/Cargo.lock +1 -1
  33. package/src-tauri/Cargo.toml +1 -1
  34. package/src-tauri/tauri.conf.json +1 -1
  35. package/static/app/asset-manifest.json +84 -6
  36. package/static/app/assets/Act-DGN37eR4.js +2 -0
  37. package/static/app/assets/Act-DGN37eR4.js.map +1 -0
  38. package/static/app/assets/Brain-HDcIwPHW.js +322 -0
  39. package/static/app/assets/Brain-HDcIwPHW.js.map +1 -0
  40. package/static/app/assets/Capture--eZfb_Ex.js +2 -0
  41. package/static/app/assets/Capture--eZfb_Ex.js.map +1 -0
  42. package/static/app/assets/Library-BbagRFyd.js +2 -0
  43. package/static/app/assets/Library-BbagRFyd.js.map +1 -0
  44. package/static/app/assets/System-C6pd3Mp_.js +2 -0
  45. package/static/app/assets/System-C6pd3Mp_.js.map +1 -0
  46. package/static/app/assets/index-C950aES_.js +17 -0
  47. package/static/app/assets/index-C950aES_.js.map +1 -0
  48. package/static/app/assets/index-ztppMg0c.css +2 -0
  49. package/static/app/assets/primitives-Bcm5lZRu.js +2 -0
  50. package/static/app/assets/primitives-Bcm5lZRu.js.map +1 -0
  51. package/static/app/assets/textarea-C2PLu6_O.js +2 -0
  52. package/static/app/assets/textarea-C2PLu6_O.js.map +1 -0
  53. package/static/app/index.html +2 -2
  54. package/static/app/assets/index-C1J_1441.js +0 -16
  55. package/static/app/assets/index-C1J_1441.js.map +0 -1
  56. package/static/app/assets/index-CdCVz_i4.css +0 -2
package/README.md CHANGED
@@ -69,42 +69,42 @@ You need Lattice AI when:
69
69
  Choose the owner of the Brain. The profile is not a SaaS account by default; it
70
70
  is the local identity for the knowledge you keep.
71
71
 
72
- ![Login](output/release/v6.5.0/screenshots/01-login.png)
72
+ ![Login](output/release/v6.7.0/screenshots/01-login.png)
73
73
 
74
74
  ### 2. Environment Analysis
75
75
 
76
76
  See what kind of local AI experience this computer can support before choosing a
77
77
  model.
78
78
 
79
- ![Environment Analysis](output/release/v6.5.0/screenshots/02-environment-analysis.png)
79
+ ![Environment Analysis](output/release/v6.7.0/screenshots/02-environment-analysis.png)
80
80
 
81
81
  ### 3. Recommended Models
82
82
 
83
83
  Start with a short list: safest recommendation, faster model, stronger model.
84
84
  Advanced details stay available without overwhelming first-time users.
85
85
 
86
- ![Recommended Models](output/release/v6.5.0/screenshots/03-recommended-models.png)
86
+ ![Recommended Models](output/release/v6.7.0/screenshots/03-recommended-models.png)
87
87
 
88
88
  ### 4. Install And Load
89
89
 
90
90
  Download and load only after consent. Lattice explains model size, local
91
91
  execution, and network use before work starts.
92
92
 
93
- ![Install and Load](output/release/v6.5.0/screenshots/04-install-load-progress.png)
93
+ ![Install and Load](output/release/v6.7.0/screenshots/04-install-load-progress.png)
94
94
 
95
95
  ### 5. Brain Chat
96
96
 
97
97
  Talk normally. Useful decisions and context become memory, then appear later as
98
98
  topics, relationships, and graph structure.
99
99
 
100
- ![Brain Chat Home](output/release/v6.5.0/screenshots/05-brain-chat-home.png)
100
+ ![Brain Chat Home](output/release/v6.7.0/screenshots/05-brain-chat-home.png)
101
101
 
102
102
  ### 6. Review Center
103
103
 
104
104
  Automation results are staged for review before they become durable decisions.
105
105
  Snooze, unsnooze, run now, approve, and dismiss actions stay explicit.
106
106
 
107
- ![Review Center](output/release/v6.5.0/screenshots/13-review-center.png)
107
+ ![Review Center](output/release/v6.7.0/screenshots/13-review-center.png)
108
108
 
109
109
  ## Brain Depths
110
110
 
@@ -120,10 +120,10 @@ The user travels inward from everyday memory to deeper structure:
120
120
 
121
121
  Walkthrough:
122
122
 
123
- ![v6.5.0 Living Brain walkthrough](output/release/v6.5.0/gifs/v6.5.0-living-brain-walkthrough.gif)
123
+ ![v6.7.0 Living Brain walkthrough](output/release/v6.7.0/gifs/v6.7.0-living-brain-walkthrough.gif)
124
124
 
125
125
  Screenshot index and capture notes:
126
- [output/release/v6.5.0/SCREENSHOT_INDEX.md](output/release/v6.5.0/SCREENSHOT_INDEX.md)
126
+ [output/release/v6.7.0/SCREENSHOT_INDEX.md](output/release/v6.7.0/SCREENSHOT_INDEX.md)
127
127
 
128
128
  ## Install
129
129
 
@@ -198,33 +198,31 @@ npm run docs:check-links
198
198
 
199
199
  See [docs/DEVELOPMENT.md](docs/DEVELOPMENT.md) for developer workflow details.
200
200
 
201
- ## Current Release Preparation
202
-
203
- The current development target is **6.5.0 Brain Experience Readiness**:
204
-
205
- - Brain Home now gives normal users a readiness signal that explains whether
206
- the Brain is waiting for its first memory, turning memories into topics, or
207
- ready to explore as a connected map. That signal now comes from the backend
208
- Memory Manager summary instead of a frontend-only estimate.
209
- - The Living Brain surface now includes a persistent depth progress rail, so
210
- users can understand and reverse the path from conversation to memory,
211
- topics, relationships, and the full knowledge graph.
212
- - Memory-save feedback now explicitly states that saved context is available
213
- later with source-aware recall, closing the gap between "chat happened" and
214
- "my Brain became more useful."
215
- - The release keeps the 6.4.0 quality hardening intact and focuses on
216
- end-user comprehension rather than adding a new storage or graph schema.
217
- - The release remains local-first: no automatic web/email/calendar ingestion,
218
- no package publishing, no production deployment, and no external reranker or
219
- embedding API use without explicit opt-in.
220
-
221
- Expected artifacts for 6.5.0 release must use exact filenames:
222
-
223
- - `dist/ltcai-6.5.0-py3-none-any.whl`
224
- - `dist/ltcai-6.5.0.tar.gz`
225
- - `ltcai-6.5.0.tgz`
226
- - `dist/ltcai-6.5.0.vsix`
227
- - `src-tauri/target/release/bundle/dmg/Lattice AI_6.5.0_aarch64.dmg`
201
+ ## Current Release
202
+
203
+ The current release is **6.7.0 Brain IA Cleanup**:
204
+
205
+ - Brain Home now surfaces direct actions for adding documents, searching the
206
+ graph, changing models, and opening settings.
207
+ - The rich Capture, Brain explorer, Library, System, and Act pages are mounted
208
+ inside a shared Brain shell instead of existing only as hard-to-discover
209
+ compatibility routes.
210
+ - `routes.ts` now separates product shell routes from legacy compatibility
211
+ aliases, so visible IA and old entry URLs can evolve independently.
212
+ - Rich pages are code-split with lazy route loading. The first Brain Home bundle
213
+ stays below the previous warning threshold while graph/search/model/settings
214
+ surfaces load when opened.
215
+ - The release keeps the 6.6.0 backend-owned Brain proof loop and
216
+ workspace-scoped ingestion intact while making the product actions more
217
+ obvious in the first five minutes.
218
+
219
+ Expected artifacts for 6.7.0 release must use exact filenames:
220
+
221
+ - `dist/ltcai-6.7.0-py3-none-any.whl`
222
+ - `dist/ltcai-6.7.0.tar.gz`
223
+ - `ltcai-6.7.0.tgz`
224
+ - `dist/ltcai-6.7.0.vsix`
225
+ - `src-tauri/target/release/bundle/dmg/Lattice AI_6.7.0_aarch64.dmg`
228
226
 
229
227
  Do not upload `dist/*`. Package registry publishing remains owner-run.
230
228
 
@@ -243,6 +241,8 @@ Do not upload `dist/*`. Package registry publishing remains owner-run.
243
241
 
244
242
  | Version | Theme |
245
243
  | --- | --- |
244
+ | 6.7.0 | Brain IA Cleanup: reachable rich pages, separated product routes vs compatibility aliases, shared Brain shell navigation, and lazy-loaded rich pages |
245
+ | 6.6.0 | Brain Proof Runtime: backend-owned Brain proof API, model-continuity wiring, first-screen proof that saved context can be recalled across model changes, and direct Brain Home document upload |
246
246
  | 6.5.0 | Brain Experience Readiness: Brain readiness signal, depth progress rail, source-aware memory-save feedback, and visual coverage for the first-memory loop |
247
247
  | 6.4.0 | Digital Brain Quality Hardening: workspace-scoped graph/search/memory reads and mutations, Brain quality primitives, structured context guardrails, and retrieval benchmark coverage |
248
248
  | 6.3.1 | Access Runtime / i18n Follow-up: app-factory access-control extraction, focused access runtime tests, and Capture/Review Center i18n coverage |
package/docs/CHANGELOG.md CHANGED
@@ -1,7 +1,64 @@
1
1
  # Changelog
2
2
 
3
- The top entry is the current release-preparation target. Older entries are
4
- historical and may describe behavior as it existed at that release.
3
+ The top entry is either the current unreleased main-branch work or the current
4
+ release line. Older entries are historical and may describe behavior as it
5
+ existed at that release.
6
+
7
+ ## [6.7.0] - 2026-06-18
8
+
9
+ > Brain IA Cleanup. Makes rich product pages reachable from Brain Home,
10
+ > separates visible product IA from legacy compatibility aliases, and
11
+ > code-splits heavy pages out of the first Brain bundle.
12
+
13
+ ### Changed
14
+ - Brain Home now exposes direct action routes for adding documents, searching
15
+ the knowledge graph, changing models, and opening settings, so the rich
16
+ Capture, Brain explorer, Library, and System pages are reachable from the
17
+ first Brain flow.
18
+ - The post-onboarding app shell now mounts Capture, Brain explorer/graph,
19
+ Library, System, and Act pages inside a shared Brain shell navigation instead
20
+ of leaving those rich pages as compatibility-only routes.
21
+ - `routes.ts` now keeps product shell routes and compatibility aliases in
22
+ separate maps while preserving old hash/entry URLs.
23
+ - Rich pages now load through `React.lazy`, splitting Brain explorer, Capture,
24
+ Library, System, and Act chunks away from the initial Brain Home bundle.
25
+ - Package/runtime/static metadata is synchronized to 6.7.0; package publish and
26
+ deployment remain owner-run only.
27
+
28
+ ## [6.6.0] - 2026-06-18
29
+
30
+ > Brain Proof Runtime. Makes the first-five-minute Brain value visible by
31
+ > showing backend-owned evidence that saved context can be recalled and survives
32
+ > model changes.
33
+
34
+ ### Added
35
+ - `/api/memory/brain-proof`, backed by `MemoryService.brain_proof()`, combining
36
+ Brain readiness, durable memory counts, graph/vector depth, active model id,
37
+ and a unified recall sample.
38
+ - Brain Home proof strip for recallable context, model-continuity, and
39
+ knowledge-store state.
40
+ - Recent recall proof card that surfaces the latest memory/item the Brain can
41
+ bring back after a useful exchange.
42
+ - Brain Home document upload CTA in the empty state and composer, giving the
43
+ first session a direct way to grow the Brain with files.
44
+ - Refreshed README-linked release evidence under `output/release/v6.6.0/`.
45
+ - Unit coverage for model-independent Brain proof recall behavior.
46
+ - Honest empty-state Brain proof: model-independent capability remains visible,
47
+ but continuity is only marked proven after durable evidence exists.
48
+
49
+ ### Changed
50
+ - Interaction router runtime context now carries an active-model getter into
51
+ the Memory router, reducing app-factory inline wiring while preserving route
52
+ order.
53
+ - Default Brain proof recall seeding is scoped to the current user/workspace
54
+ before falling back to conversation memory.
55
+ - Chat-to-Knowledge-Graph ingestion now carries workspace scope into projected
56
+ graph nodes, and Brain proof conversation counts use scoped conversations so
57
+ another user/workspace cannot make an empty Brain look proven.
58
+ - Direct Knowledge Graph ingest and document upload ingestion now resolve the
59
+ request workspace and project that scope into graph/source/document nodes.
60
+ - Package/runtime/static metadata is synchronized to 6.6.0; package publish and
61
+ deployment remain owner-run only.
5
62
 
6
63
  ## [6.5.0] - 2026-06-18
7
64
 
@@ -3757,7 +3757,7 @@
3757
3757
  },
3758
3758
  "info": {
3759
3759
  "title": "Lattice AI Server (local)",
3760
- "version": "5.6.0"
3760
+ "version": "6.6.0"
3761
3761
  },
3762
3762
  "openapi": "3.1.0",
3763
3763
  "paths": {
@@ -6941,6 +6941,70 @@
6941
6941
  "summary": "Local Agent Status"
6942
6942
  }
6943
6943
  },
6944
+ "/api/memory/brain-proof": {
6945
+ "get": {
6946
+ "operationId": "brain_proof_api_memory_brain_proof_get",
6947
+ "parameters": [
6948
+ {
6949
+ "in": "query",
6950
+ "name": "q",
6951
+ "required": false,
6952
+ "schema": {
6953
+ "default": "",
6954
+ "title": "Q",
6955
+ "type": "string"
6956
+ }
6957
+ },
6958
+ {
6959
+ "in": "query",
6960
+ "name": "limit",
6961
+ "required": false,
6962
+ "schema": {
6963
+ "default": 3,
6964
+ "title": "Limit",
6965
+ "type": "integer"
6966
+ }
6967
+ }
6968
+ ],
6969
+ "responses": {
6970
+ "200": {
6971
+ "content": {
6972
+ "application/json": {
6973
+ "schema": {}
6974
+ }
6975
+ },
6976
+ "description": "Successful Response"
6977
+ },
6978
+ "422": {
6979
+ "content": {
6980
+ "application/json": {
6981
+ "schema": {
6982
+ "$ref": "#/components/schemas/HTTPValidationError"
6983
+ }
6984
+ }
6985
+ },
6986
+ "description": "Validation Error"
6987
+ }
6988
+ },
6989
+ "summary": "Brain Proof"
6990
+ }
6991
+ },
6992
+ "/api/memory/brain-quality": {
6993
+ "get": {
6994
+ "operationId": "brain_quality_summary_api_memory_brain_quality_get",
6995
+ "responses": {
6996
+ "200": {
6997
+ "content": {
6998
+ "application/json": {
6999
+ "schema": {}
7000
+ }
7001
+ },
7002
+ "description": "Successful Response"
7003
+ }
7004
+ },
7005
+ "summary": "Brain Quality Summary"
7006
+ }
7007
+ },
6944
7008
  "/api/memory/clear": {
6945
7009
  "post": {
6946
7010
  "operationId": "memory_clear_api_memory_clear_post",
@@ -2,11 +2,16 @@ import * as React from "react";
2
2
  import { type BrainState } from "@/components/LivingBrain";
3
3
  import { ProductFlow, readProductFlowComplete } from "@/components/ProductFlow";
4
4
  import { useAppStore } from "@/store/appStore";
5
- import { parseHash } from "@/routes";
6
- import { ActPage } from "@/pages/Act";
5
+ import { parseHash, productShellRoutes } from "@/routes";
7
6
  import { BrainHome } from "@/features/brain/BrainHome";
8
7
  import { AdminConsole } from "@/features/admin/AdminConsole";
9
8
 
9
+ const ActPage = React.lazy(() => import("@/pages/Act").then((module) => ({ default: module.ActPage })));
10
+ const BrainPage = React.lazy(() => import("@/pages/Brain").then((module) => ({ default: module.BrainPage })));
11
+ const CapturePage = React.lazy(() => import("@/pages/Capture").then((module) => ({ default: module.CapturePage })));
12
+ const LibraryPage = React.lazy(() => import("@/pages/Library").then((module) => ({ default: module.LibraryPage })));
13
+ const SystemPage = React.lazy(() => import("@/pages/System").then((module) => ({ default: module.SystemPage })));
14
+
10
15
  export default function App() {
11
16
  const theme = useAppStore((state) => state.theme);
12
17
  const language = useAppStore((state) => state.language);
@@ -41,7 +46,41 @@ export default function App() {
41
46
  {rawRoute.startsWith("/admin") ? (
42
47
  <AdminConsole onBack={() => navigateHash("/brain")} />
43
48
  ) : parsed.primary === "act" ? (
44
- <ActPage initialTab={parsed.tab} />
49
+ <BrainShell active={parsed.primary}>
50
+ <React.Suspense fallback={<PageLoader />}>
51
+ <ActPage initialTab={parsed.tab} />
52
+ </React.Suspense>
53
+ </BrainShell>
54
+ ) : parsed.primary === "capture" ? (
55
+ <BrainShell active={parsed.primary}>
56
+ <React.Suspense fallback={<PageLoader />}>
57
+ <CapturePage initialTab={parsed.tab} />
58
+ </React.Suspense>
59
+ </BrainShell>
60
+ ) : parsed.primary === "library" ? (
61
+ <BrainShell active={parsed.primary}>
62
+ <React.Suspense fallback={<PageLoader />}>
63
+ <LibraryPage initialTab={parsed.tab} />
64
+ </React.Suspense>
65
+ </BrainShell>
66
+ ) : parsed.primary === "system" ? (
67
+ <BrainShell active={parsed.primary}>
68
+ <React.Suspense fallback={<PageLoader />}>
69
+ <SystemPage initialTab={parsed.tab} />
70
+ </React.Suspense>
71
+ </BrainShell>
72
+ ) : parsed.primary === "memory" ? (
73
+ <BrainShell active="memory">
74
+ <React.Suspense fallback={<PageLoader />}>
75
+ <BrainPage initialTab="memory" />
76
+ </React.Suspense>
77
+ </BrainShell>
78
+ ) : parsed.primary === "brain" && parsed.tab && parsed.tab !== "conversation" ? (
79
+ <BrainShell active="brain">
80
+ <React.Suspense fallback={<PageLoader />}>
81
+ <BrainPage initialTab={parsed.tab} />
82
+ </React.Suspense>
83
+ </BrainShell>
45
84
  ) : (
46
85
  <BrainHome brainState={brainState} intensity={intensity} onBrainChange={setBrain} />
47
86
  )}
@@ -49,6 +88,42 @@ export default function App() {
49
88
  );
50
89
  }
51
90
 
91
+ function BrainShell({
92
+ active,
93
+ children,
94
+ }: {
95
+ active: string;
96
+ children: React.ReactNode;
97
+ }) {
98
+ return (
99
+ <main className="brain-shell-page" aria-label="Lattice workspace">
100
+ <nav className="brain-shell-nav" aria-label="Brain workspace navigation">
101
+ {productShellRoutes.map((item) => (
102
+ <button
103
+ key={item.id}
104
+ type="button"
105
+ className={item.id === active ? "is-active" : ""}
106
+ onClick={() => navigateHash(`/${item.path}`)}
107
+ >
108
+ {item.label}
109
+ </button>
110
+ ))}
111
+ </nav>
112
+ <section className="brain-shell-content">
113
+ {children}
114
+ </section>
115
+ </main>
116
+ );
117
+ }
118
+
119
+ function PageLoader() {
120
+ return (
121
+ <div className="brain-shell-loader" role="status">
122
+ Loading Brain workspace...
123
+ </div>
124
+ );
125
+ }
126
+
52
127
  function useHashRoute() {
53
128
  const read = React.useCallback(() => {
54
129
  const hash = window.location.hash.replace(/^#/, "");
@@ -446,6 +446,7 @@ export const latticeApi = {
446
446
  browserReadUrl: (url: string) => post("/api/browser/read-url", { url }, {}),
447
447
  memoryManager: () => get("/api/memory/manager", { sources: [], tiers: [], usage: {} }),
448
448
  memoryBrainQuality: () => get("/api/memory/brain-quality", {}),
449
+ memoryBrainProof: (query = "", limit = 3) => get("/api/memory/brain-proof", { proofs: {}, recall: { items: [] }, model_continuity: {}, claims: {} }, { q: query, limit }),
449
450
  memoryRecall: (query: string, limit = 20) => post("/api/memory/recall", { query, limit }, { matches: [] }),
450
451
  memoryCompact: () => post("/api/memory/compact", {}, {}),
451
452
  memoryRebuild: () => post("/api/memory/rebuild", { target: "vector" }, {}),
@@ -1550,6 +1550,40 @@ export interface paths {
1550
1550
  patch?: never;
1551
1551
  trace?: never;
1552
1552
  };
1553
+ "/api/memory/brain-proof": {
1554
+ parameters: {
1555
+ query?: never;
1556
+ header?: never;
1557
+ path?: never;
1558
+ cookie?: never;
1559
+ };
1560
+ /** Brain Proof */
1561
+ get: operations["brain_proof_api_memory_brain_proof_get"];
1562
+ put?: never;
1563
+ post?: never;
1564
+ delete?: never;
1565
+ options?: never;
1566
+ head?: never;
1567
+ patch?: never;
1568
+ trace?: never;
1569
+ };
1570
+ "/api/memory/brain-quality": {
1571
+ parameters: {
1572
+ query?: never;
1573
+ header?: never;
1574
+ path?: never;
1575
+ cookie?: never;
1576
+ };
1577
+ /** Brain Quality Summary */
1578
+ get: operations["brain_quality_summary_api_memory_brain_quality_get"];
1579
+ put?: never;
1580
+ post?: never;
1581
+ delete?: never;
1582
+ options?: never;
1583
+ head?: never;
1584
+ patch?: never;
1585
+ trace?: never;
1586
+ };
1553
1587
  "/api/memory/clear": {
1554
1588
  parameters: {
1555
1589
  query?: never;
@@ -10322,6 +10356,58 @@ export interface operations {
10322
10356
  };
10323
10357
  };
10324
10358
  };
10359
+ brain_proof_api_memory_brain_proof_get: {
10360
+ parameters: {
10361
+ query?: {
10362
+ q?: string;
10363
+ limit?: number;
10364
+ };
10365
+ header?: never;
10366
+ path?: never;
10367
+ cookie?: never;
10368
+ };
10369
+ requestBody?: never;
10370
+ responses: {
10371
+ /** @description Successful Response */
10372
+ 200: {
10373
+ headers: {
10374
+ [name: string]: unknown;
10375
+ };
10376
+ content: {
10377
+ "application/json": unknown;
10378
+ };
10379
+ };
10380
+ /** @description Validation Error */
10381
+ 422: {
10382
+ headers: {
10383
+ [name: string]: unknown;
10384
+ };
10385
+ content: {
10386
+ "application/json": components["schemas"]["HTTPValidationError"];
10387
+ };
10388
+ };
10389
+ };
10390
+ };
10391
+ brain_quality_summary_api_memory_brain_quality_get: {
10392
+ parameters: {
10393
+ query?: never;
10394
+ header?: never;
10395
+ path?: never;
10396
+ cookie?: never;
10397
+ };
10398
+ requestBody?: never;
10399
+ responses: {
10400
+ /** @description Successful Response */
10401
+ 200: {
10402
+ headers: {
10403
+ [name: string]: unknown;
10404
+ };
10405
+ content: {
10406
+ "application/json": unknown;
10407
+ };
10408
+ };
10409
+ };
10410
+ };
10325
10411
  memory_clear_api_memory_clear_post: {
10326
10412
  parameters: {
10327
10413
  query?: never;
@@ -1,5 +1,5 @@
1
1
  import * as React from "react";
2
- import { ImagePlus, Send } from "lucide-react";
2
+ import { FileUp, ImagePlus, Send } from "lucide-react";
3
3
  import { Button } from "@/components/ui/button";
4
4
  import { t, type Language } from "@/i18n";
5
5
 
@@ -8,16 +8,20 @@ export function BrainComposer({
8
8
  draft,
9
9
  streaming,
10
10
  imageData,
11
+ uploadingDocument,
11
12
  onDraftChange,
12
13
  onImageDataChange,
14
+ onUploadDocument,
13
15
  onSend,
14
16
  }: {
15
17
  language: Language;
16
18
  draft: string;
17
19
  streaming: boolean;
18
20
  imageData: string | null;
21
+ uploadingDocument: boolean;
19
22
  onDraftChange: (value: string) => void;
20
23
  onImageDataChange: (value: string | null) => void;
24
+ onUploadDocument: (file: File) => void;
21
25
  onSend: () => void;
22
26
  }) {
23
27
  return (
@@ -34,6 +38,21 @@ export function BrainComposer({
34
38
  placeholder={t(language, "brain.placeholder")}
35
39
  />
36
40
  <div className="brain-composer-actions">
41
+ <label className={`brain-document-input ${uploadingDocument ? "is-disabled" : ""}`}>
42
+ <FileUp className="h-3.5 w-3.5" />
43
+ <span>{uploadingDocument ? t(language, "brain.upload.uploading") : t(language, "brain.upload.ctaShort")}</span>
44
+ <input
45
+ type="file"
46
+ accept=".pdf,.docx,.xlsx,.pptx,.txt,.md,.csv,application/pdf,text/plain,text/markdown,text/csv"
47
+ className="sr-only"
48
+ disabled={uploadingDocument}
49
+ onChange={(event) => {
50
+ const file = event.target.files?.[0];
51
+ event.currentTarget.value = "";
52
+ if (file) onUploadDocument(file);
53
+ }}
54
+ />
55
+ </label>
37
56
  <label className="brain-image-input">
38
57
  <ImagePlus className="h-3.5 w-3.5" />
39
58
  <span>{t(language, "brain.image")}</span>
@@ -1,8 +1,8 @@
1
1
  import * as React from "react";
2
- import { DatabaseZap, ShieldCheck } from "lucide-react";
2
+ import { Cpu, DatabaseZap, FileUp, Search, Settings, ShieldCheck } from "lucide-react";
3
3
  import { LanguageSwitcher } from "@/components/LanguageSwitcher";
4
4
  import { t, type Language } from "@/i18n";
5
- import type { BrainDepth, BrainReadiness, KnowledgeConcept, MemoryFragment, Message } from "./types";
5
+ import type { BrainDepth, BrainProof, BrainReadiness, KnowledgeConcept, MemoryFragment, Message } from "./types";
6
6
  import { BrainCarePanel } from "./BrainCarePanel";
7
7
  import { BrainComposer } from "./BrainComposer";
8
8
  import { BrainOverviewPanel } from "./BrainOverviewPanel";
@@ -21,9 +21,12 @@ export function BrainConversation({
21
21
  memories,
22
22
  concepts,
23
23
  readiness,
24
+ proof,
25
+ uploadingDocument,
24
26
  onOpenDepth,
25
27
  onDraftChange,
26
28
  onImageDataChange,
29
+ onUploadDocument,
27
30
  onSend,
28
31
  }: {
29
32
  language: Language;
@@ -39,9 +42,12 @@ export function BrainConversation({
39
42
  memories: MemoryFragment[];
40
43
  concepts: KnowledgeConcept[];
41
44
  readiness: BrainReadiness;
45
+ proof: BrainProof;
46
+ uploadingDocument: boolean;
42
47
  onOpenDepth: (depth: BrainDepth) => void;
43
48
  onDraftChange: (value: string) => void;
44
49
  onImageDataChange: (value: string | null) => void;
50
+ onUploadDocument: (file: File) => void;
45
51
  onSend: () => void;
46
52
  }) {
47
53
  return (
@@ -57,7 +63,25 @@ export function BrainConversation({
57
63
  <span>{t(language, "brain.portable")}</span>
58
64
  <span>{t(language, "brain.private")}</span>
59
65
  </div>
60
- <div>{modelName}</div>
66
+ <div className="brain-flow-actions" aria-label={t(language, "brain.aria.actions")}>
67
+ <button type="button" onClick={() => navigateHash("/capture")}>
68
+ <FileUp className="h-3.5 w-3.5" />
69
+ {t(language, "brain.action.add")}
70
+ </button>
71
+ <button type="button" onClick={() => navigateHash("/knowledge-graph")}>
72
+ <Search className="h-3.5 w-3.5" />
73
+ {t(language, "brain.action.find")}
74
+ </button>
75
+ <button type="button" onClick={() => navigateHash("/models")}>
76
+ <Cpu className="h-3.5 w-3.5" />
77
+ {t(language, "brain.action.model")}
78
+ </button>
79
+ <button type="button" onClick={() => navigateHash("/settings")}>
80
+ <Settings className="h-3.5 w-3.5" />
81
+ {t(language, "brain.action.settings")}
82
+ </button>
83
+ </div>
84
+ <div className="brain-model-pill">{modelName}</div>
61
85
  <button className="brain-admin-link" type="button" onClick={() => navigateHash("/admin")}>
62
86
  <ShieldCheck className="h-3.5 w-3.5" />
63
87
  {t(language, "brain.admin")}
@@ -69,10 +93,17 @@ export function BrainConversation({
69
93
  memories={memories}
70
94
  concepts={concepts}
71
95
  readiness={readiness}
96
+ proof={proof}
72
97
  onOpenDepth={onOpenDepth}
73
98
  />
74
99
  {messages.length === 0 ? (
75
- <BrainEmptyState language={language} starterPrompts={starterPrompts} onDraftChange={onDraftChange} />
100
+ <BrainEmptyState
101
+ language={language}
102
+ starterPrompts={starterPrompts}
103
+ uploadingDocument={uploadingDocument}
104
+ onDraftChange={onDraftChange}
105
+ onUploadDocument={onUploadDocument}
106
+ />
76
107
  ) : (
77
108
  messages.map((message, index) => (
78
109
  <div key={`${message.role}-${index}`} className={`brain-message ${message.role}`}>
@@ -97,8 +128,10 @@ export function BrainConversation({
97
128
  draft={draft}
98
129
  streaming={streaming}
99
130
  imageData={imageData}
131
+ uploadingDocument={uploadingDocument}
100
132
  onDraftChange={onDraftChange}
101
133
  onImageDataChange={onImageDataChange}
134
+ onUploadDocument={onUploadDocument}
102
135
  onSend={onSend}
103
136
  />
104
137
  </section>
@@ -108,17 +141,37 @@ export function BrainConversation({
108
141
  function BrainEmptyState({
109
142
  language,
110
143
  starterPrompts,
144
+ uploadingDocument,
111
145
  onDraftChange,
146
+ onUploadDocument,
112
147
  }: {
113
148
  language: Language;
114
149
  starterPrompts: string[];
150
+ uploadingDocument: boolean;
115
151
  onDraftChange: (value: string) => void;
152
+ onUploadDocument: (file: File) => void;
116
153
  }) {
117
154
  return (
118
155
  <div className="mind-empty">
119
156
  <div className="mind-empty-kicker">{t(language, "brain.empty.kicker")}</div>
120
157
  <div className="mind-empty-title">{t(language, "brain.empty.title")}</div>
121
158
  <p>{t(language, "brain.empty.body")}</p>
159
+ <label className={`mind-empty-upload ${uploadingDocument ? "is-disabled" : ""}`}>
160
+ <DatabaseZap className="h-3.5 w-3.5" />
161
+ <span>{uploadingDocument ? t(language, "brain.upload.uploading") : t(language, "brain.upload.cta")}</span>
162
+ <input
163
+ type="file"
164
+ accept=".pdf,.docx,.xlsx,.pptx,.txt,.md,.csv,application/pdf,text/plain,text/markdown,text/csv"
165
+ className="sr-only"
166
+ disabled={uploadingDocument}
167
+ onChange={(event) => {
168
+ const file = event.target.files?.[0];
169
+ event.currentTarget.value = "";
170
+ if (file) onUploadDocument(file);
171
+ }}
172
+ />
173
+ </label>
174
+ <small className="mind-empty-upload-hint">{t(language, "brain.upload.hint")}</small>
122
175
  <div className="mind-empty-prompts" aria-label={t(language, "brain.aria.starterPrompts")}>
123
176
  {starterPrompts.map((prompt) => (
124
177
  <button key={prompt} type="button" onClick={() => onDraftChange(prompt)}>