Commit Graph
74 Commits
Author SHA1 Message Date
RockChinQ 68a3f64cef test(core): update bot fixtures for platform policy checks 2026-10-15 05:31:04 +00:00
Hyu e29fd27f02 feat(i18n): localize backend messages by workspace language 2026-10-15 05:31:04 +00:00
Hyu 09a84f6642 fix(provider): preserve streaming when removing thinking content 2026-10-12 13:30:17 +08:00
Hyu 1c70218383 feat: reset bot session context while retaining monitoring history 2026-10-10 22:35:27 +08:00
Hyu 40a3a941a3 fix(monitoring): unify execution records and stabilize streaming cleanup 2026-10-08 03:02:37 +08:00
Hyu 9f76037e64 feat(monitoring): unify execution views and trace tool calls 2026-10-07 22:36:10 +08:00
Hyu 4482e8d876 feat(telemetry)!: upload one record per execution node and one closure per chain
Core no longer assembles a whole trace locally. Every workflow node is uploaded
the moment it completes as its own `execution_node` record, and each execution
closes with exactly one `execution_chain` record; all records of one execution
carry the same `event_id`, so Space groups them back into a single chain.

- every execution starts at an inbound event: event-less Pipeline lanes and
  WebUI/API debug runs synthesize their virtual inbound event at the boundary
  and are marked debug=true, so a Runner is never a trace origin
- sampling is decided once per event from a stable hash of the event id (the
  previous `int(id[:8], 16)` raised on every `platform:`-prefixed id and so
  dropped every successful inbound-event chain) and is reported on each record
  as sample{mode,denominator}; the default mode is now `all`
- the local trace buffer, the 120s TTL, the per-process trace cap and the shared
  open-node mirror are gone, which also removes the truncated-chain upload and
  the re-buffered-closed-trace leak they caused
- a broken chain is always uploaded, and its reason falls back to the first
  failed node so the chain explains itself
- flush keeps records until the sender accepts them and counts what it drops;
  telemetry health replaces the unused send-task queue
- heartbeat reports bound Agent / plugin-processor / event-binding counts
- bound Pipeline and Agent resources (plugins, MCP servers, knowledge bases,
  tools with their Host source, skills, models and the Runner schema selectors
  that picked them) are reported on the chain record
- failure text is bounded and redacted instead of passing exception text through
- the dead per-query feature counters and their call sites are removed

Wire contract: schema 2 (`execution_node` / `execution_chain`).
2026-10-07 09:41:41 +08:00
Hyu 5a31ac75fc style(tools): format the sandbox interpreter and skill tool changes with ruff 2026-09-30 18:45:00 +08:00
Hyu 4fc700b7e0 fix(tools): hide register_skill when Cloud sandboxes cannot scan host directories
scan_skill_directory is disabled for Cloud-managed sandboxes, but the
register_skill tool was still advertised to the model whenever a backend was
available, so every call failed closed without a usable explanation. Advertise
register_skill only when the runtime may scan sandbox directories, and keep
activate available in both modes.
2026-09-30 18:44:16 +08:00
Hyu ff3f321120 fix(tools): resolve the sandbox interpreter for workspace file scripts
The workspace file tools (read/write/edit/glob/grep) ran a script through
`python`, which a sandbox built from a host rootfs may not provide: those hosts
ship `python3` only, and a read-only /usr prevents creating a `python` shim
inside the jail. Every file tool then failed with `/bin/sh: 1: python: not
found`. Resolve the interpreter with `command -v python3 || command -v python`,
matching the interpreter the Box service already uses for its own scripts.
2026-09-30 18:44:16 +08:00
RockChinQ e77acfa3ab fix(box): align integration tests with runner-owned bindings 2026-09-18 01:07:43 +08:00
RockChinQ b264d46d77 feat: delegate sandbox policy to runners and simplify pipeline migration 2026-09-17 23:05:27 +08:00
RockChinQ 8c119bc4b6 feat: add verified manual pipeline migration for plugin runners 2026-09-16 18:13:11 +00:00
RockChinQ 273b1ea3cf Merge master into dev/4.11.x and preserve plugin runner architecture
Reconcile migration branches without rewriting published revisions; retain additive Codex, monitoring, provider and platform fixes. Keep dynamic runner schemas and Host ownership, restore compatibility regressions, and preserve safe model-test error handling.
2026-09-16 08:13:07 +00:00
RockChinQ f24a7c9bb2 feat(runner): unify plugin execution across agents and event processors 2026-09-10 18:04:38 +08:00
huige66631andRockChinQ ce6b647fe7 feat(mcp): detect OAuth-protected remote MCP servers (#2363)
* feat(mcp): surface OAuth-required server tests

* fix(mcp): show connection failure details in status cards

---------

Co-authored-by: RockChinQ <[email protected]>
2026-09-09 16:13:33 +08:00
Hyuanddadachann 0f216a0d4d feat(provider): support Codex subscriptions with ChatGPT sign-in (#2513)
* feat(provider): support Codex subscriptions with ChatGPT sign-in

* style: format Codex live integration test

* fix(provider): preserve Codex identity in temporary model tests

* fix(web): portal provider selector without dialog overflow

* fix(web): allow native scrolling in provider dropdown

* fix(provider): surface safe Codex quota and upstream errors

* fix(web): provide reliable Codex copy feedback in dialogs

* feat(provider): confirm cascade deletion from edit dialog

* fix(persistence): discard connections after failed commit

* fix(web): polish provider loading and confirmation motion

---------

Co-authored-by: dadachann <[email protected]>
2026-09-06 23:31:02 +08:00
RockChinQ 75f117ae50 fix(provider): preserve explicit streaming finish reasons 2026-09-06 00:33:20 +08:00
Hyu 8f0a55a1f4 fix(agent-debug): stream execution traces with platform mocks and coverage 2026-09-05 15:34:29 +08:00
Hyu fde04e64f6 Merge remote-tracking branch 'origin/master' into dev/4.11.x
# Conflicts:
#	src/langbot/pkg/api/http/controller/groups/pipelines/pipelines.py
#	src/langbot/pkg/api/http/service/bot.py
#	src/langbot/pkg/provider/runners/localagent.py
#	src/langbot/templates/metadata/pipeline/ai.yaml
#	tests/unit_tests/api/service/test_bot_service.py
#	tests/unit_tests/provider/runners/test_difysvapi_runner.py
#	tests/unit_tests/utils/test_safe_regex.py
#	web/src/app/infra/entities/adapter-categories.ts
#	web/src/app/wizard/page.tsx
#	web/src/i18n/locales/en-US.ts
#	web/src/i18n/locales/ja-JP.ts
#	web/src/i18n/locales/zh-Hans.ts
#	web/tests/e2e/plugin-page-auth.spec.ts
2026-08-31 17:17:47 +08:00
NeosandHyu e69a80f5e9 Windows 兼容性修复 + Dify API 适配 + 企微 WS 加载优化 (#2470)
* fix: Windows fsync requires write access to file descriptor

- _fsync_file: os.O_RDONLY -> os.O_RDWR (Windows _commit() requires write access)
- _fsync_directory: tolerate OSError on fsync and os.open (chmod 0o700 blocks access on Windows)

* fix: Dify SSE empty data lines and upload response format mismatch

- Skip malformed/flushed SSE data lines (JSONDecodeError)
- Accept HTTP 200 besides 201 for file upload response
- Unwrap data wrapper in upload response (resp.get('data', resp))

* feat: WeCom WS mode sends empty initial stream frame for loading spinner

Send an empty reply_stream frame immediately after stream session
creation so the WeCom client shows its built-in loading indicator
while the pipeline processes the message (e.g. RAG retrieval).

* fix(compat): harden Windows, Dify, and WeCom changes

* fix(migration): clean interrupted SQLite temp files

---------

Co-authored-by: Hyu <[email protected]>
2026-08-29 22:34:10 +08:00
fishzjp b66db86bff fix(provider): stringify MCP tool results for OpenAI-compatible APIs (#2476)
execute_func_call returns list[ContentElement] for MCP tools, but the
runner assigned that list directly to the tool-message content. The
OpenAI chat-completions spec requires tool-message content to be a
string, so OpenAI-compatible endpoints return HTTP 500 when the raw
list is sent.

Serialize the list to a string before building the tool message, using
ContentElement.__str__ which returns the text payload for text elements
and a human-readable placeholder for images and files. Fixes #2457.
2026-08-27 18:19:04 +08:00
fishzjp 95b8736e93 fix(provider): tolerate trimmed image parts in litellm message conversion (#2475)
SessionManager clears image_base64 on past turns to save memory, and
exclude_none serialization drops the hollowed field entirely, so a
replayed history part can arrive as {'type': 'image_base64'} with no
payload. The converter accessed the missing key unconditionally and
raised KeyError on every turn after an image was sent.

Prefer the base64 payload when present, fall back to an image_url that
survived on the same element, and drop hollow parts otherwise (same
strategy as the existing file-part handling). Fixes #2469.
2026-08-27 18:07:43 +08:00
Junyan Qin f94243c725 chore: merge master into dev/4.11.x 2026-08-14 16:04:52 +08:00
Dongchuan Fu e37987215e feat(provider): add pipeline reasoning controls (#2373)
* feat(provider): add pipeline reasoning controls

* fix(provider): preserve local agent model compatibility

* refactor(web): use shadcn reasoning slider

* fix(runtime): stabilize reasoning chat delivery

* fix(provider): route reasoning controls by model family

* fix(provider): handle hosted Kimi reasoning protocols

* fix(provider): map qwen reasoning levels to budgets

* fix(provider): preserve think tags in streamed reasoning

* fix(provider): preserve reasoning tool metadata

* style(provider): satisfy ruff checks after merge

* fix(persistence): preserve reasoning migration compatibility
2026-08-09 17:38:01 +08:00
huanghuoguoguo 79611a5513 fix(agent): harden runner integration and QA 2026-08-01 09:23:41 +08:00
huanghuoguoguo 55f42a4ebc chore(merge): sync master into dev/4.11.x 2026-07-31 19:29:38 +08:00
RockChinQanddadachann e1ac5e0fc8 feat(tenancy): add Workspace multi-tenant foundation (#2353)
* Document multi-tenant workspace architecture

* Add OSS and commercial workspace boundaries

* docs: redesign multi-tenant workspace architecture

* feat(tenancy): implement workspace isolation

* docs(tenancy): record verification evidence

* docs(tenancy): revise single-instance SaaS topology

* docs(tenancy): refine architecture options

* docs: finalize cloud v2 multi-tenant decisions

* feat(tenancy): establish cloud isolation foundations

* feat(tenancy): harden shared cloud runtime boundaries

* docs(tenancy): record final isolation verification

* fix(tenancy): close isolation and permission gaps

* docs(tenancy): record final isolation verification

* feat(tenancy): connect cloud workspace control plane

* fix(build): install git for pinned SDK

* docs(cloud): update control plane verification

* chore: update multi-tenant SDK pin

* fix(cloud): skip legacy model sync during startup

* test(cloud): preserve minimal model manager fixtures

* fix(cloud): preserve authenticated account context

* fix(cloud): reuse authenticated account for user info

* feat(cloud): complete Workspace settings navigation

* test(web): cover Workspace dropdown menu

* feat(web): place workspace controls in sidebar

* refactor(web): streamline workspace controls

* style(web): format workspace layout test

* fix(cloud): surface runtime and workspace plan status

* fix(plugin): keep runtime identity stable across restarts

* fix(ui): widen and center workspace switcher

* fix(ui): hide roles from workspace switcher

* fix(ui): align workspace switcher with sidebar entries

* feat(workspace): add in-product collaboration and direct Cloud launch

* style: format collaboration changes

* fix(workspace): bind collaboration APIs to tenant UoW

* fix(cloud): preserve Core-owned collaboration state

* test(cloud): require Space identity for invite registration

* feat(cloud): complete secure invitation experience

* style(web): format invitation flows

* fix(cloud): recover box runtime without unscoped skill reload

* feat(oss): enforce invitation account and owner billing flows

* style: format OSS account service

* test(oss): cover invitation logout handoff

* fix(oss): resolve workspace owner in scoped session

* feat(cloud): harden multi-tenant runtime resources

* fix(cloud): bound runtime restart storms

* fix(cloud): eliminate periodic runtime CPU spikes

* fix(cloud): enforce instance capacity ceilings

* fix(cloud): scope public login capability discovery

* fix(cloud): bound tenant maintenance and monitoring work

* fix(runtime): bound tenant resource amplification

* fix(deps): pin green multi-tenant plugin SDK

* fix(cloud): handle unavailable skill capability

* fix(security): require authentication for image file endpoint (H-2)

- Changed /api/v1/files/image from AuthType.NONE to USER_TOKEN_OR_API_KEY
- Added Permission.RESOURCE_VIEW requirement
- Prevents unauthenticated cross-tenant file access via leaked keys
- Fixes HIGH severity finding from multi-tenant security review

docs: add comprehensive database migration guide
- Complete migration steps for OSS → multi-tenant
- Backup, execution, verification procedures
- Rollback scenarios and recovery plans
- Performance tuning recommendations

* test: add comprehensive cross-tenant isolation tests

Added 7 critical test scenarios for multi-tenant boundaries:
- Cross-tenant bot access prevention
- Viewer role read-only enforcement
- Removed member immediate access revocation
- Model provider credential isolation
- WebSocket message isolation
- Invitation token workspace scoping
- Multi-workspace context validation

These tests address P0-2 coverage gaps for:
- workspaces.py (membership & invitation flows)
- user.py (authentication & authorization)
- websocket_chat.py (real-time isolation)
- plugins.py (resource access control)

docs: finalize database migration guide

* fix(security): resolve M-1, M-2, M-3 security findings

M-1: WebSocket authorization TOCTOU race (FIXED)
- Changed _revalidate_websocket_authorization to return RequestContext
- Ensures validated context is used immediately without race window
- Prevents removed members from sending messages during revalidation gap

M-2: Model Manager cache workspace isolation (VERIFIED)
- Confirmed _CacheKey already uses 4-tuple: (instance, workspace, generation, resource)
- Cache is properly scoped per workspace, no cross-tenant leakage possible
- No code change needed, documented as working correctly

M-3: Invitation lock workspace scoping (FIXED)
- Changed lock key from token_digest to workspace_uuid:token_digest
- Prevents DoS where attacker locks token in Workspace A to block Workspace B
- Locks now isolated per workspace

All MEDIUM severity findings from security review now resolved.

* fix(cloud): unblock tenant CI and enforce knowledge quotas

* fix(tenancy): scope rerank model sync

---------

Co-authored-by: dadachann <[email protected]>
2026-07-30 21:43:35 +08:00
Hyuandchan dd8d1007a1 feat: support Space rerank models (#2358)
Co-authored-by: chan <[email protected]>
2026-07-26 16:37:34 +08:00
Junyan Qin 283c6949f4 fix(mcp): validate tool call timeout config 2026-07-23 18:26:41 +08:00
Junyan Qin 0dfae76e39 fix(mcp): make tool call timeout configurable 2026-07-23 18:26:37 +08:00
Junyan Qin 73e47ea2d4 fix(mcp): keep waiting for box recovery 2026-07-23 17:41:27 +08:00
Junyan Qin 06e03af994 fix(runtime): complete reconnect recovery paths 2026-07-23 17:28:31 +08:00
Junyan Qin 998b76d53a fix(runtime): make plugin and box connectors resilient 2026-07-21 18:43:24 +08:00
Junyan Qin 1765c43262 Revert "fix(runtime): make plugin and box connectors resilient"
This reverts commit 0b461e5830.
2026-07-21 18:43:01 +08:00
Junyan Qin 0b461e5830 fix(runtime): make plugin and box connectors resilient 2026-07-21 18:41:22 +08:00
DongXiaoming 76c5003c21 fix(localagent): stop re-seeding stream accumulator with previous round content (#2329)
When the LLM (e.g. MiniMax-M3) returns multiple rounds after tool calls, the _StreamAccumulator was initialized with initial_content=first_content, causing every subsequent round to repeat the entire first message. Remove the re-seeding so each round starts with a clean accumulator.

Add regression test verifying multi-round tool call content is not duplicated.
2026-07-20 16:38:11 +08:00
huanghuoguoguo 8afab5fa49 fix(mcp): recover box stdio sessions after disconnect 2026-07-19 22:47:09 +08:00
huanghuoguoguo cfa7c7b336 fix(tools): support skill mount root discovery 2026-07-19 22:46:01 +08:00
huanghuoguoguo 54c872b74f fix(agent-runner): close sandbox skill authoring flow 2026-07-19 22:46:01 +08:00
huanghuoguoguo c55be79f9f fix(agent-runner): prepare local runner functional tests 2026-07-19 22:46:01 +08:00
huanghuoguoguo d88d05e27c feat(agent-runner): enforce 4.x host-owned execution 2026-07-19 22:46:01 +08:00
huanghuoguoguo 9aa71d54e3 feat(agent-runner): finalize 4.x processor integration 2026-07-19 22:45:15 +08:00
huanghuoguoguo 662627142e test(agent-runner): strengthen local agent e2e gate 2026-07-19 22:42:40 +08:00
huanghuoguoguo 5ab1e36eba test(provider): support fake token counting 2026-07-19 22:41:31 +08:00
huanghuoguoguo 517986bd10 feat(agent-runner): support scoped token counting 2026-07-19 22:41:31 +08:00
huanghuoguoguo 07a19136c6 test(agent): remove obsolete local agent runner attachment tests 2026-07-19 22:41:30 +08:00
huanghuoguoguo 5f65f962c5 feat(skill): unify skill activation as authorized tools
Expose skill tools (activate/register_skill/native exec) like native tools
instead of gating them behind the skill_authoring capability:
- toolmgr.get_all_tools drops include_skill_authoring; SkillToolLoader
  self-gates on sandbox + skill_mgr
- preproc drops the include_skill_authoring branch; pipeline-bound skills
  and the skills resource gate on skill_mgr presence

Persist activated skills into host.activated_skills conversation state so
they survive across runs (host writes at activate; last-write-wins); drop
the dead restore_activated_skills helper.

Prefill ToolResource.parameters host-side (tool_mgr.get_tool_schema) so
runners build LLM tools without per-tool get_tool_detail round-trips.

Align agent-runner-pluginization design docs to the all-tool model.
2026-07-19 22:41:30 +08:00
huanghuoguoguo cb9930c9e4 feat(agent-runner): add plugin runner host integration 2026-07-19 22:41:30 +08:00
DongXiaomingandWangCham c53b800267 fix(provider): strip think tags for MiniMax-M3 and other OpenAI-compatible models (#2330)
* fix(provider): strip think tags for MiniMax-M3 and other OpenAI-compatible models

MiniMax-M3 (and other OpenAI-compatible providers) emit chain-of-thought
reasoning directly in the content field wrapped in  tags, instead
of using a separate reasoning_content field or the legacy CRETIRE_REASONING
markers. The existing remove_think logic only handled CRETIRE_* tags, so
think blocks leaked into user-visible output even when remove_think was enabled.

- Add _ThinkStripState: a stateful filter that correctly handles  tags
  split across streaming chunk boundaries.
- Add _strip_think classmethod with regex patterns for both  and
  CRETIRE_* tags.
- Wire think_state into invoke_llm_stream so deltas are filtered before
  reaching the accumulator.
- Add remove_think safety net in _StreamAccumulator so the final message
  from tool-call rounds also gets stripped.
- Fix remove_think resolution to use defensive nested .get() so
  pipelines missing output.misc don't raise AttributeError.

* fix(litellmchat): add missing _CLOSE_TAG class attribute on _ThinkStripState

* fix(provider): handle think stripping across LiteLLM paths

---------

Co-authored-by: WangCham <[email protected]>
2026-07-15 10:54:41 +08:00