opcode-pg-memory 2.2.8 → 2.3.1

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 (76) hide show
  1. package/dist/cli.js +232 -214
  2. package/dist/index.d.ts +1 -0
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +30 -21006
  5. package/dist/index.js.map +1 -0
  6. package/dist/mcp-server.js +319 -302
  7. package/dist/mcp-server.js.map +1 -0
  8. package/dist/src/cache/semantic-cache.js +399 -0
  9. package/dist/src/cache/semantic-cache.js.map +1 -0
  10. package/dist/src/cli.js +404 -0
  11. package/dist/src/cli.js.map +1 -0
  12. package/dist/src/config.d.ts +5 -0
  13. package/dist/src/config.d.ts.map +1 -1
  14. package/dist/src/config.js +89 -0
  15. package/dist/src/config.js.map +1 -0
  16. package/dist/src/db/init-db.js +545 -0
  17. package/dist/src/db/init-db.js.map +1 -0
  18. package/dist/src/hooks/message-part-updated.js +203 -0
  19. package/dist/src/hooks/message-part-updated.js.map +1 -0
  20. package/dist/src/hooks/message-updated.js +347 -0
  21. package/dist/src/hooks/message-updated.js.map +1 -0
  22. package/dist/src/hooks/session-compacting.js +179 -0
  23. package/dist/src/hooks/session-compacting.js.map +1 -0
  24. package/dist/src/hooks/session-completed.js +337 -0
  25. package/dist/src/hooks/session-completed.js.map +1 -0
  26. package/dist/src/hooks/session-created.js +206 -0
  27. package/dist/src/hooks/session-created.js.map +1 -0
  28. package/dist/src/hooks/tool-execute.js +267 -0
  29. package/dist/src/hooks/tool-execute.js.map +1 -0
  30. package/dist/src/index.d.ts +1 -0
  31. package/dist/src/index.d.ts.map +1 -1
  32. package/dist/src/index.js +642 -0
  33. package/dist/src/index.js.map +1 -0
  34. package/dist/src/mcp/hindsight-reflect-omo.js +318 -0
  35. package/dist/src/mcp/hindsight-reflect-omo.js.map +1 -0
  36. package/dist/src/mcp/hindsight-reflect.js +838 -0
  37. package/dist/src/mcp/hindsight-reflect.js.map +1 -0
  38. package/dist/src/mcp/recall-memory-omo.js +263 -0
  39. package/dist/src/mcp/recall-memory-omo.js.map +1 -0
  40. package/dist/src/mcp/recall-memory.d.ts +6 -0
  41. package/dist/src/mcp/recall-memory.d.ts.map +1 -1
  42. package/dist/src/mcp/recall-memory.js +900 -0
  43. package/dist/src/mcp/recall-memory.js.map +1 -0
  44. package/dist/src/omo/adapter.js +583 -0
  45. package/dist/src/omo/adapter.js.map +1 -0
  46. package/dist/src/omo/types.js +44 -0
  47. package/dist/src/omo/types.js.map +1 -0
  48. package/dist/src/services/db-polling.d.ts +33 -0
  49. package/dist/src/services/db-polling.d.ts.map +1 -0
  50. package/dist/src/services/db-polling.js +104 -0
  51. package/dist/src/services/db-polling.js.map +1 -0
  52. package/dist/src/services/event-synchronizer.d.ts +15 -0
  53. package/dist/src/services/event-synchronizer.d.ts.map +1 -0
  54. package/dist/src/services/event-synchronizer.js +119 -0
  55. package/dist/src/services/event-synchronizer.js.map +1 -0
  56. package/dist/src/services/keyword.js +29 -0
  57. package/dist/src/services/keyword.js.map +1 -0
  58. package/dist/src/services/logger.js +42 -0
  59. package/dist/src/services/logger.js.map +1 -0
  60. package/dist/src/services/opencode-schema-adapter.d.ts +100 -0
  61. package/dist/src/services/opencode-schema-adapter.d.ts.map +1 -0
  62. package/dist/src/services/opencode-schema-adapter.js +192 -0
  63. package/dist/src/services/opencode-schema-adapter.js.map +1 -0
  64. package/dist/src/services/privacy.js +23 -0
  65. package/dist/src/services/privacy.js.map +1 -0
  66. package/dist/src/topic/segment-manager.js +447 -0
  67. package/dist/src/topic/segment-manager.js.map +1 -0
  68. package/dist/src/types.d.ts +20 -2
  69. package/dist/src/types.d.ts.map +1 -1
  70. package/dist/src/types.js +8 -0
  71. package/dist/src/types.js.map +1 -0
  72. package/dist/src/utils/embedding.js +180 -0
  73. package/dist/src/utils/embedding.js.map +1 -0
  74. package/dist/src/utils/token-budget.js +152 -0
  75. package/dist/src/utils/token-budget.js.map +1 -0
  76. package/package.json +5 -4
@@ -0,0 +1,179 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handleSessionCompacting = handleSessionCompacting;
4
+ exports.getCachePriorityConfig = getCachePriorityConfig;
5
+ exports.handleSessionCompacted = handleSessionCompacted;
6
+ exports.isMessageCompacted = isMessageCompacted;
7
+ exports.getCompactionStats = getCompactionStats;
8
+ const logger_1 = require("../services/logger");
9
+ const logger = (0, logger_1.createLogger)('session-compacting');
10
+ const DEFAULT_CONFIG = {
11
+ preserveHighImportanceObservations: true,
12
+ minImportanceToPreserve: 4,
13
+ markPrunedInCache: true
14
+ };
15
+ /**
16
+ * 处理 experimental.session.compacting / session.compacted 事件
17
+ *
18
+ * 功能:
19
+ * 1. 标记将被压缩的低价值消息
20
+ * 2. 避免对已压缩消息重复产生缓存
21
+ * 3. 与 DCP 协同,semantic_cache 检索优先级设为最高
22
+ *
23
+ * 签名规范:(input, output) => Promise<void>
24
+ */
25
+ async function handleSessionCompacting(input, output, // ✅ 添加 output 参数
26
+ pool, config = {}) {
27
+ const mergedConfig = { ...DEFAULT_CONFIG, ...config };
28
+ const { session, messagesToCompact, compactionStrategy } = input;
29
+ logger.info(`Session compacting: ${session.id}, strategy: ${compactionStrategy}, messages: ${messagesToCompact.length}`);
30
+ try {
31
+ // 获取 session 内部 ID
32
+ const sessionResult = await pool.query('SELECT id FROM session_map WHERE opencode_session_id = $1', [session.id]);
33
+ if (sessionResult.rows.length === 0) {
34
+ logger.warn(`Session not found: ${session.id}`);
35
+ return; // ✅ 返回 void
36
+ }
37
+ const sessionInternalId = sessionResult.rows[0].id;
38
+ // 1. 标记语义缓存中的相关条目
39
+ if (mergedConfig.markPrunedInCache && messagesToCompact.length > 0) {
40
+ await markCacheEntriesAsPruned(sessionInternalId, messagesToCompact, pool);
41
+ }
42
+ // 2. 确定需要保留的高价值消息
43
+ const preserveMessageIds = await determineMessagesToPreserve(sessionInternalId, messagesToCompact, pool, mergedConfig);
44
+ // 3. 记录压缩事件
45
+ await pool.query(`
46
+ INSERT INTO token_usage_log (session_id, operation_type, tokens_used, metadata)
47
+ VALUES ($1, $2, $3, $4)
48
+ `, [
49
+ sessionInternalId,
50
+ 'session_compaction',
51
+ 0,
52
+ JSON.stringify({
53
+ compactedMessageCount: messagesToCompact.length,
54
+ preservedMessageCount: preserveMessageIds.length,
55
+ strategy: compactionStrategy
56
+ })
57
+ ]);
58
+ logger.info(`Session compacting complete. Preserved ${preserveMessageIds.length} high-value messages`);
59
+ // ✅ 正确的钩子签名:mutate output (可选)
60
+ if (preserveMessageIds.length > 0) {
61
+ output.preserveMessageIds = preserveMessageIds;
62
+ }
63
+ }
64
+ catch (error) {
65
+ logger.error('Error handling session.compacting:', error);
66
+ // 出错时不阻断主流程
67
+ }
68
+ }
69
+ /**
70
+ * 标记缓存条目为已压缩
71
+ */
72
+ async function markCacheEntriesAsPruned(sessionId, messageIds, pool) {
73
+ // 查找与这些消息相关的观察记录
74
+ const observationResult = await pool.query(`
75
+ SELECT id FROM observations
76
+ WHERE session_id = $1 AND message_id = ANY($2)
77
+ `, [sessionId, messageIds]);
78
+ if (observationResult.rows.length === 0) {
79
+ return;
80
+ }
81
+ const observationIds = observationResult.rows.map(row => row.id);
82
+ // 标记相关的语义缓存条目
83
+ // 注意:这里假设缓存条目可能通过某种方式与观察记录关联
84
+ // 实际实现可能需要根据具体业务逻辑调整
85
+ const result = await pool.query(`
86
+ UPDATE semantic_cache
87
+ SET is_pruned = TRUE
88
+ WHERE session_id = $1
89
+ AND query_text IN (
90
+ SELECT tool_output_summary FROM observations
91
+ WHERE id = ANY($2) AND tool_output_summary IS NOT NULL
92
+ )
93
+ `, [sessionId, observationIds]);
94
+ logger.info(`Marked ${result.rowCount} cache entries as pruned`);
95
+ }
96
+ /**
97
+ * 确定需要保留的高价值消息
98
+ */
99
+ async function determineMessagesToPreserve(sessionId, messagesToCompact, pool, config) {
100
+ if (!config.preserveHighImportanceObservations) {
101
+ return [];
102
+ }
103
+ // 查找高重要性的观察记录
104
+ const result = await pool.query(`
105
+ SELECT message_id
106
+ FROM observations
107
+ WHERE session_id = $1
108
+ AND message_id = ANY($2)
109
+ AND importance >= $3
110
+ GROUP BY message_id
111
+ `, [sessionId, messagesToCompact, config.minImportanceToPreserve]);
112
+ return result.rows.map(row => row.message_id);
113
+ }
114
+ /**
115
+ * 获取缓存优先级配置
116
+ *
117
+ * 说明:
118
+ * - semantic_cache 检索优先级设为最高(在 DCP 处理之前执行缓存查找)
119
+ * - 缓存命中后直接返回,无需进入 DCP 通道(零 token 消耗)
120
+ */
121
+ function getCachePriorityConfig() {
122
+ return {
123
+ // 最高优先级(数值越小优先级越高)
124
+ priority: 1,
125
+ // 缓存命中时绕过 DCP
126
+ bypassDCPOnHit: true
127
+ };
128
+ }
129
+ /**
130
+ * 处理 session.compacted 事件(压缩完成后)
131
+ *
132
+ * 签名规范:(input, output) => Promise<void>
133
+ */
134
+ async function handleSessionCompacted(input, output, // ✅ 添加 output 参数
135
+ pool, config = {}) {
136
+ logger.info(`Session compacted: ${input.session.id}`);
137
+ // 压缩完成后的清理工作
138
+ // ✅ 正确的钩子签名:不返回任何值
139
+ }
140
+ /**
141
+ * 检查消息是否已被压缩
142
+ */
143
+ async function isMessageCompacted(sessionId, messageId, pool) {
144
+ // 检查是否有相关的观察记录被标记
145
+ const result = await pool.query(`
146
+ SELECT COUNT(*) as count
147
+ FROM observations o
148
+ JOIN semantic_cache sc ON o.session_id = sc.session_id
149
+ WHERE o.session_id = $1
150
+ AND o.message_id = $2
151
+ AND sc.is_pruned = TRUE
152
+ `, [sessionId, messageId]);
153
+ return parseInt(result.rows[0].count, 10) > 0;
154
+ }
155
+ /**
156
+ * 获取会话的压缩统计
157
+ */
158
+ async function getCompactionStats(sessionId, pool) {
159
+ const sessionResult = await pool.query('SELECT id FROM session_map WHERE opencode_session_id = $1', [sessionId]);
160
+ if (sessionResult.rows.length === 0) {
161
+ return {
162
+ totalObservations: 0,
163
+ prunedCacheEntries: 0,
164
+ highImportanceObservations: 0
165
+ };
166
+ }
167
+ const internalId = sessionResult.rows[0].id;
168
+ const [obsResult, cacheResult, highImportanceResult] = await Promise.all([
169
+ pool.query('SELECT COUNT(*) as count FROM observations WHERE session_id = $1', [internalId]),
170
+ pool.query('SELECT COUNT(*) as count FROM semantic_cache WHERE session_id = $1 AND is_pruned = TRUE', [internalId]),
171
+ pool.query('SELECT COUNT(*) as count FROM observations WHERE session_id = $1 AND importance >= 4', [internalId])
172
+ ]);
173
+ return {
174
+ totalObservations: parseInt(obsResult.rows[0].count, 10),
175
+ prunedCacheEntries: parseInt(cacheResult.rows[0].count, 10),
176
+ highImportanceObservations: parseInt(highImportanceResult.rows[0].count, 10)
177
+ };
178
+ }
179
+ //# sourceMappingURL=session-compacting.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-compacting.js","sourceRoot":"","sources":["../../../src/hooks/session-compacting.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,337 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handleSessionCompleted = handleSessionCompleted;
4
+ exports.getPendingReflections = getPendingReflections;
5
+ exports.retryFailedReflections = retryFailedReflections;
6
+ const logger_1 = require("../services/logger");
7
+ const logger = (0, logger_1.createLogger)('session-completed');
8
+ const DEFAULT_CONFIG = {
9
+ reflectionThreshold: 30, // 基础阈值
10
+ minObservationThreshold: 30,
11
+ maxObservationThreshold: 50,
12
+ enableReflection: true,
13
+ offPeakHours: [1, 2, 3, 4, 5] // 凌晨 1-5 点
14
+ };
15
+ /**
16
+ * 处理 session.completed 事件
17
+ *
18
+ * 功能:
19
+ * 1. 异步触发 hindsight_reflect 反思任务
20
+ * 2. 检查 observations 数量是否达到阈值 (30-50条)
21
+ * 3. 更新 sessions.reflection_last_at
22
+ * 4. 使用 7B 蒸馏模型在低峰期执行
23
+ *
24
+ * 签名规范:(input, output) => Promise<void>
25
+ */
26
+ async function handleSessionCompleted(input, output, // ✅ 添加 output 参数
27
+ pool, config = {}) {
28
+ const mergedConfig = { ...DEFAULT_CONFIG, ...config };
29
+ const { session, summary } = input;
30
+ logger.info(`Session completed: ${session.id}, messages: ${session.messageCount}, duration: ${session.durationMs}ms`);
31
+ try {
32
+ // 获取 session 内部 ID
33
+ const sessionResult = await pool.query('SELECT id, reflection_last_at FROM session_map WHERE opencode_session_id = $1', [session.id]);
34
+ if (sessionResult.rows.length === 0) {
35
+ logger.warn(`Session not found: ${session.id}`);
36
+ return; // ✅ 返回 void
37
+ }
38
+ const sessionInternalId = sessionResult.rows[0].id;
39
+ const reflectionLastAt = sessionResult.rows[0].reflection_last_at;
40
+ // 1. 统计本次会话的观察数量
41
+ const observationStats = await getObservationStats(sessionInternalId, reflectionLastAt, pool);
42
+ logger.info(`Observations since last reflection: ${observationStats.countSinceLastReflection}`);
43
+ // 2. 检查是否应该触发反思
44
+ const shouldReflect = await checkShouldTriggerReflection(sessionInternalId, observationStats.countSinceLastReflection, mergedConfig, pool);
45
+ if (shouldReflect && mergedConfig.enableReflection) {
46
+ // 3. 调度反思任务
47
+ await scheduleReflectionTask(sessionInternalId, session.id, observationStats.countSinceLastReflection, mergedConfig, pool);
48
+ }
49
+ // 4. 记录会话完成
50
+ await pool.query(`
51
+ UPDATE session_map
52
+ SET updated_at = NOW(),
53
+ metadata = metadata || $1
54
+ WHERE id = $2
55
+ `, [
56
+ JSON.stringify({
57
+ lastSessionSummary: summary,
58
+ messageCount: session.messageCount,
59
+ durationMs: session.durationMs,
60
+ reflectionTriggered: shouldReflect
61
+ }),
62
+ sessionInternalId
63
+ ]);
64
+ // 5. 记录 token 使用
65
+ await pool.query(`
66
+ INSERT INTO token_usage_log (session_id, operation_type, tokens_used, metadata)
67
+ VALUES ($1, $2, $3, $4)
68
+ `, [
69
+ sessionInternalId,
70
+ 'session_completion',
71
+ 0,
72
+ JSON.stringify({
73
+ messageCount: session.messageCount,
74
+ durationMs: session.durationMs,
75
+ observationCount: observationStats.totalCount
76
+ })
77
+ ]);
78
+ logger.info(`Session completion processed: ${session.id}`);
79
+ // ✅ 正确的钩子签名:不返回任何值
80
+ }
81
+ catch (error) {
82
+ logger.error('Error handling session.completed:', error);
83
+ // 出错时不阻断主流程
84
+ }
85
+ }
86
+ /**
87
+ * 获取观察统计
88
+ */
89
+ async function getObservationStats(sessionId, reflectionLastAt, pool) {
90
+ // 总观察数
91
+ const totalResult = await pool.query('SELECT COUNT(*) as count FROM observations WHERE session_id = $1', [sessionId]);
92
+ const totalCount = parseInt(totalResult.rows[0].count, 10);
93
+ // 上次反思后的观察数
94
+ let countSinceLastReflection = totalCount;
95
+ if (reflectionLastAt) {
96
+ const sinceResult = await pool.query(`
97
+ SELECT COUNT(*) as count
98
+ FROM observations
99
+ WHERE session_id = $1 AND created_at > $2
100
+ `, [sessionId, reflectionLastAt]);
101
+ countSinceLastReflection = parseInt(sinceResult.rows[0].count, 10);
102
+ }
103
+ return { totalCount, countSinceLastReflection };
104
+ }
105
+ /**
106
+ * 检查是否应该触发反思
107
+ */
108
+ async function checkShouldTriggerReflection(sessionId, observationCount, config, pool) {
109
+ if (!config.enableReflection) {
110
+ return false;
111
+ }
112
+ // 随机阈值:30-50 条经验
113
+ const threshold = Math.floor(Math.random() * (config.maxObservationThreshold - config.minObservationThreshold + 1)) + config.minObservationThreshold;
114
+ logger.info(`Reflection threshold: ${threshold}, current: ${observationCount}`);
115
+ if (observationCount < threshold) {
116
+ return false;
117
+ }
118
+ // 检查是否有正在进行的反思任务
119
+ const pendingResult = await pool.query(`
120
+ SELECT COUNT(*) as count
121
+ FROM reflections
122
+ WHERE session_id = $1 AND created_at > NOW() - INTERVAL '1 hour'
123
+ `, [sessionId]);
124
+ const pendingCount = parseInt(pendingResult.rows[0].count, 10);
125
+ if (pendingCount > 0) {
126
+ logger.info(`Reflection already in progress for session: ${sessionId}`);
127
+ return false;
128
+ }
129
+ return true;
130
+ }
131
+ /**
132
+ * 调度反思任务
133
+ */
134
+ async function scheduleReflectionTask(sessionInternalId, externalSessionId, observationCount, config, pool) {
135
+ const currentHour = new Date().getHours();
136
+ const isOffPeak = config.offPeakHours.includes(currentHour);
137
+ logger.info(`Scheduling reflection task for session: ${externalSessionId}, off-peak: ${isOffPeak}`);
138
+ if (isOffPeak) {
139
+ // 低峰期:立即执行
140
+ await executeReflection(sessionInternalId, externalSessionId, observationCount, pool);
141
+ }
142
+ else {
143
+ // 非低峰期:延迟到下一个低峰期
144
+ await queueReflectionForOffPeak(sessionInternalId, externalSessionId, observationCount, pool);
145
+ }
146
+ }
147
+ /**
148
+ * 执行反思任务
149
+ */
150
+ async function executeReflection(sessionId, externalSessionId, observationCount, pool) {
151
+ logger.info(`Executing reflection for session: ${externalSessionId}`);
152
+ try {
153
+ // 1. 获取待反思的观察记录
154
+ const observations = await pool.query(`
155
+ SELECT id, tool_name, tool_input_summary, tool_output_summary,
156
+ importance, created_at, metadata
157
+ FROM observations
158
+ WHERE session_id = $1
159
+ ORDER BY importance DESC, created_at DESC
160
+ LIMIT 100
161
+ `, [sessionId]);
162
+ if (observations.rows.length === 0) {
163
+ logger.info(`No observations to reflect on for session: ${externalSessionId}`);
164
+ return;
165
+ }
166
+ // 2. 调用 LLM 进行反思(简化版)
167
+ const reflectionResult = await performReflection(observations.rows);
168
+ // 3. 存储反思结果
169
+ for (const pattern of reflectionResult.patterns) {
170
+ if (pattern.confidence >= 0.6) {
171
+ await pool.query(`
172
+ INSERT INTO reflections (
173
+ session_id, summary, source_observation_ids,
174
+ confidence, pattern_type, metadata
175
+ ) VALUES ($1, $2, $3, $4, $5, $6)
176
+ `, [
177
+ sessionId,
178
+ pattern.description,
179
+ pattern.sourceObservationIds,
180
+ pattern.confidence,
181
+ pattern.patternType,
182
+ JSON.stringify({
183
+ generatedAt: new Date().toISOString(),
184
+ modelSize: '7b',
185
+ observationCount: observations.rows.length
186
+ })
187
+ ]);
188
+ }
189
+ }
190
+ // 4. 更新会话的 reflection_last_at
191
+ await pool.query(`
192
+ UPDATE session_map
193
+ SET reflection_last_at = NOW()
194
+ WHERE id = $1
195
+ `, [sessionId]);
196
+ logger.info(`Reflection completed for session: ${externalSessionId}, patterns: ${reflectionResult.patterns.length}`);
197
+ }
198
+ catch (error) {
199
+ logger.error(`Reflection failed for session: ${externalSessionId}`, error);
200
+ // 记录反思错误
201
+ await pool.query(`
202
+ INSERT INTO reflection_errors (
203
+ session_id, error_message, error_stack,
204
+ observation_count, retry_count
205
+ ) VALUES ($1, $2, $3, $4, $5)
206
+ `, [
207
+ sessionId,
208
+ error instanceof Error ? error.message : 'Unknown error',
209
+ error instanceof Error ? error.stack : '',
210
+ observationCount,
211
+ 0
212
+ ]);
213
+ }
214
+ }
215
+ /**
216
+ * 执行反思(简化版)
217
+ *
218
+ * 注意:实际应调用 LLM API,使用 REFLECTION_SYSTEM_PROMPT
219
+ */
220
+ async function performReflection(observations) {
221
+ // 简化版:基于规则的模式识别
222
+ // 实际应调用 7B 蒸馏模型
223
+ const patterns = [];
224
+ // 错误模式检测
225
+ const errorObservations = observations.filter(obs => obs.tool_output_summary?.toLowerCase().includes('error') ||
226
+ obs.importance >= 4);
227
+ if (errorObservations.length >= 3) {
228
+ patterns.push({
229
+ patternType: 'error_pattern',
230
+ description: `Detected ${errorObservations.length} error-related observations. Common issues may need attention.`,
231
+ confidence: 0.7,
232
+ sourceObservationIds: errorObservations.map(obs => obs.id).slice(0, 10)
233
+ });
234
+ }
235
+ // 高频工具使用模式
236
+ const toolUsage = {};
237
+ for (const obs of observations) {
238
+ if (obs.tool_name) {
239
+ toolUsage[obs.tool_name] = (toolUsage[obs.tool_name] || 0) + 1;
240
+ }
241
+ }
242
+ const frequentTools = Object.entries(toolUsage)
243
+ .filter(([_, count]) => count >= 5)
244
+ .sort((a, b) => b[1] - a[1]);
245
+ if (frequentTools.length > 0) {
246
+ patterns.push({
247
+ patternType: 'tool_preference',
248
+ description: `Frequently used tools: ${frequentTools.map(([name, count]) => `${name}(${count})`).join(', ')}`,
249
+ confidence: 0.8,
250
+ sourceObservationIds: observations
251
+ .filter(obs => obs.tool_name === frequentTools[0][0])
252
+ .map(obs => obs.id)
253
+ .slice(0, 10)
254
+ });
255
+ }
256
+ // 成功模式检测
257
+ const successObservations = observations.filter(obs => obs.tool_output_summary?.toLowerCase().includes('success') ||
258
+ obs.tool_output_summary?.toLowerCase().includes('completed'));
259
+ if (successObservations.length >= 5) {
260
+ patterns.push({
261
+ patternType: 'success_pattern',
262
+ description: `Session showed ${successObservations.length} successful operations.`,
263
+ confidence: 0.75,
264
+ sourceObservationIds: successObservations.map(obs => obs.id).slice(0, 10)
265
+ });
266
+ }
267
+ return { patterns };
268
+ }
269
+ /**
270
+ * 将反思任务排队到低峰期执行
271
+ */
272
+ async function queueReflectionForOffPeak(sessionId, externalSessionId, observationCount, pool) {
273
+ logger.info(`Queued reflection for off-peak execution: ${externalSessionId}`);
274
+ // 存储队列信息到 metadata
275
+ await pool.query(`
276
+ UPDATE session_map
277
+ SET metadata = metadata || $1
278
+ WHERE id = $2
279
+ `, [
280
+ JSON.stringify({
281
+ pendingReflection: {
282
+ queuedAt: new Date().toISOString(),
283
+ observationCount
284
+ }
285
+ }),
286
+ sessionId
287
+ ]);
288
+ }
289
+ /**
290
+ * 获取反思队列(供定时任务调用)
291
+ */
292
+ async function getPendingReflections(pool) {
293
+ const result = await pool.query(`
294
+ SELECT
295
+ s.id as session_id,
296
+ s.opencode_session_id as external_session_id,
297
+ (s.metadata->'pendingReflection'->>'observationCount')::int as observation_count,
298
+ (s.metadata->'pendingReflection'->>'queuedAt')::timestamptz as queued_at
299
+ FROM session_map s
300
+ WHERE s.metadata->'pendingReflection' IS NOT NULL
301
+ AND s.reflection_last_at < (s.metadata->'pendingReflection'->>'queuedAt')::timestamptz
302
+ OR s.reflection_last_at IS NULL
303
+ `);
304
+ return result.rows.map(row => ({
305
+ sessionId: row.session_id,
306
+ externalSessionId: row.external_session_id,
307
+ observationCount: row.observation_count,
308
+ queuedAt: row.queued_at
309
+ }));
310
+ }
311
+ /**
312
+ * 处理反思错误重试
313
+ */
314
+ async function retryFailedReflections(pool, maxRetries = 3) {
315
+ const failedReflections = await pool.query(`
316
+ SELECT * FROM reflection_errors
317
+ WHERE retry_count < $1
318
+ AND created_at > NOW() - INTERVAL '24 hours'
319
+ ORDER BY created_at DESC
320
+ LIMIT 10
321
+ `, [maxRetries]);
322
+ for (const error of failedReflections.rows) {
323
+ logger.info(`Retrying reflection for session: ${error.session_id}`);
324
+ // 增加重试计数
325
+ await pool.query(`
326
+ UPDATE reflection_errors
327
+ SET retry_count = retry_count + 1
328
+ WHERE id = $1
329
+ `, [error.id]);
330
+ // 重新执行反思
331
+ const sessionResult = await pool.query('SELECT opencode_session_id FROM session_map WHERE id = $1', [error.session_id]);
332
+ if (sessionResult.rows.length > 0) {
333
+ await executeReflection(error.session_id, sessionResult.rows[0].opencode_session_id, error.observation_count, pool);
334
+ }
335
+ }
336
+ }
337
+ //# sourceMappingURL=session-completed.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-completed.js","sourceRoot":"","sources":["../../../src/hooks/session-completed.ts"],"names":[],"mappings":"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"}