* refactor: move Electron app to main directory and enforce ts strict mode * chore: add pre-install plugins * remove duplicated initModel function Signed-off-by: James <james@jan.ai> * chore: correct module path * fix: dynamic import does not work with ts * chore: web should be able to run on target host browser * fix: history panel, should display conversations rather just blank state * chore: init default model * chore: pluggin in ts * fix: pre-pack model management * fix: compiled core should not include plugins * chore: refactor - invoke plugin function * refactor download/delete file Signed-off-by: James <james@jan.ai> * update prebuild lib Signed-off-by: James <james@jan.ai> * chore: yarn workspace * chore: update yarn workspace * chore: yarn workspace with nohoist * fix: llama-cpp-import * chore: fix data-plugin wrong module path * chore: correct build step * chore: - separate inference service (#212) - remove base-plugin Signed-off-by: James <james@jan.ai> Co-authored-by: James <james@jan.ai> * chore: update core plugins * chore: hide installation prompt and fix model load - management plugin * chore: remove legacy files; update readme * fix: refresh page lost the download state Signed-off-by: James <james@jan.ai> * fix: ai prompt not passed to plugin Signed-off-by: James <james@jan.ai> * chore: module import fix for production * chore: auto updater * chore: package is public * chore: fix yarn workspace config * update: model management uses Q4_K_M * chore: fix yarn scripts for publishing * chore: app updater - progress update message * chore: user confirms update action * adding some state for changing page store downloaded model to database Signed-off-by: James <james@jan.ai> * chore: refactor plugins into yarn workspace - a single command to publish all base plugins * chore update readme (#218) Co-authored-by: Hien To <tominhhien97@gmail.com> * change app name and app icon Signed-off-by: James <james@jan.ai> * remove: go-to-nowhere actions * chore: bundle core plugins from root and scan default plugins * fix: app crashes on different field name lookup * chore: css fix * chore: bind download progress to app ui * chore: bind active model * chore: simplify app splash-screen only centered jan icon * feature: system monitoring plugin (#196) * feat: Add function for system monitoring * chore: register plugin functions * chore: move to corresponding directory * chore: bind system monitoring data to UI --------- Co-authored-by: Louis <louis@jan.ai> * chore: add build:plugins step to README * chore: model searching and fix model name * fix: plugin file selected appearance * fix: create new conversation does not work * fix: delete conversation not update state - messages still exist * chore: fix asset path prefix * Add CICD for macos (#221) Co-authored-by: Hien To <tominhhien97@gmail.com> * chore: fix production plugin path * chore: add shell open url in external browser --------- Signed-off-by: James <james@jan.ai> Co-authored-by: James <james@jan.ai> Co-authored-by: NamH <NamNh0122@gmail.com> Co-authored-by: 0xSage <n@pragmatic.vc> Co-authored-by: hiento09 <136591877+hiento09@users.noreply.github.com> Co-authored-by: Hien To <tominhhien97@gmail.com> Co-authored-by: namvuong <22463238+vuonghoainam@users.noreply.github.com>
308 lines
6.9 KiB
JavaScript
308 lines
6.9 KiB
JavaScript
import { setup } from './index'
|
|
import { register, trigger, remove, clear, get } from "./activation-manager";
|
|
import { add } from './extension-manager'
|
|
|
|
let mockPlugins = {}
|
|
setup({
|
|
importer(plugin) { return mockPlugins[plugin] }
|
|
})
|
|
|
|
afterEach(() => {
|
|
clear()
|
|
mockPlugins = {}
|
|
})
|
|
|
|
describe('register', () => {
|
|
it('should add a new activation point to the register when a new, valid plugin is registered',
|
|
() => {
|
|
register({
|
|
name: 'test',
|
|
url: 'testPkg',
|
|
activationPoints: ['ap1', 'ap2'],
|
|
active: true
|
|
})
|
|
|
|
expect(get()).toEqual([
|
|
{
|
|
plugin: 'test',
|
|
url: 'testPkg',
|
|
activationPoint: 'ap1',
|
|
activated: false
|
|
},
|
|
{
|
|
plugin: 'test',
|
|
url: 'testPkg',
|
|
activationPoint: 'ap2',
|
|
activated: false
|
|
}
|
|
])
|
|
}
|
|
)
|
|
|
|
it('should not add an activation point to the register when an existing, valid plugin is registered',
|
|
() => {
|
|
register({
|
|
name: 'test',
|
|
url: 'testPkg',
|
|
activationPoints: ['ap1', 'ap2'],
|
|
active: true
|
|
})
|
|
|
|
register({
|
|
name: 'test',
|
|
url: 'testPkg',
|
|
activationPoints: ['ap2', 'ap3'],
|
|
active: true
|
|
})
|
|
|
|
expect(get()).toEqual([
|
|
{
|
|
plugin: 'test',
|
|
url: 'testPkg',
|
|
activationPoint: 'ap1',
|
|
activated: false
|
|
},
|
|
{
|
|
plugin: 'test',
|
|
url: 'testPkg',
|
|
activationPoint: 'ap2',
|
|
activated: false
|
|
},
|
|
{
|
|
plugin: 'test',
|
|
url: 'testPkg',
|
|
activationPoint: 'ap3',
|
|
activated: false
|
|
},
|
|
])
|
|
}
|
|
)
|
|
|
|
it('should throw an error when an invalid plugin is registered',
|
|
() => {
|
|
const noActivationPoints = () => register({
|
|
name: 'test',
|
|
url: 'testPkg',
|
|
active: true
|
|
})
|
|
|
|
expect(noActivationPoints).toThrow(/does not have any activation points set up in its manifest/)
|
|
}
|
|
)
|
|
})
|
|
|
|
describe('trigger', () => {
|
|
it('should trigger all and only the activations with for the given execution point on triggering an execution, using the defined importer',
|
|
async () => {
|
|
const triggered = []
|
|
|
|
mockPlugins.plugin1 = {
|
|
ap1() { triggered.push('plugin1-ap1') }
|
|
}
|
|
mockPlugins.plugin2 = {
|
|
ap2() { triggered.push('plugin2-ap2') }
|
|
}
|
|
mockPlugins.plugin3 = {
|
|
ap1() { triggered.push('plugin3-ap1') },
|
|
ap2() { triggered.push('plugin3-ap2') }
|
|
}
|
|
|
|
register({
|
|
name: 'plugin1',
|
|
url: 'plugin1',
|
|
activationPoints: ['ap1'],
|
|
active: true
|
|
})
|
|
register({
|
|
name: 'plugin2',
|
|
url: 'plugin2',
|
|
activationPoints: ['ap2'],
|
|
active: true
|
|
})
|
|
register({
|
|
name: 'plugin3',
|
|
url: 'plugin3',
|
|
activationPoints: ['ap1', 'ap2'],
|
|
active: true
|
|
})
|
|
|
|
await trigger('ap1')
|
|
|
|
expect(triggered).toEqual(['plugin1-ap1', 'plugin3-ap1'])
|
|
}
|
|
)
|
|
|
|
it('should return an error if an activation point is triggered on a plugin that does not include it',
|
|
async () => {
|
|
mockPlugins.plugin1 = {
|
|
wrongAp() { }
|
|
}
|
|
|
|
register({
|
|
name: 'plugin1',
|
|
url: 'plugin1',
|
|
activationPoints: ['ap1']
|
|
})
|
|
|
|
await expect(() => trigger('ap1')).rejects.toThrow(/was triggered but does not exist on plugin/)
|
|
}
|
|
)
|
|
|
|
it('should provide the registered extension points to the triggered activation point if presetEPs is set to true in the setup',
|
|
async () => {
|
|
setup({
|
|
importer(plugin) { return mockPlugins[plugin] },
|
|
presetEPs: true,
|
|
})
|
|
|
|
let ap1Res
|
|
|
|
mockPlugins.plugin1 = {
|
|
ap1: eps => ap1Res = eps
|
|
}
|
|
register({
|
|
name: 'plugin1',
|
|
url: 'plugin1',
|
|
activationPoints: ['ap1']
|
|
})
|
|
|
|
add('ep1')
|
|
add('ep2')
|
|
|
|
await trigger('ap1')
|
|
|
|
expect(ap1Res.ep1.constructor.name).toEqual('ExtensionPoint')
|
|
expect(ap1Res.ep2.constructor.name).toEqual('ExtensionPoint')
|
|
}
|
|
)
|
|
|
|
it('should allow registration, execution and serial execution of execution points when an activation point is triggered if presetEPs is set to false in the setup',
|
|
async () => {
|
|
setup({
|
|
importer(plugin) { return mockPlugins[plugin] },
|
|
})
|
|
|
|
let ap1Res
|
|
|
|
mockPlugins.plugin1 = {
|
|
ap1: eps => ap1Res = eps
|
|
}
|
|
register({
|
|
name: 'plugin1',
|
|
url: 'plugin1',
|
|
activationPoints: ['ap1']
|
|
})
|
|
|
|
await trigger('ap1')
|
|
|
|
expect(typeof ap1Res.register).toBe('function')
|
|
expect(typeof ap1Res.execute).toBe('function')
|
|
expect(typeof ap1Res.executeSerial).toBe('function')
|
|
}
|
|
)
|
|
|
|
it('should not provide any reference to extension points during activation point triggering if presetEPs is set to null in the setup',
|
|
async () => {
|
|
setup({
|
|
importer(plugin) { return mockPlugins[plugin] },
|
|
presetEPs: null,
|
|
})
|
|
|
|
let ap1Res = true
|
|
|
|
mockPlugins.plugin1 = {
|
|
ap1: eps => ap1Res = eps
|
|
}
|
|
register({
|
|
name: 'plugin1',
|
|
url: 'plugin1',
|
|
activationPoints: ['ap1']
|
|
})
|
|
|
|
await trigger('ap1')
|
|
|
|
expect(ap1Res).not.toBeDefined()
|
|
}
|
|
)
|
|
})
|
|
|
|
describe('remove and clear', () => {
|
|
|
|
beforeEach(() => {
|
|
register({
|
|
name: 'plugin1',
|
|
url: 'plugin1',
|
|
activationPoints: ['ap1', 'ap2'],
|
|
active: true
|
|
})
|
|
|
|
register({
|
|
name: 'plugin2',
|
|
url: 'plugin2',
|
|
activationPoints: ['ap2', 'ap3'],
|
|
active: true
|
|
})
|
|
})
|
|
it('should remove all and only the activations for the given plugin from the register when removing activations',
|
|
() => {
|
|
remove('plugin1')
|
|
|
|
expect(get()).toEqual([
|
|
{
|
|
plugin: 'plugin2',
|
|
url: 'plugin2',
|
|
activationPoint: 'ap2',
|
|
activated: false
|
|
},
|
|
{
|
|
plugin: 'plugin2',
|
|
url: 'plugin2',
|
|
activationPoint: 'ap3',
|
|
activated: false
|
|
},
|
|
])
|
|
}
|
|
)
|
|
|
|
it('should not remove any activations from the register if no plugin name is provided',
|
|
() => {
|
|
remove()
|
|
|
|
expect(get()).toEqual([
|
|
{
|
|
plugin: 'plugin1',
|
|
url: 'plugin1',
|
|
activationPoint: 'ap1',
|
|
activated: false
|
|
},
|
|
{
|
|
plugin: 'plugin1',
|
|
url: 'plugin1',
|
|
activationPoint: 'ap2',
|
|
activated: false
|
|
},
|
|
{
|
|
plugin: 'plugin2',
|
|
url: 'plugin2',
|
|
activationPoint: 'ap2',
|
|
activated: false
|
|
},
|
|
{
|
|
plugin: 'plugin2',
|
|
url: 'plugin2',
|
|
activationPoint: 'ap3',
|
|
activated: false
|
|
},
|
|
])
|
|
}
|
|
)
|
|
|
|
it('should remove all activations from the register when clearing the register',
|
|
() => {
|
|
clear()
|
|
|
|
expect(get()).toEqual([])
|
|
}
|
|
)
|
|
})
|