ltcai 7.7.0 → 7.8.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 +24 -16
- package/docs/CHANGELOG.md +20 -0
- package/frontend/src/App.tsx +3 -1
- package/frontend/src/components/ProductFlow.tsx +19 -23
- package/frontend/src/components/onboarding/RecommendationScreen.tsx +11 -12
- package/frontend/src/features/brain/BrainConversation.tsx +107 -108
- package/frontend/src/features/brain/BrainHome.tsx +32 -33
- package/frontend/src/i18n.ts +53 -19
- package/frontend/src/pages/Ask.tsx +11 -2
- package/frontend/src/pages/Brain.tsx +12 -2
- package/frontend/src/styles.css +390 -65
- package/lattice_brain/__init__.py +1 -1
- package/lattice_brain/runtime/multi_agent.py +1 -1
- package/latticeai/__init__.py +1 -1
- package/latticeai/core/marketplace.py +1 -1
- package/latticeai/core/workspace_os.py +1 -1
- package/latticeai/services/architecture_readiness.py +1 -1
- package/latticeai/services/product_readiness.py +15 -15
- package/package.json +1 -1
- package/scripts/product_readiness.py +1 -1
- package/src-tauri/Cargo.toml +1 -1
- package/src-tauri/tauri.conf.json +1 -1
- package/static/app/asset-manifest.json +28 -28
- package/static/app/assets/Act-DOvf59ru.js +2 -0
- package/static/app/assets/{Act-CX5hL0Z3.js.map → Act-DOvf59ru.js.map} +1 -1
- package/static/app/assets/Brain-C7_0mEiI.js +322 -0
- package/static/app/assets/Brain-C7_0mEiI.js.map +1 -0
- package/static/app/assets/Capture-B9Tlhzqr.js +2 -0
- package/static/app/assets/{Capture-CdFSrZnA.js.map → Capture-B9Tlhzqr.js.map} +1 -1
- package/static/app/assets/{Library-CZFVGSmG.js → Library-BJPEEm5O.js} +2 -2
- package/static/app/assets/{Library-CZFVGSmG.js.map → Library-BJPEEm5O.js.map} +1 -1
- package/static/app/assets/System-D6t9jo9V.js +2 -0
- package/static/app/assets/{System-CMoOoUrZ.js.map → System-D6t9jo9V.js.map} +1 -1
- package/static/app/assets/index-C7g26IF6.css +2 -0
- package/static/app/assets/index-DbcEYJQ2.js +17 -0
- package/static/app/assets/{index-B4_drWel.js.map → index-DbcEYJQ2.js.map} +1 -1
- package/static/app/assets/primitives-CD38lt4n.js +2 -0
- package/static/app/assets/{primitives-CFhU5Rka.js.map → primitives-CD38lt4n.js.map} +1 -1
- package/static/app/assets/textarea-BZk6ybp5.js +2 -0
- package/static/app/assets/{textarea-uBpGDOJM.js.map → textarea-BZk6ybp5.js.map} +1 -1
- package/static/app/index.html +2 -2
- package/frontend/src/components/BrainConversation.tsx +0 -533
- package/frontend/src/components/FirstRunGuide.tsx +0 -99
- package/static/app/assets/Act-CX5hL0Z3.js +0 -2
- package/static/app/assets/Brain-m19en5wz.js +0 -322
- package/static/app/assets/Brain-m19en5wz.js.map +0 -1
- package/static/app/assets/Capture-CdFSrZnA.js +0 -2
- package/static/app/assets/System-CMoOoUrZ.js +0 -2
- package/static/app/assets/index-B4_drWel.js +0 -17
- package/static/app/assets/index-DjpDeE0c.css +0 -2
- package/static/app/assets/primitives-CFhU5Rka.js +0 -2
- package/static/app/assets/textarea-uBpGDOJM.js +0 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Lattice AI
|
|
2
2
|
|
|
3
|
-
**Lattice AI 7.
|
|
3
|
+
**Lattice AI 7.8 is the glanceable local-first Digital Brain product. It keeps your knowledge durable across any AI model, with Brain Chat Home rebuilt around immediate use instead of dashboard clutter.**
|
|
4
4
|
|
|
5
5
|
**Lattice AI는 모델이 바뀌어도 내 지식과 맥락을 보존하는 로컬 우선 AI 브레인입니다.**
|
|
6
6
|
|
|
@@ -11,7 +11,7 @@ downloads, update checks, and other external communication happen only after
|
|
|
11
11
|
explicit consent.
|
|
12
12
|
|
|
13
13
|
It is not a ChatGPT clone, a model launcher, a graph database, or a note app.
|
|
14
|
-
It is the finished private AI memory layer wrapped in a Living Brain experience — 7.
|
|
14
|
+
It is the finished private AI memory layer wrapped in a Living Brain experience — now with a cleaner 7.8 Brain Chat Home.
|
|
15
15
|
|
|
16
16
|
[](https://pypi.org/project/ltcai/)
|
|
17
17
|
[](https://www.npmjs.com/package/ltcai)
|
|
@@ -64,6 +64,10 @@ You need Lattice AI when:
|
|
|
64
64
|
|
|
65
65
|
## Living Brain Flow
|
|
66
66
|
|
|
67
|
+
The screenshots below are release evidence captures. The 7.8 line keeps the
|
|
68
|
+
same first-run flow and rebuilds the Brain Chat Home layout so chat and the
|
|
69
|
+
composer are the first visible action.
|
|
70
|
+
|
|
67
71
|
### 1. Wake Brain
|
|
68
72
|
|
|
69
73
|
The first screen makes the Brain the product. It explains the three-step path:
|
|
@@ -206,30 +210,33 @@ See [docs/DEVELOPMENT.md](docs/DEVELOPMENT.md) for developer workflow details.
|
|
|
206
210
|
|
|
207
211
|
## Current Release
|
|
208
212
|
|
|
209
|
-
The current release is **7.
|
|
213
|
+
The current release is **7.8.0 — Brain Chat Home UX Simplification**:
|
|
210
214
|
|
|
211
|
-
- Brain Home now opens with
|
|
212
|
-
action,
|
|
213
|
-
|
|
214
|
-
-
|
|
215
|
-
|
|
215
|
+
- Brain Chat Home now opens with chat, starter prompts, and the composer as the
|
|
216
|
+
first action. Source ingestion, readiness, proof, timeline, and care controls
|
|
217
|
+
move behind a single utility drawer instead of occupying the first viewport.
|
|
218
|
+
- The default Brain surface now keeps workspace navigation visible, removes
|
|
219
|
+
permanent marketing intro copy, and only reveals deep memory controls after
|
|
220
|
+
the user chooses to travel deeper.
|
|
221
|
+
- Obsolete Brain conversation and first-run guide components were removed so the
|
|
222
|
+
canonical Brain/onboarding implementation is the only path.
|
|
216
223
|
- Product readiness is machine-checkable through `product_readiness()`, which
|
|
217
224
|
composes the architecture contract with exact artifact/docs/workflow evidence.
|
|
218
225
|
- CI and release workflows now run frontend lint/typecheck/build gates plus the
|
|
219
|
-
7.
|
|
226
|
+
7.8 product readiness score before a tag can be treated as release-safe.
|
|
220
227
|
|
|
221
|
-
Expected artifacts for 7.
|
|
228
|
+
Expected artifacts for 7.8.0 release must use exact filenames:
|
|
222
229
|
|
|
223
|
-
- `dist/ltcai-7.
|
|
224
|
-
- `dist/ltcai-7.
|
|
225
|
-
- `ltcai-7.
|
|
226
|
-
- `dist/ltcai-7.
|
|
227
|
-
- `src-tauri/target/release/bundle/dmg/Lattice AI_7.
|
|
230
|
+
- `dist/ltcai-7.8.0-py3-none-any.whl`
|
|
231
|
+
- `dist/ltcai-7.8.0.tar.gz`
|
|
232
|
+
- `ltcai-7.8.0.tgz`
|
|
233
|
+
- `dist/ltcai-7.8.0.vsix`
|
|
234
|
+
- `src-tauri/target/release/bundle/dmg/Lattice AI_7.8.0_aarch64.dmg`
|
|
228
235
|
|
|
229
236
|
Do not upload `dist/*`. Package registry publishing remains owner-run.
|
|
230
237
|
|
|
231
238
|
See [docs/ROADMAP_RECOMMENDATIONS.md](docs/ROADMAP_RECOMMENDATIONS.md) for the
|
|
232
|
-
strategic roadmap slices applied through 7.
|
|
239
|
+
strategic roadmap slices applied through 7.8.0 and the follow-up tracks.
|
|
233
240
|
|
|
234
241
|
## Known Limitations
|
|
235
242
|
|
|
@@ -246,6 +253,7 @@ strategic roadmap slices applied through 7.7.0 and the follow-up tracks.
|
|
|
246
253
|
|
|
247
254
|
| Version | Theme |
|
|
248
255
|
| --- | --- |
|
|
256
|
+
| 7.8.0 | Brain Chat Home UX Simplification: chat-first first viewport, visible workspace navigation, collapsed source/status utilities, hidden default depth controls, and removal of obsolete Brain UX components |
|
|
249
257
|
| 7.7.0 | Complete Product Polish: command-center Brain Home, repaired Review Center evidence, exact 7.7 docs/artifacts, product readiness gate, and stronger CI/release checks |
|
|
250
258
|
| 7.6.0 | Brain-Centered UX & Architecture Closure: Wake Brain first-run surface, concentric memory rings with direct depth controls, and machine-checkable closure of the two architecture/UX review files |
|
|
251
259
|
| 7.5.0 | Runtime Debt Burn-down & Release Risk Cleanup: API consumers get normalized contract views, retrieval quality uses a 250+ record corpus fixture, stale artifact risk is removed, npm audit is clean, and Tauri is updated past the old block warning |
|
package/docs/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,26 @@ The top entry is either the current unreleased main-branch work or the current
|
|
|
4
4
|
release line. Older entries are historical and may describe behavior as it
|
|
5
5
|
existed at that release.
|
|
6
6
|
|
|
7
|
+
## [Unreleased]
|
|
8
|
+
|
|
9
|
+
## [7.8.0] - 2026-06-22
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
- Rebuilt Brain Chat Home around immediate conversation: chat purpose, starter
|
|
13
|
+
prompts, and the composer now occupy the first viewport.
|
|
14
|
+
- Collapsed source ingestion, readiness, proof, timeline, overview, model
|
|
15
|
+
continuity, and care controls behind one utility drawer.
|
|
16
|
+
- Kept workspace navigation visible on the default Brain surface.
|
|
17
|
+
- Hid default depth controls until the user intentionally travels deeper.
|
|
18
|
+
- Integrated the six post-7.7 UX drafts into the canonical Brain experience:
|
|
19
|
+
first-run value cards, stronger recommendation affordances, product-toned
|
|
20
|
+
Brain Home copy, and routed legacy Brain conversation entry points to the
|
|
21
|
+
canonical Brain Home surface.
|
|
22
|
+
- Removed obsolete Brain conversation and first-run guide components.
|
|
23
|
+
- Moved draft onboarding polish out of inline styles and into the shared design
|
|
24
|
+
stylesheet with responsive behavior and bilingual copy.
|
|
25
|
+
- Updated architecture and product readiness targets to 7.8.0.
|
|
26
|
+
|
|
7
27
|
## [7.7.0] - 2026-06-22
|
|
8
28
|
|
|
9
29
|
> 7.7.0 marks the complete, finished product stage for Lattice AI.
|
package/frontend/src/App.tsx
CHANGED
|
@@ -88,7 +88,9 @@ export default function App() {
|
|
|
88
88
|
</React.Suspense>
|
|
89
89
|
</BrainShell>
|
|
90
90
|
) : (
|
|
91
|
-
<
|
|
91
|
+
<BrainShell active="brain">
|
|
92
|
+
<BrainHome brainState={brainState} intensity={intensity} onBrainChange={setBrain} />
|
|
93
|
+
</BrainShell>
|
|
92
94
|
)}
|
|
93
95
|
</div>
|
|
94
96
|
);
|
|
@@ -3,7 +3,7 @@ import { latticeApi } from "@/api/client";
|
|
|
3
3
|
import { type BrainState, LivingBrain } from "@/components/LivingBrain";
|
|
4
4
|
import { t } from "@/i18n";
|
|
5
5
|
import { useAppStore } from "@/store/appStore";
|
|
6
|
-
import { ArrowRight, Shield, Zap
|
|
6
|
+
import { ArrowRight, Cpu, Shield, Zap } from "lucide-react";
|
|
7
7
|
import {
|
|
8
8
|
AnalysisScreen,
|
|
9
9
|
InstallScreen,
|
|
@@ -107,25 +107,26 @@ export function ProductFlow({ onComplete }: { onComplete: () => void }) {
|
|
|
107
107
|
|
|
108
108
|
function WakeBrainScreen({ onWake, onUseExisting }: { onWake: () => void; onUseExisting: () => void }) {
|
|
109
109
|
const language = useAppStore((state) => state.language);
|
|
110
|
+
const valueCards = [
|
|
111
|
+
{ icon: Shield, label: t(language, "flow.wake.value.local.k"), body: t(language, "flow.wake.value.local.v") },
|
|
112
|
+
{ icon: Zap, label: t(language, "flow.wake.value.instant.k"), body: t(language, "flow.wake.value.instant.v") },
|
|
113
|
+
{ icon: Cpu, label: t(language, "flow.wake.value.brain.k"), body: t(language, "flow.wake.value.brain.v") },
|
|
114
|
+
];
|
|
110
115
|
return (
|
|
111
116
|
<section className="ritual-wake" aria-label={t(language, "flow.wake.aria")}>
|
|
112
117
|
<div className="ritual-title">{t(language, "flow.wake.title")}</div>
|
|
113
118
|
<div className="ritual-subtitle">{t(language, "flow.wake.body")}</div>
|
|
114
119
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
<div style={{border: "1px solid hsl(var(--border)/0.5)", borderRadius: "12px", padding: "0.7rem 0.8rem", background: "hsl(var(--surface))", textAlign: "left"}}>
|
|
126
|
-
<div style={{display: "flex", alignItems: "center", gap: "0.4rem", color: "hsl(var(--brain-core))", fontSize: "0.75rem", fontWeight: 700}}><Cpu size={14}/> 영원한 Brain</div>
|
|
127
|
-
<div style={{fontSize: "0.85rem", marginTop: "0.2rem", fontWeight: 600}}>모델 바꿔도 지식은 그대로 영원히</div>
|
|
128
|
-
</div>
|
|
120
|
+
<div className="ritual-value-grid" aria-label={t(language, "flow.wake.value.aria")}>
|
|
121
|
+
{valueCards.map((card) => {
|
|
122
|
+
const Icon = card.icon;
|
|
123
|
+
return (
|
|
124
|
+
<div className="ritual-value-card" key={card.label}>
|
|
125
|
+
<div className="ritual-value-label"><Icon size={14} /> {card.label}</div>
|
|
126
|
+
<div className="ritual-value-body">{card.body}</div>
|
|
127
|
+
</div>
|
|
128
|
+
);
|
|
129
|
+
})}
|
|
129
130
|
</div>
|
|
130
131
|
|
|
131
132
|
<div className="ritual-wake-plan" aria-label={t(language, "flow.wake.plan.aria")}>
|
|
@@ -143,20 +144,15 @@ function WakeBrainScreen({ onWake, onUseExisting }: { onWake: () => void; onUseE
|
|
|
143
144
|
</div>
|
|
144
145
|
</div>
|
|
145
146
|
|
|
146
|
-
<div className="ritual-button-row
|
|
147
|
-
<button
|
|
148
|
-
type="button"
|
|
149
|
-
className="ritual-full-button"
|
|
150
|
-
onClick={onWake}
|
|
151
|
-
style={{fontSize: "1.05rem", padding: "0.85rem 2.2rem", display: "inline-flex", alignItems: "center", gap: "0.5rem"}}
|
|
152
|
-
>
|
|
147
|
+
<div className="ritual-button-row ritual-button-row-primary">
|
|
148
|
+
<button type="button" className="ritual-full-button ritual-full-button-primary" onClick={onWake}>
|
|
153
149
|
{t(language, "flow.wake.primary")} <ArrowRight size={18} />
|
|
154
150
|
</button>
|
|
155
151
|
<button type="button" className="ritual-secondary-button" onClick={onUseExisting}>
|
|
156
152
|
{t(language, "flow.wake.existing")}
|
|
157
153
|
</button>
|
|
158
154
|
</div>
|
|
159
|
-
<div
|
|
155
|
+
<div className="ritual-start-note">{t(language, "flow.wake.startNote")}</div>
|
|
160
156
|
</section>
|
|
161
157
|
);
|
|
162
158
|
}
|
|
@@ -2,7 +2,7 @@ import { Button } from "@/components/ui/button";
|
|
|
2
2
|
import { t, type Language } from "@/i18n";
|
|
3
3
|
import { useAppStore } from "@/store/appStore";
|
|
4
4
|
import { fallbackModel, type RecommendedModel } from "./recommendationModel";
|
|
5
|
-
import {
|
|
5
|
+
import { ArrowRight, Gauge, Star, Zap } from "lucide-react";
|
|
6
6
|
|
|
7
7
|
export function RecommendationScreen({
|
|
8
8
|
recommendations,
|
|
@@ -24,9 +24,9 @@ export function RecommendationScreen({
|
|
|
24
24
|
|
|
25
25
|
<div className="ritual-model-list">
|
|
26
26
|
{items[0]?.supported ? (
|
|
27
|
-
<div className="ritual-primary-cta"
|
|
28
|
-
<Button onClick={() => onSelect(items[0])} className="ritual-primary-model-button"
|
|
29
|
-
{t(language, "flow.recommend.primary")} <ArrowRight size={16}/>
|
|
27
|
+
<div className="ritual-primary-cta">
|
|
28
|
+
<Button onClick={() => onSelect(items[0])} className="ritual-primary-model-button">
|
|
29
|
+
{t(language, "flow.recommend.primary")} <ArrowRight size={16} />
|
|
30
30
|
</Button>
|
|
31
31
|
<div className="ritual-time-estimate ritual-primary-note">{primaryNote(items[0], language)}</div>
|
|
32
32
|
<div className="ritual-muted-hint ritual-next-hint">{t(language, "flow.recommend.nextHint")}</div>
|
|
@@ -40,24 +40,23 @@ export function RecommendationScreen({
|
|
|
40
40
|
className="ritual-model-card"
|
|
41
41
|
onClick={() => model.supported && onSelect(model)}
|
|
42
42
|
disabled={!model.supported}
|
|
43
|
-
style={{display: "flex", flexDirection: "column", alignItems: "flex-start", gap: "0.3rem"}}
|
|
44
43
|
>
|
|
45
|
-
<div
|
|
46
|
-
<Icon size={16}
|
|
47
|
-
<div className="role"
|
|
44
|
+
<div className="ritual-model-heading">
|
|
45
|
+
<Icon size={16} />
|
|
46
|
+
<div className="role">{rankLabel(model.role, index, language)}</div>
|
|
48
47
|
</div>
|
|
49
|
-
<div className="name"
|
|
50
|
-
<div className="reason"
|
|
48
|
+
<div className="name">{model.shortName}</div>
|
|
49
|
+
<div className="reason">
|
|
51
50
|
{model.reason} · {model.size || t(language, "flow.recommend.sizeReady")}
|
|
52
51
|
{comparisonLabel(model.role, language) ? (
|
|
53
52
|
<span className="ritual-model-comparison"> {comparisonLabel(model.role, language)}</span>
|
|
54
53
|
) : null}
|
|
55
54
|
</div>
|
|
56
|
-
<div className="ritual-model-stats"
|
|
55
|
+
<div className="ritual-model-stats">
|
|
57
56
|
<span className="ritual-time-estimate">{timeEstimate(model, language)}</span>
|
|
58
57
|
</div>
|
|
59
58
|
{model.supported ? (
|
|
60
|
-
<span className="ritual-model-choose"
|
|
59
|
+
<span className="ritual-model-choose">{t(language, "flow.recommend.choose")} <ArrowRight size={14} /></span>
|
|
61
60
|
) : (
|
|
62
61
|
<div className="ritual-model-warning">{t(language, "flow.recommend.unsupported")}</div>
|
|
63
62
|
)}
|
|
@@ -12,7 +12,6 @@ import {
|
|
|
12
12
|
Loader2,
|
|
13
13
|
Repeat2,
|
|
14
14
|
Search,
|
|
15
|
-
Settings,
|
|
16
15
|
ShieldCheck,
|
|
17
16
|
Sparkles,
|
|
18
17
|
} from "lucide-react";
|
|
@@ -44,7 +43,6 @@ import { BrainOverviewPanel } from "./BrainOverviewPanel";
|
|
|
44
43
|
|
|
45
44
|
export function BrainConversation({
|
|
46
45
|
language,
|
|
47
|
-
explorationDepth,
|
|
48
46
|
modelName,
|
|
49
47
|
messages,
|
|
50
48
|
starterPrompts,
|
|
@@ -100,129 +98,130 @@ export function BrainConversation({
|
|
|
100
98
|
return (
|
|
101
99
|
<section className="brain-conversation" aria-label={t(language, "brain.aria.conversation")}>
|
|
102
100
|
<div className="brain-conversation-header">
|
|
103
|
-
<div>
|
|
101
|
+
<div className="brain-conversation-title">
|
|
104
102
|
<h1>
|
|
105
103
|
{t(language, "brain.title")}
|
|
106
104
|
<span className="brain-edition-badge" title={t(language, "brain.edition.tip")}>
|
|
107
105
|
{t(language, "brain.edition")}
|
|
108
106
|
</span>
|
|
109
107
|
</h1>
|
|
110
|
-
<span>{t(language,
|
|
111
|
-
</div>
|
|
112
|
-
<LanguageSwitcher compact />
|
|
113
|
-
<div className="brain-ownership-strip" aria-label={t(language, "brain.aria.ownership")}>
|
|
114
|
-
<span>{t(language, "brain.local")}</span>
|
|
115
|
-
<span>{t(language, "brain.portable")}</span>
|
|
116
|
-
<span>{t(language, "brain.private")}</span>
|
|
108
|
+
<span>{t(language, "brain.chatHome.headerLine")}</span>
|
|
117
109
|
</div>
|
|
118
|
-
<div className="brain-
|
|
119
|
-
<
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
<Search className="h-3.5 w-3.5" />
|
|
125
|
-
{t(language, "brain.action.find")}
|
|
126
|
-
</button>
|
|
127
|
-
<button type="button" onClick={() => navigateHash("/models")}>
|
|
128
|
-
<Cpu className="h-3.5 w-3.5" />
|
|
129
|
-
{t(language, "brain.action.model")}
|
|
130
|
-
</button>
|
|
131
|
-
<button type="button" onClick={() => navigateHash("/settings")}>
|
|
132
|
-
<Settings className="h-3.5 w-3.5" />
|
|
133
|
-
{t(language, "brain.action.settings")}
|
|
110
|
+
<div className="brain-header-tools">
|
|
111
|
+
<LanguageSwitcher compact />
|
|
112
|
+
<div className="brain-model-pill">{modelName}</div>
|
|
113
|
+
<button className="brain-admin-link" type="button" onClick={() => navigateHash("/admin")}>
|
|
114
|
+
<ShieldCheck className="h-3.5 w-3.5" />
|
|
115
|
+
{t(language, "brain.admin")}
|
|
134
116
|
</button>
|
|
135
117
|
</div>
|
|
136
|
-
<div className="brain-model-pill">{modelName}</div>
|
|
137
|
-
<button className="brain-admin-link" type="button" onClick={() => navigateHash("/admin")}>
|
|
138
|
-
<ShieldCheck className="h-3.5 w-3.5" />
|
|
139
|
-
{t(language, "brain.admin")}
|
|
140
|
-
</button>
|
|
141
118
|
</div>
|
|
142
119
|
|
|
143
|
-
<div
|
|
144
|
-
<
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
120
|
+
<div className="brain-chat-home-layout">
|
|
121
|
+
<section className="brain-chat-home-card" aria-label={t(language, "brain.chatHome.aria")}>
|
|
122
|
+
<div className="brain-chat-home-head">
|
|
123
|
+
<div>
|
|
124
|
+
<span>{t(language, "brain.chatHome.kicker")}</span>
|
|
125
|
+
<h2>{t(language, "brain.chatHome.title")}</h2>
|
|
126
|
+
<p>{t(language, "brain.chatHome.body")}</p>
|
|
127
|
+
</div>
|
|
128
|
+
<div className="brain-chat-home-proof" aria-label={t(language, "brain.aria.ownership")}>
|
|
129
|
+
<span><CheckCircle2 className="h-3.5 w-3.5" />{t(language, "brain.local")}</span>
|
|
130
|
+
<span><CheckCircle2 className="h-3.5 w-3.5" />{t(language, "brain.private")}</span>
|
|
131
|
+
<span><CheckCircle2 className="h-3.5 w-3.5" />{t(language, "brain.portable")}</span>
|
|
132
|
+
</div>
|
|
133
|
+
</div>
|
|
134
|
+
|
|
135
|
+
<div ref={streamRef} className="brain-stream">
|
|
136
|
+
{messages.length === 0 ? (
|
|
137
|
+
<BrainEmptyState
|
|
138
|
+
language={language}
|
|
139
|
+
starterPrompts={starterPrompts}
|
|
140
|
+
uploadingDocument={uploadingDocument}
|
|
141
|
+
onDraftChange={onDraftChange}
|
|
142
|
+
onUploadDocument={onUploadDocument}
|
|
143
|
+
/>
|
|
144
|
+
) : (
|
|
145
|
+
messages.map((message, index) => {
|
|
146
|
+
const messageId = `brain-msg-${index}`;
|
|
147
|
+
const proof = message.role === "assistant" ? message.proof : undefined;
|
|
148
|
+
return (
|
|
149
|
+
<div key={`${message.role}-${index}`} className={`brain-message ${message.role}`}>
|
|
150
|
+
<div className="brain-message-bubble">
|
|
151
|
+
{message.content}
|
|
152
|
+
{proof && proof.citations.length ? (
|
|
153
|
+
<InlineCitationMarkers language={language} proof={proof} messageId={messageId} />
|
|
154
|
+
) : null}
|
|
155
|
+
</div>
|
|
156
|
+
{proof ? <AnswerProofCard language={language} proof={proof} messageId={messageId} /> : null}
|
|
157
|
+
</div>
|
|
158
|
+
);
|
|
159
|
+
})
|
|
160
|
+
)}
|
|
161
|
+
</div>
|
|
162
|
+
|
|
163
|
+
{memoryFeedback ? (
|
|
164
|
+
<div className="brain-save-feedback" role="status">
|
|
165
|
+
<DatabaseZap className="h-3.5 w-3.5" />
|
|
166
|
+
<span>{memoryFeedback}</span>
|
|
167
|
+
<small>{t(language, "brain.saved.detail")}</small>
|
|
168
|
+
</div>
|
|
169
|
+
) : null}
|
|
170
|
+
|
|
171
|
+
<BrainComposer
|
|
180
172
|
language={language}
|
|
181
|
-
|
|
173
|
+
draft={draft}
|
|
174
|
+
streaming={streaming}
|
|
175
|
+
imageData={imageData}
|
|
182
176
|
uploadingDocument={uploadingDocument}
|
|
183
177
|
onDraftChange={onDraftChange}
|
|
178
|
+
onImageDataChange={onImageDataChange}
|
|
184
179
|
onUploadDocument={onUploadDocument}
|
|
180
|
+
onSend={onSend}
|
|
185
181
|
/>
|
|
186
|
-
) : (
|
|
187
|
-
messages.map((message, index) => {
|
|
188
|
-
const messageId = `brain-msg-${index}`;
|
|
189
|
-
const proof = message.role === "assistant" ? message.proof : undefined;
|
|
190
|
-
return (
|
|
191
|
-
<div key={`${message.role}-${index}`} className={`brain-message ${message.role}`}>
|
|
192
|
-
<div className="brain-message-bubble">
|
|
193
|
-
{message.content}
|
|
194
|
-
{proof && proof.citations.length ? (
|
|
195
|
-
<InlineCitationMarkers language={language} proof={proof} messageId={messageId} />
|
|
196
|
-
) : null}
|
|
197
|
-
</div>
|
|
198
|
-
{proof ? <AnswerProofCard language={language} proof={proof} messageId={messageId} /> : null}
|
|
199
|
-
</div>
|
|
200
|
-
);
|
|
201
|
-
})
|
|
202
|
-
)}
|
|
203
|
-
</div>
|
|
204
182
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
183
|
+
<details className="brain-utility-drawer">
|
|
184
|
+
<summary>{t(language, "brain.chatHome.utility")}</summary>
|
|
185
|
+
<div className="brain-utility-grid">
|
|
186
|
+
<BrainIngestionPanel
|
|
187
|
+
language={language}
|
|
188
|
+
uploadingDocument={uploadingDocument}
|
|
189
|
+
ingestionStates={ingestionStates}
|
|
190
|
+
onUploadDocument={onUploadDocument}
|
|
191
|
+
onConnectFolder={onConnectFolder}
|
|
192
|
+
onIngestNote={onIngestNote}
|
|
193
|
+
onIngestWeb={onIngestWeb}
|
|
194
|
+
/>
|
|
195
|
+
<ProductCommandCenter
|
|
196
|
+
language={language}
|
|
197
|
+
readiness={readiness}
|
|
198
|
+
proof={proof}
|
|
199
|
+
modelName={modelName}
|
|
200
|
+
memories={memories}
|
|
201
|
+
concepts={concepts}
|
|
202
|
+
emergenceEvents={emergenceEvents}
|
|
203
|
+
onOpenDepth={onOpenDepth}
|
|
204
|
+
onVerifyModelContinuity={onVerifyModelContinuity}
|
|
205
|
+
/>
|
|
206
|
+
<IngestionTimelineSection language={language} emergenceEvents={emergenceEvents} />
|
|
207
|
+
<ModelContinuityDemo
|
|
208
|
+
language={language}
|
|
209
|
+
proof={proof}
|
|
210
|
+
modelName={modelName}
|
|
211
|
+
onVerify={onVerifyModelContinuity}
|
|
212
|
+
/>
|
|
213
|
+
<BrainOverviewPanel
|
|
214
|
+
memories={memories}
|
|
215
|
+
concepts={concepts}
|
|
216
|
+
readiness={readiness}
|
|
217
|
+
proof={proof}
|
|
218
|
+
onOpenDepth={onOpenDepth}
|
|
219
|
+
/>
|
|
220
|
+
<BrainCarePanel language={language} />
|
|
221
|
+
</div>
|
|
222
|
+
</details>
|
|
223
|
+
</section>
|
|
224
|
+
</div>
|
|
226
225
|
</section>
|
|
227
226
|
);
|
|
228
227
|
}
|
|
@@ -483,11 +483,6 @@ export function BrainHome({
|
|
|
483
483
|
|
|
484
484
|
return (
|
|
485
485
|
<main className="brain-home" aria-label={t(language, "brain.aria.home")}>
|
|
486
|
-
{/* 강력하고 직관적인 첫인상 - BrainHome */}
|
|
487
|
-
<div style={{textAlign: "center", marginBottom: "0.4rem", opacity: 0.9}}>
|
|
488
|
-
<div style={{fontSize: "0.78rem", letterSpacing: "1.5px", textTransform: "uppercase", color: "hsl(var(--brain-core))"}}>LATTICE AI — YOUR LIVING BRAIN</div>
|
|
489
|
-
<div style={{fontSize: "1.05rem", fontWeight: 600, marginTop: "0.15rem"}}>대화할수록 더 똑똑해지는, 당신만의 영원한 지식</div>
|
|
490
|
-
</div>
|
|
491
486
|
<section className="brain-presence" aria-label={t(language, "brain.aria.exploration")}>
|
|
492
487
|
<div className="brain-exploration" data-depth={explorationDepth}>
|
|
493
488
|
<LivingBrain
|
|
@@ -499,34 +494,38 @@ export function BrainHome({
|
|
|
499
494
|
onInteract={deepen}
|
|
500
495
|
/>
|
|
501
496
|
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
<
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
497
|
+
{explorationDepth > 1 ? (
|
|
498
|
+
<>
|
|
499
|
+
<BrainDepthRings explorationDepth={explorationDepth} onOpenDepth={jumpToDepth} />
|
|
500
|
+
|
|
501
|
+
<div className="brain-depth-badge" aria-live="polite">
|
|
502
|
+
<span>{t(language, "brain.level")} {explorationDepth}</span>
|
|
503
|
+
<strong>{t(language, `brain.depth.${explorationDepth}`)}</strong>
|
|
504
|
+
</div>
|
|
505
|
+
|
|
506
|
+
<div className="brain-depth-actions" aria-label={t(language, "brain.aria.quickViews")}>
|
|
507
|
+
<button type="button" className={explorationDepth === 2 ? "is-active" : ""} onClick={() => jumpToDepth(2)}>{t(language, "brain.view.memories")}</button>
|
|
508
|
+
<button type="button" className={explorationDepth === 3 ? "is-active" : ""} onClick={() => jumpToDepth(3)}>{t(language, "brain.view.topics")}</button>
|
|
509
|
+
<button type="button" className={explorationDepth === 4 ? "is-active" : ""} onClick={() => jumpToDepth(4)}>{t(language, "brain.view.relationships")}</button>
|
|
510
|
+
<button type="button" className={explorationDepth === 5 ? "is-active" : ""} onClick={() => jumpToDepth(5)}>{t(language, "brain.view.graph")}</button>
|
|
511
|
+
</div>
|
|
512
|
+
|
|
513
|
+
<div className="brain-depth-rail" aria-label={t(language, "brain.depthRail.aria")}>
|
|
514
|
+
{DEPTHS.map((depth) => (
|
|
515
|
+
<button
|
|
516
|
+
key={depth.level}
|
|
517
|
+
type="button"
|
|
518
|
+
className={depth.level <= explorationDepth ? "is-revealed" : ""}
|
|
519
|
+
aria-current={depth.level === explorationDepth ? "step" : undefined}
|
|
520
|
+
onClick={() => jumpToDepth(depth.level)}
|
|
521
|
+
>
|
|
522
|
+
<span>{depth.level}</span>
|
|
523
|
+
<strong>{t(language, `brain.depth.${depth.level}`)}</strong>
|
|
524
|
+
</button>
|
|
525
|
+
))}
|
|
526
|
+
</div>
|
|
527
|
+
</>
|
|
528
|
+
) : null}
|
|
530
529
|
|
|
531
530
|
<div className="brain-field-layer" aria-hidden={explorationDepth < 2}>
|
|
532
531
|
<DepthEmergence
|