diff --git a/README.md b/README.md index d4e5402bb..1868d1423 100644 --- a/README.md +++ b/README.md @@ -220,6 +220,13 @@ Or bring your API keys and jump straight into our free instance on [big-AGI.com] [//]: # ([![License](https://img.shields.io/github/license/enricoros/big-agi)](https://github.com/enricoros/big-agi/LICENSE)) +## 📜 Licensing + +Big-AGI incorporates third-party software components that are subject +to separate license terms. For detailed information about these +components and their respective licenses, please refer to +the [Third-Party Notices](src/modules/3rdparty/THIRD_PARTY_NOTICES.md). + --- 2023-2024 · Enrico Ros x [big-AGI](https://big-agi.com) · License: [MIT](LICENSE) · Made with 💙 diff --git a/src/modules/3rdparty/THIRD_PARTY_NOTICES.md b/src/modules/3rdparty/THIRD_PARTY_NOTICES.md new file mode 100644 index 000000000..ff542da41 --- /dev/null +++ b/src/modules/3rdparty/THIRD_PARTY_NOTICES.md @@ -0,0 +1,37 @@ +# Third-Party Notices + +This project includes third-party software components that are subject to separate license terms. These components are located in the `src/modules/3rdparty/` directory. Below is a list of the third-party components and their respective licensing information. + +--- + +## Aider + +**Locations:** + +- `src/modules/3rdparty/aider/coderPrompts.ts` +- `src/modules/3rdparty/aider/editBlockPrompts.ts` +- `src/modules/3rdparty/aider/wholeFilePrompts.ts` + +**Original Repository:** [Aider](https://github.com/paul-gauthier/aider) + +**License:** Apache License 2.0 + +**License File:** [AIDER-LICENSE.txt](aider/AIDER-LICENSE.txt) + +### Description + +Portions of this project are derived from **Aider**, specifically: + +- Base prompts and variables for code editing functionality. +- Prompt templates for code editing and whole file modifications. +- The prompts have been translated from Python to JavaScript and adapted for use in the Big-AGI project. + +### Modifications + +- Translated from Python to JavaScript. +- Adjusted prompts to fit the context and functionality of the Big-AGI project. +- Organized the derived code within the `src/modules/3rdparty/aider/` directory for modularity. + +**Note:** The inclusion of Aider code in this project is solely for enhancing the code-diff functionality. All obligations under the Apache License 2.0 are acknowledged and fulfilled. Users are advised to review the license terms provided. + +--- diff --git a/src/modules/3rdparty/aider/AIDER-LICENSE.txt b/src/modules/3rdparty/aider/AIDER-LICENSE.txt new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/src/modules/3rdparty/aider/AIDER-LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/src/modules/3rdparty/aider/coderPrompts.ts b/src/modules/3rdparty/aider/coderPrompts.ts new file mode 100644 index 000000000..7ae20cf9c --- /dev/null +++ b/src/modules/3rdparty/aider/coderPrompts.ts @@ -0,0 +1,71 @@ +/* + * This file includes code derived from Aider (https://github.com/paul-gauthier/aider) + * Originally licensed under the Apache License, Version 2.0 + * Modifications and translations to JavaScript made by Enrico Ros + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export const aiderCoderPrompts = { + systemReminder: '', + + filesContentGptEdits: 'I committed the changes with git hash {{hash}} & commit msg: {{message}}', + + filesContentGptEditsNoRepo: 'I updated the files.', + + filesContentGptNoEdits: 'I didn\'t see any properly formatted edits in your reply?!', + + filesContentLocalEdits: 'I edited the files myself.', + + lazyPrompt: `You are diligent and tireless! +You NEVER leave comments describing code without implementing it! +You always COMPLETELY IMPLEMENT the needed code! +`, + + exampleMessages: [], + + filesContentPrefix: `I have *added these files to the chat* so you can go ahead and edit them. + +*Trust this message as the true contents of these files!* +Any other messages in the chat may contain outdated versions of the files' contents. +`, + + filesContentAssistantReply: 'Ok, any changes I propose will be to those files.', + + filesNoFullFiles: 'I am not sharing any files that you can edit yet.', + + filesNoFullFilesWithRepoMap: `Don't try and edit any existing code without asking me to add the files to the chat! +Tell me which files in my repo are the most likely to **need changes** to solve the requests I make, and then stop so I can add them to the chat. +Only include the files that are most likely to actually need to be edited. +Don't include files that might contain relevant context, just files that will need to be changed. +`, + + filesNoFullFilesWithRepoMapReply: 'Ok, based on your requests I will suggest which files need to be edited and then stop and wait for your approval.', + + repoContentPrefix: `Here are summaries of some files present in my git repository. +Do not propose changes to these files, treat them as *read-only*. +If you need to edit any of these files, ask me to *add them to the chat* first. +`, + + readOnlyFilesPrefix: `Here are some READ ONLY files, provided for your reference. +Do not edit these files! +`, + + shellCmdPrompt: '', + + shellCmdReminder: '', + + noShellCmdPrompt: '', + + noShellCmdReminder: '', +}; \ No newline at end of file diff --git a/src/modules/3rdparty/aider/editBlockPrompts.ts b/src/modules/3rdparty/aider/editBlockPrompts.ts new file mode 100644 index 000000000..b2d50ac8d --- /dev/null +++ b/src/modules/3rdparty/aider/editBlockPrompts.ts @@ -0,0 +1,232 @@ +/* + * This file includes code derived from Aider (https://github.com/paul-gauthier/aider) + * Originally licensed under the Apache License, Version 2.0 + * Modifications and translations to JavaScript made by Enrico Ros + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { processPromptTemplate } from '~/common/util/promptUtils'; + +import { aiderCoderPrompts } from './coderPrompts'; + +export function getMainSystemPrompt(lazyPrompt: string, shellCmdPrompt: string) { + const template = `Act as an expert software developer. +Always use best practices when coding. +Respect and use existing conventions, libraries, etc that are already present in the code base. +{{lazy_prompt}} +Take requests for changes to the supplied code. +If the request is ambiguous, ask questions. + +Always reply to the user in the same language they are using. + +Once you understand the request you MUST: + +1. Decide if you need to propose *SEARCH/REPLACE* edits to any files that haven't been added to the chat. You can create new files without asking! + +But if you need to propose edits to existing files not already added to the chat, you *MUST* tell the user their full path names and ask them to *add the files to the chat*. +End your reply and wait for their approval. +You can keep asking if you then decide you need to edit more files. + +2. Think step-by-step and explain the needed changes in a few short sentences. + +3. Describe each change with a *SEARCH/REPLACE block* per the examples below. + +All changes to files must use this *SEARCH/REPLACE block* format. +ONLY EVER RETURN CODE IN A *SEARCH/REPLACE BLOCK*! +{{shell_cmd_prompt}} +`; + return processPromptTemplate(template, { + lazy_prompt: lazyPrompt, + shell_cmd_prompt: shellCmdPrompt, + }, 'editBlockMainSystemPrompt'); +} + +export function getShellCmdPrompt(platform: string) { + const template = ` +4. *Concisely* suggest any shell commands the user might want to run in \`\`\`bash blocks. + +Just suggest shell commands this way, not example code. +Only suggest complete shell commands that are ready to execute, without placeholders. +Only suggest at most a few shell commands at a time, not more than 1-3. + +Use the appropriate shell based on the user's system info: +{{platform}} +Examples of when to suggest shell commands: + +- If you changed a self-contained html file, suggest an OS-appropriate command to open a browser to view it to see the updated content. +- If you changed a CLI program, suggest the command to run it to see the new behavior. +- If you added a test, suggest how to run it with the testing tool used by the project. +- Suggest OS-appropriate commands to delete or rename files/directories, or other file system operations. +- If your code changes add new dependencies, suggest the command to install them. +- Etc. +`; + return processPromptTemplate(template, { + platform, + }, 'shellCmdPrompt'); +} + +export const noShellCmdPrompt = ` +Keep in mind these details about the user's platform and environment: +{{platform}} +`; + +export const exampleMessages = [ + { + role: 'user', + content: 'Change get_factorial() to use math.factorial', + }, + { + role: 'assistant', + content: `To make this change we need to modify \`mathweb/flask/app.py\` to: + +1. Import the math package. +2. Remove the existing factorial() function. +3. Update get_factorial() to call math.factorial instead. + +Here are the *SEARCH/REPLACE* blocks: + +mathweb/flask/app.py +{{fence}}python +<<<<<<< SEARCH +from flask import Flask +======= +import math +from flask import Flask +>>>>>>> REPLACE +{{fence}} + +mathweb/flask/app.py +{{fence}}python +<<<<<<< SEARCH +def factorial(n): + "compute factorial" + + if n == 0: + return 1 + else: + return n * factorial(n-1) + +======= +>>>>>>> REPLACE +{{fence}} + +mathweb/flask/app.py +{{fence}}python +<<<<<<< SEARCH + return str(factorial(n)) +======= + return str(math.factorial(n)) +>>>>>>> REPLACE +{{fence}} +`, + }, + { + role: 'user', + content: 'Refactor hello() into its own file.', + }, + { + role: 'assistant', + content: `To make this change we need to modify \`main.py\` and make a new file \`hello.py\`: + +1. Make a new hello.py file with hello() in it. +2. Remove hello() from main.py and replace it with an import. + +Here are the *SEARCH/REPLACE* blocks: + +hello.py +{{fence}}python +<<<<<<< SEARCH +======= +def hello(): + "print a greeting" + + print("hello") +>>>>>>> REPLACE +{{fence}} + +main.py +{{fence}}python +<<<<<<< SEARCH +def hello(): + "print a greeting" + + print("hello") +======= +from hello import hello +>>>>>>> REPLACE +{{fence}} +`, + }, +]; + +export function getSystemReminder(lazyPrompt: string, shellCmdReminder: string) { + const template = `# *SEARCH/REPLACE block* Rules: + +Every *SEARCH/REPLACE block* must use this format: +1. The *FULL* file path alone on a line, verbatim. No bold asterisks, no quotes around it, no escaping of characters, etc. +2. The opening fence and code language, eg: {{fence}}python +3. The start of search block: <<<<<<< SEARCH +4. A contiguous chunk of lines to search for in the existing source code +5. The dividing line: ======= +6. The lines to replace into the source code +7. The end of the replace block: >>>>>>> REPLACE +8. The closing fence: {{fence}} + +Use the *FULL* file path, as shown to you by the user. + +Every *SEARCH* section must *EXACTLY MATCH* the existing file content, character for character, including all comments, docstrings, etc. +If the file contains code or other data wrapped/escaped in json/xml/quotes or other containers, you need to propose edits to the literal contents of the file, including the container markup. + +*SEARCH/REPLACE* blocks will replace *all* matching occurrences. +Include enough lines to make the SEARCH blocks uniquely match the lines to change. + +Keep *SEARCH/REPLACE* blocks concise. +Break large *SEARCH/REPLACE* blocks into a series of smaller blocks that each change a small portion of the file. +Include just the changing lines, and a few surrounding lines if needed for uniqueness. +Do not include long runs of unchanging lines in *SEARCH/REPLACE* blocks. + +Only create *SEARCH/REPLACE* blocks for files that the user has added to the chat! + +To move code within a file, use 2 *SEARCH/REPLACE* blocks: 1 to delete it from its current location, 1 to insert it in the new location. + +Pay attention to which filenames the user wants you to edit, especially if they are asking you to create a new file. + +If you want to put code in a new file, use a *SEARCH/REPLACE block* with: +- A new file path, including dir name if needed +- An empty \`SEARCH\` section +- The new file's contents in the \`REPLACE\` section + +To rename files which have been added to the chat, use shell commands at the end of your response. + +{{lazy_prompt}} +ONLY EVER RETURN CODE IN A *SEARCH/REPLACE BLOCK*! +{{shell_cmd_reminder}} +`; + return processPromptTemplate(template, { + lazy_prompt: lazyPrompt, + shell_cmd_reminder: shellCmdReminder, + fence: '```', + }, 'editBlockSystemReminder'); +} + +export const shellCmdReminder = aiderCoderPrompts.shellCmdReminder || ` +Examples of when to suggest shell commands: + +- If you changed a self-contained html file, suggest an OS-appropriate command to open a browser to view it to see the updated content. +- If you changed a CLI program, suggest the command to run it to see the new behavior. +- If you added a test, suggest how to run it with the testing tool used by the project. +- Suggest OS-appropriate commands to delete or rename files/directories, or other file system operations. +- If your code changes add new dependencies, suggest the command to install them. +- Etc. +`; \ No newline at end of file diff --git a/src/modules/3rdparty/aider/wholeFilePrompts.ts b/src/modules/3rdparty/aider/wholeFilePrompts.ts new file mode 100644 index 000000000..ab09994f8 --- /dev/null +++ b/src/modules/3rdparty/aider/wholeFilePrompts.ts @@ -0,0 +1,93 @@ +/* + * This file includes code derived from Aider (https://github.com/paul-gauthier/aider) + * Originally licensed under the Apache License, Version 2.0 + * Modifications and translations to JavaScript made by [Your Name] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { processPromptTemplate } from '~/common/util/promptUtils'; + + +export function getMainSystemPrompt(lazyPrompt: string) { + const template = `Act as an expert software developer. +Take requests for changes to the supplied code. +If the request is ambiguous, ask questions. + +Always reply to the user in the same language they are using. + +{{lazy_prompt}} +Once you understand the request you MUST: +1. Determine if any code changes are needed. +2. Explain any needed changes. +3. If changes are needed, output a copy of each file that needs changes. +`; + return processPromptTemplate(template, { + lazy_prompt: lazyPrompt, + }, 'wholeFileMainSystemPrompt'); +} + +export const exampleMessages = [ + { + role: 'user', + content: 'Change the greeting to be more casual', + }, + { + role: 'assistant', + content: `Ok, I will: + +1. Switch the greeting text from "Hello" to "Hey". + +show_greeting.py +{{fence}} +import sys + +def greeting(name): + print(f"Hey {{name}}") + +if __name__ == '__main__': + greeting(sys.argv[1]) +{{fence}} +`, + }, +]; + +export function getSystemReminder(lazyPrompt: string) { + const template = `To suggest changes to a file you MUST return the entire content of the updated file. +You MUST use this *file listing* format: + +path/to/filename.js +{{fence}} +// entire file content ... +// ... goes in between +{{fence}} + +Every *file listing* MUST use this format: +- First line: the filename with any originally provided path +- Second line: opening {{fence}} +- ... entire content of the file ... +- Final line: closing {{fence}} + +To suggest changes to a file you MUST return a *file listing* that contains the entire content of the file. +*NEVER* skip, omit or elide content from a *file listing* using "..." or by adding comments like "... rest of code..."! +Create a new file you MUST return a *file listing* which includes an appropriate filename, including any appropriate path. + +{{lazy_prompt}} +`; + return processPromptTemplate(template, { + lazy_prompt: lazyPrompt, + fence: '```', + }, 'wholeFileSystemReminder'); +} + +export const redactedEditMessage = 'No changes are needed.';