Skip to content

v2026.06.10#409

Merged
duguwanglong merged 64 commits into
mainfrom
dev
Jun 10, 2026
Merged

v2026.06.10#409
duguwanglong merged 64 commits into
mainfrom
dev

Conversation

@stephamie7

Copy link
Copy Markdown
Contributor

No description provided.

John Yin and others added 30 commits June 3, 2026 17:07
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
fix(log): restructure log directory retention
)

Skip installing the current project during Windows self-upgrade dependency sync to avoid transient hatchling file traversal failures, and keep flockshub resources out of wheel build metadata.

Co-authored-by: Cursor <cursoragent@cursor.com>
Persist and resolve TDP service origins without /config/api or /api/v1
segments. Add handler and secrets normalization with tests, fix TDP
plugin test paths, and remove obsolete docs.
* feat(workspace): treat jsonl as text and stabilize Files tab loading

Add .jsonl to workspace text extensions with API/UI coverage, and fix
racey directory loads plus unstable toast deps that re-triggered list fetches.

* fix(workspace): cap text preview size and disable edit when truncated

Limit workspace/memory file reads via FLOCKS_WORKSPACE_MAX_READ_BYTES (default 2MB),
return truncation metadata, and show a read-only preview banner in the WebUI.
* fix(session): recover orphaned running tools after server restart

Mark persisted running tool parts as interrupted after unexpected server exits so session history no longer shows stale in-progress tools. Add startup, session-read, and session-loop recovery coverage with regression tests for idle and busy sessions.

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

* fix(session): avoid duplicate orphan tool scans in message listing

Reuse preloaded message parts during orphan tool recovery so GET /message no longer performs a redundant scan before returning results.
Extract shared graph layout for branch/loop routing, add edge property
panel and join conflict settings, and refresh node/edge styling in the editor.
* feat(workflow): unify trigger integrations and simplify setup

Make workflow.json the source of truth for trigger definitions and consolidate the workflow integration UI around API publishing plus four trigger entrypoints. This removes legacy trigger resurrection and streamlines the trigger configuration experience.

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

* feat(workflow): route ingest triggers through unified dispatcher

Wire Kafka and Syslog managers through EventDispatcher so filter, mapping,
and trigger IDs match unified definitions. Add webhook HMAC verification,
singleton trigger validation, public webhook auth bypass, and runtime
adapter reload when custom trigger config changes.

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

* chore: move contributing guide to root and ignore docs/

Add docs/ to gitignore, stop tracking local documentation, and point
README links at CONTRIBUTING.md. Simplify workflow trigger editor UI by
removing preview/test mapping panels and unused adapter controls.
- Enable MULTI_GROUP_ENABLED by default in backend (env var to opt out)
- Refactor DeviceIntegration page with left sidebar for room navigation
  - GroupSidebar with inline create / rename / delete for rooms
  - "All Rooms" aggregate view with collapsible per-room sections
  - Collapse-all / expand-all toggle when multiple rooms are present
- Fix sidebar height: route /devices as fullscreen to bypass min-h-full
  wrapper that breaks flex height propagation chain
- Room assignment in DeviceConfigPanel: dropdown (editable) when viewing
  "All Rooms", read-only field when viewing a specific room or editing
- Add i18n (zh-CN / en-US) for all hardcoded strings in device page;
  register "device" namespace in i18n.ts
- Align page header icon with other pages (ServerCog w-8 h-8)
- Update index.test.tsx mocks to cover createGroup / deleteGroup /
  listDeviceTools / updateDeviceTool

Co-authored-by: Cursor <cursoragent@cursor.com>
feat(device): add multi-room support and i18n for device integration
When opening a tool's test panel from within a specific device's
configuration panel, the device UUID (generated at onboarding time)
is now pre-filled as `device_id` in the test parameters JSON.

This resolves the error "当前存在多台同类型设备,调用前必须显式传入
`device_id`" that appeared whenever multiple instances of the same
device type were registered, because the registry's `_resolve_device_target`
could not auto-select a target without an explicit `device_id`.

Changes:
- ToolDetailModal: add optional `deviceId` prop; inject it as the first
  key in the template produced by `buildParamsTemplate`, skipping any
  duplicate `device_id` param entry from the tool's parameter list only
  when the prop is already provided (avoids regression for tools whose
  YAML explicitly declares a required `device_id` parameter)
- ToolDetailModal: show a contextual hint below the params label when
  `deviceId` is pre-filled, so the user knows where the value came from
- DeviceConfigPanel: pass `device?.id` as `deviceId` when opening
  ToolDetailModal from the per-device tools tab
- buildParamsTemplate: fix number/boolean default values to emit actual
  `0` / `false` instead of the string literals `"0"` / `"false"`

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

feat(device): auto-inject device_id into tool test params
Clicking a fixture called setTestParams with the fixture's raw params,
silently overwriting the pre-filled device_id injected by the deviceId
prop. Merge device_id as the first key so it is never lost regardless
of which fixture the user selects.

Co-authored-by: Cursor <cursoragent@cursor.com>
setToolModal(tool) passed the raw tool object whose enabled field
reflects the initial load, ignoring any per-device toggle the user
applied in the same session. Replace with { ...tool, enabled: isOn }
so the modal always receives the current effective enabled state.

Co-authored-by: Cursor <cursoragent@cursor.com>
…l reveal (#349)

* feat(webui): add custom device access wizard (API/WebCLI/Syslog)

Extend Device Integration with custom device onboarding for API, WebCLI,
and syslog modes, including types, panel UI, and tests. Document a third
web2cli capture path when CLI requirements are already specified.

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

* feat(webui,web2cli): align WebCLI custom device with device plugin flow

Require skill integration first, then optional device plugin packaging for
security devices. Add cli-in-device reference, tighten session prompts and
provider description guidance, and update custom device access UI/tests.

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

* feat(device,web2cli): reveal persisted secrets and streamline CLI docs

Add an explicit credentials endpoint so the device UI can show full
masked secrets on demand. Update web2cli to document cookie/auth-state
defaults and replace the spec-generation step with cli-requirements.

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

* feat(web2cli,webui): document optional auth recovery credentials

Allow optional username/password for browser-based cookie recovery
after auth-state expires, and align custom device session prompts
with the updated cli-in-device guidance.

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

* feat(device,webui): scope credential reveal and add audit trail

Switch credentials reveal to POST with per-field requests, emit
device.credentials_reveal audit events without logging secrets, and
localize the custom device access UI.
…E_ID handlers

_config_override_service was set to the bare service_id (e.g. "sangfor_af")
derived by storage_key_to_service_id(), but several device handlers declare
SERVICE_ID as the full versioned storage key (e.g. "sangfor_af_v8_0_48").
get_config_override() performed an exact match, so these handlers always
got None and silently fell back to the global default config — using the
plugin's hardcoded DEFAULT_BASE_URL (192.168.1.1) instead of the device's
configured IP (e.g. 10.201.255.17).

Fix:
- _build_overrides() now returns a 4-tuple including storage_key
- activate_device_credentials() stores storage_key in a new ContextVar
  _config_override_storage_key alongside the existing service_id var
- get_config_override() accepts a match on either bare service_id OR
  full storage_key, so all handler SERVICE_ID conventions work correctly

Affected handlers (non-exhaustive):
  sangfor_af_v8_0_48, sangfor_af_v8_0_85, sangfor_af_v8_0_106

Co-authored-by: Cursor <cursoragent@cursor.com>
* feat(session): add write file links and concise workflow tool output

Append clickable local-file Markdown links to write tool results in session
output, omit verbose workflow execution history from default run_workflow text
while keeping it in metadata, and strip reasoning block whitespace on both ends.

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

* refactor(session): drop runner-side write tool file link formatting

Remove clickable Markdown link injection from session runner write output;
workflow concise output and reasoning strip changes remain unchanged.

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

* feat(workflow): show live stage in WebUI and forward session cancel

Expose workflow_name and total_nodes in run_workflow metadata, forward the
session abort flag to the workflow runtime, and render a compact running-stage
summary in the session tool header.

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

* fix(session): propagate abort to tools and guard late metadata updates

Forward the session abort event into StreamProcessor tool execution,
mark metadata callbacks finished in a finally block, ignore stale running
updates after completion, and persist interrupted tool state on cancel.

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

* fix(session): cancel inflight metadata tasks and localize workflow header

Cancel pending running-metadata publish/persist tasks when a tool completes,
and use i18n labels for run_workflow stage summaries in the WebUI header.

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

* feat(workflow): make llm.ask cancellable and show cancelling UI state

Propagate workflow cancel checks through LLM nodes, lazy llm helpers,
and provider calls, then surface a cancelling phase in workflow detail
run/history views with localized status messaging.

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

* fix(workflow): add cancel_checker to sandbox python runtime

Declare cancel_checker on SandboxPythonExecRuntime and update sandbox
tests to match the keyword-aware get_lazy_llm factory.
B1 (ToolDetailModal): { device_id: deviceId, ...fx.params } had the spread
order backwards — a fixture that already carries a device_id key would
overwrite the prop-injected value, exactly undoing the fix. Swap to
{ ...fx.params, device_id: deviceId } so the parent-supplied deviceId
always takes precedence regardless of fixture contents.

S1 (credential_context): 'and' binds tighter than 'or', so the guard
  if secret_ovr is None and config_ovr is None or service_id is None
was already evaluated correctly, but was easy to misread as
  if secret_ovr is None and (config_ovr is None or service_id is None).
Add explicit parentheses to match the intended semantics at a glance.

Co-authored-by: Cursor <cursoragent@cursor.com>
S2 — Add unit tests for get_config_override dual-key matching
  New test file tests/tool/test_credential_context_config_override.py
  covers 7 scenarios without touching the DB or ToolRegistry:
  · bare service_id match (existing behaviour)
  · versioned storage_key match (new behaviour, regression target)
  · unrelated service_id → None
  · no active override → None
  · storage_key=None does not match empty string (falsy trap)
  · service_id=None does not match empty string (falsy trap)
  · identical service_id and storage_key (no version suffix)

S3 — Improve readability of the dual-key match in get_config_override
  Replace 'service_id in (expected_service, expected_storage)' with
  explicit named booleans (matches_service / matches_storage) and an
  expanded docstring that explains the two naming conventions handlers
  use, so future readers do not mistake either branch as redundant.

S4 — _build_overrides return type → _DeviceOverrides NamedTuple
  Positional 4-tuples are fragile: a caller adding or reordering fields
  silently shifts every unpack site. Introducing _DeviceOverrides makes
  field access self-documenting (.service_id, .storage_key, …) and lets
  type-checkers catch missing fields at import time.

Co-authored-by: Cursor <cursoragent@cursor.com>
- Add autouse fixture _reset_context_vars that clears the three
  ContextVars before and after every test; without it a test that sets
  a var leaks state into the next test in the same thread
- Remove bare 'import pytest' that was unused before the fixture was
  added (would have triggered a lint warning)

Co-authored-by: Cursor <cursoragent@cursor.com>
…-drops-device-id

fix/device tool test fixture drops device
…ingtalk, telegram

Apply PR #190 (wecom inbound + outbound file attachments) and extend the
same pattern to dingtalk and telegram. Refactor the inbound dispatcher
into a per-channel hook registry so new channels no longer need to
modify dispatcher.py.

Inbound (download to local FilePart):
- wecom: AES-256-CBC decrypt via wecom_aibot_sdk, 30MB cap, nested
  mixed-message aeskey, Content-Disposition filename extraction
- dingtalk: exchange download_code via OAPI /v1.0/robot/messageFiles/download,
  20MB cap, separate exchange/download error classification
- telegram: resolve telegram://<kind>/<file_id> via getFile +
  https://api.telegram.org/file/bot<token>/<file_path> download

Outbound (send_media per channel):
- wecom: SDK upload_media → send_media_message / reply_media; companion
  text sent as a follow-up markdown message
- dingtalk: OAPI multipart upload → msgKey=file (downloadCode+fileName)
  for any type; msgKey=image (photoURL) for remote image URLs
- telegram: route to sendPhoto / sendDocument / sendVideo / sendAudio /
  sendVoice / sendAnimation based on inferred kind; agent can force
  document via telegram:document:<url> prefix

Dispatcher:
- register_inbound_media_downloader() + _DOWNLOADERS table
- dynamic per-channel lookup so test monkeypatches on the channel's
  inbound_media module still apply
- SSE message.part.updated events for both FilePart and the rewritten
  text part; placeholder text replaced with 'Attached files: <path>'

Tests:
- wecom: +14 (send_media, inbound_media, content-disposition, mixed file)
- dingtalk: +9 (download_code exchange, oversized guard, send_media
  routing, text-after-file, image URL inline)
- telegram: +15 (file_id resolution, kind inference for image/pdf/gif/ogg,
  endpoint routing, kind override prefix, error path)
- dispatcher: +9 (per-channel routing, placeholder detection,
  end-to-end per-channel pipeline)
- test_e2e_file_roundtrip.py: 7 new tests covering real PNG byte
  round-trips for all five channels with in-process fake servers

All 354 channel tests pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Documents the bidirectional file/image contract for all built-in
channels, the dispatcher refactor, the per-channel downloader hook
pattern, and the channel-specific outbound quirks reviewers need
to know before approving changes to the media path.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…escription)

The channel file/image review notes are better kept in the PR
description itself (where reviewers see them first) than in a
root-level doc that the gitignore policy excludes from the
docs/ folder.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ge points, impact scope, and review focus

Rewrite the "Pull Request Guidelines" section in CONTRIBUTING.md so the
required PR description structure is explicit:

- Key Changes (改动点) — concrete deltas grouped by area.
- Impact Scope (影响范围) — user-visible behavior, compatibility,
  configuration, dependencies, performance, security.
- Business Logic to Focus On During Review (需重点 Review 的业务逻辑) —
  the parts of the change that deserve extra reviewer attention.

The previous section listed five reviewer-facing questions but did not
constrain the order or depth of the description, which led to PRs that
mentioned the impact but omitted the logic that needed a careful read.

Also update the PR description template to match the new structure and
add a Why-This-Approach section plus an explicit Compatibility, Migration
& Rollback section.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
PR #380 added flex flex-col to the shared content wrapper for the
/devices page height chain, which unintentionally changed home and
other standard page layout. Keep /devices on the fullscreen route and
restore the v2026.6.4 wrapper for all other pages.
Add admin-managed user-defined pages with backend build/watch/runtime support and a WebUI host for published pages.
xiami762 and others added 26 commits June 9, 2026 09:34
* refactor: unify subagent delegation under delegate_task

Consolidate task scheduling into delegate_task (task becomes a compat alias),
remove plan mode and standalone background tools, and run independent foreground
subagents in parallel. Update WebUI cards, skill installer, and agent configs.

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

* fix/skill remove

* fix/skill install skill.sh

* fix(webui): render parallel delegate tasks as separate cards

Remove buildParallelDelegateGroupParts which merged multiple sibling
delegate_task tool parts into a single 'Parallel Agents' card. Each
parallel subagent now renders as its own DelegateTaskCard with its
real subagent_type name, matching the user-facing expectation of
'one tool card per agent'.

* refactor(delegate_task): remove legacy tasks=[...] batch shape

The unified delegate_task tool only needs the single-subagent shape now
that parallel work is expressed as multiple sibling tool calls in one
assistant turn. Drop the batch path from delegate_task, the task compat
alias, the stream-processor branch that aggregated it into one card, and
the matching batch compat tests; replace the latter with a small
tolerance test for the slimmer schema and adjust model-pinning tests
accordingly. Also remove the now-redundant fallback to the
load_skills-aware description in the webui DelegateTaskCard since the
card already renders the explicit description when provided.

* Fix legacy todo permission migration
…w-usability

# Conflicts:
#	webui/src/components/common/SessionChat.tsx
Revert PR #398 changes that touched workflow pages and workflow-local config support.

This removes the workflow detail UI tuning, edit markdown/config APIs, generated config templates, and matching test/mock updates while keeping later dev commits intact.
revert(workflow): restore pre-pr398 workflow experience
* feat(device): unify device plugin intake

* refactor(device): streamline custom intake chat

* refine device intake layout and webcli guidance
* feat: improve device integration auto-sync

* fix: harden device refresh auto-provisioning
@duguwanglong duguwanglong merged commit dd82bac into main Jun 10, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants