principles-disciple 1.6.0 → 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 (67) hide show
  1. package/dist/commands/context.js +7 -3
  2. package/dist/commands/evolution-status.d.ts +4 -0
  3. package/dist/commands/evolution-status.js +138 -0
  4. package/dist/commands/export.d.ts +2 -0
  5. package/dist/commands/export.js +45 -0
  6. package/dist/commands/focus.js +9 -6
  7. package/dist/commands/pain.js +8 -0
  8. package/dist/commands/principle-rollback.d.ts +4 -0
  9. package/dist/commands/principle-rollback.js +22 -0
  10. package/dist/commands/samples.d.ts +2 -0
  11. package/dist/commands/samples.js +55 -0
  12. package/dist/core/config.d.ts +5 -0
  13. package/dist/core/control-ui-db.d.ts +68 -0
  14. package/dist/core/control-ui-db.js +274 -0
  15. package/dist/core/detection-funnel.d.ts +1 -1
  16. package/dist/core/detection-funnel.js +4 -0
  17. package/dist/core/dictionary.d.ts +2 -0
  18. package/dist/core/dictionary.js +13 -0
  19. package/dist/core/event-log.d.ts +2 -1
  20. package/dist/core/event-log.js +3 -0
  21. package/dist/core/evolution-engine.d.ts +5 -5
  22. package/dist/core/evolution-engine.js +18 -18
  23. package/dist/core/evolution-migration.d.ts +5 -0
  24. package/dist/core/evolution-migration.js +65 -0
  25. package/dist/core/evolution-reducer.d.ts +69 -0
  26. package/dist/core/evolution-reducer.js +369 -0
  27. package/dist/core/evolution-types.d.ts +103 -0
  28. package/dist/core/path-resolver.js +75 -36
  29. package/dist/core/paths.d.ts +7 -8
  30. package/dist/core/paths.js +48 -40
  31. package/dist/core/profile.js +1 -1
  32. package/dist/core/session-tracker.d.ts +4 -0
  33. package/dist/core/session-tracker.js +15 -0
  34. package/dist/core/thinking-models.d.ts +38 -0
  35. package/dist/core/thinking-models.js +170 -0
  36. package/dist/core/trajectory.d.ts +184 -0
  37. package/dist/core/trajectory.js +817 -0
  38. package/dist/core/trust-engine.d.ts +2 -0
  39. package/dist/core/trust-engine.js +30 -4
  40. package/dist/core/workspace-context.d.ts +13 -0
  41. package/dist/core/workspace-context.js +50 -7
  42. package/dist/hooks/gate.js +117 -48
  43. package/dist/hooks/llm.js +114 -69
  44. package/dist/hooks/pain.js +105 -5
  45. package/dist/hooks/prompt.d.ts +11 -14
  46. package/dist/hooks/prompt.js +283 -57
  47. package/dist/hooks/subagent.js +27 -1
  48. package/dist/http/principles-console-route.d.ts +2 -0
  49. package/dist/http/principles-console-route.js +257 -0
  50. package/dist/i18n/commands.js +16 -0
  51. package/dist/index.js +83 -4
  52. package/dist/service/control-ui-query-service.d.ts +217 -0
  53. package/dist/service/control-ui-query-service.js +537 -0
  54. package/dist/service/evolution-worker.d.ts +9 -0
  55. package/dist/service/evolution-worker.js +152 -22
  56. package/dist/service/trajectory-service.d.ts +2 -0
  57. package/dist/service/trajectory-service.js +15 -0
  58. package/dist/tools/agent-spawn.d.ts +27 -6
  59. package/dist/tools/agent-spawn.js +339 -87
  60. package/dist/tools/deep-reflect.d.ts +27 -7
  61. package/dist/tools/deep-reflect.js +210 -121
  62. package/dist/types/event-types.d.ts +9 -2
  63. package/dist/types.d.ts +10 -0
  64. package/dist/types.js +5 -0
  65. package/openclaw.plugin.json +43 -11
  66. package/package.json +14 -4
  67. package/templates/langs/zh/skills/pd-daily/SKILL.md +97 -13
package/dist/hooks/llm.js CHANGED
@@ -2,8 +2,11 @@ import * as fs from 'fs';
2
2
  import * as path from 'path';
3
3
  import { trackFriction, trackLlmOutput, recordThinkingCheckpoint, resetFriction } from '../core/session-tracker.js';
4
4
  import { writePainFlag } from '../core/pain.js';
5
+ import { ControlUiDatabase } from '../core/control-ui-db.js';
5
6
  import { DetectionService } from '../core/detection-service.js';
7
+ import { detectThinkingModelMatches, deriveThinkingScenarios } from '../core/thinking-models.js';
6
8
  import { WorkspaceContext } from '../core/workspace-context.js';
9
+ import { sanitizeAssistantText } from './message-sanitize.js';
7
10
  const empathyDedupState = new Map();
8
11
  const empathyRateState = new Map();
9
12
  function clamp(value, min, max) {
@@ -184,6 +187,25 @@ export function handleLlmOutput(event, ctx) {
184
187
  if (!event.assistantTexts || event.assistantTexts.length === 0)
185
188
  return;
186
189
  const text = event.assistantTexts.join('\n');
190
+ const signal = extractEmpathySignal(text);
191
+ const createdAt = new Date().toISOString();
192
+ let assistantTurnId = null;
193
+ try {
194
+ assistantTurnId = wctx.trajectory?.recordAssistantTurn?.({
195
+ sessionId: ctx.sessionId,
196
+ runId: event.runId,
197
+ provider: event.provider,
198
+ model: event.model,
199
+ rawText: text,
200
+ sanitizedText: sanitizeAssistantText(text),
201
+ usageJson: event.usage || {},
202
+ empathySignalJson: signal,
203
+ createdAt,
204
+ });
205
+ }
206
+ catch (error) {
207
+ ctx.logger?.warn?.(`[PD:LLM] Failed to persist assistant turn to trajectory: ${String(error)}`);
208
+ }
187
209
  // ── Track B: Semantic Pain Detection (V1.3.0 Funnel) ──
188
210
  const detectionService = DetectionService.get(wctx.stateDir);
189
211
  const detection = detectionService.detect(text);
@@ -205,7 +227,6 @@ export function handleLlmOutput(event, ctx) {
205
227
  // empathy sub-pipeline (enabled by default)
206
228
  const empathyEnabled = config.get('empathy_engine.enabled');
207
229
  if (empathyEnabled !== false) {
208
- const signal = extractEmpathySignal(text);
209
230
  if (signal.detected) {
210
231
  const dedupeWindow = Number(config.get('empathy_engine.dedupe_window_ms') ?? 60000);
211
232
  const deduped = shouldDedupe(ctx.sessionId, event.runId, signal, dedupeWindow);
@@ -217,6 +238,20 @@ export function handleLlmOutput(event, ctx) {
217
238
  const boundedScore = applyRateLimit(ctx.sessionId, event.runId, calibratedScore, config);
218
239
  if (boundedScore > 0) {
219
240
  trackFriction(ctx.sessionId, boundedScore, `user_empathy_${signal.severity}`, ctx.workspaceDir);
241
+ try {
242
+ wctx.trajectory?.recordPainEvent?.({
243
+ sessionId: ctx.sessionId,
244
+ source: 'user_empathy',
245
+ score: boundedScore,
246
+ reason: signal.reason || 'Assistant self-reported user emotional distress.',
247
+ severity: signal.severity,
248
+ origin: 'assistant_self_report',
249
+ confidence: signal.confidence,
250
+ });
251
+ }
252
+ catch (error) {
253
+ ctx.logger?.warn?.(`[PD:LLM] Failed to persist empathy pain event to trajectory: ${String(error)}`);
254
+ }
220
255
  // Generate unique event ID for rollback support
221
256
  const eventId = `emp_${Date.now()}_${Math.random().toString(36).substring(2, 8)}`;
222
257
  eventLog.recordPainSignal(ctx.sessionId, {
@@ -297,56 +332,18 @@ export function handleLlmOutput(event, ctx) {
297
332
  });
298
333
  }
299
334
  // ═══ Thinking OS: Mental Model Usage Tracking ═══
300
- trackThinkingModelUsage(text, wctx, ctx.sessionId);
335
+ trackThinkingModelUsage({
336
+ text,
337
+ wctx,
338
+ sessionId: ctx.sessionId,
339
+ runId: event.runId,
340
+ assistantTurnId,
341
+ createdAt,
342
+ logger: ctx.logger,
343
+ });
301
344
  }
302
- const THINKING_MODEL_SIGNALS = {
303
- 'T-01': [
304
- /let me (first )?(understand|map|outline|survey|review the (structure|architecture|dependencies))/i,
305
- /让我先(梳理|了解|画出|理解|查看)(一下)?(结构|架构|依赖|全貌)/,
306
- ],
307
- 'T-02': [
308
- /(type|test|contract|schema|interface) (constraint|requirement|check|validation)/i,
309
- /we (must|need to) (respect|follow|adhere to) the/i,
310
- /(必须|需要).*?(遵守|符合|满足).*?(类型|测试|契约|接口|规范)/,
311
- ],
312
- 'T-03': [
313
- /based on (the |this )?(evidence|logs?|output|error|stack trace|test result)/i,
314
- /let me (check|verify|confirm|read|look at) (the |)(actual|source|code|file|log)/i,
315
- /根据(日志|证据|输出|报错|堆栈|测试结果)/,
316
- ],
317
- 'T-04': [
318
- /this (is|would be) (irreversible|destructive|permanent|not easily undone)/i,
319
- /(reversible|can be undone|safely roll back)/i,
320
- /(不可逆|破坏性|永久的|无法回滚|可以回滚|安全地撤销)/,
321
- ],
322
- 'T-05': [
323
- /we (must|should) (not|never|avoid|prevent|ensure we don't)/i,
324
- /(critical|important) (not to|that we don't|to avoid)/i,
325
- /(绝不能|必须避免|不可以|禁止|确保不会)/,
326
- ],
327
- 'T-06': [
328
- /(simpl(er|est|ify)|minimal|straightforward|lean) (approach|solution|fix|implementation)/i,
329
- /(simple is better|keep it simple|no need to over)/i,
330
- /(最简(单|洁)|精简|没有必要(过度|额外))/,
331
- ],
332
- 'T-07': [
333
- /(minimal|smallest|narrowest|least) (change|diff|modification|impact)/i,
334
- /only (change|modify|touch|edit) (the |what)/i,
335
- /(最小(改动|变更|修改)|只(改|动|修))/,
336
- ],
337
- 'T-08': [
338
- /this (error|failure|issue) (tells us|indicates|signals|suggests|means)/i,
339
- /let me (stop|pause|step back|reconsider|rethink)/i,
340
- /这个(错误|失败|问题)(告诉我们|表明|说明|意味)/,
341
- /让我(停下|暂停|退一步|重新(考虑|思考|审视))/,
342
- ],
343
- 'T-09': [
344
- /(break|split|decompose|divide) (this |the task |it )?(into|down)/i,
345
- /(step 1|first,? (we|i|let's)|phase 1)/i,
346
- /(拆分|分解|分步|分阶段|第一步)/,
347
- ],
348
- };
349
- function trackThinkingModelUsage(text, wctx, sessionId) {
345
+ function trackThinkingModelUsage(args) {
346
+ const { text, wctx, sessionId, runId, assistantTurnId, createdAt, logger } = args;
350
347
  const logPath = wctx.resolve('THINKING_OS_USAGE');
351
348
  const logDir = path.dirname(logPath);
352
349
  if (!fs.existsSync(logDir))
@@ -360,27 +357,75 @@ function trackThinkingModelUsage(text, wctx, sessionId) {
360
357
  console.error(`[PD:LLM] Failed to parse thinking OS usage log: ${String(e)}`);
361
358
  }
362
359
  }
363
- let anyMatch = false;
364
- for (const [modelId, patterns] of Object.entries(THINKING_MODEL_SIGNALS)) {
365
- for (const pattern of patterns) {
366
- if (pattern.test(text)) {
367
- usageLog[modelId] = (usageLog[modelId] || 0) + 1;
368
- anyMatch = true;
369
- break;
370
- }
371
- }
360
+ const matches = detectThinkingModelMatches(text);
361
+ for (const match of matches) {
362
+ usageLog[match.modelId] = (usageLog[match.modelId] || 0) + 1;
372
363
  }
373
364
  usageLog['_total_turns'] = (usageLog['_total_turns'] || 0) + 1;
374
- if (anyMatch) {
375
- // Record thinking checkpoint for gate enforcement
376
- if (sessionId) {
377
- recordThinkingCheckpoint(sessionId, wctx.workspaceDir);
378
- }
379
- try {
380
- fs.writeFileSync(logPath, JSON.stringify(usageLog, null, 2), 'utf8');
381
- }
382
- catch (e) {
383
- console.error(`[PD:LLM] Failed to write thinking OS usage log: ${String(e)}`);
365
+ try {
366
+ fs.writeFileSync(logPath, JSON.stringify(usageLog, null, 2), 'utf8');
367
+ }
368
+ catch (e) {
369
+ console.error(`[PD:LLM] Failed to write thinking OS usage log: ${String(e)}`);
370
+ }
371
+ if (matches.length === 0) {
372
+ return;
373
+ }
374
+ if (sessionId) {
375
+ recordThinkingCheckpoint(sessionId, wctx.workspaceDir);
376
+ }
377
+ if (!sessionId || !assistantTurnId) {
378
+ return;
379
+ }
380
+ const uiDb = new ControlUiDatabase({ workspaceDir: wctx.workspaceDir });
381
+ try {
382
+ const recentContext = uiDb.getRecentThinkingContext(sessionId, createdAt);
383
+ const toolContext = recentContext.toolCalls.map((call) => ({
384
+ toolName: call.toolName,
385
+ outcome: call.outcome,
386
+ errorType: call.errorType,
387
+ }));
388
+ const painContext = recentContext.painEvents.map((event) => ({
389
+ source: event.source,
390
+ score: event.score,
391
+ }));
392
+ const principleContext = recentContext.principleEvents.map((event) => ({
393
+ principleId: event.principleId,
394
+ eventType: event.eventType,
395
+ }));
396
+ const triggerExcerpt = text.length > 280 ? `${text.slice(0, 277)}...` : text;
397
+ for (const match of matches) {
398
+ const scenarios = deriveThinkingScenarios(match.modelId, {
399
+ recentToolCalls: toolContext,
400
+ recentPainEvents: painContext,
401
+ recentGateBlocks: recentContext.gateBlocks.map((block) => ({
402
+ toolName: block.toolName,
403
+ reason: block.reason,
404
+ })),
405
+ recentUserCorrections: recentContext.userCorrections.map((correction) => ({
406
+ correctionCue: correction.correctionCue,
407
+ })),
408
+ recentPrincipleEvents: principleContext,
409
+ });
410
+ uiDb.recordThinkingModelEvent({
411
+ sessionId,
412
+ runId,
413
+ assistantTurnId,
414
+ modelId: match.modelId,
415
+ matchedPattern: match.matchedPattern,
416
+ scenarioJson: scenarios,
417
+ toolContextJson: toolContext,
418
+ painContextJson: painContext,
419
+ principleContextJson: principleContext,
420
+ triggerExcerpt,
421
+ createdAt,
422
+ });
384
423
  }
385
424
  }
425
+ catch (error) {
426
+ logger?.warn?.(`[PD:LLM] Failed to persist thinking model events: ${String(error)}`);
427
+ }
428
+ finally {
429
+ uiDb.dispose();
430
+ }
386
431
  }
@@ -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 (_e) { }
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 // 👈 NEW: Pass toolName for classification
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 (_e) { }
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)
@@ -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
- * OpenClaw 配置中解析模型选择
30
- * 支持 string { primary, fallbacks } 格式
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
- * PROFILE.json 读取 contextInjection 配置,如果不存在则返回默认配置
37
- * @internal 导出供其他模块使用
32
+ * 闁告梻濮惧ù鍥ㄧ▔婵犱胶鐟撻柡鍌氭处閺佺偤宕楅妷鈺佸赋缂?
33
+ * 濞?PROFILE.json 閻犲洩顕цぐ?contextInjection 闂佹澘绉堕悿鍡涙晬鐏炵瓔娲ら柡瀣矆缁楀鈧稒锚濠€顏堝礆濞嗘帞绠查柛銉у仱缁垳鎷嬮妶澶婂赋缂?
34
+ * @internal 閻庣數鍘ч崵顓熺瑹濞戞ê寰撳ù鐘崇墬鑶╅柛褎銇炴繛鍥偨?
38
35
  */
39
36
  export declare function loadContextInjectionConfig(workspaceDir: string): ContextInjectionConfig;
40
37
  /**
41
- * 获取诊断子智能体应使用的模型
42
- * 优先级:subagents.model > 主模型
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 & {