426e9eeabd
Voice Workbench / headless workbench (mocked backends) (push) Has been cancelled
Voice Workbench / real acoustic lane (nightly, provisioned only) (push) Has been cancelled
ci / test (push) Has been cancelled
ci / lint-and-format (push) Has been cancelled
ci / build (push) Has been cancelled
ci / dev-startup (push) Has been cancelled
gitleaks / gitleaks (push) Has been cancelled
Markdown Links / Relative Markdown Links (push) Has been cancelled
Quality (Extended) / Homepage Build (PR smoke) (push) Has been cancelled
Quality (Extended) / Comment-only diff guard (push) Has been cancelled
Quality (Extended) / Format + Type Safety Ratchet (push) Has been cancelled
Quality (Extended) / Develop Gate (secret scan + UI determinism) (push) Has been cancelled
Quality (Extended) / Develop Gate (lint) (push) Has been cancelled
Chat shell gestures / Chat shell gesture + parity e2e (push) Has been cancelled
Cloud Gateway Discord / Test (push) Has been cancelled
Benchmark Bridge Tests / benchmark (bunx @biomejs/biome check packages/lifeops-bench/src, benchmark-lint) (push) Has been cancelled
Benchmark Bridge Tests / benchmark (bunx vitest run --config packages/lifeops-bench/vitest.config.ts --root packages/lifeops-bench --passWithNoTests, benchmark-tests) (push) Has been cancelled
Build Agent Image / build-and-push (push) Has been cancelled
Dev Smoke / bun run dev onboarding chat (push) Has been cancelled
Dev Smoke / Vite HMR dependency-level smoke (push) Has been cancelled
Electrobun Submodule Guard / electrobun gitlink is fetchable (push) Has been cancelled
Publish @elizaos/example-code / check_npm (push) Has been cancelled
Publish @elizaos/example-code / publish_npm (push) Has been cancelled
Publish @elizaos/plugin-elizacloud / verify_version (push) Has been cancelled
Publish @elizaos/plugin-elizacloud / publish_npm (push) Has been cancelled
Sandbox Live Smoke / Sandbox live smoke (push) Has been cancelled
Snap Build & Test / Build Snap (amd64) (push) Has been cancelled
Snap Build & Test / Build Snap (arm64) (push) Has been cancelled
Test Packaging / elizaos CLI global-install smoke (node + bun) (push) Has been cancelled
Cloud Gateway Webhook / Test (push) Has been cancelled
Cloud Tests / lint-and-types (push) Has been cancelled
Cloud Tests / unit-tests (push) Has been cancelled
Cloud Tests / integration-tests (push) Has been cancelled
Cloud Tests / e2e-tests (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Deploy Apps Worker (Product 2) / Determine environment (push) Has been cancelled
Deploy Apps Worker (Product 2) / Deploy apps worker to apps-control host (${{ needs.determine-env.outputs.environment }}) (push) Has been cancelled
Deploy Eliza Provisioning Worker / Determine environment (push) Has been cancelled
Deploy Eliza Provisioning Worker / Deploy worker to Hetzner host (${{ needs.determine-env.outputs.environment }} @ ${{ needs.determine-env.outputs.deployment_sha }}) (push) Has been cancelled
Dev Smoke / Classify changed paths (push) Has been cancelled
supply-chain / sbom (push) Has been cancelled
supply-chain / vulnerability-scan (push) Has been cancelled
Build, Push & Deploy to Phala Cloud / build-and-push (push) Has been cancelled
Test Packaging / Validate Packaging Configs (push) Has been cancelled
Test Packaging / Build & Test PyPI Package (push) Has been cancelled
Test Packaging / PyPI on Python ${{ matrix.python }} (push) Has been cancelled
Test Packaging / Pack & Test JS Tarballs (push) Has been cancelled
UI Fixture E2E / ui-fixture-e2e (push) Has been cancelled
UI Fixture E2E / fixture-e2e (push) Has been cancelled
UI Story Gate / story-gate (push) Has been cancelled
vault-ci / test (macos-latest) (push) Has been cancelled
vault-ci / test (ubuntu-latest) (push) Has been cancelled
vault-ci / test (windows-latest) (push) Has been cancelled
vault-ci / app-core wiring tests (push) Has been cancelled
verify-patches / verify patches/CHECKSUMS.sha256 (push) Has been cancelled
Voice Benchmark Smoke / voice-emotion fixture smoke (push) Has been cancelled
Voice Benchmark Smoke / voiceagentbench fixture smoke (push) Has been cancelled
Voice Benchmark Smoke / voicebench-quality unit smoke (push) Has been cancelled
Voice Benchmark Smoke / voicebench TypeScript unit (no audio) (push) Has been cancelled
Voice Benchmark Smoke / voice bench smoke summary (push) Has been cancelled
Windows CI / windows ([bun run --cwd packages/app-core test bun run --cwd packages/elizaos test bun run --cwd packages/cloud/shared test], app-and-cli) (push) Has been cancelled
Windows CI / windows ([bun run --cwd packages/scenario-runner test bun run --cwd packages/vault test bun run --cwd packages/security test bun run --cwd plugins/plugin-coding-tools test], framework-packages) (push) Has been cancelled
Windows CI / windows ([bun run --cwd plugins/plugin-elizacloud test bun run --cwd plugins/plugin-discord test bun run --cwd plugins/plugin-anthropic test bun run --cwd plugins/plugin-openai test bun run --cwd plugins/plugin-app-control test bun run --cwd plugins/pl… (push) Has been cancelled
Windows CI / windows ([node packages/scripts/run-turbo.mjs run build --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/agent --concurrency=4 node packages/scripts/run-bash-linux-only.mjs scripts/verify-riscv64-buildpaths.sh node packages/scripts/run… (push) Has been cancelled
Windows CI / windows ([node packages/scripts/run-turbo.mjs run typecheck --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/cloud-shared --concurrency=4 bun run --cwd packages/core test bun run --cwd packages/shared test], core-runtime, 75) (push) Has been cancelled
537 lines
15 KiB
JavaScript
Executable File
537 lines
15 KiB
JavaScript
Executable File
#!/usr/bin/env node
|
|
// Supports Linux live-image build and release evidence automation.
|
|
|
|
import fs from "node:fs";
|
|
import path from "node:path";
|
|
import process from "node:process";
|
|
import { fileURLToPath } from "node:url";
|
|
|
|
const args = process.argv.slice(2);
|
|
const distroRoot = path.resolve(
|
|
path.dirname(fileURLToPath(import.meta.url)),
|
|
"..",
|
|
);
|
|
const defaultStage = path.join(
|
|
distroRoot,
|
|
"tails/config/chroot_local-includes/usr/share/elizaos/elizaos-app",
|
|
);
|
|
const defaultOsOverlayRoot = path.join(
|
|
distroRoot,
|
|
"tails/config/chroot_local-includes",
|
|
);
|
|
|
|
function parseArgs(argv) {
|
|
const parsed = {
|
|
stage: process.env.ELIZAOS_APP_STAGE ?? defaultStage,
|
|
osOverlayRoot: defaultOsOverlayRoot,
|
|
};
|
|
|
|
for (let index = 0; index < argv.length; index += 1) {
|
|
const arg = argv[index];
|
|
if (arg === "--stage") {
|
|
parsed.stage = argv[index + 1];
|
|
index += 1;
|
|
continue;
|
|
}
|
|
if (arg.startsWith("--stage=")) {
|
|
parsed.stage = arg.slice("--stage=".length);
|
|
continue;
|
|
}
|
|
if (arg === "--os-overlay-root") {
|
|
parsed.osOverlayRoot = argv[index + 1];
|
|
index += 1;
|
|
continue;
|
|
}
|
|
if (arg.startsWith("--os-overlay-root=")) {
|
|
parsed.osOverlayRoot = arg.slice("--os-overlay-root=".length);
|
|
continue;
|
|
}
|
|
if (!arg.startsWith("--")) {
|
|
parsed.stage = arg;
|
|
}
|
|
}
|
|
|
|
return {
|
|
stage: path.resolve(parsed.stage),
|
|
osOverlayRoot: path.resolve(parsed.osOverlayRoot),
|
|
};
|
|
}
|
|
|
|
const { stage, osOverlayRoot } = parseArgs(args);
|
|
const manifestPath = path.join(
|
|
stage,
|
|
"Resources/app/elizaos-live-overlay-manifest.json",
|
|
);
|
|
const errors = [];
|
|
const warnings = [];
|
|
|
|
function fail(message) {
|
|
errors.push(message);
|
|
}
|
|
|
|
function warn(message) {
|
|
warnings.push(message);
|
|
}
|
|
|
|
function readJson(filePath) {
|
|
try {
|
|
return JSON.parse(fs.readFileSync(filePath, "utf8"));
|
|
} catch (error) {
|
|
fail(`${filePath}: cannot read JSON: ${error.message}`);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
function readText(filePath) {
|
|
try {
|
|
return fs.readFileSync(filePath, "utf8");
|
|
} catch (error) {
|
|
fail(`${filePath}: cannot read file: ${error.message}`);
|
|
return "";
|
|
}
|
|
}
|
|
|
|
function assertFile(filePath, label) {
|
|
if (!fs.existsSync(filePath)) {
|
|
fail(`${label} missing: ${filePath}`);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
function assertExecutable(filePath, label) {
|
|
if (!assertFile(filePath, label)) return;
|
|
const mode = fs.statSync(filePath).mode;
|
|
if ((mode & 0o111) === 0) {
|
|
fail(`${label} is not executable: ${filePath}`);
|
|
}
|
|
}
|
|
|
|
function assertContains(filePath, needle, label) {
|
|
if (!assertFile(filePath, label)) return;
|
|
const text = readText(filePath);
|
|
if (!text.includes(needle)) {
|
|
fail(`${label} does not contain ${JSON.stringify(needle)}: ${filePath}`);
|
|
}
|
|
}
|
|
|
|
function walkFiles(dir, visit) {
|
|
if (!fs.existsSync(dir)) return;
|
|
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
const fullPath = path.join(dir, entry.name);
|
|
if (entry.isDirectory()) {
|
|
walkFiles(fullPath, visit);
|
|
} else if (entry.isFile()) {
|
|
visit(fullPath);
|
|
}
|
|
}
|
|
}
|
|
|
|
function packageDirectory(packageName) {
|
|
return path.join(
|
|
stage,
|
|
"Resources/app/eliza-dist/node_modules",
|
|
...packageName.split("/"),
|
|
);
|
|
}
|
|
|
|
function packageManifestPath(packageName) {
|
|
return path.join(packageDirectory(packageName), "package.json");
|
|
}
|
|
|
|
function packageNameFromManifest(filePath, packageJson) {
|
|
if (typeof packageJson?.name === "string" && packageJson.name) {
|
|
return packageJson.name;
|
|
}
|
|
const relative = path.relative(
|
|
path.join(stage, "Resources/app/eliza-dist/node_modules"),
|
|
path.dirname(filePath),
|
|
);
|
|
const parts = relative.split(path.sep);
|
|
if (parts[0]?.startsWith("@")) return `${parts[0]}/${parts[1]}`;
|
|
return parts[0] ?? relative;
|
|
}
|
|
|
|
function relativeToStage(filePath) {
|
|
return path.relative(stage, filePath).split(path.sep).join("/");
|
|
}
|
|
|
|
function validateEntrypoints(manifest) {
|
|
for (const entry of manifest.entrypoints ?? []) {
|
|
if (!entry.required) continue;
|
|
const filePath = path.join(stage, entry.stagePath);
|
|
if (entry.executable) {
|
|
assertExecutable(filePath, entry.name);
|
|
} else {
|
|
assertFile(filePath, entry.name);
|
|
}
|
|
}
|
|
|
|
for (const entry of manifest.osEntrypoints ?? []) {
|
|
if (!entry.required) continue;
|
|
const filePath = path.join(osOverlayRoot, entry.sourcePath);
|
|
if (entry.executable) {
|
|
assertExecutable(filePath, entry.name);
|
|
} else {
|
|
assertFile(filePath, entry.name);
|
|
}
|
|
}
|
|
}
|
|
|
|
function validateGeneratedStubs(manifest) {
|
|
const explicitOptionalStubs = manifest.generated?.optionalPluginStubs ?? [];
|
|
if (explicitOptionalStubs.length === 0) {
|
|
fail("manifest does not explicitly enumerate optional plugin stubs");
|
|
}
|
|
|
|
for (const stub of explicitOptionalStubs) {
|
|
const packagePath = path.join(stage, stub.packagePath);
|
|
const indexPath = path.join(stage, stub.indexPath);
|
|
if (!stub.generated) continue;
|
|
const packageJson = readJson(packagePath);
|
|
assertFile(indexPath, `${stub.packageName} stub entrypoint`);
|
|
if (!packageJson) continue;
|
|
if (packageJson.version !== "0.0.0-elizaos-live-stub") {
|
|
fail(
|
|
`${packagePath}: generated optional stub must use 0.0.0-elizaos-live-stub, got ${packageJson.version}`,
|
|
);
|
|
}
|
|
if (packageJson.type !== "module") {
|
|
fail(`${packagePath}: generated optional stub must be ESM`);
|
|
}
|
|
const index = readText(indexPath);
|
|
if (!/\bexport\s+default\b/.test(index)) {
|
|
fail(`${indexPath}: generated optional stub must have a default export`);
|
|
}
|
|
}
|
|
|
|
const nodeModules = path.join(stage, "Resources/app/eliza-dist/node_modules");
|
|
walkFiles(nodeModules, (filePath) => {
|
|
if (path.basename(filePath) !== "package.json") return;
|
|
const packageJson = readJson(filePath);
|
|
if (packageJson?.version !== "0.0.0-elizaos-live-stub") return;
|
|
const packageName = packageJson.name;
|
|
const manifestEntry = explicitOptionalStubs.find(
|
|
(stub) => stub.packageName === packageName,
|
|
);
|
|
const generatedEntry = (manifest.generated?.packages ?? []).find(
|
|
(stub) => stub.packageName === packageName,
|
|
);
|
|
if (!manifestEntry && !generatedEntry) {
|
|
fail(
|
|
`${filePath}: live stub package is not declared in the runtime manifest`,
|
|
);
|
|
}
|
|
});
|
|
}
|
|
|
|
function validatePackageInventory(manifest) {
|
|
const nodeModules = path.join(stage, "Resources/app/eliza-dist/node_modules");
|
|
let packageJsonCount = 0;
|
|
const inventory = [];
|
|
walkFiles(nodeModules, (filePath) => {
|
|
if (path.basename(filePath) !== "package.json") return;
|
|
packageJsonCount += 1;
|
|
const packageJson = readJson(filePath);
|
|
if (!packageJson) return;
|
|
inventory.push({
|
|
name: packageNameFromManifest(filePath, packageJson),
|
|
version: packageJson.version ?? null,
|
|
path: relativeToStage(filePath),
|
|
private: packageJson.private === true,
|
|
liveStub: packageJson.version === "0.0.0-elizaos-live-stub",
|
|
});
|
|
});
|
|
inventory.sort(
|
|
(left, right) =>
|
|
left.name.localeCompare(right.name) ||
|
|
left.path.localeCompare(right.path),
|
|
);
|
|
|
|
const manifestCount = manifest.packages?.packageJsonCount;
|
|
if (typeof manifestCount !== "number") {
|
|
fail("manifest packages.packageJsonCount is missing");
|
|
} else if (manifestCount !== packageJsonCount) {
|
|
fail(
|
|
`manifest package count mismatch: manifest=${manifestCount}, actual=${packageJsonCount}`,
|
|
);
|
|
}
|
|
|
|
const manifestInventory = manifest.packages?.inventory;
|
|
if (!Array.isArray(manifestInventory)) {
|
|
fail("manifest packages.inventory is missing");
|
|
return;
|
|
}
|
|
const normalizedManifestInventory = manifestInventory
|
|
.map((pkg) => ({
|
|
name: pkg.name,
|
|
version: pkg.version ?? null,
|
|
path: pkg.path,
|
|
private: pkg.private === true,
|
|
liveStub: pkg.liveStub === true,
|
|
}))
|
|
.sort(
|
|
(left, right) =>
|
|
String(left.name).localeCompare(String(right.name)) ||
|
|
String(left.path).localeCompare(String(right.path)),
|
|
);
|
|
if (
|
|
JSON.stringify(normalizedManifestInventory) !== JSON.stringify(inventory)
|
|
) {
|
|
fail("manifest package inventory does not match staged node_modules");
|
|
}
|
|
}
|
|
|
|
function validateRepositoryResolution(manifest) {
|
|
const forbidden = manifest.repositoryResolution
|
|
?.forbiddenHardCodedNeedles ?? [
|
|
"github.com/elizaos/elizaos",
|
|
'orgName:"elizaos"',
|
|
'repoName:"eliza"',
|
|
'docsUrl:"https://docs.elizaos.ai"',
|
|
'appUrl:"https://app.elizaos.ai"',
|
|
];
|
|
const scanRoots = [
|
|
path.join(stage, "Resources/app/brand-config.json"),
|
|
path.join(stage, "Resources/app/renderer/index.html"),
|
|
path.join(stage, "Resources/app/renderer/site.webmanifest"),
|
|
path.join(stage, "Resources/app/renderer/assets"),
|
|
];
|
|
|
|
for (const scanRoot of scanRoots) {
|
|
const scan = (filePath) => {
|
|
const ext = path.extname(filePath);
|
|
if (![".html", ".js", ".json", ".webmanifest"].includes(ext)) return;
|
|
const text = readText(filePath);
|
|
for (const needle of forbidden) {
|
|
if (text.includes(needle)) {
|
|
fail(
|
|
`${filePath}: hard-coded elizaOS repo/app resolution remains: ${needle}`,
|
|
);
|
|
}
|
|
}
|
|
};
|
|
|
|
if (!fs.existsSync(scanRoot)) continue;
|
|
if (fs.statSync(scanRoot).isDirectory()) {
|
|
walkFiles(scanRoot, scan);
|
|
} else {
|
|
scan(scanRoot);
|
|
}
|
|
}
|
|
}
|
|
|
|
function validatePorts(manifest) {
|
|
const apiPort = manifest.expectedPorts?.api?.defaultPort;
|
|
const rendererPort = manifest.expectedPorts?.renderer?.defaultPort;
|
|
if (apiPort !== 31337) {
|
|
fail(`manifest expected API port must be 31337, got ${apiPort}`);
|
|
}
|
|
if (rendererPort !== 5174) {
|
|
fail(`manifest expected renderer port must be 5174, got ${rendererPort}`);
|
|
}
|
|
|
|
const liveLauncher = path.join(osOverlayRoot, "usr/local/bin/elizaos");
|
|
const agentLauncher = path.join(
|
|
osOverlayRoot,
|
|
"usr/local/lib/elizaos/start-elizaos-agent-user",
|
|
);
|
|
const rendererLauncher = path.join(
|
|
osOverlayRoot,
|
|
"usr/local/lib/elizaos/start-elizaos-renderer-user",
|
|
);
|
|
const browserLauncher = path.join(
|
|
osOverlayRoot,
|
|
"usr/local/lib/elizaos/start-elizaos-browser-user",
|
|
);
|
|
const rendererServer = path.join(
|
|
osOverlayRoot,
|
|
"usr/local/lib/elizaos/renderer-server.mjs",
|
|
);
|
|
const webkitShell = path.join(
|
|
osOverlayRoot,
|
|
"usr/local/lib/elizaos/elizaos-webkit-shell",
|
|
);
|
|
|
|
for (const filePath of [
|
|
liveLauncher,
|
|
agentLauncher,
|
|
rendererLauncher,
|
|
browserLauncher,
|
|
]) {
|
|
assertContains(filePath, `ELIZA_API_PORT:-${apiPort}`, "API port default");
|
|
}
|
|
for (const filePath of [rendererLauncher, browserLauncher]) {
|
|
assertContains(
|
|
filePath,
|
|
`ELIZAOS_RENDERER_PORT:-${rendererPort}`,
|
|
"renderer port default",
|
|
);
|
|
}
|
|
assertContains(
|
|
rendererServer,
|
|
`|| "${rendererPort}"`,
|
|
"renderer server port default",
|
|
);
|
|
assertContains(
|
|
rendererServer,
|
|
`|| "${apiPort}"`,
|
|
"renderer server API default",
|
|
);
|
|
assertContains(
|
|
webkitShell,
|
|
`127.0.0.1:${rendererPort}`,
|
|
"WebKit renderer URL",
|
|
);
|
|
assertContains(webkitShell, `127.0.0.1%3A${apiPort}`, "WebKit API URL");
|
|
}
|
|
|
|
function validateBranding() {
|
|
const versionPath = path.join(stage, "Resources/version.json");
|
|
const brandPath = path.join(stage, "Resources/app/brand-config.json");
|
|
const version = readJson(versionPath);
|
|
const brand = readJson(brandPath);
|
|
|
|
if (version?.name !== "elizaOS") {
|
|
fail(`${versionPath}: name must be elizaOS`);
|
|
}
|
|
if (version?.identifier !== "org.elizaos.app") {
|
|
fail(`${versionPath}: identifier must be org.elizaos.app`);
|
|
}
|
|
for (const [key, expected] of Object.entries({
|
|
appName: "elizaOS",
|
|
appId: "org.elizaos.app",
|
|
namespace: "eliza",
|
|
urlScheme: "elizaos",
|
|
configDirName: "elizaOS",
|
|
})) {
|
|
if (brand?.[key] !== expected) {
|
|
fail(`${brandPath}: ${key} must be ${expected}`);
|
|
}
|
|
}
|
|
}
|
|
|
|
function validateRuntimeEntry() {
|
|
const entryPath = path.join(stage, "Resources/app/eliza-dist/entry.js");
|
|
const appCoreEntryPath = path.join(
|
|
stage,
|
|
"Resources/app/eliza-dist/node_modules/@elizaos/app-core/dist/entry.js",
|
|
);
|
|
assertFile(entryPath, "agent runtime entry");
|
|
assertFile(appCoreEntryPath, "bundled app-core runtime entry");
|
|
const entry = readText(entryPath);
|
|
if (entry.includes("../packages/") || entry.includes("src/entry.ts")) {
|
|
fail(
|
|
`${entryPath}: live runtime entry must not point back to source checkout paths`,
|
|
);
|
|
}
|
|
if (!entry.includes("./node_modules/@elizaos/app-core/dist/entry.js")) {
|
|
fail(`${entryPath}: live runtime entry must import bundled app-core dist`);
|
|
}
|
|
}
|
|
|
|
function validateAgentApiLazyWalletImport() {
|
|
const filePath = path.join(
|
|
stage,
|
|
"Resources/app/eliza-dist/node_modules/@elizaos/agent/src/api/index.ts",
|
|
);
|
|
assertFile(filePath, "agent API barrel");
|
|
const text = readText(filePath);
|
|
if (!text.includes("export const handleWalletRoutes")) {
|
|
fail(`${filePath}: agent API barrel must expose lazy handleWalletRoutes`);
|
|
}
|
|
if (!text.includes('await import("@elizaos/plugin-wallet")')) {
|
|
fail(`${filePath}: wallet routes must be loaded lazily`);
|
|
}
|
|
if (text.includes(" handleWalletRoutes,\n type WalletAddressesSnapshot")) {
|
|
fail(`${filePath}: static plugin-wallet re-export must not return`);
|
|
}
|
|
}
|
|
|
|
function validateSymlinks() {
|
|
for (const [relativePath, target] of [
|
|
["node_modules", "Resources/app/eliza-dist/node_modules"],
|
|
["bin/node_modules", "../Resources/app/eliza-dist/node_modules"],
|
|
]) {
|
|
const linkPath = path.join(stage, relativePath);
|
|
if (!assertFile(linkPath, `${relativePath} dependency symlink`)) continue;
|
|
let actual;
|
|
try {
|
|
actual = fs.readlinkSync(linkPath);
|
|
} catch {
|
|
fail(`${linkPath}: expected symlink to ${target}`);
|
|
continue;
|
|
}
|
|
if (actual !== target) {
|
|
fail(`${linkPath}: expected symlink to ${target}, got ${actual}`);
|
|
}
|
|
}
|
|
}
|
|
|
|
function validateRequiredRuntimePackages() {
|
|
for (const packageName of [
|
|
"agent-orchestrator",
|
|
"@elizaos/plugin-agent-orchestrator",
|
|
"@elizaos/plugin-app-control",
|
|
"@elizaos/plugin-calendly",
|
|
"@elizaos/plugin-health",
|
|
]) {
|
|
assertFile(
|
|
packageManifestPath(packageName),
|
|
`${packageName} package manifest`,
|
|
);
|
|
}
|
|
|
|
for (const [packageName, relativeFile] of [
|
|
["agent-orchestrator", "index.js"],
|
|
["@elizaos/plugin-agent-orchestrator", "index.js"],
|
|
["@elizaos/plugin-calendly", "dist/index.js"],
|
|
["@elizaos/plugin-health", "dist/index.js"],
|
|
]) {
|
|
assertFile(
|
|
path.join(packageDirectory(packageName), relativeFile),
|
|
`${packageName} runtime file`,
|
|
);
|
|
}
|
|
}
|
|
|
|
if (!fs.existsSync(stage)) {
|
|
fail(`runtime overlay stage does not exist: ${stage}`);
|
|
}
|
|
if (!fs.existsSync(manifestPath)) {
|
|
fail(`runtime overlay manifest missing: ${manifestPath}`);
|
|
}
|
|
|
|
const manifest = fs.existsSync(manifestPath) ? readJson(manifestPath) : null;
|
|
if (manifest) {
|
|
if (manifest.schemaVersion !== 1) {
|
|
fail(`${manifestPath}: schemaVersion must be 1`);
|
|
}
|
|
if (!manifest.source?.gitCommit) {
|
|
warn(`${manifestPath}: source git commit is not recorded`);
|
|
}
|
|
validateEntrypoints(manifest);
|
|
validateGeneratedStubs(manifest);
|
|
validatePackageInventory(manifest);
|
|
validateRepositoryResolution(manifest);
|
|
validatePorts(manifest);
|
|
validateBranding();
|
|
validateRuntimeEntry();
|
|
validateAgentApiLazyWalletImport();
|
|
validateSymlinks();
|
|
validateRequiredRuntimePackages();
|
|
}
|
|
|
|
for (const message of warnings) {
|
|
console.warn(`warning: ${message}`);
|
|
}
|
|
|
|
if (errors.length > 0) {
|
|
for (const message of errors) {
|
|
console.error(`error: ${message}`);
|
|
}
|
|
process.exit(1);
|
|
}
|
|
|
|
console.log(`Runtime overlay validated: ${stage}`);
|