principles-disciple 1.5.4 → 1.7.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.
Files changed (88) hide show
  1. package/dist/commands/context.d.ts +5 -0
  2. package/dist/commands/context.js +312 -0
  3. package/dist/commands/evolution-status.d.ts +4 -0
  4. package/dist/commands/evolution-status.js +138 -0
  5. package/dist/commands/export.d.ts +2 -0
  6. package/dist/commands/export.js +45 -0
  7. package/dist/commands/focus.d.ts +14 -0
  8. package/dist/commands/focus.js +582 -0
  9. package/dist/commands/pain.js +143 -6
  10. package/dist/commands/principle-rollback.d.ts +4 -0
  11. package/dist/commands/principle-rollback.js +22 -0
  12. package/dist/commands/rollback.d.ts +19 -0
  13. package/dist/commands/rollback.js +119 -0
  14. package/dist/commands/samples.d.ts +2 -0
  15. package/dist/commands/samples.js +55 -0
  16. package/dist/core/config.d.ts +37 -0
  17. package/dist/core/config.js +47 -0
  18. package/dist/core/control-ui-db.d.ts +68 -0
  19. package/dist/core/control-ui-db.js +274 -0
  20. package/dist/core/detection-funnel.d.ts +1 -1
  21. package/dist/core/detection-funnel.js +4 -0
  22. package/dist/core/dictionary.d.ts +2 -0
  23. package/dist/core/dictionary.js +13 -0
  24. package/dist/core/event-log.d.ts +22 -1
  25. package/dist/core/event-log.js +319 -0
  26. package/dist/core/evolution-engine.d.ts +5 -5
  27. package/dist/core/evolution-engine.js +18 -18
  28. package/dist/core/evolution-migration.d.ts +5 -0
  29. package/dist/core/evolution-migration.js +65 -0
  30. package/dist/core/evolution-reducer.d.ts +69 -0
  31. package/dist/core/evolution-reducer.js +369 -0
  32. package/dist/core/evolution-types.d.ts +103 -0
  33. package/dist/core/focus-history.d.ts +65 -0
  34. package/dist/core/focus-history.js +266 -0
  35. package/dist/core/init.js +30 -7
  36. package/dist/core/migration.js +0 -2
  37. package/dist/core/path-resolver.d.ts +3 -0
  38. package/dist/core/path-resolver.js +90 -31
  39. package/dist/core/paths.d.ts +7 -8
  40. package/dist/core/paths.js +48 -40
  41. package/dist/core/profile.js +1 -1
  42. package/dist/core/session-tracker.d.ts +4 -0
  43. package/dist/core/session-tracker.js +15 -0
  44. package/dist/core/thinking-models.d.ts +38 -0
  45. package/dist/core/thinking-models.js +170 -0
  46. package/dist/core/trajectory.d.ts +184 -0
  47. package/dist/core/trajectory.js +817 -0
  48. package/dist/core/trust-engine.d.ts +2 -0
  49. package/dist/core/trust-engine.js +30 -4
  50. package/dist/core/workspace-context.d.ts +13 -0
  51. package/dist/core/workspace-context.js +50 -7
  52. package/dist/hooks/gate.js +301 -30
  53. package/dist/hooks/llm.d.ts +8 -0
  54. package/dist/hooks/llm.js +347 -69
  55. package/dist/hooks/message-sanitize.d.ts +3 -0
  56. package/dist/hooks/message-sanitize.js +37 -0
  57. package/dist/hooks/pain.js +105 -5
  58. package/dist/hooks/prompt.d.ts +20 -11
  59. package/dist/hooks/prompt.js +558 -158
  60. package/dist/hooks/subagent.d.ts +9 -2
  61. package/dist/hooks/subagent.js +40 -3
  62. package/dist/http/principles-console-route.d.ts +2 -0
  63. package/dist/http/principles-console-route.js +257 -0
  64. package/dist/i18n/commands.js +48 -20
  65. package/dist/index.js +264 -8
  66. package/dist/service/control-ui-query-service.d.ts +217 -0
  67. package/dist/service/control-ui-query-service.js +537 -0
  68. package/dist/service/empathy-observer-manager.d.ts +42 -0
  69. package/dist/service/empathy-observer-manager.js +147 -0
  70. package/dist/service/evolution-worker.d.ts +10 -0
  71. package/dist/service/evolution-worker.js +156 -24
  72. package/dist/service/trajectory-service.d.ts +2 -0
  73. package/dist/service/trajectory-service.js +15 -0
  74. package/dist/tools/agent-spawn.d.ts +27 -6
  75. package/dist/tools/agent-spawn.js +339 -87
  76. package/dist/tools/deep-reflect.d.ts +27 -7
  77. package/dist/tools/deep-reflect.js +282 -113
  78. package/dist/types/event-types.d.ts +84 -2
  79. package/dist/types/event-types.js +33 -0
  80. package/dist/types.d.ts +52 -0
  81. package/dist/types.js +24 -1
  82. package/openclaw.plugin.json +43 -11
  83. package/package.json +16 -6
  84. package/templates/langs/zh/core/HEARTBEAT.md +28 -4
  85. package/templates/langs/zh/skills/pd-daily/SKILL.md +97 -13
  86. package/templates/pain_settings.json +54 -2
  87. package/templates/workspace/.principles/PROFILE.json +2 -0
  88. package/templates/workspace/okr/CURRENT_FOCUS.md +57 -0
@@ -1,9 +1,81 @@
1
1
  import { Type } from '@sinclair/typebox';
2
2
  import { randomUUID } from 'node:crypto';
3
3
  import * as fs from 'fs';
4
+ import * as path from 'node:path';
4
5
  import { EventLogService } from '../core/event-log.js';
5
6
  import { buildCritiquePromptV2 } from './critique-prompt.js';
6
7
  import { resolvePdPath } from '../core/paths.js';
8
+ import { reflectionLogRetentionDays } from '../types.js';
9
+ /**
10
+ * Write reflection result to reflection-log.md
11
+ * Uses atomic write (temp file + rename) to prevent race conditions
12
+ */
13
+ function writeToReflectionLog(workspaceDir, context, insights, modelId, depth) {
14
+ const reflectionLogPath = resolvePdPath(workspaceDir, 'REFLECTION_LOG');
15
+ const memoryDir = path.dirname(reflectionLogPath);
16
+ // Ensure memory directory exists
17
+ if (!fs.existsSync(memoryDir)) {
18
+ fs.mkdirSync(memoryDir, { recursive: true });
19
+ }
20
+ const timestamp = new Date().toISOString();
21
+ const entry = `
22
+ ---
23
+ ## Reflection at ${timestamp}
24
+ **Model**: ${modelId || 'auto-select'}
25
+ **Depth**: ${depth || 2}
26
+
27
+ ### Context
28
+ ${context.substring(0, 500)}${context.length > 500 ? '...' : ''}
29
+
30
+ ### Insights
31
+ ${insights}
32
+
33
+ `;
34
+ const header = `# Reflection Log\n\n> Auto-generated by Deep Reflection Tool\n> Retention: ${reflectionLogRetentionDays} days\n`;
35
+ // Read existing content
36
+ let existingContent = '';
37
+ if (fs.existsSync(reflectionLogPath)) {
38
+ existingContent = fs.readFileSync(reflectionLogPath, 'utf8');
39
+ }
40
+ const newContent = header + entry + existingContent.replace(header, '');
41
+ // Atomic write: write to temp file first, then rename
42
+ const tempPath = `${reflectionLogPath}.tmp`;
43
+ fs.writeFileSync(tempPath, newContent, 'utf8');
44
+ fs.renameSync(tempPath, reflectionLogPath);
45
+ }
46
+ /**
47
+ * Clean up reflection log entries older than retention period
48
+ */
49
+ function cleanupReflectionLog(workspaceDir) {
50
+ const reflectionLogPath = resolvePdPath(workspaceDir, 'REFLECTION_LOG');
51
+ if (!fs.existsSync(reflectionLogPath))
52
+ return;
53
+ const content = fs.readFileSync(reflectionLogPath, 'utf8');
54
+ const cutoffDate = new Date();
55
+ cutoffDate.setDate(cutoffDate.getDate() - reflectionLogRetentionDays);
56
+ // Use more precise regex to match ISO timestamp
57
+ // Pattern: ---\n## Reflection at 2024-01-15T10:30:00
58
+ const entryPattern = /---\n## Reflection at (\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2})/g;
59
+ const parts = content.split(entryPattern);
60
+ // parts[0] = header, then alternates: timestamp, content, timestamp, content...
61
+ const header = parts[0];
62
+ const validEntries = [];
63
+ for (let i = 1; i < parts.length; i += 2) {
64
+ const timestamp = parts[i];
65
+ const entryContent = parts[i + 1] || '';
66
+ const entryDate = new Date(timestamp);
67
+ if (entryDate >= cutoffDate) {
68
+ validEntries.push(`---\n## Reflection at ${timestamp}${entryContent}`);
69
+ }
70
+ }
71
+ if (validEntries.length < (parts.length - 1) / 2) {
72
+ const newContent = header + validEntries.join('');
73
+ // Atomic write
74
+ const tempPath = `${reflectionLogPath}.tmp`;
75
+ fs.writeFileSync(tempPath, newContent, 'utf8');
76
+ fs.renameSync(tempPath, reflectionLogPath);
77
+ }
78
+ }
7
79
  const DEFAULT_CONFIG = {
8
80
  enabled: true,
9
81
  mode: 'auto',
@@ -40,97 +112,176 @@ function loadConfig(workspaceDir, api) {
40
112
  }
41
113
  return DEFAULT_CONFIG;
42
114
  }
43
- export const deepReflectTool = {
44
- name: 'deep_reflect',
45
- description: '执行深层次的元认知反思,分析当前任务的潜在风险、逻辑漏洞或架构改进点。',
46
- parameters: Type.Object({
47
- context: Type.String({ description: '需要反思的任务上下文、代码片段或当前遇到的困难。' }),
48
- depth: Type.Optional(Type.Number({ description: '反思深度 (1-3)。1: 快速扫描, 2: 均衡分析, 3: 彻底解构。默认为 2。', minimum: 1, maximum: 3 })),
49
- model_id: Type.Optional(Type.String({ description: '可选:强制指定使用的思维模型 ID。' }))
50
- }),
51
- /**
52
- * Tool execution logic
53
- * @param workspaceDir Optional parameter for unit testing
54
- */
55
- async execute(params, api, workspaceDir) {
56
- const { context, depth = 2, model_id } = params;
57
- if (!context)
58
- return '❌ 错误: 必须提供反思上下文 (context)。';
59
- // 路径解析优先级:显式传入 > api.config > api.workspaceDir > api.resolvePath
60
- const effectiveWorkspaceDir = workspaceDir
61
- || api.config?.workspaceDir
62
- || api.workspaceDir
63
- || api.resolvePath?.('.');
64
- if (!effectiveWorkspaceDir) {
65
- return `❌ 反思执行失败: Workspace directory is required for deep reflection.。请检查 API 配置或网络连接。`;
66
- }
67
- const config = loadConfig(effectiveWorkspaceDir, api);
68
- if (config.mode === 'disabled' || !config.enabled) {
69
- return `⏭️ Deep Reflection 已禁用。`;
70
- }
71
- if (model_id) {
72
- safeLog(api, 'warn', `[DeepReflect] The 'model_id' parameter is deprecated. The agent will now auto-select models based on the context index.`);
73
- }
74
- const agentId = 'main';
75
- const sessionKey = `agent:${agentId}:reflection:${randomUUID()}`;
76
- const sessionId = sessionKey.split(':').pop();
77
- const stateDir = resolvePdPath(effectiveWorkspaceDir, 'STATE_DIR');
78
- const eventLog = EventLogService.get(stateDir, api.logger);
79
- try {
80
- const extraSystemPrompt = buildCritiquePromptV2({
81
- context,
82
- depth,
83
- model_id,
84
- api,
85
- workspaceDir: effectiveWorkspaceDir
86
- });
87
- const startTime = Date.now();
88
- const subagentRuntime = api.runtime.subagent;
89
- if (!subagentRuntime)
90
- throw new Error('OpenClaw subagent runtime not found.');
91
- await subagentRuntime.run({
92
- sessionKey, // 👈 对齐官方字段
93
- message: `请对我当前的任务进行深层次反思。\n\n上下文:${context}`, // 👈 对齐官方字段
94
- extraSystemPrompt,
95
- deliver: false
96
- });
97
- const finalStatus = await subagentRuntime.waitForRun({ runId: sessionKey }); // 👈 对齐官方对象传参
98
- const duration = Date.now() - startTime;
99
- if (finalStatus.status === 'timeout') {
100
- return `⚠️ 反思任务执行超时。你可以尝试减少上下文长度或增加深度。`;
115
+ /**
116
+ * Helper to read string parameter from rawParams
117
+ * Supports both camelCase and snake_case parameter names
118
+ */
119
+ function readStringParam(rawParams, key) {
120
+ const value = rawParams[key];
121
+ if (typeof value === 'string')
122
+ return value.trim() || undefined;
123
+ // Try snake_case alias
124
+ const snakeKey = key.replace(/([A-Z])/g, '_$1').toLowerCase();
125
+ const snakeValue = rawParams[snakeKey];
126
+ if (typeof snakeValue === 'string')
127
+ return snakeValue.trim() || undefined;
128
+ return undefined;
129
+ }
130
+ /**
131
+ * Helper to read number parameter from rawParams
132
+ * Supports both camelCase and snake_case parameter names
133
+ */
134
+ function readNumberParam(rawParams, key) {
135
+ const value = rawParams[key];
136
+ if (typeof value === 'number')
137
+ return value;
138
+ // Try snake_case alias
139
+ const snakeKey = key.replace(/([A-Z])/g, '_$1').toLowerCase();
140
+ const snakeValue = rawParams[snakeKey];
141
+ if (typeof snakeValue === 'number')
142
+ return snakeValue;
143
+ return undefined;
144
+ }
145
+ /**
146
+ * Create Deep Reflect Tool
147
+ *
148
+ * Uses factory pattern to capture `api` in closure, following OpenClaw plugin SDK conventions.
149
+ * The execute signature must be: async (_toolCallId: string, rawParams: Record<string, unknown>)
150
+ */
151
+ export function createDeepReflectTool(api) {
152
+ return {
153
+ name: 'deep_reflect',
154
+ description: '执行深层次的元认知反思,分析当前任务的潜在风险、逻辑漏洞或架构改进点。',
155
+ parameters: Type.Object({
156
+ context: Type.String({ description: '需要反思的任务上下文、代码片段或当前遇到的困难。' }),
157
+ depth: Type.Optional(Type.Number({ description: '反思深度 (1-3)。1: 快速扫描, 2: 均衡分析, 3: 彻底解构。默认为 2。', minimum: 1, maximum: 3 })),
158
+ model_id: Type.Optional(Type.String({ description: '可选:强制指定使用的思维模型 ID。' }))
159
+ }),
160
+ /**
161
+ * Tool execution logic
162
+ *
163
+ * OpenClaw tool execute signature:
164
+ * - First parameter: _toolCallId (string) - the tool call ID
165
+ * - Second parameter: rawParams (Record<string, unknown>) - the actual parameters
166
+ * - Third parameter (optional): signal (AbortSignal) - for cancellation
167
+ */
168
+ async execute(_toolCallId, rawParams) {
169
+ const context = readStringParam(rawParams, 'context') || '';
170
+ const depth = readNumberParam(rawParams, 'depth') ?? 2;
171
+ const model_id = readStringParam(rawParams, 'model_id');
172
+ if (!context) {
173
+ return {
174
+ content: [{
175
+ type: 'text',
176
+ text: '❌ 错误: 必须提供反思上下文 (context)。'
177
+ }]
178
+ };
179
+ }
180
+ // 路径解析优先级:api.config > api.workspaceDir > api.resolvePath
181
+ const effectiveWorkspaceDir = api.config?.workspaceDir
182
+ || api.workspaceDir
183
+ || api.resolvePath?.('.');
184
+ if (!effectiveWorkspaceDir) {
185
+ return {
186
+ content: [{
187
+ type: 'text',
188
+ text: '❌ 反思执行失败: Workspace directory is required for deep reflection.。请检查 API 配置或网络连接。'
189
+ }]
190
+ };
191
+ }
192
+ const config = loadConfig(effectiveWorkspaceDir, api);
193
+ if (config.mode === 'disabled' || !config.enabled) {
194
+ return {
195
+ content: [{
196
+ type: 'text',
197
+ text: '⏭️ Deep Reflection 已禁用。'
198
+ }]
199
+ };
101
200
  }
102
- if (finalStatus.status === 'ok') { // 👈 对齐官方状态码
103
- const rawMessages = await subagentRuntime.getSessionMessages({ sessionKey });
104
- let insights = '';
105
- if (rawMessages.assistantTexts && Array.isArray(rawMessages.assistantTexts)) {
106
- insights = rawMessages.assistantTexts.join('\n');
201
+ if (model_id) {
202
+ safeLog(api, 'warn', `[DeepReflect] The 'model_id' parameter is deprecated. The agent will now auto-select models based on the context index.`);
203
+ }
204
+ const agentId = 'main';
205
+ const sessionKey = `agent:${agentId}:reflection:${randomUUID()}`;
206
+ const sessionId = sessionKey.split(':').pop();
207
+ const stateDir = resolvePdPath(effectiveWorkspaceDir, 'STATE_DIR');
208
+ const eventLog = EventLogService.get(stateDir, api.logger);
209
+ try {
210
+ const extraSystemPrompt = buildCritiquePromptV2({
211
+ context,
212
+ depth,
213
+ model_id,
214
+ api,
215
+ workspaceDir: effectiveWorkspaceDir
216
+ });
217
+ const startTime = Date.now();
218
+ const subagentRuntime = api.runtime.subagent;
219
+ if (!subagentRuntime)
220
+ throw new Error('OpenClaw subagent runtime not found.');
221
+ await subagentRuntime.run({
222
+ sessionKey,
223
+ message: `请对我当前的任务进行深层次反思。\n\n上下文:${context}`,
224
+ extraSystemPrompt,
225
+ deliver: false
226
+ });
227
+ const finalStatus = await subagentRuntime.waitForRun({ runId: sessionKey });
228
+ const duration = Date.now() - startTime;
229
+ if (finalStatus.status === 'timeout') {
230
+ return {
231
+ content: [{
232
+ type: 'text',
233
+ text: '⚠️ 反思任务执行超时。你可以尝试减少上下文长度或增加深度。'
234
+ }]
235
+ };
107
236
  }
108
- else {
109
- const messages = rawMessages.messages || [];
110
- const lastMessage = messages[messages.length - 1];
111
- if (typeof lastMessage?.content === 'string') {
112
- insights = lastMessage.content;
237
+ if (finalStatus.status === 'ok') {
238
+ const rawMessages = await subagentRuntime.getSessionMessages({ sessionKey });
239
+ let insights = '';
240
+ if (rawMessages.assistantTexts && Array.isArray(rawMessages.assistantTexts)) {
241
+ insights = rawMessages.assistantTexts.join('\n');
113
242
  }
114
- else if (Array.isArray(lastMessage?.content)) {
115
- insights = lastMessage.content.filter((c) => c.type === 'text').map((c) => c.text).join('\n');
243
+ else {
244
+ const messages = rawMessages.messages || [];
245
+ const lastMessage = messages[messages.length - 1];
246
+ if (typeof lastMessage?.content === 'string') {
247
+ insights = lastMessage.content;
248
+ }
249
+ else if (Array.isArray(lastMessage?.content)) {
250
+ insights = lastMessage.content.filter((c) => c.type === 'text').map((c) => c.text).join('\n');
251
+ }
116
252
  }
117
- }
118
- if (insights.includes('REFLECTION_OK')) {
119
- return `✅ 反思完成:当前任务逻辑严密,未发现显著问题。`;
120
- }
121
- if (eventLog && sessionId) {
122
- eventLog.recordDeepReflection(sessionId, {
123
- modelId: model_id || 'auto-select',
124
- modelSelectionMode: model_id ? 'manual' : 'auto',
125
- depth,
126
- contextPreview: context.substring(0, 200),
127
- resultPreview: insights.substring(0, 300),
128
- durationMs: duration,
129
- passed: true,
130
- timeout: false
131
- });
132
- }
133
- return `
253
+ if (insights.includes('REFLECTION_OK')) {
254
+ return {
255
+ content: [{
256
+ type: 'text',
257
+ text: '✅ 反思完成:当前任务逻辑严密,未发现显著问题。'
258
+ }]
259
+ };
260
+ }
261
+ if (eventLog && sessionId) {
262
+ eventLog.recordDeepReflection(sessionId, {
263
+ modelId: model_id || 'auto-select',
264
+ modelSelectionMode: model_id ? 'manual' : 'auto',
265
+ depth,
266
+ contextPreview: context.substring(0, 200),
267
+ resultPreview: insights.substring(0, 300),
268
+ durationMs: duration,
269
+ passed: true,
270
+ timeout: false
271
+ });
272
+ }
273
+ // Write to reflection log and cleanup old entries
274
+ try {
275
+ writeToReflectionLog(effectiveWorkspaceDir, context, insights, model_id, depth);
276
+ cleanupReflectionLog(effectiveWorkspaceDir);
277
+ }
278
+ catch (logErr) {
279
+ safeLog(api, 'warn', `[DeepReflect] Failed to write reflection log: ${String(logErr)}`);
280
+ }
281
+ return {
282
+ content: [{
283
+ type: 'text',
284
+ text: `
134
285
  # 💎 Deep Reflection Insights
135
286
  ---
136
287
  **Selected Model(s)**: ${model_id || 'auto-select'}
@@ -141,34 +292,52 @@ ${insights}
141
292
 
142
293
  ---
143
294
  *Generated by Principles Disciple Meta-Cognitive Engine*
144
- `.trim();
295
+ `.trim()
296
+ }]
297
+ };
298
+ }
299
+ else {
300
+ throw new Error(`Subagent status: ${finalStatus.status}`);
301
+ }
145
302
  }
146
- else {
147
- throw new Error(`Subagent status: ${finalStatus.status}`);
303
+ catch (err) {
304
+ const errorMsg = err instanceof Error ? err.message : String(err);
305
+ safeLog(api, 'error', `[DeepReflect] Reflection failed: ${errorMsg}`);
306
+ if (eventLog && sessionId) {
307
+ eventLog.recordDeepReflection(sessionId, {
308
+ modelId: model_id || 'auto-select',
309
+ modelSelectionMode: model_id ? 'manual' : 'auto',
310
+ depth,
311
+ contextPreview: context.substring(0, 200),
312
+ durationMs: 0,
313
+ passed: false,
314
+ timeout: errorMsg.toLowerCase().includes('timeout'),
315
+ error: errorMsg
316
+ });
317
+ }
318
+ if (errorMsg === 'API throw')
319
+ throw err;
320
+ return {
321
+ content: [{
322
+ type: 'text',
323
+ text: `❌ 反思执行失败: ${errorMsg}。请检查 API 配置或网络连接。`
324
+ }]
325
+ };
148
326
  }
149
- }
150
- catch (err) {
151
- const errorMsg = err instanceof Error ? err.message : String(err);
152
- safeLog(api, 'error', `[DeepReflect] Reflection failed: ${errorMsg}`);
153
- if (eventLog && sessionId) {
154
- eventLog.recordDeepReflection(sessionId, {
155
- modelId: model_id || 'auto-select',
156
- modelSelectionMode: model_id ? 'manual' : 'auto',
157
- depth,
158
- contextPreview: context.substring(0, 200),
159
- durationMs: 0,
160
- passed: false,
161
- timeout: errorMsg.toLowerCase().includes('timeout'),
162
- error: errorMsg
163
- });
327
+ finally {
328
+ if (api.runtime.subagent)
329
+ await api.runtime.subagent.deleteSession({ sessionKey }).catch(() => { });
164
330
  }
165
- if (errorMsg === 'API throw')
166
- throw err;
167
- return `❌ 反思执行失败: ${errorMsg}。请检查 API 配置或网络连接。`;
168
- }
169
- finally {
170
- if (api.runtime.subagent)
171
- await api.runtime.subagent.deleteSession({ sessionKey }).catch(() => { });
172
331
  }
173
- }
332
+ };
333
+ }
334
+ // Legacy export for backward compatibility with tests that call execute directly
335
+ export const deepReflectTool = {
336
+ name: 'deep_reflect',
337
+ description: '执行深层次的元认知反思,分析当前任务的潜在风险、逻辑漏洞或架构改进点。',
338
+ parameters: Type.Object({
339
+ context: Type.String({ description: '需要反思的任务上下文、代码片段或当前遇到的困难。' }),
340
+ depth: Type.Optional(Type.Number({ description: '反思深度 (1-3)。1: 快速扫描, 2: 均衡分析, 3: 彻底解构。默认为 2。', minimum: 1, maximum: 3 })),
341
+ model_id: Type.Optional(Type.String({ description: '可选:强制指定使用的思维模型 ID。' }))
342
+ }),
174
343
  };
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * Event types for structured logging and daily statistics.
3
3
  */
4
- export type EventType = 'tool_call' | 'pain_signal' | 'rule_match' | 'rule_promotion' | 'hook_execution' | 'gate_block' | 'plan_approval' | 'evolution_task' | 'deep_reflection' | 'trust_change' | 'error' | 'warn';
5
- export type EventCategory = 'success' | 'failure' | 'detected' | 'blocked' | 'approved' | 'enqueued' | 'completed' | 'promoted' | 'passed' | 'changed';
4
+ export type EventType = 'tool_call' | 'pain_signal' | 'rule_match' | 'rule_promotion' | 'hook_execution' | 'gate_block' | 'gate_bypass' | 'plan_approval' | 'evolution_task' | 'deep_reflection' | 'trust_change' | 'empathy_rollback' | 'error' | 'warn';
5
+ export type EventCategory = 'success' | 'failure' | 'detected' | 'blocked' | 'bypassed' | 'approved' | 'enqueued' | 'completed' | 'promoted' | 'passed' | 'changed' | 'rolled_back';
6
6
  /**
7
7
  * Base event structure for JSONL logging.
8
8
  */
@@ -42,6 +42,14 @@ export interface PainSignalEventData {
42
42
  source: string;
43
43
  reason?: string;
44
44
  isRisky?: boolean;
45
+ origin?: 'assistant_self_report' | 'user_manual' | 'system_infer';
46
+ severity?: 'mild' | 'moderate' | 'severe';
47
+ confidence?: number;
48
+ detection_mode?: 'structured' | 'legacy_tag';
49
+ deduped?: boolean;
50
+ trigger_text_excerpt?: string;
51
+ raw_score?: number;
52
+ calibrated_score?: number;
45
53
  }
46
54
  export interface RuleMatchEventData {
47
55
  ruleId: string;
@@ -67,6 +75,13 @@ export interface GateBlockEventData {
67
75
  reason: string;
68
76
  planStatus?: string;
69
77
  }
78
+ export interface GateBypassEventData {
79
+ toolName: string;
80
+ filePath: string;
81
+ bypassType: 'stage4_architect' | 'plan_approved' | 'whitelisted';
82
+ trustScore: number;
83
+ trustStage: number;
84
+ }
70
85
  export interface PlanApprovalEventData {
71
86
  toolName: string;
72
87
  filePath: string;
@@ -106,6 +121,18 @@ export interface DeepReflectionEventData {
106
121
  /** 发现的风险数量 */
107
122
  risksCount?: number;
108
123
  }
124
+ export interface EmpathyRollbackEventData {
125
+ /** Event ID being rolled back */
126
+ eventId: string;
127
+ /** Original penalty score that was applied */
128
+ originalScore: number;
129
+ /** Session ID where the original event occurred */
130
+ originalSessionId?: string;
131
+ /** Reason for rollback (manual, false_positive, etc.) */
132
+ reason: string;
133
+ /** Who initiated the rollback */
134
+ triggeredBy: 'user_command' | 'natural_language' | 'system';
135
+ }
109
136
  export interface ToolCallStats {
110
137
  total: number;
111
138
  success: number;
@@ -128,6 +155,59 @@ export interface PainStats {
128
155
  avgScore: number;
129
156
  maxScore: number;
130
157
  }
158
+ /**
159
+ * Empathy Engine event statistics for tracking emotional signals.
160
+ * Used for /pd-status empathy card and effectiveness metrics.
161
+ */
162
+ export interface EmpathyEventStats {
163
+ /** Total empathy events detected (excluding deduped) */
164
+ totalEvents: number;
165
+ /** Events that were deduped (not counted in totalEvents) */
166
+ dedupedCount: number;
167
+ /** Dedupe hit rate (dedupedCount / (totalEvents + dedupedCount)) */
168
+ dedupeHitRate: number;
169
+ /** Total penalty score applied */
170
+ totalPenaltyScore: number;
171
+ /** Score rolled back via manual rollback */
172
+ rolledBackScore: number;
173
+ /** Number of rollback operations */
174
+ rollbackCount: number;
175
+ /** Events by severity level */
176
+ bySeverity: {
177
+ mild: number;
178
+ moderate: number;
179
+ severe: number;
180
+ };
181
+ /** Score by severity level */
182
+ scoreBySeverity: {
183
+ mild: number;
184
+ moderate: number;
185
+ severe: number;
186
+ };
187
+ /** Events by detection mode */
188
+ byDetectionMode: {
189
+ structured: number;
190
+ legacy_tag: number;
191
+ };
192
+ /** Events by origin */
193
+ byOrigin: {
194
+ assistant_self_report: number;
195
+ user_manual: number;
196
+ system_infer: number;
197
+ };
198
+ /** Confidence distribution */
199
+ confidenceDistribution: {
200
+ high: number;
201
+ medium: number;
202
+ low: number;
203
+ };
204
+ /** Daily trend (last 7 days) */
205
+ dailyTrend: Array<{
206
+ date: string;
207
+ count: number;
208
+ score: number;
209
+ }>;
210
+ }
131
211
  export interface GfiStats {
132
212
  peak: number;
133
213
  samples: number;
@@ -214,6 +294,8 @@ export interface DailyStats {
214
294
  errors: ErrorStats;
215
295
  /** Pain signal statistics */
216
296
  pain: PainStats;
297
+ /** Empathy Engine event statistics */
298
+ empathy: EmpathyEventStats;
217
299
  /** GFI statistics */
218
300
  gfi: GfiStats;
219
301
  /** Evolution statistics */
@@ -34,6 +34,39 @@ export function createEmptyDailyStats(date) {
34
34
  avgScore: 0,
35
35
  maxScore: 0,
36
36
  },
37
+ empathy: {
38
+ totalEvents: 0,
39
+ dedupedCount: 0,
40
+ dedupeHitRate: 0,
41
+ totalPenaltyScore: 0,
42
+ rolledBackScore: 0,
43
+ rollbackCount: 0,
44
+ bySeverity: {
45
+ mild: 0,
46
+ moderate: 0,
47
+ severe: 0,
48
+ },
49
+ scoreBySeverity: {
50
+ mild: 0,
51
+ moderate: 0,
52
+ severe: 0,
53
+ },
54
+ byDetectionMode: {
55
+ structured: 0,
56
+ legacy_tag: 0,
57
+ },
58
+ byOrigin: {
59
+ assistant_self_report: 0,
60
+ user_manual: 0,
61
+ system_infer: 0,
62
+ },
63
+ confidenceDistribution: {
64
+ high: 0,
65
+ medium: 0,
66
+ low: 0,
67
+ },
68
+ dailyTrend: [],
69
+ },
37
70
  gfi: {
38
71
  peak: 0,
39
72
  samples: 0,
package/dist/types.d.ts CHANGED
@@ -1 +1,53 @@
1
1
  export type { PluginCommandContext, PluginCommandResult } from './openclaw-sdk.js';
2
+ /**
3
+ * Context Injection Configuration
4
+ * Controls what content gets injected into the LLM prompt.
5
+ *
6
+ * NOTE: Core Principles (PRINCIPLES.md) are ALWAYS injected and cannot be disabled.
7
+ * This is by design - principles are the foundation of the agent's behavior.
8
+ */
9
+ export type ProjectFocusMode = 'full' | 'summary' | 'off';
10
+ export interface EvolutionContextConfig {
11
+ /** Enable conversation context in evolution task (default: true) */
12
+ enabled: boolean;
13
+ /** Max recent messages included in evolution task (default: 4) */
14
+ maxMessages: number;
15
+ /** Max chars per message snippet (default: 200) */
16
+ maxCharsPerMessage: number;
17
+ }
18
+ export interface ContextInjectionConfig {
19
+ /** Thinking OS (mental models) - can be toggled */
20
+ thinkingOs: boolean;
21
+ /** Project context (CURRENT_FOCUS.md) mode */
22
+ projectFocus: ProjectFocusMode;
23
+ /** Reflection log - can be toggled */
24
+ reflectionLog: boolean;
25
+ /** Trust score awareness - can be toggled */
26
+ trustScore: boolean;
27
+ /** Evolution task context injection settings */
28
+ evolutionContext: EvolutionContextConfig;
29
+ }
30
+ /**
31
+ * Default context injection configuration
32
+ * Based on user requirements:
33
+ * - principles: always on (not configurable)
34
+ * - thinkingOs: true (can be turned off)
35
+ * - projectFocus: 'off' (default closed, user can enable)
36
+ * - reflectionLog: true (default on)
37
+ * - trustScore: true (can be turned off)
38
+ */
39
+ export declare const defaultContextConfig: ContextInjectionConfig;
40
+ /**
41
+ * Reflection log entry structure
42
+ */
43
+ export interface ReflectionLogEntry {
44
+ timestamp: string;
45
+ context: string;
46
+ insights: string;
47
+ modelId?: string;
48
+ depth?: number;
49
+ }
50
+ /**
51
+ * Reflection log retention configuration
52
+ */
53
+ export declare const reflectionLogRetentionDays = 7;