Commit Graph

425 Commits

Author SHA1 Message Date
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
matevip
a9cf3cbd55 fix(llm): show all enabled chat models in multimodal sidecar selector
The vision/video sidecar dropdown filtered candidates through the built-in
capability heuristics, so provider-compatible models whose custom names match
no known prefix (and carry no declared modalities) were hidden and could not be
selected as a sidecar — even when they natively support the modality.

- listByType now returns every enabled chat model, annotating each row with a
  transient modalityCapable flag and sorting known-capable rows first, instead
  of hard-filtering recognized models only.
- MultimodalRouter honours an explicitly configured sidecar model instead of
  dropping it when the heuristics don't recognize it; a wrong pick degrades
  gracefully through the caption path rather than silently disabling routing.
- ModelPicker gains an optional capability badge; the sidecar UI tags
  recognized vision models while keeping every enabled model selectable.
2026-06-09 10:30:37 +08:00
倪程伟
a4f2980240 feat(channel): position webchat as Web/API access with optional agentId & multi-session sessionId
Rename the webchat channel from "embed widget" to "Web / API access" (key
unchanged, docs/i18n only) and extend the backend SSE endpoint for pure
backend integration:

- WebChatRequest gains optional agentId (route one Key to multiple agents;
  rejected unless the agent shares the channel's workspace) and sessionId
  (one visitor, multiple isolated threads).
- sessionId is validated ([A-Za-z0-9_-]{1,64}) and only composed into the
  server-derived conversationId — raw conversationIds are never accepted, so
  the key+visitor namespace still bounds every thread.
- A `meta` SSE event echoes the effective sessionId/conversationId at stream
  start so callers can persist and re-address a thread.
- Memory stays attributed per visitor (api:<visitorId>), shared across that
  visitor's sessions.

All new fields are optional; omitting them reproduces the prior behaviour
byte-for-byte. Refs matevip/mateclaw#295.
2026-06-09 09:29:01 +08:00
matevip
b95ee90c64 fix(wiki,agent): tidy up post-merge review nits
- WikiPageTypeProfile: normalise pageType keys to lowercase on set, so a
  user-authored profile with an uppercase key still matches the
  case-insensitive hasPageType/get lookups.
- WikiDirectoryScanService: normalise the symlink-resolved glob base to
  forward slashes so directory-scan globs work on Windows paths.
- Agents roster tag filter: keep selected tags that no longer exist on any
  agent visible and deselectable (and show the filter bar when only such
  orphan selections remain) instead of silently filtering with no way to clear.
2026-06-08 22:48:53 +08:00
matevip
21798d6be5 fix(wiki): guard page reclassification against concurrent re-trigger
A second POST to /reclassify on the same KB spawned an independent pass over
the same pages, doubling LLM spend and racing the first pass's page-type
writes. Add a per-KB in-flight guard that rejects a concurrent run with a
friendly message (409 via R.fail rather than a generic 500), released in a
finally once the async pass completes. Also count and broadcast per-page
failures so an all-failing run is visible instead of reporting changed=0, and
type the api modelId param as string|number per the snowflake ID convention.
2026-06-08 21:59:39 +08:00
倪程伟
e3ddea9a70 feat(wiki): reclassify existing pages against the current pageType profile
Add a backfill path so pages created before a KB's pageType profile changed
can be migrated into newly-added types. A per-page classify-only LLM call
(title + summary in, single page_type out) is normalised through the profile
and written back via a partial update that never touches page content.

Exposed as POST /knowledge-bases/{id}/reclassify (admin) and a "re-classify
existing pages" action in the Wiki advanced panel.
2026-06-08 21:04:24 +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
倪程伟
da5aaba0f7 feat(agents): open AGENTS.md editor in a modal, as a settings row, with section reordering
Move the AGENTS.md section editing into a click-to-open modal so the Basic
tab no longer expands the full document inline. Present the entry as a
settings-style row (title + description on the left, a "manage" button on the
right) instead of stacked label/hint/button.

Add optional move-up/move-down controls to MemorySection (off by default, so
MemoryBrowser is unaffected) and wire reordering in AgentGuideEditor: adjacent
sections swap and the whole file is re-saved, with a synthetic preamble pinned
to the top.
2026-06-08 21:00:07 +08:00
倪程伟
4f11a444c1 feat(agents): manage AGENTS.md from the agent editor + clarify context-file roles
Add a friendly AGENTS.md section editor inside the edit-agent modal's
"高级" (Advanced) collapsible, alongside the existing additional-instructions
field. New AgentGuideEditor reuses MemorySection cards, parses the file into
## sections, and saves whole-file via the workspace API (no backend change).
Empty files offer a "create" scaffold flow.

Reword the collapsible to a generic "高级" and add a role-clarifying note that
fixes the boundary: factory identity goes in the form fields, evolving
memory/rules go in the context files. Also fix the additional-instructions
textarea so it fills the form width.

Closes matevip/mateclaw#290
2026-06-08 21:00:07 +08:00
倪程伟
c7ae406dcc feat(ui): 数字员工标签改为芯片式编辑器
将编辑弹窗的标签输入从逗号分隔文本框改为芯片编辑器:每个标签独立
展示并带 × 删除,回车/空格/逗号(含全角「,」)添加,自动去重 + trim。
输入法选词态的回车不会误提交半成品;删除后提供 5 秒内联撤销。

form.tags 仍为逗号分隔字符串,后端零改动、API 契约不变。Closes #145.
2026-06-08 20:58:18 +08:00
倪程伟
9488634372 feat(agent): add tag filtering to the roster (#146)
Adds a tag filter bar to the agent roster, orthogonal to the existing
type/status tabs. Multi-select narrows by intersection (an agent must
carry every selected tag). Tags also render as clickable chips on each
agent card. The bar is hidden when no agent has tags.

Tags are de-duped per agent and ordered by usage frequency. When a
workspace has more than 12 distinct tags, only the top-N show inline and
a search box filters the rest; selected tags stay visible regardless.
2026-06-08 20:41:31 +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
5ebdccb1f6 feat(agent): scope agent knowledge base access to a bound subset (#261) 2026-06-07 22:41:14 +08:00
matevip
396a54440f fix(wiki): type scanResult.errors so the scan error list type-checks 2026-06-07 18:05:15 +08:00
倪程伟
d2e1f9eb9c feat(wiki): support multi-path and glob patterns for KB source directory
Allow knowledge base source paths to be configured as a newline-separated
list of absolute paths or glob patterns rather than a single directory.

- Each non-blank, non-# line is treated as one path or glob pattern
- Plain paths (no wildcards) retain the existing recursive-scan behaviour
  filtered by SUPPORTED_EXTENSIONS
- Glob patterns (e.g. /data/ocr/**/*.txt) walk from the fixed-prefix base
  and apply Java's PathMatcher against each candidate's absolute path
- Patterns whose filename segment explicitly specifies an extension
  (*.txt, *.{xlsx,csv}) skip the SUPPORTED_EXTENSIONS secondary filter,
  respecting the user's explicit choice (key for OCR pipelines that
  produce .txt output and should ignore the original PDF scans)
- Candidates collected across multiple patterns are deduplicated by
  resolved absolute path so overlapping patterns don't double-count
- Symlink-escape check uses each pattern's own validated scan root
- parseSourcePatterns / extractBasePath moved into WikiSourcePathValidator
  to eliminate a static circular reference between the two services
- Frontend watcher panel: single-line <input> replaced with <textarea>
  supporting multiline editing; i18n updated with example patterns
- No DB schema change; fully backward-compatible with existing single-path
  configs stored in sourceDirectory

Closes #(pending issue)
2026-06-07 18:05:04 +08:00
matevip
6c8283e77a fix(wiki): use index as key for scan error list to avoid duplicate-key warnings 2026-06-07 16:22:04 +08:00
倪程伟
29fcfb5572
fix(wiki): surface scan errors and fix Chinese path handling in Docker (#260)
Surface directory-scan failures to the user via toast and render ScanResult.errors[]; expose MATE_WIKI_ALLOWED_SOURCE_ROOTS as a Docker env entry with blank-entry filtering in the path validator; set C.UTF-8 locale in the runtime image so non-ASCII file names decode correctly during scans.

Fixes #259
2026-06-07 16:18:49 +08:00
matevip
808047d723 feat(proxy): global outbound HTTP/SOCKS proxy with settings page (#109)
Add a single global-proxy switch that routes the backend's outbound traffic
through a configured HTTP/HTTPS/SOCKS proxy, for deployments that cannot reach
overseas APIs directly or must use a unified egress.

- ProxyManager installs the proxy via a default ProxySelector (honored by
  java.net.http and HttpURLConnection), the proxy system properties, and a
  --proxy-server arg for the browser tool; restores direct egress when
  disabled. One switch covers LLM, web search, media generation, channels,
  MCP and the browser.
- SOCKS applies to the HttpURLConnection-based egress only; the java.net.http
  LLM/streaming path uses an HTTP proxy, and the UI states this.
- New Settings -> Network Proxy page: enable toggle, address, bypass list,
  test-connection, and a coverage summary. Config stored as key/value in
  mate_system_setting (no migration).

refs #109
2026-06-07 16:12:02 +08:00
matevip
6a6652d99a chore: bump version to 1.6.0-SNAPSHOT 2026-06-06 20:50:40 +08:00
matevip
86670312e4 release: v1.5.0 2026-06-05 07:53:15 +08:00
matevip
478f169782 fix(goal): hide inline 'set a goal?' prompt once the stream shows a setGoal call 2026-06-03 21:19:27 +08:00
matevip
3883b68cca fix(goal): drop score gate, bill failed evaluator calls, fix Evaluator SPI + tool prompt + bootstrap cap 2026-06-03 21:19:27 +08:00
matevip
da332f2fd8 feat(goal): checklist UI — progress ring, hover checklist card, criteria SSE 2026-06-03 21:19:27 +08:00
matevip
c92bfa1f12 fix(mcp): raise default tool read timeout from 30s to 60s (#247) 2026-06-03 09:47:18 +08:00
matevip
bb2cf12f49 feat(chat): add execution-plan & tool-call detail viewer (closes #246) 2026-06-02 20:17:53 +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
3fe1f65bef fix(wiki-ui): use the shared employee picker and 'employee' wording in pageType permissions 2026-05-31 08:00:13 +08:00
matevip
4cde845e27 feat(wiki-ui): advanced management panel for page types, layers, permissions, watcher and pipelines 2026-05-31 08:00:06 +08:00
matevip
f3e6e1152a feat(chat): add in-chat /skill slash menu with searchable picker 2026-05-29 08:10:22 +08:00
matevip
69bea272dd fix(memory-ui): escape < in <!-- user-edited literals to unblock vite dep-scan
Vite's dep pre-bundling runs esbuild's lite parser over .vue script blocks
to find imports. On esbuild 0.27.5 that parser interprets the
HTML-style sequence `<!--` inside a JS string/regex literal as the start
of a legacy line comment, which made it conflate two unrelated string
literals on lines 95 and 110 of MemoryBrowser.vue and report a fake
"Unterminated string literal" against a phantom line that doesn't exist
in the source.

Replacing the raw `<` with `\x3c` keeps the runtime behavior identical
(includes/regex match the same `<!-- user-edited` marker) but breaks the
HTML-comment heuristic so the scanner no longer chokes. The two call
sites — userEdited detection in parseSections and the strip regex in
stripMarker — both need the escape.

Repro: `pnpm dev` from a cold cache surfaces the error during dep scan,
runtime tests passed already because the actual JS parser handles the
strings fine.
2026-05-29 06:16:41 +08:00
lichuan
bd02734d61 feat(agent): add knowledge base binding tab to agent editor (#237)
Agents now have a per-agent primary wiki KB stored on
mate_agent.primary_kb_id. KBs remain workspace-shared — selecting one in
the agent editor only chooses the default wiki target for that agent, it
does not change the KB's ownership or visibility.

Backend
- AgentEntity: add primary_kb_id field (FieldStrategy.ALWAYS so the UI
  can clear it back to "no primary")
- AgentController#update: switch body to Map<String, Object> so we can
  tell "field missing" apart from "explicit null" via containsKey, then
  convertValue back to AgentEntity
- WikiKnowledgeBaseService:
  - new resolvePrimaryKb(agentId): prefers agent.primary_kb_id when it
    points to a workspace-visible KB; falls back to legacy
    kb.agent_id marker, then to most-recently-updated workspace KB
  - listByAgentId now returns the full workspace set (KBs are
    workspace-shared under the new model)
  - update(id, name, description) no longer touches agent_id
- WikiController: new GET /knowledge-bases/bindable for the UI picker;
  PUT /knowledge-bases/{id} no longer reads agentId
- WikiKnowledgeBaseEntity: add FieldStrategy.ALWAYS on embeddingModelId
  and configContent so explicit nulls actually unbind/clear instead of
  being silently skipped by MyBatis-Plus's NOT_NULL default
- Migrations V129 (H2 + MySQL): add primary_kb_id column + index, backfill
  from legacy kb.agent_id, MySQL uses INFORMATION_SCHEMA guard +
  PREPARE/EXECUTE for idempotency
- WikiKnowledgeBaseServiceTest: 13 cases, all passing

Frontend
- Agents.vue: new "Knowledge Base" tab, radio-select bindable KBs
- API: listBindableKBs() + Agent.primaryKbId typed string | number | null
- IDs handled as strings throughout (Snowflake-safe)
- i18n keys for the new tab in zh-CN and en-US
2026-05-29 06:00:52 +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
16eac232c4 feat(wiki): cascade delete + rename to keep wikilinks consistent 2026-05-28 08:17:19 +08:00
matevip
2b3c068db9 feat(wiki): broken-link lint with job-based async scan 2026-05-28 08:17:04 +08:00
matevip
66d3d90ea9 feat(wiki): slug-first wikilink resolution and safe DOM postprocess 2026-05-28 08:16:56 +08:00
matevip
b81660a2a1 polish(approval-grants-ui): fix active-count pill + reuse mcConfirm for revoke 2026-05-27 15:54:47 +08:00
matevip
fe4f051672 polish(approval-grants-ui): pin the Actions column to the right edge 2026-05-27 15:09:18 +08:00
matevip
5f2adf15f6 polish(approval-grants-ui): show granter name, fix note cell rendering, tighten layout 2026-05-27 15:09:11 +08:00
matevip
b34de4e078 refactor(approval-grants-ui): strip Element Plus, reuse project list+pagination 2026-05-27 15:09:04 +08:00
matevip
6a754f5bfa refactor(approval-grants-ui): rebuild create dialog to match ToolGuard pattern 2026-05-27 15:08:56 +08:00
matevip
b9c5ec03d4 refactor(approval-grants-ui): header aligned with project conventions 2026-05-27 15:08:49 +08:00
matevip
65cf53779a refactor(approval-grants-ui): paginated list, Element Plus icons, shorter sidebar label 2026-05-27 15:08:41 +08:00
matevip
2f5e06f286 fix(approval): three minor issues surfaced by end-to-end testing 2026-05-27 14:08:12 +08:00
matevip
f15b2dced3 feat(ui): auto-approve banner dropdown, management page, and workspace chip 2026-05-27 14:08:04 +08:00
matevip
f163c0b5bc feat(ui): rewrite chat welcome subtitle and suggestions around agent capabilities 2026-05-27 06:58:52 +08:00
matevip
0ac325a337 feat(agent): explicit "no skills / no tools" opt-out flags (#184) 2026-05-26 22:07:12 +08:00
matevip
3ae4498f38 fix(channel,agent,chat): unify channel binding / conversation agent / model pin state sources 2026-05-26 09:40:49 +08:00
matevip
9e9a96f674 fix(agent): resolve relative workspaceBasePath under workspace root 2026-05-25 15:58:05 +08:00