principles-disciple 1.56.0 → 1.58.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/openclaw.plugin.json
CHANGED
package/package.json
CHANGED
package/scripts/sync-plugin.mjs
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* --help Show help message
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
-
import { copyFileSync, cpSync, existsSync, rmSync, readFileSync, readFileSync as readFileSyncRaw, mkdirSync, writeFileSync, readdirSync } from 'fs';
|
|
20
|
+
import { copyFileSync, cpSync, existsSync, lstatSync, rmSync, readFileSync, readFileSync as readFileSyncRaw, mkdirSync, writeFileSync, readdirSync } from 'fs';
|
|
21
21
|
import { createHash } from 'crypto';
|
|
22
22
|
import { join, dirname } from 'path';
|
|
23
23
|
import { fileURLToPath } from 'url';
|
|
@@ -80,7 +80,7 @@ function parseArgs() {
|
|
|
80
80
|
skipBuild: false,
|
|
81
81
|
skipDeps: false,
|
|
82
82
|
force: false,
|
|
83
|
-
restart:
|
|
83
|
+
restart: true,
|
|
84
84
|
dev: false,
|
|
85
85
|
bump: false,
|
|
86
86
|
help: false,
|
|
@@ -100,7 +100,8 @@ function parseArgs() {
|
|
|
100
100
|
args.skipDeps = true;
|
|
101
101
|
break;
|
|
102
102
|
case '--restart':
|
|
103
|
-
|
|
103
|
+
case '--no-restart':
|
|
104
|
+
args.restart = !arg.startsWith('--no-');
|
|
104
105
|
break;
|
|
105
106
|
case '--dev':
|
|
106
107
|
case '-d':
|
|
@@ -145,7 +146,7 @@ Options:
|
|
|
145
146
|
--lang <zh|en> Language for skills (default: zh)
|
|
146
147
|
--skip-build Skip build step (use existing dist/)
|
|
147
148
|
--skip-deps Skip dependency installation
|
|
148
|
-
--restart
|
|
149
|
+
--restart Automatically restart OpenClaw gateway after installation (default: true, use --no-restart to skip)
|
|
149
150
|
--dev, -d Developer mode: --force + --restart + --bump + clean stale backups
|
|
150
151
|
--bump, -b Auto-bump patch version if there are uncommitted source changes
|
|
151
152
|
--force, -f Force overwrite without prompts
|
|
@@ -610,6 +611,58 @@ function syncItem(item) {
|
|
|
610
611
|
}
|
|
611
612
|
}
|
|
612
613
|
|
|
614
|
+
/**
|
|
615
|
+
* Recursive directory copy (Windows-safe, no symlinks).
|
|
616
|
+
*/
|
|
617
|
+
function copyDir(src, dest) {
|
|
618
|
+
mkdirSync(dest, { recursive: true });
|
|
619
|
+
for (const entry of readdirSync(src)) {
|
|
620
|
+
const srcPath = join(src, entry);
|
|
621
|
+
const destPath = join(dest, entry);
|
|
622
|
+
if (lstatSync(srcPath).isDirectory()) {
|
|
623
|
+
copyDir(srcPath, destPath);
|
|
624
|
+
} else {
|
|
625
|
+
copyFileSync(srcPath, destPath);
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
/**
|
|
631
|
+
* Inject local workspace packages (monorepo) into node_modules before npm install.
|
|
632
|
+
* @principles/core is a workspace package, not published to npm — we must copy it
|
|
633
|
+
* from the monorepo's node_modules so npm install --production doesn't 404 it.
|
|
634
|
+
*/
|
|
635
|
+
function injectLocalWorkspacePackages() {
|
|
636
|
+
const monorepoModules = join(SOURCE_DIR, '..', '..', 'node_modules', '@principles', 'core');
|
|
637
|
+
const targetModules = join(INSTALL_DIR, 'node_modules', '@principles', 'core');
|
|
638
|
+
|
|
639
|
+
if (!existsSync(monorepoModules)) {
|
|
640
|
+
// Not in monorepo context (e.g., npm pack / CI tarball) — skip
|
|
641
|
+
return;
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
console.log(' 📦 Injecting local workspace packages (@principles/core)...');
|
|
645
|
+
mkdirSync(dirname(targetModules), { recursive: true });
|
|
646
|
+
// cpSync creates symlinks on Windows for symlinked dirs — use cp -rL (dereference) via exec
|
|
647
|
+
let injected = false;
|
|
648
|
+
try {
|
|
649
|
+
execSync(`cp -rL "${monorepoModules}" "${targetModules}"`, { stdio: 'ignore' });
|
|
650
|
+
injected = true;
|
|
651
|
+
} catch {
|
|
652
|
+
// Fallback: manual copy via node (Windows-compatible)
|
|
653
|
+
try {
|
|
654
|
+
copyDir(monorepoModules, targetModules);
|
|
655
|
+
injected = true;
|
|
656
|
+
} catch (copyErr) {
|
|
657
|
+
console.warn(' ⚠️ Failed to inject @principles/core from monorepo: ' + copyErr.message);
|
|
658
|
+
console.warn(' ⚠️ npm install --production may fail if @principles/core is not published');
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
if (injected && !existsSync(targetModules)) {
|
|
662
|
+
console.warn(' ⚠️ Injection reported success but target not found: ' + targetModules);
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
|
|
613
666
|
/**
|
|
614
667
|
* Install production dependencies in target.
|
|
615
668
|
*/
|
|
@@ -844,6 +897,7 @@ function main() {
|
|
|
844
897
|
for (const item of SYNC_ITEMS) syncItem(item);
|
|
845
898
|
syncSkills(args.lang);
|
|
846
899
|
|
|
900
|
+
injectLocalWorkspacePackages();
|
|
847
901
|
installTargetDependencies();
|
|
848
902
|
|
|
849
903
|
console.log('\n🔍 Verifying installed plugin can load native dependencies...');
|
|
@@ -260,7 +260,7 @@ export class EvolutionLogger {
|
|
|
260
260
|
logCompleted(params: {
|
|
261
261
|
traceId: string;
|
|
262
262
|
taskId: string;
|
|
263
|
-
resolution: 'marker_detected' | 'auto_completed_timeout' | 'manual' | 'late_marker_principle_created' | 'late_marker_no_principle' | 'diagnostician_timeout';
|
|
263
|
+
resolution: 'marker_detected' | 'auto_completed_timeout' | 'manual' | 'late_marker_principle_created' | 'late_marker_no_principle' | 'diagnostician_timeout' | 'noise_classified' | 'duplicate' | 'serverDuplicate';
|
|
264
264
|
durationMs?: number;
|
|
265
265
|
principlesGenerated?: number;
|
|
266
266
|
}): void {
|
|
@@ -271,6 +271,8 @@ export class EvolutionLogger {
|
|
|
271
271
|
summary = `任务 ${params.taskId} 完成,已生成 ${params.principlesGenerated || 0} 条原则`;
|
|
272
272
|
} else if (params.resolution === 'auto_completed_timeout' || params.resolution === 'diagnostician_timeout' || params.resolution === 'late_marker_no_principle') {
|
|
273
273
|
summary = `任务 ${params.taskId} 超时自动完成`;
|
|
274
|
+
} else if (params.resolution === 'noise_classified' || params.resolution === 'duplicate' || params.resolution === 'serverDuplicate') {
|
|
275
|
+
summary = `任务 ${params.taskId} 分类为噪音/重复,已过滤`;
|
|
274
276
|
} else {
|
|
275
277
|
summary = `任务 ${params.taskId} 已完成`;
|
|
276
278
|
}
|
|
@@ -921,6 +921,7 @@ async function processEvolutionQueue(wctx: WorkspaceContext, logger: PluginLogge
|
|
|
921
921
|
if (fs.existsSync(completeMarker)) {
|
|
922
922
|
if (logger) logger.info(`[PD:EvolutionWorker] Task ${task.id} completed - marker file detected`);
|
|
923
923
|
|
|
924
|
+
let principlesGenerated = 0;
|
|
924
925
|
// Create principle from the diagnostician's JSON report.
|
|
925
926
|
const reportPath = path.join(wctx.stateDir, `.diagnostician_report_${task.id}.json`);
|
|
926
927
|
if (fs.existsSync(reportPath)) {
|
|
@@ -1021,6 +1022,7 @@ async function processEvolutionQueue(wctx: WorkspaceContext, logger: PluginLogge
|
|
|
1021
1022
|
});
|
|
1022
1023
|
if (principleId) {
|
|
1023
1024
|
logger.info(`[PD:EvolutionWorker] Created principle ${principleId} from marker fallback for task ${task.id}`);
|
|
1025
|
+
principlesGenerated = 1;
|
|
1024
1026
|
} else {
|
|
1025
1027
|
logger.warn(`[PD:EvolutionWorker] createPrincipleFromDiagnosis returned null for task ${task.id} (may be duplicate or blacklisted)`);
|
|
1026
1028
|
}
|
|
@@ -1042,7 +1044,8 @@ async function processEvolutionQueue(wctx: WorkspaceContext, logger: PluginLogge
|
|
|
1042
1044
|
|
|
1043
1045
|
task.status = 'completed';
|
|
1044
1046
|
task.completed_at = new Date().toISOString();
|
|
1045
|
-
|
|
1047
|
+
// resolution already set by each branch (noise_classified | marker_detected)
|
|
1048
|
+
if (!task.resolution) task.resolution = 'marker_detected';
|
|
1046
1049
|
try {
|
|
1047
1050
|
fs.unlinkSync(completeMarker);
|
|
1048
1051
|
} catch { /* marker may have been deleted already, not critical */ }
|
|
@@ -1063,8 +1066,9 @@ async function processEvolutionQueue(wctx: WorkspaceContext, logger: PluginLogge
|
|
|
1063
1066
|
evoLogger.logCompleted({
|
|
1064
1067
|
traceId: task.traceId || task.id,
|
|
1065
1068
|
taskId: task.id,
|
|
1066
|
-
resolution: 'marker_detected',
|
|
1069
|
+
resolution: task.resolution as 'marker_detected' | 'auto_completed_timeout' | 'manual' | 'late_marker_principle_created' | 'late_marker_no_principle' | 'diagnostician_timeout',
|
|
1067
1070
|
durationMs,
|
|
1071
|
+
principlesGenerated,
|
|
1068
1072
|
});
|
|
1069
1073
|
|
|
1070
1074
|
// Record task completion in event stats
|
|
@@ -1078,14 +1082,14 @@ async function processEvolutionQueue(wctx: WorkspaceContext, logger: PluginLogge
|
|
|
1078
1082
|
wctx.trajectory?.updateEvolutionTask?.(task.id, {
|
|
1079
1083
|
status: 'completed',
|
|
1080
1084
|
completedAt: task.completed_at,
|
|
1081
|
-
resolution: 'marker_detected',
|
|
1085
|
+
resolution: task.resolution as 'marker_detected' | 'auto_completed_timeout' | 'manual' | 'late_marker_principle_created' | 'late_marker_no_principle' | 'diagnostician_timeout',
|
|
1082
1086
|
});
|
|
1083
1087
|
|
|
1084
1088
|
wctx.trajectory?.recordTaskOutcome({
|
|
1085
1089
|
sessionId: task.assigned_session_key || 'heartbeat:diagnostician',
|
|
1086
1090
|
taskId: task.id,
|
|
1087
1091
|
outcome: 'ok',
|
|
1088
|
-
summary: `Task ${task.id} completed
|
|
1092
|
+
summary: `Task ${task.id} completed — ${principlesGenerated} principle(s) generated (${task.resolution}).`
|
|
1089
1093
|
});
|
|
1090
1094
|
queueChanged = true;
|
|
1091
1095
|
continue;
|
|
@@ -1098,9 +1102,11 @@ async function processEvolutionQueue(wctx: WorkspaceContext, logger: PluginLogge
|
|
|
1098
1102
|
const timeoutCompleteMarker = path.join(wctx.stateDir, `.evolution_complete_${task.id}`);
|
|
1099
1103
|
const timeoutReportPath = path.join(wctx.stateDir, `.diagnostician_report_${task.id}.json`);
|
|
1100
1104
|
|
|
1105
|
+
let principlesGenerated = 0;
|
|
1106
|
+
|
|
1107
|
+
|
|
1101
1108
|
if (fs.existsSync(timeoutCompleteMarker) && fs.existsSync(timeoutReportPath)) {
|
|
1102
1109
|
if (logger) logger.info(`[PD:EvolutionWorker] Task ${task.id} timed out but marker found — creating principle anyway`);
|
|
1103
|
-
let principleCreated = false;
|
|
1104
1110
|
try {
|
|
1105
1111
|
const reportData = JSON.parse(fs.readFileSync(timeoutReportPath, 'utf8'));
|
|
1106
1112
|
const principle = reportData?.principle
|
|
@@ -1126,7 +1132,7 @@ async function processEvolutionQueue(wctx: WorkspaceContext, logger: PluginLogge
|
|
|
1126
1132
|
});
|
|
1127
1133
|
if (principleId) {
|
|
1128
1134
|
logger.info(`[PD:EvolutionWorker] Created principle ${principleId} from late marker for task ${task.id}`);
|
|
1129
|
-
|
|
1135
|
+
principlesGenerated = 1;
|
|
1130
1136
|
}
|
|
1131
1137
|
}
|
|
1132
1138
|
}
|
|
@@ -1139,7 +1145,7 @@ async function processEvolutionQueue(wctx: WorkspaceContext, logger: PluginLogge
|
|
|
1139
1145
|
const lateReportPath = path.join(wctx.stateDir, `.diagnostician_report_${task.id}.json`);
|
|
1140
1146
|
if (fs.existsSync(lateReportPath)) fs.unlinkSync(lateReportPath);
|
|
1141
1147
|
} catch { /* report may not exist, not critical */ }
|
|
1142
|
-
task.resolution =
|
|
1148
|
+
task.resolution = principlesGenerated > 0 ? 'late_marker_principle_created' : 'late_marker_no_principle';
|
|
1143
1149
|
} else {
|
|
1144
1150
|
if (logger) logger.info(`[PD:EvolutionWorker] Task ${task.id} auto-completed after ${timeoutMinutes} minute timeout`);
|
|
1145
1151
|
// #190: Clean up diagnostician report file even on timeout (may have been written late)
|
|
@@ -1160,6 +1166,7 @@ async function processEvolutionQueue(wctx: WorkspaceContext, logger: PluginLogge
|
|
|
1160
1166
|
taskId: task.id,
|
|
1161
1167
|
resolution: task.resolution,
|
|
1162
1168
|
durationMs: age,
|
|
1169
|
+
principlesGenerated,
|
|
1163
1170
|
});
|
|
1164
1171
|
|
|
1165
1172
|
// Record task completion in event stats (for timeout path too)
|
|
@@ -1180,7 +1187,7 @@ async function processEvolutionQueue(wctx: WorkspaceContext, logger: PluginLogge
|
|
|
1180
1187
|
sessionId: task.assigned_session_key || 'heartbeat:diagnostician',
|
|
1181
1188
|
taskId: task.id,
|
|
1182
1189
|
outcome: 'timeout',
|
|
1183
|
-
summary: `Task ${task.id}
|
|
1190
|
+
summary: `Task ${task.id} completed — ${principlesGenerated} principle(s) generated (${task.resolution}).`
|
|
1184
1191
|
});
|
|
1185
1192
|
queueChanged = true;
|
|
1186
1193
|
}
|