Skip to content

Commit

Permalink
Move extlib generation into its own source package
Browse files Browse the repository at this point in the history
  • Loading branch information
Thomas101 committed Dec 10, 2024
1 parent e4fcff0 commit 5b71def
Show file tree
Hide file tree
Showing 18 changed files with 320 additions and 134 deletions.
4 changes: 4 additions & 0 deletions build/generate_eslint.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ await writeConfig(path.join(srcDir, 'extension'), {
root: true,
overrides: [jsEslint, mergeEnv(tsEslint, { browser: true })]
})
await writeConfig(path.join(srcDir, 'extlib'), {
root: true,
overrides: [jsEslint, mergeEnv(tsEslint, { browser: true })]
})
await writeConfig(path.join(srcDir, 'native/main'), {
root: true,
overrides: [jsEslint, mergeEnv(tsEslint, { node: true })]
Expand Down
22 changes: 4 additions & 18 deletions src/extension/contentscript-main/AI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import {
} from '#Shared/API/AIIPCTypes'
import { throwIPCErrorResponse } from '#Shared/IPC/IPCErrorHelper'
import { AICapabilities } from '#Shared/API/AI'
import { kExtensionNotFound } from '#Shared/BrowserErrors'

class AI extends EventTarget {
/* **************************************************************************/
Expand Down Expand Up @@ -79,23 +78,10 @@ class AI extends EventTarget {
/* **************************************************************************/

capabilities = async () => {
if (process.env.BROWSER !== 'extlib') {
const capabilities = throwIPCErrorResponse(
await IPC.request(kAIGetCapabilities, {})
) as AICapabilities
return capabilities
} else {
try {
const capabilities = await IPC.request(kAIGetCapabilities, {})
return capabilities as AICapabilities
} catch (ex) {
if (ex.message === kExtensionNotFound) {
return { extension: false, helper: false } as AICapabilities
} else {
throw ex
}
}
}
const capabilities = throwIPCErrorResponse(
await IPC.request(kAIGetCapabilities, {})
) as AICapabilities
return capabilities
}

getHelperDownloadUrl = async () => {
Expand Down
2 changes: 1 addition & 1 deletion src/extension/contentscript-main/IPC/ContentScriptPort.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {
kContentScriptMessageChannel,
kContentScriptDisconnectChannel
} from '#Shared/IPC/ContentScriptIPC'
import { PortEventHandler } from './PortEventHandler'
import { PortEventHandler } from '#Shared/IPC/PortEventHandler'

export default class ContentScriptPort {
/* **************************************************************************/
Expand Down
20 changes: 5 additions & 15 deletions src/extension/contentscript-main/IPC/IPC.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,10 @@
import IPCClient from '#Shared/IPC/IPCClient'
import ContentScriptPort from './ContentScriptPort'
import ExtensionLibPort from './ExtensionLibPort'

let ipcClient
if (process.env.BROWSER === 'extlib') {
ipcClient = new IPCClient(new ExtensionLibPort(), {
// The port in contentscript-main automatically reconnects after it's been destroyed
// and there's no persisted state in the background page between different ports
portReconnects: true
})
} else {
ipcClient = new IPCClient(new ContentScriptPort(), {
// The port in the extension automatically reconnects after it's been destroyed
// and there's no persisted state in the background page between different ports
portReconnects: true
})
}
const ipcClient = new IPCClient(new ContentScriptPort(), {
// The port in the extension automatically reconnects after it's been destroyed
// and there's no persisted state in the background page between different ports
portReconnects: true
})

export default ipcClient
18 changes: 8 additions & 10 deletions src/extension/contentscript-main/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,14 @@ import Translation from './Translation'
export const ai = new AI(window.ai)
export const translation = new Translation(ai, (window as any).translation)

if (process.env.BROWSER !== 'extlib') {
const genericWindow = window as any
if (!window.ai || genericWindow.ai?.__aibrowOverride === true) {
genericWindow.ai = ai
}
if (!genericWindow.translation || genericWindow.translation?.__aibrowOverride === true) {
genericWindow.translation = translation
}
genericWindow.aibrow = ai
genericWindow.aibrowTranslation = translation
const genericWindow = window as any
if (!window.ai || genericWindow.ai?.__aibrowOverride === true) {
genericWindow.ai = ai
}
if (!genericWindow.translation || genericWindow.translation?.__aibrowOverride === true) {
genericWindow.translation = translation
}
genericWindow.aibrow = ai
genericWindow.aibrowTranslation = translation

export default ai
129 changes: 40 additions & 89 deletions src/extension/webpack.config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -13,102 +13,53 @@ const rollupTypesPlugin = require('../../build/rollupTypesPlugin.cjs')
module.exports = function ({ outDir, nodeModulesDir, pkg, config }, { mode }) {
const srcDir = __dirname

return ['crx', 'moz', 'extlib'].map((browser) => {
let entry
let output
let copyPatterns
let plugins
switch (browser) {
case 'extlib':
entry = {
index: path.join(srcDir, 'contentscript-main/index.ts')
}
output = {
filename: '[name].js',
path: path.join(outDir, browser),
library: config.extensionLibrary.name,
libraryTarget: 'umd',
umdNamedDefine: true
}
copyPatterns = [
{
from: path.join(srcDir, `${browser}-package.json`),
to: 'package.json',
force: true,
transform: (content) => {
const manifest = JSON.parse(content.toString())
manifest.name = config.extensionLibrary.name
for (const key of ['version', 'author', 'license', 'description', 'repository']) {
manifest[key] = pkg[key]
}
return JSON.stringify(manifest, null, 2)
}
},
{ from: path.join(srcDir, `${browser}-README.md`), to: 'README.md', force: true }
]
plugins = [
rollupTypesPlugin(
path.join(srcDir, 'contentscript-main/index.ts'),
path.join(__dirname, 'types-rollup.config.js'),
path.join(outDir, browser, 'index.d.ts')
)
]
break
default: {
const uiEntryPoints = ['ui-permission-popup', 'ui-model-install-popup', 'ui-options']
entry = {
background: path.join(srcDir, 'background/index.ts'),
'contentscript-isolated': path.join(srcDir, 'contentscript-isolated/index.ts'),
'contentscript-main': path.join(srcDir, 'contentscript-main/index.ts'),
'contentscript-main-override': path.join(srcDir, 'contentscript-main-override/index.ts'),
...uiEntryPoints.reduce((acc, key) => {
acc[key] = path.join(srcDir, `${key}/index.ts`)
return acc
}, {})
}
output = {
filename: '[name].js',
path: path.join(outDir, 'extension', browser)
}
copyPatterns = [
{
from: path.join(srcDir, `${browser}-manifest.json`),
to: 'manifest.json',
force: true,
transform: (content) => {
const manifest = JSON.parse(content.toString())
manifest.version = pkg.version
return JSON.stringify(manifest, null, 2)
}
},
{ from: path.join(srcDir, 'icons'), to: 'icons', force: true }
]
plugins = [
...uiEntryPoints.map((key) => new HtmlWebpackPlugin({
chunks: [key],
filename: `${key}.html`,
template: path.join(srcDir, `${key}/index.html`),
title: 'AiBrow',
meta: {
viewport: 'width=device-width, initial-scale=1, shrink-to-fit=no'
}
}))
]
break
}
}

const uiEntryPoints = ['ui-permission-popup', 'ui-model-install-popup', 'ui-options']
return ['crx', 'moz'].map((browser) => {
return {
entry,
output,
entry: {
background: path.join(srcDir, 'background/index.ts'),
'contentscript-isolated': path.join(srcDir, 'contentscript-isolated/index.ts'),
'contentscript-main': path.join(srcDir, 'contentscript-main/index.ts'),
'contentscript-main-override': path.join(srcDir, 'contentscript-main-override/index.ts'),
...uiEntryPoints.reduce((acc, key) => {
acc[key] = path.join(srcDir, `${key}/index.ts`)
return acc
}, {})
},
output: {
filename: '[name].js',
path: path.join(outDir, 'extension', browser)
},
devtool: mode === 'development' ? 'inline-cheap-source-map' : undefined,
plugins: [
...plugins,
...uiEntryPoints.map((key) => new HtmlWebpackPlugin({
chunks: [key],
filename: `${key}.html`,
template: path.join(srcDir, `${key}/index.html`),
title: 'AiBrow',
meta: {
viewport: 'width=device-width, initial-scale=1, shrink-to-fit=no'
}
})),
new webpack.DefinePlugin({ 'process.env.BROWSER': JSON.stringify(browser) }),
new CleanWebpackPlugin(),
new CaseSensitivePathsPlugin(),
new CircularDependencyPlugin({ exclude: /node_modules/, failOnError: true, allowAsyncCycles: false }),
new CopyWebpackPlugin({ patterns: copyPatterns }),
new CopyWebpackPlugin({
patterns: [
{
from: path.join(srcDir, `${browser}-manifest.json`),
to: 'manifest.json',
force: true,
transform: (content) => {
const manifest = JSON.parse(content.toString())
manifest.version = pkg.version
return JSON.stringify(manifest, null, 2)
}
},
{ from: path.join(srcDir, 'icons'), to: 'icons', force: true }
]
}),
new MiniCssExtractPlugin()
],
module: {
Expand Down
99 changes: 99 additions & 0 deletions src/extlib/AI.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import AISummarizerFactory from '#Shared/API/AISummarizer/AISummarizerFactory'
import AIWriterFactory from '#Shared/API/AIWriter/AIWriterFactory'
import AIRewriterFactory from '#Shared/API/AIRewriter/AIRewriterFactory'
import AILanguageModelFactory from '#Shared/API/AILanguageModel/AILanguageModelFactory'
import AICoreModelFactory from '#Shared/API/AICoreModel/AICoreModelFactory'
import AIEmbeddingFactory from '#Shared/API/AIEmbedding/AIEmbeddingFactory'
import AITranslatorFactory from '#Shared/API/AITranslator/AITranslatorFactory'
import AILanguageDetectorFactory from '#Shared/API/AILanguageDetector/AILanguageDetectorFactory'
import IPC from './IPC'
import {
kAIGetCapabilities,
kAIGetNativeHelperDownloadUrl
} from '#Shared/API/AIIPCTypes'
import { AICapabilities } from '#Shared/API/AI'
import { kExtensionNotFound } from '#Shared/BrowserErrors'

class AI extends EventTarget {
/* **************************************************************************/
// MARK: Private
/* **************************************************************************/

#browserAI: globalThis.AI | undefined
#summarizer: AISummarizerFactory
#writer: AIWriterFactory
#rewriter: AIRewriterFactory
#languageModel: AILanguageModelFactory
#coreModel: AICoreModelFactory
#embedding: AIEmbeddingFactory
#translator: AITranslatorFactory
#languageDetector: AILanguageDetectorFactory

/* **************************************************************************/
// MARK: Lifecycle
/* **************************************************************************/

constructor (browserAI: globalThis.AI | undefined) {
super()

this.#browserAI = browserAI
this.#summarizer = new AISummarizerFactory(IPC)
this.#writer = new AIWriterFactory(IPC)
this.#rewriter = new AIRewriterFactory(IPC)
this.#languageModel = new AILanguageModelFactory(IPC)
this.#coreModel = new AICoreModelFactory(IPC)
this.#embedding = new AIEmbeddingFactory(IPC)
this.#translator = new AITranslatorFactory(IPC)
this.#languageDetector = new AILanguageDetectorFactory(IPC)
}

/* **************************************************************************/
// MARK: Properties
/* **************************************************************************/

get browserAI () { return this.#browserAI }

get aibrow () { return true }

get assistant () { return this.#languageModel }

get summarizer () { return this.#summarizer }

get writer () { return this.#writer }

get rewriter () { return this.#rewriter }

get languageModel () { return this.#languageModel }

get coreModel () { return this.#coreModel }

get embedding () { return this.#embedding }

get translator () { return this.#translator }

get languageDetector () { return this.#languageDetector }

/* **************************************************************************/
// MARK: Capabilities
/* **************************************************************************/

capabilities = async () => {
try {
const capabilities = await IPC.request(kAIGetCapabilities, {})
return capabilities as AICapabilities
} catch (ex) {
if (ex.message === kExtensionNotFound) {
return { extension: false, helper: false } as AICapabilities
} else {
throw ex
}
}
}

getHelperDownloadUrl = async () => {
const url = await IPC.request(kAIGetNativeHelperDownloadUrl, {})
return url
}
}

export default AI
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {
kExtensionLibPortName
} from '#Shared/IPC/ContentScriptIPC'
import config from '#Shared/Config'
import { PortEventHandler } from './PortEventHandler'
import { PortEventHandler } from '#Shared/IPC/PortEventHandler'
import { kExtensionNotFound } from '#Shared/BrowserErrors'

export default class ExtensionLibPort {
Expand Down
10 changes: 10 additions & 0 deletions src/extlib/IPC/IPC.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import IPCClient from '#Shared/IPC/IPCClient'
import ExtensionLibPort from './ExtensionLibPort'

const ipcClient = new IPCClient(new ExtensionLibPort(), {
// The port in contentscript-main automatically reconnects after it's been destroyed
// and there's no persisted state in the background page between different ports
portReconnects: true
})

export default ipcClient
2 changes: 2 additions & 0 deletions src/extlib/IPC/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import IPC from './IPC'
export default IPC
1 change: 1 addition & 0 deletions src/extlib/extlib-README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Extension library for AiBrow. See [AiBrow](https://github.com/axonzeta/aibrow/)
4 changes: 4 additions & 0 deletions src/extlib/extlib-package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"main": "index.js",
"types": "index.d.ts"
}
5 changes: 5 additions & 0 deletions src/extlib/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import AI from './AI'

export const ai = new AI(window.ai)

export default ai
Loading

0 comments on commit 5b71def

Please sign in to comment.