Commit Graph

107 Commits

Author SHA1 Message Date
wizardchen 15b81d1581 fix(agent): gate web search controls by provider readiness 2026-07-08 00:26:34 +08:00
wizardchen 3209ed77fd feat(quick-qa): add references drawer and polish retrieval source UI
Add a side panel for web and knowledge-base citations with citation-badge
highlighting, refine collapsed RAG pipeline summary layout, and emit
knowledge_base_id from agent knowledge_search results.
2026-07-08 00:26:34 +08:00
wizardchen 45eab4a95f fix(quick-qa): distinguish web and knowledge base retrieval in pipeline UI
Emit search_source metadata from RAG progress events so quick-answer steps,
summaries, and IM labels no longer mislabel web-only results as knowledge base search.
2026-07-08 00:26:34 +08:00
wizardchen 8d40959f88 fix lint and test failures 2026-07-01 17:31:42 +08:00
wizardchen 4588e95ba3 fix(frontend): hide redundant card badges when section headers apply
Suppress duplicate origin, builtin, role, and org-name pills on knowledge
base, agent, and organization list cards when the visible group header or
sidebar filter already conveys the same information.
2026-06-26 16:55:44 +08:00
wizardchen 5f2ca6c975 fix(agent): reconcile agent stream mode and shared-agent readiness UX
Derive stream pipeline from selectedAgentId to fix quick-answer/isAgentEnabled drift, gate configure actions for shared agents, and polish selector detail panel positioning.
2026-06-25 23:33:39 +08:00
wizardchen 47478491c9 fix(agent): address readiness review findings
Tighten shared-agent readiness checks, surface not-ready toasts in the
selector, validate chat-model overrides in resolveChatModelID, and
improve configure deep-links for shared agents.
2026-06-25 23:33:39 +08:00
wizardchen 9ca4e1f23a feat(agent): enforce model readiness and polish selector UX
Block chat when agents lack an explicit chat or rerank model, guide users
through the selector and editor with field highlight, and align session QA
checks with the same readiness rules on backend and frontend.
2026-06-25 23:33:39 +08:00
wizardchen 2c44a41f2a feat(models): add model test debugger for saved model configs
Let admins send real requests against configured chat, embedding, rerank,
VLM, and ASR models from settings, with thinking controls shown only when
the model supports them.
2026-06-25 17:05:33 +08:00
wizardchen 635d7c9643 feat(integrations): polish embed/IM channel editors and agent rebind
Align embed channel setup with a step wizard, simplify deploy layout,
and allow changing bound agents on update for embed and IM channels.
2026-06-24 20:09:19 +08:00
wizardchen 8ada130ee1 fix(frontend): enhance repairFlankingEmphasis to handle opening delimiters correctly
- Update regex patterns to account for opening delimiters preceded by letters/numbers and followed by punctuation, ensuring proper rendering of emphasis in markdown.
- Add tests to validate new behavior for various edge cases, including punctuation-adjacent emphasis and exponent markers.
- Improve overall markdown rendering consistency in chat components.
2026-06-22 12:31:34 +08:00
wizardchen 483f507104 feat(frontend): add wiki tool support and enhance agent tool icon mapping
- Implement `getWikiPageText` function to handle persisted slugs and JSON input for wiki page text retrieval.
- Update `getAgentToolIconName` to include mappings for `wiki_search` and `wiki_read_page` tools.
- Enhance tests to cover new functionality for wiki tools and ensure proper icon mapping in the agent stream display.
- Modify `AgentStreamDisplay` to utilize new wiki tool features and improve localization for wiki-related actions.
2026-06-22 12:25:28 +08:00
wizardchen cc9de85c25 feat(frontend): enhance chat streaming visuals with shimmer effect and fade tail
- Introduce a shimmer effect for in-progress step titles in chat components, providing visual feedback during processing.
- Implement a trailing fade effect for the most recently streamed characters in chat markdown, enhancing the typing experience.
- Update CSS styles to support the new shimmer and fade effects, ensuring smooth transitions and visual coherence.
- Add tests to verify the functionality of the shimmer effect and the application of the fade tail in markdown rendering.
2026-06-22 10:48:53 +08:00
wizardchen 58461a5b68 feat(frontend): enhance chat markdown rendering and streaming behavior
- Introduce functions to stabilize rendering of dangling inline markers during streaming, preventing flickering and layout shifts.
- Implement tagging for standalone strong paragraphs to ensure consistent styling as subtitles.
- Update CSS for chat components to improve animation smoothness and visual feedback during typing.
- Add tests for new markdown rendering features, including handling of incomplete emphasis and citation tags.
2026-06-22 10:48:53 +08:00
wizardchen 80bcf200b6 feat(frontend): enhance chat image handling and typewriter effect
- Introduce a stable skeleton box for protected images during loading to prevent flickering.
- Implement a new composable `useStickyBottomOnResize` to maintain chat scroll position as content loads.
- Add `useTypewriter` for smoother text rendering in chat, improving user experience during streaming.
- Create a directive `vStableHtml` to efficiently update HTML content without losing image states.
- Enhance chat markdown rendering to handle incomplete citation tags and trailing horizontal rules during streaming.
- Add tests for new typewriter functionality and citation handling.
2026-06-18 18:42:16 +08:00
wizardchen 4e2d568149 feat(frontend): polish chat suggestions, citations, and drawers
- unify suggested-question styling across chat entry points
- keep citation markers inline with their preceding list content
- prevent manual editor viewport shifts and synchronize drawer motion
- align embedded preview and editor drawers in the body stacking context
2026-06-18 18:42:16 +08:00
wizardchen e0d3c1dafd feat(frontend): improve manual knowledge editor and chat citation rendering
- Replace manual knowledge editor dialog with SettingDrawer and refine toolbar/footer layout
- Add draft status resolution for manual knowledge items in the knowledge base
- Fix citation placement near fenced code blocks and add regression tests
- Update ChatRequestInfoButton icon and chat message/citation styles
- Add i18n strings for manual knowledge editor features
2026-06-17 20:52:37 +08:00
wizardchen e76738d054 feat(wiki): implement folder management features in wiki API
Add new API functions for managing wiki folders, including creating, updating, deleting, and listing folders. Introduce a new WikiFolder interface to represent folder structure and enhance the WikiBrowser component with folder actions. Update internationalization strings for folder-related actions in English, Korean, Russian, and Chinese locales. Refactor existing code to accommodate folder hierarchy and improve user experience in the wiki browser.
2026-06-16 23:51:29 +08:00
FFFFFFpy 6d07e20204 fix(wiki): use placeholder src for protected provider images to avoid failed initial loads 2026-06-16 12:24:01 +08:00
FFFFFFpy e21a5da422 feat: add EPUB and MHTML document support 2026-06-16 11:25:27 +08:00
wizardchen c6f1b54f73 feat(chat): refactor agent stream display and tool result rendering
Add RagPipelineProgress timeline, simplify AgentStreamDisplay structure,
group grep hits per document, and add KnowledgeChunksList tool result UI.
2026-06-16 01:21:19 +08:00
wizardchen 05f39b859f feat(chat): add citation popover and chunk caching
Introduce ChatCitationFloat hover UI, session-scoped citation chunk cache,
and unified citation markdown handling for main chat and embed views.
2026-06-16 01:09:55 +08:00
wizardchen ee1c3c732c feat(chat): add shared markdown rendering pipeline
Extract chat markdown styles, renderer, DOMPurify config, syntax
highlighting, and mermaid support into reusable utilities with tests.
2026-06-16 01:09:55 +08:00
wizardchen 08852ab19d feat(embed): add widget, visitor chat, and management UI (#1657)
Add embed.html entrypoint, floating widget SDK, secure-mode snippets,
management panel with preview, visitor chat composables, citation rendering,
and integration docs for subdomain and server-side token exchange.
2026-06-12 23:10:39 +08:00
wizardchen ad27ed134e feat(i18n): update WeKnoraCloud integration and enhance model management
- Revised usage steps in English, Korean, Russian, and Chinese localization files for clarity on saving credentials and adding cloud models.
- Introduced a new section in WeKnoraCloudSettings.vue to display the status of cloud model integration based on credential configuration.
- Added utility functions for managing WeKnoraCloud models, including model configuration and existing model checks.
- Enhanced ModelSettings.vue to improve model management actions and confirm deletion prompts.
- Implemented logic to handle adding cloud models with success and failure notifications.
2026-06-10 20:52:39 +08:00
wizardchen b820e690f0 fix(auth): allow anonymous access to share-link endpoints (#1617)
The global Auth middleware allowlist (noAuthAPI) was missing the
share-link routes, so an unauthenticated invitee opening /register?token=
hit a 401 on /auth/invitations/lookup and the frontend bounced them to
/login instead of showing the register page. Add both share-link
endpoints to the allowlist and stop the request interceptor from treating
their 401s as a session-expiry redirect.

Refs: https://github.com/Tencent/WeKnora/issues/1617
2026-06-05 18:51:32 +08:00
wizardchen e2a41ecf0a feat(thinkingControl): implement thinking mode configuration in model editor
- Added a new thinking mode control field in the ModelEditorDialog, allowing users to specify how the agent's thinking mode is formatted for API requests.
- Introduced localization strings for thinking mode labels and descriptions in English, Korean, Russian, and Chinese, enhancing user experience across multiple languages.
- Updated the model form data structure to include thinking control settings, ensuring proper handling during model edits and saves.
- Implemented utility functions for resolving and defaulting thinking control values based on provider and model, improving backend integration.
- Added tests for the new thinking control functionality to ensure reliability and correctness in handling user configurations.
2026-06-05 14:56:48 +08:00
jackson.jia 10383c6ddd fix(frontend): pass {size} param to fileSizeExceeded i18n on Nginx 413
The Nginx 413 error handler in request.ts calls t('error.fileSizeExceeded')
without the required {size} parameter, causing the toast to display
"文件大小不能超过 M!" instead of "文件大小不能超过 50M!".

Export MAX_FILE_SIZE_MB from utils/index.ts and pass it as {size} to the
i18n call, matching the sibling call site in kbFileTypeVerification().
2026-06-04 17:23:50 +08:00
wizardchen 2714ab18f3 feat(security): implement throttling for protected file fetch retries
- Added a mechanism to throttle retries for failed file fetches, preventing excessive 404 requests during streaming.
- Introduced a cooldown period for re-fetching files that previously failed, improving performance and user experience.
- Implemented a function to clear the failure cache, allowing immediate retries after streaming ends.
- Updated the `hydrateProtectedFileImages` function to utilize the new throttling logic, ensuring efficient image loading.
2026-06-04 15:48:04 +08:00
wizardchen d38a6efd87 refactor(agent): remove final_answer tool references and update related logic
- Eliminated all instances of the final_answer tool from the agent's configuration and logic, transitioning to a model where the agent concludes responses with plain text instead.
- Updated event handling and response analysis to reflect this change, ensuring that the agent's output is now directly delivered as text without relying on a dedicated final answer tool.
- Adjusted localization strings across multiple languages to remove references to final_answer, enhancing clarity and consistency in user-facing messages.
- Improved the overall structure of the agent's response handling to streamline the process and reduce potential confusion regarding tool usage.

refactor(agent): streamline answer handling and preamble logic

- Updated the agent's response handling to treat any text streamed before a tool call as a preamble, ensuring it is not included in the final answer.
- Removed the superseded marker logic from the event emission process, simplifying the flow of answer content and enhancing clarity in the UI.
- Adjusted the event handling to ensure that preamble segments are correctly retracted and relocated into the steps tree, improving the overall user experience.
- Enhanced the agent's internal logic to better manage answer segments and their states during streaming, leading to a more coherent response structure.
2026-06-04 15:48:04 +08:00
wizardchen bd1a764a91 feat(chat): add request info button and debug payload for stream requests
- Introduced a new `ChatRequestInfoButton` component to display detailed request information for chat sessions.
- Enhanced the `useStream` function to track the last stream request, including request ID, URL, method, and sanitized body.
- Updated localization files to include new strings for request information in both English and Chinese.
- Integrated the request info button into the chat interface, allowing users to easily access and copy request details.
- Improved handling of stream requests by attaching debug information to messages for better tracking and debugging.
2026-06-04 15:48:04 +08:00
langcaiye 2caa1e0508 fix: allow slower datasource resource listing 2026-06-04 15:32:06 +08:00
wizardchen f4af9cca97 feat(contextualGuides): add multiple contextual guide components for agent and knowledge base creation
- Introduced new components: AgentCreateContextualGuide, KbCreateContextualGuide, TenantModelsGuide, and SpotlightGuide to enhance user onboarding.
- Implemented dynamic step configurations for each guide, allowing tailored user experiences based on context.
- Enhanced the existing NewUserGuide component to utilize the new SpotlightGuide for improved visual guidance.
- Updated localization files to include new strings for contextual guides, ensuring a comprehensive user experience across languages.
- Refactored existing components to integrate with the new guide system, improving maintainability and user interaction.
2026-06-03 14:42:46 +08:00
wizardchen ef1047bf67 feat(parser): add OpenDataLoader, PaddleOCR-VL engines, and parser improvements
Introduce opendataloader and PaddleOCR-VL parser engines with tenant-level
settings UI, replace liteparse, and harden Excel/PPT/Markdown parsing.
Optional odl-hybrid sidecar stays local-build only and is excluded from
default dev-start and full profiles.
2026-06-03 12:29:13 +08:00
wizardchen 4e58dd42cc feat(knowledge-base): integrate trace availability checks and enhance UI interactions
This commit introduces a new utility function, `knowledgeSpansPayloadHasTrace`, to determine if the knowledge spans data contains a valid trace. Key changes include:

1. Updated the `KnowledgeBase` component to utilize the new trace availability checks, improving the logic for displaying trace-related UI elements.
2. Enhanced the `fetchSpans` function in the `knowledge-processing-timeline` component to emit trace availability based on the new utility.
3. Implemented caching for trace availability to optimize performance and reduce unnecessary API calls.

These changes aim to improve user experience by providing accurate trace information and enhancing the overall responsiveness of the UI.
2026-05-28 15:26:53 +08:00
wizardchen 30332cca99 fix(frontend): correct floating UI positioning under root zoom
The user font-size preference applies CSS `zoom` on `<html>`
(see `composables/useFont.ts`). This breaks every popover that
anchors itself with `getBoundingClientRect()` + `position: fixed/absolute`,
because the rect is in visual pixels while CSS lengths are then
multiplied by zoom again — shifting popovers toward the lower-right
and miscomputing maxHeight / width / viewport-edge clamping.

PR #1459 patched only `AgentSelector.vue` (and left its width/maxHeight
unfixed). This PR introduces a shared helper `frontend/src/utils/zoom.ts`
(`getRootZoom`, `rectToCssPx`, `cssViewportSize`) and applies it to every
affected popover:

- `AgentSelector.vue` — refactored to use the helper; also normalizes
  `width` and `maxHeight` (previously still in visual px).
- `Input-field.vue` — model dropdown, mention popup (typed @ and button-
  triggered), and agent-mode dropdown.
- `KnowledgeBaseSelector.vue` — primary anchor path and fallback path.
- `UserMenu.vue` — tenant and IM floating submenus + viewport clamp.
- `FAQTagTooltip.vue` — fixed tooltip positioning + edge clamp.
- `AgentEditorModal.vue` — placeholder popups for system_prompt,
  context_template, and rewrite/fallback prompts.
- `AgentStreamDisplay.vue` — `kb-float-popup` (absolute under body, also
  under the zoom containing block).

Verified with `npm --prefix frontend run build`.
2026-05-24 23:03:26 +08:00
MidnightSun 6210f44fb6 fix(docparser): preserve MinerU markdown and persist relative images
MinerU already returns markdown with embedded HTML blocks, but the current\nreader runs the whole document back through html-to-markdown. That\nsecond conversion escapes valid headings and image syntax, so chunk\nprofiling sees plain text instead of markdown structure and relative\nimage references stop matching the storage pipeline.\n\nKeep MinerU output in its original markdown form and only apply narrow\ncompatibility normalization for the specific over-escaped patterns we\nactually need to recover. The converter now matches image refs by the\npaths that are really present in markdown or embedded HTML instead of\nassuming a single images/<name> form.\n\nExtend ImageResolver so relative HTML <img src=...> references share the\nsame storage rewrite path as markdown images, deduplicate repeated saves,\nand keep the frontend sanitizer compatible with MinerU's details/summary\nblocks. Add focused docparser tests that cover escaped markdown repair,\nvariant image path matching, and relative HTML image persistence.
2026-05-21 11:39:57 +08:00
wizardchen 9f6148784a fix(frontend): improve offline and legacy browser support 2026-05-21 11:19:44 +08:00
wizardchen 4344765cf9 feat(i18n): enhance notification templates with raw message handling
Updated the notification system to utilize the `tm` function for template resolution, ensuring that placeholders like `{name}` and `{role}` remain intact for proper rendering. This change improves the display of workspace and role information in login and tenant switch notifications, allowing for better localization and visual consistency across the application. Adjustments were made in `App.vue`, `Login.vue`, and related utility functions to accommodate the new template handling.
2026-05-18 20:37:57 +08:00
wizardchen 559b5a6e20 feat(ui): render workspace-context notifications with styled chips
The login-success and tenant-switch toasts previously showed the
workspace name and role inline as bracketed plain text, which read
flat and made the two key data points hard to scan at a glance.

Render them through a shared `renderWorkspaceNotifyContent` helper
that produces a NotifyPlugin VNode with:

* a neutral rounded chip for the workspace name (with a generic
  workspace icon), and
* a role-coloured chip for the role (with the existing per-role icon
  from useRoleLabel), so owner / admin / contributor / viewer each
  get a distinct visual identity that matches the role badges used
  elsewhere in the product.

The i18n templates lose the surrounding 「」 / "" / «» quote marks
because the chip itself now provides the visual delineation; double
emphasis looked off. Translators control the surrounding wording via
`{name}` and `{role}` placeholders and the renderer splits on those
markers to interleave plain text and chips in the original order.

The PendingTenantSwitchToast payload (sessionStorage-stashed for the
hard-reload survival trick) grows a `roleEnum` field so the post-
reload toast can colour the chip — without that, the switch toast
would fall back to a neutral chip while the login toast got the
colour treatment.

Note on icon resolution: the chip renderer imports TDesign's `Icon`
component directly rather than referencing it by string tag in `h()`
— Vue's render function does not auto-resolve component names the
way templates do, so `h('t-icon', ...)` would silently render an
unknown HTML element.
2026-05-18 20:37:57 +08:00
wizardchen 60a579d869 feat(auth): rich workspace-aware notification on successful login
Replace the plain "Login successful" toast with a TDesign Notify card
that surfaces the workspace the user just landed in and their role
there, so users immediately see which space they're working in —
especially useful now that login can drop them into a remembered
non-home tenant.

A small shared helper (utils/loginNotify.ts) handles both the password
login path (views/auth/Login.vue) and the OIDC callback path
(App.vue handleGlobalOIDCCallback), so the two flows stay consistent.
Role label goes through the same useRoleLabel composable used by the
rest of the role-aware UI, so locale + future role-name tweaks live in
one place. The membership lookup falls back gracefully (no role line)
when the active tenant isn't in the response's memberships list — e.g.
the auto-setup path that synthesises a single owner row.

The legacy auth.loginSuccess key is left in place; nothing else
references it, so a future cleanup PR can drop it safely.
2026-05-18 20:37:57 +08:00
wizardchen 0cdb922d84 feat(tenant): remember user's last-active workspace across logins
Until now a fresh login (new device, expired refresh token, cleared
browser) always dropped the user into their home tenant, even if they
spend most of their time in a peer workspace. The session-local
X-Tenant-ID override in localStorage gave a "same browser sticky"
effect, but never crossed devices or new sessions.

This adds a small server-side preference, `users.preferences.
last_active_tenant_id`, persisted in the existing jsonb column (no
new migration), and threads it through:

* Backend
  * `UserPreferences` gains `LastActiveTenantID *uint64` with sentinel
    semantics (`*0` from the PATCH endpoint = clear preference).
  * `resolveLoginTenantID` validates the stored id (tenant still
    exists + active membership, or CanAccessAllTenants) and falls
    back to home on any failure, best-effort clearing the stale
    preference so subsequent logins don't pay for it again.
  * `Login` and `LoginWithOIDC` resolve once and use the result for
    both the JWT `tenant_id` claim and the returned `active_tenant`,
    keeping the two in sync. `RefreshToken` rides through
    `GenerateTokens` so refresh rotations also land the user back in
    their preferred tenant instead of bouncing to home.
  * `UpdateUserPreferences` learns to merge the new key.
  * `PUT /auth/me/preferences` accepts the new field.

* Frontend
  * `Login.vue` now writes the user's HOME tenant id into
    `user.tenant_id` (matching the field's documented semantics) and
    expresses any active-vs-home divergence via `setSelectedTenant`,
    so `useHomeTenant` and the "current"/"home" badges stay correct
    after the backend honours a remembered preference. `App.vue`'s
    OIDC sync does the same reconciliation.
  * `TenantSelector`, `UserMenu` and the post-tenant-create handlers
    fire `persistLastActiveTenantPreference` after every successful
    user-initiated switch (switching to home sends `0` to clear).
    The call is raced against the existing reload-grace window so
    most writes finish before the page tears down; lost writes are
    recoverable on the next switch.

No new UI. Users will simply notice that, after re-logging in on
another device, they land back in the workspace they were last
using rather than always in their home tenant.

Note: `make docs` is unrelated-broken on `main` (audit_log.go
references `errors.AppError` which swag can't resolve), so the
Swagger artifacts under docs/ are intentionally not regenerated
in this PR. The handler code is the source of truth.
2026-05-18 20:37:57 +08:00
wizardchen 0655b545be feat(tenant): show rich workspace-switch confirmation that survives reload
Replace the lightweight "switch success" message with a richer
NotifyPlugin notification that reports the new workspace name and the
user's role in it. Because the post-switch flow does a hard reload,
the notification is stashed in sessionStorage before navigation and
consumed by App.vue on the next mount, so the toast actually appears
on the destination page with its full 6s duration instead of being
torn down a frame after it is shown.

For the cross-tenant superuser path (TenantSelector), the role line is
omitted when the user has no membership row in the target tenant,
avoiding a misleading empty/raw role value. Role labels are formatted
through the shared useRoleLabel composable so any future role text
change still lives in one place.

i18n keys updated across zh-CN, en-US, ko-KR, ru-RU.
2026-05-18 19:39:53 +08:00
Li Xianggang b3dbf86bf5 feat(obs): 支持华为云obs存储 2026-05-18 19:38:23 +08:00
wizardchen 4ca5469d1e refactor(tenant-switch): unify tenant switch navigation to always redirect to KB list
Updated the tenant switch logic to consistently redirect users to the platform's knowledge base list after a tenant switch, simplifying the navigation experience. Removed the previous handling of tenant-scoped routes, ensuring a more predictable behavior during tenant transitions. This change enhances user experience by avoiding potential empty states on reload.

Refs: #1303
2026-05-18 17:28:58 +08:00
wizardchen 854cb0c2a1 feat(ui): redirect tenant switch away from tenant-scoped routes
Switching the active tenant triggers window.location.reload() to
re-key every cached store / open SSE stream / in-flight request.
The catch: when the user is currently sitting on a route whose URL
embeds a tenant-scoped resource id, the new tenant lands on a
404/403 and the user sees a blank screen.

Three risky route shapes today:

  /platform/knowledge-bases/:kbId
  /platform/knowledge-bases/:kbId/creatChat
  /platform/chat/:chatid

Add a tiny tenantSwitch utility (navigateAfterTenantSwitch) that
matches the current path against this list and redirects to
/platform/knowledge-bases — the platform default landing, always
renderable regardless of role. Anything else (settings, agent
list, KB list, etc.) continues to reload its current path because
those views handle empty/forbidden data gracefully.

Both tenant-switch call sites (TenantSelector and UserMenu) use
the helper so the matrix lives in one place; future tenant-scoped
routes only need to add a regex to the list.
2026-05-18 17:28:58 +08:00
wizardchen b9a1ce7617 fix(rbac): drop X-Tenant-ID short-circuit in SSE / fetch paths
The previous PR removed the
"selectedTenantId === weknora_tenant.id → skip header" short-circuit
from the axios interceptor, but the same copy-pasted logic lived in
three more places that bypass axios:

- `api/chat/streame.ts` — `fetchEventSource` for the streaming chat
  endpoint. Without this fix the chat reply would 404 with
  "流式连接失败:HTTP 404" on the first message after switching to
  a non-home tenant: the SSE call landed on the home tenant where
  the freshly-created session did not exist.
- `api/initialization/index.ts` — native `fetch` for multimodal
  test (FormData) requests. Misroutes the test to the home tenant.
- `utils/security.ts` — `getProtectedFileRequestHeaders` used by the
  Markdown image proxy. Authenticated file fetches landed on the
  home tenant, breaking image rendering after a tenant switch.

All three now mirror the simplified rule: if `weknora_selected_tenant_id`
is set, attach `X-Tenant-ID` unconditionally. The server's
`IsTenantAccessible` already accepts a header pointing at the user's
home tenant, so always attaching is safe.

Same root cause as the axios fix: any code path that writes the
active tenant into `weknora_tenant` (UserMenu's `loadUserInfo`, OIDC
sync, router hydrate) made the two values equal, after which these
non-axios paths silently dropped the header and re-routed to home.
2026-05-18 17:28:58 +08:00
wizardchen 1a46fcf8ca fix(rbac): role-aware UI gates leaked write affordances after tenant switch
When an Owner of tenant A invited user B as a Viewer, B could log in,
switch the active tenant from B's home to A via the user menu, and
still see every write button — Create KB, Upload Document, Edit/Delete
agent — because the role-gate plumbing on the client was wired to the
wrong tenant. The server's RBAC enforcement (PR 2 / PR 5) still blocked
the actual mutations with 403, so no data leaked, but the UI presented
authority the user did not have, which is a confusing and embarrassing
defect.

Five distinct root causes, all on the client / server boundary:

1. `currentTenantRole` (frontend/src/stores/auth.ts) read
   `tenant.value.id` — the user's *home* tenant — instead of the active
   tenant id. After switching to A, the helper still returned B's home
   role (Owner), so every `hasRole(...)` gate in the codebase silently
   short-circuited. Fix: read `selectedTenantId` first, fall back to
   `tenant.id`.

2. `setMemberships` was only called once, on /auth/login. Hard reloads
   (which the tenant switcher triggers) re-ran `getCurrentUser()` via
   `App.vue` and `router/index.ts`, but those callers discarded the
   `memberships` field of the response, so the auth store kept the
   login-time snapshot forever. Role changes between sessions stayed
   invisible. Fix: extract memberships in both /auth/me consumers and
   feed them into `setMemberships`.

3. `KnowledgeBase.vue`'s `isOwner` compared `kb.tenant_id` to the
   active tenant id, so any KB inside the current tenant was treated
   as "owned by the caller" — bypassing every role gate below. Fix:
   compare against `kb.creator_id` (the field PR 5 introduced) and
   require an actual creator match. `canEdit` / `canManage` now layer
   `hasRole('admin')` on top so a non-creator with sufficient role can
   still manage.

4. `KnowledgeBaseList.vue` and `AgentList.vue` rendered the per-card
   more-menu (Settings, Delete, Edit) unconditionally. With the
   ownership column from PR 5 this is straightforward to gate on the
   client: Settings/Delete now require creator-match or `hasRole('admin')`
   per the server's `OwnedKBOrAdmin` / `OwnedAgentOrAdmin` matrix.

5. The axios interceptor (frontend/src/utils/request.ts) had a
   "selectedTenantId === defaultTenantId → don't attach X-Tenant-ID"
   short-circuit. Any code that wrote the active tenant into
   `weknora_tenant` (UserMenu's loadUserInfo, OIDC sync, router
   hydrate) made the two values equal, after which the header silently
   stopped attaching and subsequent navigation requests landed on the
   home tenant. Fix: drop the short-circuit; always attach when
   selectedTenantId is set.

Server-side, /auth/me read `user.TenantID` (the immutable home tenant
id stamped at signup) when fetching the tenant for the response, so
the `tenant` field always pointed at home even after the auth
middleware had already resolved an active tenant from X-Tenant-ID.
The frontend then re-keyed `authStore.tenant` to the home tenant on
every refresh, undoing the switch. Fix: read the active tenant id from
context (`types.TenantIDFromContext(ctx)`) and only fall back to
user.TenantID when context is unset.

The server-side enforcement was correct throughout — every fix here is
purely about not lying to the user with the rendered UI.
2026-05-18 17:28:58 +08:00
wizardchen d199628701 fix(agent): exclude wiki-only KBs from quick-answer (RAG) mode
Quick-answer agent mode retrieves purely through vector/keyword chunk
search and ships with no `allowed_tools`, so the existing capability
filter (which only reads from `allowed_tools`) let wiki-only KBs through
in every entry point. End result: users could @-mention, select, and
receive suggested questions from wiki-only KBs in quick-answer mode,
but the underlying retrieval always returned empty.

Treat "RAG-only" as an implicit property of `agent_mode = quick-answer`
and union it with the tool-derived filter. The same predicate is now
used everywhere the user can pick or be steered toward a KB:

Backend
- `tools.DeriveKBFilterForAgent` / `KBSatisfiesAgentRequirements`
  layer the implicit quick-answer requirement on top of tool derivation.
- `ListKnowledgeBases`, `SearchKnowledge` (shared-agent `@file`),
  `resolveKnowledgeBasesFromAgent` (chat runtime), `/search` IM command,
  and `GetSuggestedQuestions` now all use the agent-mode-aware variant.
- `GetSuggestedQuestions` also skips the wiki-page fallback for
  quick-answer agents to cover the `selected` / explicit-kb-ids paths
  where a wiki-only KB could still slip through.

Frontend
- `deriveKbFilterForAgent` / `kbSatisfiesAgentRequirements` mirror the
  Go helpers.
- `@` mention dropdown (`Input-field.vue`) uses the new helper.
- Agent editor's "specified KB" picker (`AgentEditorModal.vue`) grays
  out wiki-only KBs for quick-answer agents with a tooltip, and the
  pre-save warning fires for quick-answer mode too.
- i18n: add `agentEditor.agentType.kbMismatch.quickAnswer` across all
  four locales.
2026-05-12 16:27:28 +08:00
wizardchen 921e4c015a fix(agent): hide trailing thinking event when it duplicates final answer
The natural-stop path on the backend (observe.go Case 1) emits the same
content twice: once as streaming thinking chunks (from
streamThinkingToEventBus's per-chunk callback) which the frontend merges
into a single thinking event, and once as one big EventAgentFinalAnswer.
The result is that the intermediate-steps tree contains a thinking card
whose content is identical to the answer card rendered below it.

Detect this duplication and hide the offending thinking event from the
tree:

- New utils `normaliseForComparison` and `thinkingEqualsAnswer` perform
  a tolerant comparison: strip <think>…</think> blocks (which leak into
  raw thinking chunks but not into the post-StripThinkBlocks answer),
  strip final-answer wrappers, collapse whitespace, then exact-equal or
  ±2% length with matching head/tail.
- `hiddenThinkingEventIds` (replacing the previous single-id
  `promotedThinkingEventId`) now collects two cases of duplicate
  thinking: the legacy promotion fallback (no answer event present) and
  the natural-stop content-match case.

The final_answer-tool path is unaffected because reasoning thinking
events ("我找到了…让我整理…") and the answer payload have different
content and don't match the equivalence check.
2026-05-07 17:33:03 +08:00