Commit Graph

87 Commits

Author SHA1 Message Date
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
wizardchen 4677caba01 fix(agent): unify answer rendering when model skips final_answer tool
Many models (especially smaller or non-OpenAI-style ones) do not reliably
call the structured final_answer tool, even when the system prompt
explicitly requires it. Two visible symptoms in the agent UI:

1. The natural-stop path emits the answer as a final_answer event whose
   content is wrapped in <answer>...</answer>, <final_answer>...</final_answer>,
   or prefixed with "Final Answer:" / "最终答案:". These wrappers were
   rendered verbatim into the answer card.

2. When no answer event arrives at all, the trailing thinking event was
   surfaced via the legacy fallback but kept its collapsed "思考" card
   styling instead of rendering as a proper answer.

This change adds a small unwrap helper and wires it through the answer
rendering path:

- New util `unwrapFinalAnswerWrappers` strips conservative outer wrappers
  (XML-style answer tags, fenced ```final_answer code blocks, and leading
  "Final Answer:" / "最终答案:" prefixes) only when they cover the entire
  trimmed content, so user markdown that happens to contain similar text
  is left alone.
- `renderAnswerContent` and `getActualContent` apply the unwrap before the
  markdown renderer / clipboard copy, so users see and copy clean text.
- The legacy "promote trailing thinking to final answer" fallback now
  synthesizes a virtual answer event so it renders with the answer card
  UI (expanded markdown + copy/add toolbar) instead of the collapsed
  thinking card. The promoted thinking event is hidden from the
  intermediate-steps tree to avoid duplication.
2026-05-07 17:33:03 +08:00
wizardchen d46a51cf6e fix(security): forbid <style> in sanitized document HTML
DOMPurify was configured with USE_PROFILES.svg, which implicitly allows
<style> tags so that inline SVG styling works. User-authored markdown
rendered via v-html therefore let a pasted nginx error page's
<style>body { width: 35em; margin: 0 auto }</style> through the
sanitizer and apply as global CSS, squashing the entire app layout.

Add 'style' to FORBID_TAGS so top-level style elements from document
content are dropped regardless of the SVG profile.
2026-05-06 16:41:20 +08:00
toy0116 05d35c904b feat(frontend): respect BASE_URL so the SPA works behind a path-prefix reverse proxy
When WeKnora is mounted under a sub-path (Kubernetes Ingress with a
path-prefix rule, an Nginx `location /weknora/` block, a Cloudflare
Tunnel route, or any other reverse-proxy gateway), the frontend's
`getApiBaseUrl()` currently returns `''` and axios issues `/api/v1/...`
requests at the origin root — bypassing the sub-path entirely and
404'ing every backend call.

This change makes `getApiBaseUrl()` honor Vite's
`import.meta.env.BASE_URL` so that, when the bundle was built with e.g.
`vite build --base /weknora/`, axios produces `/weknora/api/v1/...`.
Trailing-slash stripped to avoid double slashes (`/weknora//api/v1/...`).

For deployments at the origin root (the common case), `BASE_URL`
defaults to `'/'` which strips to `''` — behavior unchanged from
upstream. No new build flag required; no behavior change for existing
users.

Reproduce the original problem:

  1. cd frontend && vite build --base /weknora/
  2. Serve dist/ behind Nginx at `location /weknora/`, proxy
     /weknora/api/* → backend.
  3. Open https://example.com/weknora/ → 404 on every API request
     because axios calls /api/v1/auth/test instead of
     /weknora/api/v1/auth/test.

After the fix the same setup just works.
2026-05-05 00:58:19 +08:00
ChenRussell 42348eb40d feat(ks3): add KS3 object storage support
Add Kingsoft Cloud KS3 as a supported storage provider, including
  backend service implementation, storage config UI, and provider
  scheme recognition throughout the codebase.
2026-05-05 00:22:27 +08:00
wizardchen c62ff4c906 fix(frontend): knowledge document list layout, batch bar, and selection
- Platform route outlet: flex min-height so document area is not collapsed
- Card grid: stable :key=item.id; clamp selection anchor after list reload
- DocumentListView: TDesign checkbox, sticky header, neutral file icons
- DocumentBatchBar: column-footer placement; toned style vs floating pill
- Clear selection i18n: less ambiguous wording (e.g. 取消选择)
- Batch delete: poll list refresh after async queue; getKnowled returns Promise
- files.ts: use file icon for text types; align chat/upload icon usage
2026-04-29 15:20:41 +08:00
nullkey be8e53bf08 feat(knowledge-base): add document batch delete and list view
Add a list-view alongside the existing card grid (issue #957) and
multi-select batch delete (issue #1045) for documents inside a knowledge
base. The two views are toggled from the toolbar and the preference is
persisted in localStorage. Selection state is shared between views with
shift-range support and a sticky batch-action bar.

Backend
- POST /api/v1/knowledge/batch-delete: validates KB scope and editor
  permission, then delegates to the existing DeleteKnowledgeList service
  which already cascades vector/file/graph cleanup. Caps batch size at
  200 and uses a single GetKnowledgeBatch call for membership validation.

Frontend
- DocumentListView: table layout with sticky header, checkbox column
  (with indeterminate select-all), file-type icons, status badges,
  per-row action menu.
- DocumentBatchBar: floating pill bar with selected count and delete
  action; appears when items are selected.
- KnowledgeBase.vue: view-mode toggle, selection state, batch-delete
  confirmation dialog, hover/active checkbox overlay on existing cards.
- Extracted formatFileSize and getFileIcon to utils/files.ts to share
  with the new list view and avoid further drift from the existing
  inline copies.
- i18n keys added for zh-CN, en-US, ko-KR, ru-RU.

Closes #1045
Closes #957
2026-04-29 12:01:38 +08:00
wizardchen 3231ae30a4 fix(frontend): bundle tdesign-icons sprite locally for offline deploys
The <t-icon> component from tdesign-vue-next lazily loads its SVG sprite
from https://tdesign.gtimg.com/icon/<ver>/fonts/index.js at runtime. In
air-gapped or intranet deployments this request fails and the whole UI
loses its icons (agent cards, knowledge-base breadcrumbs/cards, upload
buttons, etc.).

Ship the sprite (tdesign-icons-vue-next@0.4.1) as a static asset under
frontend/public/tdesign-icons/0.4.1/fonts/index.js and preload it from
index.html so every <t-icon name="..."> resolves against local symbols.
An offline guard injects stub <script>/<link> nodes that match tdesign's
dedup selectors, so checkScriptAndLoad / checkLinkAndLoad short-circuit
without ever hitting the CDN (covers both the 0.4.0 and 0.4.1 hardcoded
URLs for forward-compat).

Closes #867
Closes #897
2026-04-23 18:21:49 +08:00
wizardchen 4c906e0431 feat: Enhance agent tool compatibility and knowledge base filtering
- Introduced a unified capability requirements system for agent tools, ensuring consistent filtering of knowledge bases based on their capabilities.
- Implemented derived `kb_filter` logic to streamline compatibility checks between agent tools and knowledge bases, reducing redundancy in configuration.
- Updated frontend components to reflect new filtering logic, including improved handling of empty states and user feedback when no compatible knowledge bases are available.
- Enhanced internationalization support by adding relevant messages for tool compatibility issues across multiple languages.
2026-04-23 17:28:00 +08:00
jw_mac a121a5d636 fix(frontend): 修复公式输出展示问题并引入 KaTeX 支持 (#912) 2026-04-22 16:38:24 +08:00
wizardchen 8609c09a63 feat(request): enhance token refresh handling and public auth request logic
- Introduced a function to identify public authentication requests, preventing unnecessary token refresh attempts for specific endpoints.
- Simplified the redirection logic to the login page upon 401 errors, improving code readability and maintainability.
- Updated error handling to provide clearer messages for failed authentication attempts.

This update improves the request handling process, ensuring a smoother user experience during authentication flows.
2026-04-15 15:58:01 +08:00
wizardchen 86d26fa9bf feat(video): remove video upload support and update related terminology
- Removed support for video file uploads across the application, including updates to the knowledge base and document processing services.
- Updated internationalization files to reflect the removal of video-related terminology, changing labels and descriptions to focus solely on audio processing.
- Adjusted file type handling to exclude video formats, ensuring users receive accurate feedback regarding supported file types.
- Enhanced error handling to provide clear messages when users attempt to upload unsupported video files.

This update streamlines the application by focusing on audio processing capabilities and improving user experience through clearer messaging.
2026-04-14 22:59:14 +08:00
bingxiang.cheng 847660e4fc feat(storage): 添加对阿里云OSS的支持,更新相关文档和界面文本 2026-04-13 15:37:33 +08:00
wizardchen 9a2b54536d fix: update environment configuration for debugging and logging, enhance SQLite FTS5 table management, and improve API base URL handling 2026-04-11 18:51:16 +08:00
DaWesen b80bdb1079 feat: add video multimodal functionality 2026-04-09 19:19:42 +08:00
wizardchen 36dac0120a fix(datasource): improve error handling and user feedback in DataSource components
- Updated error handling in DataSourceSettings and DataSourceEditorDialog to provide more informative messages.
- Enhanced the UI to display error details more clearly, improving user experience during connection tests and resource loading.
- Adjusted HTTP response status checks in request utility for better accuracy in handling success responses.
2026-03-30 20:46:07 +08:00
wizardchen adabf8e089 feat(datasource): implement data source management functionality
- Added a new API for managing data sources, including CRUD operations and connection validation.
- Introduced UI components for data source settings, sync logs, and editor dialog, enhancing user experience in managing external data sources.
- Updated localization files to support new data source features in multiple languages.
- Implemented cron expression humanization for better scheduling visibility.
- Enhanced knowledge base editor to include data source management options.
2026-03-30 20:46:07 +08:00
ochan.kwon 5c0cda3630 fix(storage): add S3 provider scheme support to frontend and backend allowlists
The S3 storage adapter (s3.go) was added in e309e0b but the provider
scheme integration was incomplete — ParseProviderScheme() and frontend
security.ts were not updated, causing s3:// URLs to fail in the /files
proxy, VLM image processing, and frontend rendering.

Additionally, S3-compatible services (MinIO, Ceph, etc.) require
path-style addressing (endpoint/bucket/key) but the SDK client only
used virtual-hosted style. The deprecated WithEndpointResolver API
is replaced with BaseEndpoint, and path-style is auto-enabled for
non-AWS endpoints (detected by amazonaws.com in the URL).

Changes:
- types/knowledgebase.go: add "s3" to ParseProviderScheme()
- file/s3.go: auto path-style for S3-compatible endpoints + replace
  deprecated WithEndpointResolver with BaseEndpoint
- frontend/security.ts: add s3 to 5 provider scheme allowlists
- knowledgebase_test.go: add ParseProviderScheme + InferStorage tests
- s3_test.go: add path-style detection + parseS3FilePath tests
2026-03-30 16:57:27 +08:00
Manx98 66f4207bbc fix(frontend): prevent duplicate click binding 2026-03-30 10:46:50 +08:00
Manx98 b6fd4ba133 fix(frontend): resolve mermaid not rendering on page refresh 2026-03-30 10:46:50 +08:00
Manx98 5c0b265ea7 fix: marked usage errors 2026-03-27 14:57:54 +08:00