ltcai 7.0.0 → 7.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -20
- package/docs/CHANGELOG.md +43 -0
- package/frontend/src/App.tsx +80 -0
- package/frontend/src/api/client.ts +9 -0
- package/frontend/src/components/AdminAccessGate.tsx +70 -0
- package/frontend/src/components/BrainConversation.tsx +232 -8
- package/frontend/src/components/FeedbackState.tsx +45 -0
- package/frontend/src/components/WorkspaceProfileSwitcher.tsx +176 -0
- package/frontend/src/components/onboarding/AnalysisScreen.tsx +20 -12
- package/frontend/src/components/onboarding/InstallScreen.tsx +55 -0
- package/frontend/src/components/onboarding/RecommendationScreen.tsx +55 -5
- package/frontend/src/components/onboarding/recommendationModel.ts +59 -2
- package/frontend/src/features/admin/AdminConsole.tsx +41 -1
- package/frontend/src/features/brain/BrainConversation.tsx +232 -19
- package/frontend/src/features/brain/BrainGraphLayer.tsx +258 -25
- package/frontend/src/features/brain/BrainHome.tsx +193 -1
- package/frontend/src/features/brain/brainData.ts +25 -1
- package/frontend/src/features/brain/graphLayout.ts +12 -1
- package/frontend/src/features/brain/types.ts +41 -0
- package/frontend/src/i18n.ts +328 -0
- package/frontend/src/store/appStore.ts +15 -0
- package/frontend/src/styles.css +1175 -0
- package/lattice_brain/__init__.py +1 -1
- package/lattice_brain/runtime/agent_runtime.py +51 -0
- package/lattice_brain/runtime/multi_agent.py +1 -1
- package/latticeai/__init__.py +1 -1
- package/latticeai/api/agents.py +12 -0
- package/latticeai/api/tools.py +14 -0
- package/latticeai/api/workspace.py +59 -0
- package/latticeai/core/marketplace.py +1 -1
- package/latticeai/core/tool_registry.py +47 -0
- package/latticeai/core/workspace_os.py +1 -1
- package/latticeai/services/tool_dispatch.py +14 -0
- package/package.json +1 -1
- 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 +28 -28
- package/static/app/assets/Act-Di4tRFWY.js +2 -0
- package/static/app/assets/{Act-DhLaHnrT.js.map → Act-Di4tRFWY.js.map} +1 -1
- package/static/app/assets/Brain-BZB3Gy9w.js +322 -0
- package/static/app/assets/Brain-BZB3Gy9w.js.map +1 -0
- package/static/app/assets/{Capture-CAKouj52.js → Capture-tNyYWxnh.js} +2 -2
- package/static/app/assets/{Capture-CAKouj52.js.map → Capture-tNyYWxnh.js.map} +1 -1
- package/static/app/assets/Library-DAtDDLdg.js +2 -0
- package/static/app/assets/{Library-B_hW4AwR.js.map → Library-DAtDDLdg.js.map} +1 -1
- package/static/app/assets/System-DEu0xNUc.js +2 -0
- package/static/app/assets/System-DEu0xNUc.js.map +1 -0
- package/static/app/assets/{index-DKFpn5Kn.css → index-Bi_bpigM.css} +1 -1
- package/static/app/assets/index-COuGp7_5.js +17 -0
- package/static/app/assets/index-COuGp7_5.js.map +1 -0
- package/static/app/assets/primitives-CdwcE--L.js +2 -0
- package/static/app/assets/primitives-CdwcE--L.js.map +1 -0
- package/static/app/assets/textarea-CqOdBPL1.js +2 -0
- package/static/app/assets/{textarea-DR2Tyy_6.js.map → textarea-CqOdBPL1.js.map} +1 -1
- package/static/app/index.html +2 -2
- package/static/app/assets/Act-DhLaHnrT.js +0 -2
- package/static/app/assets/Brain-DS7NULyY.js +0 -322
- package/static/app/assets/Brain-DS7NULyY.js.map +0 -1
- package/static/app/assets/Library-B_hW4AwR.js +0 -2
- package/static/app/assets/System-9OAoXWPz.js +0 -2
- package/static/app/assets/System-9OAoXWPz.js.map +0 -1
- package/static/app/assets/index-C-7aHabu.js +0 -17
- package/static/app/assets/index-C-7aHabu.js.map +0 -1
- package/static/app/assets/primitives-DcO2H3yh.js +0 -2
- package/static/app/assets/primitives-DcO2H3yh.js.map +0 -1
- package/static/app/assets/textarea-DR2Tyy_6.js +0 -2
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import type { KnowledgeConcept } from "./types";
|
|
2
|
+
import type { KnowledgeConcept, RelationshipThread } from "./types";
|
|
3
|
+
|
|
4
|
+
// Return the set of node ids that share a direct (1-hop) edge with `nodeId`.
|
|
5
|
+
// The focused node itself is not included.
|
|
6
|
+
export function computeGraphNeighbors(nodeId: string, edges: RelationshipThread[]): Set<string> {
|
|
7
|
+
const neighbors = new Set<string>();
|
|
8
|
+
for (const edge of edges) {
|
|
9
|
+
if (edge.source === nodeId) neighbors.add(edge.target);
|
|
10
|
+
else if (edge.target === nodeId) neighbors.add(edge.source);
|
|
11
|
+
}
|
|
12
|
+
return neighbors;
|
|
13
|
+
}
|
|
3
14
|
|
|
4
15
|
export function layoutGraphNodes(nodes: KnowledgeConcept[], radiusX: number, radiusY: number) {
|
|
5
16
|
return nodes.map((node, index) => {
|
|
@@ -33,6 +33,9 @@ export type KnowledgeConcept = {
|
|
|
33
33
|
type: string;
|
|
34
34
|
summary: string;
|
|
35
35
|
importance: number;
|
|
36
|
+
// Optional unix epoch (ms) the concept was added to the graph. Enables
|
|
37
|
+
// time-based exploration; absent when the backend does not yet emit it.
|
|
38
|
+
createdAt?: number;
|
|
36
39
|
};
|
|
37
40
|
|
|
38
41
|
export type RelationshipThread = {
|
|
@@ -100,6 +103,44 @@ export type BrainProof = {
|
|
|
100
103
|
};
|
|
101
104
|
};
|
|
102
105
|
|
|
106
|
+
export type IngestionSourceType = "file" | "folder" | "note" | "web";
|
|
107
|
+
|
|
108
|
+
export type IngestionPipelineStage =
|
|
109
|
+
| "preparing"
|
|
110
|
+
| "parsing"
|
|
111
|
+
| "embedding"
|
|
112
|
+
| "indexing"
|
|
113
|
+
| "complete"
|
|
114
|
+
| "error";
|
|
115
|
+
|
|
116
|
+
export type IngestionState = {
|
|
117
|
+
sourceType: IngestionSourceType;
|
|
118
|
+
label: string;
|
|
119
|
+
stage: IngestionPipelineStage;
|
|
120
|
+
startedAt: number;
|
|
121
|
+
completedAt: number | null;
|
|
122
|
+
newMemories: number;
|
|
123
|
+
newEntities: number;
|
|
124
|
+
error?: string;
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
export type EmergenceEvent = {
|
|
128
|
+
id: string;
|
|
129
|
+
sourceType: IngestionSourceType;
|
|
130
|
+
label: string;
|
|
131
|
+
newMemories: number;
|
|
132
|
+
newEntities: number;
|
|
133
|
+
at: number;
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
export const INGESTION_STAGE_ORDER: IngestionPipelineStage[] = [
|
|
137
|
+
"preparing",
|
|
138
|
+
"parsing",
|
|
139
|
+
"embedding",
|
|
140
|
+
"indexing",
|
|
141
|
+
"complete",
|
|
142
|
+
];
|
|
143
|
+
|
|
103
144
|
export const DEPTHS: Array<{ level: BrainDepth; labelKey: string; state: BrainState }> = [
|
|
104
145
|
{ level: 1, labelKey: "brain.depthLabel.1", state: "idle" },
|
|
105
146
|
{ level: 2, labelKey: "brain.depthLabel.2", state: "recalling" },
|
package/frontend/src/i18n.ts
CHANGED
|
@@ -43,6 +43,28 @@ export const COPY: Record<Language, TextMap> = {
|
|
|
43
43
|
"brain.portable": "이동 가능",
|
|
44
44
|
"brain.private": "개인 소유",
|
|
45
45
|
"brain.admin": "관리자 콘솔",
|
|
46
|
+
"shell.workspace.label": "작업공간 및 프로필",
|
|
47
|
+
"shell.workspace.current": "현재 작업공간",
|
|
48
|
+
"shell.workspace.switch": "전환",
|
|
49
|
+
"shell.workspace.active": "사용 중",
|
|
50
|
+
"shell.workspace.empty": "아직 작업공간이 없습니다",
|
|
51
|
+
"shell.workspace.personal": "개인 Brain",
|
|
52
|
+
"shell.workspace.manageSpaces": "작업공간 관리",
|
|
53
|
+
"shell.workspace.close": "닫기",
|
|
54
|
+
"shell.profile.label": "프로필",
|
|
55
|
+
"shell.profile.owner": "소유자",
|
|
56
|
+
"shell.profile.signedOut": "로그인하지 않음",
|
|
57
|
+
"shell.profile.manage": "계정 설정 열기",
|
|
58
|
+
"shell.admin.label": "관리자",
|
|
59
|
+
"shell.admin.open": "관리자 콘솔 열기",
|
|
60
|
+
"shell.admin.tooltip": "설정, 에이전트, 도구 레지스트리 관리",
|
|
61
|
+
"shell.admin.needsMode": "관리자 콘솔은 고급 또는 관리자 모드에서만 사용할 수 있습니다",
|
|
62
|
+
"shell.admin.enable": "관리자 모드로 전환",
|
|
63
|
+
"shell.mode.label": "모드",
|
|
64
|
+
"shell.mode.basic": "기본",
|
|
65
|
+
"shell.mode.advanced": "고급",
|
|
66
|
+
"shell.mode.admin": "관리자",
|
|
67
|
+
"shell.mode.info": "모드는 표시되는 도구와 관리자 화면의 범위를 정합니다",
|
|
46
68
|
"brain.action.add": "넣기",
|
|
47
69
|
"brain.action.find": "찾기",
|
|
48
70
|
"brain.action.model": "모델",
|
|
@@ -85,6 +107,38 @@ export const COPY: Record<Language, TextMap> = {
|
|
|
85
107
|
"brain.ingest.web.pending": "{url}을 읽어 Brain에 넣는 중입니다.",
|
|
86
108
|
"brain.ingest.web.saved": "{url}이 Brain에 저장됐습니다.",
|
|
87
109
|
"brain.ingest.web.failed": "웹 페이지를 넣지 못했습니다: {reason}",
|
|
110
|
+
"brain.ingest.type.file": "파일",
|
|
111
|
+
"brain.ingest.type.folder": "폴더",
|
|
112
|
+
"brain.ingest.type.note": "노트",
|
|
113
|
+
"brain.ingest.type.web": "웹",
|
|
114
|
+
"brain.ingest.cta.file": "선택해서 바로 넣기",
|
|
115
|
+
"brain.ingest.cta.folder": "경로를 넣고 Enter",
|
|
116
|
+
"brain.ingest.cta.note": "내용을 붙여넣고 Enter",
|
|
117
|
+
"brain.ingest.cta.web": "URL을 넣고 Enter",
|
|
118
|
+
"brain.ingest.active": "{label} 처리 중",
|
|
119
|
+
"brain.ingest.progress.aria": "{label} 수집 진행 상태",
|
|
120
|
+
"brain.ingest.stage.preparing": "준비",
|
|
121
|
+
"brain.ingest.stage.parsing": "파싱",
|
|
122
|
+
"brain.ingest.stage.embedding": "임베딩",
|
|
123
|
+
"brain.ingest.stage.indexing": "인덱싱",
|
|
124
|
+
"brain.ingest.stage.complete": "메모리화 완료",
|
|
125
|
+
"brain.ingest.stage.error": "실패",
|
|
126
|
+
"brain.ingest.stage.preparing.hint": "원본을 읽어들이는 중",
|
|
127
|
+
"brain.ingest.stage.parsing.hint": "텍스트와 구조를 추출하는 중",
|
|
128
|
+
"brain.ingest.stage.embedding.hint": "의미 벡터로 변환하는 중",
|
|
129
|
+
"brain.ingest.stage.indexing.hint": "지식 그래프에 연결하는 중",
|
|
130
|
+
"brain.ingest.stage.complete.hint": "내 지식으로 들어왔습니다",
|
|
131
|
+
"brain.ingest.result": "새 기억 {memories}개 · 새 엔티티 {entities}개",
|
|
132
|
+
"brain.ingest.result.empty": "기존 지식과 통합됨",
|
|
133
|
+
"brain.timeline.aria": "최근 메모리 생성 타임라인",
|
|
134
|
+
"brain.timeline.emergenceTitle": "방금 생긴 지식",
|
|
135
|
+
"brain.timeline.recent": "최근 수집",
|
|
136
|
+
"brain.timeline.newMemories": "새 기억 {count}개",
|
|
137
|
+
"brain.timeline.newEntities": "새 엔티티 {count}개",
|
|
138
|
+
"brain.timeline.at": "{time}",
|
|
139
|
+
"brain.timeline.justNow": "방금",
|
|
140
|
+
"brain.timeline.minutesAgo": "{count}분 전",
|
|
141
|
+
"brain.timeline.empty": "아직 수집 기록이 없습니다. 위에서 무엇이든 넣어보세요.",
|
|
88
142
|
"brain.image": "이미지",
|
|
89
143
|
"brain.unavailable": "지금은 답할 수 없음",
|
|
90
144
|
"brain.imageAttached": "이미지 첨부됨",
|
|
@@ -139,6 +193,18 @@ export const COPY: Record<Language, TextMap> = {
|
|
|
139
193
|
"brain.answerProof.modelProven": "{model} 밖에 남은 Brain 증거",
|
|
140
194
|
"brain.answerProof.modelPending": "{model} 응답 · 증거 저장 대기",
|
|
141
195
|
"brain.answerProof.empty": "아직 연결된 출처가 없습니다. 기억이 인덱싱되면 여기에 표시됩니다.",
|
|
196
|
+
"brain.citation.chip": "출처 {num}",
|
|
197
|
+
"brain.citation.chip.long": "출처 {num}: {title}",
|
|
198
|
+
"brain.citation.expand": "출처 열기",
|
|
199
|
+
"brain.citation.close": "출처 닫기",
|
|
200
|
+
"brain.citation.preview.from": "출처: ",
|
|
201
|
+
"brain.citation.preview.snippet": "발췌: ",
|
|
202
|
+
"brain.citation.keyboard.tip": "스페이스/엔터로 출처를 열고, ESC로 닫습니다.",
|
|
203
|
+
"brain.citation.region": "본문에서 참조한 출처 인용",
|
|
204
|
+
"brain.citation.announce.open": "{num}번 출처를 열었습니다: {title}",
|
|
205
|
+
"brain.citation.announce.close": "출처 미리보기를 닫았습니다.",
|
|
206
|
+
"brain.citation.count": "이 답변은 {count}개의 출처를 인용합니다.",
|
|
207
|
+
"brain.citation.score": "관련도 {score}%",
|
|
142
208
|
"brain.memory.empty.kicker": "첫 기억",
|
|
143
209
|
"brain.memory.empty": "기억이 조용합니다.",
|
|
144
210
|
"brain.knowledge.empty": "지식이 형성되는 중입니다.",
|
|
@@ -148,6 +214,24 @@ export const COPY: Record<Language, TextMap> = {
|
|
|
148
214
|
"brain.graph.emptyFocus": "대화, 문서, 프로젝트를 쌓으면 Brain 그래프가 자랍니다.",
|
|
149
215
|
"brain.graph.search": "검색",
|
|
150
216
|
"brain.graph.searchAria": "지식 그래프 검색",
|
|
217
|
+
"brain.graph.control.panel": "그래프 탐색 컨트롤",
|
|
218
|
+
"brain.graph.control.filter": "필터",
|
|
219
|
+
"brain.graph.control.types": "엔티티 타입",
|
|
220
|
+
"brain.graph.control.allTypes": "전체 타입",
|
|
221
|
+
"brain.graph.control.time": "시간 탐색",
|
|
222
|
+
"brain.graph.control.dateRange": "최근 추가 강조 범위",
|
|
223
|
+
"brain.graph.control.resetFilters": "필터 초기화",
|
|
224
|
+
"brain.graph.control.recentWindow": "최근 {days}일",
|
|
225
|
+
"brain.graph.control.allTime": "전체 기간",
|
|
226
|
+
"brain.graph.control.toggleType": "{type} 타입 표시 전환",
|
|
227
|
+
"brain.graph.search.typeahead": "검색 추천",
|
|
228
|
+
"brain.graph.search.typeaheadAria": "검색 추천 결과",
|
|
229
|
+
"brain.graph.search.noMatches": "일치하는 노드가 없습니다.",
|
|
230
|
+
"brain.graph.search.matchCount": "{count}개 일치",
|
|
231
|
+
"brain.graph.focus.neighbors": "이웃 {count}개 강조",
|
|
232
|
+
"brain.graph.focus.smooth": "선택한 노드로 부드럽게 포커스 이동하고 이웃을 강조합니다.",
|
|
233
|
+
"brain.graph.focus.recent": "최근 추가됨",
|
|
234
|
+
"brain.graph.focus.clear": "포커스 해제",
|
|
151
235
|
"care.title": "내 Brain 돌보기",
|
|
152
236
|
"care.subtitle": "내 컴퓨터에 두고, 필요하면 옮길 수 있습니다.",
|
|
153
237
|
"care.private": "개인 보관",
|
|
@@ -264,6 +348,8 @@ export const COPY: Record<Language, TextMap> = {
|
|
|
264
348
|
"admin.panel.protection": "보호",
|
|
265
349
|
"admin.panel.brainOps": "Brain 운영",
|
|
266
350
|
"admin.panel.maintenance": "유지보수",
|
|
351
|
+
"admin.panel.runtimeTrust": "런타임 신뢰도",
|
|
352
|
+
"admin.panel.contracts": "계약",
|
|
267
353
|
"admin.empty.users": "관리 API가 보고한 사용자가 없습니다.",
|
|
268
354
|
"admin.empty.roles": "보고된 역할 매트릭스가 없습니다.",
|
|
269
355
|
"admin.empty.audit": "최근 감사 이벤트가 없습니다.",
|
|
@@ -285,6 +371,16 @@ export const COPY: Record<Language, TextMap> = {
|
|
|
285
371
|
"admin.brain.summaryFallback": "로컬 Brain 서비스는 사용자 대화와 분리되어 있습니다.",
|
|
286
372
|
"admin.brain.rebuilding": "재구성 중",
|
|
287
373
|
"admin.brain.rebuild": "인덱스 재구성",
|
|
374
|
+
"admin.runtime.agent": "AgentRuntime",
|
|
375
|
+
"admin.runtime.tools": "ToolRegistry",
|
|
376
|
+
"admin.runtime.readyDetail": "실행 preview와 실제 실행이 준비되었습니다.",
|
|
377
|
+
"admin.runtime.blockedFallback": "실행 전 preview가 차단 사유를 반환합니다.",
|
|
378
|
+
"admin.runtime.aligned": "정렬됨",
|
|
379
|
+
"admin.runtime.drift": "점검 필요",
|
|
380
|
+
"admin.runtime.toolCounts": "등록 {registered} · 정책 {governed} · 설명 {described}",
|
|
381
|
+
"admin.runtime.mode": "mode {mode}",
|
|
382
|
+
"admin.runtime.execution": "exec {mode}",
|
|
383
|
+
"admin.runtime.health": "health {status}",
|
|
288
384
|
"admin.policy.fallback": "정책",
|
|
289
385
|
"admin.policy.quiet": "정책 API 대기 중",
|
|
290
386
|
"admin.retention.days": "{days}일 보관",
|
|
@@ -335,6 +431,37 @@ export const COPY: Record<Language, TextMap> = {
|
|
|
335
431
|
"flow.install.step.download": "다운로드",
|
|
336
432
|
"flow.install.step.validate": "확인",
|
|
337
433
|
"flow.install.step.load": "로드",
|
|
434
|
+
"flow.analysis.hardware.icon.chip": "🖥️",
|
|
435
|
+
"flow.analysis.hardware.icon.ram": "🧠",
|
|
436
|
+
"flow.analysis.hardware.icon.gpu": "⚡",
|
|
437
|
+
"flow.analysis.hardware.icon.support": "🧩",
|
|
438
|
+
"flow.analysis.hardware.icon.models": "📦",
|
|
439
|
+
"flow.analysis.hardware.label.chip": "컴퓨터 (운영체제와 칩)",
|
|
440
|
+
"flow.analysis.hardware.label.ram": "메모리 (생각할 작업 공간, RAM)",
|
|
441
|
+
"flow.analysis.hardware.label.gpu": "그래픽 (계산을 도와주는 GPU)",
|
|
442
|
+
"flow.analysis.hardware.label.support": "로컬 지원 (모델 실행 도우미)",
|
|
443
|
+
"flow.analysis.hardware.label.models": "모델 (설치된 AI Brain)",
|
|
444
|
+
"flow.recommend.timeEstimate": "다운로드 약 {download} · 첫 응답 약 {response}초",
|
|
445
|
+
"flow.recommend.timeEstimate.ready": "다운로드 불필요 · 첫 응답 약 {response}초",
|
|
446
|
+
"flow.recommend.timeEstimate.unknown": "다운로드 시간 미확인 · 첫 응답 약 {response}초",
|
|
447
|
+
"flow.recommend.timeNote": "네트워크 속도에 따라 달라질 수 있어요.",
|
|
448
|
+
"flow.recommend.minutes": "{count}분",
|
|
449
|
+
"flow.recommend.comparison.faster": "(더 빠름)",
|
|
450
|
+
"flow.recommend.comparison.advanced": "(더 강력함)",
|
|
451
|
+
"flow.recommend.choose": "이 모델 선택",
|
|
452
|
+
"flow.recommend.primaryNote": "약 {time} 후 사용 준비 완료",
|
|
453
|
+
"flow.recommend.primaryNote.unknown": "다운로드 후 바로 사용 준비 완료",
|
|
454
|
+
"flow.recommend.nextHint": "선택하면 다운로드와 준비 화면으로 넘어가고, 끝나면 바로 Brain이 열립니다.",
|
|
455
|
+
"flow.install.expectedTitle": "예상 진행",
|
|
456
|
+
"flow.install.expected": "약 {download} 다운로드 후 약 {response}초 안에 첫 응답",
|
|
457
|
+
"flow.install.expected.ready": "다운로드 없이 약 {response}초 안에 첫 응답",
|
|
458
|
+
"flow.install.expected.unknown": "다운로드 후 약 {response}초 안에 첫 응답",
|
|
459
|
+
"flow.install.timelineStep.download": "모델 다운로드",
|
|
460
|
+
"flow.install.timelineStep.validate": "응답 확인",
|
|
461
|
+
"flow.install.timelineStep.load": "Brain에 로드",
|
|
462
|
+
"flow.install.timelineApprox": "약 {time}",
|
|
463
|
+
"flow.install.timelineQuick": "잠깐",
|
|
464
|
+
"flow.install.expectedCompletion": "끝나면 바로 Brain이 열립니다.",
|
|
338
465
|
"flow.shell": "내 로컬 AI 브레인 만들기",
|
|
339
466
|
"flow.login.title": "내 AI 브레인의 주인을 정합니다.",
|
|
340
467
|
"flow.login.body": "Lattice AI는 내 지식과 맥락을 이 컴퓨터에 보관하는 로컬 우선 AI 브레인입니다. 모델은 바꿀 수 있고, 외부 전송은 사용자가 선택할 때만 시작됩니다.",
|
|
@@ -401,6 +528,43 @@ export const COPY: Record<Language, TextMap> = {
|
|
|
401
528
|
"flow.consent.location": "저장 위치",
|
|
402
529
|
"flow.consent.external": "외부 접속 대상",
|
|
403
530
|
"flow.consent.externalNone": "선택 전 외부 접속 없음",
|
|
531
|
+
"brain.answerProof.citationsLabel": "근거 출처 {count}개",
|
|
532
|
+
"brain.answerProof.marker": "출처 {index}로 이동",
|
|
533
|
+
"brain.answerProof.markerShort": "출처 {index}",
|
|
534
|
+
"brain.answerProof.citationItem": "출처 {index}: {title}",
|
|
535
|
+
"brain.answerProof.modelLine": "{model} 기준 답변 근거",
|
|
536
|
+
"shell.account.aria": "계정과 워크스페이스",
|
|
537
|
+
"shell.account.workspaceLabel": "워크스페이스",
|
|
538
|
+
"shell.account.personal": "개인 Brain",
|
|
539
|
+
"shell.account.modeLabel": "보기 모드",
|
|
540
|
+
"shell.account.mode.basic": "기본",
|
|
541
|
+
"shell.account.mode.advanced": "고급",
|
|
542
|
+
"shell.account.mode.admin": "관리자",
|
|
543
|
+
"shell.account.open": "계정·워크스페이스 메뉴 열기",
|
|
544
|
+
"shell.account.menuAria": "계정과 워크스페이스 메뉴",
|
|
545
|
+
"shell.account.profile": "프로필과 계정",
|
|
546
|
+
"shell.account.workspaces": "워크스페이스 전환",
|
|
547
|
+
"shell.account.admin": "관리자 콘솔",
|
|
548
|
+
"shell.account.settings": "설정 열기",
|
|
549
|
+
"shell.sync.aria": "VS Code 확장 연동 상태",
|
|
550
|
+
"shell.sync.label": "VS Code",
|
|
551
|
+
"shell.sync.connected": "연결됨",
|
|
552
|
+
"shell.sync.indexing": "인덱싱 중",
|
|
553
|
+
"shell.sync.synced": "동기화됨",
|
|
554
|
+
"shell.sync.offline": "연결 안 됨",
|
|
555
|
+
"shell.sync.checking": "확인 중",
|
|
556
|
+
"shell.sync.detail": "확장과 메인 앱이 같은 Brain을 공유합니다.",
|
|
557
|
+
"shell.sync.detailOffline": "VS Code 확장이 아직 이 Brain에 연결되지 않았습니다.",
|
|
558
|
+
"feedback.retry": "다시 시도",
|
|
559
|
+
"feedback.error.title": "문제가 생겼어요",
|
|
560
|
+
"feedback.error.body": "잠시 후 다시 시도하거나 설정에서 연결을 확인하세요.",
|
|
561
|
+
"feedback.consent.aria": "외부 연결 동의 상태",
|
|
562
|
+
"feedback.consent.activeTitle": "외부 연결 허용됨",
|
|
563
|
+
"feedback.consent.activeBody": "필요할 때만 외부 저장소에서 모델과 페이지를 가져옵니다.",
|
|
564
|
+
"feedback.consent.revoke": "외부 연결 해제",
|
|
565
|
+
"feedback.consent.revokedTitle": "외부 연결이 해제되었습니다",
|
|
566
|
+
"feedback.consent.revokedBody": "이 Brain은 지금 완전히 로컬에서만 동작합니다. 다시 허용하려면 아래에서 켜세요.",
|
|
567
|
+
"feedback.consent.reenable": "다시 허용",
|
|
404
568
|
},
|
|
405
569
|
en: {
|
|
406
570
|
"language.label": "Language",
|
|
@@ -437,6 +601,28 @@ export const COPY: Record<Language, TextMap> = {
|
|
|
437
601
|
"brain.portable": "Portable",
|
|
438
602
|
"brain.private": "Private",
|
|
439
603
|
"brain.admin": "Admin Console",
|
|
604
|
+
"shell.workspace.label": "Workspace and profile",
|
|
605
|
+
"shell.workspace.current": "Current workspace",
|
|
606
|
+
"shell.workspace.switch": "Switch",
|
|
607
|
+
"shell.workspace.active": "Active",
|
|
608
|
+
"shell.workspace.empty": "No workspaces yet",
|
|
609
|
+
"shell.workspace.personal": "Personal Brain",
|
|
610
|
+
"shell.workspace.manageSpaces": "Manage workspaces",
|
|
611
|
+
"shell.workspace.close": "Close",
|
|
612
|
+
"shell.profile.label": "Profile",
|
|
613
|
+
"shell.profile.owner": "Owner",
|
|
614
|
+
"shell.profile.signedOut": "Not signed in",
|
|
615
|
+
"shell.profile.manage": "Open account settings",
|
|
616
|
+
"shell.admin.label": "Admin",
|
|
617
|
+
"shell.admin.open": "Open Admin Console",
|
|
618
|
+
"shell.admin.tooltip": "Manage settings, agents, and the tool registry",
|
|
619
|
+
"shell.admin.needsMode": "Admin Console is available in Advanced or Admin mode",
|
|
620
|
+
"shell.admin.enable": "Switch to Admin mode",
|
|
621
|
+
"shell.mode.label": "Mode",
|
|
622
|
+
"shell.mode.basic": "Basic",
|
|
623
|
+
"shell.mode.advanced": "Advanced",
|
|
624
|
+
"shell.mode.admin": "Admin",
|
|
625
|
+
"shell.mode.info": "Mode sets which tools and admin surfaces are shown",
|
|
440
626
|
"brain.action.add": "Add",
|
|
441
627
|
"brain.action.find": "Find",
|
|
442
628
|
"brain.action.model": "Model",
|
|
@@ -479,6 +665,38 @@ export const COPY: Record<Language, TextMap> = {
|
|
|
479
665
|
"brain.ingest.web.pending": "Reading {url} into Brain.",
|
|
480
666
|
"brain.ingest.web.saved": "{url} was saved to Brain.",
|
|
481
667
|
"brain.ingest.web.failed": "Could not add the web page: {reason}",
|
|
668
|
+
"brain.ingest.type.file": "File",
|
|
669
|
+
"brain.ingest.type.folder": "Folder",
|
|
670
|
+
"brain.ingest.type.note": "Note",
|
|
671
|
+
"brain.ingest.type.web": "Web",
|
|
672
|
+
"brain.ingest.cta.file": "Pick a file to add now",
|
|
673
|
+
"brain.ingest.cta.folder": "Enter a path and press Enter",
|
|
674
|
+
"brain.ingest.cta.note": "Paste content and press Enter",
|
|
675
|
+
"brain.ingest.cta.web": "Enter a URL and press Enter",
|
|
676
|
+
"brain.ingest.active": "Processing {label}",
|
|
677
|
+
"brain.ingest.progress.aria": "Ingestion progress for {label}",
|
|
678
|
+
"brain.ingest.stage.preparing": "Preparing",
|
|
679
|
+
"brain.ingest.stage.parsing": "Parsing",
|
|
680
|
+
"brain.ingest.stage.embedding": "Embedding",
|
|
681
|
+
"brain.ingest.stage.indexing": "Indexing",
|
|
682
|
+
"brain.ingest.stage.complete": "Memorized",
|
|
683
|
+
"brain.ingest.stage.error": "Failed",
|
|
684
|
+
"brain.ingest.stage.preparing.hint": "Reading the source",
|
|
685
|
+
"brain.ingest.stage.parsing.hint": "Extracting text and structure",
|
|
686
|
+
"brain.ingest.stage.embedding.hint": "Turning into semantic vectors",
|
|
687
|
+
"brain.ingest.stage.indexing.hint": "Linking into the knowledge graph",
|
|
688
|
+
"brain.ingest.stage.complete.hint": "It is now part of your knowledge",
|
|
689
|
+
"brain.ingest.result": "{memories} new memories · {entities} new entities",
|
|
690
|
+
"brain.ingest.result.empty": "Merged into existing knowledge",
|
|
691
|
+
"brain.timeline.aria": "Recent memory emergence timeline",
|
|
692
|
+
"brain.timeline.emergenceTitle": "Knowledge that just emerged",
|
|
693
|
+
"brain.timeline.recent": "Recent ingestion",
|
|
694
|
+
"brain.timeline.newMemories": "{count} new memories",
|
|
695
|
+
"brain.timeline.newEntities": "{count} new entities",
|
|
696
|
+
"brain.timeline.at": "{time}",
|
|
697
|
+
"brain.timeline.justNow": "just now",
|
|
698
|
+
"brain.timeline.minutesAgo": "{count}m ago",
|
|
699
|
+
"brain.timeline.empty": "No ingestion yet. Add anything above to begin.",
|
|
482
700
|
"brain.image": "Image",
|
|
483
701
|
"brain.unavailable": "Unavailable",
|
|
484
702
|
"brain.imageAttached": "Image attached",
|
|
@@ -533,6 +751,18 @@ export const COPY: Record<Language, TextMap> = {
|
|
|
533
751
|
"brain.answerProof.modelProven": "Brain evidence outside {model}",
|
|
534
752
|
"brain.answerProof.modelPending": "{model} response · evidence pending",
|
|
535
753
|
"brain.answerProof.empty": "No linked source yet. Indexed memory appears here.",
|
|
754
|
+
"brain.citation.chip": "Source {num}",
|
|
755
|
+
"brain.citation.chip.long": "Source {num}: {title}",
|
|
756
|
+
"brain.citation.expand": "Expand source",
|
|
757
|
+
"brain.citation.close": "Close source",
|
|
758
|
+
"brain.citation.preview.from": "From: ",
|
|
759
|
+
"brain.citation.preview.snippet": "Excerpt: ",
|
|
760
|
+
"brain.citation.keyboard.tip": "Press Space or Enter to expand a source, Escape to close.",
|
|
761
|
+
"brain.citation.region": "Source citations referenced in the answer",
|
|
762
|
+
"brain.citation.announce.open": "Opened source {num}: {title}",
|
|
763
|
+
"brain.citation.announce.close": "Closed source preview.",
|
|
764
|
+
"brain.citation.count": "This answer cites {count} source(s).",
|
|
765
|
+
"brain.citation.score": "Relevance {score}%",
|
|
536
766
|
"brain.memory.empty.kicker": "First memory",
|
|
537
767
|
"brain.memory.empty": "Memory is quiet",
|
|
538
768
|
"brain.knowledge.empty": "Knowledge is forming",
|
|
@@ -542,6 +772,24 @@ export const COPY: Record<Language, TextMap> = {
|
|
|
542
772
|
"brain.graph.emptyFocus": "Your Brain graph grows as you add conversations, documents, and projects.",
|
|
543
773
|
"brain.graph.search": "Search",
|
|
544
774
|
"brain.graph.searchAria": "Search knowledge graph",
|
|
775
|
+
"brain.graph.control.panel": "Graph exploration controls",
|
|
776
|
+
"brain.graph.control.filter": "Filter",
|
|
777
|
+
"brain.graph.control.types": "Entity types",
|
|
778
|
+
"brain.graph.control.allTypes": "All types",
|
|
779
|
+
"brain.graph.control.time": "Time exploration",
|
|
780
|
+
"brain.graph.control.dateRange": "Recently added window",
|
|
781
|
+
"brain.graph.control.resetFilters": "Reset filters",
|
|
782
|
+
"brain.graph.control.recentWindow": "Last {days} days",
|
|
783
|
+
"brain.graph.control.allTime": "All time",
|
|
784
|
+
"brain.graph.control.toggleType": "Toggle {type} type",
|
|
785
|
+
"brain.graph.search.typeahead": "Search suggestions",
|
|
786
|
+
"brain.graph.search.typeaheadAria": "Search suggestion results",
|
|
787
|
+
"brain.graph.search.noMatches": "No matching nodes",
|
|
788
|
+
"brain.graph.search.matchCount": "{count} matches",
|
|
789
|
+
"brain.graph.focus.neighbors": "{count} neighbors highlighted",
|
|
790
|
+
"brain.graph.focus.smooth": "Smoothly focuses the selected node and highlights its neighbors.",
|
|
791
|
+
"brain.graph.focus.recent": "Recently added",
|
|
792
|
+
"brain.graph.focus.clear": "Clear focus",
|
|
545
793
|
"care.title": "Care for my Brain",
|
|
546
794
|
"care.subtitle": "Own it locally. Keep it portable.",
|
|
547
795
|
"care.private": "Private",
|
|
@@ -658,6 +906,8 @@ export const COPY: Record<Language, TextMap> = {
|
|
|
658
906
|
"admin.panel.protection": "Protection",
|
|
659
907
|
"admin.panel.brainOps": "Brain Operations",
|
|
660
908
|
"admin.panel.maintenance": "Maintenance",
|
|
909
|
+
"admin.panel.runtimeTrust": "Runtime Trust",
|
|
910
|
+
"admin.panel.contracts": "Contracts",
|
|
661
911
|
"admin.empty.users": "No users reported by the admin API.",
|
|
662
912
|
"admin.empty.roles": "No role matrix reported.",
|
|
663
913
|
"admin.empty.audit": "No recent audit events.",
|
|
@@ -679,6 +929,16 @@ export const COPY: Record<Language, TextMap> = {
|
|
|
679
929
|
"admin.brain.summaryFallback": "Local Brain services are separated from user chat.",
|
|
680
930
|
"admin.brain.rebuilding": "Rebuilding",
|
|
681
931
|
"admin.brain.rebuild": "Rebuild index",
|
|
932
|
+
"admin.runtime.agent": "AgentRuntime",
|
|
933
|
+
"admin.runtime.tools": "ToolRegistry",
|
|
934
|
+
"admin.runtime.readyDetail": "Run preview and execution are ready.",
|
|
935
|
+
"admin.runtime.blockedFallback": "Run preview returns the blocking reason before execution.",
|
|
936
|
+
"admin.runtime.aligned": "Aligned",
|
|
937
|
+
"admin.runtime.drift": "Needs review",
|
|
938
|
+
"admin.runtime.toolCounts": "Registered {registered} · governed {governed} · described {described}",
|
|
939
|
+
"admin.runtime.mode": "mode {mode}",
|
|
940
|
+
"admin.runtime.execution": "exec {mode}",
|
|
941
|
+
"admin.runtime.health": "health {status}",
|
|
682
942
|
"admin.policy.fallback": "Policy",
|
|
683
943
|
"admin.policy.quiet": "Policy API quiet",
|
|
684
944
|
"admin.retention.days": "{days} day retention",
|
|
@@ -729,6 +989,37 @@ export const COPY: Record<Language, TextMap> = {
|
|
|
729
989
|
"flow.install.step.download": "Download",
|
|
730
990
|
"flow.install.step.validate": "Validate",
|
|
731
991
|
"flow.install.step.load": "Load",
|
|
992
|
+
"flow.analysis.hardware.icon.chip": "🖥️",
|
|
993
|
+
"flow.analysis.hardware.icon.ram": "🧠",
|
|
994
|
+
"flow.analysis.hardware.icon.gpu": "⚡",
|
|
995
|
+
"flow.analysis.hardware.icon.support": "🧩",
|
|
996
|
+
"flow.analysis.hardware.icon.models": "📦",
|
|
997
|
+
"flow.analysis.hardware.label.chip": "Computer (operating system and chip)",
|
|
998
|
+
"flow.analysis.hardware.label.ram": "Memory (working space to think, RAM)",
|
|
999
|
+
"flow.analysis.hardware.label.gpu": "Graphics (the GPU that speeds up math)",
|
|
1000
|
+
"flow.analysis.hardware.label.support": "Local support (helpers that run models)",
|
|
1001
|
+
"flow.analysis.hardware.label.models": "Models (AI Brains already installed)",
|
|
1002
|
+
"flow.recommend.timeEstimate": "Download about {download} · first reply about {response}s",
|
|
1003
|
+
"flow.recommend.timeEstimate.ready": "No download needed · first reply about {response}s",
|
|
1004
|
+
"flow.recommend.timeEstimate.unknown": "Download time unknown · first reply about {response}s",
|
|
1005
|
+
"flow.recommend.timeNote": "Actual time depends on your network speed.",
|
|
1006
|
+
"flow.recommend.minutes": "{count} min",
|
|
1007
|
+
"flow.recommend.comparison.faster": "(faster)",
|
|
1008
|
+
"flow.recommend.comparison.advanced": "(more capable)",
|
|
1009
|
+
"flow.recommend.choose": "Choose this model",
|
|
1010
|
+
"flow.recommend.primaryNote": "Ready to use in about {time}",
|
|
1011
|
+
"flow.recommend.primaryNote.unknown": "Ready to use right after download",
|
|
1012
|
+
"flow.recommend.nextHint": "Choosing takes you to download and setup, then your Brain opens automatically.",
|
|
1013
|
+
"flow.install.expectedTitle": "What to expect",
|
|
1014
|
+
"flow.install.expected": "About {download} to download, then a first reply within about {response}s",
|
|
1015
|
+
"flow.install.expected.ready": "No download — first reply within about {response}s",
|
|
1016
|
+
"flow.install.expected.unknown": "After download, a first reply within about {response}s",
|
|
1017
|
+
"flow.install.timelineStep.download": "Download model",
|
|
1018
|
+
"flow.install.timelineStep.validate": "Check the reply",
|
|
1019
|
+
"flow.install.timelineStep.load": "Load into Brain",
|
|
1020
|
+
"flow.install.timelineApprox": "about {time}",
|
|
1021
|
+
"flow.install.timelineQuick": "moment",
|
|
1022
|
+
"flow.install.expectedCompletion": "When it finishes, your Brain opens right away.",
|
|
732
1023
|
"flow.shell": "Create your local AI Brain",
|
|
733
1024
|
"flow.login.title": "Choose the owner of your AI Brain.",
|
|
734
1025
|
"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.",
|
|
@@ -795,6 +1086,43 @@ export const COPY: Record<Language, TextMap> = {
|
|
|
795
1086
|
"flow.consent.location": "Storage location",
|
|
796
1087
|
"flow.consent.external": "External target",
|
|
797
1088
|
"flow.consent.externalNone": "No external connection before selection",
|
|
1089
|
+
"brain.answerProof.citationsLabel": "{count} evidence sources",
|
|
1090
|
+
"brain.answerProof.marker": "Jump to source {index}",
|
|
1091
|
+
"brain.answerProof.markerShort": "Source {index}",
|
|
1092
|
+
"brain.answerProof.citationItem": "Source {index}: {title}",
|
|
1093
|
+
"brain.answerProof.modelLine": "Evidence behind this {model} answer",
|
|
1094
|
+
"shell.account.aria": "Account and workspace",
|
|
1095
|
+
"shell.account.workspaceLabel": "Workspace",
|
|
1096
|
+
"shell.account.personal": "Personal Brain",
|
|
1097
|
+
"shell.account.modeLabel": "View mode",
|
|
1098
|
+
"shell.account.mode.basic": "Basic",
|
|
1099
|
+
"shell.account.mode.advanced": "Advanced",
|
|
1100
|
+
"shell.account.mode.admin": "Admin",
|
|
1101
|
+
"shell.account.open": "Open account and workspace menu",
|
|
1102
|
+
"shell.account.menuAria": "Account and workspace menu",
|
|
1103
|
+
"shell.account.profile": "Profile & account",
|
|
1104
|
+
"shell.account.workspaces": "Switch workspace",
|
|
1105
|
+
"shell.account.admin": "Admin console",
|
|
1106
|
+
"shell.account.settings": "Open settings",
|
|
1107
|
+
"shell.sync.aria": "VS Code extension link status",
|
|
1108
|
+
"shell.sync.label": "VS Code",
|
|
1109
|
+
"shell.sync.connected": "Connected",
|
|
1110
|
+
"shell.sync.indexing": "Indexing",
|
|
1111
|
+
"shell.sync.synced": "Synced",
|
|
1112
|
+
"shell.sync.offline": "Not connected",
|
|
1113
|
+
"shell.sync.checking": "Checking",
|
|
1114
|
+
"shell.sync.detail": "The extension and main app share the same Brain.",
|
|
1115
|
+
"shell.sync.detailOffline": "The VS Code extension is not linked to this Brain yet.",
|
|
1116
|
+
"feedback.retry": "Retry",
|
|
1117
|
+
"feedback.error.title": "Something went wrong",
|
|
1118
|
+
"feedback.error.body": "Try again shortly or check the connection in Settings.",
|
|
1119
|
+
"feedback.consent.aria": "External access consent status",
|
|
1120
|
+
"feedback.consent.activeTitle": "External access allowed",
|
|
1121
|
+
"feedback.consent.activeBody": "Models and pages are fetched externally only when needed.",
|
|
1122
|
+
"feedback.consent.revoke": "Revoke external access",
|
|
1123
|
+
"feedback.consent.revokedTitle": "External access revoked",
|
|
1124
|
+
"feedback.consent.revokedBody": "This Brain now runs fully local. Re-enable below to allow external access again.",
|
|
1125
|
+
"feedback.consent.reenable": "Re-enable",
|
|
798
1126
|
},
|
|
799
1127
|
};
|
|
800
1128
|
|
|
@@ -10,11 +10,13 @@ type AppState = {
|
|
|
10
10
|
workspaceId: string | null;
|
|
11
11
|
apiBase: string | null;
|
|
12
12
|
language: Language;
|
|
13
|
+
externalConsent: boolean;
|
|
13
14
|
setTheme: (theme: Theme) => void;
|
|
14
15
|
setMode: (mode: WorkspaceMode) => void;
|
|
15
16
|
setWorkspaceId: (workspaceId: string | null) => void;
|
|
16
17
|
setApiBase: (apiBase: string | null) => void;
|
|
17
18
|
setLanguage: (language: Language) => void;
|
|
19
|
+
setExternalConsent: (externalConsent: boolean) => void;
|
|
18
20
|
};
|
|
19
21
|
|
|
20
22
|
function readTheme(): Theme {
|
|
@@ -40,6 +42,14 @@ function readWorkspaceId(): string | null {
|
|
|
40
42
|
return null;
|
|
41
43
|
}
|
|
42
44
|
|
|
45
|
+
function readExternalConsent(): boolean {
|
|
46
|
+
try {
|
|
47
|
+
// Default: external access allowed (matches existing user-initiated download flow).
|
|
48
|
+
return localStorage.getItem("lattice.externalConsent") !== "revoked";
|
|
49
|
+
} catch {}
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
|
|
43
53
|
function readLanguage(): Language {
|
|
44
54
|
try {
|
|
45
55
|
const saved = localStorage.getItem("lattice.language");
|
|
@@ -55,6 +65,7 @@ export const useAppStore = create<AppState>((set) => ({
|
|
|
55
65
|
workspaceId: readWorkspaceId(),
|
|
56
66
|
apiBase: null,
|
|
57
67
|
language: readLanguage(),
|
|
68
|
+
externalConsent: readExternalConsent(),
|
|
58
69
|
setTheme: (theme) => {
|
|
59
70
|
document.documentElement.dataset.theme = theme;
|
|
60
71
|
try { localStorage.setItem("lattice.theme", theme); } catch {}
|
|
@@ -71,6 +82,10 @@ export const useAppStore = create<AppState>((set) => ({
|
|
|
71
82
|
set({ workspaceId });
|
|
72
83
|
},
|
|
73
84
|
setApiBase: (apiBase) => set({ apiBase }),
|
|
85
|
+
setExternalConsent: (externalConsent) => {
|
|
86
|
+
try { localStorage.setItem("lattice.externalConsent", externalConsent ? "granted" : "revoked"); } catch {}
|
|
87
|
+
set({ externalConsent });
|
|
88
|
+
},
|
|
74
89
|
setLanguage: (language) => {
|
|
75
90
|
document.documentElement.lang = language === "ko" ? "ko" : "en";
|
|
76
91
|
try { localStorage.setItem("lattice.language", language); } catch {}
|