principles-disciple 1.6.0 → 1.7.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.
- package/dist/commands/context.js +7 -3
- package/dist/commands/evolution-status.d.ts +4 -0
- package/dist/commands/evolution-status.js +134 -0
- package/dist/commands/export.d.ts +2 -0
- package/dist/commands/export.js +45 -0
- package/dist/commands/focus.js +9 -6
- package/dist/commands/pain.js +8 -0
- package/dist/commands/principle-rollback.d.ts +4 -0
- package/dist/commands/principle-rollback.js +22 -0
- package/dist/commands/rollback.js +9 -3
- package/dist/commands/samples.d.ts +2 -0
- package/dist/commands/samples.js +55 -0
- package/dist/commands/trust.js +64 -81
- package/dist/core/config.d.ts +5 -0
- package/dist/core/control-ui-db.d.ts +68 -0
- package/dist/core/control-ui-db.js +274 -0
- package/dist/core/detection-funnel.d.ts +1 -1
- package/dist/core/detection-funnel.js +4 -0
- package/dist/core/dictionary.d.ts +2 -0
- package/dist/core/dictionary.js +13 -0
- package/dist/core/event-log.d.ts +7 -1
- package/dist/core/event-log.js +10 -0
- package/dist/core/evolution-engine.d.ts +5 -5
- package/dist/core/evolution-engine.js +18 -18
- package/dist/core/evolution-migration.d.ts +5 -0
- package/dist/core/evolution-migration.js +65 -0
- package/dist/core/evolution-reducer.d.ts +69 -0
- package/dist/core/evolution-reducer.js +369 -0
- package/dist/core/evolution-types.d.ts +103 -0
- package/dist/core/path-resolver.js +75 -36
- package/dist/core/paths.d.ts +7 -8
- package/dist/core/paths.js +48 -40
- package/dist/core/profile.js +1 -1
- package/dist/core/session-tracker.d.ts +14 -2
- package/dist/core/session-tracker.js +75 -9
- package/dist/core/thinking-models.d.ts +38 -0
- package/dist/core/thinking-models.js +170 -0
- package/dist/core/trajectory.d.ts +184 -0
- package/dist/core/trajectory.js +817 -0
- package/dist/core/trust-engine.d.ts +6 -0
- package/dist/core/trust-engine.js +50 -29
- package/dist/core/workspace-context.d.ts +13 -0
- package/dist/core/workspace-context.js +50 -7
- package/dist/hooks/gate.js +171 -87
- package/dist/hooks/llm.js +119 -71
- package/dist/hooks/pain.js +105 -5
- package/dist/hooks/prompt.d.ts +11 -14
- package/dist/hooks/prompt.js +283 -57
- package/dist/hooks/subagent.js +69 -28
- package/dist/hooks/trajectory-collector.d.ts +32 -0
- package/dist/hooks/trajectory-collector.js +256 -0
- package/dist/http/principles-console-route.d.ts +2 -0
- package/dist/http/principles-console-route.js +257 -0
- package/dist/i18n/commands.js +16 -0
- package/dist/index.js +105 -4
- package/dist/service/control-ui-query-service.d.ts +217 -0
- package/dist/service/control-ui-query-service.js +537 -0
- package/dist/service/empathy-observer-manager.d.ts +2 -0
- package/dist/service/empathy-observer-manager.js +43 -1
- package/dist/service/evolution-worker.d.ts +27 -0
- package/dist/service/evolution-worker.js +256 -41
- package/dist/service/runtime-summary-service.d.ts +79 -0
- package/dist/service/runtime-summary-service.js +319 -0
- package/dist/service/trajectory-service.d.ts +2 -0
- package/dist/service/trajectory-service.js +15 -0
- package/dist/tools/agent-spawn.d.ts +27 -6
- package/dist/tools/agent-spawn.js +339 -87
- package/dist/tools/deep-reflect.d.ts +27 -7
- package/dist/tools/deep-reflect.js +210 -121
- package/dist/types/event-types.d.ts +10 -2
- package/dist/types.d.ts +10 -0
- package/dist/types.js +5 -0
- package/openclaw.plugin.json +43 -11
- package/package.json +14 -4
- package/templates/langs/zh/skills/pd-daily/SKILL.md +97 -13
package/dist/hooks/pain.js
CHANGED
|
@@ -2,11 +2,25 @@ import * as fs from 'fs';
|
|
|
2
2
|
import { isRisky, normalizePath } from '../utils/io.js';
|
|
3
3
|
import { normalizeProfile } from '../core/profile.js';
|
|
4
4
|
import { computePainScore, writePainFlag } from '../core/pain.js';
|
|
5
|
-
import { trackFriction, resetFriction } from '../core/session-tracker.js';
|
|
5
|
+
import { getSession, trackFriction, resetFriction, getInjectedProbationIds, clearInjectedProbationIds } from '../core/session-tracker.js';
|
|
6
6
|
import { denoiseError, computeHash } from '../utils/hashing.js';
|
|
7
7
|
import { SystemLogger } from '../core/system-logger.js';
|
|
8
8
|
import { WorkspaceContext } from '../core/workspace-context.js';
|
|
9
9
|
const WRITE_TOOLS = ['write', 'edit', 'apply_patch', 'write_file', 'edit_file', 'replace'];
|
|
10
|
+
function shouldAttributePrincipleToTool(principle, toolName) {
|
|
11
|
+
return principle.contextTags.includes(toolName) || principle.trigger.includes(toolName);
|
|
12
|
+
}
|
|
13
|
+
function emitPainDetectedEvent(wctx, event) {
|
|
14
|
+
try {
|
|
15
|
+
wctx.evolutionReducer.emitSync(event);
|
|
16
|
+
}
|
|
17
|
+
catch (e) {
|
|
18
|
+
SystemLogger.log(wctx.workspaceDir, 'EVOLUTION_EMIT_WARN', `Failed to emit evolution event: ${String(e)}`);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
function createPainId(sessionId) {
|
|
22
|
+
return `pain_${Date.now()}_${computeHash(sessionId).slice(0, 8)}`;
|
|
23
|
+
}
|
|
10
24
|
export function handleAfterToolCall(event, ctx, api) {
|
|
11
25
|
const effectiveWorkspaceDir = ctx.workspaceDir || api?.workspaceDir || api?.resolvePath?.('.');
|
|
12
26
|
if (!effectiveWorkspaceDir) {
|
|
@@ -17,6 +31,8 @@ export function handleAfterToolCall(event, ctx, api) {
|
|
|
17
31
|
const eventLog = wctx.eventLog;
|
|
18
32
|
const trust = wctx.trust;
|
|
19
33
|
const sessionId = ctx.sessionId || 'unknown';
|
|
34
|
+
const sessionState = ctx.sessionId ? getSession(ctx.sessionId) : undefined;
|
|
35
|
+
const gfiBefore = sessionState?.currentGfi ?? 0;
|
|
20
36
|
const params = event.params;
|
|
21
37
|
// ── Track A: Empirical Friction (GFI) ──
|
|
22
38
|
// 0. Special Case: Manual Pain Intervention
|
|
@@ -30,6 +46,25 @@ export function handleAfterToolCall(event, ctx, api) {
|
|
|
30
46
|
reason: `User intervention: ${reason}`,
|
|
31
47
|
isRisky: true
|
|
32
48
|
});
|
|
49
|
+
wctx.trajectory?.recordPainEvent?.({
|
|
50
|
+
sessionId,
|
|
51
|
+
source: 'manual',
|
|
52
|
+
score: 100,
|
|
53
|
+
reason: `User intervention: ${reason}`,
|
|
54
|
+
origin: 'user_manual',
|
|
55
|
+
});
|
|
56
|
+
emitPainDetectedEvent(wctx, {
|
|
57
|
+
ts: new Date().toISOString(),
|
|
58
|
+
type: 'pain_detected',
|
|
59
|
+
data: {
|
|
60
|
+
painId: createPainId(sessionId),
|
|
61
|
+
painType: 'user_frustration',
|
|
62
|
+
source: event.toolName,
|
|
63
|
+
reason: `User intervention: ${reason}`,
|
|
64
|
+
score: 100,
|
|
65
|
+
sessionId,
|
|
66
|
+
},
|
|
67
|
+
});
|
|
33
68
|
return;
|
|
34
69
|
}
|
|
35
70
|
// 1. Determine if this was a failure
|
|
@@ -52,13 +87,16 @@ export function handleAfterToolCall(event, ctx, api) {
|
|
|
52
87
|
try {
|
|
53
88
|
profile = normalizeProfile(JSON.parse(fs.readFileSync(profilePath, 'utf8')));
|
|
54
89
|
}
|
|
55
|
-
catch (
|
|
90
|
+
catch (e) {
|
|
91
|
+
SystemLogger.log(effectiveWorkspaceDir, 'PROFILE_PARSE_WARN', `Failed to parse PROFILE.json: ${String(e)}`);
|
|
92
|
+
}
|
|
56
93
|
}
|
|
57
94
|
const isRisk = isRisky(relPath, profile.risk_paths);
|
|
58
95
|
trust.recordFailure(isRisk ? 'risky' : 'tool', {
|
|
59
96
|
sessionId,
|
|
60
97
|
api,
|
|
61
|
-
toolName: event.toolName
|
|
98
|
+
toolName: event.toolName,
|
|
99
|
+
error: event.error // Pass error for timeout detection
|
|
62
100
|
});
|
|
63
101
|
// Record tool call failure event
|
|
64
102
|
eventLog.recordToolCall(sessionId, {
|
|
@@ -70,16 +108,56 @@ export function handleAfterToolCall(event, ctx, api) {
|
|
|
70
108
|
consecutiveErrors: updatedState.consecutiveErrors,
|
|
71
109
|
exitCode,
|
|
72
110
|
});
|
|
111
|
+
wctx.trajectory?.recordToolCall?.({
|
|
112
|
+
sessionId,
|
|
113
|
+
toolName: event.toolName,
|
|
114
|
+
outcome: 'failure',
|
|
115
|
+
durationMs: event.durationMs,
|
|
116
|
+
exitCode,
|
|
117
|
+
errorType,
|
|
118
|
+
errorMessage: event.error ? String(event.error) : undefined,
|
|
119
|
+
gfiBefore,
|
|
120
|
+
gfiAfter: updatedState.currentGfi,
|
|
121
|
+
paramsJson: event.params,
|
|
122
|
+
});
|
|
123
|
+
const injectedProbationIds = getInjectedProbationIds(sessionId, effectiveWorkspaceDir);
|
|
124
|
+
for (const id of injectedProbationIds) {
|
|
125
|
+
const principle = wctx.evolutionReducer.getPrincipleById(id);
|
|
126
|
+
const shouldAttribute = !!principle && shouldAttributePrincipleToTool(principle, event.toolName);
|
|
127
|
+
if (shouldAttribute) {
|
|
128
|
+
wctx.evolutionReducer.recordProbationFeedback(id, false);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
clearInjectedProbationIds(sessionId, effectiveWorkspaceDir);
|
|
73
132
|
}
|
|
74
133
|
else {
|
|
75
134
|
// ── SUCCESS BRANCH ──
|
|
76
|
-
resetFriction(sessionId, effectiveWorkspaceDir);
|
|
135
|
+
const resetState = resetFriction(sessionId, effectiveWorkspaceDir);
|
|
77
136
|
// 👈 Record success to reset failure streak and earn minor trust (if constructive)
|
|
78
137
|
trust.recordSuccess('tool_success', {
|
|
79
138
|
sessionId,
|
|
80
139
|
api,
|
|
81
140
|
toolName: event.toolName // 👈 NEW: Pass toolName for classification
|
|
82
141
|
});
|
|
142
|
+
const injectedProbationIds = getInjectedProbationIds(sessionId, effectiveWorkspaceDir);
|
|
143
|
+
for (const id of injectedProbationIds) {
|
|
144
|
+
const principle = wctx.evolutionReducer.getPrincipleById(id);
|
|
145
|
+
const shouldAttribute = !!principle && shouldAttributePrincipleToTool(principle, event.toolName);
|
|
146
|
+
if (shouldAttribute) {
|
|
147
|
+
wctx.evolutionReducer.recordProbationFeedback(id, true);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
clearInjectedProbationIds(sessionId, effectiveWorkspaceDir);
|
|
151
|
+
wctx.trajectory?.recordToolCall?.({
|
|
152
|
+
sessionId,
|
|
153
|
+
toolName: event.toolName,
|
|
154
|
+
outcome: 'success',
|
|
155
|
+
durationMs: event.durationMs,
|
|
156
|
+
exitCode,
|
|
157
|
+
gfiBefore,
|
|
158
|
+
gfiAfter: resetState.currentGfi,
|
|
159
|
+
paramsJson: event.params,
|
|
160
|
+
});
|
|
83
161
|
if (WRITE_TOOLS.includes(event.toolName)) {
|
|
84
162
|
const filePath = params.file_path || params.path || params.file;
|
|
85
163
|
eventLog.recordToolCall(sessionId, {
|
|
@@ -128,7 +206,9 @@ export function handleAfterToolCall(event, ctx, api) {
|
|
|
128
206
|
try {
|
|
129
207
|
profile = normalizeProfile(JSON.parse(fs.readFileSync(profilePath, 'utf8')));
|
|
130
208
|
}
|
|
131
|
-
catch (
|
|
209
|
+
catch (e) {
|
|
210
|
+
SystemLogger.log(effectiveWorkspaceDir, 'PROFILE_PARSE_WARN', `Failed to parse PROFILE.json: ${String(e)}`);
|
|
211
|
+
}
|
|
132
212
|
}
|
|
133
213
|
const isRisk = isRisky(relPath, profile.risk_paths);
|
|
134
214
|
const painScore = computePainScore(1, false, false, isRisk ? 20 : 0, effectiveWorkspaceDir);
|
|
@@ -146,6 +226,26 @@ export function handleAfterToolCall(event, ctx, api) {
|
|
|
146
226
|
reason: `Tool ${event.toolName} failed on ${relPath}`,
|
|
147
227
|
isRisky: isRisk,
|
|
148
228
|
});
|
|
229
|
+
wctx.trajectory?.recordPainEvent?.({
|
|
230
|
+
sessionId,
|
|
231
|
+
source: 'tool_failure',
|
|
232
|
+
score: painScore,
|
|
233
|
+
reason: `Tool ${event.toolName} failed on ${relPath}`,
|
|
234
|
+
severity: painScore >= 70 ? 'severe' : painScore >= 40 ? 'moderate' : 'mild',
|
|
235
|
+
origin: 'system_infer',
|
|
236
|
+
});
|
|
237
|
+
emitPainDetectedEvent(wctx, {
|
|
238
|
+
ts: new Date().toISOString(),
|
|
239
|
+
type: 'pain_detected',
|
|
240
|
+
data: {
|
|
241
|
+
painId: createPainId(sessionId),
|
|
242
|
+
painType: 'tool_failure',
|
|
243
|
+
source: event.toolName,
|
|
244
|
+
reason: `Tool ${event.toolName} failed on ${relPath}`,
|
|
245
|
+
score: painScore,
|
|
246
|
+
sessionId,
|
|
247
|
+
},
|
|
248
|
+
});
|
|
149
249
|
}
|
|
150
250
|
function extractErrorType(error) {
|
|
151
251
|
if (!error)
|
package/dist/hooks/prompt.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { PluginHookBeforePromptBuildEvent, PluginHookAgentContext, PluginHo
|
|
|
2
2
|
import { ContextInjectionConfig } from '../types.js';
|
|
3
3
|
import { type EmpathyObserverApi } from '../service/empathy-observer-manager.js';
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* 濞寸媴绲块幃濠冾渶濡鍚囬梺鏉跨Ф閻?
|
|
6
6
|
*/
|
|
7
7
|
interface AgentsDefaultsConfig {
|
|
8
8
|
model?: unknown;
|
|
@@ -10,9 +10,6 @@ interface AgentsDefaultsConfig {
|
|
|
10
10
|
model?: unknown;
|
|
11
11
|
};
|
|
12
12
|
}
|
|
13
|
-
/**
|
|
14
|
-
* OpenClaw API 接口定义(Prompt Hook 所需部分)
|
|
15
|
-
*/
|
|
16
13
|
interface PromptHookApi {
|
|
17
14
|
config?: {
|
|
18
15
|
agents?: {
|
|
@@ -26,22 +23,22 @@ interface PromptHookApi {
|
|
|
26
23
|
logger: PluginLogger;
|
|
27
24
|
}
|
|
28
25
|
/**
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
* @internal
|
|
26
|
+
* 濞?OpenClaw 闂佹澘绉堕悿鍡樼▔椤撯寬鎺楀几閹邦劷渚€宕圭€n喒鍋撴径瀣仴
|
|
27
|
+
* 闁衡偓椤栨稑鐦?string 闁?{ primary, fallbacks } 闁哄秶鍘х槐?
|
|
28
|
+
* @internal 閻庣數鍘ч崵顓熺閸涱剛杩旀繛鏉戭儓閻︻垱鎷呯捄銊︽殢
|
|
32
29
|
*/
|
|
33
30
|
export declare function resolveModelFromConfig(modelConfig: unknown, logger?: PluginLogger): string | null;
|
|
34
31
|
/**
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
* @internal
|
|
32
|
+
* 闁告梻濮惧ù鍥ㄧ▔婵犱胶鐟撻柡鍌氭处閺佺偤宕楅妷鈺佸赋缂?
|
|
33
|
+
* 濞?PROFILE.json 閻犲洩顕цぐ?contextInjection 闂佹澘绉堕悿鍡涙晬鐏炵瓔娲ら柡瀣矆缁楀鈧稒锚濠€顏堝礆濞嗘帞绠查柛銉у仱缁垳鎷嬮妶澶婂赋缂?
|
|
34
|
+
* @internal 閻庣數鍘ч崵顓熺瑹濞戞ê寰撳ù鐘崇墬鑶╅柛褎銇炴繛鍥偨?
|
|
38
35
|
*/
|
|
39
36
|
export declare function loadContextInjectionConfig(workspaceDir: string): ContextInjectionConfig;
|
|
40
37
|
/**
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
* @internal
|
|
38
|
+
* 闁兼儳鍢茶ぐ鍥╂嫚婵犲啯鐒介悗娑欏姈濞呫倝鎳楅幋鎺旂Ъ閹煎瓨鏌ф繛鍥偨閵娧勭暠婵☆垪鈧磭鈧?
|
|
39
|
+
* 濞村吋锚閸樻稓鐥缁辩殜ubagents.model > 濞戞挾绮啯闁?
|
|
40
|
+
* 濠碘€冲€归悘澶愭焾閼恒儳姊鹃柡鍫濐樀閸樸倗绱旈鍡欑闁硅埖绋戦崵顓㈡煥濞嗘帩鍤?
|
|
41
|
+
* @internal 閻庣數鍘ч崵顓熺閸涱剛杩旀繛鏉戭儓閻︻垱鎷呯捄銊︽殢
|
|
45
42
|
*/
|
|
46
43
|
export declare function getDiagnosticianModel(api: PromptHookApi | null, logger?: PluginLogger): string;
|
|
47
44
|
export declare function handleBeforePromptBuild(event: PluginHookBeforePromptBuildEvent, ctx: PluginHookAgentContext & {
|