diff --git a/packages/frontend/src/scripts/install-plugin.ts b/packages/frontend/src/scripts/install-plugin.ts index e6576b8bb9..625fab4cb8 100644 --- a/packages/frontend/src/scripts/install-plugin.ts +++ b/packages/frontend/src/scripts/install-plugin.ts @@ -21,6 +21,7 @@ export type AiScriptPluginMeta = { description?: string; permissions?: string[]; config?: Record; + id?: string; }; const parser = new Parser(); @@ -42,19 +43,19 @@ export function savePlugin({ id, meta, src, token }: { } as Plugin)); } -async function savePluginToAccount(pluginOnlyOverride: boolean, { hash, meta, src, token }: { - hash: string; +async function savePluginToAccount(pluginOnlyOverride: boolean, { id, meta, src, token }: { + id: string; meta: AiScriptPluginMeta; src: string; token: string; }) { const plugins = await getPluginList(); // pluginOnlyOverrideがtrueになっているということはすでに重複していることが確定している - const configData = pluginOnlyOverride ? plugins[hash].configData : {}; - const pluginToken = pluginOnlyOverride ? plugins[hash].token : token; - plugins[hash] = { + const configData = pluginOnlyOverride ? plugins[id].configData : {}; + const pluginToken = pluginOnlyOverride ? plugins[id].token : token; + plugins[id] = { ...meta, - id: hash, + id, active: true, configData, token: pluginToken, @@ -63,7 +64,7 @@ async function savePluginToAccount(pluginOnlyOverride: boolean, { hash, meta, sr } as Plugin; if (!pluginOnlyOverride) { - await os.api('i/registry/remove-all-keys-in-scope', { scope: ['client', 'aiscript', 'plugins', hash] }); + await os.api('i/registry/remove-all-keys-in-scope', { scope: ['client', 'aiscript', 'plugins', id] }); } await os.api('i/registry/set', { scope: ['client'], key: 'plugins', value: plugins }); @@ -106,11 +107,15 @@ export async function parsePluginMeta(code: string): Promise throw new Error('Metadata not found'); } - const { name, version, author, description, permissions, config } = metadata; + const { name, version, author, description, permissions, config, id } = metadata; if (name == null || version == null || author == null) { throw new Error('Required property not found'); } + if (id != null && !/^[a-zA-Z0-9_]+$/.test(id)) { + throw new Error('Invalid id format.'); + } + return { name, version, @@ -118,6 +123,7 @@ export async function parsePluginMeta(code: string): Promise description, permissions, config, + id, }; } @@ -134,15 +140,16 @@ export async function installPlugin(code: string, meta?: AiScriptPluginMeta) { const plugins = Object.keys(await getPluginList()); const pluginHash = await toHash(realMeta.name, realMeta.author); - const { isLocal, pluginOnlyOverride } = (await new Promise((res, rej) => { + const { isLocal, pluginOnlyOverride } = await new Promise((res, rej) => { + const pluginCheckId = realMeta.id ?? pluginHash; os.popup(defineAsyncComponent(() => import('@/components/MkPluginSelectSaveWindow.vue')), { - isExistsFromAccount: plugins.some(v => v === pluginHash) + isExistsFromAccount: plugins.some(v => v === pluginCheckId) }, { done: result => { res(result); }, }, 'closed'); - })); + }); const token = realMeta.permissions == null || realMeta.permissions.length === 0 || pluginOnlyOverride ? null : await new Promise((res, rej) => { os.popup(defineAsyncComponent(() => import('@/components/MkTokenGenerateWindow.vue')), { @@ -165,14 +172,14 @@ export async function installPlugin(code: string, meta?: AiScriptPluginMeta) { if (isLocal) { savePlugin({ - id: uuid(), + id: realMeta.id ?? uuid(), meta: realMeta, token, src: code, }); } else { await savePluginToAccount(pluginOnlyOverride, { - hash: pluginHash, + id: realMeta.id ?? pluginHash, meta: realMeta, token, src: code,