chore: stabilize Zhinian pilot delivery
This commit is contained in:
@@ -3,9 +3,9 @@
|
||||
* Cross-platform path resolution helpers
|
||||
*/
|
||||
import { createRequire } from 'node:module';
|
||||
import { dirname, isAbsolute, join, normalize } from 'path';
|
||||
import { basename, dirname, isAbsolute, join, normalize } from 'path';
|
||||
import { homedir } from 'os';
|
||||
import { cpSync, existsSync, mkdirSync, readFileSync, realpathSync, rmSync } from 'fs';
|
||||
import { cpSync, existsSync, mkdirSync, readFileSync, realpathSync, rmSync, symlinkSync } from 'fs';
|
||||
import { cleanupOpenClawRuntimeNativeClipboard } from './optional-native-cleanup';
|
||||
|
||||
const require = createRequire(import.meta.url);
|
||||
@@ -35,7 +35,12 @@ const REQUIRED_OPENCLAW_CONTEXT_MODULES = [
|
||||
'qrcode-terminal/vendor/QRCode/QRErrorCorrectLevel.js',
|
||||
] as const;
|
||||
const YINIAN_OPENCLAW_RUNTIME_PATCH_MARKER = '.yinian-runtime-patch.json';
|
||||
const YINIAN_OPENCLAW_RUNTIME_PATCH_VERSION = '2026-05-07-desktop-fast-chat-v1';
|
||||
const YINIAN_OPENCLAW_RUNTIME_PATCH_VERSION = '2026-05-12-runtime-templates-selfref-v1';
|
||||
const REQUIRED_OPENCLAW_RUNTIME_TEMPLATE_FILES = [
|
||||
'AGENTS.md',
|
||||
'TOOLS.md',
|
||||
'HEARTBEAT.md',
|
||||
] as const;
|
||||
|
||||
export {
|
||||
quoteForCmd,
|
||||
@@ -190,8 +195,59 @@ function hasYinianOpenClawRuntimePatch(dir: string): boolean {
|
||||
return readYinianOpenClawRuntimePatchVersion(dir) === YINIAN_OPENCLAW_RUNTIME_PATCH_VERSION;
|
||||
}
|
||||
|
||||
function hasRequiredOpenClawRuntimeTemplates(dir: string): boolean {
|
||||
return REQUIRED_OPENCLAW_RUNTIME_TEMPLATE_FILES.every((fileName) => (
|
||||
existsSync(fsPath(join(dir, 'docs', 'reference', 'templates', fileName)))
|
||||
));
|
||||
}
|
||||
|
||||
function isNodeModulesPackagePath(dir: string): boolean {
|
||||
try {
|
||||
const realDir = realpathSync(fsPath(dir));
|
||||
return basename(realDir) === 'openclaw' && basename(dirname(realDir)) === 'node_modules';
|
||||
} catch {
|
||||
return basename(dir) === 'openclaw' && basename(dirname(dir)) === 'node_modules';
|
||||
}
|
||||
}
|
||||
|
||||
function hasOpenClawSelfReference(dir: string): boolean {
|
||||
if (isNodeModulesPackagePath(dir)) return true;
|
||||
const selfRefDir = join(dir, 'node_modules', 'openclaw');
|
||||
if (!existsSync(fsPath(join(selfRefDir, 'package.json')))) return false;
|
||||
|
||||
try {
|
||||
return realpathSync(fsPath(selfRefDir)) === realpathSync(fsPath(dir));
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function ensureOpenClawSelfReference(dir: string): void {
|
||||
if (!isValidOpenClawPackageDir(dir) || hasOpenClawSelfReference(dir)) return;
|
||||
|
||||
const nodeModulesDir = join(dir, 'node_modules');
|
||||
const selfRefDir = join(nodeModulesDir, 'openclaw');
|
||||
try {
|
||||
rmSync(fsPath(selfRefDir), { recursive: true, force: true });
|
||||
mkdirSync(fsPath(nodeModulesDir), { recursive: true });
|
||||
symlinkSync(
|
||||
process.platform === 'win32' ? fsPath(dir) : '..',
|
||||
fsPath(selfRefDir),
|
||||
process.platform === 'win32' ? 'junction' : 'dir',
|
||||
);
|
||||
} catch (error) {
|
||||
logOpenClawRuntime('[openclaw-runtime] Failed to create OpenClaw self-reference for managed runtime', {
|
||||
dir,
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function hasPackagedOpenClawRuntimeRequirements(dir: string): boolean {
|
||||
return hasRequiredOpenClawContextModules(dir) && hasYinianOpenClawRuntimePatch(dir);
|
||||
return hasRequiredOpenClawContextModules(dir)
|
||||
&& hasRequiredOpenClawRuntimeTemplates(dir)
|
||||
&& hasOpenClawSelfReference(dir)
|
||||
&& hasYinianOpenClawRuntimePatch(dir);
|
||||
}
|
||||
|
||||
function samePath(left: string, right: string): boolean {
|
||||
@@ -312,6 +368,7 @@ function installBundledOpenClawToManagedRuntime(bundledDir: string, managedDir:
|
||||
rmSync(fsPath(managedDir), { recursive: true, force: true });
|
||||
cpSync(fsPath(tempDir), fsPath(managedDir), { recursive: true, dereference: true });
|
||||
rmSync(fsPath(tempDir), { recursive: true, force: true });
|
||||
ensureOpenClawSelfReference(managedDir);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -389,6 +446,9 @@ function resolveOpenClawRuntime(): OpenClawRuntimeResolution {
|
||||
logOpenClawRuntime('[openclaw-runtime] Ignoring managed OpenClaw runtime because it is not a patched Yinian runtime', {
|
||||
managedDir,
|
||||
requiredModules: REQUIRED_OPENCLAW_CONTEXT_MODULES,
|
||||
requiredTemplates: REQUIRED_OPENCLAW_RUNTIME_TEMPLATE_FILES,
|
||||
hasRuntimeTemplates: hasRequiredOpenClawRuntimeTemplates(managedDir),
|
||||
hasSelfReference: hasOpenClawSelfReference(managedDir),
|
||||
runtimePatchVersion: readYinianOpenClawRuntimePatchVersion(managedDir) ?? null,
|
||||
expectedRuntimePatchVersion: YINIAN_OPENCLAW_RUNTIME_PATCH_VERSION,
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user