Commit Graph

88 Commits

Author SHA1 Message Date
matevip
6a13cc2f50 perf(chat): throttle streaming markdown render and defer chart mounts
- add useStreamingMarkdown: cap mid-stream markdown re-render to ~140ms,
  full-fidelity render once the segment completes
- skip code-block language auto-detection while streaming (escaped plain
  text), restore full highlighting on the final render
- defer echarts/mermaid blocks to a lightweight loading placeholder while
  streaming so their parsers never run on truncated source
- bypass the render cache for streaming-mode output
- wire into ContentSegment and MessageBubble (content + thinking)
2026-06-15 11:39:24 +08:00
matevip
fb93f99425 fix(chat): 工具框乱序 + 流式/调试开关失效 + 思考堆积修复 2026-06-09 16:04:41 +08:00
matevip
64b8e167d5 fix(mcp): refresh agent cache on MCP connection change + non-blocking connect (#289)
Closes #289 — after an MCP server (re)connects, chat queries kept replying
"from memory" instead of calling MCP tools.

Root cause: agents snapshot their tool set at build time and are cached in
AgentService.agentInstances, but MCP server lifecycle changes never
invalidated that cache (unlike model-config / tool-guard changes which do).
A stale, tool-less agent graph survived until process restart.

Changes:
- Add McpServerChangedEvent; McpServerService publishes it on connect /
  disconnect / reconnect / delete / (re)connect-failure / batch refresh /
  startup init. AgentService listens and calls refreshAllAgents(), so the
  next turn rebuilds against the live MCP tool set. Also closes the boot
  race where the web server accepts requests before the @Order(200) MCP
  init runner finishes.
- Make create/update/toggle connect asynchronously on a dedicated pool
  ("mcp-connect") so a slow/unreachable server can no longer freeze the
  admin request; status returns immediately as "connecting".
- UI: render the new "connecting" status (pulsing amber dot), show a
  friendly "connecting in background" toast, and poll until the status
  settles (window widened to ~40s to outlast the default connect timeout).
- UI: MCP config modal no longer closes on outside/backdrop click — only
  the × and Cancel buttons close it, so an accidental click can't discard
  unsaved config.

Verified E2E: ckjia-shopping (参考价) MCP server connected at runtime with
no backend restart; the cached 通用助手 agent immediately enabled and called
ckjia_shopping_recommend, returning real product cards.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 14:14:08 +08:00
倪程伟
28f2ba973d feat(wiki): honour KB pageType profile in transformations, agent pages & UI
Wiki page classification was only profile-aware in the main ingest pipeline.
Transformation outputs hard-coded "synthesis", agent-created pages were left
untyped, and the frontend hard-coded the built-in ten types for ordering,
colouring and labels — so custom/synthesis types sank to the bottom, rendered
grey and showed raw keys.

Backend:
- Add nullable target_page_type column to mate_wiki_transformation (V142,
  mysql + h2) plus the entity field and CRUD normalization (blank = use
  profile fallbackType; membership validated at save time, not edit time).
- Route transformation single-run + KB-aggregate page saves through
  WikiPageTypeProfileService.normalizePageType so output joins the KB
  classification; agent wiki_create_page now lands on the profile fallbackType
  instead of an untyped page.

Frontend:
- Load + parse the KB pageType profile into the wiki store (order, labels,
  fallbackType) on KB select / refresh.
- New useWikiPageType composable: profile-driven label (3-tier fallback) and
  colour (built-in fixed + deterministic hash palette for custom types).
- Sidebar grouping order, graph colouring, node panel, graph filter and the
  page header badge now follow the profile; transformation editor gains a
  target-type dropdown sourced from the profile when output target is a page.

Refs #292
2026-06-08 21:02:50 +08:00
matevip
3c87efdb15 feat(chat): 购物推荐结果渲染为可点击商品卡片
- 聊天 markdown 渲染器解析 product-cards 围栏为卡片网格(图片/价格/平台/去购买按钮),整卡可点跳购买页
- DOMPurify afterSanitizeAttributes 钩子补回被 ALLOWED_URI_REGEXP 剥掉的 target/referrerpolicy,确保防盗链图片加载与新标签打开
- 后端在购物推荐工具结果尾部追加卡片渲染指令,保证模型稳定输出卡片而非表格
- 技能:购物意图优先调用参考价工具并约定 product-cards 输出格式
2026-06-08 15:11:56 +08:00
matevip
da332f2fd8 feat(goal): checklist UI — progress ring, hover checklist card, criteria SSE 2026-06-03 21:19:27 +08:00
matevip
9073c94de1 fix(ui): intercept generated-file downloads so failures never wedge the SPA (#243) 2026-06-01 20:21:21 +08:00
matevip
0ef735588a fix(wiki): 3 bugs caught by browser-driven chat e2e + 12-round trace 2026-05-28 10:55:30 +08:00
matevip
0e01b2b526 feat(wiki): chat-rendered wikilinks navigate via cross-KB lookup 2026-05-28 09:25:58 +08:00
matevip
66d3d90ea9 feat(wiki): slug-first wikilink resolution and safe DOM postprocess 2026-05-28 08:16:56 +08:00
matevip
5f571e86a2 feat(agent,ui): multi-level subagent delegation tree 2026-05-22 13:44:01 +08:00
matevip
8bd8a02cd0 feat(agent,ui): nested subagent timeline + always-on plan panel 2026-05-22 09:48:06 +08:00
matevip
34175ab94d fix(goal,ui): guard evaluating flag against the message_complete race 2026-05-21 22:27:25 +08:00
matevip
495a5c126d fix(goal,ui): wire evaluating halo, followup ↻ mark, dedupe system-line icon 2026-05-21 22:26:48 +08:00
matevip
c34e8290ac feat(goal,ui): inline set-goal prompt, terminal system-line, sidebar dot 2026-05-21 22:26:40 +08:00
matevip
9c5ad29d42 chore(llm): drop unused imports, add XIAOMI_MIMO cross-turn cache tests 2026-05-21 17:24:53 +08:00
matevip
c9e54e820f fix(goal,ui): live ring update after agent-triggered setGoal / addGoalCriterion 2026-05-21 14:43:59 +08:00
matevip
3a0595d5bd feat(goal,ui): Jobs-cut frontend for persistent goal 2026-05-21 14:43:28 +08:00
matevip
51e6542a5a feat(channel/qq): add scan-to-bind onboarding via QQ Open Platform Lite portal 2026-05-20 21:47:49 +08:00
matevip
d53d66abe3 feat(chat): per-conversation model selection (#150) 2026-05-18 16:27:27 +08:00
matevip
001cb1a2ed refactor(chat): extract conversation sidebar and shared UI primitives 2026-05-17 11:49:44 +08:00
matevip
82594878a0 refactor(ui): fold the live runtime view into the Employees page 2026-05-16 14:50:58 +08:00
matevip
0800c03cd3 fix(ui): preserve snowflake ID precision through form round-trips (#133) 2026-05-15 15:51:33 +08:00
matevip
e10dd9d0a0 refactor(ui): swap ElMessage for project-native mcToast, finish mcConfirm migration 2026-05-15 10:19:24 +08:00
matevip
777e2ecee2 feat(ui,router): gate routes and sidebar by workspace capability 2026-05-15 10:18:38 +08:00
matevip
aa27853712 feat(ui,workspace): consume backend access endpoint for capability state 2026-05-15 10:18:30 +08:00
matevip
eb6badeb61 feat(ui): surface pending approvals + stuck agents as sidebar badges 2026-05-15 10:17:30 +08:00
matevip
d1be02985c fix(agent): collapse model-predicted tool results that the actual tool replaced 2026-05-14 15:44:03 +08:00
matevip
0192a62f21 feat(ui/mcp): redesign MCP connections page with componentized layout 2026-05-14 14:09:44 +08:00
matevip
faf7f98358 feat(context): consume compact_status on the frontend; load history from latest boundary; backfill summaryId 2026-05-13 08:50:35 +08:00
matevip
f18626304e feat(agent,ui): recovery affordance card for non-transient LLM errors 2026-05-10 19:15:57 +08:00
matevip
97e2b12f71 feat(chat): show reply model attribution in assistant message bubbles 2026-05-09 16:41:18 +08:00
matevip
0cbe271f6f fix(ui/chat): mermaid streaming flicker + copy/download buttons 2026-05-08 17:09:22 +08:00
matevip
de89df6900 feat(ui/workflows): Monaco editor + schema validation + compile-error markers 2026-05-08 15:08:50 +08:00
matevip
dae74cf26c feat(channel,trigger): wire channel_message + content_match event sources 2026-05-08 15:07:11 +08:00
matevip
dac774f15e feat(workflow): trigger workspace isolation + step property editor + custom dialogs 2026-05-08 15:06:16 +08:00
matevip
f8499eefa7 feat(ui/workflows): vue-flow canvas + component dialogs + dark / mobile polish 2026-05-08 15:05:45 +08:00
matevip
32fe582b82 fix: avoid auto-scroll while reading history (#61) 2026-05-05 11:12:38 +08:00
matevip
f5d845ff31 feat(backstage): tool chip, triage sort, bento metadata tiles 2026-05-04 14:00:39 +08:00
matevip
7708e26851 feat(backstage): avatar status ring, hero focus panel, brand-tone time dial 2026-05-04 14:00:25 +08:00
matevip
7d02841d1d fix(chat): per-event SSE ids for safe reconnect dedup + queue race recovery 2026-05-03 19:57:06 +08:00
matevip
66f09a968a feat(chat-stream): streaming UX overhaul + multi-agent stability layer 2026-05-03 17:15:02 +08:00
matevip
5f125364e9 fix(skill): parseIconValue accepts site-absolute paths + restore ckjia-shopping nameZh/nameEn/tags 2026-05-03 17:14:43 +08:00
matevip
28c3b0e62f feat(model3d): Tencent Hunyuan 3D provider — Pro/Rapid action routing + <model-viewer> preview 2026-05-01 22:39:13 +08:00
matevip
e3ab06d57c feat(generative): unified async pipeline + live SSE delivery for music/video/image 2026-05-01 20:15:20 +08:00
matevip
5e6764ecf1 fix(skill): tool-gate whitelist + markdown link host normalization
When an agent had any skill bound, the runtime tool gate was silently
hiding @Tool beans that aren't declared in any skill manifest, even
though the global system prompts (SOUL.md / "Web Search Capability" /
"File Reading Guidelines") explicitly tell the LLM these tools are
available. Result: the model would call search / renderDocx / read_file
/ etc., hit "Tool not found", then either give up or fall back to
unhelpful behaviour (e.g. dumping markdown text instead of producing a
.docx download).

This commit:

- Adds universally-promised, agent-wide tools to SYSTEM_LEVEL_TOOLS so
  they bypass the manifest restriction: document/media generation
  (renderDocx*, image_generate, music_generate, video_generate),
  global capability tools the system prompt mentions (search,
  browser_use, read_file / write_file / edit_file /
  execute_shell_command, detect_file_type, extract_*_text,
  readMateClawDoc), skill discovery siblings (listSkillFiles,
  listAvailableSkills), and the delegate triplet (delegateToAgent,
  delegateParallel, listAvailableAgents).

- Fixes 5 entries in the prior whitelist whose names did not match
  any real @Tool bean and were therefore silently dead:
    read_workspace_file   -> read_workspace_memory_file
    write_workspace_file  -> write_workspace_memory_file
    list_workspace_files  -> list_workspace_memory_files
    delegate_agent        -> delegateToAgent
    datetime              -> getCurrentDate / getCurrentDateTime / getCurrentTime
  Also adds the missing edit_workspace_memory_file.

- In the chat markdown renderer, strips any hallucinated
  https?://<host> prefix from /api/v1/files/generated/<id> download
  links before building the <a href>. Multiple LLMs have been
  observed prepending bogus hosts when echoing tool-returned download
  URLs back to the user, breaking the click. One-line defensive
  normalization independent of which model is in use.

Verified end-to-end on a previously-broken agent: search / browser_use
/ execute_shell_command / renderDocx all dispatch correctly now and
the final markdown link is a clean same-origin path. 36 whitelist
entries cross-checked against real @Tool method names.
AgentBindingServiceTest green.
2026-05-01 12:24:25 +08:00
matevip
8ce7e7d26d feat(ui): agent integration of SkillIcon + SkillIconPicker 2026-05-01 10:58:15 +08:00
matevip
efb91796fb feat(skill): pixelarticons icon library + picker component 2026-05-01 09:52:12 +08:00
matevip
b4aef56c89 fix(channels): close QR loading dead-window for feishu and dingtalk register flows
Reported issue: click 'scan to create' -> button momentarily flickers
loading -> button re-enables but no QR shows up -> blank for 1-2 seconds
-> QR suddenly appears. Looks broken even though it works.

Root cause: loading.value flipped back to false the moment the begin HTTP
call returned (sessionId in hand), but the actual QR image only arrives on
the first status poll, which the existing code waited a full 2 seconds
for. Between begin completing and the first poll firing the UI was a
disabled button + nothing.

Three coordinated changes:
- useFeishuAppRegister and useDingTalkAppRegister: keep loading.value true
  through begin AND across the polls, only flip false when the QR image
  is actually populated (or a terminal failure status arrives). Also run
  an immediate first poll right after begin instead of waiting for the
  setInterval tick — usually the first poll already has the rendered QR
  for dingtalk, and pushes the feishu user roughly 2 seconds closer.
- ChannelEditModal: same-sized loading placeholder (min-height 240px,
  matching the QR card) that renders when loading is true and no QR is
  in hand. CSS spinner ring tinted with the channel brand color (feishu
  indigo, dingtalk blue) and a new
  channels.{feishu,dingtalk}Register.qrcodeLoading hint. The placeholder
  swaps to the real image with no layout shift.
- i18n: new qrcodeLoading key in zh-CN and en-US for both flows.

Net effect: click to spinner-visible is ~50ms; the user is never staring
at a frozen button-without-content again.
2026-04-28 11:14:14 +08:00
matevip
acf6eccb3a feat(dingtalk): one-click bot creation via OAuth device flow
Mirrors the feishu one-click flow: scan a QR with the DingTalk app,
approve, and the bot's client_id / client_secret get auto-filled instead
of forcing the user through the open-dev console. Saves about seven
manual steps per channel setup.

Backend
- Bump dingtalk-stream from 1.3.5 to 1.3.12. Diff against the classes we
  depend on (OpenDingTalkStreamClient, ChatbotMessage, MessageContent,
  GenericEventListener) is empty — pure point-release bumps, no API churn.
- New DingTalkAppRegistrationService: synchronously runs init + begin
  against /app/registration/{init,begin} on oapi.dingtalk.com to obtain
  the device_code and verification URL, then spawns a daemon worker that
  polls /app/registration/poll every 5s until SUCCESS / FAIL / EXPIRED is
  returned. Sessions evict after 7 minutes, worker has a 6-minute hard
  runtime cap, transient HTTP errors do not terminate the loop. Same
  shape as the feishu service, but written from scratch because the
  dingtalk-stream SDK doesn't wrap this OAuth device flow.
- Two new endpoints under /api/v1/channels/webhook:
  POST /dingtalk/register/begin returns session_id;
  GET  /dingtalk/register/status returns status + qrcode_img (data URI
  PNG, ZXing-encoded from the verification URL, matching the feishu and
  weixin flows). Status surface: waiting / confirmed / expired / denied.

Frontend
- channelApi.dingtalkRegisterBegin / dingtalkRegisterStatus.
- New useDingTalkAppRegister composable, structurally identical to
  useFeishuAppRegister minus the domain argument. Stops polling on
  terminal status, fires onConfirmed with {clientId, clientSecret}.
- ChannelEditModal: dingtalk-register-card rendered when channelType is
  dingtalk, scoped DingTalk blue (#1f79ff) to differentiate from feishu's
  indigo. onConfirmed writes channelConfig.client_id / client_secret so
  the existing form fields update reactively.
- i18n: channels.dingtalkRegister.* keys for title / hint / button states
  / scan / confirmed / expired / denied / startFailed.
2026-04-28 11:12:22 +08:00