Skip to content

v2026.06.18#461

Merged
duguwanglong merged 180 commits into
mainfrom
dev
Jun 18, 2026
Merged

v2026.06.18#461
duguwanglong merged 180 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.
duguwanglong and others added 27 commits June 17, 2026 11:31
Add backend config-store authentication guidance to workflow chat and publish guide prompts so Rex uses the server_api_token bearer flow against the backend API.

Cover the workflow detail and integration prompt paths with assertions for server_api_token and Authorization headers.
Fix device plugin loading and config defaults
Keep API service driver switching available after publish and guard async operations against stale UI state.

Avoid duplicate dynamic ports by reserving persisted and in-flight service ports, and release reservations on failed local or Docker publishes.

Render stale API service records as stopped without persisting stoppedAt so autostart can still recover them.
fix(workflow): prevent workbench interaction timeouts
Pin LiteLLM to 1.83.7 to include the fix for the MCP stdio command injection vulnerability in the test connection and tools list endpoints.
fix(workflow): stabilize docker publish startup
…op-timeout

fix: prevent DingTalk stream from blocking event loop
fix(cli): constrain typer below incompatible release
…-jsx

Fix workflow integration tab JSX closure
Remove bundled Hub catalog entries that reference missing Anthropic skill manifests.

Fix the IntegrationTab test mock object so eslint can parse the suite.
* perf: optimize session page loading

* fix: avoid restoring last session on initial load

* fix: gate last session restore by entrypoint

* fix: preserve optimistic sessions during list refresh

* fix: address session pagination review issues
* fix(log): restructure log directory retention

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

* fix(log): address retention review feedback

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

* fix(updater): avoid Windows project install during dependency sync (#373)

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>

* fix(tdp): normalize base_url by stripping UI/API path suffixes (#376)

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): jsonl text preview and Files tab load stability (#367)

* 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 (#370)

* 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.

* feat(webui): improve workflow graph layout and editor edge UX (#379)

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 trigger integration (#375)

* 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.

* feat(device): add multi-room support and i18n for device integration

- 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): auto-inject device_id into tool test params

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>

* fix(device): preserve device_id when applying a test fixture

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>

* fix(device): sync toolEnabled state into ToolDetailModal on open

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>

* feat(webui,device,web2cli): custom device access wizard and credential 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.

* fix(credential-context): resolve config override for versioned SERVICE_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 concise workflow tool output (#381)

* 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.

* fix: correct merge order and operator precedence from review

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>

* refactor(credential-context): address S2/S3/S4 from PR review

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>

* test: fix ContextVar isolation and remove unused import

- 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>

* feat(channel): complete bidirectional file/image support for wecom, dingtalk, 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>

* docs(channel): add review guide for file/image attachment support

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>

* docs(channel): remove standalone review guide (move content into PR description)

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>

* docs(contributing): restructure PR description guidelines around change 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>

* build(deps): bump starlette to >=1.0.1

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

* fix(webui): remove global flex-col wrapper from standard pages (#384)

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.

* feat(user-defined-pages): add custom page runtime (#389)

Add admin-managed user-defined pages with backend build/watch/runtime support and a WebUI host for published pages.

* Fix Telegram file roundtrip media upload

* Fix channel media filename and caption handling

* fix(provider): thinking params (#387)

* fix(provider): send enable_thinking for catalog-declared interleaved models

Trace ses_1628dfe6cffe1i5xZY9lv1u20m showed GLM-5 on alibaba returning
finishReason=stop with empty content + zero tool calls on every turn, so
the agent loop handed the turn back to the user after every step.

Root cause: the request-side dispatch in options.py was a hard-coded
substring whitelist (qwen3 / kimi / mimo / qwq / qwen-max). GLM-5,
minimax-m2.* / m3, deepseek-reasoner and step-3.5-flash all declare
interleaved in the catalog but their model names match none of those
substrings, so enable_thinking: true was never sent. Without the flag,
DashScope / Moonshot / Zhipu / MiniMax / Stepfun / DeepSeek stream their
thinking into content instead of reasoning_content and stop mid-tool-call.

Replace the token-list dispatch with _THINKING_REQUEST_SHAPES, a
provider-id-keyed dict of callables gated on the catalog interleaved
capability. The catalog becomes the single source of truth for "this
model wants thinking-aware streaming"; adding a new provider is one line.

Also fix openai_compatible.py chat() and chat_stream(): both were
silently dropping caller-supplied extra_body whenever kwargs.thinking was
None. This made the user-configured openai-compatible provider ignore
default_parameters.enable_thinking in flocks.json. Now mirrors
openai_base.py:905-913.

Adds tests/provider/test_thinking_params.py with 44 tests:
- Property test: every catalog entry with interleaved != null resolves
  to a thinking flag (regression net for this class of bug)
- Specific GLM-5 step-50 trace replay across alibaba / threatbook-cn /
  threatbook-io / zhipu
- All previously-dropped models (minimax-m2.* / m3 × 3 providers,
  deepseek-reasoner, step-3.5-flash)
- Shape-registry structural checks (no legacy token constant, every
  reasoning provider has a shape entry)
- openai_compatible extra_body propagation smoke test

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

* refactor(provider): drop _deepseek_thinking_shape V3 model-name branching

Follow-up to 2299b33.  The catalog is the single source of truth for
"this model wants thinking-aware streaming" — the V3 string checks
(re)introduced the exact fragility the catalog-driven dispatch was
meant to eliminate.  Catalog already says the right thing:
``deepseek-chat`` (family=deepseek-v3) has no ``interleaved`` capability,
so ``interleaved_enabled`` is False and the shape function is never
called for it.  A future catalog change that adds ``interleaved`` to V3
would have been silently stripped by the V3 branch; deleting the branch
makes the catalog gate honest.

Add TestShapeRegistry.test_deepseek_v3_is_not_a_thinking_model which
pins both directions:
- Sanity: every catalog entry with family starting ``deepseek-v3`` has
  no ``interleaved`` capability.  If someone changes that, the test
  fails and forces a re-evaluation.
- Runtime: with ``_resolve_interleaved_capability`` returning None, the
  dispatcher emits no ``enable_thinking`` flag for ``deepseek-chat``.

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

* refactor(provider): drop shape registry, use transport-driven dispatch

Follow-up to 699f717.  The provider-keyed shape registry introduced in
2299b33 was over-engineered: every entry produced the same dict
({"enable_thinking": bool(reasoning_enabled)}), and the gate was
already correctly computed upstream by ``resolve_interleaved_capability``
in ``interleaved.py`` (catalog explicit declaration → series-token
inference fallback).  Replacing it with a transport-based branch:

  reasoning_transport == anthropic_messages
    → thinking={type: "enabled", budget_tokens:...}   (unchanged)

  reasoning_transport == generic_chat
    → extra_body.enable_thinking = bool(reasoning_enabled)

This unblocks the natural design goal: read the model series globally,
no per-provider dispatch.  Concrete consequences:

- deepseek-v4-flash and similar models that the catalog forgets to
  declare now get enable_thinking automatically via the series-token
  inference in ``infer_interleaved_capability`` (qwen3 / glm-* / kimi-k2*
  / deepseek-v4* / step-3.5* / minimax-m* tokens).
- A user-configured openai-compatible endpoint pointing at a known
  family Just Works without anyone editing a per-provider registry.
- Adding a new provider or a new model from a known family is now
  zero-touch: no catalog edit, no shape entry, no dispatch change.

Removed:
- _THINKING_REQUEST_SHAPES dict (9 entries, all identical product)
- _openai_base_thinking_shape helper function
- TestShapeRegistry.test_all_thinking_providers_have_a_shape
  (replaced with transport-based and shape-removal assertions)
- Property test skip-on-missing-shape (no longer needed; transport
  dispatch is universal for interleaved models)

Added:
- TestDispatchShape.test_no_shape_registry — pins the removal
- TestDispatchShape.test_anthropic_transport_still_uses_thinking_field
  — pins the contract that the new generic_chat branch did not
  regress the anthropic_messages path
- TestDispatchShape.test_series_token_fallback_emits_enable_thinking
  — 5 parametrized cases proving series-token inference closes the
  "forgot to add to catalog" gap (qwen3, glm-5, kimi-k2.6, minimax,
  step-3.5-flash)

Tests: 51/51 in test_thinking_params.py pass; full tests/provider/
shows the same 7 pre-existing failures as baseline, none introduced
by this refactor.

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

* feat(provider): expand deepseek thinking coverage to full series

User-driven follow-up to 3335cc7.  Aligns the deepseek handling with
the "全局读模型系列" design intent: any model in the deepseek family
should be treated as thinking-capable unless explicitly overridden.

Changes:

catalog.json (deepseek provider):
- Add ``deepseek-v4-flash`` with explicit ``interleaved`` declaration.
  Previously only present in the threatbook-cn-llm / threatbook-io-llm
  providers.
- Add ``deepseek-v4-pro`` (new model entry) with explicit ``interleaved``.

interleaved.py (_STRICT_REASONING_CONTENT_TOKENS):
- Add ``deepseek`` (broad catch-all) and ``deepseek-v3`` (specific) to
  cover the entire deepseek series.  Previously only V4-subset and R1
  tokens were listed, so a model named ``deepseek-chat`` (V3) or any
  future V5 / V6 would not be auto-inferred.
- Result: every deepseek model now auto-resolves to the strict
  reasoning_content policy via series-token inference, including
  ``deepseek-chat`` (V3).

Test impact:

- test_thinking_params.py: invert
  ``test_deepseek_v3_is_not_a_thinking_model`` →
  ``test_deepseek_v3_is_a_thinking_model`` to assert the new
  behavior using the real resolution chain (no monkeypatch).

- test_chinese_providers.py::test_deepseek_catalog: extend the model
  set assertion to include deepseek-v4-flash / deepseek-v4-pro; add
  per-model interleaved assertions for the new entries.

- test_provider.py::test_resolve_model_does_not_infer_interleaved_for_non_reasoning_model:
  switch the test fixture from ``deepseek-chat`` to ``gpt-4-turbo``
  because ``deepseek-chat`` is no longer a non-reasoning model under
  the new design.  ``gpt-4-turbo`` doesn't match any series token and
  remains a true non-reasoning fixture.

Net result of this + the previous three commits:

  - Original bug (2299b33): GLM-5 / minimax / deepseek / stepfun
    dropped from request-side enable_thinking because of a hard-coded
    substring whitelist — fixed.
  - 699f717: removed the model-name V3 carve-out in
    _deepseek_thinking_shape so catalog becomes the only gate.
  - 3335cc7: replaced provider-keyed shape registry with
    transport-driven dispatch, hooking up the series-token inference
    in interleaved.py as a fallback for any uncatalogued model.
  - This commit: extend the deepseek series coverage to "all of it"
    (V3 / R1 / V4 and forward) and make V4-flash / V4-pro explicit in
    the deepseek provider catalog.

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

* fix(provider,session): per-model thinking extra_body and queued user cache

Route generic-chat reasoning to provider-specific wire formats (DeepSeek/GLM/Kimi/MiMo thinking blocks, MiniMax reasoning_split). Apply queued-user reminders inside _to_chat_messages with chat context cache invalidation, and persist aborted assistant messages when LLM streams are interrupted.

* feat(workflow): improve diagram usability

Add a Flocks Help entry point to AI editing and replace the default canvas controls with lightweight controls that include tooltips. Document PowerShell encoding requirements for agents.

* chore(gitignore): ignore .codex/ directory

Local Codex CLI cache / config directory; not meant to be tracked.

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

* Fix fallback port conflict detection (#394)

* Improve chat model picker controls (#391)

* refactor: unify subagent delegation under delegate_task (#385)

* 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

* feat(workflow): support config-driven publish templates

* feat(workflow): add editable workflow document flow

* feat(session): refine chat selector controls

* Fix channel image preview rendering

* Fix DingTalk inbound file detection

* feat(session): refine agent and model selectors

* feat(session): add context usage indicator

* fix(session): stabilize selector button widths

* fix(session): localize selector control widths

* fix(session): cap adaptive agent selector width

* fix(session): stabilize streaming status (#396)

* Reduce workflow default log noise (#399)

* fix: clarify browser doctor and session streaming status (#400)

* feat(workflow): add publish config templates

Add storage-backed workflow publish config templates with config.json migration, template workflow assets, and the hidden workflow-config-guide skill.

Refine workflow detail publish/chat UX with process folding, question follow-up inputs, and UI-hidden workflow/skill filtering.

Clean workflow runtime state on deletion and cover the new publish config, visibility, skill, and chat behaviors with tests.

* revert(workflow): restore pre-pr398 workflow experience

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.

* feat(device): unify device plugin intake (#392)

* feat(device): unify device plugin intake

* refactor(device): streamline custom intake chat

* refine device intake layout and webcli guidance

* feat(workflows): improve workflow configuration UX

Use workflow.md as the editable workflow source, add inline markdown diff review, improve chat process folding and flow canvas controls, and harden workflow publish configuration guidance.

* fix(channel): preserve plugin instances across load_all (#402)

* Fix session model persistence (#403)

* feat(device): Improve device integration auto-sync (#405)

* feat: improve device integration auto-sync

* fix: harden device refresh auto-provisioning

* fix: default model reasoning to enabled (#406)

* fix skill install from GitHub blob URLs (#407)

* chore/update-version-2026-6-10 (#408)

* feat(workflows): improve workbench publishing guidance

Add workflow-local guide support, refine publish guidance UI, reuse current workflow chat sessions for launch requests, and share prompt selector controls across session surfaces.

Also persist display labels through prompt queue/session APIs so shortcut prompts render as compact instruction tags.

* Fix device refresh sync flow (#410)

* feat(workflow): refine builder workbench experience

* docs: reorganize web2cli reference guides (#411)

Co-authored-by: xiami762 <>

* feat(tool): Add l IM send message tool (#404)

* Add high-level IM send message tool

* Add high-level IM send message tool

* fix: channel question

* fix: honor selected IM session binding

* fix: bound SSH connection pool (#415)

* feat(device): add 360 FW v5.5 integration

* feat(session): refine todo tool rendering

* Fix updater cancellation and session statistics (#414)

* Support structured ACP command arguments (#412)

* fix(sip): preserve plugin result output

* Fix Windows updater venv rotation (#413)

* Fix Windows updater venv rotation

* Improve restart readiness diagnostics

* Fix skill install timeouts and session streaming state (#418)

* Fix skill install timeouts and tool native defaults

* Fix session streaming state during tool calls

* Fix unavailable model error display

* Handle unavailable model connection errors

* Tune OpenAI-compatible provider timeouts

* Fix session chat auto-scroll with sticky composer

* Address PR review feedback

* fix(updater): preserve restart after upgrade disconnect

* fix: handle windows image paths and default workflow history

* feat(workflow): improve workbench and publishing flows

* fix(workflow): show guide info tooltip above panels

* fix(updater): restore restart argv reconstruction

* chore(updater): remove unused service restart argv helper

* Add Windows updater restart handoff

* fix(updater): tune restart handoff timeouts

* fix(session): correct context usage after compaction

* fix(session): handle multimodal image paths across platforms

* fix(provider): enable vision for ThreatBook MiniMax M3

* fix(workflow): preserve cron schedules and refine guides

Keep cron expressions when applying schedule templates to poller runtime config.

Make workflow chat guide actions compact by default, grouped in the expanded panel, and dismissible on outside click.

* fix(updater): defer dependency sync to restart handoff

* chore(skills): remove unused cybersecurity skills

* chore(skills): remove supply chain malware analysis skill

* feat(workflow): improve workflow authoring usability

* fix(provider): support configured OpenAI-compatible extra_body (#424)

* Resolve custom model limits automatically (#421)

* fix(session): attribute context usage breakdown

* fix(session): exclude delegated tools from usage calls

* fix(session): include system prompt usage segment

* fix(session): count tool schemas as definitions

* fix(session): show zero agent delegation usage

* fix(session): split reasoning from conversation usage

* fix(session): refine context usage and compaction divider

* fix(session): constrain compaction divider width

* fix(session): show compacted history in timeline

* fix(session): reset context usage after compaction

* fix(session): stabilize context usage popover

* fix(session): compact only new turns after summary

* fix(session): refresh context usage on compaction failure

* fix(session): keep context usage during compaction

* fix(session): reduce context usage refresh overhead

* Add WebUI dark mode support (#430)

* Add WebUI dark mode support

* feat: darm mode

* fix(session): improve dark send button contrast

* fix(workflow): collapse invisible chat process markers

* fix(workflow): stabilize compact chat bubble width

* fix(session): expand grouped process steps by default

* fix(session): enforce disabled agent availability (#433)

* feat(workflow): improve publish runtime configuration

Add runtime API service deletion support and expose frontend workflow endpoint metadata to assistant prompts.

Refine publish and trigger cards so configuration, enable/disable, delete, and Flocks assisted setup share the same runtime-card model.

* feat: add persistent goal mode (#431)

* feat: add persistent goal command

* feat: goal mode

* Use model-based goal judging and normalize question options

* Harden goal judging and wait on judge failures

* Support goal clarification and custom question answers

* Fix goal clear and verdict handling

* feat(webui): add guided Rex creation for capabilities

* feat(workflow): refine overview run experience

Embed test and history flows inside the overview run section with compact stats.

Rename workflow info to info, show workflow file locations, and keep history details inline.

Load user-defined page bundles via relative API URLs without download headers.

* feat(webui): refine guided capability workbench

* fix(webui): handle guided workbench edge cases

* fix(webui): load user page bundles with credentials

* fix: enforce workflow API keys and restore agent tests

Validate published workflow runtime invokes with x-api-key and pass the generated key through local/docker runtime startup and center proxy calls.

Restore the Agent edit sheet test hook so the Test tab runs agentAPI.test instead of only offering Rex guide prompts.

* Reduce workflow progress storage contention (#435)

* Reduce workflow progress storage contention

* Preserve workflow step logs during summary writes

* Reduce workflow log noise and add debug output logging

* Default workflow history retention off

* Persist trigger workflow steps without retaining history

* fix(user-defined-pages): handle client disconnects in page api

* fix: preserve device draft config during tests (#437)

* fix(workflow): improve API service recovery

* fix(workflow): prevent workbench interaction timeouts

* fix: improve device plugin loading and config defaults

* fix(webui): collapse entity workbench process details

* fix: load package entry points for tool plugins

* fix: align device tool switch semantics

* fix(webui): align entity Rex workbench with workflow

Validate stored Rex sessions before resuming the entity workbench, matching the workflow detail chat behavior for stale sessions.

Keep empty conversations on the welcome guide only, move extract-from-Rex into guide actions, and normalize guide button sizing/layout across entity workbenches.

* fix(webui): document workflow config API auth

Add backend config-store authentication guidance to workflow chat and publish guide prompts so Rex uses the server_api_token bearer flow against the backend API.

Cover the workflow detail and integration prompt paths with assertions for server_api_token and Authorization headers.

* fix(workflow): stabilize API service publishing

Keep API service driver switching available after publish and guard async operations against stale UI state.

Avoid duplicate dynamic ports by reserving persisted and in-flight service ports, and release reservations on failed local or Docker publishes.

Render stale API service records as stopped without persisting stoppedAt so autostart can still recover them.

* fix(deps): upgrade litellm for CVE-2026-42271

Pin LiteLLM to 1.83.7 to include the fix for the MCP stdio command injection vulnerability in the test connection and tools list endpoints.

* fix(workflow): stabilize docker publish startup

* fix: prevent dingtalk stream from blocking event loop

* chore/update-version-2026-6-17 (#446)

* fix(cli): constrain typer below incompatible release

* Fix workflow integration tab JSX closure

* Remove duplicate WebUI declarations

* fix(ci): restore FlocksHub validation

Remove bundled Hub catalog entries that reference missing Anthropic skill manifests.

Fix the IntegrationTab test mock object so eslint can parse the suite.
Merge main into dev and resolve conflicts
@stephamie7 stephamie7 requested a review from duguwanglong June 18, 2026 09:40
@duguwanglong duguwanglong merged commit 5f89607 into main Jun 18, 2026
3 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.

6 participants