principles-disciple 1.10.0 → 1.12.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/CHANGELOG.md +26 -0
- package/README.md +66 -0
- package/esbuild.config.js +1 -1
- package/openclaw.plugin.json +4 -4
- package/package.json +2 -3
- package/run-nocturnal.mjs +30 -0
- package/scripts/db-migrate.mjs +170 -0
- package/scripts/sync-plugin.mjs +94 -5
- package/src/commands/archive-impl.ts +136 -0
- package/src/commands/capabilities.ts +4 -2
- package/src/commands/context.ts +5 -1
- package/src/commands/disable-impl.ts +151 -0
- package/src/commands/evolution-status.ts +64 -19
- package/src/commands/export.ts +8 -6
- package/src/commands/focus.ts +8 -20
- package/src/commands/nocturnal-review.ts +5 -7
- package/src/commands/nocturnal-rollout.ts +1 -12
- package/src/commands/nocturnal-train.ts +17 -42
- package/src/commands/pain.ts +10 -5
- package/src/commands/principle-rollback.ts +4 -2
- package/src/commands/promote-impl.ts +274 -0
- package/src/commands/rollback-impl.ts +234 -0
- package/src/commands/rollback.ts +6 -3
- package/src/commands/samples.ts +2 -0
- package/src/commands/thinking-os.ts +3 -4
- package/src/commands/workflow-debug.ts +2 -1
- package/src/config/errors.ts +1 -0
- package/src/core/AGENTS.md +34 -0
- package/src/core/adaptive-thresholds.ts +4 -3
- package/src/core/code-implementation-storage.ts +241 -0
- package/src/core/config.ts +5 -2
- package/src/core/control-ui-db.ts +29 -10
- package/src/core/detection-funnel.ts +12 -7
- package/src/core/diagnostician-task-store.ts +156 -0
- package/src/core/dictionary.ts +4 -4
- package/src/core/empathy-keyword-matcher.ts +7 -3
- package/src/core/empathy-types.ts +13 -2
- package/src/core/event-log.ts +14 -6
- package/src/core/evolution-engine.ts +27 -31
- package/src/core/evolution-logger.ts +3 -2
- package/src/core/evolution-reducer.ts +83 -31
- package/src/core/evolution-types.ts +10 -0
- package/src/core/external-training-contract.ts +1 -0
- package/src/core/focus-history.ts +38 -24
- package/src/core/hygiene/tracker.ts +10 -6
- package/src/core/init.ts +5 -2
- package/src/core/migration.ts +3 -3
- package/src/core/model-deployment-registry.ts +6 -4
- package/src/core/model-training-registry.ts +5 -3
- package/src/core/nocturnal-arbiter.ts +13 -14
- package/src/core/nocturnal-artifact-lineage.ts +117 -0
- package/src/core/nocturnal-artificer.ts +257 -0
- package/src/core/nocturnal-candidate-scoring.ts +4 -2
- package/src/core/nocturnal-compliance.ts +67 -19
- package/src/core/nocturnal-dataset.ts +95 -2
- package/src/core/nocturnal-executability.ts +2 -3
- package/src/core/nocturnal-export.ts +6 -3
- package/src/core/nocturnal-rule-implementation-validator.ts +245 -0
- package/src/core/nocturnal-trajectory-extractor.ts +10 -3
- package/src/core/nocturnal-trinity.ts +300 -57
- package/src/core/pain-context-extractor.ts +29 -15
- package/src/core/pain.ts +7 -5
- package/src/core/path-resolver.ts +16 -15
- package/src/core/paths.ts +2 -1
- package/src/core/pd-task-reconciler.ts +463 -0
- package/src/core/pd-task-service.ts +42 -0
- package/src/core/pd-task-store.ts +77 -0
- package/src/core/pd-task-types.ts +128 -0
- package/src/core/principle-internalization/deprecated-readiness.ts +91 -0
- package/src/core/principle-internalization/internalization-routing-policy.ts +208 -0
- package/src/core/principle-internalization/lifecycle-metrics.ts +149 -0
- package/src/core/principle-internalization/lifecycle-read-model.ts +243 -0
- package/src/core/principle-internalization/lifecycle-refresh.ts +11 -0
- package/src/core/principle-internalization/principle-lifecycle-service.ts +167 -0
- package/src/core/principle-training-state.ts +95 -370
- package/src/core/principle-tree-ledger.ts +713 -0
- package/src/core/profile.ts +3 -1
- package/src/core/promotion-gate.ts +14 -18
- package/src/core/replay-engine.ts +562 -0
- package/src/core/risk-calculator.ts +6 -4
- package/src/core/rule-host-helpers.ts +39 -0
- package/src/core/rule-host-types.ts +82 -0
- package/src/core/rule-host.ts +245 -0
- package/src/core/rule-implementation-runtime.ts +38 -0
- package/src/core/schema/db-types.ts +16 -0
- package/src/core/schema/index.ts +26 -0
- package/src/core/schema/migration-runner.ts +207 -0
- package/src/core/schema/migrations/001-init-trajectory.ts +211 -0
- package/src/core/schema/migrations/002-init-central.ts +122 -0
- package/src/core/schema/migrations/003-init-workflow.ts +55 -0
- package/src/core/schema/migrations/004-add-thinking-and-gfi.ts +74 -0
- package/src/core/schema/migrations/index.ts +31 -0
- package/src/core/schema/schema-definitions.ts +650 -0
- package/src/core/session-tracker.ts +6 -4
- package/src/core/shadow-observation-registry.ts +6 -3
- package/src/core/system-logger.ts +2 -2
- package/src/core/thinking-models.ts +182 -46
- package/src/core/thinking-os-parser.ts +164 -0
- package/src/core/training-program.ts +7 -7
- package/src/core/trajectory.ts +42 -36
- package/src/core/workspace-context.ts +77 -11
- package/src/core/workspace-dir-validation.ts +152 -0
- package/src/hooks/AGENTS.md +31 -0
- package/src/hooks/bash-risk.ts +3 -1
- package/src/hooks/edit-verification.ts +9 -5
- package/src/hooks/gate-block-helper.ts +5 -1
- package/src/hooks/gate.ts +152 -5
- package/src/hooks/gfi-gate.ts +9 -2
- package/src/hooks/lifecycle-routing.ts +124 -0
- package/src/hooks/lifecycle.ts +12 -12
- package/src/hooks/llm.ts +17 -109
- package/src/hooks/message-sanitize.ts +5 -3
- package/src/hooks/pain.ts +19 -15
- package/src/hooks/progressive-trust-gate.ts +7 -1
- package/src/hooks/prompt.ts +169 -60
- package/src/hooks/subagent.ts +5 -4
- package/src/hooks/thinking-checkpoint.ts +2 -0
- package/src/hooks/trajectory-collector.ts +15 -12
- package/src/http/principles-console-route.ts +31 -68
- package/src/i18n/commands.ts +2 -2
- package/src/index.ts +126 -40
- package/src/service/central-database.ts +131 -43
- package/src/service/central-health-service.ts +47 -0
- package/src/service/central-overview-service.ts +135 -0
- package/src/service/central-sync-service.ts +87 -0
- package/src/service/control-ui-query-service.ts +46 -36
- package/src/service/event-log-auditor.ts +261 -0
- package/src/service/evolution-query-service.ts +23 -22
- package/src/service/evolution-worker.ts +565 -261
- package/src/service/health-query-service.ts +213 -36
- package/src/service/nocturnal-runtime.ts +8 -4
- package/src/service/nocturnal-service.ts +499 -59
- package/src/service/nocturnal-target-selector.ts +5 -7
- package/src/service/runtime-summary-service.ts +2 -1
- package/src/service/subagent-workflow/deep-reflect-workflow-manager.ts +25 -336
- package/src/service/subagent-workflow/dynamic-timeout.ts +30 -0
- package/src/service/subagent-workflow/empathy-observer-workflow-manager.ts +48 -386
- package/src/service/subagent-workflow/index.ts +2 -0
- package/src/service/subagent-workflow/nocturnal-workflow-manager.ts +155 -285
- package/src/service/subagent-workflow/runtime-direct-driver.ts +114 -16
- package/src/service/subagent-workflow/subagent-error-utils.ts +25 -0
- package/src/service/subagent-workflow/types.ts +9 -4
- package/src/service/subagent-workflow/workflow-manager-base.ts +573 -0
- package/src/service/subagent-workflow/workflow-store.ts +71 -11
- package/src/service/trajectory-service.ts +2 -1
- package/src/tools/critique-prompt.ts +1 -1
- package/src/tools/deep-reflect.ts +175 -209
- package/src/tools/model-index.ts +2 -1
- package/src/types/event-types.ts +2 -2
- package/src/types/principle-tree-schema.ts +29 -23
- package/src/utils/file-lock.ts +5 -3
- package/src/utils/io.ts +5 -2
- package/src/utils/nlp.ts +5 -46
- package/src/utils/node-vm-polyfill.ts +11 -0
- package/src/utils/plugin-logger.ts +2 -0
- package/src/utils/retry.ts +572 -0
- package/src/utils/subagent-probe.ts +1 -1
- package/templates/langs/en/core/AGENTS.md +0 -13
- package/templates/langs/en/core/SOUL.md +1 -31
- package/templates/langs/en/core/TOOLS.md +0 -4
- package/templates/langs/en/principles/THINKING_OS.md +64 -0
- package/templates/langs/en/skills/admin/SKILL.md +0 -1
- package/templates/langs/en/skills/evolution-framework-update/SKILL.md +1 -1
- package/templates/langs/en/skills/pd-diagnostician/SKILL.md +18 -5
- package/templates/langs/zh/core/AGENTS.md +0 -22
- package/templates/langs/zh/core/SOUL.md +1 -31
- package/templates/langs/zh/core/TOOLS.md +0 -4
- package/templates/langs/zh/principles/THINKING_OS.md +64 -0
- package/templates/langs/zh/skills/admin/SKILL.md +0 -1
- package/templates/langs/zh/skills/evolution-framework-update/SKILL.md +1 -1
- package/templates/langs/zh/skills/pd-diagnostician/SKILL.md +25 -4
- package/tests/commands/evolution-status.test.ts +119 -0
- package/tests/commands/implementation-lifecycle.test.ts +362 -0
- package/tests/core/code-implementation-storage.test.ts +398 -0
- package/tests/core/evolution-reducer.detector-metadata.test.ts +28 -28
- package/tests/core/nocturnal-artifact-lineage.test.ts +53 -0
- package/tests/core/nocturnal-artificer.test.ts +241 -0
- package/tests/core/nocturnal-compliance-p-principles.test.ts +133 -0
- package/tests/core/nocturnal-rule-implementation-validator.test.ts +127 -0
- package/tests/core/pd-task-store.test.ts +126 -0
- package/tests/core/principle-internalization/deprecated-readiness.test.ts +193 -0
- package/tests/core/principle-internalization/internalization-routing-policy.test.ts +212 -0
- package/tests/core/principle-internalization/lifecycle-metrics.test.ts +350 -0
- package/tests/core/principle-internalization/principle-lifecycle-service.test.ts +211 -0
- package/tests/core/principle-training-state.test.ts +228 -1
- package/tests/core/principle-tree-ledger.test.ts +423 -0
- package/tests/core/regression-v1-9-1.test.ts +265 -0
- package/tests/core/replay-engine.test.ts +234 -0
- package/tests/core/rule-host-helpers.test.ts +120 -0
- package/tests/core/rule-host.test.ts +389 -0
- package/tests/core/rule-implementation-runtime.test.ts +64 -0
- package/tests/core/workspace-context.test.ts +53 -0
- package/tests/core/workspace-dir-validation.test.ts +272 -0
- package/tests/hooks/gate-rule-host-pipeline.test.ts +385 -0
- package/tests/hooks/pain.test.ts +74 -10
- package/tests/hooks/prompt.test.ts +63 -1
- package/tests/integration/principle-lifecycle.e2e.test.ts +197 -0
- package/tests/integration/tool-hooks-workspace-dir.e2e.test.ts +211 -0
- package/tests/service/data-endpoints-regression.test.ts +834 -0
- package/tests/service/evolution-worker.test.ts +0 -123
- package/tests/service/nocturnal-service-code-candidate.test.ts +330 -0
- package/tests/utils/nlp.test.ts +1 -19
- package/tests/utils/retry.test.ts +327 -0
- package/ui/src/App.tsx +1 -1
- package/ui/src/api.ts +4 -0
- package/ui/src/charts.tsx +366 -0
- package/ui/src/components/WorkspaceConfig.tsx +107 -75
- package/ui/src/i18n/ui.ts +55 -22
- package/ui/src/pages/OverviewPage.tsx +441 -81
- package/ui/src/styles.css +43 -0
- package/ui/src/types.ts +17 -1
- package/src/agents/nocturnal-dreamer.md +0 -152
- package/src/agents/nocturnal-philosopher.md +0 -138
- package/src/agents/nocturnal-reflector.md +0 -126
- package/src/agents/nocturnal-scribe.md +0 -164
- package/templates/workspace/.principles/00-kernel.md +0 -51
- package/templates/workspace/.principles/DECISION_POLICY.json +0 -44
- package/templates/workspace/.principles/PRINCIPLES.md +0 -20
- package/templates/workspace/.principles/PROFILE.json +0 -54
- package/templates/workspace/.principles/PROFILE.schema.json +0 -56
- package/templates/workspace/.principles/THINKING_OS.md +0 -64
- package/templates/workspace/.principles/THINKING_OS_ARCHIVE.md +0 -7
- package/templates/workspace/.principles/THINKING_OS_CANDIDATES.md +0 -9
- package/templates/workspace/.principles/models/_INDEX.md +0 -27
- package/templates/workspace/.principles/models/first_principles.md +0 -62
- package/templates/workspace/.principles/models/marketing_4p.md +0 -52
- package/templates/workspace/.principles/models/porter_five.md +0 -63
- package/templates/workspace/.principles/models/swot.md +0 -60
- package/templates/workspace/.principles/models/user_story_map.md +0 -63
- package/templates/workspace/.state/WORKBOARD.json +0 -4
|
@@ -7,6 +7,8 @@ import { getEvolutionQueryService } from '../service/evolution-query-service.js'
|
|
|
7
7
|
import { HealthQueryService } from '../service/health-query-service.js';
|
|
8
8
|
import { TrajectoryRegistry } from '../core/trajectory.js';
|
|
9
9
|
import { getCentralDatabase } from '../service/central-database.js';
|
|
10
|
+
import { CentralOverviewService } from '../service/central-overview-service.js';
|
|
11
|
+
import { CentralHealthService } from '../service/central-health-service.js';
|
|
10
12
|
|
|
11
13
|
const ROUTE_PREFIX = '/plugins/principles';
|
|
12
14
|
const API_PREFIX = `${ROUTE_PREFIX}/api`;
|
|
@@ -92,6 +94,7 @@ function createService(api: OpenClawPluginApi): ControlUiQueryService {
|
|
|
92
94
|
return new ControlUiQueryService(workspaceDir);
|
|
93
95
|
}
|
|
94
96
|
|
|
97
|
+
/* eslint-disable @typescript-eslint/max-params -- Reason: Route handler requires api, pathname, req, and res */
|
|
95
98
|
function handleApiRoute(
|
|
96
99
|
api: OpenClawPluginApi,
|
|
97
100
|
pathname: string,
|
|
@@ -99,6 +102,7 @@ function handleApiRoute(
|
|
|
99
102
|
res: ServerResponse,
|
|
100
103
|
): Promise<boolean> | boolean {
|
|
101
104
|
// Check authentication for API routes
|
|
105
|
+
/* eslint-disable @typescript-eslint/no-use-before-define -- Reason: validateGatewayAuth is defined later in the file */
|
|
102
106
|
if (!validateGatewayAuth(req)) {
|
|
103
107
|
json(res, 401, { error: 'unauthorized', message: 'Valid Gateway token required.' });
|
|
104
108
|
return true;
|
|
@@ -137,61 +141,12 @@ function handleApiRoute(
|
|
|
137
141
|
if (pathname === `${API_PREFIX}/central/overview` && method === 'GET') {
|
|
138
142
|
const days = parseDays(url.searchParams.get('days'));
|
|
139
143
|
return done(() => {
|
|
140
|
-
const
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
return {
|
|
148
|
-
workspaceDir: 'central',
|
|
149
|
-
generatedAt: new Date().toISOString(),
|
|
150
|
-
dataFreshness: workspaces.length > 0 ? (workspaces[0].lastSync ?? null) : null,
|
|
151
|
-
dataSource: 'central_aggregated_db',
|
|
152
|
-
runtimeControlPlaneSource: 'all_workspaces',
|
|
153
|
-
summary: {
|
|
154
|
-
repeatErrorRate: stats.totalToolCalls > 0
|
|
155
|
-
? stats.totalFailures / stats.totalToolCalls
|
|
156
|
-
: 0,
|
|
157
|
-
userCorrectionRate: stats.totalToolCalls > 0
|
|
158
|
-
? stats.totalCorrections / stats.totalToolCalls
|
|
159
|
-
: 0,
|
|
160
|
-
pendingSamples: stats.pendingSamples,
|
|
161
|
-
approvedSamples: stats.approvedSamples,
|
|
162
|
-
thinkingCoverageRate: stats.totalToolCalls > 0
|
|
163
|
-
? stats.totalThinkingEvents / stats.totalToolCalls
|
|
164
|
-
: 0,
|
|
165
|
-
painEvents: stats.totalPainEvents,
|
|
166
|
-
principleEventCount: 0,
|
|
167
|
-
gateBlocks: 0,
|
|
168
|
-
taskOutcomes: 0,
|
|
169
|
-
},
|
|
170
|
-
dailyTrend: trend,
|
|
171
|
-
topRegressions: regressions,
|
|
172
|
-
sampleQueue: {
|
|
173
|
-
counters: {
|
|
174
|
-
pending: stats.pendingSamples,
|
|
175
|
-
approved: stats.approvedSamples,
|
|
176
|
-
rejected: stats.rejectedSamples,
|
|
177
|
-
},
|
|
178
|
-
preview: [],
|
|
179
|
-
},
|
|
180
|
-
thinkingSummary: {
|
|
181
|
-
activeModels: thinkingStats.activeModels,
|
|
182
|
-
dormantModels: thinkingStats.totalModels - thinkingStats.activeModels,
|
|
183
|
-
effectiveModels: thinkingStats.models.filter(m => m.coverageRate > 0.1).length,
|
|
184
|
-
coverageRate: stats.totalToolCalls > 0
|
|
185
|
-
? stats.totalThinkingEvents / stats.totalToolCalls
|
|
186
|
-
: 0,
|
|
187
|
-
},
|
|
188
|
-
centralInfo: {
|
|
189
|
-
workspaceCount: stats.workspaceCount,
|
|
190
|
-
enabledWorkspaceCount: stats.enabledWorkspaceCount,
|
|
191
|
-
workspaces: stats.workspaceNames,
|
|
192
|
-
enabledWorkspaces: stats.enabledWorkspaceNames,
|
|
193
|
-
},
|
|
194
|
-
};
|
|
144
|
+
const centralOverviewService = new CentralOverviewService();
|
|
145
|
+
try {
|
|
146
|
+
return centralOverviewService.getOverview(days);
|
|
147
|
+
} finally {
|
|
148
|
+
centralOverviewService.dispose();
|
|
149
|
+
}
|
|
195
150
|
});
|
|
196
151
|
}
|
|
197
152
|
|
|
@@ -224,7 +179,14 @@ function handleApiRoute(
|
|
|
224
179
|
});
|
|
225
180
|
}
|
|
226
181
|
|
|
227
|
-
|
|
182
|
+
// === Central Health: per-workspace health indicators ===
|
|
183
|
+
if (pathname === `${API_PREFIX}/central/health` && method === 'GET') {
|
|
184
|
+
return done(() => {
|
|
185
|
+
return new CentralHealthService().getAllWorkspaceHealth();
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const workspaceConfigMatch = /^\/plugins\/principles\/api\/central\/workspaces\/([^/]+)$/.exec(pathname);
|
|
228
190
|
if (workspaceConfigMatch && method === 'GET') {
|
|
229
191
|
return done(() => {
|
|
230
192
|
const centralDb = getCentralDatabase();
|
|
@@ -238,7 +200,7 @@ function handleApiRoute(
|
|
|
238
200
|
if (workspaceConfigMatch && method === 'PATCH') {
|
|
239
201
|
return (async () => {
|
|
240
202
|
try {
|
|
241
|
-
const body = await readJsonBody(req)
|
|
203
|
+
const body = await readJsonBody(req);
|
|
242
204
|
const centralDb = getCentralDatabase();
|
|
243
205
|
const workspaceName = decodeURIComponent(workspaceConfigMatch[1]);
|
|
244
206
|
centralDb.updateWorkspaceConfig(workspaceName, {
|
|
@@ -264,7 +226,7 @@ function handleApiRoute(
|
|
|
264
226
|
if (pathname === `${API_PREFIX}/central/workspaces` && method === 'POST') {
|
|
265
227
|
return (async () => {
|
|
266
228
|
try {
|
|
267
|
-
const body = await readJsonBody(req)
|
|
229
|
+
const body = await readJsonBody(req);
|
|
268
230
|
const name = typeof body.name === 'string' ? body.name : '';
|
|
269
231
|
const workspacePath = typeof body.path === 'string' ? body.path : '';
|
|
270
232
|
if (!name || !workspacePath) {
|
|
@@ -299,7 +261,7 @@ function handleApiRoute(
|
|
|
299
261
|
}));
|
|
300
262
|
}
|
|
301
263
|
|
|
302
|
-
const sampleDetailMatch =
|
|
264
|
+
const sampleDetailMatch = /^\/plugins\/principles\/api\/samples\/([^/]+)$/.exec(pathname);
|
|
303
265
|
if (sampleDetailMatch && method === 'GET') {
|
|
304
266
|
try {
|
|
305
267
|
const detail = service.getSampleDetail(decodeURIComponent(sampleDetailMatch[1]));
|
|
@@ -318,7 +280,7 @@ function handleApiRoute(
|
|
|
318
280
|
}
|
|
319
281
|
}
|
|
320
282
|
|
|
321
|
-
const sampleReviewMatch =
|
|
283
|
+
const sampleReviewMatch = /^\/plugins\/principles\/api\/samples\/([^/]+)\/review$/.exec(pathname);
|
|
322
284
|
if (sampleReviewMatch && method === 'POST') {
|
|
323
285
|
return (async () => {
|
|
324
286
|
try {
|
|
@@ -355,7 +317,7 @@ function handleApiRoute(
|
|
|
355
317
|
return done(() => service.getThinkingOverview());
|
|
356
318
|
}
|
|
357
319
|
|
|
358
|
-
const thinkingDetailMatch =
|
|
320
|
+
const thinkingDetailMatch = /^\/plugins\/principles\/api\/thinking\/models\/([^/]+)$/.exec(pathname);
|
|
359
321
|
if (thinkingDetailMatch && method === 'GET') {
|
|
360
322
|
try {
|
|
361
323
|
const detail = service.getThinkingModelDetail(decodeURIComponent(thinkingDetailMatch[1]));
|
|
@@ -414,7 +376,7 @@ function handleApiRoute(
|
|
|
414
376
|
});
|
|
415
377
|
}
|
|
416
378
|
|
|
417
|
-
const evolutionTraceMatch =
|
|
379
|
+
const evolutionTraceMatch = /^\/plugins\/principles\/api\/evolution\/trace\/([^/]+)$/.exec(pathname);
|
|
418
380
|
if (evolutionTraceMatch && method === 'GET') {
|
|
419
381
|
const evoService = evolutionService();
|
|
420
382
|
try {
|
|
@@ -590,8 +552,8 @@ function validateGatewayAuth(req: IncomingMessage): boolean {
|
|
|
590
552
|
// No token configured, allow all requests
|
|
591
553
|
return true;
|
|
592
554
|
}
|
|
593
|
-
const authHeader = (req.headers?.
|
|
594
|
-
const tokenMatch =
|
|
555
|
+
const authHeader = (req.headers?.authorization as string) || '';
|
|
556
|
+
const tokenMatch = /^Bearer\s+(.+)$/i.exec(authHeader);
|
|
595
557
|
const providedToken = tokenMatch?.[1];
|
|
596
558
|
return providedToken === gatewayToken;
|
|
597
559
|
}
|
|
@@ -611,7 +573,7 @@ export function createPrinciplesConsoleRoutes(api: OpenClawPluginApi): OpenClawP
|
|
|
611
573
|
async handler(req, res) {
|
|
612
574
|
if (!api.rootDir) { text(res, 500, 'Plugin rootDir not available'); return true; }
|
|
613
575
|
const url = new URL(req.url || ROUTE_PREFIX, 'http://127.0.0.1');
|
|
614
|
-
const pathname = url
|
|
576
|
+
const {pathname} = url;
|
|
615
577
|
const method = (req.method || 'GET').toUpperCase();
|
|
616
578
|
|
|
617
579
|
// Skip API routes - they'll be handled by the API route
|
|
@@ -653,7 +615,7 @@ export function createPrinciplesConsoleRoutes(api: OpenClawPluginApi): OpenClawP
|
|
|
653
615
|
match: 'prefix',
|
|
654
616
|
async handler(req, res) {
|
|
655
617
|
const url = new URL(req.url || API_PREFIX, 'http://127.0.0.1');
|
|
656
|
-
const pathname = url
|
|
618
|
+
const {pathname} = url;
|
|
657
619
|
return handleApiRoute(api, pathname, req, res);
|
|
658
620
|
},
|
|
659
621
|
};
|
|
@@ -663,7 +625,8 @@ export function createPrinciplesConsoleRoutes(api: OpenClawPluginApi): OpenClawP
|
|
|
663
625
|
|
|
664
626
|
// Legacy export for backwards compatibility
|
|
665
627
|
export function createPrinciplesConsoleRoute(api: OpenClawPluginApi): OpenClawPluginHttpRouteParams {
|
|
666
|
-
|
|
628
|
+
// Side effect: registers all console routes via createPrinciplesConsoleRoutes
|
|
629
|
+
createPrinciplesConsoleRoutes(api);
|
|
667
630
|
// Return the combined behavior - this will be called from index.ts
|
|
668
631
|
return {
|
|
669
632
|
path: ROUTE_PREFIX,
|
|
@@ -672,7 +635,7 @@ export function createPrinciplesConsoleRoute(api: OpenClawPluginApi): OpenClawPl
|
|
|
672
635
|
async handler(req, res) {
|
|
673
636
|
if (!api.rootDir) { text(res, 500, 'Plugin rootDir not available'); return true; }
|
|
674
637
|
const url = new URL(req.url || ROUTE_PREFIX, 'http://127.0.0.1');
|
|
675
|
-
const pathname = url
|
|
638
|
+
const {pathname} = url;
|
|
676
639
|
const method = (req.method || 'GET').toUpperCase();
|
|
677
640
|
|
|
678
641
|
if (!pathname.startsWith(ROUTE_PREFIX)) {
|
package/src/i18n/commands.ts
CHANGED
|
@@ -99,7 +99,7 @@ export function getCommandDescription(name: string, lang: string): string {
|
|
|
99
99
|
if (!descriptions) {
|
|
100
100
|
return name;
|
|
101
101
|
}
|
|
102
|
-
return descriptions[normalizedLang] || descriptions
|
|
102
|
+
return descriptions[normalizedLang] || descriptions.en || name;
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
/**
|
|
@@ -111,7 +111,7 @@ export function getAllCommandDescriptions(lang: string): Record<string, string>
|
|
|
111
111
|
const normalizedLang = normalizeLanguage(lang);
|
|
112
112
|
const result: Record<string, string> = {};
|
|
113
113
|
for (const [name, descriptions] of Object.entries(commandDescriptions)) {
|
|
114
|
-
result[name] = descriptions[normalizedLang] || descriptions
|
|
114
|
+
result[name] = descriptions[normalizedLang] || descriptions.en || name;
|
|
115
115
|
}
|
|
116
116
|
return result;
|
|
117
117
|
}
|
package/src/index.ts
CHANGED
|
@@ -15,8 +15,6 @@ import type {
|
|
|
15
15
|
PluginHookSubagentSpawningEvent,
|
|
16
16
|
PluginHookSubagentSpawningResult,
|
|
17
17
|
PluginHookSubagentContext,
|
|
18
|
-
PluginHookBeforeMessageWriteEvent,
|
|
19
|
-
PluginHookBeforeMessageWriteResult,
|
|
20
18
|
} from './openclaw-sdk.js';
|
|
21
19
|
import * as crypto from 'crypto';
|
|
22
20
|
import type { WorkerProfile } from './core/model-deployment-registry.js';
|
|
@@ -30,7 +28,6 @@ import { handleAfterToolCall } from './hooks/pain.js';
|
|
|
30
28
|
import { handleBeforeReset, handleBeforeCompaction, handleAfterCompaction } from './hooks/lifecycle.js';
|
|
31
29
|
import { handleLlmOutput } from './hooks/llm.js';
|
|
32
30
|
import { handleSubagentEnded } from './hooks/subagent.js';
|
|
33
|
-
import { handleBeforeMessageWrite } from './hooks/message-sanitize.js';
|
|
34
31
|
import * as TrajectoryCollector from './hooks/trajectory-collector.js';
|
|
35
32
|
import { handleInitStrategy, handleManageOkr } from './commands/strategy.js';
|
|
36
33
|
import { handleBootstrapTools, handleResearchTools } from './commands/capabilities.js';
|
|
@@ -39,6 +36,10 @@ import { handlePainCommand } from './commands/pain.js';
|
|
|
39
36
|
import { handleContextCommand } from './commands/context.js';
|
|
40
37
|
import { handleFocusCommand } from './commands/focus.js';
|
|
41
38
|
import { handleRollbackCommand } from './commands/rollback.js';
|
|
39
|
+
import { handlePromoteImplCommand } from './commands/promote-impl.js';
|
|
40
|
+
import { handleDisableImplCommand } from './commands/disable-impl.js';
|
|
41
|
+
import { handleArchiveImplCommand } from './commands/archive-impl.js';
|
|
42
|
+
import { handleRollbackImplCommand } from './commands/rollback-impl.js';
|
|
42
43
|
import { handleEvolutionStatusCommand } from './commands/evolution-status.js';
|
|
43
44
|
import { handlePrincipleRollbackCommand } from './commands/principle-rollback.js';
|
|
44
45
|
import { handleExportCommand } from './commands/export.js';
|
|
@@ -49,6 +50,8 @@ import { handleNocturnalRolloutCommand } from './commands/nocturnal-rollout.js';
|
|
|
49
50
|
import { handleWorkflowDebugCommand } from './commands/workflow-debug.js';
|
|
50
51
|
import { EvolutionWorkerService } from './service/evolution-worker.js';
|
|
51
52
|
import { TrajectoryService } from './service/trajectory-service.js';
|
|
53
|
+
import { PDTaskService } from './core/pd-task-service.js';
|
|
54
|
+
import { CentralSyncService } from './service/central-sync-service.js';
|
|
52
55
|
import { ensureWorkspaceTemplates } from './core/init.js';
|
|
53
56
|
import { migrateDirectoryStructure } from './core/migration.js';
|
|
54
57
|
import { SystemLogger } from './core/system-logger.js';
|
|
@@ -79,6 +82,16 @@ function computeRuntimeShadowTaskFingerprint(event: PluginHookSubagentSpawningEv
|
|
|
79
82
|
return crypto.createHash('sha256').update(JSON.stringify(payload)).digest('hex').slice(0, 16);
|
|
80
83
|
}
|
|
81
84
|
|
|
85
|
+
import { resolveValidWorkspaceDir, validateWorkspaceDir } from './core/workspace-dir-validation.js';
|
|
86
|
+
|
|
87
|
+
function resolveToolHookWorkspaceDir(
|
|
88
|
+
ctx: { workspaceDir?: string; agentId?: string },
|
|
89
|
+
api: OpenClawPluginApi,
|
|
90
|
+
source: string,
|
|
91
|
+
): string {
|
|
92
|
+
return resolveValidWorkspaceDir(ctx, api, { source });
|
|
93
|
+
}
|
|
94
|
+
|
|
82
95
|
const plugin = {
|
|
83
96
|
name: "Principles Disciple",
|
|
84
97
|
description: "Evolutionary programming agent framework with strategic guardrails and reflection loops.",
|
|
@@ -88,6 +101,20 @@ const plugin = {
|
|
|
88
101
|
PathResolver.setExtensionRoot(api.rootDir ?? '.');
|
|
89
102
|
api.registerHttpRoute(createPrinciplesConsoleRoute(api));
|
|
90
103
|
|
|
104
|
+
// ── Startup Health Check: Verify workspaceDir resolution ──
|
|
105
|
+
// Catches OpenClaw context bugs early (e.g., missing workspaceDir in tool hooks)
|
|
106
|
+
setTimeout(() => {
|
|
107
|
+
const testCtx = { agentId: 'main' };
|
|
108
|
+
const toolWorkspaceDir = resolveToolHookWorkspaceDir(testCtx, api, 'startup.health_check');
|
|
109
|
+
const toolIssue = validateWorkspaceDir(toolWorkspaceDir);
|
|
110
|
+
if (toolIssue) {
|
|
111
|
+
api.logger.error(`[PD:health] Tool hook workspaceDir is INVALID: "${toolWorkspaceDir}" - ${toolIssue}`);
|
|
112
|
+
api.logger.error(`[PD:health] Tool hook events will be written to the WRONG .state directory!`);
|
|
113
|
+
} else {
|
|
114
|
+
api.logger.info(`[PD:health] Tool hook workspaceDir OK: "${toolWorkspaceDir}"`);
|
|
115
|
+
}
|
|
116
|
+
}, 1000);
|
|
117
|
+
|
|
91
118
|
const language = (api.pluginConfig?.language as string) || 'en';
|
|
92
119
|
|
|
93
120
|
// ── Hook: Prompt Building ──
|
|
@@ -127,22 +154,23 @@ const plugin = {
|
|
|
127
154
|
api.on(
|
|
128
155
|
'before_tool_call',
|
|
129
156
|
(event: PluginHookBeforeToolCallEvent, ctx: PluginHookToolContext): PluginHookBeforeToolCallResult | void => {
|
|
130
|
-
const workspaceDir = ctx
|
|
157
|
+
const workspaceDir = resolveToolHookWorkspaceDir(ctx, api, 'before_tool_call');
|
|
131
158
|
try {
|
|
132
159
|
const pluginConfig = api.pluginConfig ?? {};
|
|
133
|
-
const logger = api
|
|
160
|
+
const {logger} = api;
|
|
134
161
|
const result = handleBeforeToolCall(event, { ...ctx, workspaceDir, pluginConfig, logger });
|
|
135
|
-
|
|
162
|
+
|
|
136
163
|
WorkspaceContext.fromHookContext({ workspaceDir }).eventLog.recordHookExecution({
|
|
137
164
|
hook: 'before_tool_call'
|
|
138
|
-
});
|
|
139
|
-
|
|
165
|
+
}, { flushImmediately: true });
|
|
166
|
+
|
|
140
167
|
return result;
|
|
141
168
|
} catch (err) {
|
|
142
|
-
|
|
169
|
+
const fallbackDir = resolveToolHookWorkspaceDir(ctx, api, 'before_tool_call');
|
|
170
|
+
WorkspaceContext.fromHookContext({ workspaceDir: fallbackDir }).eventLog.recordHookExecution({
|
|
143
171
|
hook: 'before_tool_call',
|
|
144
172
|
error: String(err)
|
|
145
|
-
});
|
|
173
|
+
}, { flushImmediately: true });
|
|
146
174
|
api.logger.error(`[PD] Error in before_tool_call: ${String(err)}`);
|
|
147
175
|
}
|
|
148
176
|
}
|
|
@@ -152,20 +180,21 @@ const plugin = {
|
|
|
152
180
|
api.on(
|
|
153
181
|
'after_tool_call',
|
|
154
182
|
(event: PluginHookAfterToolCallEvent, ctx: PluginHookToolContext): void => {
|
|
155
|
-
const workspaceDir = ctx
|
|
183
|
+
const workspaceDir = resolveToolHookWorkspaceDir(ctx, api, 'after_tool_call');
|
|
156
184
|
try {
|
|
157
185
|
const pluginConfig = api.pluginConfig ?? {};
|
|
158
186
|
// Pass api separately to handleAfterToolCall to maintain type safety
|
|
159
187
|
handleAfterToolCall(event, { ...ctx, workspaceDir, pluginConfig }, api);
|
|
160
|
-
|
|
188
|
+
|
|
161
189
|
WorkspaceContext.fromHookContext({ workspaceDir }).eventLog.recordHookExecution({
|
|
162
190
|
hook: 'after_tool_call'
|
|
163
|
-
});
|
|
191
|
+
}, { flushImmediately: true });
|
|
164
192
|
} catch (err) {
|
|
165
|
-
|
|
193
|
+
const fallbackDir = resolveToolHookWorkspaceDir(ctx, api, 'after_tool_call');
|
|
194
|
+
WorkspaceContext.fromHookContext({ workspaceDir: fallbackDir }).eventLog.recordHookExecution({
|
|
166
195
|
hook: 'after_tool_call',
|
|
167
196
|
error: String(err)
|
|
168
|
-
});
|
|
197
|
+
}, { flushImmediately: true });
|
|
169
198
|
api.logger.error(`[PD:EmpathyObserver] Error in after_tool_call: ${String(err)}`);
|
|
170
199
|
}
|
|
171
200
|
}
|
|
@@ -175,10 +204,10 @@ const plugin = {
|
|
|
175
204
|
api.on(
|
|
176
205
|
'llm_output',
|
|
177
206
|
(event: PluginHookLlmOutputEvent, ctx: PluginHookAgentContext): void => {
|
|
178
|
-
const workspaceDir = ctx
|
|
207
|
+
const workspaceDir = resolveToolHookWorkspaceDir(ctx as unknown as Record<string, unknown>, api, 'llm_output');
|
|
179
208
|
try {
|
|
180
209
|
handleLlmOutput(event, { ...ctx, workspaceDir });
|
|
181
|
-
|
|
210
|
+
|
|
182
211
|
WorkspaceContext.fromHookContext({ workspaceDir }).eventLog.recordHookExecution({
|
|
183
212
|
hook: 'llm_output',
|
|
184
213
|
sessionId: ctx.sessionId
|
|
@@ -194,28 +223,16 @@ const plugin = {
|
|
|
194
223
|
}
|
|
195
224
|
);
|
|
196
225
|
|
|
197
|
-
// ── Hook: Message Sanitization ──
|
|
198
|
-
api.on(
|
|
199
|
-
'before_message_write',
|
|
200
|
-
(event: PluginHookBeforeMessageWriteEvent): PluginHookBeforeMessageWriteResult | void => {
|
|
201
|
-
try {
|
|
202
|
-
return handleBeforeMessageWrite(event);
|
|
203
|
-
} catch (err) {
|
|
204
|
-
api.logger.error(`[PD] Error in before_message_write: ${String(err)}`);
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
);
|
|
208
|
-
|
|
209
226
|
// ── Hook: Trajectory Collection (Behavior Evolution Phase 0) ──
|
|
210
227
|
// Note: after_tool_call and llm_output are safe to collect
|
|
211
|
-
// before_message_write conflicts with message-sanitize, skipping for now
|
|
212
228
|
api.on(
|
|
213
229
|
'after_tool_call',
|
|
214
230
|
(event: PluginHookAfterToolCallEvent, ctx: PluginHookToolContext): void => {
|
|
215
231
|
try {
|
|
216
|
-
const workspaceDir = ctx
|
|
232
|
+
const workspaceDir = resolveToolHookWorkspaceDir(ctx, api, 'trajectory.after_tool_call');
|
|
217
233
|
TrajectoryCollector.handleAfterToolCall(event, { ...ctx, workspaceDir });
|
|
218
|
-
|
|
234
|
+
// eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars -- Reason: catch binding intentionally unused
|
|
235
|
+
} catch (_err) {
|
|
219
236
|
// Non-critical: don't log, just skip
|
|
220
237
|
}
|
|
221
238
|
}
|
|
@@ -225,9 +242,10 @@ const plugin = {
|
|
|
225
242
|
'llm_output',
|
|
226
243
|
(event: PluginHookLlmOutputEvent, ctx: PluginHookAgentContext): void => {
|
|
227
244
|
try {
|
|
228
|
-
const workspaceDir = ctx
|
|
245
|
+
const workspaceDir = resolveToolHookWorkspaceDir(ctx as unknown as Record<string, unknown>, api, 'trajectory.llm_output');
|
|
229
246
|
TrajectoryCollector.handleLlmOutput(event, { ...ctx, workspaceDir });
|
|
230
|
-
|
|
247
|
+
// eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars -- Reason: catch binding intentionally unused
|
|
248
|
+
} catch (_err) {
|
|
231
249
|
// Non-critical: don't log, just skip
|
|
232
250
|
}
|
|
233
251
|
}
|
|
@@ -236,7 +254,8 @@ const plugin = {
|
|
|
236
254
|
// ── Hook: Subagent Loop Closure ──
|
|
237
255
|
api.on(
|
|
238
256
|
'subagent_spawning',
|
|
239
|
-
|
|
257
|
+
// eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars -- Reason: ctx param required by hook callback signature but not used in this handler
|
|
258
|
+
(event: PluginHookSubagentSpawningEvent, _ctx: PluginHookSubagentContext): void | PluginHookSubagentSpawningResult => {
|
|
240
259
|
try {
|
|
241
260
|
// Resolve workspace via official API, falling back to PathResolver
|
|
242
261
|
const workspaceDir = resolveWorkspaceDirFromApi(api, event.agentId) || '.';
|
|
@@ -259,7 +278,7 @@ const plugin = {
|
|
|
259
278
|
|
|
260
279
|
if (shouldRecordShadow) {
|
|
261
280
|
const observation = recordShadowRouting(workspaceDir, {
|
|
262
|
-
checkpointId: decision.activeCheckpointId!,
|
|
281
|
+
checkpointId: decision.activeCheckpointId!, // eslint-disable-line @typescript-eslint/no-non-null-assertion -- Reason: !!decision.activeCheckpointId guard above ensures truthiness
|
|
263
282
|
workerProfile: agentId as WorkerProfile,
|
|
264
283
|
taskFingerprint: computeRuntimeShadowTaskFingerprint(event),
|
|
265
284
|
});
|
|
@@ -327,6 +346,8 @@ const plugin = {
|
|
|
327
346
|
EvolutionWorkerService.api = api;
|
|
328
347
|
api.registerService(EvolutionWorkerService);
|
|
329
348
|
api.registerService(TrajectoryService);
|
|
349
|
+
api.registerService(PDTaskService);
|
|
350
|
+
api.registerService(CentralSyncService);
|
|
330
351
|
} catch (err) {
|
|
331
352
|
api.logger.error(`[PD] Failed to register EvolutionWorkerService: ${String(err)}`);
|
|
332
353
|
}
|
|
@@ -366,8 +387,8 @@ const plugin = {
|
|
|
366
387
|
api.registerCommand({
|
|
367
388
|
name: "pd-daily",
|
|
368
389
|
description: getCommandDescription('pd-daily', language),
|
|
369
|
-
handler: (
|
|
370
|
-
return { text: language === 'zh'
|
|
390
|
+
handler: () => {
|
|
391
|
+
return { text: language === 'zh'
|
|
371
392
|
? "请执行 pd-daily 技能来配置并发送进化日报。系统将引导你完成配置流程,包括发送时间、渠道和报告风格偏好。"
|
|
372
393
|
: "Please execute the pd-daily skill to configure and send your daily evolution report. The system will guide you through the configuration process." };
|
|
373
394
|
}
|
|
@@ -376,7 +397,7 @@ const plugin = {
|
|
|
376
397
|
api.registerCommand({
|
|
377
398
|
name: "pd-grooming",
|
|
378
399
|
description: getCommandDescription('pd-grooming', language),
|
|
379
|
-
handler: (
|
|
400
|
+
handler: () => {
|
|
380
401
|
return { text: language === 'zh'
|
|
381
402
|
? "请执行 pd-grooming 技能来执行大扫除。例如输入: '执行 pd-grooming 技能'"
|
|
382
403
|
: "Please execute the pd-grooming skill to clean up. For example: 'Execute pd-grooming skill'" };
|
|
@@ -386,7 +407,7 @@ const plugin = {
|
|
|
386
407
|
api.registerCommand({
|
|
387
408
|
name: "pd-help",
|
|
388
409
|
description: getCommandDescription('pd-help', language),
|
|
389
|
-
handler: (
|
|
410
|
+
handler: () => {
|
|
390
411
|
if (language === 'zh') {
|
|
391
412
|
return { text: `
|
|
392
413
|
📖 **Principles Disciple 命令大全**
|
|
@@ -687,6 +708,71 @@ const plugin = {
|
|
|
687
708
|
}
|
|
688
709
|
});
|
|
689
710
|
|
|
711
|
+
// ── Implementation Lifecycle Commands (Phase 13) ──
|
|
712
|
+
api.registerCommand({
|
|
713
|
+
name: "pd-promote-impl",
|
|
714
|
+
description: 'Promote a candidate implementation to active [list|show <id>|<id>]',
|
|
715
|
+
acceptsArgs: true,
|
|
716
|
+
handler: (ctx) => {
|
|
717
|
+
try {
|
|
718
|
+
const workspaceDir = api.resolvePath('.');
|
|
719
|
+
if (ctx.config) ctx.config.workspaceDir = workspaceDir;
|
|
720
|
+
return handlePromoteImplCommand(ctx);
|
|
721
|
+
} catch (err) {
|
|
722
|
+
api.logger.error(`[PD] Command /pd-promote-impl failed: ${String(err)}`);
|
|
723
|
+
return { text: language === 'zh' ? '\u547d\u4ee4\u6267\u884c\u5931\u8d25\uff0c\u8bf7\u68c0\u67e5\u65e5\u5fd7\u3002' : 'Command failed. Check logs.' };
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
});
|
|
727
|
+
|
|
728
|
+
api.registerCommand({
|
|
729
|
+
name: "pd-disable-impl",
|
|
730
|
+
description: 'Disable an active implementation [list|<id> --reason "..."]',
|
|
731
|
+
acceptsArgs: true,
|
|
732
|
+
handler: (ctx) => {
|
|
733
|
+
try {
|
|
734
|
+
const workspaceDir = api.resolvePath('.');
|
|
735
|
+
if (ctx.config) ctx.config.workspaceDir = workspaceDir;
|
|
736
|
+
return handleDisableImplCommand(ctx);
|
|
737
|
+
} catch (err) {
|
|
738
|
+
api.logger.error(`[PD] Command /pd-disable-impl failed: ${String(err)}`);
|
|
739
|
+
return { text: language === 'zh' ? '\u547d\u4ee4\u6267\u884c\u5931\u8d25\uff0c\u8bf7\u68c0\u67e5\u65e5\u5fd7\u3002' : 'Command failed. Check logs.' };
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
});
|
|
743
|
+
|
|
744
|
+
api.registerCommand({
|
|
745
|
+
name: "pd-archive-impl",
|
|
746
|
+
description: 'Archive an implementation permanently [list|<id>]',
|
|
747
|
+
acceptsArgs: true,
|
|
748
|
+
handler: (ctx) => {
|
|
749
|
+
try {
|
|
750
|
+
const workspaceDir = api.resolvePath('.');
|
|
751
|
+
if (ctx.config) ctx.config.workspaceDir = workspaceDir;
|
|
752
|
+
return handleArchiveImplCommand(ctx);
|
|
753
|
+
} catch (err) {
|
|
754
|
+
api.logger.error(`[PD] Command /pd-archive-impl failed: ${String(err)}`);
|
|
755
|
+
return { text: language === 'zh' ? '\u547d\u4ee4\u6267\u884c\u5931\u8d25\uff0c\u8bf7\u68c0\u67e5\u65e5\u5fd7\u3002' : 'Command failed. Check logs.' };
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
});
|
|
759
|
+
|
|
760
|
+
api.registerCommand({
|
|
761
|
+
name: "pd-rollback-impl",
|
|
762
|
+
description: 'Rollback current active implementation to previous active [list|<id> --reason "..."]',
|
|
763
|
+
acceptsArgs: true,
|
|
764
|
+
handler: (ctx) => {
|
|
765
|
+
try {
|
|
766
|
+
const workspaceDir = api.resolvePath('.');
|
|
767
|
+
if (ctx.config) ctx.config.workspaceDir = workspaceDir;
|
|
768
|
+
return handleRollbackImplCommand(ctx);
|
|
769
|
+
} catch (err) {
|
|
770
|
+
api.logger.error(`[PD] Command /pd-rollback-impl failed: ${String(err)}`);
|
|
771
|
+
return { text: language === 'zh' ? '\u547d\u4ee4\u6267\u884c\u5931\u8d25\uff0c\u8bf7\u68c0\u67e5\u65e5\u5fd7\u3002' : 'Command failed. Check logs.' };
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
});
|
|
775
|
+
|
|
690
776
|
api.registerTool(createDeepReflectTool(api));
|
|
691
777
|
}
|
|
692
778
|
};
|