Skip to content

Commit fbabb29

Browse files
committed
Add Meta AI chatbot support
1 parent 10b7892 commit fbabb29

12 files changed

Lines changed: 202 additions & 12 deletions

File tree

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,10 @@ Get accurate code at cursor from state-of-the-art reasoning models.
7272
Modify files based on natural language instructions.
7373

7474
**Intelligent Update** \
75-
Integrate AI responses in "truncated" edit format and fix malformed diffs.
75+
Integrate truncated code blocks and fix malformed diffs.
7676

7777
**Commit Messages** \
78-
Generate meaningful summaries of changes precisely adhering to your preferred style.
78+
Generate meaningful summaries of changes adhering to your preferred style.
7979

8080
## <span style="background-color: #fbb100; color: black; padding: 0.2em 0.6em; border-radius: 999px">Commands</span>
8181

packages/browser/src/content-scripts/send-prompt-content-script/chatbots/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ export * from './claude'
44
export * from './deepseek'
55
export * from './gemini'
66
export * from './grok'
7+
export * from './meta'
78
export * from './mistral'
89
export * from './open-webui'
910
export * from './openrouter'
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
import { Chatbot } from '../types/chatbot'
2+
// import browser from 'webextension-polyfill'
3+
// import {
4+
// apply_chat_response_button_style,
5+
// set_button_disabled_state
6+
// } from '../utils/apply-response-styles'
7+
// import { Message } from '@/types/messages'
8+
// import { is_eligible_code_block } from '../utils/is-eligible-code-block'
9+
// import {
10+
// apply_response_button_text,
11+
// apply_response_button_title
12+
// } from '../constants/copy'
13+
// import { show_response_ready_notification } from '../utils/show-response-ready-notification'
14+
15+
export const meta: Chatbot = {
16+
wait_until_ready: async () => {
17+
await new Promise((resolve) => {
18+
const check_for_element = () => {
19+
if (document.querySelector('i[data-visualcompletion="css-img"]')) {
20+
resolve(null)
21+
} else {
22+
setTimeout(check_for_element, 100)
23+
}
24+
}
25+
check_for_element()
26+
})
27+
},
28+
enter_message_and_send: async (message: string) => {
29+
const input_element = document.querySelector(
30+
'div[contenteditable=true]'
31+
) as HTMLElement
32+
33+
if (!input_element) return
34+
35+
input_element.dispatchEvent(
36+
new InputEvent('input', {
37+
bubbles: true,
38+
cancelable: true,
39+
inputType: 'insertText',
40+
data: message
41+
})
42+
)
43+
44+
new Promise<void>((resolve) => {
45+
const check_button_state = () => {
46+
const path_element = document.querySelector(
47+
'path[d="M13 7.414V19a1 1 0 1 1-2 0V7.414l-3.293 3.293a1 1 0 0 1-1.414-1.414l5-5a1 1 0 0 1 1.414 0l5 5a1 1 0 0 1-1.414 1.414L13 7.414z"]'
48+
)
49+
const send_button = path_element?.closest(
50+
'div[role="button"]'
51+
) as HTMLElement
52+
53+
if (
54+
send_button &&
55+
send_button.getAttribute('aria-disabled') != 'true'
56+
) {
57+
send_button.click()
58+
resolve()
59+
} else {
60+
setTimeout(check_button_state, 100)
61+
}
62+
}
63+
check_button_state()
64+
})
65+
}
66+
// Disabled for now because code blocks in copied text are not enclosed in markdown blocks (```)
67+
// inject_apply_response_button: (client_id: number) => {
68+
// const add_buttons = (params: { footer: Element }) => {
69+
// // Check if buttons already exist by text content to avoid duplicates
70+
// const existing_apply_response_button = Array.from(
71+
// params.footer.querySelectorAll('button')
72+
// ).find((btn) => btn.textContent == apply_response_button_text)
73+
74+
// if (existing_apply_response_button) return
75+
76+
// const chat_turn = params.footer.parentElement as HTMLElement
77+
// if (!chat_turn) return
78+
79+
// const code_blocks = chat_turn.querySelectorAll('code')
80+
// let has_eligible_block = false
81+
// for (const code_block of Array.from(code_blocks)) {
82+
// const first_line_text = code_block?.textContent?.split('\n')[0]
83+
// if (first_line_text && is_eligible_code_block(first_line_text)) {
84+
// has_eligible_block = true
85+
// break
86+
// }
87+
// }
88+
// if (!has_eligible_block) return
89+
90+
// const create_apply_response_button = () => {
91+
// const apply_response_button = document.createElement('button')
92+
// apply_response_button.textContent = apply_response_button_text
93+
// apply_response_button.title = apply_response_button_title
94+
// apply_chat_response_button_style(apply_response_button)
95+
96+
// apply_response_button.addEventListener('click', async () => {
97+
// set_button_disabled_state(apply_response_button)
98+
// const copy_button = params.footer.querySelector(
99+
// 'div[role="button"]'
100+
// ) as HTMLDivElement
101+
// if (copy_button) {
102+
// copy_button.click()
103+
// }
104+
// await new Promise((resolve) => setTimeout(resolve, 500))
105+
// browser.runtime.sendMessage<Message>({
106+
// action: 'apply-chat-response',
107+
// client_id
108+
// })
109+
// })
110+
111+
// params.footer.insertBefore(
112+
// apply_response_button,
113+
// params.footer.children[params.footer.children.length]
114+
// )
115+
// }
116+
117+
// create_apply_response_button()
118+
// }
119+
120+
// const observer = new MutationObserver(() => {
121+
// const thumb_up_paths = document.querySelectorAll(
122+
// 'div[role="button"] path[d="m10.894 6.447 1.715-3.429c.56.107.939.669.794 1.247L13.04 5.72l-.988 2.964A1 1 0 0 0 13 10h6.53a.7.7 0 0 1 .436 1.246l-.526.421a1.09 1.09 0 0 0-.226 1.457.818.818 0 0 1-.19 1.108l-.624.468a1 1 0 0 0-.294 1.247l.105.211a1 1 0 0 1-.447 1.342l-.211.106a1 1 0 0 0-.502 1.21l.092.276a.69.69 0 0 1-.655.908h-4.204a4.515 4.515 0 0 1-3.192-1.323A5.727 5.727 0 0 0 5.042 17H4a1 1 0 1 0 0 2h1.042c.988 0 1.936.393 2.636 1.092A6.515 6.515 0 0 0 12.284 22h4.204a2.69 2.69 0 0 0 2.67-3.025 3.004 3.004 0 0 0 1.06-3.138l.006-.005a2.819 2.819 0 0 0 1.015-3.043A2.7 2.7 0 0 0 19.53 8h-5.142l.562-1.684a.993.993 0 0 0 .021-.073l.373-1.493A3.018 3.018 0 0 0 12.416 1c-.634 0-1.213.358-1.496.925L9.127 5.51l-1.3 2.08A3 3 0 0 1 5.283 9H4a1 1 0 0 0 0 2h1.283a5 5 0 0 0 4.24-2.35l1.325-2.12a.977.977 0 0 0 .046-.083z"]'
123+
// )
124+
// const thumb_up_buttons: Element[] = []
125+
// thumb_up_paths.forEach((path) =>
126+
// thumb_up_buttons.push(path.closest('div[role="button"]') as HTMLElement)
127+
// )
128+
// const all_footers: Element[] = []
129+
// thumb_up_buttons.forEach((button) =>
130+
// all_footers.push(button.closest('div:not([role="button"])') as Element)
131+
// )
132+
133+
// if (
134+
// !all_footers.length ||
135+
// !document.querySelector(
136+
// 'div[aria-disabled="true"] path[d="M3 6a3 3 0 0 1 3-3h12a3 3 0 0 1 3 3v12a3 3 0 0 1-3 3H6a3 3 0 0 1-3-3V6z"]'
137+
// )
138+
// ) {
139+
// return
140+
// }
141+
142+
// show_response_ready_notification({ chatbot_name: 'Meta' })
143+
144+
// all_footers.forEach((footer) => add_buttons({ footer }))
145+
// })
146+
147+
// observer.observe(document.body, { childList: true, subtree: true })
148+
// }
149+
}

packages/browser/src/content-scripts/send-prompt-content-script/send-prompt-content-script.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
gemini,
88
chatgpt,
99
claude,
10+
meta,
1011
mistral,
1112
open_webui,
1213
deepseek,
@@ -57,6 +58,9 @@ const is_qwen = current_url.startsWith(qwen_url)
5758
const yuanbao_url = 'https://yuanbao.tencent.com/chat'
5859
const is_yuanbao = current_url.startsWith(yuanbao_url)
5960

61+
const meta_url = 'https://www.meta.ai/'
62+
const is_meta = current_url.startsWith(meta_url)
63+
6064
const grok_url = 'https://grok.com/'
6165
const is_grok = current_url.startsWith(grok_url)
6266

@@ -87,6 +91,8 @@ if (is_ai_studio) {
8791
chatbot = chatgpt
8892
} else if (is_claude) {
8993
chatbot = claude
94+
} else if (is_meta) {
95+
chatbot = meta
9096
} else if (is_mistral) {
9197
chatbot = mistral
9298
} else if (is_open_webui) {
@@ -118,6 +124,7 @@ export const get_textarea_element = () => {
118124
[ai_studio_url]: 'textarea',
119125
[gemini_url]: 'div[contenteditable="true"]',
120126
[openrouter_url]: 'textarea',
127+
[meta_url]: 'div[contenteditable="true"]',
121128
[chatgpt_url]: 'div#prompt-textarea',
122129
[deepseek_url]: 'textarea',
123130
[mistral_url]: 'div[contenteditable="true"]',

packages/browser/src/manifest.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"author": "Robert Piosik",
44
"name": "Code Web Chat Connector",
55
"short_name": "CWC",
6-
"description": "Initialize 15+ chatbots and manage websites for context.",
6+
"description": "Initialize 15+ chatbots with your code and instructions. Manage websites for context.",
77
"version": "1.23.0",
88
"homepage_url": "https://github.com/robertpiosik/CodeWebChat",
99
"icons": {
@@ -32,6 +32,7 @@
3232
"https://grok.com/",
3333
"https://chat.deepseek.com/",
3434
"https://chat.mistral.ai/chat",
35+
"https://www.meta.ai/",
3536
"https://chat.qwen.ai/",
3637
"https://yuanbao.tencent.com/chat*",
3738
"https://www.doubao.com/chat/",

packages/shared/src/constants/chatbots.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,19 @@ export const CHATBOTS = {
169169
default_top_p: 0,
170170
models: {}
171171
},
172+
Meta: {
173+
url: 'https://www.meta.ai/',
174+
supports_custom_temperature: false,
175+
supports_custom_top_p: false,
176+
supports_system_instructions: false,
177+
supports_user_provided_model: false,
178+
supports_user_provided_port: false,
179+
supports_thinking_budget: false,
180+
default_system_instructions: '',
181+
supported_options: {},
182+
default_top_p: 0,
183+
models: {}
184+
},
172185
'Open WebUI': {
173186
url: 'http://openwebui/',
174187
supports_custom_temperature: true,
Lines changed: 7 additions & 0 deletions
Loading

packages/ui/src/components/editor/Icon/Icon.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import ChatGPT from '../../../assets/icons/openai.svg'
77
import Claude from '../../../assets/icons/claude.svg'
88
import DeepSeek from '../../../assets/icons/deepseek.svg'
99
import Mistral from '../../../assets/icons/mistral.svg'
10+
import Meta from '../../../assets/icons/meta.svg'
1011
import Grok from '../../../assets/icons/grok.svg'
1112
import Kimi from '../../../assets/icons/kimi.svg'
1213
import Qwen from '../../../assets/icons/qwen.svg'
@@ -32,6 +33,7 @@ export namespace Icon {
3233
| 'CLAUDE'
3334
| 'DEEPSEEK'
3435
| 'MISTRAL'
36+
| 'META'
3537
| 'GROK'
3638
| 'KIMI'
3739
| 'QWEN'
@@ -82,6 +84,9 @@ export const Icon: React.FC<Icon.Props> = ({ variant }) => {
8284
case 'MISTRAL':
8385
icon = <Mistral />
8486
break
87+
case 'META':
88+
icon = <Meta />
89+
break
8590
case 'GROK':
8691
icon = <Grok />
8792
break

packages/ui/src/components/editor/Presets/Presets.module.scss

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,14 @@
7676
}
7777
}
7878

79-
&__icon > svg {
80-
fill: var(--vscode-icon-foreground);
81-
width: 16px;
82-
height: 16px;
79+
&__icon {
80+
display: flex;
81+
82+
> svg {
83+
fill: var(--vscode-icon-foreground);
84+
width: 16px;
85+
height: 16px;
86+
}
8387
}
8488

8589
&__text {

packages/ui/src/components/editor/Presets/Presets.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import { ReactSortable } from 'react-sortablejs'
66
import { Icon } from '../Icon'
77
import { useState } from 'react'
88
import { CHATBOTS } from '@shared/constants/chatbots'
9-
import { TextButton } from '../TextButton'
109

1110
export const chatbot_to_icon: Record<keyof typeof CHATBOTS, Icon.Variant> = {
1211
'AI Studio': 'AI_STUDIO',
@@ -17,6 +16,7 @@ export const chatbot_to_icon: Record<keyof typeof CHATBOTS, Icon.Variant> = {
1716
Claude: 'CLAUDE',
1817
DeepSeek: 'DEEPSEEK',
1918
Mistral: 'MISTRAL',
19+
Meta: 'META',
2020
Grok: 'GROK',
2121
Qwen: 'QWEN',
2222
Yuanbao: 'YUANBAO',

0 commit comments

Comments
 (0)