Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -273,12 +273,12 @@ New routers import domain services directly (`from modules.monitoring.service im
**Theme**: Night-eyes (warm brown/amber/gold), hardcoded — no theme switching. Background `#1a1308`, text `#d9c9a8`, primary amber-600, cards stone-800.

**Role-based access**:
- **Admin** (`role=admin`): full chat controls — LLM provider selector, RAG collection multi-select, system prompt editing, export (copy/md/json), branching, context files, all message actions (edit, regenerate, summarize, delete branch), session creation/deletion
- **Non-admin**: only shared chats visible (`is_shared_with_me` filter), Claude-like welcome screen, basic message actions (TTS + copy only), no branching/context/export/LLM/RAG
- **Admin** (`role=admin`): full chat controls — LLM provider selector, RAG collection multi-select, system prompt editing, export (copy/md/json), branching, context files, all message actions (edit, regenerate, summarize, delete branch), session creation/deletion. Admin-only controls live in admin panel only (not mobile).
- **Non-admin**: shared chats (`is_shared_with_me` filter), Claude-like welcome, basic message actions (TTS + copy), branching, context files, web search toggle. No LLM/RAG selectors, no export, no session deletion.

**Mobile Instances**: Admin creates `MobileAppInstance` (LLM backend, persona, system prompt, TTS, RAG) in admin panel (`/mobile-app` view). Users are assigned to instances via `ResourceShare`. On login, mobile app fetches `GET /admin/mobile/my-config` to get assigned instance config. Chat sessions use `source="mobile"` + `mobile_instance_id` for per-instance LLM/prompt routing.

**API layer** (`mobile/src/api/`): `client.ts` (base fetch), `chat.ts` (sessions/streaming/branches), `admin.ts` (LLM providers + RAG collections for admin controls).
**API layer** (`mobile/src/api/`): `client.ts` (base fetch), `chat.ts` (sessions/streaming/branches), `admin.ts` (admin-only APIs, used only by admin panel).

**Key differences from admin panel**:
- Hardcoded server URL (`https://ai-sekretar24.ru`), no user configuration
Expand Down
2 changes: 1 addition & 1 deletion admin/src/components/AccordionNav.vue
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
import WhatsAppIcon from './WhatsAppIcon.vue'
const WhatsApp = markRaw(WhatsAppIcon)

const props = defineProps<{

Check warning on line 33 in admin/src/components/AccordionNav.vue

View workflow job for this annotation

GitHub Actions / lint-frontend

'props' is assigned a value but never used. Allowed unused vars must match /^_/u
collapsed: boolean
}>()

Expand All @@ -54,7 +54,7 @@
nameKey: 'nav.group.monitoring',
icon: Activity,
items: [
{ path: '/', nameKey: 'nav.dashboard', icon: LayoutDashboard, module: 'dashboard', localOnly: true },
{ path: '/dashboard', nameKey: 'nav.dashboard', icon: LayoutDashboard, module: 'dashboard', localOnly: true },
{ path: '/monitoring', nameKey: 'nav.monitoring', icon: Activity, module: 'system', localOnly: true },
{ path: '/services', nameKey: 'nav.services', icon: Server, module: 'system', minLevel: 'manage', localOnly: true },
{ path: '/audit', nameKey: 'nav.audit', icon: FileText, module: 'audit' },
Expand Down Expand Up @@ -137,7 +137,7 @@
}, { deep: true })

// Expand group containing active route
function expandActiveGroup() {

Check warning on line 140 in admin/src/components/AccordionNav.vue

View workflow job for this annotation

GitHub Actions / lint-frontend

'expandActiveGroup' is defined but never used. Allowed unused vars must match /^_/u
for (const group of navGroups.value) {
if (group.items.some(item => item.path === route.path)) {
expandedGroups.value.add(group.id)
Expand Down
17 changes: 6 additions & 11 deletions admin/src/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ const router = createRouter({
},
{
path: "/",
redirect: { name: "chat" },
},
{
path: "/dashboard",
name: "dashboard",
component: DashboardView,
meta: { title: "Dashboard", icon: "LayoutDashboard", module: "dashboard", localOnly: true },
Expand Down Expand Up @@ -215,14 +219,7 @@ router.beforeEach((to, from, next) => {
}
} else if (to.name === "login" && authStore.isAuthenticated) {
// Already logged in, redirect to landing page
const isChatUser = authStore.isChatOnlyUser
|| (authStore.user?.role !== "admin" && Object.keys(authStore.permissions).length === 0);
const landing = isChatUser
? "chat"
: authStore.hasModule("dashboard") && !authStore.isCloudMode
? "dashboard"
: "chat";
next({ name: landing });
next({ name: "chat" });
return;
}

Expand All @@ -246,9 +243,7 @@ router.beforeEach((to, from, next) => {
if (mod && Object.keys(authStore.permissions).length > 0) {
const minLvl = (to.meta.minLevel as string) || "view";
if ((LVL[authStore.permissions[mod]] ?? 0) < (LVL[minLvl] ?? 1)) {
const landing =
authStore.hasModule("dashboard") && !authStore.isCloudMode ? "dashboard" : "chat";
next({ name: landing });
next({ name: "chat" });
return;
}
}
Expand Down
166 changes: 80 additions & 86 deletions mobile/src/components/MessageBubble.vue
Original file line number Diff line number Diff line change
Expand Up @@ -152,52 +152,49 @@ function cancelEdit() {
</svg>
</button>

<!-- Admin-only actions -->
<template v-if="isAdmin">
<!-- Edit -->
<button
class="p-1.5 rounded text-stone-500 hover:text-stone-300 transition-colors"
title="Редактировать"
@click="startEdit"
>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" /><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" />
</svg>
</button>
<!-- Edit -->
<button
class="p-1.5 rounded text-stone-500 hover:text-stone-300 transition-colors"
title="Редактировать"
@click="startEdit"
>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" /><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" />
</svg>
</button>

<!-- Save to context -->
<button
class="p-1.5 rounded text-stone-500 hover:text-stone-300 transition-colors"
title="В контекст"
@click="$emit('saveToContext', message.id, message.content)"
>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="m21.44 11.05-9.19 9.19a6 6 0 0 1-8.49-8.49l8.57-8.57A4 4 0 1 1 18 8.84l-8.59 8.57a2 2 0 0 1-2.83-2.83l8.49-8.48" />
</svg>
</button>
<!-- Save to context -->
<button
class="p-1.5 rounded text-stone-500 hover:text-stone-300 transition-colors"
title="В контекст"
@click="$emit('saveToContext', message.id, message.content)"
>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="m21.44 11.05-9.19 9.19a6 6 0 0 1-8.49-8.49l8.57-8.57A4 4 0 1 1 18 8.84l-8.59 8.57a2 2 0 0 1-2.83-2.83l8.49-8.48" />
</svg>
</button>

<!-- Summarize branch -->
<button
class="p-1.5 rounded text-stone-500 hover:text-stone-300 transition-colors"
title="Суммаризация ветки"
@click="$emit('summarizeBranch', message.id)"
>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" /><polyline points="14 2 14 8 20 8" /><line x1="16" y1="13" x2="8" y2="13" /><line x1="16" y1="17" x2="8" y2="17" /><polyline points="10 9 9 9 8 9" />
</svg>
</button>
<!-- Summarize branch -->
<button
class="p-1.5 rounded text-stone-500 hover:text-stone-300 transition-colors"
title="Суммаризация ветки"
@click="$emit('summarizeBranch', message.id)"
>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" /><polyline points="14 2 14 8 20 8" /><line x1="16" y1="13" x2="8" y2="13" /><line x1="16" y1="17" x2="8" y2="17" /><polyline points="10 9 9 9 8 9" />
</svg>
</button>

<!-- Delete branch from here -->
<button
class="p-1.5 rounded text-stone-500 hover:text-red-400 transition-colors"
title="Удалить ветку"
@click="$emit('deleteBranch', message.id)"
>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="3 6 5 6 21 6" /><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" />
</svg>
</button>
</template>
<!-- Delete branch from here -->
<button
class="p-1.5 rounded text-stone-500 hover:text-red-400 transition-colors"
title="Удалить ветку"
@click="$emit('deleteBranch', message.id)"
>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="3 6 5 6 21 6" /><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" />
</svg>
</button>
</div>

<!-- Action buttons for user messages -->
Expand Down Expand Up @@ -234,52 +231,49 @@ function cancelEdit() {
</svg>
</button>

<!-- Admin-only actions -->
<template v-if="isAdmin">
<!-- Edit -->
<button
class="p-1.5 rounded text-amber-300/50 hover:text-amber-200 transition-colors"
title="Редактировать"
@click="startEdit"
>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" /><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" />
</svg>
</button>
<!-- Edit -->
<button
class="p-1.5 rounded text-amber-300/50 hover:text-amber-200 transition-colors"
title="Редактировать"
@click="startEdit"
>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" /><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" />
</svg>
</button>

<!-- Regenerate response -->
<button
class="p-1.5 rounded text-amber-300/50 hover:text-amber-200 transition-colors"
title="Перегенерировать"
@click="$emit('regenerate', message.id)"
>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="23 4 23 10 17 10" /><path d="M20.49 15a9 9 0 1 1-2.12-9.36L23 10" />
</svg>
</button>
<!-- Regenerate response -->
<button
class="p-1.5 rounded text-amber-300/50 hover:text-amber-200 transition-colors"
title="Перегенерировать"
@click="$emit('regenerate', message.id)"
>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="23 4 23 10 17 10" /><path d="M20.49 15a9 9 0 1 1-2.12-9.36L23 10" />
</svg>
</button>

<!-- Summarize branch -->
<button
class="p-1.5 rounded text-amber-300/50 hover:text-amber-200 transition-colors"
title="Суммаризация ветки"
@click="$emit('summarizeBranch', message.id)"
>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" /><polyline points="14 2 14 8 20 8" /><line x1="16" y1="13" x2="8" y2="13" /><line x1="16" y1="17" x2="8" y2="17" /><polyline points="10 9 9 9 8 9" />
</svg>
</button>
<!-- Summarize branch -->
<button
class="p-1.5 rounded text-amber-300/50 hover:text-amber-200 transition-colors"
title="Суммаризация ветки"
@click="$emit('summarizeBranch', message.id)"
>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" /><polyline points="14 2 14 8 20 8" /><line x1="16" y1="13" x2="8" y2="13" /><line x1="16" y1="17" x2="8" y2="17" /><polyline points="10 9 9 9 8 9" />
</svg>
</button>

<!-- Delete branch from here -->
<button
class="p-1.5 rounded text-amber-300/50 hover:text-red-400 transition-colors"
title="Удалить ветку"
@click="$emit('deleteBranch', message.id)"
>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="3 6 5 6 21 6" /><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" />
</svg>
</button>
</template>
<!-- Delete branch from here -->
<button
class="p-1.5 rounded text-amber-300/50 hover:text-red-400 transition-colors"
title="Удалить ветку"
@click="$emit('deleteBranch', message.id)"
>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="3 6 5 6 21 6" /><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" />
</svg>
</button>
</div>
</template>
</div>
Expand Down
Loading
Loading