Commit Graph
2678 Commits
Author SHA1 Message Date
PP1 06eeb95b4e fix(embedding): validate WeKnoraCloud response indexes
Reject out-of-range and duplicate response indexes before mapping them to batch inputs. Return an error when a requested input has no response item instead of silently passing an incomplete batch downstream.

Add focused coverage for malformed responses and valid out-of-order results.

Signed-off-by: PP1 <74917296+pengpengyi92@users.noreply.github.com>
2026-08-11 16:59:48 +08:00
chenjunhong 9bf3dee28a fix(frontend): enable scrolling in share space selector 2026-08-11 15:47:53 +08:00
wizardchen 738fe1ec53 feat(sandbox): 沙箱后端改为按空间配置,并补齐 E2B 模板与检测诊断
沙箱的后端类型、凭据、模板、超时和私网访问策略此前分散在部署级
WEKNORA_SANDBOX_* 环境变量里,一个实例只能有一套,租户之间无法各用
自己的 E2B 账号或自建 Cube 集群。现在这些配置全部落到空间维度的具名
沙箱配置上:部署环境不再提供覆盖项,未选择配置的智能体直接不启用脚本
执行,而不是静默回落到某个部署默认值——后者会让「这个智能体到底跑在
哪」无从判断。

同时把连接检测从「能不能连上控制面」扩展成可解释的诊断:
- E2B 标准模板显式带上 default 标签构建。创建沙箱时裸模板名/ID 只解析
  default 标签,构建带了别的标签就永远拿不到,表现为一个与「模板不存在」
  无法区分的 404。
- 模板状态不再从历史构建或 spawn 次数反推就绪,只认当前构建;构建完成
  却没有 default 标签的模板单独报成 untagged,因为它在列表里和「仍在构建」
  长得一样,但等待永远不会有结果。
- 创建失败带上 HTTP 状态,404 走模板解释路径,给出具体到「重建模板」还是
  「Key 属于其他团队」的结论。
- 探针脚本改在进程工作目录下暂存。系统临时目录在 macOS 上位于
  /var/folders,Docker 虚拟机并不共享,挂载进容器后是空目录,真实技能执行
  (脚本在 skills/ 下)却不会踩到,检测因此报假失败。
- 检测失败不再只说「命令输出与预期不符」,带上退出码与 stderr 首行。

前端把沙箱设置页与配置抽屉重做:凭据按「是否已配置」展示而非回显掩码,
删除与停用改为就地确认,占用情况走右侧抽屉,列表卡片展示模板状态、凭据、
超时等可判断健康度的事实。
2026-08-11 15:42:02 +08:00
sunmh 95ddeae067 feat(auth): add /auth/oidc/start endpoint for direct 302 OIDC login
New endpoint GET /api/v1/auth/oidc/start — unlike /auth/oidc/url which
returns JSON and requires frontend JS to navigate, this endpoint directly
returns a 302 redirect to the OIDC Provider's authorization page. This
enables external platforms (enterprise portals, Nexus, etc.) to give a
single clickable link that triggers the full OIDC authorization code
flow and, when the IdP has an active SSO session, achieves passwordless
login without any frontend involvement.

- backend derives the callback URL from the request origin automatically
  (no caller-supplied redirect_uri needed)
- OIDC nonce cookie is bound identically to /auth/oidc/url (CSRF/replay
  protection)
- registered in the auth middleware public-path whitelist (otherwise
  the global auth middleware returns 401 before routing reaches the
  handler)
- refactored shared nonce-cookie helper out of GetOIDCAuthorizationURL
  for reuse by OIDCStart
2026-08-11 15:41:48 +08:00
hanxiantao dcaa2d3883 fix(i18n): add common update success translations 2026-08-11 11:08:42 +08:00
5df788dc77 feat(sandbox) (#2301)
* cubesandbox support

* feat(agent): add sandbox shell execution, file management tools, and Artifacts collection/download system

- Add three sandbox agent tools: shell_exec / sandbox_ls / sandbox_read
  - shell_exec: safely execute shell commands in session sandbox with timeout & output truncation
  - sandbox_ls: enumerate files under sandbox artifact output directory with recursive listing & pagination
  - sandbox_read: read sandbox file content with offset-based chunked reading
- Add Artifacts system:
  - ArtifactCollector: real-time collection of sandbox tool output files, attached to messages
  - /api/artifacts/{session_id}/{message_id}/{filename}: download endpoint for frontend
  - ChatArtifactsDrawer.vue: frontend artifacts sidebar UI
  - DB migration 000066_message_artifacts: add artifacts column to messages table
- Attachment sandbox staging: upload user attachments to session sandbox on QA request for skill tool access
- Update Agent Prompts: add shell/sandbox tool usage constraints and safety rules
- Extend Agent Observe: include agent steps in Langfuse observability tracing
- Refactor Sandbox SessionManager: support session-scoped file listing, reading, and status queries
- Frontend: render artifact events in AgentStreamDisplay, i18n updates for 4 locales
- Add comprehensive tests: shell_exec_test, sandbox_read_test, artifact_collector_test, etc.

* feat(agent):add remote sandbox client abstract  & client errors

* feat(sandbox): implement Redis binding store with distributed lifecycle lock;

* feat(sandbox): add remote session lifecycle with ownership context

Implement remoteSessionLifecycle to coordinate persistent remote sandboxes
across multi-instance deployments. Supports Resolve (lazy provision,
recovery, race-safe create) and Destroy with compare-delete semantics.
Add ownership context isolation to decouple remote resource cleanup from
request cancellation.

* feat(sandbox): add CubeRemoteClient adapter for RemoteSandboxClient

Implement CubeRemoteClient as a provider-neutral RemoteSandboxClient
implementation. Error normalization, timeout mapping, and metadata
support are fully integrated. SDK details remain private to the
adapter.

* refactor(sandbox): decouple SessionBoundManager from Cube

Remove internal/sandbox/cube.go (CubeSandbox, sync.Map reaper). Add
RemoteSandbox as provider-neutral Sandbox interface implementation.
Rewrite SessionBoundManager to depend on RemoteSandboxClient +
SessionSandboxBindingStore + SessionExistenceChecker, with all
lifecycle ops delegated to remoteSessionLifecycle (Redis + distributed
lock). Application-layer interfaces migrated to RemoteDirEntry/StatEntry
with time.Time ModTime. Cleanup delegated to provider idle-timeout.

* refactor(agent): enhance session capability handling in sandbox manager

- Introduced sessionFileStore and sessionShellExecutor functions to centralize capability checks for session-scoped file and shell execution.
- Updated agent service to register tools based on the presence of session filesystem capabilities, improving compatibility with various sandbox backends.
- Refactored tests to validate behavior when session capabilities are absent, ensuring robust handling of different sandbox types.
- Removed Cube-specific checks, promoting a more provider-neutral approach to session management.

* refactor(sandbox): add E2B backend, modernize Cube adapter, and enable multi-instance Redis binding

- Add e2b_remote_client.go (~850 lines) — full RemoteSandboxClient implementation
  covering lifecycle, execution, and filesystem ops (ListDir/Stat/MakeDir/Remove)
- Wire E2B into NewManagerFromType and container/bootstrap path (buildE2BManager)
- Dependency: matiasinsaurralde/go-e2b v0.1.0

- Cut ~1500 lines of legacy SDK wrapper (cube_client.go, cube_envd.go,
  cube_defaults.go) and replace with direct *cubesandbox.Client usage
- Parse CubeProxy URL directly in adapter (parseProxyURL), removing the
  old hand-rolled envd transport layer
- Pass lifecycle extra fields (onTimeout, autoResume) via SDK CreateOptions.Extra
- Target Cube deployment v0.5.1

- Add RemoteNetworkPolicy to RemoteCreateRequest with AllowInternetAccess,
  AllowPublicTraffic, AllowOut/DenyOut — shared by Cube and E2B adapters
- Both adapters default to permissive (internet+public on) for backwards compat

- Add selectSessionBindingStore() — Redis-backed or in-memory, controlled by
  WEKNORA_SANDBOX_REDIS_NAMESPACE / WEKNORA_REDIS_NAMESPACE
- Add repositorySessionExistenceChecker — checks session existence via DB
  (gorm.ErrRecordNotFound → not exists, transient errors → preserve binding)
- newSandboxManager() now accepts redisClient + sessionRepo; deprecated
  hardcoded NewMemorySessionSandboxBindingStore() in production path

- buildSessionCreateRequest default timeout action: Kill → Pause+AutoResume
  (Cube and E2B). Sessions survive brief idle periods; providers still
  handle TTL-based reaping.

- buildSessionCreateRequest() and effectiveHTTPTimeout() parameterized
  by RemoteProvider (was hardcoded to Cube Config fields)
- NewSessionBoundManager validates provider and delegates defaults to
  per-provider apply*Defaults helpers

- Legacy SDK wrapper: cube_client.go, cube_envd.go, cube_defaults.go,
  cube_envd_test.go, cube_net_diag_test.go, cube_test.go (~2500 lines)
- Unused helpers: DefaultManager.validateExecution, IsRemoteTerminal,
  IsRemoteUnsupported, IsRemoteTransient, ShouldPreserveRemoteBinding
- Dead Config fields: CubeEnvdPort, CubeIdleTTL, AllowedCmds
- Dead ExecuteResult method: GetOutput
- Unused test: session_artifacts_integration_test.go
- Preloaded skill: sandbox-test-python

- Extract shared httpErrorKind() from per-adapter normalize functions
- Add SupportsFilesystemEnumeration capability flag — gates SessionFileStore
  advertisement (E2B returns true post-reconnect, Cube always true)
- Fix stale comments: Cube-only → remote backends, remove "tomorrow"/"future"
- Bump session sandbox TTL defaults: 604800s → 300s (.env.example)
- Update docs/agent-skills.md: full multi-instance deployment guide

Total: 29 files, +1188 / -3721

* feat(agent): bind collected skill artifacts to owning message in resource registry

When ArtifactCollector persists a skill-generated file it now registers a
resource:// binding (owner_type=message, owner_id=assistantMessageID,
relation=artifact) in addition to the messages.artifacts JSONB record. This
mirrors how knowledge uploads and chat attachments bind their resources, so
artifacts can be enumerated and garbage-collected through the resource
registry instead of only via the message JSONB column.

- ArtifactCollector: inject ResourceCatalog, add messageID to Collect/
  maybePersist, and add best-effort bindArtifactResource (binding failures are
  logged, never drop the artifact; only resource:// refs are bound).
- agent_stream_handler: pass assistantMessageID into Collect.
- Renumber message_artifacts migration 000066 -> 000077 to resolve the
  version collision with existing migrations (upstream now uses 000075/000076).
- Tests: update collector signatures and add coverage for the binding path
  and for graceful degradation when Bind fails.

Note: binding applies to newly generated artifacts only; existing rows are
not backfilled.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(sandbox): harden remote sandbox security and artifact collection

Disable Cube local fallback so skill scripts never run on the host when
the remote provider is unavailable. Require Redis for cube/e2b binding
unless WEKNORA_SANDBOX_ALLOW_MEMORY_BINDING=true for single-node dev.

Collect artifacts with WithoutCancel so user stop does not drop files,
reject shell_exec work_dir outside /workspace, and refuse session-scoped
Execute when a local fallback would be engaged.

* fix(ci): gofmt sandbox files and resolve artifact drawer type error

Apply gofmt to PR-touched Go files and narrow ChatArtifactsDrawer
props in AgentStreamDisplay so session-id is always a string.

* fix(sandbox): adapt to upstream main after rebase

Renumber the message_artifacts migration 000077 -> 000079: upstream now
uses 000077_remove_wiki_log and 000078_chunk_editing_and_custom_metadata.

Declare empty model-handle policies for shell_exec / list_sandbox_files /
read_sandbox_file. Upstream added a coverage test requiring every
UI-exposed tool to declare one; sandbox output is arbitrary skill-authored
content, so it gets the same treatment as execute_skill_script.

Co-authored-by: Cursor <cursoragent@cursor.com>

* feat(sandbox): replace single tenant sandbox config column with a configs table to support multi-sandbox config per tenant.

* feat(sandbox): add sandbox config entity, cordon lease and session pin field

* feat(sandbox): add sandbox config repository with tenant scoping and cordon lease

* feat(sandbox): stamp sandbox config ID onto sandbox metadata

* feat(sandbox): scope sandbox listing, release and reaping to a single config

* feat(sandbox): resolve managers per config and refuse cordoned or missing configs

* feat(sandbox): implement session pinning and config identity change detection

- Add SessionSandboxPinner with read/pin/clear to bind session to config
- Refactor four entry points (execute/attachment/artifact/destroy) to use pinned config
- Add config_identity.go to detect identity changes by effective values (APIURL/APIKey/Domain/ProxyURL)
- Add SandboxIdentityChanged with key-masked comparison to prevent false 409 conflicts
- Fix artifact collection for default backend and destroy for legacy empty-pin sessions

* feat(sandbox): add multi-tenant sandbox config management and HTTP APIs

Service layer:
- Add sandbox config business service supporting CRUD and inventory listing
- For non-identity changes (e.g., template, TTL), save directly without locking or remote interactions
- For identity changes (e.g., API key, endpoint), reject save if there are still live sandboxes under this config on the remote side,
  and return structured inventory details (sandbox count, affected sessions, related agents) for frontend prompting
- Before deleting a config, check remote live sandboxes; if occupied, reject and prompt user to end sessions or create a new config
- Identity comparison based on effective values to avoid normal saves being misidentified as credential rotation

HTTP interfaces and routing:
- Add REST endpoints for sandbox config (List/Create/Get/Update/Delete/Inventory)
- Mask sensitive credentials (API key, etc.) in all read responses
- Return 409 with structured inventory details on rejection scenarios
- sandbox-check probing supports specifying an existing config_id directly
- Remove old handler file, consolidate validation logic into service layer
- DI wiring and route registration for all six endpoints

* feat(sandbox): add sandbox_config_id field to allow agent referencing named sandbox config

- Add SandboxConfigID field to CustomAgentConfig with omitempty; empty value falls back to global defaults
- Validate config existence on create/update; return 400 if not found
- Inject sandboxConfigService into CustomAgentHandler
- Add unit tests covering field serialization and validation logic

* feat(sandbox, agent): Migrate sandbox config to multi-config CRUD, support named backend selection and workspace scripts policy

Migrate frontend API from legacy KV single-config to /sandbox-configs REST interface, supplement type definitions, detection methods and policy fields; refactor sandbox settings page to multi-config card grid, manage configs with cube/e2b tabs, add editor drawer for create/edit/delete, connection testing and occupancy hints, and add workspace scripts policy toggle; add sandbox config dropdown in Agent editor skill section, integrate config caching, and support selecting named config or falling back to deployment default.

* feat(sandbox): Unify sandbox disable semantics and add tenant-level policy master switch

- Backend: Unify interception in resolveTenantSandboxForConfig with priority: global disable > tenant disable > default fallback > named config; add deploymentSandboxDisabled() using env var to avoid mis‑impacting named E2B; update WorkspaceSandboxPolicy comment as master switch for entire workspace; add unit tests for various scenarios.
- Frontend: Sync i18n copy: button text changed to "Disable/Enable sandbox execution"; confirmation dialog clarifies impact scope; success/failure messages aligned.
- Semantic layering: WEKNORA_SANDBOX_MODE=disabled disables globally; tenant‑level "Disable sandbox execution" only disables for the current workspace.

* feat(sandbox): Add SSRF protection, Agent binding to named configs, and reference query capabilities

- Add outbound URL security guard to validate Cube/E2B API/Proxy addresses against SSRF (including cloud metadata), support allowing private endpoints via env var, link-local always blocked
- Add named backend type validation, only cube/e2b can be stored as workspace named config
- Add sandbox config ID field to Agent at runtime, resolve sandbox for attachments and execution based on Agent's selected named config instead of always global default
- Add query to list Agents referencing a sandbox config ID, useful for deletion/changes to show dependents
- Adapt artifact collector and other callers to fill missing resolve signature parameter

* fix(sandbox): fix session teardown and config-update, add HTTP pool sharing for Cube

Session teardown & deletion ordering
- Move sandbox destroy (and pin `Clear`) before soft‑delete operations (`DeleteSession`/`BatchDeleteSessions`/`DeleteAllSessions`) to prevent remote sandbox leaks and stale pins.
- Pass deployment‑wide `SessionBoundManager` as fallback into `resolveTenantSandboxForConfig` for sentinel pins (`"-"`) to support deployment‑default sessions.

## Config update edge cases
- When identity fields change but old credentials cannot build a client or list config sandboxes, log a warning and proceed with the update instead of returning `sandbox_inventory_unverifiable`; live sandboxes still return 409.
- UI: move `sandboxes_still_live` / `unverifiable` alerts to the top of the sandbox config drawer and auto‑scroll on save refusal and connectivity check results.

Artifact collection for Cube skills
- Pre‑create `/workspace/output` via envd with correct ownership/permissions for `DefaultSandboxExecUser` to ensure Cube skill artifacts are collected properly by `ArtifactCollector`.

HTTP pool sharing for named Cube configs
- Named sandbox configs rebuilt a client on every `Resolve`, causing fresh TCP connections to CubeAPI and the envd proxy on each request.
- Add `CubeTransportPool` and `cubeSplitTransport`:
  - Control plane traffic reuses the same `SharedTransport` as E2B.
  - Data plane traffic uses a guarded transport cached per proxy host:port, preserving the sandbox `Host` header.
- Wire the pool through the tenant resolver `buildClient`; keep SDK defaults for the deployment‑default manager and connectivity probes.

* feat(sandbox): sandbox execution DefaultUser change from root to user

* fix(multi-sandbox-config-per-tenant): align deployment config with tenant resolver and centralize defaults

- Merge form overrides onto DeploymentConfig() via WEKNORA_SANDBOX_* env vars
  instead of DefaultConfig() hardcoded values, allowing empty fields to inherit
  from .env rather than Go constants
- Centralize deployment baseline parsing in sandbox/defaults.go with
  DeploymentConfig, CubeConfigFromEnv, E2BConfigFromEnv
- Delegate container startup to shared helpers to avoid drift
- Propagate tenant env_vars through ResolveEffectiveConfig into
  buildSessionCreateRequest for both Cube and E2B session sandboxes

* fix(multi-sandbox-config-per-tenant): fix some bugs frontend.

* fix(sandbox): guard check-path dials, fix staging gate and shared-agent binding tenant

Three defects found while reviewing the remote sandbox work:

- The Cube connectivity probe and the deployment-default Cube/E2B managers
  built clients without a guarded transport, so an admin-supplied api_url or
  proxy_url could reach link-local addresses via DNS rebinding even though
  save-time validation passed. All three now dial through the same outbound
  guard the per-tenant resolver enforces.

- Attachment staging was gated on the process-wide manager, so a workspace
  pointing an agent at a named Cube/E2B config while the deployment default
  stayed docker/local would run its tools remotely against an empty
  /workspace/input. The gate now resolves the manager the session actually
  runs on.

- Session to sandbox bindings were keyed by the tenant in context, which a
  shared agent deliberately swaps for the agent owner's so models, KBs and
  named configs resolve in the sharing workspace. Session deletion only ever
  knows the session's own tenant, so teardown looked up a key nobody wrote
  and abandoned a paused MicroVM that keeps billing. The binding tenant is
  now carried separately and survives CloneContext.

* chore(sandbox): renumber migrations above upstream and de-collide test stub

Upstream main took 000079 (knowledge_folder_path) and 000080
(knowledge_base_auto_tag_config) while this branch was open, so the three
sandbox migrations move to 000081-000083. golang-migrate requires unique,
ordered versions, and the RAISE NOTICE labels move with the file names.

Main also added a handler test declaring stubSessionService in the same
package; the artifact download test's configurable variant is renamed rather
than merged, since the two stubs answer GetSession differently.

---------

Co-authored-by: hailongzhao <hailongzhao@tencent.com>
Co-authored-by: wizardchen <wizardchen@tencent.com>
2026-08-10 21:28:20 +08:00
jacentsao 20c9e5cfe1 feat(yunzhijia): support thread sessions 2026-08-10 19:44:13 +08:00
sunmh bcc54353e3 fix(config): 补齐 WEKNORA_TENANT_ENABLE_CROSS_TENANT_ACCESS 的 env 读取 2026-08-10 19:40:09 +08:00
MidoriKurage 58ee0b7d38 refactor(handler): extract shared searchResultFromMap
Deduplicate the two inline SearchResult rebuilds (SSE references and
agent-stream references) into one searchResultFromMap helper.

Add a JSON round-trip test pinning all fields.
2026-08-10 19:34:02 +08:00
jiahao6635 18eff14915 test(cli): refresh wire goldens for KnowledgeBase.auto_tag_config
Client KnowledgeBase JSON now includes auto_tag_config; update
kb_list/kb_view success wire fixtures so acceptance/contract stays green.
2026-08-10 19:33:39 +08:00
jiahao6635 c4f3a6a2c6 fix(cli): align stream/list interfaces with client ResourceURLOptions
Client methods gained optional ...ResourceURLOptions, which broke
CLI service interfaces used for compile-time Client assignability and
caused `go build ./...` to fail on main. Update interfaces and fakes
so ChatService/ListService/AskService/ResumeService/ViewService/MCP
match the SDK again.
2026-08-10 19:33:39 +08:00
jiahao6635 8ec5388655 fix(cli): preserve agent update flags in retry_argv
When agent update hit exit-10 confirmation, retry_argv dropped
--add-kb/--remove-kb/--system-prompt-file/--config-file, so re-running
after approval could not reproduce the original update.

Expand pflag SliceValue flags as repeated --flag value pairs in
BuildRetryArgv, and include the missing agent update flags in the
allow list. Fixes #2597.
2026-08-10 19:33:39 +08:00
wizardchen 4cb9ed6f3b fix(test): use resolvable URLs in MCP service update test
UpdateMCPService now validates outbound URLs for SSRF; subdomains like
before.example.com fail DNS resolution and break App CI.
2026-08-10 19:25:25 +08:00
jay3cx 8fc36d0265 fix(mcp): preserve omitted service update fields
Clarify partial update contract in tests.
2026-08-10 19:14:21 +08:00
Binks Riverton ac1164dfb9 fix(frontend): dismiss stale card popover on folder navigation 2026-08-10 17:25:05 +08:00
MidoriKurage 1431e9414e feat(agent): prefill default rerank model on agent creation
Prefill rerank_model_id in the agent create dialog with the same
is_default-first, first-active fallback as chat

Extract the selection into frontend/src/utils/modelDefaults.ts and reuse
it in the KB dialog.
2026-08-10 17:20:01 +08:00
jacentsao 6d833abfc0 fix(im): persist session mode configuration 2026-08-10 17:09:35 +08:00
wizardchen afd1ef8cf3 fix(invitation): harden auto-accept follow-ups from code review
- Reconcile stale pending invites after auto-accept AddMember
- Adopt invited workspace as home tenant when invitee is tenantless
- Await refreshFromAuthMe on SPA boot; sync auto_accept in hydrateSessionFromToken
- Document capabilities.auto_accept_invitation; extend client SDK and OpenAPI
2026-08-10 15:47:29 +08:00
sunmh 47d95cd720 feat(invitation): add auto-accept switch for inviting registered users
Add a global tenant switch (tenant.auto_accept_invitation /
WEKNORA_TENANT_AUTO_ACCEPT_INVITATION, default false). When enabled,
inviting an already-registered user adds them to the tenant as an
active member immediately, instead of creating a pending invitation
the invitee must accept from their inbox.

Backend:
- CreateInvitation reads the switch and, when on, calls the new shared
  addMemberAndRespond helper (extracted from TenantMemberHandler.AddMember)
  to persist the member and write the HTTP response. Both call sites
  share it so the sentinel->status mapping can't drift apart.
- Register the setting in the system_setting registry (bool, default
  false).
- Expose the switch as capabilities.auto_accept_invitation on
  GET /auth/me, so the SPA can adapt the invite popup without calling
  the super-admin settings API.
- Cover enabled/disabled, already-a-member, unknown email, owner role
  rejection, and nil member service with unit tests.

Frontend:
- The invite popup adapts to the mode. With auto-accept, the form
  submits directly (button reads "Send", no "confirm invitation" step)
  and refreshes the member roster silently (no toast; the new row is
  the feedback). The classic two-step flow is unchanged when off.
- Fix capabilities hydration: refreshFromAuthMe (the only reader of
  /auth/me capabilities) was invoked solely from the invitation-token
  flow, so on page reload can_create_tenant and auto_accept_invitation
  stayed at their initial false. Trigger it from initFromStorage once a
  token is restored so deployment switches are reconciled with the live
  server.
2026-08-10 15:04:29 +08:00
sunmh 8309370fa9 feat: 邀请链接在 invite_only 模式下改为登录后加入空间 2026-08-10 14:57:38 +08:00
Binks Riverton 355d161d64 feat: add Metaso web search provider 2026-08-10 13:33:55 +08:00
lyingbug 1030832c4b fix(security): harden outbound URL SSRF protection (#2626)
* fix(security): harden outbound URL SSRF protection

* test(security): add SSRF validation tests for outbound URL caching

Introduce tests for outbound SSRF validation cache to ensure proper handling of URL validation, including cache reuse for the same origin, cache invalidation on whitelist changes, and expiration of cached entries. This enhances the robustness of SSRF protection mechanisms in the application.

* refactor: clean up whitespace in engine_factory.go and ssrf_outbound_cache.go

Removed unnecessary blank lines in engine_factory.go and adjusted variable declarations for consistency in ssrf_outbound_cache.go. This improves code readability without altering functionality.
2026-08-10 13:24:14 +08:00
Xi(Darcy) Chen 090612da54 fix: pptx/ppt attachment parsing fails — missing parser engine + markitdown extras (#2621) 2026-08-09 16:23:36 +08:00
Rene ZanderandClaude Opus 5 d823ef61ae fix(vlm): use max_completion_tokens for GPT-5 / o-series vision models
The VLM path sent max_tokens and temperature, both rejected by reasoning
and GPT-5 models. go-openai's reasoning validator failed the request
client-side, so every OCR and caption call errored with "this model is
not supported MaxTokens, please use MaxCompletionTokens" and no image
chunk was ever created.

The chat path already solved this in shapeOpenAIReasoning (issue #1283);
the VLM path was never wired to it. Reuse the shared
provider.IsOpenAIReasoningOrGPT5Model predicate so both paths agree on
which models are affected. Migrating max_tokens alone is not enough --
the VLM default temperature of 0.1 is independently rejected.

Also report an empty completion with finish_reason=length as an error.
max_completion_tokens covers reasoning tokens, so an exhausted budget
returns empty content rather than an API error, which was previously
recorded as no_extracted_content and looked identical to an image with
no text.

Fixes #2537

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-09 08:46:17 +08:00
wizardchen 18739bb1a3 feat(files): add message-scoped proxy for shared-agent chat images
Shared-agent replies can reference resources in the source workspace. Route
those images through a session/message file proxy that derives authorization
from the persisted message and active share, and align the chat renderer to
use the assistant message ID during streaming hydration.
2026-08-07 18:10:16 +08:00
jiahao6635 7ef8e03751 docs: fix 登陆 typo to 登录
Use the standard term 登录 in knowledge-graph docs and a frontend
comment. No behavior change.
2026-08-07 17:04:49 +08:00
MidoriKurage 1d2d623bfd fix(query-understand): fall back to original query on unparsable output 2026-08-07 15:55:48 +08:00
MidoriKurage d763816ebf test(query-understand): pin fallback for unparsable LLM output
Add failing tests for query understanding: RewriteQuery must remain the
original user query if LLM output is unparsable.
2026-08-07 15:55:48 +08:00
wizardchen 5494e669bc fix(auth): harden self-service change password after #2591
Address post-merge review: verify old password before policy checks,
reject same-password rotations, mark OIDC-provisioned users in preferences
and hide the self-service form with guidance, map API error details to
i18n, sync docs/api, Swagger, and the Go client SDK.
2026-08-07 15:49:58 +08:00
jiahao6635 ec4bc8b9a4 feat(auth): add self-service change password in user profile
Expose the existing change-password API in the User Profile settings
page with current / new / confirm fields, shared password policy
validation, and i18n. Align the service layer with registration policy
(8-32 chars, letter + number) and map invalid-old / weak-password
errors cleanly. After success, revoke sessions and return the user to
login.

Fixes #2267
2026-08-07 15:42:12 +08:00
wizardchen f1ef364820 fix(knowledge): harden auto-tagging and let it respect manual tags
Automatic tagging shipped with a few paths that quietly disabled it and a
prompt that spent most of its budget on data the model never needed.

Robustness:
- Treat an omitted confidence as a deliberate selection instead of zero.
  Models frequently drop the field, and the 0.75 floor then filtered out
  every match, silently turning the feature off. Percentage-scale values
  are rescaled rather than accepted as out-of-range certainty.
- Classify the first 500 tags when a knowledge base has more, logging a
  warning, instead of dropping the task entirely. Large knowledge bases
  previously got no auto-tagging at all with no user-visible signal.
- Reuse common.ParseLLMJsonResponse for the model reply, and give that
  helper a balanced-scan fallback. The local extraction cut the payload at
  the last "}" or "]", so a trailing citation such as "see [1]" produced
  invalid JSON and burned the task's retries.

Prompt:
- Address candidates by ordinal rather than UUID. Tag names are short while
  a UUID is 36 characters, so this cuts candidate tokens roughly tenfold,
  keeps the model from having to reproduce (and corrupt) an id, and is what
  makes the raised 500 ceiling affordable. Ordinals are range-checked and
  mapped back to ids server-side.
- Drop the rationale field. Nothing read it, and at max_tags=10 it competed
  with the 1024-token output budget and risked truncating the JSON.
- Fence document text in <document> so file content cannot be read as
  instructions.

Behaviour:
- Add auto_tag_config.skip_if_tagged, defaulting to true, so documents the
  user already tagged at upload time keep their classification. Existing
  tags are now loaded before the model call, so a skipped document costs no
  LLM round-trip. Configs stored without the field adopt the default.

Also promote AddKnowledgeTagRelations to KnowledgeRepository instead of
reaching for it through a type assertion that failed at runtime, and route
the max_tags bounds through AutoTagConfig.Normalize so the prompt, the match
filter and the persisted config cannot drift apart.

Adds handler-level coverage for scope, cancellation, idempotency, ordinal
validation and the new toggle, plus SDK, Swagger and API doc updates.
2026-08-07 15:35:58 +08:00
lkx 926f1ac582 fix(knowledge): address auto-tag review findings 2026-08-07 15:01:01 +08:00
lkx 9426ee1470 feat: 增加自动添加标签的功能 2026-08-07 15:01:01 +08:00
jiahao6635 d7a620d278 fix(tenant): clear stale home tenant after member removal
RemoveMember left users.tenant_id and LastActiveTenantID pointing at the
removed workspace, so login synthesised it back into the space switcher
while RBAC returned 403 on every request.

After a successful soft-delete, clear dangling home/preference pointers
and revoke outstanding sessions. On the login path, validate that home
still has an active membership and stop synthesising memberships from
users.tenant_id when the membership table is authoritative and empty.

Fixes #2586
2026-08-07 14:35:10 +08:00
wizardchen 3d5d8bfcdf docs(readme): replace showcase screenshots with consistent website-docs captures
Swap all README interface showcase images for the latest screenshots from
website-docs/public/screenshots (3840x2112) so widths and heights align.
v0.7.2
2026-08-07 11:37:05 +08:00
wizardchen 89221ba015 docs(release): prepare v0.7.2 release notes and version bump
Update version numbers, CHANGELOG, multilingual READMEs, QA docs,
architecture diagram, and showcase screenshots for the v0.7.2 release.
2026-08-07 11:37:05 +08:00
jiahao6635 9cf8e72ed9 fix(auth): do not sanitize registration password before hashing
SanitizeForLog is for log output and rewrites tabs/newlines/control
characters. Applying it to req.Password during public registration
changed the credential that was hashed, so login with the original
password failed. Match the invite registration path and pass the
password through unchanged.

Fixes #2521
2026-08-07 10:58:41 +08:00
wizardchen ac9656af1d docs(website): use VERSION label in landing footer note 2026-08-06 21:59:01 +08:00
wizardchen b30f369ca3 feat(docker): add custom entrypoint script and update Dockerfile
Introduce a new entrypoint script for the Nginx container to ensure proper startup behavior. Update the Dockerfile to use a stable-alpine Nginx base image and include the entrypoint script, enhancing the deployment process for the documentation site.
2026-08-06 21:59:01 +08:00
wizardchen 84eb205a27 fix(nginx): change server listen port from 80 to 8081
Update the Nginx configuration to listen on port 8081 instead of the default port 80. This change is necessary for serving the documentation site correctly in the current deployment setup.
2026-08-06 21:59:01 +08:00
wizardchen 10293acba3 feat(website-docs): add Dockerfile and Nginx configuration for documentation site
Introduce a Dockerfile for building the documentation site using VitePress and an Nginx configuration for serving the built assets. The Dockerfile sets up a multi-stage build process, while the Nginx config handles routing and caching for the /docs/ path. Update VitePress configuration to set the base path for asset links. This enhances the deployment process for the WeKnora documentation site.
2026-08-06 21:59:01 +08:00
wizardchen 0a310e5327 docs(website): add official site link and inject VERSION at build time
Read the repo VERSION file for footer and landing hero labels, and add navigation to https://weknora.weixin.qq.com from the docs site.
2026-08-06 21:59:01 +08:00
wizardchen 267c847fb8 docs: complete docker compose pull guidance across deployment docs
Follow up on #2567 by documenting the upgrade workflow, syncing JA/KO
READMEs and installation guide, and clarifying that WEKNORA_VERSION
changes require docker compose pull to avoid stale cached images.
2026-08-06 19:58:02 +08:00
wizardchen f266ac4dcf feat(website-docs): add quickstart sample data and local MCP demo
Provide demo documents and FAQ import JSON for onboarding tests, plus a
minimal HTTP Streamable MCP server for validating WeKnora MCP integration.
2026-08-06 19:54:40 +08:00
wizardchen f780f81fc0 docs(website-docs): add comprehensive product documentation site
Import and update WeKnora documentation with VitePress: getting started,
architecture, features, API reference, clients, and development guides.
Includes landing page with inline SVG illustrations, theme components,
doc check scripts, and product screenshots.
2026-08-06 19:54:40 +08:00
lyingbug 8d9309e8fc Revert "docs: add comprehensive WeKnora documentation"
This reverts commit 4aeef20b46.
2026-08-06 19:52:25 +08:00
lyingbug 09e900c779 Revert "feat(docs): initialize WeKnora documentation site with VitePress"
This reverts commit 99c483f6eb.
2026-08-06 19:52:25 +08:00
lyingbug fefc2c1dc0 Revert "docs: complete docker compose pull guidance across deployment docs"
This reverts commit 485454a9ea.
2026-08-06 19:51:39 +08:00
wizardchen 485454a9ea docs: complete docker compose pull guidance across deployment docs
Follow up on #2567 by documenting the upgrade workflow, syncing JA/KO
READMEs and installation guide, and clarifying that WEKNORA_VERSION
changes require docker compose pull to avoid stale cached images.
2026-08-06 19:30:55 +08:00
chenjunhong 8fd679a443 docs: add docker compose pull to deployment steps to prevent stale images
Users downloading a release and running `docker compose up -d` may get
cached old images because Docker doesn't pull by default. This caused
confusion when the UI displayed an older version than the release.

- Add `docker compose pull` before `up -d` in both README and README_CN
- Enable WEKNORA_VERSION in .env.example so users can pin a release tag

Closes #2560
2026-08-06 19:24:33 +08:00