ltcai 0.1.26 → 0.1.28
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 +1 -1
- package/docs/CHANGELOG.md +38 -0
- package/docs/architecture.md +35 -0
- package/docs/kg-schema.md +210 -0
- package/docs/spec-vs-impl.md +132 -0
- package/knowledge_graph.py +29 -1
- package/package.json +3 -1
- package/server.py +44 -2
- package/static/account.html +237 -37
- package/static/admin.html +18 -1
- package/static/chat.html +533 -10
- package/static/css/tokens.css +169 -0
- package/static/graph.html +18 -1
- package/static/lattice-reference.css +1421 -0
- package/static/sw.js +3 -1
package/static/chat.html
CHANGED
|
@@ -3066,10 +3066,331 @@
|
|
|
3066
3066
|
background: #ffffff;
|
|
3067
3067
|
box-shadow: 0 10px 24px rgba(0,0,0,0.28);
|
|
3068
3068
|
}
|
|
3069
|
+
|
|
3070
|
+
/* PPT reference skin: light workspace, indigo navigation, modal-first flow. */
|
|
3071
|
+
:root {
|
|
3072
|
+
--bg: #f8f6ff;
|
|
3073
|
+
--surface: #ffffff;
|
|
3074
|
+
--surface-2: #f3f0ff;
|
|
3075
|
+
--surface-3: #ece7ff;
|
|
3076
|
+
--accent: #6f4bf6;
|
|
3077
|
+
--accent-2: #ffb84d;
|
|
3078
|
+
--accent-3: #7868ff;
|
|
3079
|
+
--accent-soft: rgba(111,75,246,0.10);
|
|
3080
|
+
--danger: #ef4444;
|
|
3081
|
+
--text: #24223d;
|
|
3082
|
+
--muted: #625f7c;
|
|
3083
|
+
--faint: #9690b2;
|
|
3084
|
+
--border: rgba(111,75,246,0.13);
|
|
3085
|
+
--border-strong: rgba(111,75,246,0.24);
|
|
3086
|
+
--shadow: 0 24px 68px rgba(86,70,160,0.16);
|
|
3087
|
+
--shadow-sm: 0 10px 28px rgba(86,70,160,0.10);
|
|
3088
|
+
}
|
|
3089
|
+
body::before {
|
|
3090
|
+
background:
|
|
3091
|
+
radial-gradient(circle at 76% 14%, rgba(111,75,246,0.12), transparent 30%),
|
|
3092
|
+
radial-gradient(circle at 8% 80%, rgba(196,181,253,0.26), transparent 35%),
|
|
3093
|
+
linear-gradient(180deg, #fbfaff 0%, #f6f2ff 100%);
|
|
3094
|
+
}
|
|
3095
|
+
.bg-grid {
|
|
3096
|
+
opacity: 0.28;
|
|
3097
|
+
background-image:
|
|
3098
|
+
radial-gradient(circle, rgba(111,75,246,0.28) 1px, transparent 1.8px),
|
|
3099
|
+
linear-gradient(rgba(111,75,246,0.06) 1px, transparent 1px),
|
|
3100
|
+
linear-gradient(90deg, rgba(111,75,246,0.05) 1px, transparent 1px);
|
|
3101
|
+
background-size: 84px 84px, 48px 48px, 48px 48px;
|
|
3102
|
+
mask-image: linear-gradient(180deg, rgba(0,0,0,0.24), rgba(0,0,0,0.04));
|
|
3103
|
+
}
|
|
3104
|
+
.app-layout::after {
|
|
3105
|
+
background:
|
|
3106
|
+
linear-gradient(115deg, transparent 0 40%, rgba(111,75,246,0.08) 40.15%, transparent 40.4% 100%),
|
|
3107
|
+
radial-gradient(ellipse at 5% 88%, rgba(111,75,246,0.16), transparent 35%);
|
|
3108
|
+
}
|
|
3109
|
+
.app-layout .sidebar {
|
|
3110
|
+
background: rgba(255,255,255,0.88);
|
|
3111
|
+
border-right-color: rgba(111,75,246,0.12);
|
|
3112
|
+
box-shadow: 12px 0 46px rgba(86,70,160,0.08);
|
|
3113
|
+
}
|
|
3114
|
+
.app-layout .sidebar-header,
|
|
3115
|
+
.app-layout .user-strip,
|
|
3116
|
+
.app-layout .sidebar-footer,
|
|
3117
|
+
.app-layout .sidebar-primary-actions,
|
|
3118
|
+
.app-layout .chat-header {
|
|
3119
|
+
border-color: rgba(111,75,246,0.10);
|
|
3120
|
+
}
|
|
3121
|
+
.app-layout .logo-box,
|
|
3122
|
+
.app-layout .user-avatar {
|
|
3123
|
+
background: linear-gradient(135deg, #6f4bf6, #9b87ff);
|
|
3124
|
+
color: #fff;
|
|
3125
|
+
box-shadow: 0 14px 28px rgba(111,75,246,0.22);
|
|
3126
|
+
}
|
|
3127
|
+
.app-layout .brand-title,
|
|
3128
|
+
.app-layout .empty-state h1 {
|
|
3129
|
+
color: #24223d;
|
|
3130
|
+
}
|
|
3131
|
+
.app-layout .brand-subtitle,
|
|
3132
|
+
.app-layout .user-strip,
|
|
3133
|
+
.app-layout .history-item,
|
|
3134
|
+
.app-layout .logout-btn {
|
|
3135
|
+
color: var(--muted);
|
|
3136
|
+
}
|
|
3137
|
+
.app-layout .sidebar-search input,
|
|
3138
|
+
.app-layout .mcp-add-form input,
|
|
3139
|
+
.app-layout .mcp-add-form textarea,
|
|
3140
|
+
.app-layout .mcp-add-form select,
|
|
3141
|
+
.app-layout .pw-field input {
|
|
3142
|
+
background: #fbfaff;
|
|
3143
|
+
border-color: rgba(111,75,246,0.12);
|
|
3144
|
+
color: var(--text);
|
|
3145
|
+
}
|
|
3146
|
+
.app-layout .new-chat-btn,
|
|
3147
|
+
.app-layout .status-btn,
|
|
3148
|
+
.app-layout .setup-wizard-sidebar-btn,
|
|
3149
|
+
.app-layout .admin-btn {
|
|
3150
|
+
background: #fff;
|
|
3151
|
+
border-color: rgba(111,75,246,0.13);
|
|
3152
|
+
color: var(--text);
|
|
3153
|
+
box-shadow: 0 8px 22px rgba(86,70,160,0.06);
|
|
3154
|
+
}
|
|
3155
|
+
.app-layout .new-chat-btn:hover,
|
|
3156
|
+
.app-layout .status-btn:hover,
|
|
3157
|
+
.app-layout .setup-wizard-sidebar-btn:hover,
|
|
3158
|
+
.app-layout .admin-btn:hover,
|
|
3159
|
+
.app-layout .history-item:hover,
|
|
3160
|
+
.app-layout .history-item.active {
|
|
3161
|
+
background: #f1ecff;
|
|
3162
|
+
border-color: rgba(111,75,246,0.25);
|
|
3163
|
+
color: var(--accent);
|
|
3164
|
+
}
|
|
3165
|
+
.app-layout .chat-header {
|
|
3166
|
+
background: rgba(255,255,255,0.78);
|
|
3167
|
+
box-shadow: 0 8px 28px rgba(86,70,160,0.08);
|
|
3168
|
+
}
|
|
3169
|
+
.app-layout .model-badge,
|
|
3170
|
+
.app-layout .status-pill,
|
|
3171
|
+
.app-layout .logout-btn {
|
|
3172
|
+
background: rgba(255,255,255,0.78);
|
|
3173
|
+
border-color: rgba(111,75,246,0.14);
|
|
3174
|
+
color: var(--muted);
|
|
3175
|
+
}
|
|
3176
|
+
.app-layout .model-badge {
|
|
3177
|
+
color: var(--text);
|
|
3178
|
+
}
|
|
3179
|
+
.app-layout .status-dot {
|
|
3180
|
+
background: var(--accent);
|
|
3181
|
+
box-shadow: 0 0 0 4px rgba(111,75,246,0.10), 0 0 18px rgba(111,75,246,0.30);
|
|
3182
|
+
}
|
|
3183
|
+
.app-layout .ops-card,
|
|
3184
|
+
.app-layout .empty-chip,
|
|
3185
|
+
.app-layout .ai .bubble,
|
|
3186
|
+
.app-layout .acct-modal,
|
|
3187
|
+
.app-layout .mcp-modal {
|
|
3188
|
+
background: rgba(255,255,255,0.86);
|
|
3189
|
+
border-color: rgba(111,75,246,0.13);
|
|
3190
|
+
box-shadow: var(--shadow-sm), inset 0 1px 0 rgba(255,255,255,0.9);
|
|
3191
|
+
}
|
|
3192
|
+
.app-layout .ops-card.primary {
|
|
3193
|
+
background: linear-gradient(135deg, rgba(111,75,246,0.12), rgba(255,255,255,0.92) 62%);
|
|
3194
|
+
border-color: rgba(111,75,246,0.23);
|
|
3195
|
+
}
|
|
3196
|
+
.app-layout .ops-card.interactive:hover,
|
|
3197
|
+
.app-layout .empty-chip:hover {
|
|
3198
|
+
background: #f3efff;
|
|
3199
|
+
border-color: rgba(111,75,246,0.30);
|
|
3200
|
+
box-shadow: 0 18px 42px rgba(86,70,160,0.16);
|
|
3201
|
+
}
|
|
3202
|
+
.app-layout .ops-card.primary .ops-icon,
|
|
3203
|
+
.app-layout .ops-card:not(.primary) .ops-icon,
|
|
3204
|
+
.app-layout .empty-state > div[style] {
|
|
3205
|
+
background: linear-gradient(135deg, rgba(111,75,246,0.14), rgba(155,135,255,0.12)) !important;
|
|
3206
|
+
border-color: rgba(111,75,246,0.18) !important;
|
|
3207
|
+
color: var(--accent) !important;
|
|
3208
|
+
}
|
|
3209
|
+
.app-layout .messages-viewport {
|
|
3210
|
+
background: transparent;
|
|
3211
|
+
}
|
|
3212
|
+
.app-layout .user .bubble {
|
|
3213
|
+
background: linear-gradient(135deg, #6f4bf6, #7366ff);
|
|
3214
|
+
color: #fff;
|
|
3215
|
+
border-color: rgba(111,75,246,0.28);
|
|
3216
|
+
box-shadow: 0 14px 32px rgba(111,75,246,0.22);
|
|
3217
|
+
}
|
|
3218
|
+
.app-layout .input-area {
|
|
3219
|
+
background: linear-gradient(0deg, rgba(248,246,255,0.98) 0%, rgba(248,246,255,0.76) 64%, transparent 100%);
|
|
3220
|
+
}
|
|
3221
|
+
.app-layout .input-box {
|
|
3222
|
+
background: rgba(255,255,255,0.92);
|
|
3223
|
+
border-color: rgba(111,75,246,0.16);
|
|
3224
|
+
box-shadow: 0 18px 54px rgba(86,70,160,0.15);
|
|
3225
|
+
}
|
|
3226
|
+
.app-layout textarea {
|
|
3227
|
+
color: var(--text);
|
|
3228
|
+
}
|
|
3229
|
+
.app-layout .send-btn {
|
|
3230
|
+
background: linear-gradient(135deg, #6f4bf6, #796cff);
|
|
3231
|
+
color: #fff;
|
|
3232
|
+
box-shadow: 0 14px 30px rgba(111,75,246,0.24);
|
|
3233
|
+
}
|
|
3234
|
+
.workspace-modal-overlay,
|
|
3235
|
+
.mode-modal-overlay {
|
|
3236
|
+
display: none;
|
|
3237
|
+
position: fixed;
|
|
3238
|
+
inset: 0;
|
|
3239
|
+
z-index: 1400;
|
|
3240
|
+
align-items: center;
|
|
3241
|
+
justify-content: center;
|
|
3242
|
+
padding: 24px;
|
|
3243
|
+
background: rgba(25, 21, 47, 0.24);
|
|
3244
|
+
backdrop-filter: blur(14px);
|
|
3245
|
+
}
|
|
3246
|
+
.workspace-modal-overlay.open,
|
|
3247
|
+
.mode-modal-overlay.open {
|
|
3248
|
+
display: flex;
|
|
3249
|
+
}
|
|
3250
|
+
.workspace-modal,
|
|
3251
|
+
.mode-modal {
|
|
3252
|
+
width: min(620px, 100%);
|
|
3253
|
+
border-radius: 20px;
|
|
3254
|
+
background:
|
|
3255
|
+
linear-gradient(180deg, rgba(255,255,255,0.98), rgba(250,248,255,0.94));
|
|
3256
|
+
border: 1px solid rgba(111,75,246,0.16);
|
|
3257
|
+
box-shadow: 0 30px 90px rgba(60,45,130,0.24);
|
|
3258
|
+
padding: 30px;
|
|
3259
|
+
color: var(--text);
|
|
3260
|
+
position: relative;
|
|
3261
|
+
}
|
|
3262
|
+
.mode-modal {
|
|
3263
|
+
width: min(520px, 100%);
|
|
3264
|
+
background:
|
|
3265
|
+
radial-gradient(circle at 18% 8%, rgba(111,75,246,0.28), transparent 32%),
|
|
3266
|
+
linear-gradient(180deg, #211b3b, #151329);
|
|
3267
|
+
color: #fff;
|
|
3268
|
+
border-color: rgba(255,255,255,0.12);
|
|
3269
|
+
}
|
|
3270
|
+
.modal-kicker {
|
|
3271
|
+
color: var(--accent);
|
|
3272
|
+
font-size: 11px;
|
|
3273
|
+
font-weight: 800;
|
|
3274
|
+
letter-spacing: .08em;
|
|
3275
|
+
text-transform: uppercase;
|
|
3276
|
+
text-align: center;
|
|
3277
|
+
margin-bottom: 8px;
|
|
3278
|
+
}
|
|
3279
|
+
.mode-modal .modal-kicker { color: #b9aaff; }
|
|
3280
|
+
.workspace-modal h2,
|
|
3281
|
+
.mode-modal h2 {
|
|
3282
|
+
text-align: center;
|
|
3283
|
+
font-size: 24px;
|
|
3284
|
+
margin-bottom: 7px;
|
|
3285
|
+
}
|
|
3286
|
+
.workspace-modal p,
|
|
3287
|
+
.mode-modal p {
|
|
3288
|
+
text-align: center;
|
|
3289
|
+
color: var(--muted);
|
|
3290
|
+
font-size: 13px;
|
|
3291
|
+
line-height: 1.6;
|
|
3292
|
+
margin-bottom: 22px;
|
|
3293
|
+
}
|
|
3294
|
+
.mode-modal p { color: #b8b2d4; }
|
|
3295
|
+
.workspace-options,
|
|
3296
|
+
.mode-options {
|
|
3297
|
+
display: grid;
|
|
3298
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
3299
|
+
gap: 14px;
|
|
3300
|
+
}
|
|
3301
|
+
.workspace-card,
|
|
3302
|
+
.mode-card {
|
|
3303
|
+
border-radius: 16px;
|
|
3304
|
+
border: 1px solid rgba(111,75,246,0.14);
|
|
3305
|
+
background: #fff;
|
|
3306
|
+
padding: 22px 18px;
|
|
3307
|
+
cursor: pointer;
|
|
3308
|
+
text-align: center;
|
|
3309
|
+
transition: transform .18s, box-shadow .18s, border-color .18s;
|
|
3310
|
+
}
|
|
3311
|
+
.workspace-card:hover,
|
|
3312
|
+
.workspace-card.selected,
|
|
3313
|
+
.mode-card:hover,
|
|
3314
|
+
.mode-card.selected {
|
|
3315
|
+
transform: translateY(-3px);
|
|
3316
|
+
border-color: rgba(111,75,246,0.42);
|
|
3317
|
+
box-shadow: 0 18px 44px rgba(86,70,160,0.18);
|
|
3318
|
+
}
|
|
3319
|
+
.mode-card {
|
|
3320
|
+
background: rgba(255,255,255,0.08);
|
|
3321
|
+
border-color: rgba(255,255,255,0.12);
|
|
3322
|
+
color: #fff;
|
|
3323
|
+
position: relative;
|
|
3324
|
+
}
|
|
3325
|
+
.mode-card.selected::after {
|
|
3326
|
+
content: '✓';
|
|
3327
|
+
position: absolute;
|
|
3328
|
+
top: 12px;
|
|
3329
|
+
right: 12px;
|
|
3330
|
+
width: 20px;
|
|
3331
|
+
height: 20px;
|
|
3332
|
+
border-radius: 50%;
|
|
3333
|
+
background: #7b6dff;
|
|
3334
|
+
display: grid;
|
|
3335
|
+
place-items: center;
|
|
3336
|
+
font-size: 12px;
|
|
3337
|
+
}
|
|
3338
|
+
.workspace-icon,
|
|
3339
|
+
.mode-icon {
|
|
3340
|
+
width: 58px;
|
|
3341
|
+
height: 58px;
|
|
3342
|
+
margin: 0 auto 14px;
|
|
3343
|
+
border-radius: 20px;
|
|
3344
|
+
display: grid;
|
|
3345
|
+
place-items: center;
|
|
3346
|
+
color: #fff;
|
|
3347
|
+
font-size: 26px;
|
|
3348
|
+
background: linear-gradient(135deg, #6f4bf6, #9b87ff);
|
|
3349
|
+
box-shadow: 0 14px 30px rgba(111,75,246,0.24);
|
|
3350
|
+
}
|
|
3351
|
+
.workspace-card h3,
|
|
3352
|
+
.mode-card h3 {
|
|
3353
|
+
font-size: 15px;
|
|
3354
|
+
margin-bottom: 7px;
|
|
3355
|
+
}
|
|
3356
|
+
.workspace-card span,
|
|
3357
|
+
.mode-card span {
|
|
3358
|
+
display: block;
|
|
3359
|
+
color: var(--muted);
|
|
3360
|
+
font-size: 12px;
|
|
3361
|
+
line-height: 1.45;
|
|
3362
|
+
}
|
|
3363
|
+
.mode-card span { color: #c9c3e2; }
|
|
3364
|
+
.modal-footnote {
|
|
3365
|
+
color: var(--faint);
|
|
3366
|
+
font-size: 12px;
|
|
3367
|
+
text-align: center;
|
|
3368
|
+
margin-top: 18px;
|
|
3369
|
+
}
|
|
3370
|
+
.mode-close {
|
|
3371
|
+
position: absolute;
|
|
3372
|
+
top: 14px;
|
|
3373
|
+
right: 14px;
|
|
3374
|
+
border: 0;
|
|
3375
|
+
background: rgba(255,255,255,0.08);
|
|
3376
|
+
color: #c9c3e2;
|
|
3377
|
+
border-radius: 10px;
|
|
3378
|
+
width: 32px;
|
|
3379
|
+
height: 32px;
|
|
3380
|
+
cursor: pointer;
|
|
3381
|
+
}
|
|
3382
|
+
@media (max-width: 768px) {
|
|
3383
|
+
.app-layout .sidebar { background: #fff; }
|
|
3384
|
+
.workspace-options,
|
|
3385
|
+
.mode-options { grid-template-columns: 1fr; }
|
|
3386
|
+
.workspace-modal,
|
|
3387
|
+
.mode-modal { padding: 24px 18px; }
|
|
3388
|
+
}
|
|
3069
3389
|
</style>
|
|
3390
|
+
<link rel="stylesheet" href="/static/lattice-reference.css">
|
|
3070
3391
|
</head>
|
|
3071
3392
|
|
|
3072
|
-
<body>
|
|
3393
|
+
<body class="lattice-ref-chat">
|
|
3073
3394
|
<!-- 배경 장식 -->
|
|
3074
3395
|
<div class="bg-shapes">
|
|
3075
3396
|
<div class="bg-orb bg-orb-1"></div>
|
|
@@ -3098,6 +3419,13 @@
|
|
|
3098
3419
|
<div style="font-size:10.5px;color:var(--faint)">Local Workspace</div>
|
|
3099
3420
|
</div>
|
|
3100
3421
|
</div>
|
|
3422
|
+
<nav class="reference-side-nav" aria-label="Lattice AI navigation">
|
|
3423
|
+
<button class="reference-nav-item active"><i class="ti ti-home"></i><span>홈</span></button>
|
|
3424
|
+
<button class="reference-nav-item" onclick="startNewChat()"><i class="ti ti-message-circle"></i><span>채팅</span></button>
|
|
3425
|
+
<button class="reference-nav-item" onclick="openDataGraph()"><i class="ti ti-chart-dots-3"></i><span>지식 그래프</span></button>
|
|
3426
|
+
<button class="reference-nav-item" onclick="openLocalBrowser()"><i class="ti ti-file"></i><span>파일</span></button>
|
|
3427
|
+
<button class="reference-nav-item" onclick="openSetupWizard()"><i class="ti ti-settings"></i><span>설정</span></button>
|
|
3428
|
+
</nav>
|
|
3101
3429
|
<div class="sidebar-search">
|
|
3102
3430
|
<div class="sidebar-search-wrap">
|
|
3103
3431
|
<i class="ti ti-search"></i>
|
|
@@ -3133,6 +3461,7 @@
|
|
|
3133
3461
|
<div id="vpc-header-pill" class="status-pill hide-mobile"><i class="ti ti-network"></i> VPC 대기</div>
|
|
3134
3462
|
</div>
|
|
3135
3463
|
<div class="header-pills">
|
|
3464
|
+
<button class="status-pill" onclick="openModeSelector()" id="mode-pill"><i class="ti ti-layout-grid"></i> 기본 모드</button>
|
|
3136
3465
|
<div class="status-pill"><i class="ti ti-device-desktop"></i> Local</div>
|
|
3137
3466
|
<div class="lang-picker" id="header-lang-picker">
|
|
3138
3467
|
<button class="logout-btn" id="lang-btn" onclick="toggleLangMenu('header-lang-picker')" title="Language">🌐</button>
|
|
@@ -3246,14 +3575,56 @@
|
|
|
3246
3575
|
|
|
3247
3576
|
<div class="messages-viewport" id="chat-viewport">
|
|
3248
3577
|
<div class="empty-state" id="empty-state">
|
|
3249
|
-
<
|
|
3250
|
-
|
|
3251
|
-
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
<div class="
|
|
3255
|
-
|
|
3256
|
-
|
|
3578
|
+
<section class="reference-home">
|
|
3579
|
+
<div class="reference-home-head">
|
|
3580
|
+
<h1>안녕하세요, 사용자님 👋</h1>
|
|
3581
|
+
<p>Basic Mode에서 로컬 AI, 지식 그래프, 파일, 자동 설정을 한 화면에서 관리하세요.</p>
|
|
3582
|
+
</div>
|
|
3583
|
+
<div class="reference-card-grid">
|
|
3584
|
+
<article class="reference-dash-card">
|
|
3585
|
+
<div class="reference-card-icon"><i class="ti ti-activity"></i></div>
|
|
3586
|
+
<h3>AI 상태</h3>
|
|
3587
|
+
<p><span class="green-dot"></span> 실행 중</p>
|
|
3588
|
+
<div class="reference-stat-row"><span>모델</span><strong>Gemma 4 26B</strong></div>
|
|
3589
|
+
<div class="reference-progress"><span style="width:45%"></span></div>
|
|
3590
|
+
<button onclick="openModelPanel()"><i class="ti ti-cube"></i> 모델 변경</button>
|
|
3591
|
+
</article>
|
|
3592
|
+
<article class="reference-dash-card">
|
|
3593
|
+
<div class="reference-card-icon"><i class="ti ti-chart-dots-3"></i></div>
|
|
3594
|
+
<h3>지식 그래프</h3>
|
|
3595
|
+
<div class="reference-stat-row"><span>대화</span><strong>12개</strong></div>
|
|
3596
|
+
<div class="reference-stat-row"><span>파일</span><strong>5개</strong></div>
|
|
3597
|
+
<div class="reference-stat-row"><span>연결</span><strong>48개</strong></div>
|
|
3598
|
+
<button onclick="openDataGraph()"><i class="ti ti-chart-dots"></i> 그래프 보기</button>
|
|
3599
|
+
</article>
|
|
3600
|
+
<article class="reference-dash-card">
|
|
3601
|
+
<div class="reference-card-icon"><i class="ti ti-tool"></i></div>
|
|
3602
|
+
<h3>자동 설정</h3>
|
|
3603
|
+
<p>설치 가능한 도구</p>
|
|
3604
|
+
<div class="reference-big-number">3개</div>
|
|
3605
|
+
<button onclick="openSetupWizard()"><i class="ti ti-wand"></i> 설정 시작</button>
|
|
3606
|
+
</article>
|
|
3607
|
+
</div>
|
|
3608
|
+
<div class="reference-lists">
|
|
3609
|
+
<article>
|
|
3610
|
+
<header><i class="ti ti-message-circle"></i> 최근 채팅 <button onclick="startNewChat()">전체 보기</button></header>
|
|
3611
|
+
<p>Lattice AI의 기능과 활용 방법에 대해 알려줘 <span>오전 10:30</span></p>
|
|
3612
|
+
<p>RAG와 벡터 검색의 차이점은 무엇인가요? <span>어제</span></p>
|
|
3613
|
+
<p>파이썬으로 웹 크롤링하는 예제 코드 작성해줘 <span>어제</span></p>
|
|
3614
|
+
</article>
|
|
3615
|
+
<article>
|
|
3616
|
+
<header><i class="ti ti-file-text"></i> 최근 파일 <button onclick="openLocalBrowser()">전체 보기</button></header>
|
|
3617
|
+
<p>Lattice AI 사용자 가이드.pdf <span>2.4 MB</span></p>
|
|
3618
|
+
<p>AI 모델 성능 비교.xlsx <span>1.1 MB</span></p>
|
|
3619
|
+
<p>프로젝트 계획서.docx <span>856 KB</span></p>
|
|
3620
|
+
</article>
|
|
3621
|
+
</div>
|
|
3622
|
+
<div class="empty-grid">
|
|
3623
|
+
<div class="empty-chip" id="chip-file" onclick="document.getElementById('user-input').value=t('chip_file_prompt');document.getElementById('user-input').focus()"><span class="empty-chip-icon"><i class="ti ti-file-text"></i></span><span data-i18n="chip_file">파일 생성 · 코드 초안</span></div>
|
|
3624
|
+
<div class="empty-chip" id="chip-vpc" onclick="document.getElementById('user-input').value=t('chip_vpc_prompt');document.getElementById('user-input').focus()"><span class="empty-chip-icon"><i class="ti ti-shield-check"></i></span><span data-i18n="chip_vpc">VPC 보안 구성 점검</span></div>
|
|
3625
|
+
<div class="empty-chip" id="chip-kb" onclick="document.getElementById('user-input').value=t('chip_kb_prompt');document.getElementById('user-input').focus()"><span class="empty-chip-icon"><i class="ti ti-brain"></i></span><span data-i18n="chip_kb">로컬 지식 정리</span></div>
|
|
3626
|
+
</div>
|
|
3627
|
+
</section>
|
|
3257
3628
|
</div>
|
|
3258
3629
|
</div>
|
|
3259
3630
|
|
|
@@ -3291,6 +3662,48 @@
|
|
|
3291
3662
|
</main>
|
|
3292
3663
|
</div>
|
|
3293
3664
|
|
|
3665
|
+
<div class="workspace-modal-overlay" id="workspace-modal-overlay">
|
|
3666
|
+
<section class="workspace-modal" role="dialog" aria-modal="true" aria-labelledby="workspace-title">
|
|
3667
|
+
<div class="modal-kicker">Lattice AI</div>
|
|
3668
|
+
<h2 id="workspace-title" data-i18n="workspace_title">워크스페이스 선택</h2>
|
|
3669
|
+
<p data-i18n="workspace_sub">사용 목적에 맞는 시작 공간을 고르면 홈 화면과 기본 도구가 그 흐름에 맞춰 정리됩니다.</p>
|
|
3670
|
+
<div class="workspace-options">
|
|
3671
|
+
<button class="workspace-card" onclick="selectWorkspace('personal')">
|
|
3672
|
+
<div class="workspace-icon"><i class="ti ti-user"></i></div>
|
|
3673
|
+
<h3 data-i18n="workspace_personal">개인 워크스페이스</h3>
|
|
3674
|
+
<span data-i18n="workspace_personal_sub">개인 프로젝트, 로컬 파일, 지식베이스 중심</span>
|
|
3675
|
+
</button>
|
|
3676
|
+
<button class="workspace-card" onclick="selectWorkspace('company')">
|
|
3677
|
+
<div class="workspace-icon"><i class="ti ti-building-skyscraper"></i></div>
|
|
3678
|
+
<h3 data-i18n="workspace_company">회사 워크스페이스</h3>
|
|
3679
|
+
<span data-i18n="workspace_company_sub">SSO, 보안 정책, 팀 운영 대시보드 중심</span>
|
|
3680
|
+
</button>
|
|
3681
|
+
</div>
|
|
3682
|
+
<div class="modal-footnote" data-i18n="workspace_note">나중에 상단 모드 버튼에서 다시 바꿀 수 있습니다.</div>
|
|
3683
|
+
</section>
|
|
3684
|
+
</div>
|
|
3685
|
+
|
|
3686
|
+
<div class="mode-modal-overlay" id="mode-modal-overlay" onclick="if(event.target===this)closeModeSelector()">
|
|
3687
|
+
<section class="mode-modal" role="dialog" aria-modal="true" aria-labelledby="mode-title">
|
|
3688
|
+
<button class="mode-close" onclick="closeModeSelector()" title="닫기"><i class="ti ti-x"></i></button>
|
|
3689
|
+
<div class="modal-kicker">Mode Select</div>
|
|
3690
|
+
<h2 id="mode-title" data-i18n="mode_title">모드 선택</h2>
|
|
3691
|
+
<p data-i18n="mode_sub">작업 성격에 맞춰 Lattice AI의 화면 밀도와 기본 프롬프트를 전환합니다.</p>
|
|
3692
|
+
<div class="mode-options">
|
|
3693
|
+
<button class="mode-card selected" id="mode-card-default" onclick="selectMode('default')">
|
|
3694
|
+
<div class="mode-icon"><i class="ti ti-layout-dashboard"></i></div>
|
|
3695
|
+
<h3 data-i18n="mode_default">기본 모드</h3>
|
|
3696
|
+
<span data-i18n="mode_default_sub">대화, 파일 생성, 지식 정리를 한 화면에서</span>
|
|
3697
|
+
</button>
|
|
3698
|
+
<button class="mode-card" id="mode-card-code" onclick="selectMode('code')">
|
|
3699
|
+
<div class="mode-icon"><i class="ti ti-terminal-2"></i></div>
|
|
3700
|
+
<h3 data-i18n="mode_code">코딩 모드</h3>
|
|
3701
|
+
<span data-i18n="mode_code_sub">계획, 실행, 리뷰 파이프라인 중심</span>
|
|
3702
|
+
</button>
|
|
3703
|
+
</div>
|
|
3704
|
+
</section>
|
|
3705
|
+
</div>
|
|
3706
|
+
|
|
3294
3707
|
<div id="model-overlay" class="model-overlay">
|
|
3295
3708
|
<section class="model-panel">
|
|
3296
3709
|
<div class="model-panel-header">
|
|
@@ -3926,6 +4339,20 @@
|
|
|
3926
4339
|
ph_input: 'Lattice AI에게 작업을 지시하세요...',
|
|
3927
4340
|
// 파일 툴바
|
|
3928
4341
|
create_file: '파일 만들기', local_files: '로컬 파일',
|
|
4342
|
+
// 워크스페이스 / 모드
|
|
4343
|
+
workspace_title: '워크스페이스 선택',
|
|
4344
|
+
workspace_sub: '사용 목적에 맞는 시작 공간을 고르면 홈 화면과 기본 도구가 그 흐름에 맞춰 정리됩니다.',
|
|
4345
|
+
workspace_personal: '개인 워크스페이스',
|
|
4346
|
+
workspace_personal_sub: '개인 프로젝트, 로컬 파일, 지식베이스 중심',
|
|
4347
|
+
workspace_company: '회사 워크스페이스',
|
|
4348
|
+
workspace_company_sub: 'SSO, 보안 정책, 팀 운영 대시보드 중심',
|
|
4349
|
+
workspace_note: '나중에 상단 모드 버튼에서 다시 바꿀 수 있습니다.',
|
|
4350
|
+
mode_title: '모드 선택',
|
|
4351
|
+
mode_sub: '작업 성격에 맞춰 Lattice AI의 화면 밀도와 기본 프롬프트를 전환합니다.',
|
|
4352
|
+
mode_default: '기본 모드',
|
|
4353
|
+
mode_default_sub: '대화, 파일 생성, 지식 정리를 한 화면에서',
|
|
4354
|
+
mode_code: '코딩 모드',
|
|
4355
|
+
mode_code_sub: '계획, 실행, 리뷰 파이프라인 중심',
|
|
3929
4356
|
// 패널 제목
|
|
3930
4357
|
model_switcher: '모델 스위처',
|
|
3931
4358
|
model_switcher_sub: '실행 엔진을 설치하고, 엔진에 맞는 local/cloud LLM을 선택합니다.',
|
|
@@ -3965,6 +4392,20 @@
|
|
|
3965
4392
|
ph_input: 'Ask Lattice AI anything...',
|
|
3966
4393
|
// File toolbar
|
|
3967
4394
|
create_file: 'Create file', local_files: 'Local files',
|
|
4395
|
+
// Workspace / mode
|
|
4396
|
+
workspace_title: 'Select Workspace',
|
|
4397
|
+
workspace_sub: 'Choose a starting space so the home view and default tools match how you work.',
|
|
4398
|
+
workspace_personal: 'Personal Workspace',
|
|
4399
|
+
workspace_personal_sub: 'Personal projects, local files, and knowledge base',
|
|
4400
|
+
workspace_company: 'Company Workspace',
|
|
4401
|
+
workspace_company_sub: 'SSO, security policy, and team operations',
|
|
4402
|
+
workspace_note: 'You can change this later from the mode button.',
|
|
4403
|
+
mode_title: 'Mode Select',
|
|
4404
|
+
mode_sub: 'Switch Lattice AI density and defaults based on the job.',
|
|
4405
|
+
mode_default: 'Default Mode',
|
|
4406
|
+
mode_default_sub: 'Chat, file creation, and knowledge in one view',
|
|
4407
|
+
mode_code: 'Code Mode',
|
|
4408
|
+
mode_code_sub: 'Plan, execute, and review pipeline first',
|
|
3968
4409
|
// Panel titles
|
|
3969
4410
|
model_switcher: 'Model Switcher',
|
|
3970
4411
|
model_switcher_sub: 'Install a runtime engine and select a local/cloud LLM.',
|
|
@@ -4007,6 +4448,7 @@
|
|
|
4007
4448
|
localStorage.setItem('ltcai_lang', lang);
|
|
4008
4449
|
document.querySelectorAll('.lang-picker-menu').forEach(m => m.classList.remove('open'));
|
|
4009
4450
|
applyI18n();
|
|
4451
|
+
updateWorkspaceModeUi();
|
|
4010
4452
|
}
|
|
4011
4453
|
|
|
4012
4454
|
document.addEventListener('click', (e) => {
|
|
@@ -4015,6 +4457,66 @@
|
|
|
4015
4457
|
}
|
|
4016
4458
|
});
|
|
4017
4459
|
|
|
4460
|
+
function workspaceLabel(kind) {
|
|
4461
|
+
if (kind === 'company') return currentLang === 'ko' ? '회사' : 'Company';
|
|
4462
|
+
return currentLang === 'ko' ? '개인' : 'Personal';
|
|
4463
|
+
}
|
|
4464
|
+
|
|
4465
|
+
function modeLabel(mode) {
|
|
4466
|
+
if (mode === 'code') return currentLang === 'ko' ? '코딩 모드' : 'Code Mode';
|
|
4467
|
+
return currentLang === 'ko' ? '기본 모드' : 'Default Mode';
|
|
4468
|
+
}
|
|
4469
|
+
|
|
4470
|
+
function updateWorkspaceModeUi() {
|
|
4471
|
+
const workspace = localStorage.getItem('ltcai_workspace') || 'personal';
|
|
4472
|
+
const mode = localStorage.getItem('ltcai_mode') || 'default';
|
|
4473
|
+
const pill = document.getElementById('mode-pill');
|
|
4474
|
+
if (pill) pill.innerHTML = `<i class="ti ti-layout-grid"></i> ${workspaceLabel(workspace)} · ${modeLabel(mode)}`;
|
|
4475
|
+
document.querySelectorAll('.workspace-card').forEach((card, index) => {
|
|
4476
|
+
const kind = index === 1 ? 'company' : 'personal';
|
|
4477
|
+
card.classList.toggle('selected', kind === workspace);
|
|
4478
|
+
});
|
|
4479
|
+
['default', 'code'].forEach(item => {
|
|
4480
|
+
const el = document.getElementById(`mode-card-${item}`);
|
|
4481
|
+
if (el) el.classList.toggle('selected', item === mode);
|
|
4482
|
+
});
|
|
4483
|
+
}
|
|
4484
|
+
|
|
4485
|
+
function maybeShowWorkspaceModal() {
|
|
4486
|
+
updateWorkspaceModeUi();
|
|
4487
|
+
if (!localStorage.getItem('ltcai_workspace')) {
|
|
4488
|
+
document.getElementById('workspace-modal-overlay')?.classList.add('open');
|
|
4489
|
+
}
|
|
4490
|
+
}
|
|
4491
|
+
|
|
4492
|
+
function selectWorkspace(kind) {
|
|
4493
|
+
localStorage.setItem('ltcai_workspace', kind === 'company' ? 'company' : 'personal');
|
|
4494
|
+
document.getElementById('workspace-modal-overlay')?.classList.remove('open');
|
|
4495
|
+
updateWorkspaceModeUi();
|
|
4496
|
+
openModeSelector();
|
|
4497
|
+
}
|
|
4498
|
+
|
|
4499
|
+
function openModeSelector() {
|
|
4500
|
+
updateWorkspaceModeUi();
|
|
4501
|
+
document.getElementById('mode-modal-overlay')?.classList.add('open');
|
|
4502
|
+
}
|
|
4503
|
+
|
|
4504
|
+
function closeModeSelector() {
|
|
4505
|
+
document.getElementById('mode-modal-overlay')?.classList.remove('open');
|
|
4506
|
+
}
|
|
4507
|
+
|
|
4508
|
+
function selectMode(mode) {
|
|
4509
|
+
localStorage.setItem('ltcai_mode', mode === 'code' ? 'code' : 'default');
|
|
4510
|
+
updateWorkspaceModeUi();
|
|
4511
|
+
closeModeSelector();
|
|
4512
|
+
const input = document.getElementById('user-input');
|
|
4513
|
+
if (input && !input.value.trim()) {
|
|
4514
|
+
input.placeholder = mode === 'code'
|
|
4515
|
+
? (currentLang === 'ko' ? '무엇을 구현하거나 고칠까요?' : 'What should we build or fix?')
|
|
4516
|
+
: t('ph_input');
|
|
4517
|
+
}
|
|
4518
|
+
}
|
|
4519
|
+
|
|
4018
4520
|
function switchAcctTab(tab) {
|
|
4019
4521
|
['profile', 'password'].forEach(t => {
|
|
4020
4522
|
document.getElementById(`tab-${t}`).classList.toggle('active', t === tab);
|
|
@@ -6425,6 +6927,7 @@
|
|
|
6425
6927
|
|
|
6426
6928
|
document.getElementById('new-chat-btn').onclick = startNewChat;
|
|
6427
6929
|
applyI18n();
|
|
6930
|
+
maybeShowWorkspaceModal();
|
|
6428
6931
|
|
|
6429
6932
|
// Session check — redirect to /account if not logged in
|
|
6430
6933
|
(async function restoreSession() {
|
|
@@ -6808,8 +7311,28 @@
|
|
|
6808
7311
|
setTimeout(() => el.classList.add('visible'), 80 + i * 90);
|
|
6809
7312
|
});
|
|
6810
7313
|
|
|
7314
|
+
const zero = env.zero_config || {};
|
|
7315
|
+
const zeroRec = zero.recommend || {};
|
|
7316
|
+
const zeroPlan = zero.plan || {};
|
|
7317
|
+
if (zeroRec.model_id || zeroRec.runtime || zeroRec.backend) {
|
|
7318
|
+
const planCount = (zeroPlan.steps || []).length;
|
|
7319
|
+
const el = document.createElement('div');
|
|
7320
|
+
el.className = 'scan-row zero-config-row';
|
|
7321
|
+
el.innerHTML = `
|
|
7322
|
+
<span class="scan-icon">⚙️</span>
|
|
7323
|
+
<div>
|
|
7324
|
+
<div class="scan-label">Zero-Config 추천</div>
|
|
7325
|
+
<div class="scan-value">${escapeHtml([zeroRec.runtime, zeroRec.backend, zeroRec.model_id].filter(Boolean).join(' · '))}</div>
|
|
7326
|
+
<div class="scan-value" style="margin-top:4px;color:var(--faint)">${planCount ? escapeHtml(`${planCount}개 설치/검증 단계 준비됨`) : '추가 설치 단계 없음'}</div>
|
|
7327
|
+
</div>`;
|
|
7328
|
+
grid.appendChild(el);
|
|
7329
|
+
setTimeout(() => el.classList.add('visible'), 80 + rows.length * 90);
|
|
7330
|
+
}
|
|
7331
|
+
|
|
6811
7332
|
const sum = _wizRecs?.summary || {};
|
|
6812
|
-
|
|
7333
|
+
const zeroSummary = sum.zero_config || {};
|
|
7334
|
+
const recSuffix = zeroSummary.model_id ? ` · ${zeroSummary.model_id}` : '';
|
|
7335
|
+
_subtitle(`${escapeHtml(chip.name || 'Unknown')} · RAM ${env.ram_gb}GB · 여유 ${env.disk_free_gb}GB${escapeHtml(recSuffix)}`);
|
|
6813
7336
|
_footInfo(`추천 최대 모델 크기: ${sum.max_model_gb || '?'}GB`);
|
|
6814
7337
|
setTimeout(() => {
|
|
6815
7338
|
_footBtns(`
|