Updated the Vite configuration to allow dynamic setting of the API proxy target based on environment variables. The default target is now configurable via VITE_DEV_PROXY_TARGET or FRONTEND_BACKEND_URL, enhancing flexibility for different development setups. Additionally, the development script logs the current API proxy target for better visibility during startup.
The grep_chunks tool previously accepted an array of regex queries (1-5)
and an optional knowledge_base_ids filter and limit. In practice the LLM
either fired multiple near-duplicate calls or split synonyms across
entries instead of using POSIX alternation, and KB scoping plus result
limit are server-side concerns the model should not control.
Reshape the contract to match `grep -E -i` semantics:
- Schema accepts a single required `query` string. Combine concepts with
`|` alternation in one regex instead of multiple calls.
- Drop `knowledge_base_ids` and `limit` from the schema; the tool now
always searches the full agent scope and uses a fixed internal cap.
- Legacy `pattern`, `queries`, `patterns`, `max_results` keys are still
accepted and joined into a single alternation regex so older callers
and in-flight model outputs keep working.
- Update the agent system prompt template to document the new single
`query` field.
- Frontend tool title now reads `query`/`queries`/`pattern`/`patterns`
in that order so the search text is shown again under the new schema.
- Add a dedicated `grepSearch` / `grepSearchFailed` tool status (zh-CN,
en-US, ko-KR, ru-RU) and rename the zh-CN tool label to "搜索关键词"
so the UI no longer prefixes the call with a generic "调用 ..." label.
When a CanAccessAllTenants user switches into a tenant without a
tenant_members row, the backend grants temporary Admin via
resolveTenantRole step2 but currentTenantRole stayed empty, hiding
all mutation controls. Fall back to admin for UI gating only; Owner
surfaces remain hidden to match the server cap.
Add support for configuring vLLM server URL when using vlm-http-client or hybrid-http-client backend in MinerU.
Changes:
- internal/types/tenant.go: Add MinerUVLMServerURL field to ParserEngineConfig
- internal/infrastructure/docparser/mineru_converter.go: Pass server_url to MinerU API when backend is vlm-http-client or hybrid-http-client
- frontend/src/api/system/index.ts: Add TypeScript type definition
- frontend/src/views/settings/ParserEngineSettings.vue: Add vLLM server URL input field
- frontend/src/i18n/locales/*.ts: Add translations (zh-CN, en-US, ko-KR)
Problem:
The hard-coded Doris vector function implementation (cosine_distance_approximate with
UNIQUE KEY ANN tables) fails on SelectDB 4.0.2-rc01 and other Doris builds lacking that
specific function support. Users had no way to adapt without code changes.
Root cause:
There is assumption all Doris deployments support the same vector function API, but different
builds (Doris OSS, SelectDB, Doris Cloud) ship with different function variants and table
key constraints. No capability detection or user configuration existed.
Solution:
Implement DORIS_COMPAT_MODE environment variable with three modes:
* auto (default/recommended): probe Doris server on first use to detect available vector
functions; prefer inner_product_duplicate (modern Doris 4.0+), fall back to legacy
(older builds lacking inner_product_approximate)
* legacy: hard-set to cosine_distance_approximate + UNIQUE KEY (for older Doris/SelectDB
builds without inner_product_approximate support)
* inner_product_duplicate: hard-set to inner_product_approximate + DUPLICATE KEY
(for modern Doris 4.0+ and current SelectDB with normalized embeddings)
Implementation details:
- add compat.go with one-time mode resolution (sync.Once) and capability probing
- inspect existing weknora_embeddings_* table DDL via SHOW CREATE TABLE to detect and
enforce schema compatibility; prevents silent mismatches
- fail fast with clear error message when configured mode does not match existing tables,
with explicit remediation steps (recreate tables or change env var)
- branch all query paths (inner_product_approximate vs cosine_distance_approximate),
DDL generation (DUPLICATE KEY vs UNIQUE KEY), write paths (embed normalization),
and chunk updates (Stream Load vs read-modify-write) by resolved compat mode
- add comprehensive repository tests for mode selection, auto-detection, and mismatch
scenarios; all tests pass
- expose DORIS_COMPAT_MODE in docker-compose.yml with auto as default
- document in .env.example with clear mode decision guidance
- log all mode decisions (requested, detected, probed, final) at INFO/WARN level
Key guarantee:
⚠️ DORIS_COMPAT_MODE is NOT interchangeable after embedding tables are created.
App will reject mode switches that conflict with existing table layout, preventing
silent data mismatches and query failures.
vue-i18n treats a bare '@' as the start of a linked-message reference,
so the placeholder "invitee@example.com" failed to compile with
"Invalid linked format". The whole email t-form-item then failed to
render, leaving the invite-member popup with only the role row.
Escape the literal '@' as {'@'} across all four locales so vue-i18n
emits the original text and the email input renders again.
Sessions now record the input-bar state used for the most recent QA
request (agent, model, KB scope, web search). The chat UI hydrates
those settings on session reopen so users see the same configuration
they used last time, instead of the global default.
The state is stored in the existing sessions.agent_config JSONB column
to avoid a new migration. Frontend snapshots the user's global defaults
on session enter and restores them on session leave, so opening an old
session does not pollute new-chat defaults.
The session list items in the sidebar forced the title's max-width to
155px on hover and on the active item, while .menu-more-wrap was pushed
to the right edge with margin-left:auto. This left a large gap between
the truncated title and the kebab button on rows whose title actually
fit within the row.
Switch the title to a flex layout (flex: 1; min-width: 0) so it grows
to fill the available space and only shows an ellipsis when the text
genuinely overflows. The kebab wrapper keeps flex-shrink: 0 so its
opacity-controlled visibility no longer needs to reshape the layout.
The route watcher in the sidebar treated any navigation away from the
creatChat pages as "a new session was created" and called
getMessageList(), which clears menuArr and re-fetches page 1. As a
result, clicking an existing session from /platform/creatChat caused
the whole session list to flicker.
Only refresh when the target chat id is not already in the list, which
is the real signal that a brand-new session was just created.
Reduce vertical spacing in the chat session list so more sessions fit
on screen without feeling cramped: row height 38→34px, item height
32→30px, and slimmer timeline group headers.
Refactor the tenant RBAC configuration to change the default value from false to true, enabling role enforcement by default. This change allows operators to opt into a logging-only rollout window by explicitly setting the configuration to false.
Updates include:
- Modifications to .env.example and docker-compose.yml to reflect the new default.
- Adjustments in rbac.md documentation to clarify the new default behavior and the opt-in process.
- Code changes across various files to utilize the new pointer-based configuration for EnableRBAC, ensuring nil safety and clearer intent.
No functional changes were introduced; the adjustments primarily enhance clarity and maintainability of the RBAC feature.
Surface two existing config.go env overrides to the canonical
deployment artifacts so operators can flip them without reading the
Go source:
* WEKNORA_TENANT_ENABLE_RBAC — observe / enforce switch for
tenant-level role enforcement (PR 1303). Default false keeps the
current behaviour; flip to true once role assignments have been
audited per docs/rbac.md.
* WEKNORA_TENANT_MAX_OWNED_PER_USER — cap on tenants a single
non-superuser can self-create. Uses the existing <0 / 0 / >0
sentinel semantics documented on TenantConfig.MaxOwnedPerUser.
docker-compose.yml passes both through to the app container, and
.env.example gains a "Tenant / RBAC" section with the default
values and the same sentinel rules inline so the example is the
sole reference operators need.
No functional change — both env vars were already honoured by
config.go.applyAuthAndTenantDefaults.
DISABLE_REGISTRATION=true used to block /auth/register at the handler
layer only, leaving /auth/config still reporting self_serve. The
frontend therefore kept showing the Register entry even when the env
var was set — clicking it just hit the 403. Two gates, out of sync.
Wire DISABLE_REGISTRATION=true through applyAuthAndTenantDefaults so
it coerces auth.registration_mode to invite_only (env wins over YAML,
matching docs/rbac.md). The handler-side os.Getenv check is now
redundant with IsInviteOnly() and is removed, leaving a single
enforcement path.
Add config tests pinning down the env/YAML matrix, including the
explicit-self_serve override case that would otherwise be the easy
regression to ship.
DISABLE_REGISTRATION=true (handler layer) and
WEKNORA_AUTH_REGISTRATION_MODE=invite_only (config layer) were two
env-level ways of saying the same thing: block /auth/register.
Keeping both invites confusion about which wins and risks operators
setting one while expecting the other.
Remove the WEKNORA_AUTH_REGISTRATION_MODE env override so the env
layer exposes a single knob (DISABLE_REGISTRATION). The
auth.registration_mode config field stays — operators who want the
richer behaviour (frontend hides the registration entry via
/auth/config in addition to the server-side 403) flip it in
config.yaml.
No behaviour change for deployments that did not set the env var.
Update docs/rbac.md to document the deliberate split.
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.
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.
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.
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.
Wrap the role icon in a small colored circular chip and reuse the same
chip inline inside the role tags in the members and invitations
tables, so the permission-matrix popover, the members grid and the
invitations grid all share the same visual language for each role.
The chip color is keyed by role, making role recognition faster at a
glance without depending on the tag's surrounding text.
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.
Replace the default t-dropdown on knowledge document cards with a
custom t-popup-based list that matches the existing card-more popup
styling (rounded corners, blur, dark mode). Selected entries show a
brand-colored check icon.
Also fix the empty placeholder issue: when a document has no tag,
render a dashed "+ category" affordance only for users with edit
permission, instead of an empty tag chip. A "clear category" action
appears at the bottom of the popup only when a tag is already set,
avoiding ambiguity with user-defined tags named the same as the
generic "uncategorized" label.
Adds the knowledgeBase.tagClearAction i18n key in zh-CN, en-US,
ko-KR and ru-RU.
Introduced a new helper function to create a fake Elasticsearch server for testing, improving the reliability of connection probes in vector store tests. Additionally, added methods for setting and listing user-specific knowledge base pins in the knowledge base repository, aligning with recent user pinning features.
Refs: #1303
Modified the AgentQA function to conditionally pass the title disable flag to the executeQA method, enhancing flexibility in session handling. This change improves the behavior of the QA execution based on user requests.
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
Enhanced localization files for English, Korean, Russian, and Chinese by adding the "Shared by me" label to improve clarity in shared resource sections. This update ensures a more intuitive user experience when navigating shared content across different languages.
Refs: #1303
Enhanced English, Korean, Russian, and Chinese localization files by adding new section labels such as "Built-in," "Created by me," and "Other members" to improve user understanding. Adjusted existing labels for better clarity and consistency across languages. This update ensures a more intuitive user experience in navigating shared and personal resources.
Refs: #1303
Refactored the pinning mechanism for knowledge bases to be user-specific, allowing any user with read access to pin knowledge bases independently. This change includes the introduction of a new `user_kb_pins` table to manage pin states, replacing the previous tenant-wide pinning system. Updated relevant API endpoints and service logic to support this new functionality, ensuring that the UI reflects the user's personal pin status.
Additionally, adjusted the knowledge base listing to sort by user-specific pin status, enhancing the user experience by prioritizing pinned items.
Refs: #1303
Refactored the assignment of enableMemoryOverride in the sendMsg function to remove explicit type declaration, enhancing code clarity. This change maintains the existing functionality while streamlining the code structure.
Updated the memory management logic to utilize a server-side per-user preference for enabling memory. The `enable_memory` field is now conditionally set based on user preferences, allowing for better control in both normal and embedded contexts. Adjusted relevant API handlers and request structures to support this change, ensuring backward compatibility with existing clients.
Refs: #1303
Added functionality for managing user preferences, including the ability to update preferences via a new API endpoint. The preferences are now stored server-side, allowing for synchronization across devices. Updated relevant components to handle user preferences, including the UserMenu and settings views. Enhanced internationalization support for error messages related to preference updates.
Introduced a new QuickNav menu item for 'members' in the UserMenu component, allowing users with the appropriate role to access member-related functionalities. Updated the role alignment for QuickNav entries to ensure consistency with the Settings component. This enhancement improves navigation for users based on their permissions.
Refs: #1303
Updated the tenant information API to allow editing of both name and description fields, improving user experience in managing tenant details. Introduced a new GlobalInvitationBell component to display pending invitations in the UI, ensuring users can easily access their invitations without navigating away from their current context. Additionally, updated internationalization files to support new description-related messages.
Refs: #1303
Refactored the Input-field.vue component to enhance the clarity and maintainability of computed properties related to selected items. Improved the logic for handling agent configurations and user-selected files, ensuring a more streamlined approach to displaying knowledge bases and files. Additionally, adjusted the handling of disabled agents to ensure proper fallback selection when necessary.
Refs: #1303
Introduced a new optional field, creator_name, in both CustomAgent and KnowledgeBase types to allow the front end to display the creator's name. This enhancement enables better differentiation between resources created by the current user and those created by other members of the same tenant. Updated relevant API handlers to populate this field during list operations, ensuring accurate representation in the UI. Additionally, modified the ResourceOriginBadge component to utilize the creator_name for improved context in resource listings.
Refs: #1303
Consolidated the template structure in GlobalCommandPalette.vue to enhance code clarity and maintainability. Adjusted the layout of various elements for better alignment without altering existing functionality. This refactor aims to improve the overall readability of the component for future development.
Refs: #1303
Updated the AuditLogRetentionRunner to include a 'started' flag, allowing Stop() to return immediately if Start() was never invoked. This change prevents potential deadlocks during graceful shutdown. Additionally, added tests to ensure that Stop() behaves correctly when called before Start() and when the service is nil.
Refs: #1303
Added functionality for managing pending invitations, including a polling mechanism to update the invitation count in real-time. Introduced a new dialog component for users to view and respond to their invitations without navigating away from their current context. Updated API endpoints for fetching and managing invitations, and enhanced the user interface with relevant internationalization support.
Refs: #1303
Introduced a new "leave workspace" feature with corresponding titles, descriptions, and buttons in English, Korean, Russian, and Chinese. This enhancement improves user experience and clarity in workspace management, allowing users to easily understand the implications of leaving a workspace.
Refs: #1303
Modified chat titles in multiple languages to enhance user engagement. Introduced a new "leave workspace" feature with corresponding titles, descriptions, and buttons in English, Korean, Russian, and Chinese, improving user experience and clarity in workspace management.
Refs: #1303
Enhanced the GetOrganization and ListMembers methods to enforce tenant-based access control. Users can now only access organization details if their tenant is a member or if the organization is marked as searchable. This change prevents unauthorized enumeration of organizations and ensures sensitive member information is only accessible to authorized tenants.
Refs: #1303
Updated the customAgentService to include a new KBShareService interface for handling cross-tenant knowledge base sharing. Implemented logic to group knowledge base IDs by effective tenant, ensuring correct querying of shared KBs. Adjusted the GetSuggestedQuestions method to accommodate these changes, improving the handling of FAQ and document chunks for shared knowledge bases.
Refs: #1303
Implemented a new function to clear tenant-specific data from localStorage when a user switches tenants. This prevents issues with stale data being used in the new tenant context, which could lead to backend errors. The function is called during the tenant selection process to ensure a clean state for the new tenant.
Refs: #1303