Skip to content

Commit

Permalink
refactor: Simplify the codebase with functional Overleaf implementati…
Browse files Browse the repository at this point in the history
…on (#2)

Simplify and refactor the entire codebase to the new architecture.
---------

Co-authored-by: YiyanZhai <zhaiyiyan17@gmail.com>
  • Loading branch information
Neet-Nestor and YiyanZhai authored Sep 1, 2024
1 parent 567eef7 commit f9e4e6e
Show file tree
Hide file tree
Showing 11 changed files with 261 additions and 214 deletions.
3 changes: 1 addition & 2 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,10 @@ jobs:
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '16'
node-version: "16"

- name: Install dependencies
run: npm install

- name: Run linter check
run: npm run lint

60 changes: 22 additions & 38 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,57 +15,41 @@ The `web-agent-interface` library provides an API to interact with text selectio
To install and build the library, follow these steps:

1. Clone the repository:
```bash
git clone https://github.com/mlc-ai/web-agent-interface.git
cd web-agent-interface
```

```bash
git clone https://github.com/mlc-ai/web-agent-interface.git
cd web-agent-interface
```

2. Install dependencies and build the project:
```bash
npm install
npm run build
```

3. Import the necessary modules into your project. For example, if the dependency is named `@mlc-ai/web-agent-interface`:
```javascript
import { OverleafPage } from '@mlc-ai/web-agent-interface';
```
```bash
npm install
npm run build
```

## Usage

### 1. Creating a Page Instance
Depending on the platform you're working with, you can create an instance of the corresponding page class:
### 1. Initialize the page handler in content script

- For **Overleaf**:
```javascript
const overleafPage = new OverleafPage();
```
<!--
- For **Google Docs**:
```javascript
const gdocPage = new GoogleDocPage();
import { initHandler } from '@mlc-ai/web-agent-interface';
const handler = initHandler();
```
- For **Google Calendar**:
```javascript
const gcalPage = new GCalPage();
``` -->
### 2. Handling Text
### 2. Get Available Tools
- Get the selected text:
```javascript
const selectedText = overleafPage.executeAction('getTextSelection');
console.log('Selected text:', selectedText);
```
```javascript
import { getTools } from '@mlc-ai/web-agent-interface';
- Replace selected text:
```javascript
overleafPage.executeAction('replaceSelectedText', { newText: 'Your new text here' });
const availableTools = getTools();
```
- Adding Text to the End of the Document:
### 3. Handling Tool Use
```javascript
overleafPage.executeAction('addTextToEnd', { newText: 'Text to append' });
```
const observation = handler.handleToolCall(toolName, parameters);
console.log("Got observation:", observation);
```
25 changes: 25 additions & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import eslint from "eslint";

const { ESLint } = eslint;

export default new ESLint({
baseConfig: {
env: {
browser: true,
es2021: true,
node: true,
},
extends: ["eslint:recommended"],
parserOptions: {
ecmaVersion: 2021,
sourceType: "module",
},
rules: {
"no-unused-vars": "warn",
"no-console": "off",
indent: ["error", 2],
quotes: ["error", "single"],
semi: ["error", "always"],
},
},
});
66 changes: 35 additions & 31 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,33 +1,37 @@
{
"name": "web-agent-interface",
"version": "0.1.0",
"description": "A generic library for web interaction",
"main": "lib/index.js",
"type": "module",
"scripts": {
"build": "rollup -c",
"lint": "npx eslint . && prettier --check \"./**/*.{js,jsx,mjs,cjs,ts,tsx,json}\"",
"test": "jest",
"format": "prettier --write \"./**/*.{js,jsx,mjs,cjs,ts,tsx,json}\""
},
"repository": {
"type": "git",
"url": "git+https://github.com/mlc-ai/web-agent-interface.git"
},
"license": "Apache-2.0",
"bugs": {
"url": "https://github.com/mlc-ai/web-agent-interface/issues"
},
"homepage": "https://github.com/mlc-ai/web-agent-interface#readme",
"devDependencies": {
"@rollup/plugin-commonjs": "^25.0.7",
"@rollup/plugin-image": "^3.0.3",
"@rollup/plugin-node-resolve": "^15.2.3",
"@types/jest": "^29.5.12",
"@types/node": "^20.12.5",
"eslint": "^8.57.0",
"rollup": "^4.14.0",
"rollup-plugin-ignore": "^1.0.10",
"rollup-plugin-sass": "^1.12.21"
}
"name": "@mlc-ai/web-agent-interface",
"version": "0.1.0",
"description": "A generic library for web interaction",
"main": "lib/index.js",
"type": "module",
"scripts": {
"build": "webpack --config webpack.config.cjs",
"lint": "npx eslint . && prettier --check \"./**/*.{js,jsx,mjs,cjs,ts,tsx,json}\"",
"test": "jest",
"format": "prettier --write \"./**/*.{js,jsx,mjs,cjs,ts,tsx,json}\""
},
"repository": {
"type": "git",
"url": "git+https://github.com/mlc-ai/web-agent-interface.git"
},
"license": "Apache-2.0",
"bugs": {
"url": "https://github.com/mlc-ai/web-agent-interface/issues"
},
"homepage": "https://github.com/mlc-ai/web-agent-interface#readme",
"devDependencies": {
"@types/jest": "^29.5.12",
"@types/node": "^22.5.0",
"babel-loader": "^9.1.3",
"css-loader": "^7.1.2",
"eslint": "^9.9.1",
"jest": "^29.7.0",
"mini-css-extract-plugin": "^2.9.1",
"prettier": "^3.3.3",
"sass": "^1.77.8",
"sass-loader": "^16.0.1",
"style-loader": "^4.0.0",
"webpack": "^5.94.0",
"webpack-cli": "^5.1.4"
}
}
26 changes: 0 additions & 26 deletions rollup.config.mjs

This file was deleted.

15 changes: 0 additions & 15 deletions src/action.js

This file was deleted.

35 changes: 31 additions & 4 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,31 @@
export { Page } from './page/page';
export { Action } from './action';
export { OverleafPage } from './page/overleafPage';
export { GoogleDocPage } from './page/googleDocPage';
import * as Overleaf from "./page/overleaf.js";

const PAGE_HANDLER_MAP = {
"www.overleaf.com": Overleaf,
};

const initHandler = () => {
if (Object.keys(PAGE_HANDLER_MAP).includes(window.location.hostname)) {
return PAGE_HANDLER_MAP[window.location.hostname].initHandler();
}
console.error("[Web Agent Interface] No handler found for the current page");
};

const getTools = () => {
if (Object.keys(PAGE_HANDLER_MAP).includes(window.location.hostname)) {
return PAGE_HANDLER_MAP[window.location.hostname].actions;
}
console.error("[Web Agent Interface] No actions found for the current page");
};

const getToolDisplayName = (action) => {
if (
Object.keys(PAGE_HANDLER_MAP).includes(window.location.hostname) &&
PAGE_HANDLER_MAP[window.location.hostname].actions.includes(action)
) {
return PAGE_HANDLER_MAP[window.location.hostname].nameToDisplayName[action];
}
console.error("[Web Agent Interface] No actions found for the current page");
};

export { initHandler, getTools, getToolDisplayName };
88 changes: 88 additions & 0 deletions src/page/overleaf.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/**
* Implementation of getTextSelection, replaceSelectedText, etc for Overleaf
* @class OverleafPage
*/
class PageHandler {
currentSelection = null;

constructor() {
// Listen for the selection change event
document.addEventListener("selectionchange", this.handleSelectionChange);
}

handleSelectionChange = () => {
const selection = window.getSelection();

if (
selection &&
typeof selection.rangeCount !== "undefined" &&
selection.rangeCount > 0
) {
this.currentSelection = selection;
}
};

getSelectionImpl = () => {
if (!this.currentSelection) {
return "";
}
const selectedText = this.currentSelection.toString();
return selectedText;
};

replaceSelectionImpl = (params) => {
const newText = params.newText;
const selection = this.currentSelection;
if (!newText || !selection) {
return;
}
if (selection.rangeCount > 0) {
const range = selection.getRangeAt(0);
range.deleteContents();
if (Array.isArray(newText)) {
const fragment = document.createDocumentFragment();
newText.forEach((text) =>
fragment.appendChild(document.createTextNode(text)),
);
range.insertNode(fragment);
} else {
range.insertNode(document.createTextNode(newText));
}
selection.removeAllRanges();
} else {
return;
}
};

appendTextImpl = (params) => {
const text = params.text;
const editorElement = document.querySelector(".cm-content");
if (editorElement) {
const textNode = document.createTextNode(text);
editorElement.appendChild(textNode);
}
};

handleToolCall = (toolName, params) => {
const toolImplementation = this.toolNameToImplementation[actionName];
if (action) {
const response = toolImplementation(params);
return response;
} else {
console.warn(`Tool '${toolName}' not found.`);
}
};

toolNameToImplementation = {
getSelection: this.getSelectionImpl,
replaceSelection: this.replaceSelectionImpl,
appendText: this.appendTextImpl,
};
}
export const nameToDisplayName = {
getSelection: "Get Selected Text",
replaceSelection: "Replace Selected Text",
appendText: "Add Text to Document",
};
export const tools = Object.keys(nameToDisplayName);
export const initHandler = () => new PageHandler();
Loading

0 comments on commit f9e4e6e

Please sign in to comment.