Commit Graph

1393 Commits

Author SHA1 Message Date
matevip
bf6bed5511 feat(wecom): event-driven progress bubble with live tool trace 2026-07-21 10:29:00 +08:00
matevip
beb1a8c243 feat(channel): extensible magic commands (/new /help /status /stop) 2026-07-21 10:28:41 +08:00
matevip
0cfd8b133a fix(build): pin shell/SQL scripts to LF via .gitattributes 2026-07-21 10:28:26 +08:00
matevip
f517580e22 fix(weixin): send generated files through weixin channel 2026-07-21 10:28:07 +08:00
mateaix
fcd2b04397 fix(build): pin shell/SQL scripts to LF via .gitattributes (#544)
Windows checkouts with core.autocrlf=true (the Git for Windows default)
converted docker/postgres/init/10-app-role.sh to CRLF, so the container
entrypoint failed with 'cannot execute: required file not found' and the
postgres/server containers crash-looped. Pinning *.sh/*.sql to LF makes
Windows clones produce container-executable scripts regardless of the
local autocrlf setting.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 21:58:41 +08:00
jack
1e2b7bbc2c
fix(weixin): send generated files through weixin channel (#543)
Send agent-generated files as native WeChat attachments via the iLink upload flow, and fix the wire protocol for file uploads: dedicated wire ObjectMapper (bypasses the global Long-to-String serializer), md5/len fields and encrypt_type on media items, channel_version 1.0.2, and explicit business-error handling on ret != 0. The weixin adapter now routes generated-file URLs through GeneratedFileScrubber, matching WeCom/Feishu behavior.

Fixes #307
2026-07-20 20:34:59 +08:00
matevip
d10ed9dd06 feat(channel): add clear magic command 2026-07-20 18:21:46 +08:00
matevip
ae62faee4e fix(chat): refresh agent list on chat page reactivation
The chat page is kept alive by the router so navigating away and back
only fires an activation hook, not a fresh mount. An agent created,
edited, or deleted elsewhere (e.g. the employee management page) never
reached the chat page's own agent list, and stayed invisible or
unselectable in the agent picker until a full page reload forced a
fresh mount. The agent list is now refetched on every reactivation.
2026-07-17 18:15:38 +08:00
matevip
22a61e6e78 feat(wiki): closed relation schema for entity extraction
Entity extraction previously constrained entity types but let the
model freely invent any relation between entities, producing noise
that diluted the entities a knowledge base actually cares about.
Adds an optional per-KB relation schema (subjectType/predicate/
objectType triples): when set, the extraction prompt is scoped to
only those relations, and a hard filter drops anything that slips
through before it is persisted. Empty/unset keeps the existing
open-vocabulary behaviour.
2026-07-16 17:39:41 +08:00
matevip
7a1d237de4 fix(skill): decode zip entry names and content independently to fix mojibake on mixed-encoding archives
Windows-authored zips often store entry names in the local codepage (GBK)
without setting the ZIP UTF-8 flag, while file content stays UTF-8. The
previous fallback decoded the whole archive with one charset, so a single
GBK-named entry forced already-correct UTF-8 content to be re-decoded as
GBK, corrupting valid Chinese text into mojibake. Names and content now
each try UTF-8 first and fall back to GBK independently, per entry.
2026-07-16 14:13:27 +08:00
RobinZhiBin
19bd612c9a
fix(datasource): re-encrypt password on connection test and discover PostgreSQL views 2026-07-15 16:07:53 +08:00
倪程伟
b23cc32f33
fix(wiki): make global starter-pack templates read-only
Global transformation templates (workspace_id IS NULL, e.g. the 7 built-in
starter packs made global by V165) were shared across every workspace but
not actually read-only: any workspace member could edit or delete them,
mutating/affecting all workspaces, with deletes unrecoverable (Flyway
seed runs once).

- Controller: reject update/delete of null-workspace templates with 403
  (err.wiki.global_template_readonly); read/apply paths unchanged.
- Service: defense-in-depth — update/delete also reject global templates,
  guarding non-HTTP callers (WikiTool LLM entry points). delete() now
  checks the entity before deleting instead of deleting blindly.
- findByName: add deterministic ORDER BY (workspace_id IS NULL) ASC so a
  workspace-local template wins over a same-named global one (was LIMIT 1
  with no ordering). Consistent across H2/MySQL/Kingbase.
- i18n: new err.wiki.global_template_readonly (zh + en).
- Tests: +2 controller mock tests (403 on update/delete, no service write),
  +2 E2E tests (global template stays intact; findByName prefers local).

Tests: 10/10 green (4 controller + 6 E2E).
2026-07-15 14:57:18 +08:00
倪程伟
fbfb8982cc
fix(agents): keep each (provider, model) unique in the preference chain
In the "Edit Agent → Preferred Providers" tab the same (provider, model)
combination could be selected repeatedly — e.g. two rows of the same
provider both pointing at the same model, or two "provider default" rows.
This is unintended: a provider may repeat across the fallback chain, but
each (provider, model) should stay unique.

Root cause: addProviderEntry() pushed unconditionally (the code comment
even said "we never dedup here") and the model <option>s had no disabled
state, so already-chosen models remained selectable.

Fix (Agents.vue):
- isProviderChoiceTaken(): detect whether a (provider, model) slot — or the
  provider-default slot (modelId === null) — is already used in another row.
- Model <option> + the default-model option are :disabled when already taken;
  the current row's own value stays selectable (exceptIdx).
- addProviderEntry(): take the default slot if free, else the first unused
  model; do nothing if every option is taken.
- The "+ Provider" pool button is disabled once the provider has no free
  (provider, model) slot left, so the click is never a silent no-op.

The existing unique index uk_agent_provider_model(agent_id, provider_id,
model_id) already guards non-null duplicates at the DB level, but it cannot
catch model_id IS NULL rows (SQL treats NULLs as distinct); the UI is now
the single source of truth for that.

Fixes #530
2026-07-15 14:56:16 +08:00
倪程伟
97a040aa89
fix(chat): dedupe tool-call segments by toolCallId, not name+args
A tool/MCP call could render 2+ times in the timeline (issue #521). The
tool is invoked once — this is a display artifact. The segment de-dup in
MessageBubble keyed on `toolName::toolArgs`, which fails two ways:

- The same logical call rendered on both the live SSE stream and the
  reloaded/persisted path can carry differing toolArgs strings
  (whitespace / key-order from re-serialization), so the two are NOT
  de-duplicated and both survive → the reported duplicate.
- Genuine repeated calls of the same tool with identical args (e.g. shell
  / python retries) share the key and get wrongly collapsed to one.

Prefer the LLM-provided toolCallId (carried end-to-end on both live and
persisted segments, stable across serialization) and fall back to
toolName::toolArgs only for legacy segments without an id. This fixes
both the visible duplication and the over-collapse.

Adds pure-function tests for the de-dup logic.
2026-07-15 14:53:22 +08:00
倪程伟
fc3d84d6c2
fix(wiki): budget the system-prompt KB page listing to the model window
buildWikiContext enumerated an agent's bound knowledge-base pages into
the system prompt capped only by maxContextChars (default 10000, sized
for large cloud models). On a small-context model a large KB therefore
consumed a big fixed slice of the window on every turn — the "tool token
estimate fills the context" report in #521 (the growth lands in the
system-prompt bucket, not the tool-schema bucket; wiki tool schemas are
fixed-size and do not scale with file count).

Add a budgeted buildWikiContext(agentId, budgetTokens) overload mirroring
buildRelevantContext: the page enumeration also stops once the estimated
token total exceeds the budget, appending the existing
'... and more (use wiki_list_pages)' hint. AgentGraphBuilder passes the
same prefix budget it already applies to the memory block; the legacy
Integer.MAX_VALUE path keeps chars-only behavior for large models.

Tests cover null-budget (all pages), token-budget truncation, and
zero-budget skip.
2026-07-15 14:52:43 +08:00
倪程伟
04a9bb9e13
fix(chat): honour per-agent model override in web chat model selector
The web ChatConsole seeded a fresh conversation's model from the global
default, never the selected agent's model override, and handleSendMessage
then pinned that default onto the conversation row. Since a conversation
pin outranks the agent override in the backend runtime resolver
(AgentGraphBuilder.resolveRuntimeBaseModel), the model chosen on the
agent edit page was silently clobbered. IM channels and external webchat
were unaffected — they leave the conversation unpinned.

- applyConversationModel now follows the backend precedence:
  conversation pin > agent model override > global default.
- The agent tier resolves via /agents/{id}/capabilities (authoritative)
  with a synchronous fallback (currentAgent.modelName against the
  enabled-model list) so an agent switch, a capability-fetch failure, or
  a not-yet-hydrated deep-link still honour the override instead of
  dropping to the global default.
- userPickedModel guards the async re-seed from clobbering an explicit
  pick; reset on new/switch/delete conversation.
- Unit tests cover the precedence tiers, the empty-string capabilities
  wire shape, and the synchronous fallback.
2026-07-15 14:51:55 +08:00
倪程伟
bf224abc05
feat(llm): default model discovery by protocol for custom providers + configurable modelsPath
Custom (user-added) providers were hard-coded supportModelDiscovery=false in
createCustomProvider, so self-hosted OpenAI-compatible endpoints (vLLM /
Xinference / LocalAI / gateways) never surfaced the 'discover models' button —
users had to add every model id by hand.

- ModelProtocol: add per-protocol supportsSelfConfiguredDiscovery() + resolve()
  helper (single source of truth for chat-model class and capability flags).
  baseUrl+apiKey protocols (openai-compatible, dashscope-native, gemini-native,
  anthropic-messages) => true; OAuth protocols => false. The flag is deliberately
  narrower than 'can ever discover' (built-in ChatGPT-OAuth still discovers via
  its OAuth session); javadoc warns against reusing it to gate the button.
- createCustomProvider: default supportModelDiscovery from the resolved protocol
  instead of always false. Existing rows are unaffected (no migration).
- OpenAiModelsPath: new single source of truth for the models-listing path,
  honoring an optional 'modelsPath' generateKwargs override (mirrors the existing
  'completionsPath' override) for endpoints behind a reverse proxy / non-standard
  prefix (e.g. /openai/v1/models) that would otherwise 404 on /v1/models.
  Shared by BOTH discovery (ModelDiscoveryService) and the failover liveness
  probe (OpenAiCompatibleListModelsProbe) so an override can't make a provider
  discoverable yet still marked unhealthy by a probe hitting the wrong path.
- Tests: ModelProtocolTest (capability table + resolve fallback), OpenAiModelsPathTest
  (path branch table + vendor cases + modelsPath override), and custom-provider
  discovery-default assertions. Path-resolution coverage consolidated into
  OpenAiModelsPathTest (was split across the discovery + probe test files).
- Docs: zh/en models.md note custom-provider discovery + modelsPath override.

Refs matevip/mateclaw#519
2026-07-15 14:50:53 +08:00
matevip
cd0360ff3f fix(wiki): stabilize concurrent raw-material uploads and PostgreSQL-compatible IDs
Give raw-material uploads a dedicated five-minute timeout and process file-picker and drag/drop uploads through a shared two-worker queue, so constrained uplinks no longer abort multipart requests at the global 30-second deadline.

Switch wiki processing jobs and page citations to application-assigned IDs: the PostgreSQL/Kingbase migrations define plain BIGINT primary keys without identity defaults, so database-generated keys fail on insert.
2026-07-15 14:27:14 +08:00
matevip
e2c3cfd5b4 fix(db): application-assigned ids for entities lacking auto-increment on PostgreSQL-compatible dialects
Eight entities (fact, fact contradiction, morning-card seen, wiki hot
cache / relation / transformation / transformation run / image caption
cache) declared IdType.AUTO while their PostgreSQL-compatible migrations
define the primary key as a plain BIGINT with no identity default.
MyBatis-Plus omits the id column from the generated INSERT under AUTO,
so every insert fails with a NOT NULL violation on those databases —
silently on paths that only log a warning. Switch them to snowflake
ASSIGN_ID, which works on all dialects since auto-increment columns
accept explicit values. Add a parameterized contract test pinning the
id strategy for all eight entities.
2026-07-15 14:26:47 +08:00
matevip
6aad9fd945 fix(ui): resolve lint errors surfaced by the new ESLint config
Use const for a never-reassigned local, drop an unused v-for index,
add a default branch to an exhaustive switch the linter cannot prove,
and remove eslint-disable directives that no longer match enabled rules.
2026-07-15 14:26:27 +08:00
matevip
f97624874c chore(ui): add ESLint 9 flat config and fix lint script
The lint script referenced eslint with --ext flags but the repo never had
an ESLint config file, so pnpm lint always failed. Add a flat config
(typescript-eslint recommended + vue essential) with legacy-code rules
downgraded to warnings, drop the flat-config-incompatible --ext flags,
and move pnpm build approvals from the no-longer-read
pnpm.onlyBuiltDependencies field to pnpm-workspace.yaml allowBuilds.
2026-07-15 14:25:59 +08:00
RobinZhiBin
8a6dd1fa67
fix(wiki): stabilize concurrent raw-material uploads and PostgreSQL-compatible IDs
Give raw-material uploads a dedicated five-minute timeout and process file-picker and drag/drop uploads through a shared two-worker queue, so constrained uplinks no longer abort multipart requests at the global 30-second deadline.

Switch wiki processing jobs and page citations to application-assigned IDs: the PostgreSQL/Kingbase migrations define plain BIGINT primary keys without identity defaults, so database-generated keys fail on insert.
2026-07-15 09:51:20 +08:00
mateaix
e82adfed42 chore(ui): ESLint 9 flat config, lint script fix, and lint error cleanup 2026-07-14 21:11:58 +08:00
matevip
f0dcc44fef feat(workspace): default storage root setting + desktop local-tools whitelist management (#512)
- Settings → System gains a 'default workspace storage path' item: validated
  on save (absolute, creatable), applied immediately without restart, and
  re-applied from the database on startup. Blank clears the override;
  existing data is never migrated.
- Desktop local file/command tools get a renderer settings page (allowed
  directory list with per-row delete, add via native picker, enable toggle,
  tunnel status); the native dialog additionally gains a 'remove directory'
  flow, fixing the whitelist that could only grow.
- System settings save surfaces backend validation errors as a toast.
2026-07-14 18:24:58 +08:00
mateaix
cf43294a9e fix(ui): resilient lazy-route loading during heavy agent runs (#515)
- router.onError fallback: a failed route-chunk load hard-navigates to the
  clicked route once (guarded against reload loops) instead of hanging
  silently until a manual refresh
- warm all lazy route chunks during idle time after login, so sidebar
  navigation no longer depends on live chunk fetches under load
- SSE executor switches to a virtual-thread-per-task executor, matching
  the app-wide virtual-thread model
2026-07-13 21:50:53 +08:00
matevip
6f875215ab chore: bump version to 2.0.0-SNAPSHOT 2026-07-13 18:10:41 +08:00
matevip
c9cc5b4f6f feat(chat): glass-themed preview for uploaded & AI-generated docx/xlsx/pdf (#513) 2026-07-13 18:00:54 +08:00
mateaix
a466f609cf release: v1.8.0 2026-07-12 17:29:29 +08:00
mateaix
60ea00dede feat(tool/browser): 无障碍树 ref 快照与按 ref 交互 + 真实浏览器隐私护栏 + 受控 CDP 逃生舱 2026-07-12 14:56:02 +08:00
mateaix
9d6509840c feat(content-studio): 内容日历去重 + 毛玻璃改版 + 外框线加实 2026-07-12 13:08:58 +08:00
mateaix
ac4b277492 feat(content-studio): 交付即扫即记 + 内容日历只读页(自动化与打磨) 2026-07-12 11:51:12 +08:00
mateaix
f184b94bcd feat(content-studio): 生产硬化 —— 正文图上微信/密钥加密/token复用/内容日历去重/合规硬闸/封面兜底 2026-07-11 22:32:14 +08:00
mateaix
81f4b8f827 feat(content-studio): 小红书以图为主打包 xhs_package(强制≥3图 + 在线预览) 2026-07-11 20:03:34 +08:00
mateaix
85bee7a041 feat(content-studio): 公众号凭据设置+截图工具+平台规范; fix: 封面按文件名自愈 2026-07-11 18:48:11 +08:00
mateaix
f6fb7f2556 fix(skills): 补齐技能自带 scripts(去AI化检测脚本等)到开源 2026-07-11 12:15:23 +08:00
mateaix
973c4c508c feat(content-studio): 公众号/小红书图文创作场景 + gzh_package 打包与在线预览 2026-07-11 12:01:41 +08:00
matevip
e6c35ecfc7 fix(channel): sanitize conversationId as a filesystem path segment — fixes wecom/dingtalk/feishu attachment upload on Windows (#507) 2026-07-10 16:54:05 +08:00
MIST
11fa2b0a03
feat(skill): configurable pip index for skill Python scripts (mirror & private LAN sources)
Let skill Python scripts install packages from a configurable pip index instead of the default PyPI. docker-compose passes PIP_INDEX_URL / PIP_TRUSTED_HOST into the container; for the desktop app (host JVM, no Docker env) SkillScriptExecutionService falls back to mateclaw.pip.index-url / trusted-host Spring config and injects them into the subprocess, auto-deriving the trusted host for plain-HTTP LAN mirrors. The runtime image gains pip and a build toolchain (with the PEP 668 marker removed so on-the-fly installs work), and the script timeout ceiling is raised to accommodate large installs.
2026-07-10 14:48:56 +08:00
matevip
71ad735e95 feat(wiki): cross-KB wikilinks [[kbId/slug]] and raw-material batch filter/reprocess/delete (#506) 2026-07-10 12:01:48 +08:00
matevip
84bbf1cb3e chore(mcp): drop stray progress design doc from repo root; tidy snapshot map
Remove the planning document that landed at the repo root — design notes
belong in the design-doc tree, not the shipped repo root. Also recycle the
per-conversation snapshot map once its last tool-call entry is removed, and
translate a leftover non-English comment.
2026-07-09 18:07:59 +08:00
MIST
e35c07f742
feat(mcp): progress notifications for long-running MCP tools
Wire MCP standard notifications/progress into the existing SSE stream so long-running MCP tool calls surface live progress instead of a bare spinner. A per-call progressToken maps back to (conversationId, toolCallId); ProgressAwareMcpToolCallback injects it into tools/call _meta and calls McpSyncClient directly (falling back to the delegate on error, and applying identity forwarding first). Progress events skip the ring buffer and are replayed from a latest-value snapshot on SSE reconnect. Frontend renders a gradient progress bar in ToolCallSegment when a running tool reports progress.
2026-07-09 18:05:14 +08:00
matevip
4ae4731d54 fix(tool-guard): harden filesystem-root skip and chat-upload fallback in boundary checks
- Shell scan: a token normalizing to the filesystem root (//, /., /..) is
  only skipped when the command carries no destructive verb; with
  rm/rmdir/shred/srm present the scan fails closed, so 'rm -rf //' is
  refused while sed empty replacements (s/pattern//) stay allowed.
- Chat-upload fallback: a boundary violation is waived only when the
  requested path itself normalizes inside one of the conversation's
  candidate upload directories; a basename match against a stored
  attachment no longer clears the violation. Resolver/DB failures keep
  the BLOCK finding. The unused candidate-roots resolve overload is
  removed.
- Regression tests for destructive root tokens, sed allowance, the
  fail-closed compound case, stored-upload-path allowance, basename
  collisions, cross-conversation paths, and resolver failure.
2026-07-09 15:04:34 +08:00
MIST
bc9768b717
fix(tool-guard): false workspace-boundary blocks on sed empty replacement and chat-upload attachments
Skip absolute-path tokens that normalize to the filesystem root in the shell boundary scan (shell syntax like sed's s/pattern// was misread as a path outside the workspace), and add a DB-backed chat-upload fallback in WorkspaceBoundaryGuardian: when a file-tool path triggers a boundary violation, resolve the conversation's real candidate upload roots so attachments stored in workspace-scoped directories are found even when the thread-local workspaceBasePath is null.
2026-07-09 10:48:17 +08:00
matevip
cc444f4c06 feat(agent): tool-call loop guard, post-mutation verify reminder, warning chips 2026-07-08 18:18:34 +08:00
matevip
5b948f7852 perf(ui): on-demand Element Plus, tree-shake unused components 2026-07-08 15:54:18 +08:00
matevip
1318a32b71 perf(ui): cut initial-load bundle via lazy model-viewer and preload fix 2026-07-08 15:53:57 +08:00
matevip
5db8fb14a4 fix(chat): stop history view snapping to bottom during streaming (#498) 2026-07-08 15:53:10 +08:00
matevip
87a5f8a844 chore(deps): upgrade Spring Boot to 3.5.16 2026-07-08 11:26:56 +08:00
matevip
b1648cad88 feat(llm): add Volcano Engine Agent Plan provider (/api/plan/v3) with GLM-5.2 primary 2026-07-08 11:21:23 +08:00
matevip
41a518de93 fix(llm): avoid stale-connection resets on OpenAI-compatible endpoints 2026-07-08 10:54:33 +08:00