ltcai 6.1.0 → 6.3.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 +36 -38
- package/docs/CHANGELOG.md +75 -1
- package/frontend/src/App.tsx +3 -1286
- package/frontend/src/components/LanguageSwitcher.tsx +23 -0
- package/frontend/src/components/ProductFlow.tsx +32 -669
- package/frontend/src/components/onboarding/AnalysisScreen.tsx +127 -0
- package/frontend/src/components/onboarding/DownloadConsentPanel.tsx +29 -0
- package/frontend/src/components/onboarding/InstallScreen.tsx +208 -0
- package/frontend/src/components/onboarding/LanguageChooser.tsx +23 -0
- package/frontend/src/components/onboarding/LoginScreen.tsx +131 -0
- package/frontend/src/components/onboarding/ProductFlowScreens.tsx +13 -0
- package/frontend/src/components/onboarding/RecommendationScreen.tsx +59 -0
- package/frontend/src/components/onboarding/recommendationModel.ts +132 -0
- package/frontend/src/features/admin/AdminConsole.tsx +294 -0
- package/frontend/src/features/brain/BrainCarePanel.tsx +254 -0
- package/frontend/src/features/brain/BrainComposer.tsx +66 -0
- package/frontend/src/features/brain/BrainConversation.tsx +131 -0
- package/frontend/src/features/brain/BrainGraphLayer.tsx +132 -0
- package/frontend/src/features/brain/BrainHome.tsx +232 -0
- package/frontend/src/features/brain/BrainMemoryLayer.tsx +38 -0
- package/frontend/src/features/brain/BrainOverviewPanel.tsx +74 -0
- package/frontend/src/features/brain/BrainRelationshipLayer.tsx +43 -0
- package/frontend/src/features/brain/DepthEmergence.tsx +53 -0
- package/frontend/src/features/brain/brainData.ts +98 -0
- package/frontend/src/features/brain/graphLayout.ts +26 -0
- package/frontend/src/features/brain/types.ts +44 -0
- package/frontend/src/features/review/ReviewCard.tsx +3 -1
- package/frontend/src/features/review/ReviewInbox.tsx +11 -1
- package/frontend/src/i18n.ts +290 -0
- package/frontend/src/pages/Brain.tsx +63 -5
- package/frontend/src/pages/Capture.tsx +102 -13
- package/frontend/src/pages/Library.tsx +72 -6
- package/frontend/src/styles.css +220 -0
- package/lattice_brain/__init__.py +1 -1
- package/lattice_brain/runtime/multi_agent.py +1 -1
- package/latticeai/__init__.py +1 -1
- package/latticeai/api/tools.py +50 -23
- package/latticeai/app_factory.py +59 -76
- package/latticeai/cli/entrypoint.py +283 -0
- package/latticeai/core/marketplace.py +1 -1
- package/latticeai/core/workspace_os.py +1 -1
- package/latticeai/integrations/__init__.py +0 -0
- package/latticeai/integrations/telegram_bot.py +1009 -0
- package/latticeai/runtime/chat_wiring.py +119 -0
- package/latticeai/runtime/lifespan_runtime.py +1 -1
- package/latticeai/runtime/model_wiring.py +40 -0
- package/latticeai/runtime/platform_runtime_wiring.py +86 -0
- package/latticeai/runtime/review_wiring.py +37 -0
- package/latticeai/runtime/router_registration.py +49 -30
- package/latticeai/runtime/tail_wiring.py +21 -0
- package/latticeai/services/p_reinforce.py +258 -0
- package/latticeai/services/router_context.py +52 -0
- package/ltcai_cli.py +7 -279
- package/p_reinforce.py +4 -255
- package/package.json +3 -2
- package/scripts/check_i18n_literals.mjs +52 -0
- package/scripts/release_smoke.py +133 -0
- package/scripts/wheel_smoke.py +4 -0
- package/src-tauri/Cargo.lock +1 -1
- package/src-tauri/Cargo.toml +1 -1
- package/src-tauri/tauri.conf.json +1 -1
- package/static/app/asset-manifest.json +5 -5
- package/static/app/assets/index-D76dWuQk.js +16 -0
- package/static/app/assets/index-D76dWuQk.js.map +1 -0
- package/static/app/assets/index-Div5vMlq.css +2 -0
- package/static/app/index.html +2 -2
- package/telegram_bot.py +9 -1002
- package/static/app/assets/index-B744yblP.css +0 -2
- package/static/app/assets/index-DYaUKNfl.js +0 -16
- package/static/app/assets/index-DYaUKNfl.js.map +0 -1
package/frontend/src/i18n.ts
CHANGED
|
@@ -18,11 +18,24 @@ export const COPY: Record<Language, TextMap> = {
|
|
|
18
18
|
"brain.depth.3": "주제",
|
|
19
19
|
"brain.depth.4": "관계",
|
|
20
20
|
"brain.depth.5": "전체 지식 그래프",
|
|
21
|
+
"brain.depthLabel.1": "살아있는 Brain",
|
|
22
|
+
"brain.depthLabel.2": "기억 계층",
|
|
23
|
+
"brain.depthLabel.3": "지식 계층",
|
|
24
|
+
"brain.depthLabel.4": "관계 계층",
|
|
25
|
+
"brain.depthLabel.5": "지식 그래프",
|
|
21
26
|
"brain.view.memories": "기억 보기",
|
|
22
27
|
"brain.view.topics": "주제 보기",
|
|
23
28
|
"brain.view.relationships": "관계 보기",
|
|
24
29
|
"brain.view.graph": "그래프로 보기",
|
|
25
30
|
"brain.surface": "돌아가기",
|
|
31
|
+
"brain.aria.home": "Lattice Brain",
|
|
32
|
+
"brain.aria.exploration": "Brain 탐색",
|
|
33
|
+
"brain.aria.quickViews": "Brain 빠른 보기",
|
|
34
|
+
"brain.aria.conversation": "대화",
|
|
35
|
+
"brain.aria.ownership": "Brain 소유 보장",
|
|
36
|
+
"brain.aria.starterPrompts": "시작 프롬프트",
|
|
37
|
+
"brain.aria.overview": "Brain 한눈에 보기",
|
|
38
|
+
"brain.aria.graph": "지식 그래프",
|
|
26
39
|
"brain.title": "Lattice Brain",
|
|
27
40
|
"brain.local": "로컬 우선",
|
|
28
41
|
"brain.portable": "이동 가능",
|
|
@@ -54,36 +67,150 @@ export const COPY: Record<Language, TextMap> = {
|
|
|
54
67
|
"brain.overview.olderEmpty": "대화가 쌓이면 과거 기억이 보입니다.",
|
|
55
68
|
"brain.overview.topics": "주요 주제",
|
|
56
69
|
"brain.overview.topicsEmpty": "주제가 형성되는 중입니다.",
|
|
70
|
+
"brain.memory.empty": "기억이 조용합니다.",
|
|
71
|
+
"brain.knowledge.empty": "지식이 형성되는 중입니다.",
|
|
57
72
|
"brain.graph.empty": "아직 맞는 지식이 없습니다.",
|
|
58
73
|
"brain.graph.summaryFallback": "이 개념은 가장 깊은 지식 계층의 일부입니다.",
|
|
59
74
|
"brain.graph.focused": "대화와 문서에서 함께 나온 내용이 선으로 이어집니다.",
|
|
60
75
|
"brain.graph.emptyFocus": "대화, 문서, 프로젝트를 쌓으면 Brain 그래프가 자랍니다.",
|
|
76
|
+
"brain.graph.search": "검색",
|
|
77
|
+
"brain.graph.searchAria": "지식 그래프 검색",
|
|
61
78
|
"care.title": "내 Brain 돌보기",
|
|
62
79
|
"care.subtitle": "내 컴퓨터에 두고, 필요하면 옮길 수 있습니다.",
|
|
63
80
|
"care.private": "개인 보관",
|
|
81
|
+
"care.ownershipModel": "소유 모델",
|
|
64
82
|
"care.export": "내보내기",
|
|
65
83
|
"care.export.detail": "다른 곳으로 가져가기",
|
|
66
84
|
"care.backup": "백업",
|
|
67
85
|
"care.backup.detail": "복사본 저장",
|
|
86
|
+
"care.backup.count": "백업 {count}개",
|
|
87
|
+
"care.backup.ready": "백업 준비됨",
|
|
68
88
|
"care.archive": "보관 파일",
|
|
69
89
|
"care.archive.detail": "암호화된 Brain",
|
|
70
90
|
"care.path.placeholder": "확인하거나 미리 볼 보관 파일 경로",
|
|
71
91
|
"care.path.label": "Brain 보관 파일 경로",
|
|
72
92
|
"care.passphrase.placeholder": "보관 파일 비밀번호",
|
|
73
93
|
"care.passphrase.label": "Brain 보관 파일 비밀번호",
|
|
94
|
+
"care.passphrase.confirmPlaceholder": "비밀번호 다시 입력",
|
|
95
|
+
"care.passphrase.confirmLabel": "Brain 보관 파일 비밀번호 확인",
|
|
96
|
+
"care.passphrase.tooShort": "비밀번호는 12자 이상이어야 합니다.",
|
|
97
|
+
"care.passphrase.tooSimple": "대문자, 소문자, 숫자, 기호 중 3종류 이상을 섞어 주세요.",
|
|
98
|
+
"care.passphrase.mismatch": "비밀번호 확인이 일치하지 않습니다.",
|
|
99
|
+
"care.passphrase.strong": "비밀번호 강도가 충분합니다.",
|
|
100
|
+
"care.path.ready": "보관 파일 경로 형식이 올바릅니다.",
|
|
101
|
+
"care.path.invalidChars": "보관 파일 경로에 사용할 수 없는 문자가 있습니다.",
|
|
102
|
+
"care.path.extension": ".latticebrain, .zip, .json 파일만 확인할 수 있습니다.",
|
|
74
103
|
"care.inspect": "확인",
|
|
75
104
|
"care.restorePreview": "복원 미리보기",
|
|
76
105
|
"care.note": "복원 미리보기는 Brain을 바꾸지 않고 보관 파일만 확인합니다. 실제 복원은 설정에서 확정합니다.",
|
|
77
106
|
"care.working": "진행 중",
|
|
107
|
+
"care.result.error": "Brain 관리 작업을 완료하지 못했습니다.",
|
|
108
|
+
"care.result.completed": "Brain 관리 작업 완료",
|
|
109
|
+
"care.result.path": "파일: {path}",
|
|
110
|
+
"care.result.contents": "기억 {memories}개 · 연결 {links}개 · 대화 {conversations}개",
|
|
111
|
+
"care.result.dryRun": "미리보기만 실행되어 현재 Brain은 바뀌지 않았습니다.",
|
|
78
112
|
"admin.back": "Brain",
|
|
113
|
+
"admin.aria.console": "Lattice 관리자",
|
|
79
114
|
"admin.kicker": "분리된 관리자 작업공간",
|
|
80
115
|
"admin.title": "Admin Console",
|
|
81
116
|
"admin.body": "사용자, 로그, 보안, Brain 상태는 일반 사용자 화면과 분리됩니다.",
|
|
117
|
+
"admin.overview": "관리 개요",
|
|
118
|
+
"admin.metric.users": "사용자",
|
|
119
|
+
"admin.metric.logs": "최근 로그",
|
|
120
|
+
"admin.metric.security": "보안",
|
|
121
|
+
"admin.metric.index": "Brain 인덱스",
|
|
122
|
+
"admin.status.ready": "준비됨",
|
|
123
|
+
"admin.status.unavailable": "사용 불가",
|
|
124
|
+
"admin.status.indexed": "인덱싱됨",
|
|
125
|
+
"admin.status.unknown": "알 수 없음",
|
|
126
|
+
"admin.panel.users": "사용자 디렉터리",
|
|
127
|
+
"admin.panel.people": "사람",
|
|
128
|
+
"admin.panel.roles": "역할 권한",
|
|
129
|
+
"admin.panel.access": "접근",
|
|
130
|
+
"admin.panel.logs": "활동 로그",
|
|
131
|
+
"admin.panel.audit": "감사",
|
|
132
|
+
"admin.panel.securityEvents": "보안 이벤트",
|
|
133
|
+
"admin.panel.protection": "보호",
|
|
134
|
+
"admin.panel.brainOps": "Brain 운영",
|
|
135
|
+
"admin.panel.maintenance": "유지보수",
|
|
136
|
+
"admin.empty.users": "관리 API가 보고한 사용자가 없습니다.",
|
|
137
|
+
"admin.empty.roles": "보고된 역할 매트릭스가 없습니다.",
|
|
138
|
+
"admin.empty.audit": "최근 감사 이벤트가 없습니다.",
|
|
139
|
+
"admin.empty.security": "보고된 보안 이벤트가 없습니다.",
|
|
140
|
+
"admin.fallback.localUser": "로컬 사용자",
|
|
141
|
+
"admin.fallback.member": "멤버",
|
|
142
|
+
"admin.fallback.role": "역할",
|
|
143
|
+
"admin.fallback.noCaps": "권한 없음",
|
|
144
|
+
"admin.filters.label": "감사 로그 필터",
|
|
145
|
+
"admin.filters.search": "로그 검색",
|
|
146
|
+
"admin.filters.searchAria": "감사 로그 검색",
|
|
147
|
+
"admin.filters.severityAria": "심각도별 필터",
|
|
148
|
+
"admin.filters.all": "모든 심각도",
|
|
149
|
+
"admin.filters.informational": "정보",
|
|
150
|
+
"admin.filters.notice": "알림",
|
|
151
|
+
"admin.filters.warning": "경고",
|
|
152
|
+
"admin.filters.high": "높음",
|
|
153
|
+
"admin.filters.matched": "{count}개 일치",
|
|
154
|
+
"admin.brain.summaryFallback": "로컬 Brain 서비스는 사용자 대화와 분리되어 있습니다.",
|
|
155
|
+
"admin.brain.rebuilding": "재구성 중",
|
|
156
|
+
"admin.brain.rebuild": "인덱스 재구성",
|
|
157
|
+
"admin.policy.fallback": "정책",
|
|
158
|
+
"admin.policy.quiet": "정책 API 대기 중",
|
|
159
|
+
"admin.retention.days": "{days}일 보관",
|
|
160
|
+
"admin.retention.detail": "{events}개 보관 · {candidates}개 내보내기/정리 검토 가능",
|
|
161
|
+
"admin.log.event": "이벤트",
|
|
162
|
+
"admin.log.system": "시스템",
|
|
163
|
+
"admin.log.recently": "최근",
|
|
164
|
+
"admin.source.loading": "불러오는 중",
|
|
165
|
+
"admin.source.live": "라이브",
|
|
166
|
+
"admin.index.ready": "인덱스 상태 준비됨",
|
|
167
|
+
"flow.analysis.fact.computer": "컴퓨터",
|
|
168
|
+
"flow.analysis.fact.memory": "메모리",
|
|
169
|
+
"flow.analysis.fact.graphics": "그래픽",
|
|
170
|
+
"flow.analysis.fact.support": "로컬 지원",
|
|
171
|
+
"flow.analysis.fact.models": "모델",
|
|
172
|
+
"flow.analysis.checking": "확인 중",
|
|
173
|
+
"flow.analysis.fact.computerDetail": "운영체제와 칩",
|
|
174
|
+
"flow.analysis.fact.memoryDetail": "로컬 사고를 위한 여유 공간",
|
|
175
|
+
"flow.analysis.fact.graphicsDetail": "로컬 가속 지원",
|
|
176
|
+
"flow.analysis.fact.supportDetail": "설치된 모델 도우미",
|
|
177
|
+
"flow.analysis.fact.modelsDetail": "설치된 로컬 Brain",
|
|
178
|
+
"flow.analysis.apple": "Apple Silicon Mac",
|
|
179
|
+
"flow.analysis.detected": "감지됨",
|
|
180
|
+
"flow.analysis.localReady": "로컬 가속 준비됨",
|
|
181
|
+
"flow.analysis.standardLocal": "표준 로컬 모드",
|
|
182
|
+
"flow.analysis.supportReady": "준비됨",
|
|
183
|
+
"flow.analysis.supportInstall": "준비 예정",
|
|
184
|
+
"flow.analysis.modelsInstalled": "{count}개 이미 설치됨",
|
|
185
|
+
"flow.analysis.noModels": "아직 설치된 모델 없음",
|
|
186
|
+
"flow.analysis.readyDetail": "로컬 Digital Brain 사용 준비 완료",
|
|
187
|
+
"flow.analysis.memoryReadyDetail": "추천 모델에 충분한 컨텍스트",
|
|
188
|
+
"flow.analysis.graphicsReadyDetail": "Lattice가 가장 좋은 경로를 선택합니다.",
|
|
189
|
+
"flow.analysis.supportReadyDetail": "설치된 모델 도우미가 감지되었습니다.",
|
|
190
|
+
"flow.analysis.supportInstallDetail": "Lattice가 필요한 항목을 추가합니다.",
|
|
191
|
+
"flow.analysis.modelsReadyDetail": "즉시 로드할 수 있는 모델이 있습니다.",
|
|
192
|
+
"flow.analysis.modelsInstallDetail": "Lattice가 첫 설치를 안내합니다.",
|
|
193
|
+
"flow.recommend.reason.best": "최적 경험",
|
|
194
|
+
"flow.recommend.reason.faster": "빠른 선택",
|
|
195
|
+
"flow.recommend.reason.advanced": "고급 선택",
|
|
196
|
+
"flow.recommend.reason.default": "추천",
|
|
197
|
+
"flow.recommend.sizeReady": "준비됨",
|
|
198
|
+
"flow.recommend.fallbackName": "추천 Brain",
|
|
199
|
+
"flow.install.stage.download": "모델 파일을 받는 중입니다.",
|
|
200
|
+
"flow.install.stage.validate": "Brain이 응답할 수 있는지 확인 중입니다.",
|
|
201
|
+
"flow.install.stage.load": "Brain을 불러오는 중입니다.",
|
|
202
|
+
"flow.install.stage.error": "확인이 필요한 일이 있습니다.",
|
|
203
|
+
"flow.install.step.install": "준비",
|
|
204
|
+
"flow.install.step.download": "다운로드",
|
|
205
|
+
"flow.install.step.validate": "확인",
|
|
206
|
+
"flow.install.step.load": "로드",
|
|
82
207
|
"flow.shell": "내 로컬 AI 브레인 만들기",
|
|
83
208
|
"flow.login.title": "내 AI 브레인의 주인을 정합니다.",
|
|
84
209
|
"flow.login.body": "Lattice AI는 내 지식과 맥락을 이 컴퓨터에 보관하는 로컬 우선 AI 브레인입니다. 모델은 바꿀 수 있고, 외부 전송은 사용자가 선택할 때만 시작됩니다.",
|
|
85
210
|
"flow.name": "이름",
|
|
211
|
+
"flow.name.placeholder": "나",
|
|
86
212
|
"flow.email": "이메일",
|
|
213
|
+
"flow.email.placeholder": "you@local",
|
|
87
214
|
"flow.password": "비밀번호",
|
|
88
215
|
"flow.password.placeholder": "로컬 Brain 비밀번호",
|
|
89
216
|
"flow.login.busy": "Brain 여는 중...",
|
|
@@ -99,6 +226,7 @@ export const COPY: Record<Language, TextMap> = {
|
|
|
99
226
|
"flow.promise.model.v": "모델은 목소리이고, 자산은 Brain입니다.",
|
|
100
227
|
"flow.promise.ownership.k": "사용자 소유",
|
|
101
228
|
"flow.promise.ownership.v": "백업, 복원, 이동을 직접 결정합니다.",
|
|
229
|
+
"flow.promise.aria": "Lattice AI 제품 약속",
|
|
102
230
|
"flow.analysis.title": "이 컴퓨터에서 가능한 경험을 확인합니다.",
|
|
103
231
|
"flow.analysis.body": "스펙 점수가 아니라, 이 Mac에서 어떤 로컬 AI 브레인 경험이 편한지 알려드립니다. 확인은 로컬 상태를 읽는 것이고, 클라우드 모델은 선택 사항입니다.",
|
|
104
232
|
"flow.analysis.finding": "가장 편한 설정을 찾는 중...",
|
|
@@ -106,6 +234,10 @@ export const COPY: Record<Language, TextMap> = {
|
|
|
106
234
|
"flow.analysis.wait": "잠시만 기다리면 자동으로 정리됩니다.",
|
|
107
235
|
"flow.analysis.error": "Lattice가 이 컴퓨터를 끝까지 확인하지 못했습니다. 그래도 안전한 기본값으로 계속할 수 있습니다.",
|
|
108
236
|
"flow.analysis.continue": "추천 모델 보기",
|
|
237
|
+
"flow.analysis.bestFit": "{model}이 이 컴퓨터에 가장 잘 맞습니다.",
|
|
238
|
+
"flow.analysis.privateRecommended": "이 컴퓨터에는 개인 로컬 Brain을 추천합니다.",
|
|
239
|
+
"flow.analysis.os.windows": "Windows PC",
|
|
240
|
+
"flow.analysis.os.linux": "Linux 컴퓨터",
|
|
109
241
|
"flow.recommend.title": "추천대로 시작하세요.",
|
|
110
242
|
"flow.recommend.body": "모델은 Brain의 현재 목소리입니다. 가장 안전한 추천, 더 빠른 모델, 더 강한 모델만 먼저 보여드립니다.",
|
|
111
243
|
"flow.recommend.primary": "추천대로 시작하기",
|
|
@@ -113,6 +245,10 @@ export const COPY: Record<Language, TextMap> = {
|
|
|
113
245
|
"flow.recommend.back": "뒤로",
|
|
114
246
|
"flow.recommend.skip": "모델 없이 Brain 열기",
|
|
115
247
|
"flow.recommend.hint": "잘 모르겠다면 추천대로 시작하면 됩니다.",
|
|
248
|
+
"flow.recommend.rank.best": "추천",
|
|
249
|
+
"flow.recommend.rank.faster": "빠른 선택",
|
|
250
|
+
"flow.recommend.rank.advanced": "고급 선택",
|
|
251
|
+
"flow.recommend.rank.choice": "선택 {index}",
|
|
116
252
|
"flow.install.title": "모델을 설치하고 시작합니다.",
|
|
117
253
|
"flow.install.body": "이 모델이 Brain의 로컬 목소리가 됩니다. 인터넷은 다운로드할 때만 필요하고, 실행과 기억은 이 컴퓨터에서 유지됩니다.",
|
|
118
254
|
"flow.install.wait": "Brain이 사용할 모델을 기다리고 있습니다.",
|
|
@@ -124,7 +260,16 @@ export const COPY: Record<Language, TextMap> = {
|
|
|
124
260
|
"flow.install.start": "다운로드하고 시작하기",
|
|
125
261
|
"flow.install.busy": "모델 준비 중...",
|
|
126
262
|
"flow.install.enter": "Brain으로 들어가기",
|
|
263
|
+
"flow.install.later": "나중에 하기",
|
|
127
264
|
"flow.install.local": "모델 다운로드와 외부 통신은 사용자가 시작할 때만 진행됩니다.",
|
|
265
|
+
"flow.consent.title": "다운로드 전 확인",
|
|
266
|
+
"flow.consent.body": "시작하면 아래 모델 파일을 외부 저장소에서 받아 이 컴퓨터에 저장합니다.",
|
|
267
|
+
"flow.consent.ready": "이미 준비된 모델이거나, 선택하기 전에는 외부 접속을 시작하지 않습니다.",
|
|
268
|
+
"flow.consent.size": "다운로드 크기",
|
|
269
|
+
"flow.consent.sizeUnknown": "런타임 확인 후 표시",
|
|
270
|
+
"flow.consent.location": "저장 위치",
|
|
271
|
+
"flow.consent.external": "외부 접속 대상",
|
|
272
|
+
"flow.consent.externalNone": "선택 전 외부 접속 없음",
|
|
128
273
|
},
|
|
129
274
|
en: {
|
|
130
275
|
"language.label": "Language",
|
|
@@ -136,11 +281,24 @@ export const COPY: Record<Language, TextMap> = {
|
|
|
136
281
|
"brain.depth.3": "Topics",
|
|
137
282
|
"brain.depth.4": "Relationships",
|
|
138
283
|
"brain.depth.5": "Full knowledge graph",
|
|
284
|
+
"brain.depthLabel.1": "Living Brain",
|
|
285
|
+
"brain.depthLabel.2": "Memory Layer",
|
|
286
|
+
"brain.depthLabel.3": "Knowledge Layer",
|
|
287
|
+
"brain.depthLabel.4": "Relationship Layer",
|
|
288
|
+
"brain.depthLabel.5": "Knowledge Graph",
|
|
139
289
|
"brain.view.memories": "Memories",
|
|
140
290
|
"brain.view.topics": "Topics",
|
|
141
291
|
"brain.view.relationships": "Relationships",
|
|
142
292
|
"brain.view.graph": "Graph",
|
|
143
293
|
"brain.surface": "Back",
|
|
294
|
+
"brain.aria.home": "Lattice Brain",
|
|
295
|
+
"brain.aria.exploration": "Brain exploration",
|
|
296
|
+
"brain.aria.quickViews": "Brain quick views",
|
|
297
|
+
"brain.aria.conversation": "Conversation",
|
|
298
|
+
"brain.aria.ownership": "Brain ownership guarantees",
|
|
299
|
+
"brain.aria.starterPrompts": "Starter prompts",
|
|
300
|
+
"brain.aria.overview": "Brain overview",
|
|
301
|
+
"brain.aria.graph": "Knowledge Graph",
|
|
144
302
|
"brain.title": "Lattice Brain",
|
|
145
303
|
"brain.local": "Local-first",
|
|
146
304
|
"brain.portable": "Portable",
|
|
@@ -172,36 +330,150 @@ export const COPY: Record<Language, TextMap> = {
|
|
|
172
330
|
"brain.overview.olderEmpty": "Earlier memories appear as conversations accumulate.",
|
|
173
331
|
"brain.overview.topics": "Main topics",
|
|
174
332
|
"brain.overview.topicsEmpty": "Topics are still forming.",
|
|
333
|
+
"brain.memory.empty": "Memory is quiet",
|
|
334
|
+
"brain.knowledge.empty": "Knowledge is forming",
|
|
175
335
|
"brain.graph.empty": "No matching knowledge yet",
|
|
176
336
|
"brain.graph.summaryFallback": "This concept is part of the deepest knowledge layer.",
|
|
177
337
|
"brain.graph.focused": "Ideas that appeared together in conversations and documents are connected by lines.",
|
|
178
338
|
"brain.graph.emptyFocus": "Your Brain graph grows as you add conversations, documents, and projects.",
|
|
339
|
+
"brain.graph.search": "Search",
|
|
340
|
+
"brain.graph.searchAria": "Search knowledge graph",
|
|
179
341
|
"care.title": "Care for my Brain",
|
|
180
342
|
"care.subtitle": "Own it locally. Keep it portable.",
|
|
181
343
|
"care.private": "Private",
|
|
344
|
+
"care.ownershipModel": "Ownership model",
|
|
182
345
|
"care.export": "Export",
|
|
183
346
|
"care.export.detail": "Take it with you",
|
|
184
347
|
"care.backup": "Backup",
|
|
185
348
|
"care.backup.detail": "Save a copy",
|
|
349
|
+
"care.backup.count": "{count} backups",
|
|
350
|
+
"care.backup.ready": "Backups ready",
|
|
186
351
|
"care.archive": "Archive",
|
|
187
352
|
"care.archive.detail": "Encrypted Brain",
|
|
188
353
|
"care.path.placeholder": "Paste an archive path to inspect or preview",
|
|
189
354
|
"care.path.label": "Brain archive path",
|
|
190
355
|
"care.passphrase.placeholder": "Archive passphrase",
|
|
191
356
|
"care.passphrase.label": "Brain archive passphrase",
|
|
357
|
+
"care.passphrase.confirmPlaceholder": "Repeat passphrase",
|
|
358
|
+
"care.passphrase.confirmLabel": "Confirm Brain archive passphrase",
|
|
359
|
+
"care.passphrase.tooShort": "Use at least 12 characters.",
|
|
360
|
+
"care.passphrase.tooSimple": "Mix at least three of uppercase, lowercase, numbers, and symbols.",
|
|
361
|
+
"care.passphrase.mismatch": "Passphrases do not match.",
|
|
362
|
+
"care.passphrase.strong": "Passphrase strength is sufficient.",
|
|
363
|
+
"care.path.ready": "Archive path format looks valid.",
|
|
364
|
+
"care.path.invalidChars": "Archive path contains unsupported characters.",
|
|
365
|
+
"care.path.extension": "Use a .latticebrain, .zip, or .json archive.",
|
|
192
366
|
"care.inspect": "Inspect",
|
|
193
367
|
"care.restorePreview": "Restore preview",
|
|
194
368
|
"care.note": "Restore preview checks an archive without changing your Brain. Confirmed restore stays in Settings.",
|
|
195
369
|
"care.working": "Working",
|
|
370
|
+
"care.result.error": "Brain care action could not complete.",
|
|
371
|
+
"care.result.completed": "Brain care action completed.",
|
|
372
|
+
"care.result.path": "File: {path}",
|
|
373
|
+
"care.result.contents": "{memories} memories · {links} links · {conversations} conversations",
|
|
374
|
+
"care.result.dryRun": "Preview only; your current Brain was not changed.",
|
|
196
375
|
"admin.back": "Brain",
|
|
376
|
+
"admin.aria.console": "Lattice Admin",
|
|
197
377
|
"admin.kicker": "Separate admin workspace",
|
|
198
378
|
"admin.title": "Admin Console",
|
|
199
379
|
"admin.body": "Users, logs, security, and Brain health stay out of the normal user experience.",
|
|
380
|
+
"admin.overview": "Admin overview",
|
|
381
|
+
"admin.metric.users": "Users",
|
|
382
|
+
"admin.metric.logs": "Recent logs",
|
|
383
|
+
"admin.metric.security": "Security",
|
|
384
|
+
"admin.metric.index": "Brain index",
|
|
385
|
+
"admin.status.ready": "Ready",
|
|
386
|
+
"admin.status.unavailable": "Unavailable",
|
|
387
|
+
"admin.status.indexed": "Indexed",
|
|
388
|
+
"admin.status.unknown": "Unknown",
|
|
389
|
+
"admin.panel.users": "User Directory",
|
|
390
|
+
"admin.panel.people": "People",
|
|
391
|
+
"admin.panel.roles": "Role Permissions",
|
|
392
|
+
"admin.panel.access": "Access",
|
|
393
|
+
"admin.panel.logs": "Activity Logs",
|
|
394
|
+
"admin.panel.audit": "Audit",
|
|
395
|
+
"admin.panel.securityEvents": "Security Events",
|
|
396
|
+
"admin.panel.protection": "Protection",
|
|
397
|
+
"admin.panel.brainOps": "Brain Operations",
|
|
398
|
+
"admin.panel.maintenance": "Maintenance",
|
|
399
|
+
"admin.empty.users": "No users reported by the admin API.",
|
|
400
|
+
"admin.empty.roles": "No role matrix reported.",
|
|
401
|
+
"admin.empty.audit": "No recent audit events.",
|
|
402
|
+
"admin.empty.security": "No security events reported.",
|
|
403
|
+
"admin.fallback.localUser": "Local user",
|
|
404
|
+
"admin.fallback.member": "member",
|
|
405
|
+
"admin.fallback.role": "role",
|
|
406
|
+
"admin.fallback.noCaps": "No caps",
|
|
407
|
+
"admin.filters.label": "Audit log filters",
|
|
408
|
+
"admin.filters.search": "Search logs",
|
|
409
|
+
"admin.filters.searchAria": "Search audit logs",
|
|
410
|
+
"admin.filters.severityAria": "Filter by severity",
|
|
411
|
+
"admin.filters.all": "All severities",
|
|
412
|
+
"admin.filters.informational": "Informational",
|
|
413
|
+
"admin.filters.notice": "Notice",
|
|
414
|
+
"admin.filters.warning": "Warning",
|
|
415
|
+
"admin.filters.high": "High",
|
|
416
|
+
"admin.filters.matched": "{count} matched",
|
|
417
|
+
"admin.brain.summaryFallback": "Local Brain services are separated from user chat.",
|
|
418
|
+
"admin.brain.rebuilding": "Rebuilding",
|
|
419
|
+
"admin.brain.rebuild": "Rebuild index",
|
|
420
|
+
"admin.policy.fallback": "Policy",
|
|
421
|
+
"admin.policy.quiet": "Policy API quiet",
|
|
422
|
+
"admin.retention.days": "{days} day retention",
|
|
423
|
+
"admin.retention.detail": "{events} retained · {candidates} ready for export/prune review",
|
|
424
|
+
"admin.log.event": "Event",
|
|
425
|
+
"admin.log.system": "system",
|
|
426
|
+
"admin.log.recently": "recently",
|
|
427
|
+
"admin.source.loading": "Loading",
|
|
428
|
+
"admin.source.live": "Live",
|
|
429
|
+
"admin.index.ready": "Index status ready",
|
|
430
|
+
"flow.analysis.fact.computer": "Computer",
|
|
431
|
+
"flow.analysis.fact.memory": "Memory",
|
|
432
|
+
"flow.analysis.fact.graphics": "Graphics",
|
|
433
|
+
"flow.analysis.fact.support": "Local Support",
|
|
434
|
+
"flow.analysis.fact.models": "Models",
|
|
435
|
+
"flow.analysis.checking": "Checking",
|
|
436
|
+
"flow.analysis.fact.computerDetail": "Operating system and chip",
|
|
437
|
+
"flow.analysis.fact.memoryDetail": "Available room for local thinking",
|
|
438
|
+
"flow.analysis.fact.graphicsDetail": "Local acceleration support",
|
|
439
|
+
"flow.analysis.fact.supportDetail": "Installed model helpers",
|
|
440
|
+
"flow.analysis.fact.modelsDetail": "Installed local Brains",
|
|
441
|
+
"flow.analysis.apple": "Apple Silicon Mac",
|
|
442
|
+
"flow.analysis.detected": "Detected",
|
|
443
|
+
"flow.analysis.localReady": "Local acceleration ready",
|
|
444
|
+
"flow.analysis.standardLocal": "Standard local mode",
|
|
445
|
+
"flow.analysis.supportReady": "Ready",
|
|
446
|
+
"flow.analysis.supportInstall": "Will be prepared",
|
|
447
|
+
"flow.analysis.modelsInstalled": "{count} already installed",
|
|
448
|
+
"flow.analysis.noModels": "None installed yet",
|
|
449
|
+
"flow.analysis.readyDetail": "Ready for local Digital Brain use",
|
|
450
|
+
"flow.analysis.memoryReadyDetail": "Enough context for the recommended model",
|
|
451
|
+
"flow.analysis.graphicsReadyDetail": "Lattice will choose the best available path",
|
|
452
|
+
"flow.analysis.supportReadyDetail": "Installed model helpers detected",
|
|
453
|
+
"flow.analysis.supportInstallDetail": "Lattice will add what is needed",
|
|
454
|
+
"flow.analysis.modelsReadyDetail": "One can be loaded immediately",
|
|
455
|
+
"flow.analysis.modelsInstallDetail": "Lattice will guide the first install",
|
|
456
|
+
"flow.recommend.reason.best": "Best Experience",
|
|
457
|
+
"flow.recommend.reason.faster": "Faster",
|
|
458
|
+
"flow.recommend.reason.advanced": "Advanced",
|
|
459
|
+
"flow.recommend.reason.default": "Recommended",
|
|
460
|
+
"flow.recommend.sizeReady": "ready",
|
|
461
|
+
"flow.recommend.fallbackName": "Recommended Brain",
|
|
462
|
+
"flow.install.stage.download": "Getting the model files.",
|
|
463
|
+
"flow.install.stage.validate": "Checking that the Brain can answer.",
|
|
464
|
+
"flow.install.stage.load": "Loading the Brain.",
|
|
465
|
+
"flow.install.stage.error": "Something needs attention.",
|
|
466
|
+
"flow.install.step.install": "Install",
|
|
467
|
+
"flow.install.step.download": "Download",
|
|
468
|
+
"flow.install.step.validate": "Validate",
|
|
469
|
+
"flow.install.step.load": "Load",
|
|
200
470
|
"flow.shell": "Create your local AI Brain",
|
|
201
471
|
"flow.login.title": "Choose the owner of your AI Brain.",
|
|
202
472
|
"flow.login.body": "Lattice AI is a local-first Digital Brain that keeps your knowledge on this computer. Models can change; external transfer starts only when you choose it.",
|
|
203
473
|
"flow.name": "Name",
|
|
474
|
+
"flow.name.placeholder": "You",
|
|
204
475
|
"flow.email": "Email",
|
|
476
|
+
"flow.email.placeholder": "you@local",
|
|
205
477
|
"flow.password": "Password",
|
|
206
478
|
"flow.password.placeholder": "Local Brain password",
|
|
207
479
|
"flow.login.busy": "Opening Brain...",
|
|
@@ -217,6 +489,7 @@ export const COPY: Record<Language, TextMap> = {
|
|
|
217
489
|
"flow.promise.model.v": "The model is the voice; the Brain is the asset.",
|
|
218
490
|
"flow.promise.ownership.k": "User owned",
|
|
219
491
|
"flow.promise.ownership.v": "You decide when to back up, restore, or move it.",
|
|
492
|
+
"flow.promise.aria": "Lattice AI product promise",
|
|
220
493
|
"flow.analysis.title": "Checking what this computer can do.",
|
|
221
494
|
"flow.analysis.body": "This is not a spec test. Lattice reads local capability and explains what AI Brain experience this Mac can support. Cloud models remain optional.",
|
|
222
495
|
"flow.analysis.finding": "Finding the easiest setup...",
|
|
@@ -224,6 +497,10 @@ export const COPY: Record<Language, TextMap> = {
|
|
|
224
497
|
"flow.analysis.wait": "This will be summarized automatically in a moment.",
|
|
225
498
|
"flow.analysis.error": "Lattice could not finish checking this computer. You can still continue with a safe default.",
|
|
226
499
|
"flow.analysis.continue": "View recommended models",
|
|
500
|
+
"flow.analysis.bestFit": "{model} looks like the best fit.",
|
|
501
|
+
"flow.analysis.privateRecommended": "A private local Brain is recommended for this computer.",
|
|
502
|
+
"flow.analysis.os.windows": "Windows PC",
|
|
503
|
+
"flow.analysis.os.linux": "Linux computer",
|
|
227
504
|
"flow.recommend.title": "Start with the recommendation.",
|
|
228
505
|
"flow.recommend.body": "The model is your Brain's current voice. You see the safest recommendation, a faster model, and a stronger model first.",
|
|
229
506
|
"flow.recommend.primary": "Start with recommendation",
|
|
@@ -231,6 +508,10 @@ export const COPY: Record<Language, TextMap> = {
|
|
|
231
508
|
"flow.recommend.back": "Back",
|
|
232
509
|
"flow.recommend.skip": "Open Brain without a model",
|
|
233
510
|
"flow.recommend.hint": "If unsure, start with the recommendation.",
|
|
511
|
+
"flow.recommend.rank.best": "Best Experience",
|
|
512
|
+
"flow.recommend.rank.faster": "Faster",
|
|
513
|
+
"flow.recommend.rank.advanced": "Advanced",
|
|
514
|
+
"flow.recommend.rank.choice": "Choice {index}",
|
|
234
515
|
"flow.install.title": "Install the model and start.",
|
|
235
516
|
"flow.install.body": "This model becomes your Brain's local voice. Internet is needed only for download; execution and memory stay on this computer.",
|
|
236
517
|
"flow.install.wait": "Waiting for the model your Brain will use.",
|
|
@@ -242,7 +523,16 @@ export const COPY: Record<Language, TextMap> = {
|
|
|
242
523
|
"flow.install.start": "Download and start",
|
|
243
524
|
"flow.install.busy": "Preparing model...",
|
|
244
525
|
"flow.install.enter": "Enter Brain",
|
|
526
|
+
"flow.install.later": "Do later",
|
|
245
527
|
"flow.install.local": "Downloads and external communication start only when you choose them.",
|
|
528
|
+
"flow.consent.title": "Before downloading",
|
|
529
|
+
"flow.consent.body": "Starting will fetch these model files from an external repository and store them on this computer.",
|
|
530
|
+
"flow.consent.ready": "This model is already ready, or no external connection starts until you choose it.",
|
|
531
|
+
"flow.consent.size": "Download size",
|
|
532
|
+
"flow.consent.sizeUnknown": "Reported by runtime",
|
|
533
|
+
"flow.consent.location": "Storage location",
|
|
534
|
+
"flow.consent.external": "External target",
|
|
535
|
+
"flow.consent.externalNone": "No external connection before selection",
|
|
246
536
|
},
|
|
247
537
|
};
|
|
248
538
|
|
|
@@ -457,7 +457,7 @@ export function BrainPage({ initialTab }: { initialTab?: string }) {
|
|
|
457
457
|
{(data) => <MemoryStatus data={data as Record<string, unknown>} />}
|
|
458
458
|
</DataPanel>
|
|
459
459
|
<DataPanel title="Recent sources" result={provenance.data}>
|
|
460
|
-
{(data) => <
|
|
460
|
+
{(data) => <SourceProvenanceList items={(data as Record<string, unknown>).items || data} />}
|
|
461
461
|
</DataPanel>
|
|
462
462
|
</div>
|
|
463
463
|
) : null}
|
|
@@ -527,6 +527,7 @@ function RetrievalStatus({ data }: { data: Record<string, unknown> }) {
|
|
|
527
527
|
|
|
528
528
|
function MemoryStatus({ data }: { data: Record<string, unknown> }) {
|
|
529
529
|
const usage = isRecord(data.usage) ? data.usage : {};
|
|
530
|
+
const sources = asArray<Record<string, unknown>>(data.sources || data.tiers);
|
|
530
531
|
return (
|
|
531
532
|
<div className="space-y-3">
|
|
532
533
|
<StatGrid stats={[
|
|
@@ -535,7 +536,7 @@ function MemoryStatus({ data }: { data: Record<string, unknown> }) {
|
|
|
535
536
|
{ label: "Bytes", value: usage.total_bytes ?? 0 },
|
|
536
537
|
{ label: "Health", value: data.health || "reported" },
|
|
537
538
|
]} />
|
|
538
|
-
<
|
|
539
|
+
<SourceProvenanceList items={sources} limit={6} />
|
|
539
540
|
</div>
|
|
540
541
|
);
|
|
541
542
|
}
|
|
@@ -667,15 +668,20 @@ function DigitalBrainExplorer({ data }: { data: unknown }) {
|
|
|
667
668
|
{mode === "basic" ? (
|
|
668
669
|
<KeyValueList data={{
|
|
669
670
|
connections: selected.degree,
|
|
670
|
-
source: selected.source || "not
|
|
671
|
+
source: selected.source || "Source not recorded",
|
|
672
|
+
source_type: sourceType(selected.raw),
|
|
673
|
+
created_at: sourceCreatedAt(selected.raw) || "Created time not recorded",
|
|
671
674
|
}} />
|
|
672
675
|
) : (
|
|
673
676
|
<StructuredView value={{
|
|
674
677
|
id: selected.id,
|
|
675
678
|
degree: selected.degree,
|
|
676
|
-
source: selected.source || "not
|
|
679
|
+
source: selected.source || "Source not recorded",
|
|
680
|
+
source_type: sourceType(selected.raw),
|
|
681
|
+
created_at: sourceCreatedAt(selected.raw) || "Created time not recorded",
|
|
677
682
|
}} />
|
|
678
683
|
)}
|
|
684
|
+
{selected.source ? <Button variant="outline" size="sm" onClick={() => void navigator.clipboard?.writeText(selected.source)}>Copy source</Button> : null}
|
|
679
685
|
</>
|
|
680
686
|
) : selectedGroup ? (
|
|
681
687
|
<div className="space-y-2">
|
|
@@ -779,12 +785,64 @@ function ProvenancePanel() {
|
|
|
779
785
|
{(data) => <StructuredView value={data} />}
|
|
780
786
|
</DataPanel>
|
|
781
787
|
<DataPanel title="Recent sources" result={provenance.data}>
|
|
782
|
-
{(data) => <
|
|
788
|
+
{(data) => <SourceProvenanceList items={(data as Record<string, unknown>).items || data} limit={14} />}
|
|
783
789
|
</DataPanel>
|
|
784
790
|
</div>
|
|
785
791
|
);
|
|
786
792
|
}
|
|
787
793
|
|
|
794
|
+
function SourceProvenanceList({ items, limit = 8 }: { items: unknown; limit?: number }) {
|
|
795
|
+
const rows = asArray<Record<string, unknown>>(items).slice(0, limit);
|
|
796
|
+
if (!rows.length) return <EmptyState title="No sources yet" detail="New memories will show their chat, manual, document, or import origin here." />;
|
|
797
|
+
return (
|
|
798
|
+
<div className="grid gap-2">
|
|
799
|
+
{rows.map((item, index) => {
|
|
800
|
+
const title = String(item.title || item.label || item.source_title || item.filename || item.path || item.source || `Source ${index + 1}`);
|
|
801
|
+
const path = String(item.path || item.source_path || item.source || item.conversation_id || "");
|
|
802
|
+
const type = sourceType(item);
|
|
803
|
+
const created = sourceCreatedAt(item);
|
|
804
|
+
return (
|
|
805
|
+
<div key={String(item.id || item.source_id || title)} className="rounded-lg border border-border bg-background/55 p-3">
|
|
806
|
+
<div className="flex flex-wrap items-start justify-between gap-2">
|
|
807
|
+
<div>
|
|
808
|
+
<div className="font-medium">{title}</div>
|
|
809
|
+
<div className="mt-1 text-xs text-muted-foreground">
|
|
810
|
+
{type} · {created || "Created time not recorded"}
|
|
811
|
+
</div>
|
|
812
|
+
</div>
|
|
813
|
+
<Badge variant="muted">{path ? "inspectable" : "missing provenance"}</Badge>
|
|
814
|
+
</div>
|
|
815
|
+
{path ? (
|
|
816
|
+
<div className="mt-2 flex flex-wrap items-center gap-2 text-xs text-muted-foreground">
|
|
817
|
+
<span className="break-all">{path}</span>
|
|
818
|
+
<Button variant="outline" size="sm" onClick={() => void navigator.clipboard?.writeText(path)}>Copy source</Button>
|
|
819
|
+
</div>
|
|
820
|
+
) : (
|
|
821
|
+
<p className="mt-2 text-xs text-muted-foreground">This older memory did not record a source path or conversation. It remains searchable, but provenance is incomplete.</p>
|
|
822
|
+
)}
|
|
823
|
+
</div>
|
|
824
|
+
);
|
|
825
|
+
})}
|
|
826
|
+
</div>
|
|
827
|
+
);
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
function sourceType(item: Record<string, unknown>) {
|
|
831
|
+
const metadata = isRecord(item.metadata) ? item.metadata : {};
|
|
832
|
+
const raw = String(item.source_type || item.type || item.kind || metadata.source_type || metadata.role || "").toLowerCase();
|
|
833
|
+
if (/chat|conversation|message/.test(raw)) return "chat";
|
|
834
|
+
if (/document|upload|file|pdf|markdown|text/.test(raw)) return "document";
|
|
835
|
+
if (/import|archive|restore/.test(raw)) return "import";
|
|
836
|
+
if (/manual|note/.test(raw)) return "manual";
|
|
837
|
+
return "source unknown";
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
function sourceCreatedAt(item: Record<string, unknown>) {
|
|
841
|
+
const metadata = isRecord(item.metadata) ? item.metadata : {};
|
|
842
|
+
const value = item.created_at || item.timestamp || item.updated_at || metadata.created_at || metadata.timestamp;
|
|
843
|
+
return value ? String(value) : "";
|
|
844
|
+
}
|
|
845
|
+
|
|
788
846
|
function PortabilityPanel() {
|
|
789
847
|
const qc = useQueryClient();
|
|
790
848
|
const [artifact, setArtifact] = React.useState("");
|