Commit Graph

359 Commits

Author SHA1 Message Date
matevip
982c6c048c feat(security): gate Swagger/OpenAPI UI behind mateclaw.openapi.expose-ui flag
- explicit SecurityConfig authorization for /swagger-ui*, /v3/api-docs*, /webjars/**
- public for local/default profile; admin-only (ROLE_ADMIN) by default in production DB profiles
- override via MATECLAW_OPENAPI_EXPOSE_UI; add RANDOM_PORT integration tests and docs
2026-06-24 10:42:46 +08:00
倪程伟
865513a3b6
docs(api): 完善 WebAPI 文档与 OpenAPI / Swagger 配置 (#407)
Closes #406

- 新增 OpenApiConfig 全局配置 Bean:标题/描述/服务器 + bearerAuth 安全方案
  (覆盖 JWT 与 mc_ PAT,对齐 JwtAuthFilter 前缀分发)
- application.yml 增 springdoc default-flat-param-object + mateclaw.openapi.* 外置项
- api.md 中英双语补全「通用约定」(R<T> 信封、ResultCode、错误模型、IPage 分页、
  ID 约定、三态认证、X-Workspace-Id 机制)+ 9 个旗舰端点完整参考
- 新增 openapi.md 中英双语 Swagger 使用指南
2026-06-24 10:07:11 +08:00
matevip
acfac0b56f feat(agent): add SessionSendTool for multi-turn sub-agent follow-ups 2026-06-23 18:22:32 +08:00
matevip
0d9c2b3532 feat(agent): register SessionListTool as a built-in tool (three dialects) 2026-06-23 18:22:22 +08:00
matevip
f08abad076 feat(skill): self-evolving skills — out-of-band reflection, curator consolidation, agent-authored skill files 2026-06-23 13:51:04 +08:00
matevip
438a5e00d7 chore: point GitHub repo URL to mateaix/mateclaw 2026-06-22 16:23:49 +08:00
matevip
2cf08683a4 release: v1.6.0 2026-06-22 15:07:05 +08:00
matevip
eca4229751 feat(plans): per-step agent delegation + fix kanban pending column (issue #385) 2026-06-21 21:20:58 +08:00
matevip
c656aff349 feat(plans): Kanban boards in the Agents workspace
Live lifecycle board (grid<->board toggle) plus an assignee-swimlane plan
board that groups follow-up re-runs of one goal into a single xN card.
Custom right-side detail/goal panels with markdown output. Fixes plans
being persisted under the per-run trace id so the board actually populates.

Closes #385
2026-06-20 17:52:29 +08:00
matevip
d6001e3e6f fix(db): correct V154 wiki_disabled migration for MySQL and KingbaseES
The cherry-picked V154 used 'ALTER TABLE ... ADD COLUMN IF NOT EXISTS' for
MySQL — invalid on MySQL 8.0.x (a MariaDB-only extension) which aborts Flyway
at startup. Switch to the INFORMATION_SCHEMA + PREPARE guard the other MySQL
migrations use. Also change the KingbaseES column from SMALLINT to BOOLEAN to
match the Java 'Boolean wikiDisabled' field and the existing skills_disabled /
tools_disabled flags (vanilla PostgreSQL is strict about boolean vs smallint).
H2 (already BOOLEAN) is unchanged.
2026-06-20 07:23:54 +08:00
倪程伟
22a212a2e6 feat(agent): add wiki_disabled opt-out flag for knowledge bases
Issue #304. Operators who want an agent with NO knowledge base had no
way to express it: leaving the KB picker empty fell through to "inherit
workspace-wide" (every KB visible), so the agent ended up ingesting
every KB's context. This adds the same opt-out toggle that
skills_disabled (V126) / tools_disabled already provide.

Backend:
- V154 migration (h2 + mysql + kingbase): mate_agent.wiki_disabled
  BOOLEAN/TINYINT/SMALLINT NOT NULL DEFAULT FALSE. Legacy agents stay
  bit-identical.
- AgentEntity.wikiDisabled: Boolean field, @TableField("wiki_disabled").
- AgentBindingService.getBoundKbIds: short-circuit at the top —
  wiki_disabled=true returns Set.of() regardless of binding rows. Mirrors
  the precedence contract of getBoundSkillIds vs skills_disabled.
- AgentBindingService.setKbBindings: a non-empty save auto-clears a
  stale wiki_disabled flag (same contract as setSkillBindings /
  setToolBindings on their respective flags). Empty saves leave the flag
  untouched — the UI toggle owns the bit, not the binding writer.
- AgentBindingServiceWikiDisabledTest: 5 cases covering all three
  return states + the stale-flag auto-clear + empty-save no-op.

Frontend:
- Agents.vue KB picker: add the "此智能体不使用任何知识库" /
  "This agent uses no knowledge bases" toggle, mirroring the skills /
  tools picker layout. Tab badge shows "Off" when the toggle is on.
- types/index.ts: add Agent.wikiDisabled?: boolean.
- Save logic: when wikiDisabled is on, send an empty KB list (the
  setKbs contract then leaves the flag alone server-side, exactly as
  setSkills / setTools behave for their opt-out flags).
- i18n (zh + en): new strings for toggle label, hint, badge, and the
  scope description shown when the toggle is on.

Stacked on top of #382 (which introduced AgentBindingResolver
.getBoundKbIds). No agent-runtime changes — wiki tools already degrade
cleanly when getBoundKbIds returns Set.of().
2026-06-20 07:21:07 +08:00
倪程伟
0ab11f8922 docs(webchat): document /wiki/pages endpoint and [[slug]] picker
Add /wiki/pages row to endpoint table and a new "Wiki knowledge-base
reference ([[slug]] picker)" section explaining the directive-text
mechanism, query parameters, visibility rules (synthesis excluded,
100-page cap, KB-scope fallback), and curl examples (zh + en).

Follow-up docs for the wiki picker endpoint shipped in this PR.
2026-06-20 07:21:07 +08:00
倪程伟
a5e7060045 docs(webchat): polish /skills endpoint docs
Add /skills row to endpoint list table, note optional agentId on /stream,
and add a new "Skill invocation (slash picker)" section explaining the
directive-text mechanism with curl examples (zh + en).

Follow-up polish for the /skills endpoint shipped via PR #374.
2026-06-20 07:21:07 +08:00
matevip
5893d4b33d feat(llm): add GLM-5.2 to Zhipu providers; docs(webchat): integration guide + EN translation 2026-06-18 16:21:53 +08:00
matevip
8f8d43d693 fix(db): renumber webchat migrations to V151/V152 to avoid version collision
The webchat session-id (was V147) and archive/revocation (was V148) migrations
collided with the wiki migrations already occupying V147 (wiki_page_aliases)
and V148 (wiki_entity); wiki migrations run up to V150. Two files sharing a
version makes Flyway abort at startup with "Found more than one migration with
version N", so the app failed to boot on a fresh database. Renumber the webchat
migrations to the next free slots (V151, V152) across all three dialects. Table
names are unchanged, so entities and idempotent column guards are unaffected.
2026-06-18 06:43:06 +08:00
倪程伟
6bbb6489f4 feat(webchat): expose phase / tool_start / tool_end / plan as SSE events
Previously WebChatController.chatStream silently dropped every agent
lifecycle event except _usage_final (and content_delta / thinking_delta
derived from delta.payload). Visitors sat with nothing between the
meta event and the first content chunk — typically 3–10s when the
agent plans / recalls memory / runs tools, longer when the agent
chained multiple tool calls. The JWT chat path (ChatController) had
this wiring; webchat did not.

Curated 4-event subset (per design review):
- phase        — high-level phase transition (planning / generating /
                 summarizing / ...). SDK shows a "AI is thinking..."
                 typing indicator before the first token.
- tool_start   — agent invoked a tool. SDK shows a localized badge
                 ("Searching...", "Reading file.pdf", ...).
- tool_end     — tool completed. SDK clears the badge.
- plan         — Plan-Execute agents expose their step list. SDK can
                 render a checklist.

Deliberately NOT forwarded (internal noise / leak risk):
- _usage_final, _routing_decision — consumed internally
- finish_reason                  — implicit in `done`
- feedback_event                 — visitor can't retry/regenerate anyway
- perf_summary, iteration_*      — internal metrics
- plan_step_started/completed    — too granular; the plan event covers
                                   the visitor's needs

Critical safety constraint: tool_start / tool_end carry ONLY the tool
name. Tool arguments and results are dropped — agent tool calls can
contain PII (file paths, user queries, credentials), and relaying
those to a 3rd-party website frontend is a data leak. The SDK maps
tool name → localized label via its own lookup.

Backward compat: existing clients ignore unknown event types per the
SSE spec, so adding these is non-breaking.

Tests: 5 new cases in WebChatStreamE2ETest covering each event type
+ a regression case asserting internal events are silently dropped.
85/85 webchat tests green.

Docs: docs/zh/webchat.md gains a "实时进度事件" subsection.

Stack: feat/webchat-attachment-e2e → feat/webchat-stream-phase-events
Follow-up to epic #355.
2026-06-18 06:33:17 +08:00
倪程伟
b9bf332ca4 docs(webchat): visitor-facing integration guide (epic #355 PR 8)
docs/zh/webchat.md — single source of truth for downstream integrators.
Covers everything needed to embed MateClaw webchat into a third-party
site without reading source:

- Base URL, auth model (API Key + visitorToken), R<T> response wrap
- Endpoint table (14 visitor-facing + 2 admin)
- Auth flow diagram (how visitorToken gets minted on /stream, reused
  on management endpoints)
- Error code table (400/401/404/409 with semantics)
- SSE event protocol (meta / content_delta / thinking_delta / done /
  error)
- File upload + download flow (visitor-attached vs agent-generated;
  /api/v1/files/generated/<uuid> is permitAll + 7d TTL)
- visitorToken revocation admin endpoint
- Three end-to-end curl examples (first message / list sessions /
  upload-then-send)
- Limits (5 empty-session quota, upload caps, 7d expirations,
  single-instance constraint today)

@Operation / @Parameter / @ApiResponse / @ExampleObject polish on
WebChatController is intentionally deferred — it's noisy mechanical
work that deserves its own focused PR rather than getting rushed in
here. The doc is the canonical reference now; the swagger annotations
can quote it.

Part of epic #355.
2026-06-18 06:33:17 +08:00
倪程伟
332f3339a9 feat(webchat): archive flag + revoked-visitor table + view fields (epic #355 PR 1)
Schema foundations for the rest of the epic. Three additions:

1. mate_conversation.archived — INT default 0. Lets a visitor "soft-close"
   a thread: stays on disk (history preserved, addressable, downloadable)
   but excluded from default /sessions listing. Pinned/archived are
   orthogonal; archive dominates (archived+pinned still hidden by default).

2. webchat_revoked_visitor — registry table consumed in PR 2 by the
   WebChatTokenRevocationService. Unique on (channel_id, visitor_id, deleted)
   so re-revoke is idempotent and deleted=1 un-revokes. Migration written
   for all three DBs (h2 IF NOT EXISTS, MySQL INFORMATION_SCHEMA guard,
   KingbaseES native IF NOT EXISTS) following the V147 pattern.

3. WebChatSessionView gains pinned/archived/streamStatus so the visitor-
   side listing surfaces the same state the admin console sees. Closes
   the "field exposure" gap from the epic.

loadVisitorSessions gains an includeArchived flag (default false) — the
default hides archived threads and excludes them from the empty-session
quota, since the visitor already declared they're done with them.
GET /sessions and GET /sessions/page thread an `includeArchived=true`
query param through.

Tests (WebChatSchemaFieldsTest, @SpringBootTest + H2 + V148):
- revoked-visitor table is queryable
- archived column is read/write
- view exposes pinned/archived/streamStatus
- archived hidden by default, visible with includeArchived=true
- archived empty threads don't saturate the 5-thread quota

Regression: WebChatCreateSessionTest (9/9), WebChatSessionManagementTest
(5/5) — both updated for the new includeArchived param.

Part of epic #355.
2026-06-18 06:33:17 +08:00
倪程伟
ee3e391977 fix(webchat): list sessions whose conversationId hashed (long ids)
When webchat:<key8>:<visitorId>:<sessionId> exceeds 64 chars the
conversationId folds visitorId+sessionId into an unrecoverable hash, so
the thread fell outside listSessions' conversationId-prefix filter and its
sessionId could not be recovered — the thread was invisible and
unaddressable (common with a UUID visitorId + a >10-char sessionId).

Persist the sessionId on creation (new nullable webchat_session_id column)
and enumerate by username + channel prefix (webchat:<key8>:), which also
matches the hashed form. sessionId is read from the column, falling back to
parsing the conversationId only for legacy rows.

Adds a @SpringBootTest covering listing (incl. the hashed thread), message
pagination, session paging/search, rename, and token rejection end-to-end.

Refs matevip/mateclaw#346
2026-06-17 23:21:08 +08:00
matevip
6e7c137154 feat(wiki): entity-level knowledge graph extraction (#336)
Add an opt-in named-entity extraction pass so the wiki knowledge graph
captures fine-grained entities (people, organizations, locations, ...)
and their relations, not just page-level link relations.

- new tables mate_wiki_entity / _mention / _relation (h2/mysql/kingbase)
- structured LLM extraction per chunk with entity resolution
  (normalized-key dedup + embedding near-merge), mention/relation
  persistence and page linking via chunk citations
- per-KB opt-in toggle (off by default); async dispatch after embedding
- read API: entity list, KB graph, entity ego-graph, manual extract
- UI: entity-layer toggle in the graph view + KB config toggle
- replace inline fully-qualified class names with imports in WikiProcessingService

Closes #336
2026-06-17 14:17:54 +08:00
matevip
fe68f22aa8 feat(memory): bound always-on memory growth with injection budget, consolidation, and file ceilings
Always-on memory (structured user/feedback blocks, PROFILE.md, MEMORY.md) is injected into every system prompt but only ever grew, inflating per-turn context over time. This adds deterministic size control across all always-on sources:

- Injection budget: cap the always-on structured block by total chars and per-type entry count, keeping the most-recently-updated entries (LRU by Updated date) and disclosing how many were omitted
- Nightly consolidation: a dedicated scheduled pass merges duplicate/stale user & feedback entries via the LLM, preserving each entry's original Updated date; runs per owner bucket (shared + personal) with a per-run cap and a never-grow safety guard
- File ceilings: deterministic backstop truncates PROFILE.md / MEMORY.md at a section boundary when a rewrite overruns its budget
- Manual trigger endpoint for the consolidation maintenance task

All knobs under mate.memory.*; covered by unit tests.
2026-06-17 11:04:19 +08:00
matevip
d9a9d07704 fix(wiki): broken-link rescan precision, slug/title resolution, and dangling-link reconcile (#333)
- rescan: keep the KB id as a string end to end so the 19-digit snowflake id
  isn't truncated past Number.MAX_SAFE_INTEGER (rescan no longer 404s)
- lint: resolve [[...]] targets against page slugs AND titles like the viewer,
  so a title reference to an existing page is no longer reported broken
- ingest: derive the slug deterministically from the title (no inconsistent
  romanization), auto-recompute broken links once a KB finishes importing,
  and reconcile dangling [[concept]] links — redirect to the covering page via
  declared aliases, or demote to plain text when uncovered
- add the page aliases column migration for h2 / mysql / kingbase
2026-06-15 16:14:25 +08:00
matevip
a0eba17688 fix(db): keep Integer-mapped wiki flag columns as SMALLINT in the PostgreSQL-family tree
The blanket SMALLINT->BOOLEAN flag-column conversion over-reached: six wiki
columns map to Integer (1/0) entity fields, not Boolean. On vanilla PostgreSQL,
reading a BOOLEAN into a JDBC int throws 'Bad value for type int : f', breaking
every wiki KB list / SSE chat. Revert only those six back to SMALLINT (V133/V134/
V135/V136/V146 in the PostgreSQL-family tree) with guard comments; genuine
Boolean-entity columns stay BOOLEAN.
2026-06-15 07:37:04 +08:00
matevip
32ad11d6c4 fix(db): cover remaining boolean columns (ALTER-added and primitive-boolean) 2026-06-14 16:47:38 +08:00
matevip
1ac1df12bf fix(db): store JSON columns as TEXT in the PostgreSQL-family tree 2026-06-14 16:47:31 +08:00
matevip
f3119e0217 fix(db): declare boolean flag columns as BOOLEAN in the PostgreSQL-family tree 2026-06-14 16:47:23 +08:00
matevip
5685b09fd2 docs(release): add v1.6.0 release notes (changelog index mirror) 2026-06-14 16:47:09 +08:00
matevip
07da1d610b feat(db): add PostgreSQL Spring profile 2026-06-14 16:47:02 +08:00
matevip
d7418e49df fix(db): make the PostgreSQL-family SQL portable to vanilla PostgreSQL 2026-06-14 16:46:25 +08:00
matevip
25a83ad858 fix(db): make KingbaseES driver opt-in and restore default SSRF guard
The KingbaseES JDBC driver is not on Maven Central; declaring it as a
required runtime dependency broke the default build for anyone without
the proprietary jar. Move it into an opt-in `kingbase` Maven profile
(build with `mvn package -Pkingbase`). No Java code imports the driver
classes — it is loaded at runtime via driver-class-name only, so the
default build no longer needs it.

Also drop `mateclaw.browser.ssrf-check-enabled: false` from the default
application.yml: the code default is true, and disabling the SSRF guard
globally is unrelated to KingbaseES support.
2026-06-14 10:34:35 +08:00
铭萱
446f34b6b5
feat(db): support KingbaseES (人大金仓) domestic database (#324)
Add KingbaseES support as an opt-in profile: dedicated migration tree, bilingual seed data, runtime DbType detection (KINGBASE_ES / POSTGRE_SQL), and JDBC URL handling in the datasource manager.
2026-06-14 10:30:09 +08:00
倪程伟
18daad79b2
feat(wiki): unify raw materials & source watcher into a Sources tab with per-KB auto-sync (#316)
* feat(wiki): unify raw materials & source watcher into a Sources tab with per-KB auto-sync

The raw-material directory scan and the Advanced "source watcher" sub-tab were
the same engine (same kb.sourceDirectory, same WikiDirectoryScanService) split
across two surfaces with two editable directory inputs. Merge them into one
"Sources" tab (upload / paste / directory manual scan + auto-sync toggle +
the raw-material list) and drop the watcher sub-tab from Advanced.

Auto-sync is now per-KB opt-in: a new watcher_enabled column (V146) gates the
periodic scan per knowledge base. The server-global mate.wiki.watcher-enabled
stays as an ops master switch — a KB is auto-scanned only when both are on
(AND). Manual scans are unaffected. Scan interval stays global for now
(tracked separately).

Closes matevip/mateclaw#314

* docs(wiki): document source-watcher global switch env vars

Expose MATE_WIKI_WATCHER_ENABLED / MATE_WIKI_WATCHER_INTERVAL_MS as
explicit placeholders in application-mysql.yml, .env.example and
docker-compose.yml, mirroring MATE_WIKI_ALLOWED_SOURCE_ROOTS. Notes the
AND semantics (global ops gate + per-KB toggle) so operators know the
global switch alone is not sufficient.
2026-06-11 09:29:26 +08:00
matevip
83615593cd fix(tool/guard): harden workspace filesystem sandbox (#313)
- Fail closed to a global fallback sandbox root when a conversation has no
  per-workspace base path, instead of leaving file/shell tools unconstrained
- Refuse shell commands that delete the workspace root directory itself
- Block workspace-boundary escapes at the policy layer before the approval
  prompt, not only at execution time
- Approval bar now shows the actual command / target path being approved
2026-06-10 17:17:07 +08:00
matevip
7478491652 feat(llm): add Claude Fable 5 support 2026-06-10 10:14:51 +08:00
matevip
0112af7105 fix(mcp): point ckjia-shopping seed at production endpoint (#289)
The V85 seed shipped a dev/test placeholder (sse + http://localhost:8085/sse
+ "Bearer ${CKJIA_MCP_KEY}") that can never connect, so the 参考价 price-
comparison skill was unusable until an admin hand-edited the row.

Add V144 (h2 + mysql) to rewrite the seed to the real CKJIA SaaS endpoint:
streamable_http + https://m.ckjia.com/api/ai/mcp, no auth header, connect/read
timeouts raised to 60s. Conditional on the row still carrying the dev
placeholder URL, so an admin who already pointed it at a private deployment is
left untouched; idempotent and leaves `enabled` opt-in.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 14:27:50 +08:00
matevip
94cf812207 feat(tool): add execute_code for running agent-authored code (#257)
Add an execute_code built-in tool that runs python/bash/node code the agent
writes on the fly, so a documentation-only skill (a SKILL.md with no bundled
scripts) can be acted on. Scoped runs inject the skill's secrets and run in
the skill directory; otherwise a private scratch directory is used. Host
secret env vars are scrubbed from the subprocess. execute_code is an
agent-wide capability, registered in the tool catalog (V143), and screened
by the tool guard with a dedicated set of destructive-pattern rules.

Tests cover python/bash/node execution, scratch-dir fallback, env scrubbing,
argument decoding, and guard gating.
2026-06-09 08:05:50 +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
倪程伟
bd1ceace74 feat(agent): render runtime model identity line in RuntimeContextInjector
Add 5-arg buildContextMessage overload that emits [system-context] Model:
for every origin (web/cron/IM). Legacy 3/4-arg overloads delegate to the
new one with null model args, keeping their output byte-identical.

Also fix pre-existing FeishuMentionTest compile error caused by removed
mentionMatchesAnyAlias/collectMentionIdentifiers methods.
2026-06-08 20:53:39 +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
be7bbd9644 fix(skill): persist skill workspace on the existing data volume; skip binary entries in ZIP packages (#273) 2026-06-07 23:09:42 +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
46f3d425e0 feat(agent): add kill-switch for final-answer Markdown normalization
Gate MarkdownNormalizer behind mate.agent.markdown-normalize-enabled (default
true) so operators can disable the rewrite verbatim if a normalization edge
case ever mangles a legitimate answer.
2026-06-07 19:15:14 +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
7894a50067 fix(tool): emit absolute download URLs for streaming-generated files (#164)
Streaming chat ran render tools on an async thread with no bound request,
so download links lost their host and arrived without a domain. Resolve the
host on the request thread and carry it through ChatOrigin/ToolContext;
falls back to a configurable public-base-url, then a relative path.
2026-06-07 15:03:48 +08:00
matevip
86670312e4 release: v1.5.0 2026-06-05 07:53:15 +08:00
matevip
cd1c66fc0e feat(goal): structured checklist data model — criteria column, criterion records, dual-carrier evaluation result 2026-06-03 21:19:26 +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
9f02a0a221 fix(agent): unbreak DashScope tool calls, sharpen error class, rebalance plan triage (refs #246) 2026-06-03 08:38:48 +08:00
matevip
18f3675fd3 docs(api): align workflow & trigger endpoint reference with actual controllers (#248) 2026-06-03 07:32:20 +08:00
matevip
48611a6f4d feat(memory): per-owner memory isolation with owner_key + visibility scope (#235) 2026-06-02 17:04:06 +08:00
matevip
55cf2a8458 feat(wiki): wire layer derivation and fact-dependency persistence into ingest 2026-05-31 07:59:20 +08:00
matevip
8e8c1e34c7 feat(wiki): inject pageType profile into route/create/merge prompts + content templates 2026-05-31 07:59:13 +08:00
matevip
f0cbfc913e fix(wiki): default source-path validation to fail-closed in production profile 2026-05-31 07:58:04 +08:00
matevip
c3388c3f1e feat(wiki): pipeline runtime schema — definitions, runs, step runs 2026-05-31 07:56:17 +08:00
matevip
28284fbcac feat(wiki): layered-knowledge schema — layer, dependency table, stale columns 2026-05-31 07:55:55 +08:00
matevip
b50e384e0d feat(wiki): inject KB pageType profile into the batch-create prompt 2026-05-31 07:54:34 +08:00
matevip
7f4987c30a feat(wiki): resolve effective pageType profile per KB with built-in default 2026-05-31 07:54:13 +08:00
matevip
368797e619 feat(wiki): add KB-scoped pageType profile table and page metadata columns 2026-05-31 07:54:06 +08:00
matevip
502b8406a6 feat(wiki): per-agent pageType read permission gate for wiki tools 2026-05-31 07:53:48 +08:00
matevip
f1c55b80e8 feat(memory): route summarized typed facts into structured memory 2026-05-30 07:36:20 +08:00
matevip
a27084f9cf feat(memory): recall project facts via query-conditioned prefetch 2026-05-29 16:05:10 +08:00
matevip
f8088088b5 fix(feishu): align recent-file cache id with router so attachments resolve 2026-05-29 10:08:01 +08:00
matevip
237f649e7e fix(tool-guard): trust shared skill root outside the workspace boundary 2026-05-29 09:59:19 +08:00
matevip
82538ca3aa feat(llm): add Claude Opus 4.8 + 4.8 Fast model entries 2026-05-29 07:06:19 +08:00
matevip
0141b00270 docs(agent): document per-agent primary knowledge base binding (1.5.0)
Add the user-facing and API-reference docs that explain how an employee
can declare a primary knowledge base, what the runtime fallback chain
looks like, and how the binding is driven from the API.

agents.md (zh + en)
- New section "Knowledge base binding (per-agent primary KB)" right after
  the tool-binding section, with a 1.5.0 New In badge
- Lays out the design intent explicitly: KBs stay workspace-shared, the
  binding only chooses a default target, multiple agents may pick the
  same KB as primary
- Documents the runtime resolution order used by wiki tools: explicit
  kbName/kbId, agent.primaryKbId, most-recently-updated workspace KB
- Migration note about the legacy kb.agent_id to agent.primary_kb_id
  backfill and the visibility change for anyone who relied on the old
  one-to-one isolation

api.md (zh + en)
- Under Agents: document the primaryKbId field with the three-state PUT
  semantics (omit / null / value) and example curl calls
- Under LLM Wiki: document GET /api/v1/wiki/knowledge-bases/bindable and
  the explicit warning that PUT /api/v1/wiki/knowledge-bases/{id} no
  longer processes the agentId field
2026-05-29 06:33:46 +08:00
matevip
51e1bd2582 fix(migration): renumber agent primary_kb to V130 to clear V129 collision
PR #237 introduced V129__agent_primary_kb.sql while dev also has
V129__wiki_page_broken_links.sql shipped from the broken-link lint work.
Flyway rejects duplicate version numbers at startup, so the agent
primary_kb migration moves to V130 across both H2 and MySQL dialects.

No content change beyond the rename — the column add, index, and
backfill SQL are identical to the V129 originals from #237.
2026-05-29 06:01:02 +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
a71c49d374 feat(wiki): analyze-stage slug whitelist + code-aware enrich applier 2026-05-28 08:17:27 +08:00
matevip
105b075f13 feat(wiki): slug-first prompt contract and same-batch link safety 2026-05-28 08:17:13 +08:00
matevip
2b3c068db9 feat(wiki): broken-link lint with job-based async scan 2026-05-28 08:17:04 +08:00
matevip
b7e923fac4 feat(approval): grant-based auto-approve with safety floor and resolution log 2026-05-27 14:07:39 +08:00
matevip
ac090afde3 fix(workflow): pre-check unique name on create/rename, return 409 instead of 500 (Fixes Gitee #IJPYWA) 2026-05-26 23:35:04 +08:00
matevip
0ac325a337 feat(agent): explicit "no skills / no tools" opt-out flags (#184) 2026-05-26 22:07:12 +08:00
matevip
9e9a96f674 fix(agent): resolve relative workspaceBasePath under workspace root 2026-05-25 15:58:05 +08:00
倪程伟
cbdd70379b
feat(agent): optional agent-level workspace basePath override (#212)
* feat(agent): optional agent-level workspace basePath override

Add workspaceBasePath field to AgentEntity that optionally overrides
the workspace-level basePath. When set, the agent uses its own directory;
when null, it inherits the workspace's basePath (existing behavior).

- AgentEntity: new workspaceBasePath field with ALWAYS update strategy
- AgentGraphBuilder: agent-level override takes priority over workspace
- Flyway migration V121 for H2 and MySQL
- UI: form input in basic tab with i18n (zh-CN, en-US)

* fix(agent): rename migration V121→V125 to avoid Flyway conflict with upstream

Upstream already has V121__tool_disclosure_tier.sql. Rename our
migration to V125 (next available after V124).

* fix(agent): make MySQL V125 migration idempotent

Use INFORMATION_SCHEMA check before ADD COLUMN to avoid
"Duplicate column name" error on re-deploy.
2026-05-25 15:42:01 +08:00
matevip
7f45b95432 feat(agent): include progress-ledger snapshot in limit-exceeded wrap-up 2026-05-24 23:00:49 +08:00
matevip
59d090ebb5 chore(agent): raise default max_iterations 100 -> 150 2026-05-24 23:00:42 +08:00
matevip
05289e6bdb feat(agent): per-conversation progress ledger to survive context trims 2026-05-24 23:00:03 +08:00
matevip
4e01c98fc1 docs: add v1.4.0 release notes and update guides for the release 2026-05-23 22:55:03 +08:00
matevip
cef1730e6e feat(tool,skill,ui): progressive tool/skill disclosure (load_skill + enable_tool + tier UI) 2026-05-23 09:07:45 +08:00
matevip
773c64bfd7 chore(tool): localize send_file success message and use English Javadoc 2026-05-22 16:32:10 +08:00
倪程伟
f16021690f
feat(tool): add send_file tool for sending existing server files as IM attachments (#199)
* feat(tool): add send_file tool for sending existing server files as IM attachments

Adds a new built-in tool that reads a file from the server and stashes it
in GeneratedFileCache so the channel adapter (Feishu, DingTalk, etc.)
automatically sends it as a native attachment. This fills the gap where
agents had no way to send existing server files to users — ReadFileTool
only reads text, and render tools only generate new files.

- New SendFileTool with path validation, MIME detection, 20MB limit
- Added "send_file" to tool allowlist in AgentBindingService
- Added i18n error messages (zh-CN + en-US)

* fix(tool): send_file returns URL in scrubber-detectable format

The previous JSON return format caused the LLM to reply with just
"status: sent" without echoing the /api/v1/files/generated/{id} URL.
GeneratedFileScrubber only scans the LLM's final text output, so the
file was never delivered as a native attachment.

Changed to match GeneratedFileLink's format: returns a markdown link
with explicit instructions for the LLM to echo the URL verbatim.
2026-05-22 16:27:53 +08:00
倪程伟
6bf64449bd
fix(channel/feishu): register all IM event handlers to prevent HandlerNotFoundException (#196)
The Lark SDK throws HandlerNotFoundException for any event type without
a registered handler. This exception is caught internally by the SDK's
WebSocket client, which then sends a 500 response to the Feishu server.
The server may close the connection as a result, and the exception is
swallowed — never reaching the application layer.

Added empty handlers for all remaining IM event types:
- P2MessageReadV1 (read receipts)
- P2MessageRecalledV1 (message recall)
- P2ChatMemberBotDeletedV1 (bot removed from chat)
- P2ChatMemberUserAddedV1 / UserDeletedV1 / UserWithdrawnV1
- P2ChatUpdatedV1 (chat info update)
- P2ChatDisbandedV1 (chat disbanded)
- P2ChatAccessEventBotP2pChatEnteredV1 (bot entered p2p chat)

Also added explicit logback config for com.lark.oapi at WARN level
to ensure SDK internal errors are not silently filtered.

Refs: larksuite/oapi-sdk-java#185
2026-05-22 16:10:05 +08:00
matevip
81915ccfae feat(tool): read_file can page through an oversized single line via startColumn (#190) 2026-05-21 22:27:09 +08:00
matevip
e61b05bba0 fix(tool): read_file no longer returns empty content + infinite retry on oversized single lines (#190) 2026-05-21 16:26:24 +08:00
matevip
a910004b3b feat(agent): digital-employee builder skill to auto-create agents and chain them into a workflow (#165) 2026-05-21 16:26:04 +08:00
matevip
e8ec612ca8 docs: add user guide for the persistent-goal feature 2026-05-21 16:25:50 +08:00
matevip
2b6a4c64c9 fix(agent): add data-fidelity rules to summarizer prompts + fix fallback cut (#187) 2026-05-21 15:13:15 +08:00
matevip
03e68d3c74 fix(agent): structure-aware truncation to stop mid-JSON cuts inducing hallucination (#187) 2026-05-21 15:13:07 +08:00
matevip
ac6c8a18e3 feat(goal): persistent cross-turn goal with self-evaluation scaffolding 2026-05-21 14:43:01 +08:00
matevip
85d7ee23c4 sync: ChannelToolProvider SPI + node-local reconcile framework for channel-native tools 2026-05-20 12:18:51 +08:00
matevip
35f010d7a1 sync: Feishu CardKit streaming-card adapter via cardkit/v1 SDK 2026-05-20 11:37:12 +08:00
matevip
58c53687e5 fix(llm): purge mate_model_config tombstones (V118) 2026-05-20 10:14:19 +08:00
matevip
db16ff02a5 chore: drop external project name references from code comments 2026-05-20 08:09:43 +08:00
matevip
a828de1306 feat(skill): add skill-authoring builtin + retarget node-inspect-debugger to Electron/Vite 2026-05-20 08:09:34 +08:00
matevip
0a57cb3358 fix(workspace): harden workspace create and delete 2026-05-19 20:06:44 +08:00
matevip
4cd21056a0 feat(skill): automatic lifecycle archival for idle skills 2026-05-19 09:55:59 +08:00
matevip
33a40ad9d9 feat(wiki): support HTML, Excel, PowerPoint and CSV raw materials 2026-05-18 21:57:43 +08:00
matevip
d53d66abe3 feat(chat): per-conversation model selection (#150) 2026-05-18 16:27:27 +08:00