fix(db): unify schema and seed data across H2/MySQL, en/zh

This commit is contained in:
matevip 2026-04-08 16:30:33 +08:00
parent f6102c4733
commit c568b4faa8
10 changed files with 262 additions and 246 deletions

View File

@ -9,7 +9,14 @@ import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
/**
* 审批表 Schema 迁移
* 审批表增量 Schema 迁移
* <p>
* 基础表 mate_tool_approval 已在 schema.sql / schema-mysql.sql 中定义
* 本类仅负责增量字段/索引迁移确保从旧版本升级时自动补齐
* <p>
* 当前无需增量迁移保留框架以备未来扩展
*
* @author MateClaw Team
*/
@Slf4j
@Component
@ -21,55 +28,7 @@ public class ApprovalSchemaMigration implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) {
createToolApprovalTable();
}
private void createToolApprovalTable() {
try {
jdbcTemplate.execute("""
CREATE TABLE IF NOT EXISTS mate_tool_approval (
id BIGINT NOT NULL PRIMARY KEY,
pending_id VARCHAR(32) NOT NULL UNIQUE,
conversation_id VARCHAR(128) NOT NULL,
user_id VARCHAR(64),
agent_id VARCHAR(64),
channel_type VARCHAR(32),
requester_name VARCHAR(128),
reply_target VARCHAR(512),
tool_name VARCHAR(128) NOT NULL,
tool_arguments TEXT,
tool_call_payload TEXT,
tool_call_hash VARCHAR(64),
sibling_tool_calls TEXT,
summary TEXT,
findings_json TEXT,
max_severity VARCHAR(16),
status VARCHAR(32) NOT NULL DEFAULT 'PENDING',
resolved_by VARCHAR(64),
created_at DATETIME NOT NULL,
resolved_at DATETIME,
expire_at DATETIME,
create_time DATETIME NOT NULL,
update_time DATETIME NOT NULL,
deleted INT NOT NULL DEFAULT 0
)
""");
safeExecute("CREATE INDEX IF NOT EXISTS idx_tool_approval_conv ON mate_tool_approval(conversation_id)");
safeExecute("CREATE INDEX IF NOT EXISTS idx_tool_approval_status ON mate_tool_approval(status)");
safeExecute("CREATE INDEX IF NOT EXISTS idx_tool_approval_pending_id ON mate_tool_approval(pending_id)");
log.info("[ApprovalSchemaMigration] mate_tool_approval table ready");
} catch (Exception e) {
log.warn("[ApprovalSchemaMigration] Failed to create mate_tool_approval: {}", e.getMessage());
}
}
private void safeExecute(String sql) {
try {
jdbcTemplate.execute(sql);
} catch (Exception e) {
log.debug("[ApprovalSchemaMigration] Index may already exist: {}", e.getMessage());
}
// 当前无增量迁移未来新增字段时在此添加 safeAddColumn 调用
log.debug("[ApprovalSchemaMigration] Incremental migration completed (no-op)");
}
}

View File

@ -9,9 +9,10 @@ import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
/**
* Memory 模块 Schema 迁移
* Memory 模块增量 Schema 迁移
* <p>
* 确保 mate_memory_recall 表存在兼容已有部署
* 基础表 mate_memory_recall 已在 schema.sql / schema-mysql.sql 中定义
* 本类仅负责增量索引/字段迁移确保从旧版本升级时自动补齐
*
* @author MateClaw Team
*/
@ -25,31 +26,16 @@ public class MemorySchemaMigration implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) {
// 增量索引补齐v1.1 新增的复合索引旧版本可能没有
safeExecute("CREATE INDEX IF NOT EXISTS idx_memory_recall_candidates ON mate_memory_recall(agent_id, promoted, deleted)");
log.debug("[MemorySchemaMigration] Incremental migration completed");
}
private void safeExecute(String sql) {
try {
jdbcTemplate.execute("""
CREATE TABLE IF NOT EXISTS mate_memory_recall (
id BIGINT NOT NULL PRIMARY KEY,
agent_id BIGINT NOT NULL,
filename VARCHAR(256) NOT NULL,
snippet_hash VARCHAR(64),
snippet_preview VARCHAR(512),
recall_count INT NOT NULL DEFAULT 0,
daily_count INT NOT NULL DEFAULT 0,
query_hashes TEXT,
score DOUBLE NOT NULL DEFAULT 0.0,
last_recalled_at DATETIME,
promoted BOOLEAN NOT NULL DEFAULT FALSE,
create_time DATETIME NOT NULL,
update_time DATETIME NOT NULL,
deleted INT NOT NULL DEFAULT 0
)
""");
jdbcTemplate.execute("CREATE INDEX IF NOT EXISTS idx_memory_recall_agent ON mate_memory_recall(agent_id)");
jdbcTemplate.execute("CREATE INDEX IF NOT EXISTS idx_memory_recall_agent_file ON mate_memory_recall(agent_id, filename)");
jdbcTemplate.execute("CREATE INDEX IF NOT EXISTS idx_memory_recall_score ON mate_memory_recall(agent_id, score)");
log.info("[MemorySchemaMigration] mate_memory_recall schema migration completed");
jdbcTemplate.execute(sql);
} catch (Exception e) {
log.warn("[MemorySchemaMigration] Migration failed (table may already exist): {}", e.getMessage());
log.debug("[MemorySchemaMigration] Migration skipped (may already exist): {}", e.getMessage());
}
}
}

View File

@ -9,11 +9,16 @@ import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
/**
* ToolGuard Schema 迁移
* ToolGuard 增量 Schema 迁移
* <p>
* 基础表 mate_tool_guard_rule / config / audit_log 已在 schema.sql / schema-mysql.sql 中定义
* 本类仅负责增量字段迁移确保从旧版本升级时自动补齐新列
*
* @author MateClaw Team
*/
@Slf4j
@Component
@Order(100) // ApprovalSchemaMigration 之后
@Order(100)
@RequiredArgsConstructor
public class ToolGuardSchemaMigration implements ApplicationRunner {
@ -21,94 +26,9 @@ public class ToolGuardSchemaMigration implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) {
createGuardRuleTable();
createGuardConfigTable();
createAuditLogTable();
migrateGuardConfigAuditColumns();
}
private void createGuardRuleTable() {
try {
jdbcTemplate.execute("""
CREATE TABLE IF NOT EXISTS mate_tool_guard_rule (
id BIGINT NOT NULL PRIMARY KEY,
rule_id VARCHAR(64) NOT NULL UNIQUE,
name VARCHAR(128) NOT NULL,
description TEXT,
tool_name VARCHAR(128),
param_name VARCHAR(128),
category VARCHAR(64) NOT NULL,
severity VARCHAR(16) NOT NULL,
decision VARCHAR(16) NOT NULL DEFAULT 'NEEDS_APPROVAL',
pattern VARCHAR(512) NOT NULL,
exclude_pattern VARCHAR(512),
remediation TEXT,
builtin BOOLEAN NOT NULL DEFAULT FALSE,
enabled BOOLEAN NOT NULL DEFAULT TRUE,
priority INT NOT NULL DEFAULT 100,
create_time DATETIME NOT NULL,
update_time DATETIME NOT NULL,
deleted INT NOT NULL DEFAULT 0
)
""");
log.info("[ToolGuardSchemaMigration] mate_tool_guard_rule table ready");
} catch (Exception e) {
log.warn("[ToolGuardSchemaMigration] Failed to create mate_tool_guard_rule: {}", e.getMessage());
}
}
private void createGuardConfigTable() {
try {
jdbcTemplate.execute("""
CREATE TABLE IF NOT EXISTS mate_tool_guard_config (
id BIGINT NOT NULL PRIMARY KEY,
enabled BOOLEAN NOT NULL DEFAULT TRUE,
guard_scope VARCHAR(32) NOT NULL DEFAULT 'all',
guarded_tools_json TEXT,
denied_tools_json TEXT,
file_guard_enabled BOOLEAN NOT NULL DEFAULT TRUE,
sensitive_paths_json TEXT,
create_time DATETIME NOT NULL,
update_time DATETIME NOT NULL
)
""");
log.info("[ToolGuardSchemaMigration] mate_tool_guard_config table ready");
} catch (Exception e) {
log.warn("[ToolGuardSchemaMigration] Failed to create mate_tool_guard_config: {}", e.getMessage());
}
}
private void createAuditLogTable() {
try {
jdbcTemplate.execute("""
CREATE TABLE IF NOT EXISTS mate_tool_guard_audit_log (
id BIGINT NOT NULL PRIMARY KEY,
conversation_id VARCHAR(128),
agent_id VARCHAR(64),
user_id VARCHAR(64),
channel_type VARCHAR(32),
tool_name VARCHAR(128) NOT NULL,
tool_params_json TEXT,
decision VARCHAR(16) NOT NULL,
max_severity VARCHAR(16),
findings_json TEXT,
pending_id VARCHAR(32),
replay_payload_hash VARCHAR(64),
create_time DATETIME NOT NULL,
update_time DATETIME NOT NULL,
deleted INT NOT NULL DEFAULT 0
)
""");
safeExecute("CREATE INDEX IF NOT EXISTS idx_guard_audit_conv ON mate_tool_guard_audit_log(conversation_id)");
safeExecute("CREATE INDEX IF NOT EXISTS idx_guard_audit_time ON mate_tool_guard_audit_log(create_time)");
log.info("[ToolGuardSchemaMigration] mate_tool_guard_audit_log table ready");
} catch (Exception e) {
log.warn("[ToolGuardSchemaMigration] Failed to create audit log table: {}", e.getMessage());
}
}
/**
* mate_tool_guard_config 补充审计配置列向已有表兼容迁移
*/
@ -116,7 +36,7 @@ public class ToolGuardSchemaMigration implements ApplicationRunner {
safeAddColumn("mate_tool_guard_config", "audit_enabled", "BOOLEAN NOT NULL DEFAULT TRUE");
safeAddColumn("mate_tool_guard_config", "audit_min_severity", "VARCHAR(16) NOT NULL DEFAULT 'INFO'");
safeAddColumn("mate_tool_guard_config", "audit_retention_days", "INT NOT NULL DEFAULT 90");
log.info("[ToolGuardSchemaMigration] audit columns migration done");
log.debug("[ToolGuardSchemaMigration] Incremental migration completed");
}
private void safeAddColumn(String table, String column, String definition) {
@ -132,12 +52,4 @@ public class ToolGuardSchemaMigration implements ApplicationRunner {
log.debug("[ToolGuardSchemaMigration] Column migration skipped: {}", e.getMessage());
}
}
private void safeExecute(String sql) {
try {
jdbcTemplate.execute(sql);
} catch (Exception e) {
log.debug("[ToolGuardSchemaMigration] SQL may already exist: {}", e.getMessage());
}
}
}

View File

@ -9,9 +9,12 @@ import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
/**
* Wiki 模块 Schema 迁移
* Wiki 模块增量 Schema 迁移
* <p>
* 确保 Wiki 相关表存在兼容已有部署
* Wiki 基础表已在 schema.sql / schema-mysql.sql 中定义 DatabaseBootstrapRunner 初始化
* 本类仅负责增量字段迁移确保从旧版本升级时自动补齐新字段
* <p>
* 如果表已由 schema.sql 创建全新安装这里的迁移是无副作用的空操作
*
* @author MateClaw Team
*/
@ -25,88 +28,24 @@ public class WikiSchemaMigration implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) {
createKnowledgeBaseTable();
createRawMaterialTable();
createPageTable();
migrateKnowledgeBaseColumns();
log.info("[WikiSchemaMigration] Wiki schema migration completed");
}
private void createKnowledgeBaseTable() {
jdbcTemplate.execute("""
CREATE TABLE IF NOT EXISTS mate_wiki_knowledge_base (
id BIGINT NOT NULL PRIMARY KEY,
name VARCHAR(128) NOT NULL,
description TEXT,
agent_id BIGINT,
config_content CLOB,
status VARCHAR(32) NOT NULL DEFAULT 'active',
page_count INT NOT NULL DEFAULT 0,
raw_count INT NOT NULL DEFAULT 0,
create_time DATETIME NOT NULL,
update_time DATETIME NOT NULL,
deleted INT NOT NULL DEFAULT 0
)
""");
jdbcTemplate.execute("CREATE INDEX IF NOT EXISTS idx_wiki_kb_agent ON mate_wiki_knowledge_base(agent_id)");
}
private void createRawMaterialTable() {
jdbcTemplate.execute("""
CREATE TABLE IF NOT EXISTS mate_wiki_raw_material (
id BIGINT NOT NULL PRIMARY KEY,
kb_id BIGINT NOT NULL,
title VARCHAR(256) NOT NULL,
source_type VARCHAR(32) NOT NULL DEFAULT 'text',
source_path VARCHAR(512),
original_content CLOB,
extracted_text CLOB,
content_hash VARCHAR(64),
file_size BIGINT NOT NULL DEFAULT 0,
processing_status VARCHAR(32) NOT NULL DEFAULT 'pending',
last_processed_at DATETIME,
error_message VARCHAR(512),
create_time DATETIME NOT NULL,
update_time DATETIME NOT NULL,
deleted INT NOT NULL DEFAULT 0
)
""");
jdbcTemplate.execute("CREATE INDEX IF NOT EXISTS idx_wiki_raw_kb ON mate_wiki_raw_material(kb_id)");
jdbcTemplate.execute("CREATE INDEX IF NOT EXISTS idx_wiki_raw_status ON mate_wiki_raw_material(kb_id, processing_status)");
}
private void createPageTable() {
jdbcTemplate.execute("""
CREATE TABLE IF NOT EXISTS mate_wiki_page (
id BIGINT NOT NULL PRIMARY KEY,
kb_id BIGINT NOT NULL,
slug VARCHAR(256) NOT NULL,
title VARCHAR(256) NOT NULL,
content CLOB,
summary VARCHAR(1024),
outgoing_links CLOB,
source_raw_ids CLOB,
version INT NOT NULL DEFAULT 1,
last_updated_by VARCHAR(32) NOT NULL DEFAULT 'ai',
create_time DATETIME NOT NULL,
update_time DATETIME NOT NULL,
deleted INT NOT NULL DEFAULT 0,
CONSTRAINT uk_wiki_page_kb_slug UNIQUE (kb_id, slug)
)
""");
jdbcTemplate.execute("CREATE INDEX IF NOT EXISTS idx_wiki_page_kb ON mate_wiki_page(kb_id)");
}
/**
* 增量字段迁移兼容已有部署
* 增量字段迁移兼容从 wiki 功能上线前的旧版本升级
*/
private void migrateKnowledgeBaseColumns() {
try {
// v1.1: 添加 source_directory 本地目录扫描功能
jdbcTemplate.execute("ALTER TABLE mate_wiki_knowledge_base ADD COLUMN IF NOT EXISTS source_directory VARCHAR(512)");
log.debug("[WikiSchemaMigration] Incremental migration completed");
} catch (Exception e) {
// MySQL 不支持 ADD COLUMN IF NOT EXISTS忽略已存在的错误
if (!e.getMessage().contains("Duplicate column")) {
log.warn("[WikiSchemaMigration] Failed to add source_directory column: {}", e.getMessage());
String msg = e.getMessage();
if (msg != null && (msg.contains("Duplicate column") || msg.contains("already exists"))) {
log.debug("[WikiSchemaMigration] Column source_directory already exists, skipping");
} else {
log.warn("[WikiSchemaMigration] Migration warning: {}", msg);
}
}
}

View File

@ -381,6 +381,10 @@ MERGE INTO mate_tool (id, name, display_name, description, tool_type, bean_name,
KEY (id)
VALUES (1000000016, 'ImageGenerateTool', 'Image Generation', 'Generate images using AI. Supports text-to-image mode with multiple providers: DashScope, OpenAI DALL-E, fal.ai Flux, Zhipu CogView. Auto-fallback between providers.', 'builtin', 'imageGenerateTool', '🎨', TRUE, TRUE, NOW(), NOW(), 0);
MERGE INTO mate_tool (id, name, display_name, description, tool_type, bean_name, icon, enabled, builtin, create_time, update_time, deleted)
KEY (id)
VALUES (1000000017, 'WikiTool', 'Wiki Knowledge Base', 'Read, search, and trace sources in Wiki knowledge bases. Supports wiki_read_page, wiki_list_pages, wiki_search_pages, wiki_trace_source.', 'builtin', 'wikiTool', '📚', TRUE, TRUE, NOW(), NOW(), 0);
-- Example MCP Server: Filesystem (see MateClaw docs mcpServers.filesystem)
MERGE INTO mate_mcp_server (
id, name, description, transport, url, headers_json, command, args_json, env_json, cwd,

View File

@ -374,6 +374,18 @@ INSERT INTO mate_tool (id, name, display_name, description, tool_type, bean_name
VALUES (1000000014, 'DelegateAgentTool', 'Agent Delegation', 'Delegate tasks to other Agents for multi-agent collaboration. Call target Agent by name, run in isolated session and return result.', 'builtin', 'delegateAgentTool', '🤝', TRUE, TRUE, NOW(), NOW(), 0)
ON DUPLICATE KEY UPDATE name=VALUES(name), display_name=VALUES(display_name), description=VALUES(description), tool_type=VALUES(tool_type), bean_name=VALUES(bean_name), icon=VALUES(icon), enabled=VALUES(enabled), builtin=VALUES(builtin), update_time=VALUES(update_time), deleted=VALUES(deleted);
INSERT INTO mate_tool (id, name, display_name, description, tool_type, bean_name, icon, enabled, builtin, create_time, update_time, deleted)
VALUES (1000000015, 'VideoGenerateTool', 'Video Generation', 'Generate videos using AI. Supports text-to-video and image-to-video modes. Video generation is asynchronous and will appear in conversation when complete.', 'builtin', 'videoGenerateTool', '🎬', TRUE, TRUE, NOW(), NOW(), 0)
ON DUPLICATE KEY UPDATE name=VALUES(name), display_name=VALUES(display_name), description=VALUES(description), tool_type=VALUES(tool_type), bean_name=VALUES(bean_name), icon=VALUES(icon), enabled=VALUES(enabled), builtin=VALUES(builtin), update_time=VALUES(update_time), deleted=VALUES(deleted);
INSERT INTO mate_tool (id, name, display_name, description, tool_type, bean_name, icon, enabled, builtin, create_time, update_time, deleted)
VALUES (1000000016, 'ImageGenerateTool', 'Image Generation', 'Generate images using AI. Supports text-to-image mode with multiple providers: DashScope, OpenAI DALL-E, fal.ai Flux, Zhipu CogView. Auto-fallback between providers.', 'builtin', 'imageGenerateTool', '🎨', TRUE, TRUE, NOW(), NOW(), 0)
ON DUPLICATE KEY UPDATE name=VALUES(name), display_name=VALUES(display_name), description=VALUES(description), tool_type=VALUES(tool_type), bean_name=VALUES(bean_name), icon=VALUES(icon), enabled=VALUES(enabled), builtin=VALUES(builtin), update_time=VALUES(update_time), deleted=VALUES(deleted);
INSERT INTO mate_tool (id, name, display_name, description, tool_type, bean_name, icon, enabled, builtin, create_time, update_time, deleted)
VALUES (1000000017, 'WikiTool', 'Wiki Knowledge Base', 'Read, search, and trace sources in Wiki knowledge bases. Supports wiki_read_page, wiki_list_pages, wiki_search_pages, wiki_trace_source.', 'builtin', 'wikiTool', '📚', TRUE, TRUE, NOW(), NOW(), 0)
ON DUPLICATE KEY UPDATE name=VALUES(name), display_name=VALUES(display_name), description=VALUES(description), tool_type=VALUES(tool_type), bean_name=VALUES(bean_name), icon=VALUES(icon), enabled=VALUES(enabled), builtin=VALUES(builtin), update_time=VALUES(update_time), deleted=VALUES(deleted);
-- Example MCP Server: Filesystem (see MateClaw docs mcpServers.filesystem)
INSERT INTO mate_mcp_server (id, name, description, transport, url, headers_json, command, args_json, env_json, cwd,
enabled, connect_timeout_seconds, read_timeout_seconds, last_status, last_error,
@ -487,6 +499,10 @@ INSERT INTO mate_skill (id, name, description, skill_type, icon, version, author
VALUES (1000000013, 'mateclaw_source_index', 'Map user questions to MateClaw doc paths and source code entry points to reduce blind searching.', 'builtin', '🗂️', '1.0.0', 'MateClaw', '{"upstream":"mateclaw","entryFile":"SKILL.md"}', TRUE, TRUE, 'docs,index,source,qa', NOW(), NOW(), 0)
ON DUPLICATE KEY UPDATE name=VALUES(name), description=VALUES(description), skill_type=VALUES(skill_type), icon=VALUES(icon), version=VALUES(version), author=VALUES(author), config_json=VALUES(config_json), enabled=VALUES(enabled), builtin=VALUES(builtin), tags=VALUES(tags), update_time=VALUES(update_time), deleted=VALUES(deleted);
INSERT INTO mate_skill (id, name, description, skill_type, icon, version, author, config_json, enabled, builtin, tags, create_time, update_time, deleted)
VALUES (1000000014, 'sql_query', 'Query databases using natural language. Discover schemas, generate SQL, and execute read-only queries against configured external datasources.', 'builtin', '📊', '1.0.0', 'MateClaw', '{"upstream":"mateclaw","entryFile":"SKILL.md"}', TRUE, TRUE, 'sql,database,query,data', NOW(), NOW(), 0)
ON DUPLICATE KEY UPDATE name=VALUES(name), description=VALUES(description), skill_type=VALUES(skill_type), icon=VALUES(icon), version=VALUES(version), author=VALUES(author), config_json=VALUES(config_json), enabled=VALUES(enabled), builtin=VALUES(builtin), tags=VALUES(tags), update_time=VALUES(update_time), deleted=VALUES(deleted);
INSERT INTO mate_skill (id, name, description, skill_type, icon, version, author, config_json, enabled, builtin, tags, create_time, update_time, deleted)
VALUES (1000000015, 'steve_jobs_perspective', 'Steve Jobs thinking OS. Analyze products, evaluate decisions, and give feedback through Jobs'' perspective, using his six mental models and distinctive expression style.', 'builtin', '🍎', '1.0.0', 'MateClaw', '{"upstream":"mateclaw","entryFile":"SKILL.md"}', TRUE, TRUE, 'persona,jobs,product,strategy,thinking', NOW(), NOW(), 0)
ON DUPLICATE KEY UPDATE name=VALUES(name), description=VALUES(description), skill_type=VALUES(skill_type), icon=VALUES(icon), version=VALUES(version), author=VALUES(author), config_json=VALUES(config_json), enabled=VALUES(enabled), builtin=VALUES(builtin), tags=VALUES(tags), update_time=VALUES(update_time), deleted=VALUES(deleted);

View File

@ -374,6 +374,18 @@ INSERT INTO mate_tool (id, name, display_name, description, tool_type, bean_name
VALUES (1000000014, 'DelegateAgentTool', 'Agent 委派', '委派任务给其他 Agent 执行,实现多 Agent 协作。支持按名称调用目标 Agent在独立会话中运行并返回结果。', 'builtin', 'delegateAgentTool', '🤝', TRUE, TRUE, NOW(), NOW(), 0)
ON DUPLICATE KEY UPDATE name=VALUES(name), display_name=VALUES(display_name), description=VALUES(description), tool_type=VALUES(tool_type), bean_name=VALUES(bean_name), icon=VALUES(icon), enabled=VALUES(enabled), builtin=VALUES(builtin), update_time=VALUES(update_time), deleted=VALUES(deleted);
INSERT INTO mate_tool (id, name, display_name, description, tool_type, bean_name, icon, enabled, builtin, create_time, update_time, deleted)
VALUES (1000000015, 'VideoGenerateTool', '视频生成', '使用 AI 生成视频,支持文字生成视频和图片生成视频两种模式。视频生成是异步过程,完成后自动显示在对话中。', 'builtin', 'videoGenerateTool', '🎬', TRUE, TRUE, NOW(), NOW(), 0)
ON DUPLICATE KEY UPDATE name=VALUES(name), display_name=VALUES(display_name), description=VALUES(description), tool_type=VALUES(tool_type), bean_name=VALUES(bean_name), icon=VALUES(icon), enabled=VALUES(enabled), builtin=VALUES(builtin), update_time=VALUES(update_time), deleted=VALUES(deleted);
INSERT INTO mate_tool (id, name, display_name, description, tool_type, bean_name, icon, enabled, builtin, create_time, update_time, deleted)
VALUES (1000000016, 'ImageGenerateTool', '图片生成', '使用 AI 生成图片,支持文字生成图片。支持 DashScope 通义万相、OpenAI DALL-E、fal.ai Flux、智谱 CogView 等多个 Provider自动回退。', 'builtin', 'imageGenerateTool', '🎨', TRUE, TRUE, NOW(), NOW(), 0)
ON DUPLICATE KEY UPDATE name=VALUES(name), display_name=VALUES(display_name), description=VALUES(description), tool_type=VALUES(tool_type), bean_name=VALUES(bean_name), icon=VALUES(icon), enabled=VALUES(enabled), builtin=VALUES(builtin), update_time=VALUES(update_time), deleted=VALUES(deleted);
INSERT INTO mate_tool (id, name, display_name, description, tool_type, bean_name, icon, enabled, builtin, create_time, update_time, deleted)
VALUES (1000000017, 'WikiTool', 'Wiki 知识库', '读取、搜索 Wiki 知识库中的结构化页面,并追溯原始来源文件。支持 wiki_read_page、wiki_list_pages、wiki_search_pages、wiki_trace_source 四个工具。', 'builtin', 'wikiTool', '📚', TRUE, TRUE, NOW(), NOW(), 0)
ON DUPLICATE KEY UPDATE name=VALUES(name), display_name=VALUES(display_name), description=VALUES(description), tool_type=VALUES(tool_type), bean_name=VALUES(bean_name), icon=VALUES(icon), enabled=VALUES(enabled), builtin=VALUES(builtin), update_time=VALUES(update_time), deleted=VALUES(deleted);
-- 示例 MCP ServerFilesystem参考 MateClaw 文档中的 mcpServers.filesystem
INSERT INTO mate_mcp_server (
id, name, description, transport, url, headers_json, command, args_json, env_json, cwd,
@ -489,6 +501,10 @@ INSERT INTO mate_skill (id, name, description, skill_type, icon, version, author
VALUES (1000000013, 'mateclaw_source_index', '将用户问题映射到 MateClaw 文档路径与源码入口,减少盲目搜索。', 'builtin', '🗂️', '1.0.0', 'MateClaw', '{"upstream":"mateclaw","entryFile":"SKILL.md"}', TRUE, TRUE, 'docs,index,source,qa', NOW(), NOW(), 0)
ON DUPLICATE KEY UPDATE name=VALUES(name), description=VALUES(description), skill_type=VALUES(skill_type), icon=VALUES(icon), version=VALUES(version), author=VALUES(author), config_json=VALUES(config_json), enabled=VALUES(enabled), builtin=VALUES(builtin), tags=VALUES(tags), update_time=VALUES(update_time), deleted=VALUES(deleted);
INSERT INTO mate_skill (id, name, description, skill_type, icon, version, author, config_json, enabled, builtin, tags, create_time, update_time, deleted)
VALUES (1000000014, 'sql_query', '使用自然语言查询数据库。发现表结构、生成 SQL、在已配置的外部数据源上执行只读查询。', 'builtin', '📊', '1.0.0', 'MateClaw', '{"upstream":"mateclaw","entryFile":"SKILL.md"}', TRUE, TRUE, 'sql,database,query,data', NOW(), NOW(), 0)
ON DUPLICATE KEY UPDATE name=VALUES(name), description=VALUES(description), skill_type=VALUES(skill_type), icon=VALUES(icon), version=VALUES(version), author=VALUES(author), config_json=VALUES(config_json), enabled=VALUES(enabled), builtin=VALUES(builtin), tags=VALUES(tags), update_time=VALUES(update_time), deleted=VALUES(deleted);
INSERT INTO mate_skill (id, name, description, skill_type, icon, version, author, config_json, enabled, builtin, tags, create_time, update_time, deleted)
VALUES (1000000015, 'steve_jobs_perspective', '史蒂夫·乔布斯思维操作系统。以乔布斯视角审视产品、评估决策、提供反馈,运用其六大心智模型和独特表达风格。', 'builtin', '🍎', '1.0.0', 'MateClaw', '{"upstream":"mateclaw","entryFile":"SKILL.md"}', TRUE, TRUE, 'persona,jobs,product,strategy,thinking', NOW(), NOW(), 0)
ON DUPLICATE KEY UPDATE name=VALUES(name), description=VALUES(description), skill_type=VALUES(skill_type), icon=VALUES(icon), version=VALUES(version), author=VALUES(author), config_json=VALUES(config_json), enabled=VALUES(enabled), builtin=VALUES(builtin), tags=VALUES(tags), update_time=VALUES(update_time), deleted=VALUES(deleted);

View File

@ -387,6 +387,10 @@ MERGE INTO mate_tool (id, name, display_name, description, tool_type, bean_name,
KEY (id)
VALUES (1000000016, 'ImageGenerateTool', '图片生成', '使用 AI 生成图片,支持文字生成图片。支持 DashScope 通义万相、OpenAI DALL-E、fal.ai Flux、智谱 CogView 等多个 Provider自动回退。', 'builtin', 'imageGenerateTool', '🎨', TRUE, TRUE, NOW(), NOW(), 0);
MERGE INTO mate_tool (id, name, display_name, description, tool_type, bean_name, icon, enabled, builtin, create_time, update_time, deleted)
KEY (id)
VALUES (1000000017, 'WikiTool', 'Wiki 知识库', '读取、搜索 Wiki 知识库中的结构化页面,并追溯原始来源文件。支持 wiki_read_page、wiki_list_pages、wiki_search_pages、wiki_trace_source 四个工具。', 'builtin', 'wikiTool', '📚', TRUE, TRUE, NOW(), NOW(), 0);
-- 示例 MCP ServerFilesystem参考 MateClaw 文档中的 mcpServers.filesystem
MERGE INTO mate_mcp_server (
id, name, description, transport, url, headers_json, command, args_json, env_json, cwd,

View File

@ -374,3 +374,127 @@ CREATE TABLE IF NOT EXISTS mate_tool_guard_audit_log (
INDEX idx_guard_audit_conv (conversation_id),
INDEX idx_guard_audit_time (create_time)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ==================== 外部数据源 ====================
CREATE TABLE IF NOT EXISTS mate_datasource (
id BIGINT NOT NULL PRIMARY KEY,
name VARCHAR(128) NOT NULL,
description VARCHAR(512),
db_type VARCHAR(32) NOT NULL,
host VARCHAR(256) NOT NULL,
port INT NOT NULL,
database_name VARCHAR(128) NOT NULL,
username VARCHAR(128),
password VARCHAR(512),
extra_params VARCHAR(512),
schema_name VARCHAR(128),
enabled TINYINT(1) NOT NULL DEFAULT 1,
last_test_time DATETIME,
last_test_ok TINYINT(1),
create_time DATETIME NOT NULL,
update_time DATETIME NOT NULL,
deleted INT NOT NULL DEFAULT 0
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ==================== 异步任务(视频/图片生成等长耗时操作) ====================
CREATE TABLE IF NOT EXISTS mate_async_task (
id BIGINT NOT NULL PRIMARY KEY,
task_id VARCHAR(64) NOT NULL,
task_type VARCHAR(32) NOT NULL,
status VARCHAR(16) NOT NULL DEFAULT 'pending',
conversation_id VARCHAR(128),
message_id BIGINT,
provider_name VARCHAR(64),
provider_task_id VARCHAR(128),
request_json TEXT,
result_json TEXT,
error_message VARCHAR(512),
progress INT DEFAULT 0,
created_by VARCHAR(64),
create_time DATETIME NOT NULL,
update_time DATETIME NOT NULL,
UNIQUE KEY uk_async_task_taskid (task_id),
INDEX idx_async_task_conv (conversation_id),
INDEX idx_async_task_status (status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ==================== 记忆召回追踪 ====================
CREATE TABLE IF NOT EXISTS mate_memory_recall (
id BIGINT NOT NULL PRIMARY KEY,
agent_id BIGINT NOT NULL,
filename VARCHAR(256) NOT NULL,
snippet_hash VARCHAR(64),
snippet_preview VARCHAR(512),
recall_count INT NOT NULL DEFAULT 0,
daily_count INT NOT NULL DEFAULT 0,
query_hashes TEXT,
score DOUBLE NOT NULL DEFAULT 0.0,
last_recalled_at DATETIME,
promoted TINYINT(1) NOT NULL DEFAULT 0,
create_time DATETIME NOT NULL,
update_time DATETIME NOT NULL,
deleted INT NOT NULL DEFAULT 0,
INDEX idx_memory_recall_agent (agent_id),
INDEX idx_memory_recall_agent_file (agent_id, filename),
INDEX idx_memory_recall_score (agent_id, score),
INDEX idx_memory_recall_candidates (agent_id, promoted, deleted)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ==================== Wiki 知识库 ====================
CREATE TABLE IF NOT EXISTS mate_wiki_knowledge_base (
id BIGINT NOT NULL PRIMARY KEY,
name VARCHAR(128) NOT NULL,
description TEXT,
agent_id BIGINT,
config_content LONGTEXT,
source_directory VARCHAR(512),
status VARCHAR(32) NOT NULL DEFAULT 'active',
page_count INT NOT NULL DEFAULT 0,
raw_count INT NOT NULL DEFAULT 0,
create_time DATETIME NOT NULL,
update_time DATETIME NOT NULL,
deleted INT NOT NULL DEFAULT 0,
INDEX idx_wiki_kb_agent (agent_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS mate_wiki_raw_material (
id BIGINT NOT NULL PRIMARY KEY,
kb_id BIGINT NOT NULL,
title VARCHAR(256) NOT NULL,
source_type VARCHAR(32) NOT NULL DEFAULT 'text',
source_path VARCHAR(512),
original_content LONGTEXT,
extracted_text LONGTEXT,
content_hash VARCHAR(64),
file_size BIGINT NOT NULL DEFAULT 0,
processing_status VARCHAR(32) NOT NULL DEFAULT 'pending',
last_processed_at DATETIME,
error_message VARCHAR(512),
create_time DATETIME NOT NULL,
update_time DATETIME NOT NULL,
deleted INT NOT NULL DEFAULT 0,
INDEX idx_wiki_raw_kb (kb_id),
INDEX idx_wiki_raw_status (kb_id, processing_status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS mate_wiki_page (
id BIGINT NOT NULL PRIMARY KEY,
kb_id BIGINT NOT NULL,
slug VARCHAR(256) NOT NULL,
title VARCHAR(256) NOT NULL,
content LONGTEXT,
summary VARCHAR(1024),
outgoing_links LONGTEXT,
source_raw_ids LONGTEXT,
version INT NOT NULL DEFAULT 1,
last_updated_by VARCHAR(32) NOT NULL DEFAULT 'ai',
create_time DATETIME NOT NULL,
update_time DATETIME NOT NULL,
deleted INT NOT NULL DEFAULT 0,
UNIQUE KEY uk_wiki_page_kb_slug (kb_id, slug),
INDEX idx_wiki_page_kb (kb_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

View File

@ -470,3 +470,59 @@ CREATE TABLE IF NOT EXISTS mate_async_task (
CREATE INDEX IF NOT EXISTS idx_async_task_taskid ON mate_async_task(task_id);
CREATE INDEX IF NOT EXISTS idx_async_task_conv ON mate_async_task(conversation_id);
CREATE INDEX IF NOT EXISTS idx_async_task_status ON mate_async_task(status);
-- ==================== Wiki 知识库 ====================
CREATE TABLE IF NOT EXISTS mate_wiki_knowledge_base (
id BIGINT NOT NULL PRIMARY KEY,
name VARCHAR(128) NOT NULL,
description TEXT,
agent_id BIGINT,
config_content CLOB,
source_directory VARCHAR(512),
status VARCHAR(32) NOT NULL DEFAULT 'active',
page_count INT NOT NULL DEFAULT 0,
raw_count INT NOT NULL DEFAULT 0,
create_time DATETIME NOT NULL,
update_time DATETIME NOT NULL,
deleted INT NOT NULL DEFAULT 0
);
CREATE INDEX IF NOT EXISTS idx_wiki_kb_agent ON mate_wiki_knowledge_base(agent_id);
CREATE TABLE IF NOT EXISTS mate_wiki_raw_material (
id BIGINT NOT NULL PRIMARY KEY,
kb_id BIGINT NOT NULL,
title VARCHAR(256) NOT NULL,
source_type VARCHAR(32) NOT NULL DEFAULT 'text',
source_path VARCHAR(512),
original_content CLOB,
extracted_text CLOB,
content_hash VARCHAR(64),
file_size BIGINT NOT NULL DEFAULT 0,
processing_status VARCHAR(32) NOT NULL DEFAULT 'pending',
last_processed_at DATETIME,
error_message VARCHAR(512),
create_time DATETIME NOT NULL,
update_time DATETIME NOT NULL,
deleted INT NOT NULL DEFAULT 0
);
CREATE INDEX IF NOT EXISTS idx_wiki_raw_kb ON mate_wiki_raw_material(kb_id);
CREATE INDEX IF NOT EXISTS idx_wiki_raw_status ON mate_wiki_raw_material(kb_id, processing_status);
CREATE TABLE IF NOT EXISTS mate_wiki_page (
id BIGINT NOT NULL PRIMARY KEY,
kb_id BIGINT NOT NULL,
slug VARCHAR(256) NOT NULL,
title VARCHAR(256) NOT NULL,
content CLOB,
summary VARCHAR(1024),
outgoing_links CLOB,
source_raw_ids CLOB,
version INT NOT NULL DEFAULT 1,
last_updated_by VARCHAR(32) NOT NULL DEFAULT 'ai',
create_time DATETIME NOT NULL,
update_time DATETIME NOT NULL,
deleted INT NOT NULL DEFAULT 0,
CONSTRAINT uk_wiki_page_kb_slug UNIQUE (kb_id, slug)
);
CREATE INDEX IF NOT EXISTS idx_wiki_page_kb ON mate_wiki_page(kb_id);