@huo15/openclaw-enhance 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +73 -0
- package/index.ts +69 -0
- package/openclaw.plugin.json +65 -0
- package/package.json +46 -0
- package/scripts/setup.sh +144 -0
- package/skills/explore-mode/SKILL.md +71 -0
- package/skills/memory-curator/SKILL.md +76 -0
- package/skills/plan-mode/SKILL.md +69 -0
- package/skills/verify-mode/SKILL.md +69 -0
- package/src/modules/dashboard.ts +158 -0
- package/src/modules/prompt-enhancer.ts +65 -0
- package/src/modules/structured-memory.ts +167 -0
- package/src/modules/tool-safety.ts +149 -0
- package/src/modules/workflow-hooks.ts +147 -0
- package/src/types.ts +80 -0
- package/src/utils/sqlite-store.ts +159 -0
- package/templates/AGENTS.enhance-patch.md +30 -0
- package/templates/SOUL.enhance-patch.md +27 -0
package/src/types.ts
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 龙虾增强包 — 类型定义
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
// ── 结构化记忆 ──
|
|
6
|
+
export type MemoryCategory = "user" | "project" | "feedback" | "reference" | "decision";
|
|
7
|
+
|
|
8
|
+
export interface MemoryEntry {
|
|
9
|
+
id: number;
|
|
10
|
+
category: MemoryCategory;
|
|
11
|
+
content: string;
|
|
12
|
+
tags: string;
|
|
13
|
+
importance: number;
|
|
14
|
+
session_id: string;
|
|
15
|
+
created_at: string;
|
|
16
|
+
updated_at: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface MemoryConfig {
|
|
20
|
+
enabled?: boolean;
|
|
21
|
+
autoCapture?: boolean;
|
|
22
|
+
maxContextEntries?: number;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// ── 工具安全 ──
|
|
26
|
+
export type SafetyAction = "block" | "log" | "allow";
|
|
27
|
+
|
|
28
|
+
export interface SafetyRule {
|
|
29
|
+
tool: string;
|
|
30
|
+
pattern?: string;
|
|
31
|
+
pathPattern?: string;
|
|
32
|
+
action: SafetyAction;
|
|
33
|
+
reason?: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface SafetyConfig {
|
|
37
|
+
enabled?: boolean;
|
|
38
|
+
rules?: SafetyRule[];
|
|
39
|
+
defaultAction?: SafetyAction;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// ── 提示词增强 ──
|
|
43
|
+
export type PromptSection =
|
|
44
|
+
| "taskClassification"
|
|
45
|
+
| "qualityGuidelines"
|
|
46
|
+
| "memoryContext"
|
|
47
|
+
| "safetyAwareness";
|
|
48
|
+
|
|
49
|
+
export interface PromptConfig {
|
|
50
|
+
enabled?: boolean;
|
|
51
|
+
sections?: PromptSection[];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// ── 工作流 ──
|
|
55
|
+
export interface Workflow {
|
|
56
|
+
id: string;
|
|
57
|
+
name: string;
|
|
58
|
+
trigger: string;
|
|
59
|
+
instructions: string;
|
|
60
|
+
enabled: boolean;
|
|
61
|
+
created_at: string;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export interface WorkflowConfig {
|
|
65
|
+
enabled?: boolean;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// ── 仪表盘 ──
|
|
69
|
+
export interface DashboardConfig {
|
|
70
|
+
enabled?: boolean;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// ── 插件总配置 ──
|
|
74
|
+
export interface EnhancePluginConfig {
|
|
75
|
+
memory?: MemoryConfig;
|
|
76
|
+
safety?: SafetyConfig;
|
|
77
|
+
prompt?: PromptConfig;
|
|
78
|
+
workflows?: WorkflowConfig;
|
|
79
|
+
dashboard?: DashboardConfig;
|
|
80
|
+
}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SQLite 辅助工具 — 结构化记忆存储
|
|
3
|
+
*/
|
|
4
|
+
import Database from "better-sqlite3";
|
|
5
|
+
import { join } from "node:path";
|
|
6
|
+
import { existsSync, mkdirSync } from "node:fs";
|
|
7
|
+
import type { MemoryEntry, MemoryCategory } from "../types.js";
|
|
8
|
+
|
|
9
|
+
const SCHEMA = `
|
|
10
|
+
CREATE TABLE IF NOT EXISTS memories (
|
|
11
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
12
|
+
category TEXT NOT NULL CHECK(category IN ('user','project','feedback','reference','decision')),
|
|
13
|
+
content TEXT NOT NULL,
|
|
14
|
+
tags TEXT DEFAULT '',
|
|
15
|
+
importance INTEGER DEFAULT 5 CHECK(importance BETWEEN 1 AND 10),
|
|
16
|
+
session_id TEXT DEFAULT '',
|
|
17
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
18
|
+
updated_at TEXT DEFAULT (datetime('now'))
|
|
19
|
+
);
|
|
20
|
+
CREATE INDEX IF NOT EXISTS idx_memories_category ON memories(category);
|
|
21
|
+
CREATE INDEX IF NOT EXISTS idx_memories_created ON memories(created_at DESC);
|
|
22
|
+
|
|
23
|
+
CREATE TABLE IF NOT EXISTS safety_log (
|
|
24
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
25
|
+
tool TEXT NOT NULL,
|
|
26
|
+
params TEXT,
|
|
27
|
+
action TEXT NOT NULL,
|
|
28
|
+
rule TEXT,
|
|
29
|
+
reason TEXT,
|
|
30
|
+
created_at TEXT DEFAULT (datetime('now'))
|
|
31
|
+
);
|
|
32
|
+
CREATE INDEX IF NOT EXISTS idx_safety_created ON safety_log(created_at DESC);
|
|
33
|
+
`;
|
|
34
|
+
|
|
35
|
+
let _db: Database.Database | null = null;
|
|
36
|
+
|
|
37
|
+
export function getDb(openclawDir: string): Database.Database {
|
|
38
|
+
if (_db) return _db;
|
|
39
|
+
|
|
40
|
+
const memoryDir = join(openclawDir, "memory");
|
|
41
|
+
if (!existsSync(memoryDir)) mkdirSync(memoryDir, { recursive: true });
|
|
42
|
+
|
|
43
|
+
const dbPath = join(memoryDir, "enhance-memory.sqlite");
|
|
44
|
+
_db = new Database(dbPath);
|
|
45
|
+
_db.pragma("journal_mode = WAL");
|
|
46
|
+
_db.exec(SCHEMA);
|
|
47
|
+
return _db;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// ── 记忆操作 ──
|
|
51
|
+
|
|
52
|
+
export function storeMemory(
|
|
53
|
+
db: Database.Database,
|
|
54
|
+
category: MemoryCategory,
|
|
55
|
+
content: string,
|
|
56
|
+
tags: string = "",
|
|
57
|
+
importance: number = 5,
|
|
58
|
+
sessionId: string = "",
|
|
59
|
+
): MemoryEntry {
|
|
60
|
+
const stmt = db.prepare(
|
|
61
|
+
`INSERT INTO memories (category, content, tags, importance, session_id)
|
|
62
|
+
VALUES (?, ?, ?, ?, ?)`,
|
|
63
|
+
);
|
|
64
|
+
const result = stmt.run(category, content, tags, Math.min(10, Math.max(1, importance)), sessionId);
|
|
65
|
+
return db.prepare("SELECT * FROM memories WHERE id = ?").get(result.lastInsertRowid) as MemoryEntry;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function searchMemories(
|
|
69
|
+
db: Database.Database,
|
|
70
|
+
opts: {
|
|
71
|
+
category?: MemoryCategory;
|
|
72
|
+
keyword?: string;
|
|
73
|
+
limit?: number;
|
|
74
|
+
since?: string;
|
|
75
|
+
} = {},
|
|
76
|
+
): MemoryEntry[] {
|
|
77
|
+
const conditions: string[] = [];
|
|
78
|
+
const params: unknown[] = [];
|
|
79
|
+
|
|
80
|
+
if (opts.category) {
|
|
81
|
+
conditions.push("category = ?");
|
|
82
|
+
params.push(opts.category);
|
|
83
|
+
}
|
|
84
|
+
if (opts.keyword) {
|
|
85
|
+
conditions.push("(content LIKE ? OR tags LIKE ?)");
|
|
86
|
+
params.push(`%${opts.keyword}%`, `%${opts.keyword}%`);
|
|
87
|
+
}
|
|
88
|
+
if (opts.since) {
|
|
89
|
+
conditions.push("created_at >= ?");
|
|
90
|
+
params.push(opts.since);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
94
|
+
const limit = opts.limit ?? 20;
|
|
95
|
+
|
|
96
|
+
return db
|
|
97
|
+
.prepare(`SELECT * FROM memories ${where} ORDER BY importance DESC, created_at DESC LIMIT ?`)
|
|
98
|
+
.all(...params, limit) as MemoryEntry[];
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export function getRecentMemories(db: Database.Database, limit: number = 5): MemoryEntry[] {
|
|
102
|
+
return db
|
|
103
|
+
.prepare("SELECT * FROM memories ORDER BY created_at DESC LIMIT ?")
|
|
104
|
+
.all(limit) as MemoryEntry[];
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export function deleteMemory(db: Database.Database, id: number): boolean {
|
|
108
|
+
const result = db.prepare("DELETE FROM memories WHERE id = ?").run(id);
|
|
109
|
+
return result.changes > 0;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export function getMemoryStats(db: Database.Database): Record<string, number> {
|
|
113
|
+
const rows = db
|
|
114
|
+
.prepare("SELECT category, COUNT(*) as count FROM memories GROUP BY category")
|
|
115
|
+
.all() as Array<{ category: string; count: number }>;
|
|
116
|
+
const stats: Record<string, number> = { total: 0 };
|
|
117
|
+
for (const row of rows) {
|
|
118
|
+
stats[row.category] = row.count;
|
|
119
|
+
stats.total += row.count;
|
|
120
|
+
}
|
|
121
|
+
return stats;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// ── 安全日志操作 ──
|
|
125
|
+
|
|
126
|
+
export function logSafetyEvent(
|
|
127
|
+
db: Database.Database,
|
|
128
|
+
tool: string,
|
|
129
|
+
params: string,
|
|
130
|
+
action: string,
|
|
131
|
+
rule: string = "",
|
|
132
|
+
reason: string = "",
|
|
133
|
+
): void {
|
|
134
|
+
db.prepare(
|
|
135
|
+
`INSERT INTO safety_log (tool, params, action, rule, reason) VALUES (?, ?, ?, ?, ?)`,
|
|
136
|
+
).run(tool, params, action, rule, reason);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export function getRecentSafetyEvents(
|
|
140
|
+
db: Database.Database,
|
|
141
|
+
limit: number = 20,
|
|
142
|
+
): Array<{ id: number; tool: string; params: string; action: string; rule: string; reason: string; created_at: string }> {
|
|
143
|
+
return db
|
|
144
|
+
.prepare("SELECT * FROM safety_log ORDER BY created_at DESC LIMIT ?")
|
|
145
|
+
.all(limit) as any[];
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export function getSafetyStats(db: Database.Database): { total: number; blocked: number; logged: number } {
|
|
149
|
+
const row = db
|
|
150
|
+
.prepare(
|
|
151
|
+
`SELECT
|
|
152
|
+
COUNT(*) as total,
|
|
153
|
+
SUM(CASE WHEN action = 'block' THEN 1 ELSE 0 END) as blocked,
|
|
154
|
+
SUM(CASE WHEN action = 'log' THEN 1 ELSE 0 END) as logged
|
|
155
|
+
FROM safety_log`,
|
|
156
|
+
)
|
|
157
|
+
.get() as any;
|
|
158
|
+
return { total: row.total ?? 0, blocked: row.blocked ?? 0, logged: row.logged ?? 0 };
|
|
159
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
<!-- ═══ 龙虾增强包补丁 开始 ═══ -->
|
|
4
|
+
|
|
5
|
+
## 增强行为准则(龙虾增强包)
|
|
6
|
+
|
|
7
|
+
### 决策框架
|
|
8
|
+
在执行多步骤任务时,遵循「理解 → 设计 → 执行 → 验证」的流程:
|
|
9
|
+
1. **理解**: 先读相关代码和文档,不要凭空假设
|
|
10
|
+
2. **设计**: 复杂任务先规划(可使用 plan-mode 技能),简单任务直接执行
|
|
11
|
+
3. **执行**: 最小变更原则,一次只改一件事
|
|
12
|
+
4. **验证**: 改完后确认结果正确(可使用 verify-mode 技能)
|
|
13
|
+
|
|
14
|
+
### 响应模式
|
|
15
|
+
根据请求类型自动调整:
|
|
16
|
+
- **编程任务**: 简洁精准,展示最小 diff,解释 why 而非 what
|
|
17
|
+
- **研究调查**: 系统全面,给出文件路径和行号,区分事实和推测
|
|
18
|
+
- **日常对话**: 自然简短,不过度解释
|
|
19
|
+
|
|
20
|
+
### 记忆管理
|
|
21
|
+
- 当了解到重要的用户偏好、项目决策、反馈信息时,使用 `enhance_memory_store` 存储
|
|
22
|
+
- 回答问题前,考虑使用 `enhance_memory_search` 查找相关历史记忆
|
|
23
|
+
- 定期使用 memory-curator 技能整理记忆
|
|
24
|
+
|
|
25
|
+
### 安全意识
|
|
26
|
+
- 执行破坏性操作(删除、覆盖、force push)前先确认
|
|
27
|
+
- 不要提交敏感文件(.env、密钥、凭据)
|
|
28
|
+
- 如果发现安全问题立即指出并修复
|
|
29
|
+
|
|
30
|
+
<!-- ═══ 龙虾增强包补丁 结束 ═══ -->
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
<!-- ═══ 龙虾增强包补丁 开始 ═══ -->
|
|
4
|
+
|
|
5
|
+
## 增强行为特质(龙虾增强包)
|
|
6
|
+
|
|
7
|
+
### 工作风格
|
|
8
|
+
- 直奔主题,一句话能说清的不用三句话
|
|
9
|
+
- 修 bug 不顺手重构,加功能不过度设计
|
|
10
|
+
- 三行相似代码好过一个过早的抽象
|
|
11
|
+
- 失败时先诊断原因再重试,不盲目循环
|
|
12
|
+
|
|
13
|
+
### 增强能力
|
|
14
|
+
你拥有以下增强工具,在合适的时机使用:
|
|
15
|
+
- `enhance_memory_store/search/review` — 结构化记忆管理
|
|
16
|
+
- `enhance_safety_log/rules` — 安全审计
|
|
17
|
+
- `enhance_workflow_define/list/delete` — 工作流自动化
|
|
18
|
+
- `plan-mode` / `explore-mode` / `verify-mode` / `memory-curator` — 增强技能
|
|
19
|
+
|
|
20
|
+
### 记忆习惯
|
|
21
|
+
当以下情况发生时,主动存储记忆:
|
|
22
|
+
- 用户纠正你的做法(feedback 类)
|
|
23
|
+
- 用户表达偏好(user 类)
|
|
24
|
+
- 做出重要决策或发现关键信息(decision/project 类)
|
|
25
|
+
- 提到有用的外部资源(reference 类)
|
|
26
|
+
|
|
27
|
+
<!-- ═══ 龙虾增强包补丁 结束 ═══ -->
|