Giter VIP home page Giter VIP logo

chatgpt.js's Introduction


🤖 A powerful client-side JavaScript library for ChatGPT


💡 About

chatgpt.js is a powerful JavaScript library that allows for super easy interaction w/ the ChatGPT DOM.

  • Feature-rich
  • Object-oriented
  • Easy-to-use
  • Lightweight (yet optimally performant)

⚡ Importing the library

Note To always import the latest version (NOT recommended in production!) replace the versioned jsDelivr URL with: https://cdn.jsdelivr.net/npm/@kudoai/chatgpt.js/chatgpt.min.js

ES6:

(async () => {
    await import('https://cdn.jsdelivr.net/npm/@kudoai/[email protected]/dist/chatgpt.min.js');
    // Your code here...
})();

ES5:

var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://cdn.jsdelivr.net/npm/@kudoai/[email protected]/dist/chatgpt.min.js');
xhr.onload = function () {
    if (xhr.status === 200) {
        var chatgptJS = document.createElement('script');
        chatgptJS.textContent = xhr.responseText;
        document.head.append(chatgptJS);
        yourCode(); // runs your code
    }
};
xhr.send();

function yourCode() {
    // Your code here...
}

Greasemonkey:

Note To use a starter template: kudoai/chatgpt.js-greasemonkey-starter

...
// @require https://cdn.jsdelivr.net/npm/@kudoai/[email protected]/dist/chatgpt.min.js
// ==/UserScript==

// Your code here...

Chrome:

Note To use a starter template: kudoai/chatgpt.js-chrome-starter

Since Google does not allow remote code, importing chatgpt.js locally is required:

  1. Save https://raw.githubusercontent.com/KudoAI/chatgpt.js/main/chatgpt.js to a subdirectory (lib in this example)

  2. Add ES6 export statement to end of lib/chatgpt.js

...
export { chatgpt }
  1. In project's (V3) manifest.json, add lib/chatgpt.js as a web accessible resource
    "web_accessible_resources": [{
        "matches": ["<all_urls>"],
        "resources": ["lib/chatgpt.js"]
    }],
  1. In scripts that need chatgpt.js (foreground/background alike), import it like so:
(async () => {
    const { chatgpt } = await import(chrome.runtime.getURL('lib/chatgpt.js'));
    // Your code here...
})();

💾 Downloading via npm:

To download chatgpt.js for local customization, run the following command in your project's root:

npm install @kudoai/chatgpt.js

After installation, navigate to node_modules/@kudoai/chatgpt.js to find the library source (minified version in dist/).

💻 Usage

chatgpt.js was written w/ ultra flexibility in mind.

For example:

chatgpt.getLastResponse();
chatgpt.getLastReply();
chatgpt.response.getLast();
chatgpt.get('reply', 'last');

Each call equally fetches the last response. If you think it works, it probably will... so just type it!

If it didn't, check out the extended userguide, or simply submit an issue or PR and it will be integrated, ezpz!

🤖 Made with chatgpt.js

demo.mp4

Auto-clear your ChatGPT query history for maximum privacy.
Install / Readme / Discuss

Display ChatGPT answers in Brave Search sidebar (powered by GPT-4!)
Install / Readme / Discuss

Automatically continue generating multiple ChatGPT responses.
Install / Readme / Discuss

Keeps ChatGPT sessions fresh to eliminate network errors + Cloudflare checks.
Install / Readme / Discuss

Display ChatGPT answers in DuckDuckGo sidebar (powered by GPT-4!)
Install / Readme / Discuss

Display ChatGPT answers in Google Search sidebar (powered by GPT-4!)
Install / Readme / Discuss




If you've made something w/ chatgpt.js you want to share, email [email protected] or just open a pull request!

🧠 Contributors

This library exists thanks to code, translations, issues & ideas from the following contributors:



🤝 Partners

chatgpt.js is funded in part by:


chatgpt.js's People

Contributors

abhinavm24 avatar adamlui avatar cyfung1031 avatar dependabot[bot] avatar eltociear avatar iambijayd avatar iamnishantgaharwar avatar imgbotapp avatar kudo-sync-bot avatar luwa-tech avatar madkarmaa avatar mefengl avatar omahs avatar pranav-bhatt avatar rojojun avatar sabbaticaldev avatar xiaoyingyo avatar zin6969 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

chatgpt.js's Issues

temporarily remove event emitters & status check

@mefengl I'm going to temporarily remove your status check to build an initial 0.0.1 release so I can test CORS passes when using ES6 import from CDN so I can update ES6 instructions, then you can try to implement it cleaner in a branch or I will add final clean solution in main, does that sound good?

Working on a new method

I'm working on a new method I want to call getChatID. what is it? basically a rewritten fetch function. this is what I got so far:

// Needs to be called before document loading
const originalFetch = window.fetch;

window.fetch = function (url, options) {
  return originalFetch.apply(this, arguments)
    .then((response) => {
      if (response.url.includes('://chat.openai.com/backend-api/conversations')) {
        response.json().then((data) => { console.log(data); });
      }
      return response;
    });
};

the chat id is the url identifier

image

why rewriting fetch instead of splitting the url? because you can't get the current chat id unless you refresh the page

why am I opening the issue? because even tho it works (the chats ids are in the items object key)

image

it breaks the loading of conversations and I don't know how to fix it

image

tag base element

Cause ChatGPT web is using Tailwind, if we pre-tag elements with id, it will make other scripts' development easier.

Such as, I used to get sendButton by the last button in the form, but after installing the wide-screen mode script, that function actually returned the wrong button.

this should not be much work, cause can use the function defined in #1

Make `.menu.append()` + `.sidebar.append()` user friendly

I finally got around to testing it, did you notice what users have to type:

Image
It's just too unfriendly because they will mess up all the mixed ending symbols, could you change it to be like this instead:

chatgpt.sidebar.append('dropdown', [['label1', 'value1'], ['label2', 'value2']])

Failed to load as a Greasemonkey script

I tried running the following script, and every object prefixed with: chatgpt. returns null. Greasemonkey did download the minified chatgpt js file, but it cannot work at all with the object chatgpt . chatgpt.getLastReply, chatgpt.getLastResponse all return null.

// ==UserScript==
// @name ChatGPT Userscript
// @description A Greasemonkey template to start using chatgpt.js like a boss
// @author chatgpt.js
// @namespace https://chatgpt.js.org
// @Version 2024.1.28
// @match https://chat.openai.com/*
// @ICON https://raw.githubusercontent.com/kudoai/chatgpt.js-greasemonkey-starter/main/media/images/icons/robot/icon48.png
// @require https://cdn.jsdelivr.net/npm/@kudoai/[email protected]/dist/chatgpt-2.6.4.min.js
// @grant GM_getValue
// @grant GM_setValue
// @Noframes
// @homepageURL https://github.com/kudoai/chatgpt.js-greasemonkey-starter
// ==/UserScript==

(async () => {
// Init config
console.log("Inside async ");

// Print chatgpt.js methods
await chatgpt.isLoaded(); 
console.log("Past GPT loading ");


function logHello() {
       (async () => {
  					console.log("Hello again");
       try {
          let lastResponse = await chatgpt.getLastReply();
         
          if (typeof lastResponse === 'string') {
              console.log("Hello " + lastResponse);
          } else {
              console.error("Hello Error: lastResponse is not a string");
          }   

               console.log("Hello " + lastResponse);
          } catch (error) {
              console.error("Async Hello Error:", error);
          }
      })();
 }
// Run the logger when the DOM is ready
window.addEventListener('DOMContentLoaded', logHello());

})();

CORS policy

No matter what I try I get a CORS policy error.

Tried using the CDN to include the script still errors. Uploaded it to perplexity and asked it to give me code that sends a message and gets a response and perplexity says there's an error in the send on line 1575 ;(

[Feature Request] Upload file

I'm not sure if adding a file upload feature is already on your product roadmap, but I believe it is a very important capability to have.

Ability to get/set ChatGPT versions or custom GPT

As the chat GPT page has a ton of new features pertaining to GPT versions and custom GPTs, it would be very handy to have the ability to get or set chat context (amongst multiple historical chats or to a particular custom GPT) from the library.

{ Thank you so much for the time and effort you've put into making this library possible :) }

Logo design

@mefengl

IDK, then it will be two styles?

The style still matches:

image

Or do you like original one:

image

Export current temporary chat without hitting API

I would like to use this extension to save the current chat as json file.

I've noticed that when chat history is set to off, methods like getLastResponse will return messages from my last saved conversation, not the current temporary conversation.

I'm interested in getting the markdown content of messages. I know it exists locally as the copy to clipboard message at the bottom of each response will put it in your keyboard without hitting any API endpoint.

Is this something that could be supported?

Visual reference:
Temporary chat
copy to clipboard

provide hook like beforeSend, afterSend, OnGenerating, OnDidGenerate...

var chatgpt = {
    // ...
    eventEmitter: {
        events: {},

        on: function(eventName, callback) {
            if (!this.events[eventName]) {
                this.events[eventName] = [];
            }
            this.events[eventName].push(callback);
        },

        once: function(eventName, callback) {
            var self = this;
            function oneTimeCallback() {
                callback.apply(null, arguments);
                self.removeListener(eventName, oneTimeCallback);
            }
            this.on(eventName, oneTimeCallback);
        },

        removeListener: function(eventName, callback) {
            if (this.events[eventName]) {
                this.events[eventName] = this.events[eventName].filter(function(cb) {
                    return cb !== callback;
                });
            }
        },

        emit: function(eventName) {
            if (this.events[eventName]) {
                var args = Array.prototype.slice.call(arguments, 1);
                this.events[eventName].forEach(function(callback) {
                    callback.apply(null, args);
                });
            }
        }
    },
    // ...
};

emit is used when status change or other situation

user usage:

// Adding event listeners
chatgpt.eventEmitter.on('beforeSend', function() {
    console.log('Before sending message...');
});

chatgpt.eventEmitter.on('afterSend', function() {
    console.log('After sending message...');
});

chatgpt.eventEmitter.on('onGenerating', function() {
    console.log('Generating a response...');
});

chatgpt.eventEmitter.on('onDidGenerate', function() {
    console.log('Response generated.');
});

// Removing an event listener
// chatgpt.eventEmitter.removeListener('beforeSend', callback);

// Listening to an event only once
// chatgpt.eventEmitter.once('beforeSend', function() {
//     console.log('Before sending message (only once)');
// });

-- from ChatGPT and mefengl

Feature req: Please integrate apipie.ai

Users want access to as much AI as they can get, they dont want to manage 50 accounts, they want the fastest AI they want the cheapest AI, and you can provide all of that for them with this update.

in addition to or in place of integrating with any aggregators - Please integrate APIpie so devs can access them all from one place/subscription and plus it also provides:

-The most affordable, reliable and fastest AI available
-One API to access ~500 Models and growing
-Language, embedding, voice, image, vision and more
-Global AI load balancing, route queries based on price or latency
-Redundancy for major models providing the greatest up time possible
-Global reporting of AI availability, pricing and performance

Its the same API format as openai, just change the domain name and your API key and enjoy a plethora of models without changing any of your code other than how you handle the models list.

This is a win win for everyone, any new AI's from any providers will be automatically integrated into your stack with this one integration. Not to mention all the other advantages.

Rewriting getResponse

I'm using a userscript I made to rewrite the fetch function calls and log the details, and I found an API-way to get a response. I'm working on it, and it might even be better than the DOM solution

const endpoints = {
    session: 'https://chat.openai.com/api/auth/session',
    chat: 'https://chat.openai.com/backend-api/conversations',
    singleChat: 'https://chat.openai.com/backend-api/conversation'
};

    test: function(chatIdx, responseIdx, regeneratedIdx) {
        chatIdx = chatIdx ? chatIdx : 0; // leave it as is because getChatDetails already takes care of the -1
        responseIdx = responseIdx ? responseIdx - 1 : 0;
        regeneratedIdx = regeneratedIdx ? regeneratedIdx - 1 : 0;
        return new Promise((resolve) => { chatgpt.getAccessToken().then(token => {
            getChatData(token).then(data => { resolve(data); });});});

        function getChatData(token) {
            return new Promise((resolve, reject) => {
                const xhr = new XMLHttpRequest();
                chatgpt.getChatDetails(chatIdx).then(chat => {
                    xhr.open('GET', endpoints.singleChat + '/' + chat.id, true); // GET request to the conversation
                    xhr.setRequestHeader('Content-Type', 'application/json');
                    xhr.setRequestHeader('Authorization', 'Bearer ' + token);
                    xhr.onload = () => {
                        if (xhr.status !== 200) return reject('🤖 chatgpt.js >> Request failed. Cannot retrieve chat messages.');
                        const data = JSON.parse(xhr.responseText).mapping; // all messages
                        const userMessages = [];
                        const responses = [];
                        for (const key in data) if (data[key].message && data[key].message.author.role === 'user') userMessages.push(data[key].id); // filter out user messages
                        for (const key in data)
                            // match responses with their indexed parent (user message)
                            if (data[key].message && data[key].message.author.role === 'assistant' && data[key].parent === userMessages[responseIdx]) // use responseIdx because at each user message corresponds a response so it doesn't matter if the variable says response
                                responses.push(data[key].message); // push only chatgpt responses
                        responses.sort((a, b) => a.create_time - b.create_time); // sort by creation time (in case of the response being regenerated)
                        resolve(responses[regeneratedIdx].content.parts[0]); // resolve promise giving the regenerate value requested
                    };
                    xhr.send();
                });
        });}
    },

Storing access token(?)

I think we should store an access token somewhere in the chatgpt object as a variable, and update it once it expires (the token has an expiration date, reference here) to avoid getting rate limited by the api and reducing the speed of the library

problem is idk about the security of doing this

edit: it shouldn't even matter since there's literally a function that retrieves the access token, so storing it in the object is not even a big deal, and removing the object from the window will literally make it disappear

connect with 3rd party OpenAI compatible API

vLLM supports an OpenAI-Compatible API. is it possible to configure this code to connect to another service other than OpenAI?
I've tried modifying the code but i am getting errors.
image

Add access token management

          also (this is just an idea of mine), I think we should store an access token somewhere in the chatgpt object as a variable, and update it once it expires (the token has an expiration date, reference [here](https://github.com/kudoai/chatgpt.js/blob/main/chatgpt.js#L379)) to avoid getting rate limited by the api and reducing the speed of the library

problem is idk about the security of doing this

edit: it shouldn't even matter since there's literally a function that retrieves the access token, so storing it in the object is not even a big deal, and removing the object from the window will literally make it disappear

Originally posted by @madkarmaa in #79 (comment)

[Feature Request] Support InternLM

Dear chatgpt.js developer,

Greetings! I am vansinhu, a community developer and volunteer at InternLM. Your work has been immensely beneficial to me, and I believe it can be effectively utilized in InternLM as well. Welcome to add Discord https://discord.gg/gF9ezcmtM3 . I hope to get in touch with you.

Best regards,
vansinhu

'message' in data[key]

'message' in data[key] 会导致后面的data[key].message.author.role报错
'message' in data[key] 替换成 data[key].message != null 后正常运行

Missing locale

Hi,
the extension currently fails to run with a 404 error from chatgpt.js line 30
Failed to load resource: the server responded with a status of 404 () https://raw.githubusercontent.com/KudoAI/chatgpt.js/main/data/_locales/en_GB/messages.json does not exist

By the way - thank your work - I do not understand why OpenAI insists on a narrow chat window...

[feature request] delete chat

I couldn't find a delete chat func, would be great if added.

Here is playwright code to delete current chat:

        page.get_by_label("Chat history").get_by_role("button").nth(1).click()
        page.get_by_text("Delete chat").click()
        page.get_by_role("button", name="Delete").click()

chatgpt.alert()

The parameter btns in chatgpt.alert() doesn't take count of functions that have multiple words (eg. function hello_world()) and renders them in the buttons, taken the previous example, as "Hello_world". I think it could be a nice addition.

use a bundle tool or not

We may use a bundle tool like esbuild, then can split this single file into different files and then bundle them into a single file.

The main benefit is that conflict will be much less since working on a different file.

Another benefit is that it can auto-do compatibility work.

funding

Hey yall,
Curious to get in touch with whoever is managing this project
https://juicebox.money/v2/p/588 (0xad029Eb29Dc085ed2BC83c59eaC72B5BF0493EDE)

Excited to help make it successful, but first want to confirm who owns it.

[Feature Request] More width option, TOC support

Dear devloper:

Thanks for the great app. I have to feature request below:

More width option

Here are three width now:

  1. default;
  2. wide screen;
  3. full screen ( close sidebar )

It will be great that you can add the fourth option: between "default" and "wide screen", that will be good for some conversation.

TOC support

In some conversations, I have asked too many questions, it will be very easy to navigate to any question if there be an TOC on the right side.

Thank you.

send() isn't working anymore

I tried using both chatgpt.send() and creating my own logic, but none of them worked. it was working before, but the ChatGPT website got a UI update in which somehow it won't send the message automatically anymore (you have to manually modify the text first)

my own logic:

const sendButton = document.querySelector('form button[class*="bottom"]');
const chatInput = document.querySelector("form textarea");

if (chatInput) chatInput.value = "some text";
if (sendButton) {
  sendButton.removeAttribute("disabled");
  sendButton.click();
}

ChatGPT Teams broke the script

Looks like the script is not working with the new ChatGPT Teams subscriptions. Getting Uncaught (in promise) 🤖 chatgpt.js >> No chat with id = xxxxx-xxxx-xxx found.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.