Files
nexu-io__open-design/packages/plugin-runtime/tests/merge.test.ts
pftom 4c7cd5d9f2 feat(plugins): introduce plugin system with installation and management capabilities
- Added support for a new plugin system, allowing users to install, uninstall, and manage plugins through the daemon.
- Implemented API endpoints for listing installed plugins, retrieving plugin details, and applying plugins with input validation.
- Introduced a plugin doctor feature to validate plugin manifests and check for issues before application.
- Established a plugin persistence layer with SQLite migrations for managing installed plugins and their metadata.
- Enhanced the CLI with commands for plugin operations, improving user interaction with the plugin ecosystem.
2026-05-09 18:24:44 +08:00

60 lines
1.9 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import { mergeManifests } from '../src/merge';
import type { PluginManifest } from '@open-design/contracts';
const adapter: PluginManifest = {
name: 'plugin',
title: 'From Adapter',
version: '0.0.0',
description: 'adapter desc',
compat: { agentSkills: [{ path: './SKILL.md' }] },
od: {
kind: 'skill',
taskKind: 'new-generation',
mode: 'prototype',
inputs: [{ name: 'tone', type: 'string' }],
},
};
const sidecar: PluginManifest = {
name: 'plugin',
title: 'From Sidecar',
version: '1.0.0',
description: 'sidecar desc',
od: {
taskKind: 'tune-collab',
inputs: [{ name: 'audience', type: 'select', options: ['VC'] }],
},
};
describe('mergeManifests', () => {
it('lets the sidecar win for scalar fields', () => {
const merged = mergeManifests({ sidecar, adapters: [adapter] });
expect(merged.title).toBe('From Sidecar');
expect(merged.version).toBe('1.0.0');
expect(merged.description).toBe('sidecar desc');
expect(merged.od?.taskKind).toBe('tune-collab');
});
it('falls back to adapter values when sidecar omits them', () => {
const merged = mergeManifests({ sidecar, adapters: [adapter] });
expect(merged.od?.mode).toBe('prototype');
expect(merged.od?.kind).toBe('skill');
});
it('keeps the sidecar inputs array intact, not deep-merged', () => {
const merged = mergeManifests({ sidecar, adapters: [adapter] });
expect(merged.od?.inputs?.length).toBe(1);
expect(merged.od?.inputs?.[0]?.name).toBe('audience');
});
it('unions compat lists across layers', () => {
const merged = mergeManifests({
sidecar: { ...sidecar, compat: { claudePlugins: [{ path: './.claude-plugin/plugin.json' }] } },
adapters: [adapter],
});
expect(merged.compat?.agentSkills?.length).toBe(1);
expect(merged.compat?.claudePlugins?.length).toBe(1);
});
});