8000 feat: Prepare 0.x for sharing plugins with 1.x by odilitime · Pull Request #4384 · elizaOS/eliza · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

feat: Prepare 0.x for sharing plugins with 1.x #4384

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 20 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 70 additions & 9 deletions packages/cli/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
const { Command } = require('commander')
const program = new Command()
const { version } = require('./package.json')

const JSON5 = require('json5')

const pluginPkgPath = (pluginRepo) => {
const parts = pluginRepo.split('/')
Expand All @@ -30,12 +30,39 @@
.name('plugins')
.description('manage elizaOS plugins')

let metadata = {}

async function getPlugins() {
const resp = await fetch('https://raw.githubusercontent.com/elizaos-plugins/registry/refs/heads/main/index.json')
return await resp.json();
const mostlyJson = await resp.text();
const jsonLike = []
for(const l of mostlyJson.split('\n')) {
if (l.match(/""/)) {
const parts = l.split(/:/, 2)
const noLQte = parts[1].substr(2)
const parts2 = noLQte.substr(0, noLQte.length -2).split('/', 2)
metadata[parts2[0]] = parts2[1].split(/,\W*/)
} else {
jsonLike.push(l)
}
}
const json = jsonLike.join("\n")
const plugins = JSON5.parse(json)
return plugins
}


function remoteBranchExists(repoDir, branchName) {
try {
const output = execSync(`git ls-remote --heads origin`, {
cwd: repoDir,
encoding: 'utf-8',
});
return output.includes(`refs/heads/${branchName}`);
} catch (err) {
console.error('Failed to check remote branches:', err);
return false;
}
}

pluginsCmd
.command('list')
Expand All @@ -46,6 +73,7 @@
.action(async (opts) => {
try {
const plugins = await getPlugins()
//console.log('metadata', metadata)
const pluginNames = Object.keys(plugins)
.filter(name => !opts.type || name.includes(opts.type))
.sort()
Expand All @@ -65,7 +93,7 @@
.alias('install')
.description('add a plugin')
.argument('<plugin>', 'plugin name')
.action(async (plugin, opts) => {

Check notice on line 96 in packages/cli/index.js

View check run for this annotation

codefactor.io / CodeFactor

packages/cli/index.js#L96

'opts' is defined but never used. (no-unused-vars)
// ensure git is installed
try {
const gitVersion = execSync('git --version', { stdio: 'pipe' }).toString().trim();
Expand Down Expand Up @@ -108,6 +136,36 @@
// submodule init & update?
}

// branch detection
const x1Compat = remoteBranchExists(pkgPath, '0.x')
if (x1Compat) {
// switch branches
console.log('Checking out 0.x branch') // log for education
const gitOutput = execSync('git checkout 0.x', { stdio: 'pipe', cwd: pkgPath }).toString().trim();
} else {
// sniff main
const packageJsonPath = pkgPath + '/package.json'
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'))

let isV2 = false
for(const d in packageJson.dependencies) {
if (d.match(/core-plugin-v2/)) {
isV2 = true
}
}

if (isV2) {
console.error('Plugin', plugin, 'not compatible with 0.x, deleting', pkgPath)
//const gitOutput = execSync('git clone https://github.com/' + repoData[1] + ' ' + pkgPath, { stdio: 'pipe' }).toString().trim();
try {
fs.rmSync(pkgPath, { recursive: true, force: true });
} catch (err) {
console.error('Error removing package plugin directory:', err);
}
return
}
}

// we need to check for dependencies

// Read the current package.json
Expand All @@ -117,7 +175,7 @@
const updateDependencies = (deps) => {
if (!deps) return false
let changed = false
const okPackages = ['@elizaos/client-direct', '@elizaos/core', '@elizaos/plugin-bootstrap']
const okPackages = ['@elizaos/client-direct', '@elizaos/core', '@elizaos/core-plugin-v1', '@elizaos/plugin-bootstrap']
for (const dep in deps) {
if (okPackages.indexOf(dep) !== -1) continue // skip these, they're fine
// do we want/need to perserve local packages like core?
Expand Down Expand Up @@ -155,15 +213,17 @@
// # pnpm add @elizaos/core@workspace:* --filter ./packages/client-twitter

// ok this can be an issue if it's referencing a plugin it couldn't be
console.log('Making sure plugin has access to @elizaos/core')
const pluginAddCoreOutput = execSync('pnpm add @elizaos/core@workspace:* --filter ./packages/' + namePart, { cwd: elizaOSroot, stdio: 'pipe' }).toString().trim();
console.log('Making sure plugin has access to @elizaos/core-plugin-v1')
try {
const pluginAddCoreOutput = execSync('pnpm add @elizaos/core-plugin-v1@workspace:* --filter ./packages/' + namePart, { cwd: elizaOSroot, stdio: 'pipe' }).toString().trim();
} catch(e) {
console.error('pluginAddCoreOutput error', e)
}

// is this needed? if we want it to be assumed and hard coded but might not work with npm
if (packageJson.name !== '@elizaos-plugins/' + namePart) {
// Update the name field
packageJson.name = '@elizaos-plugins/' + namePart
console.log('Updating plugins package.json name to', packageJson.name)

// Write the updated package.json back to disk
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2))
}

Expand All @@ -186,6 +246,7 @@
console.log('Remember to add it to your character file\'s plugin field: ["' + pluginName + '"]')
})

// doesn't remove dependencies because can't tell if they're in use
pluginsCmd
.command('remove')
.alias('delete')
Expand All @@ -193,7 +254,7 @@
.alias('rm')
.description('remove a plugin')
.argument("<plugin>", "plugin name")
.action(async (plugin, opts) => {

Check notice on line 257 in packages/cli/index.js

View check run for this annotation

codefactor.io / CodeFactor

packages/cli/index.js#L257

'opts' is defi F438 ned but never used. (no-unused-vars)
// ensure prefix
const pluginName = '@elizaos-plugins/' + plugin.replace(/^@elizaos-plugins\//, '')
const namePart = pluginName.replace(/^@elizaos-plugins\//, '')
Expand Down
173 changes: 173 additions & 0 deletions packages/cli/lib.migrate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
const fs = require('fs');
const path = require('path');

// Configuration
const OLD_IMPORT = '@elizaos/core';
const NEW_IMPORT = '@elizaos/core-plugin-v1';

function buildPluginFromDir(pluginDir) {
const corePath = path.join(pluginDir, 'node_modules', '@elizaos', 'core');

let references
try {
const result = execSync(
`grep -r "${OLD_IMPORT}" "${pluginDir}"`,
{ encoding: 'utf-8', stdio: ['pipe', 'pipe', 'ignore'] }
).trim();
references = result ? result.split('\n') : [];
} catch (error) {
// grep returns non-zero if no matches, which is not an error for us
references = [];
}

// Check for specific reference locations
const hasSrcRefs = references.some(ref => ref.includes('/src/'));
const hasDistRefs = references.some(ref => ref.includes('/dist/'));
const hasPackageJsonRefs = references.some(ref => ref.endsWith('package.json:'));

return {
name: path.basename(pluginDir),
path: pluginDir,
references,
hasNodeModulesCore: fs.existsSync(corePath),
hasSrcRefs,
hasDistRefs,
hasPackageJsonRefs
}
}

// Migrate all references in a single plugin
function migratePlugin(plugin) {
console.log(`\nMigrating ${plugin.name}...`);
const results = {
files: 0,
packageJson: false,
tsupConfig: false,
nodeModules: false
};

// 1. Replace all text references in files
if (plugin.references.length > 0) {
const filesToUpdate = new Set();

for (const ref of plugin.references) {
const parts = ref.split(':');
if (parts.length >= 1) {
filesToUpdate.add(parts[0]);
}
}

for (const file of filesToUpdate) {
try {
const content = fs.readFileSync(file, 'utf-8');

// Use a regex that will only match the exact string @elizaos/core
// This prevents double replacements (@elizaos/core-plugin-v1-plugin-v1)
// Using word boundary \b to ensure we don't replace partial matches
const regex = new RegExp(`\\b${OLD_IMPORT}\\b`, 'g');
const newContent = content.replace(regex, NEW_IMPORT);

if (content !== newContent) {
fs.writeFileSync(file, newContent);
results.files++;
console.log(` Updated file: ${file}`);
}
} catch (error) {
console.error(` Error updating ${file}: ${error.message}`);
}
}
}

// 2. Update package.json
const packageJsonPath = path.join(plugin.path, 'package.json');
if (fs.existsSync(packageJsonPath)) {
try {
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
let updated = false;

if (packageJson.dependencies && packageJson.dependencies[OLD_IMPORT]) {
const version = packageJson.dependencies[OLD_IMPORT];
packageJson.dependencies[NEW_IMPORT] = version;
delete packageJson.dependencies[OLD_IMPORT];
updated = true;
}

if (packageJson.devDependencies && packageJson.devDependencies[OLD_IMPORT]) {
const version = packageJson.devDependencies[OLD_IMPORT];
packageJson.devDependencies[NEW_IMPORT] = version;
delete packageJson.devDependencies[OLD_IMPORT];
updated = true;
}

if (updated) {
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2) + '\n');
results.packageJson = true;
console.log(` Updated package.json`);
}
} catch (error) {
console.error(` Error updating package.json: ${error.message}`);
}
}

// 3. Update tsup.config.ts if it exists
const tsupConfigPath = path.join(plugin.path, 'tsup.config.ts');
if (fs.existsSync(tsupConfigPath)) {
try {
const content = fs.readFileSync(tsupConfigPath, 'utf-8');

// Use the same word boundary approach for tsup.config.ts
const regex = new RegExp(`external\\s*:\\s*\\[[^\\]]*\\b${OLD_IMPORT}\\b[^\\]]*\\]`, 'g');

Check notice on line 119 in packages/cli/lib.migrate.js

View check run for this annotation

codefactor.io / CodeFactor

packages/cli/lib.migrate.js#L40-L119

Complex Method
const newContent = content.replace(regex, match => match.replace(OLD_IMPORT, NEW_IMPORT));

if (content !== newContent) {
fs.writeFileSync(tsupConfigPath, newContent);
results.tsupConfig = true;
console.log(` Updated tsup.config.ts`);
}
} catch (error) {
console.error(` Error updating tsup.config.ts: ${error.message}`);
}
}

// 4. Print a message about node_modules if needed
if (plugin.hasNodeModulesCore) {
results.nodeModules = true;
console.log(` Found @elizaos/core in node_modules - will need to reinstall dependencies`);
}

// Summary for this plugin
let actionItems = [];
if (results.files > 0) {
actionItems.push(`replaced references in ${results.files} files`);
}
if (results.packageJson) {
actionItems.push('updated package.json');
}
if (results.tsupConfig) {
actionItems.push('updated tsup.config.ts');
}
if (results.nodeModules) {
actionItems.push('found node_modules that need reinstallation');
}

if (actionItems.length > 0) {
console.log(` ✅ Migration actions: ${actionItems.join(', ')}`);

// Additional instructions based on plugin type
if (plugin.hasSrcRefs) {
console.log(` ⚠️ This plugin has source code references - rebuild it after migration with 'npm run build'`);
}
if (plugin.hasNodeModulesCore) {
console.log(` ⚠️ Remove node_modules and reinstall dependencies to complete migration`);
}
} else {
console.log(` ⚠️ No changes made to this plugin - manual inspection recommended`);
}

return results;
}

module.exports = {
buildPluginFromDir,
migratePlugin,
}
3 changes: 2 additions & 1 deletion packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"license": "ISC",
"description": "",
"dependencies": {
"commander": "^13.1.0"
"commander": "^13.1.0",
"json5": "2.2.3"
}
}
5 changes: 5 additions & 0 deletions packages/core-plugin-v1/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
node_modules
dist
elizaConfig.yaml
custom_actions/
cache/
6 changes: 6 additions & 0 deletions packages/core-plugin-v1/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
*

!dist/**
!package.json
!readme.md
!tsup.config.ts
46 changes: 46 additions & 0 deletions packages/core-plugin-v1/package.json
3D11
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{
"name": "@elizaos/core-plugin-v1",
"version": "0.25.9",
"description": "",
"type": "module",
"main": "dist/index.js",
"module": "dist/index.js",
"types": "dist/index.d.ts",
"exports": {
"./package.json": "./package.json",
".": {
"import": {
"@elizaos/source": "./src/index.ts",
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
}
}
},
"files": [
"dist"
],
"scripts": {
"build": "tsup --format esm --dts",
"watch": "tsc --watch",
"dev": "tsup --format esm --dts --watch",
"build:docs": "cd docs && pnpm run build",
"test": "vitest run",
"test:coverage": "vitest run --coverage",
"test:watch": "vitest"
},
"author": "",
"license": "MIT",
"devDependencies": {
"@types/node": "22.8.4",
"tsup": "8.3.5",
"typescript": "5.6.3"
},
"dependencies": {
"@elizaos/core": "workspace:*",
"ai": "4.1.54",
"pino": "^9.6.0"
},
"publishConfig": {
"access": "public"
}
}
Loading
Loading
0