evolcore 0.0.36 → 0.0.38
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 +18 -0
- package/dist/cli/restart-monitor.js +48 -42
- package/dist/utils/cross-platform.js +6 -2
- package/dist/utils/npm-ops.js +22 -6
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,24 @@
|
|
|
5
5
|
|
|
6
6
|
## Unreleased
|
|
7
7
|
|
|
8
|
+
## 0.0.38 (2026-10-24)
|
|
9
|
+
|
|
10
|
+
### npm 升级稳定性
|
|
11
|
+
|
|
12
|
+
- 修复 npm 升级在 registry 元数据暂未同步时误报目标版本不存在的问题。
|
|
13
|
+
- 改进升级失败诊断,保留 npm 错误码和具体错误信息,便于定位网络、权限和版本解析问题。
|
|
14
|
+
|
|
15
|
+
## 0.0.37 (2026-10-24)
|
|
16
|
+
|
|
17
|
+
### 升级与重启稳定性
|
|
18
|
+
|
|
19
|
+
- 修复升级重启过程中运行时资源版本不同步的问题,暂存运行文件时一并保留 `kits` 目录。
|
|
20
|
+
- 修复 daemon Owner 通知配置异常或发送失败时可能影响重启恢复流程的问题;通知失败会保留诊断并继续执行重启。
|
|
21
|
+
|
|
22
|
+
### 配置维护
|
|
23
|
+
|
|
24
|
+
- 改进本地 Provider 配置文件的忽略规则,避免运行时凭据文件被误加入 Git 工作区。
|
|
25
|
+
|
|
8
26
|
## 0.0.36 (2026-10-24)
|
|
9
27
|
|
|
10
28
|
### Agent 创建与所有权
|
|
@@ -1184,50 +1184,56 @@ function archiveSelfHealLog(p, log) {
|
|
|
1184
1184
|
log(`Archived self-heal log to ${archivePath}`);
|
|
1185
1185
|
}
|
|
1186
1186
|
async function notifyDaemonOwners(p, message, log) {
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
if (!isValidAid(daemonAid)) {
|
|
1194
|
-
log(`Daemon owner notification skipped: invalid daemon.json.aid ${daemonAid}`);
|
|
1195
|
-
return;
|
|
1196
|
-
}
|
|
1197
|
-
const response = await ipcQuery(p.socket, { type: 'aid.ownership', argv: ['aid', 'bind', 'status'] }, OWNER_NOTIFICATION_TIMEOUT_MS).catch(() => null);
|
|
1198
|
-
const state = response?.ok ? response.state : undefined;
|
|
1199
|
-
const owners = state?.subjectAid === daemonAid && state?.consensusStatus === 'consensus'
|
|
1200
|
-
&& typeof state.ownerAid === 'string' && isValidAid(state.ownerAid) ? [state.ownerAid] : [];
|
|
1201
|
-
if (owners.length === 0) {
|
|
1202
|
-
log('Daemon owner notification skipped: fresh protocol consensus unavailable');
|
|
1203
|
-
return;
|
|
1204
|
-
}
|
|
1205
|
-
const validOwners = owners.filter(owner => {
|
|
1206
|
-
const valid = isValidAid(owner);
|
|
1207
|
-
if (!valid)
|
|
1208
|
-
log(`Daemon owner notification skipped invalid owner AID: ${owner}`);
|
|
1209
|
-
return valid;
|
|
1210
|
-
});
|
|
1211
|
-
if (validOwners.length === 0)
|
|
1212
|
-
return;
|
|
1213
|
-
const text = formatDaemonOwnerNotice(p, message);
|
|
1214
|
-
for (const owner of validOwners) {
|
|
1215
|
-
try {
|
|
1216
|
-
const result = await withTimeout(msgSend({
|
|
1217
|
-
from: daemonAid,
|
|
1218
|
-
to: owner,
|
|
1219
|
-
body: { mode: 'text', text },
|
|
1220
|
-
slotId: 'restart-monitor',
|
|
1221
|
-
}), OWNER_NOTIFICATION_TIMEOUT_MS);
|
|
1222
|
-
if (!result.ok) {
|
|
1223
|
-
log(`Daemon owner notification failed for ${owner}: ${result.error}`);
|
|
1224
|
-
continue;
|
|
1225
|
-
}
|
|
1226
|
-
log(`Daemon owner notification sent to ${owner}: ${result.message_id}`);
|
|
1187
|
+
try {
|
|
1188
|
+
const cfg = loadDaemonConfig();
|
|
1189
|
+
const daemonAid = typeof cfg.aid === 'string' ? cfg.aid.trim() : '';
|
|
1190
|
+
if (!daemonAid) {
|
|
1191
|
+
log('Daemon owner notification skipped: daemon.json.aid not configured');
|
|
1192
|
+
return;
|
|
1227
1193
|
}
|
|
1228
|
-
|
|
1229
|
-
log(`Daemon owner notification
|
|
1194
|
+
if (!isValidAid(daemonAid)) {
|
|
1195
|
+
log(`Daemon owner notification skipped: invalid daemon.json.aid ${daemonAid}`);
|
|
1196
|
+
return;
|
|
1197
|
+
}
|
|
1198
|
+
const response = await ipcQuery(p.socket, { type: 'aid.ownership', argv: ['aid', 'bind', 'status'] }, OWNER_NOTIFICATION_TIMEOUT_MS).catch(() => null);
|
|
1199
|
+
const state = response?.ok ? response.state : undefined;
|
|
1200
|
+
const owners = state?.subjectAid === daemonAid && state?.consensusStatus === 'consensus'
|
|
1201
|
+
&& typeof state.ownerAid === 'string' && isValidAid(state.ownerAid) ? [state.ownerAid] : [];
|
|
1202
|
+
if (owners.length === 0) {
|
|
1203
|
+
log('Daemon owner notification skipped: fresh protocol consensus unavailable');
|
|
1204
|
+
return;
|
|
1230
1205
|
}
|
|
1206
|
+
const validOwners = owners.filter(owner => {
|
|
1207
|
+
const valid = isValidAid(owner);
|
|
1208
|
+
if (!valid)
|
|
1209
|
+
log(`Daemon owner notification skipped invalid owner AID: ${owner}`);
|
|
1210
|
+
return valid;
|
|
1211
|
+
});
|
|
1212
|
+
if (validOwners.length === 0)
|
|
1213
|
+
return;
|
|
1214
|
+
const text = formatDaemonOwnerNotice(p, message);
|
|
1215
|
+
for (const owner of validOwners) {
|
|
1216
|
+
try {
|
|
1217
|
+
const result = await withTimeout(msgSend({
|
|
1218
|
+
from: daemonAid,
|
|
1219
|
+
to: owner,
|
|
1220
|
+
body: { mode: 'text', text },
|
|
1221
|
+
slotId: 'restart-monitor',
|
|
1222
|
+
}), OWNER_NOTIFICATION_TIMEOUT_MS);
|
|
1223
|
+
if (!result.ok) {
|
|
1224
|
+
log(`Daemon owner notification failed for ${owner}: ${result.error}`);
|
|
1225
|
+
continue;
|
|
1226
|
+
}
|
|
1227
|
+
log(`Daemon owner notification sent to ${owner}: ${result.message_id}`);
|
|
1228
|
+
}
|
|
1229
|
+
catch (error) {
|
|
1230
|
+
log(`Daemon owner notification failed for ${owner}: ${error.message?.slice(0, 200) || error}`);
|
|
1231
|
+
}
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1234
|
+
catch (error) {
|
|
1235
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
1236
|
+
log(`WARN: Daemon owner notification failed: ${reason.slice(0, 200)}`);
|
|
1231
1237
|
}
|
|
1232
1238
|
}
|
|
1233
1239
|
function formatDaemonOwnerNotice(p, message) {
|
|
@@ -409,9 +409,10 @@ export async function launchMonitorAndConfirm(args, env, isAliveInRegistry, hasO
|
|
|
409
409
|
* in a checkout: `npm install -g` swaps the whole package directory, and the
|
|
410
410
|
* monitor has ~170 lazy `await import()` sites, so a module it has not loaded
|
|
411
411
|
* yet would come from the new version while the rest is still the old one.
|
|
412
|
-
* Staging `dist/` and `
|
|
412
|
+
* Staging `dist/`, `bin/` and `kits/` keeps package-owned code and runtime
|
|
413
|
+
* schemas on one version.
|
|
413
414
|
*
|
|
414
|
-
*
|
|
415
|
+
* `dist/`, `bin/`, `kits/` and `package.json` are copied. `node_modules` is
|
|
415
416
|
* linked, because copying it is hundreds of MB. The link degrades in steps so
|
|
416
417
|
* that no platform is left without a path forward:
|
|
417
418
|
*
|
|
@@ -447,6 +448,9 @@ export function prepareMonitorStage(packageRoot, stageParent) {
|
|
|
447
448
|
const binSource = path.join(packageRoot, 'bin');
|
|
448
449
|
if (fs.existsSync(binSource))
|
|
449
450
|
fs.cpSync(binSource, path.join(stageDir, 'bin'), { recursive: true });
|
|
451
|
+
const kitsSource = path.join(packageRoot, 'kits');
|
|
452
|
+
if (fs.existsSync(kitsSource))
|
|
453
|
+
fs.cpSync(kitsSource, path.join(stageDir, 'kits'), { recursive: true });
|
|
450
454
|
const pkgJson = path.join(packageRoot, 'package.json');
|
|
451
455
|
if (fs.existsSync(pkgJson))
|
|
452
456
|
fs.copyFileSync(pkgJson, path.join(stageDir, 'package.json'));
|
package/dist/utils/npm-ops.js
CHANGED
|
@@ -394,20 +394,36 @@ export async function preparePackageCache(target, registry, options = {}) {
|
|
|
394
394
|
const run = (args) => new Promise((resolve, reject) => {
|
|
395
395
|
let failure = null;
|
|
396
396
|
let output = '';
|
|
397
|
+
let errorOutput = '';
|
|
397
398
|
const child = execFile(npm.command, [...npm.argsPrefix, ...args, '--registry', registry, ...npmConfigArgs(options.npmConfig), '--ignore-scripts'], {
|
|
398
399
|
timeout: 180_000, windowsHide: isWindows, signal: options.signal, maxBuffer: 8 * 1024 * 1024,
|
|
399
|
-
}, (error, stdout) => {
|
|
400
|
+
}, (error, stdout, stderr) => {
|
|
401
|
+
failure = error;
|
|
402
|
+
output = String(stdout ?? '');
|
|
403
|
+
errorOutput = String(stderr ?? '');
|
|
404
|
+
});
|
|
400
405
|
child.once('error', error => { failure = error; });
|
|
401
406
|
child.once('close', code => {
|
|
402
|
-
if (failure
|
|
403
|
-
reject(new Error(options.signal?.aborted
|
|
404
|
-
? 'Package cache preparation timed out or was cancelled' : 'npm cache preparation failed; check registry connectivity, credentials, disk space and permissions'));
|
|
405
|
-
else
|
|
407
|
+
if (!failure && code === 0 && !options.signal?.aborted) {
|
|
406
408
|
resolve(output);
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
411
|
+
if (options.signal?.aborted) {
|
|
412
|
+
reject(new Error('Package cache preparation timed out or was cancelled'));
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
const codeText = failure && 'code' in failure && failure.code ? ` (${String(failure.code)})` : '';
|
|
416
|
+
const detail = (errorOutput || failure?.stderr || failure?.message || '')
|
|
417
|
+
.replace(/\s+/g, ' ').trim().slice(0, 500);
|
|
418
|
+
reject(new Error(`npm cache preparation failed${codeText}${detail ? `: ${detail}` : ''}`));
|
|
407
419
|
});
|
|
408
420
|
});
|
|
409
421
|
options.onPhase?.('downloading');
|
|
410
|
-
|
|
422
|
+
// Revalidate registry metadata before resolving the exact version. A stale
|
|
423
|
+
// install-v1 packument can otherwise report ETARGET even when the registry
|
|
424
|
+
// already contains the selected release. The tarball itself remains cached
|
|
425
|
+
// and is reused when npm can do so.
|
|
426
|
+
await run(['cache', 'add', spec, '--prefer-online']);
|
|
411
427
|
options.onPhase?.('tarball-check');
|
|
412
428
|
const metadata = JSON.parse(await run(['view', spec, 'name', 'version', 'dist', '--json', '--offline']));
|
|
413
429
|
const [packed] = JSON.parse(await run(['pack', spec, '--dry-run', '--json', '--offline']));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "evolcore",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.38",
|
|
4
4
|
"description": "AI Agent gateway connecting Claude, Codex, Gemini, and the bundled ecagent runner to messaging channels with multi-project session management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|