Commit Graph

588 Commits

Author SHA1 Message Date
zhayujie
70c1c44d15 feat: add kimi-k2.7-code and glm-5.2 models
- Add Kimi kimi-k2.7-code (default), kimi-k2.7-code-highspeed, and GLM glm-5.2 (default)
- Fix 400 error when disabling thinking on kimi-k2.7-code; omit the thinking param for this series since it only accepts type=enabled
- Update README, docs (zh/en/ja), install scripts, and Web console model dropdown
2026-06-17 11:54:35 +08:00
zhayujie
3bb8ec3bea feat(web): support manually renaming sessions in console #2897 2026-06-16 20:03:38 +08:00
zhayujie
35e42a3ad6 Merge pull request #2893 from yangziyu-hhh/master
feat(knowledge): add category and document management
2026-06-16 18:52:43 +08:00
zhayujie
949575ad14 Merge pull request #2896 from 6vision/feat/wecom-bot-callback #2869
Feat: wecom bot callback
2026-06-16 17:29:30 +08:00
zhayujie
1c34f0f03d Merge pull request #2892 from HnBigVolibear/master
feat(web): enhance scheduled task management in web console
2026-06-16 17:24:05 +08:00
6vision
eed2eab014 refactor(wecom_bot): use wecom_bot_mode field and clean up temp images
Replace the boolean wecom_bot_callback with a wecom_bot_mode field
("websocket" | "webhook"), consistent with the Feishu channel's
feishu_event_mode. Update startup() and send() to branch on the mode.

Also fix a temp-file leak in _load_image_base64: downloads, format
conversions and compressions wrote to /tmp but were never removed. Track
only the temp files created here and delete them in a finally block,
leaving the caller's original local file untouched.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-16 17:23:31 +08:00
6vision
52209217fc refactor(wecom_bot): config-file-only callback mode + fixed callback path
Remove the callback-mode fields (Callback Mode / Token / EncodingAESKey /
Port) from the web console channel form; these are rarely changed and are
now configured via config.json only. The console keeps Bot ID / Secret for
the long-connection setup.

Serve the callback HTTP server on a fixed path (/wecombot) instead of any
path (/.*), so unrelated requests 404 rather than being processed as
signature-failing WeCom callbacks. The bot's receive-message URL must point
at http(s)://host:<port>/wecombot.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-15 19:47:19 +08:00
6vision
018493a60b fix(wecom_bot): revert callback image cap to 512KB (2MB inline body rejected by WeCom)
The 2MB cap (matching the long-connection upload path) does not work for
the callback path: there the whole image is base64-embedded in an
AES-encrypted body returned on every poll. A ~1.5MB image (base64 ~2.1MB,
encrypted ~2.8MB) makes WeCom reject the finish packet and poll forever,
which also surfaces as a truncated text bubble and WeCom's own timeout
error. Cap well below that at 512KB so the finish packet is accepted.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-15 19:22:16 +08:00
6vision
630373b1f0 fix(wecom_bot): defer text finish for image race; align callback image cap to 2MB
Defer the callback stream finish after a text reply so a trailing
image-with-caption send (text first, image 0.3s later) can merge in
instead of closing the stream prematurely. Raise the callback inline
image cap from 512KB to 2MB to match the long-connection upload path.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-15 18:56:20 +08:00
6vision
dec31dfd75 fix(wecom_bot): shrink callback inline images so finish packets aren't rejected
In callback mode the image is base64-embedded in the stream finish reply and
the whole response is AES-encrypted and returned on every poll. A multi-MB
body is rejected/times out on WeCom's side, leaving the "···" bubble spinning
and the image never shown.

- Compress callback images to <=512KB (JPEG, resize if needed) instead of the
  10MB the protocol nominally allows
- Fall back to the original image if compression fails, and log the final
  base64 payload size for diagnosis

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-15 18:26:38 +08:00
6vision
18ce17d21a fix(wecom_bot): finalize stream on cancel; never force-finish on a timer
The streaming "···" bubble should only stop when the task actually completes
or the user cancels — not on an arbitrary timeout that would also steal the
response_url fallback's chance to deliver a late answer.

- On agent_cancelled, finalize the stream (finish=true, "🛑 已中止" if empty)
  and schedule the response_url fallback so the bubble clears immediately when
  a run is cancelled, even past the poll window
- Do not force-finish a still-running stream on a timer; let it keep spinning
  until completion or cancel. Answers that finish after WeCom's ~6min poll
  window are delivered via response_url instead

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-15 17:26:06 +08:00
yangziyu-hhh
e7a069b060 Merge remote-tracking branch 'upstream/master' 2026-06-15 13:17:12 +08:00
yangziyu-hhh
6e3933be30 feat(knowledge): add category and document management 2026-06-15 13:15:07 +08:00
zhayujie
d281a34c6f fix(models): demote claude-fable-5 from Claude default 2026-06-14 21:06:41 +08:00
HnBigVolibear
bd5fede122 feat(web): enhance scheduled task management in web console. Now we can edit any scheduled tasks in web!
- Add toggle, update and delete APIs for scheduled tasks
- Add task edit modal with schedule/action updates in web console  (PS: In edit box, now I Prevent channel type changes during editing (weixin token bound to session) )
- Add enable/disable switch with visual feedback in task cards
- Sort task list by enabled status first, then by next_run_at

Closes #2882
2026-06-14 02:11:15 +08:00
zhayujie
c9c293f67c Merge pull request #2888 from kirs-hi/fix/robustness-cancel-keyerror-compress-loop
fix: avoid KeyError on /cancel and infinite loop in image compression
2026-06-12 18:28:10 +08:00
6vision
561631baba fix(wecom_bot): rescue late replies via response_url + fix degrade notice
Handle agent replies that finish after WeCom stops polling the passive
stream (the poll window is ~6min from the user's message).

- Capture response_url from the message callback and, when a reply is
  finalized but no poll picks it up within a short grace period, push it as
  a one-shot active markdown reply (valid 1h, single use)
- Guard against double delivery via delivered/url_sent flags
- Embed public image URLs in the active markdown; note when a local image
  can't be delivered post-timeout
- Append (instead of discarding) the unsupported-type notice for
  file/voice/video replies so streamed text is preserved
- Quiet the per-poll debug log and log stream completion with content size

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-12 18:24:33 +08:00
zhayujie
80d0a6aeb2 Merge pull request #2879 from yangziyu-hhh/master
feat: stream Bash progress and guard message actions during replies
2026-06-12 18:19:13 +08:00
zhayujie
6b5ee245ae feat(web): integrate custom providers into the provider credentials section
- Merge the separate custom-providers section into the unified provider
  grid; "Custom" in the add-provider picker now acts as an add-new action
  (trailing + mark) and opens the dedicated modal, supporting multiple
  OpenAI-compatible endpoints
- Simplify the custom provider modal: drop the default-model field, add
  an inline delete button, align colors with the theme
- Keep the legacy single "custom" card visible (models page, chat
  dropdown and legacy config page) while custom_api_key/custom_api_base
  is still in use, so existing single-provider setups don't disappear
- Unify user-facing wording from "vendor" to "provider" in UI and docs
- Restructure custom provider docs (zh/en/ja) around Web console and
  config file usage
2026-06-12 18:03:33 +08:00
6vision
5c43c2f519 feat(wecom_bot): add callback (webhook) mode alongside long connection
Support receiving WeCom smart-bot messages via encrypted HTTP callback in
addition to the existing WebSocket long connection. Disabled by default
(wecom_bot_callback=false).

- Add wecom_bot_callback / wecom_bot_token / wecom_bot_encoding_aes_key /
  wecom_bot_port config keys
- Add WXBizJsonMsgCrypt-based crypto module for URL verification, callback
  decryption and passive-reply encryption (receive_id empty for internal bots)
- Reply asynchronously via the official stream-refresh polling: register a
  stream id on first reply, accumulate agent output into per-stream state, and
  serve the latest content (text + image) on each poll until finish
- Fall back to EncodingAESKey for media decryption when callback bodies carry
  no per-message aeskey
- Degrade unsupported passive replies (file/voice/video) to a text notice
- Expose the new fields in the Web console channel config

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-12 16:26:54 +08:00
yangziyu-hhh
075d9fc608 fix: address Bash streaming review feedback 2026-06-12 13:45:39 +08:00
zhayujie
1d7e6b3703 fix(web): accept custom:<id> providers in the chat capability card
_set_chat rejected the expanded "custom:<id>" ids with "unknown
provider", so switching to a custom provider was only possible from
the custom providers section. Now the chat card and the custom section
behave consistently: _set_chat validates the id against
custom_providers, falls back to the provider's default model when none
is picked, and _chat_capability expands the dropdown with the
"custom:<id>" entries (legacy single-custom mode unchanged).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-12 11:54:19 +08:00
kirs-hi
ad64e17a34 fix: avoid KeyError on cancel and infinite loop in image compression
Two independent robustness fixes:

1. ChatChannel.cancel_session / cancel_all_session raised KeyError when a
   session existed in self.sessions but no future had been dispatched yet.
   self.sessions[sid] is created in produce(), but self.futures[sid] is only
   created later in consume() on first dispatch. Cancelling in that window
   (e.g. user sends a message then immediately cancels) crashed the cancel
   path. Use self.futures.get(sid, []) so an absent entry is a no-op.

2. compress_imgfile decremented JPEG quality by 5 with no lower bound. For an
   image that cannot be compressed below max_size, quality went 0, negative,
   ... — the loop never terminated and passed invalid quality values to PIL.
   Add a min_quality floor (10) and return the best effort once reached.

Adds tests/test_robustness_fixes.py covering both paths (5 tests).
2026-06-12 11:03:04 +08:00
kirs-hi
0092376c07 fix: address review — no auto-hijack, sync model on activation, cleanup
1. Creating a provider no longer auto-switches bot_type. Only an
   explicit make_active=true changes the active model — prevents
   silently hijacking users on Claude/OpenAI/etc.

2. When a provider IS activated, its 'model' is now written into the
   global 'model' field. This ensures all three paths (regular chat,
   agent_bridge, vision) use the correct model without per-path patches.

3. Removed unused i18n key 'models_custom_name_exists' (no longer
   referenced after the id-based rework removed name-collision checks).

4. Updated tests: 39 passing (added model-sync tests, fixed tests that
   relied on the removed auto-activation behavior).
2026-06-12 10:05:05 +08:00
kirs-hi
1940d628a8 refactor(custom): id-based routing, single source of truth, security fixes
Rework the multi custom-provider design per maintainer review:

1. Data model: use server-generated uuid4 short id as primary key;
   'name' is now a pure display label that can be freely renamed.

2. Routing: drop 'custom_active_provider'; activate a provider by
   setting bot_type to 'custom:<id>'. Single source of truth — no
   pointer drift between bot_type and a separate active selector.

3. Security: drag_sensitive() now recursively masks api_key/secret in
   nested structures (custom_providers list); previously only top-level
   string fields were masked.

4. Per-provider model: the provider's 'model' field now takes effect on
   the main chat path and agent path (was silently ignored before).

5. XSS fix: replace all inline onclick handlers in custom-provider UI
   with data-* attributes + event delegation. Provider names never
   appear in executable HTML contexts.

Legacy compatibility: bot_type='custom' (no colon) still reads the flat
custom_api_key/custom_api_base fields byte-for-byte identically.

Closes: consolidates #2876 into this PR as requested.
Ref: #2838
2026-06-11 17:25:24 +08:00
kirs-hi
cffa590d3e feat(web): manage multiple custom (OpenAI-compatible) providers in console UI
Adds first-class support for configuring more than one custom
OpenAI-compatible provider (e.g. SiliconFlow, DeepSeek, local vLLM)
and switching the active one from the web console, addressing #2838.

Backend:
- config: new `custom_providers` (list) and `custom_active_provider`
  fields, fully backward compatible with the legacy single
  `open_ai_api_base`/`model` fields (used as fallback).
- models/custom_provider.py: centralized resolver
  `resolve_custom_credentials()` returning (api_key, api_base, model),
  with active-provider selection and graceful fallback.
- chat_gpt_bot.py wired to use the resolver.
- web_channel.py: `_provider_overview` expands `custom_providers` into
  one card per provider (id `custom:<name>`, active flag, masked key);
  new POST actions `set_custom_provider`, `delete_custom_provider`,
  `set_active_custom_provider` with hermetic persistence + bridge reset.

Frontend:
- console.js: dedicated "Custom providers" section with add / edit /
  delete / set-active actions, masked-key keep-existing handling, and
  ~20 new zh/en i18n strings.
- chat.html: custom provider modal.

Tests:
- tests/test_custom_provider.py (11) - resolver/config behavior.
- tests/test_custom_provider_handlers.py (18) - write-side handlers and
  overview expansion, including duplicate-name rejection.

All 29 unit tests pass.
2026-06-10 18:12:30 +08:00
yangziyu-hhh
402e2bfee0 feat: stream Bash progress and guard message actions during replies 2026-06-10 14:19:03 +08:00
zhayujie
f5caba81d6 feat(models): support claude-fable-5 2026-06-10 09:39:37 +08:00
zhayujie
354350dec9 fix: hide code block language label when language is undefined 2026-06-09 19:20:15 +08:00
zhayujie
7c9ea62993 chore(evolution): lower trigger thresholds to 6 turns / 10 min idle 2026-06-09 15:22:38 +08:00
zhayujie
33c03e30d9 fix(web): switch to a sibling session when deleting the active one 2026-06-09 10:49:34 +08:00
zhayujie
9fc39f648f feat(evolution): give review agent full context, add knowledge signal, polish UX 2026-06-08 20:06:01 +08:00
zhayujie
ec9557e3d8 feat(web): resume live streaming when switching back to a session 2026-06-08 17:32:27 +08:00
zhayujie
7cf0f7d42d fix(web): self-heal stuck Cancel send button 2026-06-08 15:48:21 +08:00
zhayujie
b7aa64279d fix(web): support parallel sessions; fix lost/duplicate in-flight replies 2026-06-08 15:36:48 +08:00
zhayujie
26300a8d43 feat(evolution): flag self-evolution bubbles in UI and relax MEMORY.md writes 2026-06-07 21:00:03 +08:00
zhayujie
157374401a feat(web): add self-evolution toggle in agent config 2026-06-07 19:12:32 +08:00
zhayujie
ba777ed706 feat(evolution): add self-evolution subsystem
Add a self-evolution subsystem that reviews idle conversations in an
isolated agent and durably learns from them — patching/creating skills,
finishing unfinished tasks, and backfilling missed memory.

- Trigger: background idle scan, fires when a session is idle >= N min AND
  (>= N turns OR context usage > 80%). In-memory cursor reviews only new
  messages so a session never re-learns old content.
- Isolated review agent: same model, restricted toolset, hard write-guard
  confining edits to the workspace (built-in skills are protected).
- Safety: file-level backup before edits + evolution_undo tool; notify the
  user ONLY when a workspace file actually changed (no-nag rule); capped
  concurrency.
- Records to memory/evolution/<date>.md, surfaced in the memory UI's
  renamed "Self-Evolution" tab (merged with dream diaries).
- Hide internal [SCHEDULED]/[EVOLUTION]/backup_id markers from chat history
  display (also fixes scheduler marker leakage) while keeping them in stored
  content for undo.
- Flat config: self_evolution_enabled (default off until release),
  self_evolution_idle_minutes (15), self_evolution_min_turns (6).
- Tests: tests/test_evolution.py (stub + real model modes, 7 scenarios).
2026-06-07 18:55:33 +08:00
zhayujie
72847e0711 feat(i18n): order channel list by UI language 2026-06-06 19:00:38 +08:00
zhayujie
3c19614c74 refactor(web-console): polish message actions on bubbles after #2865 2026-06-06 16:07:31 +08:00
PF4YZYNS\admin
c62175c06b - Add edit/delete/regenerate for user and bot messages
- Add language labels and copy buttons to code blocks
- Enhance drag-and-drop to full chat view
- Fix data consistency bugs in message operations
- Use RLock to prevent deadlock in conversation store"
2026-06-05 18:51:35 +08:00
zhayujie
3d7c68bac6 fix(wechatmp): reject webhook requests when wechatmp_token is empty 2026-06-05 15:14:28 +08:00
zhayujie
92ec9653e5 feat(models): support qwen3.7-plus multi-modal model 2026-06-02 16:38:17 +08:00
zhayujie
e861d98007 feat(models): support ASR model selection in web console 2026-06-02 15:05:35 +08:00
nightwhite
cd88b23b5d fix: persist ASR model in models API 2026-06-02 13:01:20 +08:00
octo-patch
7fa743f01a feat(minimax): add MiniMax-M3, set as default, drop M2.5/M2.1/M2
- Add MINIMAX_M3 = "MiniMax-M3" constant and put it first in MODEL_LIST
- Default MinimaxBot model: MiniMax-M2.7 -> MiniMax-M3
- Keep MiniMax-M2.7 and MiniMax-M2.7-highspeed as legacy options
- Drop MINIMAX_M2_5 / MINIMAX_M2_1 / MINIMAX_M2_1_LIGHTNING / MINIMAX_M2
- Update web console recommended/provider model lists
- Update README capability table and docs/models index (en/zh/ja)
- Update docs/models/minimax.mdx and coding-plan.mdx MiniMax section
- Update run.sh / run.ps1 installer default and menu hint
- Update zh CLI status sample output
- Update unit tests to assert new M3 default and constant

TTS (speech-2.*) and API base URL remain unchanged.
2026-06-01 21:30:38 +08:00
zhayujie
feaa9076b0 feat: release 2.1.0 2026-06-01 16:02:55 +08:00
zhayujie
126649f70f feat(i18n): localize system prompts, workspace templates and dynamic prompts 2026-05-31 17:38:31 +08:00
zhayujie
1827a2a31c feat(i18n): bind web language switch to cow_lang config 2026-05-31 17:01:43 +08:00
zhayujie
fcf4eb78dc feat(i18n): add global language resolution and localize user-facing text 2026-05-31 16:49:35 +08:00