principles-disciple 1.65.0 → 1.67.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/ADVANCED_CONFIG_ZH.md +0 -4
- package/README.md +0 -11
- package/openclaw.plugin.json +1 -25
- package/package.json +1 -1
- package/src/commands/context.ts +6 -14
- package/src/commands/evolution-status.ts +29 -3
- package/src/commands/pain.ts +3 -4
- package/src/config/defaults/runtime.ts +0 -2
- package/src/constants/tools.ts +0 -1
- package/src/core/config.ts +0 -30
- package/src/core/event-log.ts +4 -12
- package/src/hooks/prompt.ts +3 -35
- package/src/hooks/subagent.ts +0 -7
- package/src/index.ts +0 -2
- package/src/service/evolution-worker.ts +0 -13
- package/src/service/runtime-summary-service.ts +94 -15
- package/src/service/subagent-workflow/deep-reflect-workflow-manager.ts +1 -204
- package/src/service/subagent-workflow/index.ts +0 -8
- package/src/service/subagent-workflow/types.ts +0 -11
- package/src/service/subagent-workflow/workflow-manager-base.ts +1 -1
- package/src/tools/critique-prompt.ts +1 -97
- package/src/tools/deep-reflect.ts +1 -337
- package/src/tools/model-index.ts +1 -100
- package/src/types/event-payload.ts +0 -6
- package/src/types/event-types.ts +0 -86
- package/src/types.ts +0 -21
- package/templates/langs/en/core/TOOLS.md +0 -43
- package/templates/langs/zh/core/TOOLS.md +0 -43
- package/templates/pain_settings.json +0 -21
- package/tests/commands/evolution-status.test.ts +288 -0
- package/tests/core/event-log.test.ts +1 -29
- package/tests/service/runtime-summary-service.test.ts +1 -1
|
@@ -6,6 +6,7 @@ import { WorkspaceContext } from '../core/workspace-context.js';
|
|
|
6
6
|
import { evaluatePhase3Inputs } from './phase3-input-filter.js';
|
|
7
7
|
import { TrajectoryRegistry } from '../core/trajectory.js';
|
|
8
8
|
import { getPendingDiagnosticianTasks } from '../core/diagnostician-task-store.js';
|
|
9
|
+
import type { WorkflowStage } from '../core/workflow-funnel-loader.js';
|
|
9
10
|
import type { RuntimeTruth, AnalyticsTruth } from '../types/runtime-summary.js';
|
|
10
11
|
|
|
11
12
|
export type RuntimeDataQuality = 'authoritative' | 'partial';
|
|
@@ -106,11 +107,15 @@ export interface RuntimeSummary {
|
|
|
106
107
|
recentBypasses: number | null;
|
|
107
108
|
dataQuality: RuntimeDataQuality;
|
|
108
109
|
};
|
|
110
|
+
/** YAML-driven funnel counts — only present when funnels param is provided (YAML-SSOT-01) */
|
|
111
|
+
workflowFunnels?: WorkflowFunnelOutput[];
|
|
109
112
|
metadata: {
|
|
110
113
|
generatedAt: string;
|
|
111
114
|
workspaceDir: string;
|
|
112
115
|
sessionId: string | null;
|
|
113
116
|
selectedSessionReason: 'explicit' | 'latest_active' | 'none';
|
|
117
|
+
/** 'degraded' when YAML load errors or unresolved statsField paths exist; 'ok' otherwise */
|
|
118
|
+
status: 'ok' | 'degraded';
|
|
114
119
|
warnings: string[];
|
|
115
120
|
};
|
|
116
121
|
}
|
|
@@ -153,6 +158,23 @@ interface EventLogEntry {
|
|
|
153
158
|
data?: Record<string, unknown>;
|
|
154
159
|
}
|
|
155
160
|
|
|
161
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
162
|
+
// Workflow Funnel Types (YAML-SSOT-01 / YAML-SSOT-02)
|
|
163
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
164
|
+
|
|
165
|
+
export interface WorkflowFunnelStageOutput {
|
|
166
|
+
key: string;
|
|
167
|
+
label: string;
|
|
168
|
+
statsField: string;
|
|
169
|
+
count: number;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
export interface WorkflowFunnelOutput {
|
|
173
|
+
funnelKey: string;
|
|
174
|
+
funnelLabel: string;
|
|
175
|
+
stages: WorkflowFunnelStageOutput[];
|
|
176
|
+
}
|
|
177
|
+
|
|
156
178
|
const MAX_SOURCE_EVENTS = 5;
|
|
157
179
|
const GFI_PARTIAL_WARNING =
|
|
158
180
|
'GFI source attribution remains partial in Phase 2b because only the empathy slice is source-attributed; most non-empathy friction still lacks full per-source attribution.';
|
|
@@ -167,17 +189,30 @@ function pushWarning(warnings: string[], message: string): void {
|
|
|
167
189
|
}
|
|
168
190
|
}
|
|
169
191
|
|
|
192
|
+
/**
|
|
193
|
+
* YAML-SSOT-03: resolve a dot-path (e.g. 'evolution.nocturnalDreamerCompleted') from dailyStats.
|
|
194
|
+
* Returns { count, resolvable } to distinguish "field not found / non-numeric" from "legitimate zero".
|
|
195
|
+
*/
|
|
196
|
+
function resolveStatsField(stats: unknown, dotPath: string): { count: number; resolvable: boolean } {
|
|
197
|
+
const parts = dotPath.split('.');
|
|
198
|
+
let current: unknown = stats;
|
|
199
|
+
for (const part of parts) {
|
|
200
|
+
if (current == null || typeof current !== 'object') return { count: 0, resolvable: false };
|
|
201
|
+
current = (current as Record<string, unknown>)[part];
|
|
202
|
+
}
|
|
203
|
+
if (typeof current === 'number') {
|
|
204
|
+
return { count: current, resolvable: true };
|
|
205
|
+
}
|
|
206
|
+
return { count: 0, resolvable: false };
|
|
207
|
+
}
|
|
208
|
+
|
|
170
209
|
export class RuntimeSummaryService {
|
|
171
210
|
static getSummary(
|
|
172
211
|
workspaceDir: string,
|
|
173
|
-
options?: { sessionId?: string | null; loaderWarnings?: string[] }
|
|
212
|
+
options?: { sessionId?: string | null; loaderWarnings?: string[]; funnels?: Map<string, WorkflowStage[]> }
|
|
174
213
|
): RuntimeSummary {
|
|
175
214
|
const generatedAt = new Date().toISOString();
|
|
176
215
|
const warnings: string[] = [];
|
|
177
|
-
// ERR-01: surface loader warnings (YAML parse failures) into metadata.warnings
|
|
178
|
-
if (options?.loaderWarnings) {
|
|
179
|
-
warnings.push(...options.loaderWarnings);
|
|
180
|
-
}
|
|
181
216
|
const wctx = WorkspaceContext.fromHookContext({ workspaceDir });
|
|
182
217
|
|
|
183
218
|
const sessions = this.mergeSessionSnapshots(
|
|
@@ -215,11 +250,54 @@ export class RuntimeSummaryService {
|
|
|
215
250
|
false
|
|
216
251
|
);
|
|
217
252
|
|
|
218
|
-
//
|
|
219
|
-
|
|
220
|
-
const
|
|
221
|
-
|
|
222
|
-
|
|
253
|
+
// Unified date for all "today"-scope reads in this summary — ensures funnel counts,
|
|
254
|
+
// heartbeat stats, and dailyStats all agree on the same date and never contradict.
|
|
255
|
+
const todayStr = generatedAt.slice(0, 10);
|
|
256
|
+
|
|
257
|
+
// YAML-SSOT-02/03: build workflowFunnels from funnels Map if provided
|
|
258
|
+
let workflowFunnelsOutput: WorkflowFunnelOutput[] | undefined;
|
|
259
|
+
if (options?.funnels) {
|
|
260
|
+
workflowFunnelsOutput = [];
|
|
261
|
+
for (const [funnelKey, stages] of options.funnels) {
|
|
262
|
+
const stageOutputs: WorkflowFunnelStageOutput[] = stages.map(stage => {
|
|
263
|
+
const { count, resolvable } = resolveStatsField(dailyStats?.[todayStr], stage.statsField);
|
|
264
|
+
return {
|
|
265
|
+
key: stage.name,
|
|
266
|
+
label: stage.name,
|
|
267
|
+
statsField: stage.statsField,
|
|
268
|
+
count,
|
|
269
|
+
_resolvable: resolvable, // internal tag for degraded detection
|
|
270
|
+
};
|
|
271
|
+
});
|
|
272
|
+
workflowFunnelsOutput.push({ funnelKey, funnelLabel: funnelKey, stages: stageOutputs });
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// YAML-SSOT-04: warn for any unresolvable statsField paths
|
|
277
|
+
let hasUnresolvableStage = false;
|
|
278
|
+
if (workflowFunnelsOutput) {
|
|
279
|
+
for (const funnel of workflowFunnelsOutput) {
|
|
280
|
+
for (const stage of funnel.stages) {
|
|
281
|
+
if (!(stage as { _resolvable?: boolean })._resolvable) {
|
|
282
|
+
hasUnresolvableStage = true;
|
|
283
|
+
pushWarning(warnings, `statsField not resolvable: ${stage.statsField}`);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// DEGRADED-01/02: status is degraded when YAML load errors or unresolvable statsField paths exist
|
|
290
|
+
const loaderWarnings = options?.loaderWarnings ?? [];
|
|
291
|
+
if (loaderWarnings.length > 0) {
|
|
292
|
+
for (const w of loaderWarnings) {
|
|
293
|
+
pushWarning(warnings, `YAML load warning: ${w}`);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
const status: 'ok' | 'degraded' =
|
|
297
|
+
(loaderWarnings.length > 0 || hasUnresolvableStage) ? 'degraded' : 'ok';
|
|
298
|
+
|
|
299
|
+
// GFI peak — use today's data (consistent with funnel/heartbeat)
|
|
300
|
+
const dailyGfiPeak = dailyStats?.[todayStr]?.gfi?.peak;
|
|
223
301
|
|
|
224
302
|
const gfiCurrent =
|
|
225
303
|
selectedSession.session && Number.isFinite(selectedSession.session.currentGfi)
|
|
@@ -269,7 +347,6 @@ export class RuntimeSummaryService {
|
|
|
269
347
|
// Read pending tasks from the diagnostician task store
|
|
270
348
|
const pendingDiagTasks = getPendingDiagnosticianTasks(wctx.stateDir);
|
|
271
349
|
// Read heartbeat diagnosis stats from daily event log
|
|
272
|
-
const todayStr = generatedAt.slice(0, 10);
|
|
273
350
|
const diagDailyStats = dailyStats?.[todayStr]?.evolution;
|
|
274
351
|
const heartbeatDiagnosis = {
|
|
275
352
|
pendingTasks: pendingDiagTasks.length,
|
|
@@ -310,10 +387,10 @@ export class RuntimeSummaryService {
|
|
|
310
387
|
lastUpdated: trajectoryStats.lastIngestAt ?? generatedAt,
|
|
311
388
|
},
|
|
312
389
|
dailyStats: {
|
|
313
|
-
toolCalls: dailyStats?.[
|
|
314
|
-
painSignals: dailyStats?.[
|
|
315
|
-
evolutionTasks: dailyStats?.[
|
|
316
|
-
lastUpdated:
|
|
390
|
+
toolCalls: dailyStats?.[todayStr]?.toolCalls ?? 0,
|
|
391
|
+
painSignals: dailyStats?.[todayStr]?.painSignals ?? 0,
|
|
392
|
+
evolutionTasks: dailyStats?.[todayStr]?.evolutionTasks ?? 0,
|
|
393
|
+
lastUpdated: todayStr,
|
|
317
394
|
},
|
|
318
395
|
trends: {
|
|
319
396
|
sevenDay: { successRateChange: 0, toolCallVolumeChange: 0, painSignalRateChange: 0 },
|
|
@@ -360,11 +437,13 @@ export class RuntimeSummaryService {
|
|
|
360
437
|
gate: gateStats,
|
|
361
438
|
// D: Heartbeat Diagnostician chain — separate from evolution/nocturnal
|
|
362
439
|
heartbeatDiagnosis,
|
|
440
|
+
...(workflowFunnelsOutput && { workflowFunnels: workflowFunnelsOutput }),
|
|
363
441
|
metadata: {
|
|
364
442
|
generatedAt,
|
|
365
443
|
workspaceDir,
|
|
366
444
|
sessionId: selectedSessionId,
|
|
367
445
|
selectedSessionReason: selectedSession.reason,
|
|
446
|
+
status,
|
|
368
447
|
warnings,
|
|
369
448
|
},
|
|
370
449
|
};
|
|
@@ -1,204 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import type {
|
|
3
|
-
SubagentWorkflowSpec,
|
|
4
|
-
DeepReflectResult,
|
|
5
|
-
WorkflowResultContext,
|
|
6
|
-
WorkflowPersistContext,
|
|
7
|
-
WorkflowHandle,
|
|
8
|
-
} from './types.js';
|
|
9
|
-
|
|
10
|
-
// Re-export DeepReflectResult so index.ts can re-export it
|
|
11
|
-
export type { DeepReflectResult } from './types.js';
|
|
12
|
-
import type { RuntimeDirectDriver } from './runtime-direct-driver.js';
|
|
13
|
-
import { isSubagentRuntimeAvailable } from '../../utils/subagent-probe.js';
|
|
14
|
-
import { buildCritiquePromptV2 } from '../../tools/critique-prompt.js';
|
|
15
|
-
import { WorkflowManagerBase } from './workflow-manager-base.js';
|
|
16
|
-
import { DEEP_REFLECT_TTL_MS } from '../../config/defaults/runtime.js';
|
|
17
|
-
|
|
18
|
-
const WORKFLOW_SESSION_PREFIX = 'agent:main:subagent:workflow-';
|
|
19
|
-
|
|
20
|
-
const DEFAULT_TIMEOUT_MS = 60_000; // Deep-reflect needs more time than empathy
|
|
21
|
-
|
|
22
|
-
export interface DeepReflectWorkflowOptions {
|
|
23
|
-
workspaceDir: string;
|
|
24
|
-
logger: PluginLogger;
|
|
25
|
-
subagent: RuntimeDirectDriver['subagent'];
|
|
26
|
-
/** Pass api.runtime.agent.session to enable heartbeat-safe cleanup (#188) */
|
|
27
|
-
agentSession?: RuntimeDirectDriver['agentSession'];
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export class DeepReflectWorkflowManager extends WorkflowManagerBase {
|
|
31
|
-
constructor(opts: DeepReflectWorkflowOptions) {
|
|
32
|
-
super({
|
|
33
|
-
workspaceDir: opts.workspaceDir,
|
|
34
|
-
logger: opts.logger,
|
|
35
|
-
subagent: opts.subagent,
|
|
36
|
-
agentSession: opts.agentSession,
|
|
37
|
-
workflowType: 'deep-reflect',
|
|
38
|
-
sessionPrefix: WORKFLOW_SESSION_PREFIX,
|
|
39
|
-
defaultTimeoutMs: DEFAULT_TIMEOUT_MS,
|
|
40
|
-
defaultTtlMs: DEEP_REFLECT_TTL_MS,
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
async startWorkflow<TResult>(
|
|
45
|
-
spec: SubagentWorkflowSpec<TResult>,
|
|
46
|
-
options: {
|
|
47
|
-
parentSessionId: string;
|
|
48
|
-
workspaceDir?: string;
|
|
49
|
-
taskInput: unknown;
|
|
50
|
-
metadata?: Record<string, unknown>;
|
|
51
|
-
}
|
|
52
|
-
): Promise<WorkflowHandle> {
|
|
53
|
-
// Surface degrade: skip boot sessions
|
|
54
|
-
if (options.parentSessionId.startsWith('boot-')) {
|
|
55
|
-
this.logger.info(`[PD:DeepReflectWorkflow] Skipping workflow: boot session`);
|
|
56
|
-
throw new Error(`DeepReflectWorkflowManager: cannot start workflow for boot session`);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// Surface degrade: check subagent runtime availability
|
|
60
|
-
if (!isSubagentRuntimeAvailable(this.driver.getSubagent())) {
|
|
61
|
-
this.logger.info(`[PD:DeepReflectWorkflow] Skipping workflow: subagent runtime unavailable`);
|
|
62
|
-
throw new Error(`DeepReflectWorkflowManager: subagent runtime unavailable`);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
if (spec.transport !== 'runtime_direct') {
|
|
66
|
-
throw new Error(`DeepReflectWorkflowManager only supports runtime_direct transport`);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
return super.startWorkflow(spec, options);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
protected override generateWorkflowId(): string {
|
|
75
|
-
return `wf_dr_${Date.now()}_${Math.random().toString(36).substring(2, 10)}`;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// ─── Interfaces ───────────────────────────────────────────────────────────────
|
|
80
|
-
|
|
81
|
-
export interface DeepReflectTaskInput {
|
|
82
|
-
context: string;
|
|
83
|
-
depth: number;
|
|
84
|
-
model_id?: string;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
export interface DeepReflectBuildPromptContext {
|
|
88
|
-
parentSessionId: string;
|
|
89
|
-
workspaceDir?: string;
|
|
90
|
-
taskInput: unknown;
|
|
91
|
-
startedAt: number;
|
|
92
|
-
workflowType: string;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// ─── Workflow Spec ─────────────────────────────────────────────────────────────
|
|
96
|
-
|
|
97
|
-
export const deepReflectWorkflowSpec: SubagentWorkflowSpec<DeepReflectResult> = {
|
|
98
|
-
workflowType: 'deep-reflect',
|
|
99
|
-
transport: 'runtime_direct',
|
|
100
|
-
timeoutMs: 60_000,
|
|
101
|
-
ttlMs: DEEP_REFLECT_TTL_MS,
|
|
102
|
-
shouldDeleteSessionAfterFinalize: true,
|
|
103
|
-
|
|
104
|
-
buildPrompt(taskInput: unknown, ctx: DeepReflectBuildPromptContext): string {
|
|
105
|
-
const input = taskInput as DeepReflectTaskInput;
|
|
106
|
-
// Use the existing critique prompt builder
|
|
107
|
-
return buildCritiquePromptV2({
|
|
108
|
-
context: input.context,
|
|
109
|
-
depth: input.depth,
|
|
110
|
-
model_id: input.model_id,
|
|
111
|
-
api: undefined, // Not available in workflow context
|
|
112
|
-
workspaceDir: ctx.workspaceDir,
|
|
113
|
-
});
|
|
114
|
-
},
|
|
115
|
-
|
|
116
|
-
shouldFinalizeOnWaitStatus(status: 'ok' | 'error' | 'timeout'): boolean {
|
|
117
|
-
return status === 'ok';
|
|
118
|
-
},
|
|
119
|
-
|
|
120
|
-
async parseResult(ctx: WorkflowResultContext): Promise<DeepReflectResult | null> {
|
|
121
|
-
const { assistantTexts, messages } = ctx;
|
|
122
|
-
|
|
123
|
-
let insights = '';
|
|
124
|
-
if (assistantTexts && assistantTexts.length > 0) {
|
|
125
|
-
insights = assistantTexts[assistantTexts.length - 1] || '';
|
|
126
|
-
} else if (messages && messages.length > 0) {
|
|
127
|
-
const lastMessage = messages[messages.length - 1] as { role?: string; content?: unknown };
|
|
128
|
-
if (typeof lastMessage?.content === 'string') {
|
|
129
|
-
insights = lastMessage.content;
|
|
130
|
-
} else if (Array.isArray(lastMessage?.content)) {
|
|
131
|
-
insights = (lastMessage.content as { type?: string; text?: string }[])
|
|
132
|
-
.filter((c) => c?.type === 'text' && typeof c.text === 'string')
|
|
133
|
-
|
|
134
|
-
.map((c) => c.text!)
|
|
135
|
-
.join('\n');
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
if (!insights?.trim()) {
|
|
140
|
-
return null;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
const taskInput = ctx.metadata.taskInput as DeepReflectTaskInput | undefined;
|
|
144
|
-
|
|
145
|
-
return {
|
|
146
|
-
insights,
|
|
147
|
-
context: taskInput?.context ?? '',
|
|
148
|
-
depth: taskInput?.depth ?? 2,
|
|
149
|
-
modelId: taskInput?.model_id ?? 'auto-select',
|
|
150
|
-
passed: !insights.includes('REFLECTION_FAIL'),
|
|
151
|
-
};
|
|
152
|
-
},
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
async persistResult(ctx: WorkflowPersistContext<DeepReflectResult>): Promise<void> {
|
|
156
|
-
const { result, metadata, workspaceDir } = ctx;
|
|
157
|
-
|
|
158
|
-
if (!result || !result.insights) return;
|
|
159
|
-
|
|
160
|
-
try {
|
|
161
|
-
const fs = await import('fs');
|
|
162
|
-
const pathMod = await import('path');
|
|
163
|
-
const { resolvePdPath } = await import('../../core/paths.js');
|
|
164
|
-
|
|
165
|
-
const reflectionLogPath = resolvePdPath(workspaceDir, 'REFLECTION_LOG');
|
|
166
|
-
const memoryDir = pathMod.default.dirname(reflectionLogPath);
|
|
167
|
-
if (!fs.default.existsSync(memoryDir)) {
|
|
168
|
-
fs.default.mkdirSync(memoryDir, { recursive: true });
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
const timestamp = new Date().toISOString();
|
|
172
|
-
const taskInput = metadata.taskInput as DeepReflectTaskInput | undefined;
|
|
173
|
-
const entry = `
|
|
174
|
-
---
|
|
175
|
-
## Reflection at ${timestamp}
|
|
176
|
-
**Model**: ${result.modelId || 'auto-select'}
|
|
177
|
-
**Depth**: ${result.depth || 2}
|
|
178
|
-
|
|
179
|
-
### Context
|
|
180
|
-
${(taskInput?.context ?? '').substring(0, 500)}${(taskInput?.context ?? '').length > 500 ? '...' : ''}
|
|
181
|
-
|
|
182
|
-
### Insights
|
|
183
|
-
${result.insights}
|
|
184
|
-
|
|
185
|
-
`;
|
|
186
|
-
|
|
187
|
-
const header = `# Reflection Log\n\n> Auto-generated by Deep Reflection Tool\n> Retention: 30 days\n`;
|
|
188
|
-
|
|
189
|
-
let existingContent = '';
|
|
190
|
-
if (fs.default.existsSync(reflectionLogPath)) {
|
|
191
|
-
existingContent = fs.default.readFileSync(reflectionLogPath, 'utf8');
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
const newContent = header + entry + existingContent.replace(header, '');
|
|
195
|
-
|
|
196
|
-
const tempPath = `${reflectionLogPath}.tmp`;
|
|
197
|
-
fs.default.writeFileSync(tempPath, newContent, 'utf8');
|
|
198
|
-
fs.default.renameSync(tempPath, reflectionLogPath);
|
|
199
|
-
} catch (err) {
|
|
200
|
-
// Let the error propagate to finalizeOnce for proper event logging
|
|
201
|
-
throw new Error(`DeepReflectWorkflow persistResult failed: ${String(err)}`, { cause: err });
|
|
202
|
-
}
|
|
203
|
-
},
|
|
204
|
-
};
|
|
1
|
+
export {};
|
|
@@ -21,14 +21,6 @@ export {
|
|
|
21
21
|
type EmpathyObserverWorkflowOptions,
|
|
22
22
|
} from './empathy-observer-workflow-manager.js';
|
|
23
23
|
|
|
24
|
-
export {
|
|
25
|
-
DeepReflectWorkflowManager,
|
|
26
|
-
deepReflectWorkflowSpec,
|
|
27
|
-
type DeepReflectWorkflowOptions,
|
|
28
|
-
type DeepReflectTaskInput,
|
|
29
|
-
type DeepReflectResult,
|
|
30
|
-
} from './deep-reflect-workflow-manager.js';
|
|
31
|
-
|
|
32
24
|
export {
|
|
33
25
|
NocturnalWorkflowManager,
|
|
34
26
|
nocturnalWorkflowSpec,
|
|
@@ -204,17 +204,6 @@ export interface EmpathyResult {
|
|
|
204
204
|
painScore: number;
|
|
205
205
|
}
|
|
206
206
|
|
|
207
|
-
/**
|
|
208
|
-
* Deep-reflect workflow result.
|
|
209
|
-
*/
|
|
210
|
-
export interface DeepReflectResult {
|
|
211
|
-
insights: string;
|
|
212
|
-
context: string;
|
|
213
|
-
depth: number;
|
|
214
|
-
modelId: string;
|
|
215
|
-
passed: boolean;
|
|
216
|
-
}
|
|
217
|
-
|
|
218
207
|
/**
|
|
219
208
|
* Empathy observer workflow specification.
|
|
220
209
|
* This is the concrete spec for PR2 migration.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* WorkflowManagerBase - Shared base class for polling-based workflow managers
|
|
3
3
|
*
|
|
4
4
|
* Extracts common lifecycle, state transitions, and store operations from
|
|
5
|
-
* EmpathyObserverWorkflowManager
|
|
5
|
+
* EmpathyObserverWorkflowManager.
|
|
6
6
|
*
|
|
7
7
|
* Both managers implement the same polling-based workflow lifecycle:
|
|
8
8
|
* startWorkflow → driver.run() → store.createWorkflow → scheduleWaitPollWithRetry
|
|
@@ -1,97 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { loadModelIndex } from './model-index.js';
|
|
3
|
-
import { resolveWorkspaceDirFromApi } from '../core/path-resolver.js';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* 深度指令模板 (必须与测试用例中的 quick/balanced/thorough 关键字对齐)
|
|
7
|
-
*/
|
|
8
|
-
const DEPTH_INSTRUCTIONS = {
|
|
9
|
-
1: 'Provide a quick surface-level analysis.',
|
|
10
|
-
2: 'Provide a balanced analysis with moderate depth.',
|
|
11
|
-
3: 'Provide an extremely thorough and exhaustive analysis.',
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* 构建反思提示词 (Critique Prompt) V2
|
|
16
|
-
*
|
|
17
|
-
* 严格按照测试用例的调用习惯和断言要求进行重写。
|
|
18
|
-
* 增加 OpenClaw 兼容性路径解析。
|
|
19
|
-
*/
|
|
20
|
-
|
|
21
|
-
export function buildCritiquePromptV2(
|
|
22
|
-
params: {
|
|
23
|
-
context: string;
|
|
24
|
-
depth?: number;
|
|
25
|
-
model_id?: string;
|
|
26
|
-
workspaceDir?: string;
|
|
27
|
-
api?: OpenClawPluginApi;
|
|
28
|
-
}
|
|
29
|
-
): string {
|
|
30
|
-
const { context, depth = 2, workspaceDir, api } = params;
|
|
31
|
-
|
|
32
|
-
// FIX (B): Priority: explicitly passed workspaceDir > official API resolution
|
|
33
|
-
// Do NOT chain through api.config?.workspaceDir which may be stale.
|
|
34
|
-
const effectiveWorkspaceDir = workspaceDir || resolveWorkspaceDirFromApi(api);
|
|
35
|
-
|
|
36
|
-
if (!effectiveWorkspaceDir) {
|
|
37
|
-
throw new Error('Workspace directory is required for deep reflection.');
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// 2. 深度校验与警告日志
|
|
41
|
-
let validatedDepth = 2;
|
|
42
|
-
if (typeof depth === 'number') {
|
|
43
|
-
if (depth >= 1 && depth <= 3) {
|
|
44
|
-
validatedDepth = depth;
|
|
45
|
-
} else {
|
|
46
|
-
if (api?.logger) {
|
|
47
|
-
api.logger.warn(`[DeepReflect] Invalid depth value ${depth}. Falling back to 2.`);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const depthMsg = DEPTH_INSTRUCTIONS[validatedDepth as keyof typeof DEPTH_INSTRUCTIONS];
|
|
53
|
-
|
|
54
|
-
// 3. 加载模型索引
|
|
55
|
-
const modelIndexMessage = loadModelIndex(effectiveWorkspaceDir, api);
|
|
56
|
-
|
|
57
|
-
// 4. 构造最终提示词
|
|
58
|
-
return `
|
|
59
|
-
# Role: Principal Critical Thinker & Strategist
|
|
60
|
-
---
|
|
61
|
-
[SYSTEM_ID: Critical Analysis Engine]
|
|
62
|
-
|
|
63
|
-
## Objective
|
|
64
|
-
Provide a high-intensity critical analysis and actionable feedback for the provided task context.
|
|
65
|
-
|
|
66
|
-
## Depth Requirement
|
|
67
|
-
${depthMsg}
|
|
68
|
-
|
|
69
|
-
## Meta-Cognitive Models
|
|
70
|
-
The agent has inherited meta-cognitive models (T-01 to T-09) from the **thinking_os** framework. Use these as your foundational logic.
|
|
71
|
-
|
|
72
|
-
## Model Selection Guidelines
|
|
73
|
-
Step 1: Determine if the task context is a **general planning** task or **domain-specific**.
|
|
74
|
-
Step 2: Select 1-2 relevant models.
|
|
75
|
-
Step 3: If no match is found, use **Fallback** to **Meta-Cognitive Models**.
|
|
76
|
-
|
|
77
|
-
## Domain-Specific Models Index
|
|
78
|
-
${modelIndexMessage}
|
|
79
|
-
|
|
80
|
-
## Task Context to Analyze
|
|
81
|
-
---
|
|
82
|
-
${context}
|
|
83
|
-
---
|
|
84
|
-
|
|
85
|
-
## Instructions
|
|
86
|
-
1. Apply the selected models rigorously.
|
|
87
|
-
2. Identify blind spots and logic gaps.
|
|
88
|
-
3. Provide high-impact recommendations.
|
|
89
|
-
|
|
90
|
-
## Output Structure
|
|
91
|
-
- **Blind Spots**: ...
|
|
92
|
-
- **Risk Warnings**: ...
|
|
93
|
-
- **Alternative Approaches**: ...
|
|
94
|
-
- **Recommendations**: ...
|
|
95
|
-
- **Confidence Level**: [LOW/MEDIUM/HIGH]
|
|
96
|
-
`.trim();
|
|
97
|
-
}
|
|
1
|
+
export {};
|