Merge branch 'main' into chat-messages
This commit is contained in:
commit
0630da3b09
10
.chat/instructions/commit_message/instCommitMessage.txt
Normal file
10
.chat/instructions/commit_message/instCommitMessage.txt
Normal file
@ -0,0 +1,10 @@
|
||||
As a software developer assistant, your task is to provide clear and concise responses and write commit messages based on given code, requirements, or conversations. Follow these guidelines:
|
||||
|
||||
1. A commit message should include a title and multiple body lines.
|
||||
2. Adhere to best practices, such as keeping titles under 50 characters and limiting body lines to under 72 characters.
|
||||
3. Enclose messages in code blocks using triple backticks (```).
|
||||
4. Utilize the <context>, if provided, to create the summary.
|
||||
5. Utilize the previous messages, if provided in the end of this prompt, to create the summary. Note that not all previous messages are necessarily relevant.
|
||||
6. Please output commit message in a markdown code block, flag as commitmsg type.
|
||||
|
||||
If you need more information, feel free to ask.
|
22
.chat/instructions/default/instCode.txt
Normal file
22
.chat/instructions/default/instCode.txt
Normal file
@ -0,0 +1,22 @@
|
||||
As a software developer assistant, your tasks are to:
|
||||
|
||||
- Provide a clear and concise response to address the user's <request>.
|
||||
- Write code and give advice based on given code or information in the <context> if provided.
|
||||
- Follow language-specific best practices and coding standards.
|
||||
|
||||
When responding:
|
||||
|
||||
1. Summarize and describe the requirements or provided information in your own words.
|
||||
2. The summary and description should better be written in bullet points (excluding code).
|
||||
3. If modifying given code, output the changes and avoid unnecessary unchanged code.
|
||||
4. Enclose code or changes within blocks using triple backticks (```), and include the programming language and the file path, if available. For example:
|
||||
```
|
||||
```python path=./path/to/file.py
|
||||
print("Hello, World!")
|
||||
```
|
||||
```
|
||||
If no file paths or folder structure are provided and you are unsure about the file path of the code, you may omit the file path.
|
||||
5. Use separate code blocks for different files.
|
||||
6. Utilize the previous messages, if provided in the end of this prompt, to create your response. Note that not all previous messages are necessarily relevant.
|
||||
7. When providing a suggestion or instruction, begin by explaining the reason behind it.
|
||||
8. If you need more information, ask for it.
|
1
.chat/instructions/default/instLangPython.txt
Normal file
1
.chat/instructions/default/instLangPython.txt
Normal file
@ -0,0 +1 @@
|
||||
When writing Python code, include type hints where appropriate and maintain compliance with PEP-8 guidelines, such as providing docstrings for modules, classes, and functions.
|
469
package-lock.json
generated
469
package-lock.json
generated
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "devchat",
|
||||
"version": "0.0.1",
|
||||
"version": "0.0.3",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "devchat",
|
||||
"version": "0.0.1",
|
||||
"version": "0.0.3",
|
||||
"dependencies": {
|
||||
"@emotion/react": "^11.10.8",
|
||||
"@mantine/core": "^6.0.10",
|
||||
@ -36,7 +36,6 @@
|
||||
"@babel/preset-typescript": "^7.21.5",
|
||||
"@types/glob": "^8.1.0",
|
||||
"@types/jest": "^29.5.1",
|
||||
"@types/mocha": "^10.0.1",
|
||||
"@types/ncp": "^2.0.5",
|
||||
"@types/node": "16.x",
|
||||
"@types/react-dom": "^18.2.3",
|
||||
@ -55,7 +54,6 @@
|
||||
"html-webpack-plugin": "^5.5.1",
|
||||
"jest": "^29.5.0",
|
||||
"json-loader": "^0.5.7",
|
||||
"mocha": "^10.2.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-redux": "^8.0.5",
|
||||
@ -3770,12 +3768,6 @@
|
||||
"integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/mocha": {
|
||||
"version": "10.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.1.tgz",
|
||||
"integrity": "sha512-/fvYntiO1GeICvqbQ3doGDIP97vWmvFt83GKguJ6prmQM2iXZfFcq6YE8KteFyRtX2/h5Hf91BYvPodJKFYv5Q==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/ncp": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/ncp/-/ncp-2.0.5.tgz",
|
||||
@ -4491,15 +4483,6 @@
|
||||
"ajv": "^6.9.1"
|
||||
}
|
||||
},
|
||||
"node_modules/ansi-colors": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
|
||||
"integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/ansi-escapes": {
|
||||
"version": "4.3.2",
|
||||
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
|
||||
@ -5007,12 +4990,6 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/browser-stdout": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
|
||||
"integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/browserslist": {
|
||||
"version": "4.21.5",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz",
|
||||
@ -5289,17 +5266,6 @@
|
||||
"node": ">= 10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/cliui": {
|
||||
"version": "7.0.4",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
|
||||
"integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"string-width": "^4.2.0",
|
||||
"strip-ansi": "^6.0.0",
|
||||
"wrap-ansi": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/clone-deep": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz",
|
||||
@ -5779,18 +5745,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/decamelize": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz",
|
||||
"integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/dedent": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz",
|
||||
@ -5879,15 +5833,6 @@
|
||||
"resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz",
|
||||
"integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ=="
|
||||
},
|
||||
"node_modules/diff": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz",
|
||||
"integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/diff-sequences": {
|
||||
"version": "29.4.3",
|
||||
"resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz",
|
||||
@ -6742,15 +6687,6 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/flat": {
|
||||
"version": "5.0.2",
|
||||
"resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
|
||||
"integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"flat": "cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/flat-cache": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
|
||||
@ -7649,18 +7585,6 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/is-unicode-supported": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
|
||||
"integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/is-wsl": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
|
||||
@ -8688,22 +8612,6 @@
|
||||
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/log-symbols": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
|
||||
"integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"chalk": "^4.1.0",
|
||||
"is-unicode-supported": "^0.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/loose-envify": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
||||
@ -9064,120 +8972,6 @@
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/mocha": {
|
||||
"version": "10.2.0",
|
||||
"resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz",
|
||||
"integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"ansi-colors": "4.1.1",
|
||||
"browser-stdout": "1.3.1",
|
||||
"chokidar": "3.5.3",
|
||||
"debug": "4.3.4",
|
||||
"diff": "5.0.0",
|
||||
"escape-string-regexp": "4.0.0",
|
||||
"find-up": "5.0.0",
|
||||
"glob": "7.2.0",
|
||||
"he": "1.2.0",
|
||||
"js-yaml": "4.1.0",
|
||||
"log-symbols": "4.1.0",
|
||||
"minimatch": "5.0.1",
|
||||
"ms": "2.1.3",
|
||||
"nanoid": "3.3.3",
|
||||
"serialize-javascript": "6.0.0",
|
||||
"strip-json-comments": "3.1.1",
|
||||
"supports-color": "8.1.1",
|
||||
"workerpool": "6.2.1",
|
||||
"yargs": "16.2.0",
|
||||
"yargs-parser": "20.2.4",
|
||||
"yargs-unparser": "2.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"_mocha": "bin/_mocha",
|
||||
"mocha": "bin/mocha.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/mochajs"
|
||||
}
|
||||
},
|
||||
"node_modules/mocha/node_modules/glob": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
|
||||
"integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^3.0.4",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/mocha/node_modules/glob/node_modules/minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/mocha/node_modules/minimatch": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz",
|
||||
"integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"brace-expansion": "^2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/mocha/node_modules/minimatch/node_modules/brace-expansion": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
||||
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/mocha/node_modules/ms": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/mocha/node_modules/supports-color": {
|
||||
"version": "8.1.1",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
|
||||
"integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"has-flag": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/supports-color?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
@ -9196,18 +8990,6 @@
|
||||
"multicast-dns": "cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/nanoid": {
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz",
|
||||
"integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"nanoid": "bin/nanoid.cjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/natural-compare": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
|
||||
@ -12597,12 +12379,6 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/workerpool": {
|
||||
"version": "6.2.1",
|
||||
"resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz",
|
||||
"integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/wrap-ansi": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
|
||||
@ -12691,48 +12467,6 @@
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/yargs": {
|
||||
"version": "16.2.0",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
|
||||
"integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"cliui": "^7.0.2",
|
||||
"escalade": "^3.1.1",
|
||||
"get-caller-file": "^2.0.5",
|
||||
"require-directory": "^2.1.1",
|
||||
"string-width": "^4.2.0",
|
||||
"y18n": "^5.0.5",
|
||||
"yargs-parser": "^20.2.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/yargs-parser": {
|
||||
"version": "20.2.4",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz",
|
||||
"integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/yargs-unparser": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz",
|
||||
"integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"camelcase": "^6.0.0",
|
||||
"decamelize": "^4.0.0",
|
||||
"flat": "^5.0.2",
|
||||
"is-plain-obj": "^2.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/yocto-queue": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
|
||||
@ -15449,12 +15183,6 @@
|
||||
"integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/mocha": {
|
||||
"version": "10.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.1.tgz",
|
||||
"integrity": "sha512-/fvYntiO1GeICvqbQ3doGDIP97vWmvFt83GKguJ6prmQM2iXZfFcq6YE8KteFyRtX2/h5Hf91BYvPodJKFYv5Q==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/ncp": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/ncp/-/ncp-2.0.5.tgz",
|
||||
@ -16023,12 +15751,6 @@
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"ansi-colors": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
|
||||
"integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
|
||||
"dev": true
|
||||
},
|
||||
"ansi-escapes": {
|
||||
"version": "4.3.2",
|
||||
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
|
||||
@ -16425,12 +16147,6 @@
|
||||
"fill-range": "^7.0.1"
|
||||
}
|
||||
},
|
||||
"browser-stdout": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
|
||||
"integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==",
|
||||
"dev": true
|
||||
},
|
||||
"browserslist": {
|
||||
"version": "4.21.5",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz",
|
||||
@ -16607,17 +16323,6 @@
|
||||
"source-map": "~0.6.0"
|
||||
}
|
||||
},
|
||||
"cliui": {
|
||||
"version": "7.0.4",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
|
||||
"integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"string-width": "^4.2.0",
|
||||
"strip-ansi": "^6.0.0",
|
||||
"wrap-ansi": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"clone-deep": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz",
|
||||
@ -16969,12 +16674,6 @@
|
||||
"ms": "2.1.2"
|
||||
}
|
||||
},
|
||||
"decamelize": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz",
|
||||
"integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==",
|
||||
"dev": true
|
||||
},
|
||||
"dedent": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz",
|
||||
@ -17041,12 +16740,6 @@
|
||||
"resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz",
|
||||
"integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ=="
|
||||
},
|
||||
"diff": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz",
|
||||
"integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==",
|
||||
"dev": true
|
||||
},
|
||||
"diff-sequences": {
|
||||
"version": "29.4.3",
|
||||
"resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz",
|
||||
@ -17699,12 +17392,6 @@
|
||||
"path-exists": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"flat": {
|
||||
"version": "5.0.2",
|
||||
"resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
|
||||
"integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==",
|
||||
"dev": true
|
||||
},
|
||||
"flat-cache": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
|
||||
@ -18337,12 +18024,6 @@
|
||||
"integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
|
||||
"dev": true
|
||||
},
|
||||
"is-unicode-supported": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
|
||||
"integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
|
||||
"dev": true
|
||||
},
|
||||
"is-wsl": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
|
||||
@ -19151,16 +18832,6 @@
|
||||
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
|
||||
"dev": true
|
||||
},
|
||||
"log-symbols": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
|
||||
"integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "^4.1.0",
|
||||
"is-unicode-supported": "^0.1.0"
|
||||
}
|
||||
},
|
||||
"loose-envify": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
||||
@ -19432,97 +19103,6 @@
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
},
|
||||
"mocha": {
|
||||
"version": "10.2.0",
|
||||
"resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz",
|
||||
"integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-colors": "4.1.1",
|
||||
"browser-stdout": "1.3.1",
|
||||
"chokidar": "3.5.3",
|
||||
"debug": "4.3.4",
|
||||
"diff": "5.0.0",
|
||||
"escape-string-regexp": "4.0.0",
|
||||
"find-up": "5.0.0",
|
||||
"glob": "7.2.0",
|
||||
"he": "1.2.0",
|
||||
"js-yaml": "4.1.0",
|
||||
"log-symbols": "4.1.0",
|
||||
"minimatch": "5.0.1",
|
||||
"ms": "2.1.3",
|
||||
"nanoid": "3.3.3",
|
||||
"serialize-javascript": "6.0.0",
|
||||
"strip-json-comments": "3.1.1",
|
||||
"supports-color": "8.1.1",
|
||||
"workerpool": "6.2.1",
|
||||
"yargs": "16.2.0",
|
||||
"yargs-parser": "20.2.4",
|
||||
"yargs-unparser": "2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"glob": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
|
||||
"integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^3.0.4",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz",
|
||||
"integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"brace-expansion": "^2.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"brace-expansion": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
||||
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||
"dev": true
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "8.1.1",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
|
||||
"integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"has-flag": "^4.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
@ -19538,12 +19118,6 @@
|
||||
"thunky": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"nanoid": {
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz",
|
||||
"integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==",
|
||||
"dev": true
|
||||
},
|
||||
"natural-compare": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
|
||||
@ -22033,12 +21607,6 @@
|
||||
"integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
|
||||
"dev": true
|
||||
},
|
||||
"workerpool": {
|
||||
"version": "6.2.1",
|
||||
"resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz",
|
||||
"integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==",
|
||||
"dev": true
|
||||
},
|
||||
"wrap-ansi": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
|
||||
@ -22095,39 +21663,6 @@
|
||||
"resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
|
||||
"integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg=="
|
||||
},
|
||||
"yargs": {
|
||||
"version": "16.2.0",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
|
||||
"integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"cliui": "^7.0.2",
|
||||
"escalade": "^3.1.1",
|
||||
"get-caller-file": "^2.0.5",
|
||||
"require-directory": "^2.1.1",
|
||||
"string-width": "^4.2.0",
|
||||
"y18n": "^5.0.5",
|
||||
"yargs-parser": "^20.2.2"
|
||||
}
|
||||
},
|
||||
"yargs-parser": {
|
||||
"version": "20.2.4",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz",
|
||||
"integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==",
|
||||
"dev": true
|
||||
},
|
||||
"yargs-unparser": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz",
|
||||
"integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"camelcase": "^6.0.0",
|
||||
"decamelize": "^4.0.0",
|
||||
"flat": "^5.0.2",
|
||||
"is-plain-obj": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"yocto-queue": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
|
||||
|
@ -2,7 +2,7 @@
|
||||
"name": "devchat",
|
||||
"displayName": "devchat",
|
||||
"description": "devchat",
|
||||
"version": "0.0.1",
|
||||
"version": "0.0.3",
|
||||
"engines": {
|
||||
"vscode": "^1.77.0"
|
||||
},
|
||||
@ -24,7 +24,9 @@
|
||||
"DevChat.llmModel": {
|
||||
"type": "string",
|
||||
"default": "OpenAI",
|
||||
"enum": ["OpenAI"],
|
||||
"enum": [
|
||||
"OpenAI"
|
||||
],
|
||||
"description": "Select whose llm to use."
|
||||
},
|
||||
"DevChat.OpenAI.model": {
|
||||
@ -123,7 +125,6 @@
|
||||
"@babel/preset-typescript": "^7.21.5",
|
||||
"@types/glob": "^8.1.0",
|
||||
"@types/jest": "^29.5.1",
|
||||
"@types/mocha": "^10.0.1",
|
||||
"@types/ncp": "^2.0.5",
|
||||
"@types/node": "16.x",
|
||||
"@types/react-dom": "^18.2.3",
|
||||
@ -142,7 +143,6 @@
|
||||
"html-webpack-plugin": "^5.5.1",
|
||||
"jest": "^29.5.0",
|
||||
"json-loader": "^0.5.7",
|
||||
"mocha": "^10.2.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-redux": "^8.0.5",
|
||||
|
107
src/chatPanel.ts
107
src/chatPanel.ts
@ -1,107 +0,0 @@
|
||||
// chatPanel.ts
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs';
|
||||
import DevChat from './devchat';
|
||||
import handleMessage from './messageHandler';
|
||||
|
||||
export default class ChatPanel {
|
||||
private static _instance: ChatPanel | undefined;
|
||||
private readonly _panel: vscode.WebviewPanel;
|
||||
private _disposables: vscode.Disposable[] = [];
|
||||
|
||||
// Create or reveal the chat panel
|
||||
public static createOrShow(extensionUri: vscode.Uri) {
|
||||
if (ChatPanel._instance) {
|
||||
ChatPanel._instance._panel.reveal();
|
||||
} else {
|
||||
const panel = ChatPanel.createWebviewPanel(extensionUri);
|
||||
ChatPanel._instance = new ChatPanel(panel, extensionUri);
|
||||
}
|
||||
}
|
||||
|
||||
public static currentPanel(): ChatPanel | undefined {
|
||||
return ChatPanel._instance;
|
||||
}
|
||||
|
||||
// Create a new webview panel
|
||||
private static createWebviewPanel(extensionUri: vscode.Uri): vscode.WebviewPanel {
|
||||
const column = vscode.window.activeTextEditor
|
||||
? vscode.window.activeTextEditor.viewColumn
|
||||
: undefined;
|
||||
|
||||
return vscode.window.createWebviewPanel(
|
||||
'chatPanel',
|
||||
'Chat',
|
||||
column || vscode.ViewColumn.One,
|
||||
{
|
||||
enableScripts: true,
|
||||
localResourceRoots: [vscode.Uri.joinPath(extensionUri, 'dist')],
|
||||
retainContextWhenHidden: true
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private constructor(panel: vscode.WebviewPanel, extensionUri: vscode.Uri) {
|
||||
this._panel = panel;
|
||||
|
||||
this.setWebviewOptions(extensionUri);
|
||||
this.setWebviewContent(extensionUri);
|
||||
this.registerEventListeners();
|
||||
}
|
||||
|
||||
// Set webview options
|
||||
private setWebviewOptions(extensionUri: vscode.Uri) {
|
||||
this._panel.webview.options = {
|
||||
enableScripts: true,
|
||||
localResourceRoots: [vscode.Uri.joinPath(extensionUri, 'dist')],
|
||||
};
|
||||
}
|
||||
|
||||
// Set webview content
|
||||
private setWebviewContent(extensionUri: vscode.Uri) {
|
||||
this._panel.webview.html = this._getHtmlContent(extensionUri);
|
||||
}
|
||||
|
||||
public panel(): vscode.WebviewPanel {
|
||||
return this._panel;
|
||||
}
|
||||
|
||||
// Register event listeners for the panel and webview
|
||||
private registerEventListeners() {
|
||||
this._panel.onDidDispose(() => this.dispose(), null, this._disposables);
|
||||
|
||||
this._panel.webview.onDidReceiveMessage(
|
||||
async (message) => {
|
||||
handleMessage(message, this._panel);
|
||||
},
|
||||
null,
|
||||
this._disposables
|
||||
);
|
||||
}
|
||||
|
||||
// Get the HTML content for the panel
|
||||
private _getHtmlContent(extensionUri: vscode.Uri): string {
|
||||
const htmlPath = vscode.Uri.joinPath(extensionUri, 'dist', 'assets', 'chatPanel.html');
|
||||
// const htmlPath = vscode.Uri.joinPath(extensionUri, 'dist', 'index.html');
|
||||
const htmlContent = fs.readFileSync(htmlPath.fsPath, 'utf8');
|
||||
|
||||
return htmlContent.replace(/<vscode-resource:(\/.+?)>/g, (_, resourcePath) => {
|
||||
const resourceUri = vscode.Uri.joinPath(extensionUri, 'dist', resourcePath);
|
||||
return this._panel.webview.asWebviewUri(resourceUri).toString();
|
||||
});
|
||||
}
|
||||
|
||||
// Dispose the panel and clean up resources
|
||||
public dispose() {
|
||||
ChatPanel._instance = undefined;
|
||||
this._panel.dispose();
|
||||
while (this._disposables.length) {
|
||||
const disposable = this._disposables.pop();
|
||||
if (disposable) {
|
||||
disposable.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -7,8 +7,8 @@ import * as fs from 'fs';
|
||||
import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
import { promisify } from 'util';
|
||||
import { createTempSubdirectory } from './commonUtil';
|
||||
import ExtensionContextHolder from './extensionContext';
|
||||
import { createTempSubdirectory } from '../util/commonUtil';
|
||||
import ExtensionContextHolder from '../util/extensionContext';
|
||||
|
||||
const mkdirAsync = promisify(fs.mkdir);
|
||||
const execAsync = promisify(exec);
|
@ -1,7 +1,7 @@
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import * as path from 'path';
|
||||
import { createTempSubdirectory, getLanguageIdByFileName } from './commonUtil';
|
||||
import { createTempSubdirectory, getLanguageIdByFileName } from '../util/commonUtil';
|
||||
|
||||
export async function handleCodeSelected(fileSelected: string, codeSelected: string) {
|
||||
// get file name from fileSelected
|
@ -1,7 +1,7 @@
|
||||
import * as path from 'path';
|
||||
import * as vscode from 'vscode';
|
||||
import { ChatContext } from './contextManager';
|
||||
import { createTempSubdirectory, runCommandAndWriteOutput, runCommandStringAndWriteOutput } from './commonUtil';
|
||||
import { createTempSubdirectory, runCommandAndWriteOutput, runCommandStringAndWriteOutput } from '../util/commonUtil';
|
||||
|
||||
export const customCommandContext: ChatContext = {
|
||||
name: '<custom command>',
|
@ -1,7 +1,7 @@
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import * as path from 'path';
|
||||
import { createTempSubdirectory, getLanguageIdByFileName } from './commonUtil';
|
||||
import { createTempSubdirectory, getLanguageIdByFileName } from '../util/commonUtil';
|
||||
|
||||
export async function handleFileSelected(fileSelected: string) {
|
||||
// get file name from fileSelected
|
@ -1,6 +1,6 @@
|
||||
import * as path from 'path';
|
||||
import { ChatContext } from './contextManager';
|
||||
import { createTempSubdirectory, runCommandAndWriteOutput } from './commonUtil';
|
||||
import { createTempSubdirectory, runCommandAndWriteOutput } from '../util/commonUtil';
|
||||
|
||||
export const gitDiffContext: ChatContext = {
|
||||
name: 'git diff',
|
@ -1,6 +1,6 @@
|
||||
import * as path from 'path';
|
||||
import { ChatContext } from './contextManager';
|
||||
import { createTempSubdirectory, runCommandAndWriteOutput } from './commonUtil';
|
||||
import { createTempSubdirectory, runCommandAndWriteOutput } from '../util/commonUtil';
|
||||
|
||||
export const gitDiffCachedContext: ChatContext = {
|
||||
name: 'git diff cached',
|
73
src/contributes/commands.ts
Normal file
73
src/contributes/commands.ts
Normal file
@ -0,0 +1,73 @@
|
||||
import * as vscode from 'vscode';
|
||||
import ChatPanel from '../panel/chatPanel';
|
||||
import { sendFileSelectMessage, sendCodeSelectMessage } from './util';
|
||||
|
||||
function registerOpenChatPanelCommand(context: vscode.ExtensionContext) {
|
||||
let disposable = vscode.commands.registerCommand('devchat.openChatPanel', () => {
|
||||
if (vscode.workspace.workspaceFolders) {
|
||||
ChatPanel.createOrShow(context.extensionUri);
|
||||
} else {
|
||||
vscode.window.showErrorMessage('Please open a directory before using the chat panel.');
|
||||
}
|
||||
});
|
||||
context.subscriptions.push(disposable);
|
||||
}
|
||||
|
||||
function ensureChatPanel(context: vscode.ExtensionContext): boolean {
|
||||
if (!ChatPanel.currentPanel()) {
|
||||
if (vscode.workspace.workspaceFolders) {
|
||||
ChatPanel.createOrShow(context.extensionUri);
|
||||
} else {
|
||||
vscode.window.showErrorMessage('Please open a directory before using the chat panel.');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function registerAddContextCommand(context: vscode.ExtensionContext) {
|
||||
const disposable_add_context = vscode.commands.registerCommand('devchat.addConext', async (uri: { path: any; }) => {
|
||||
if (!ensureChatPanel(context)) {
|
||||
return;
|
||||
}
|
||||
|
||||
await sendFileSelectMessage(ChatPanel.currentPanel()!.panel(), uri.path);
|
||||
});
|
||||
context.subscriptions.push(disposable_add_context);
|
||||
}
|
||||
|
||||
function registerAskForCodeCommand(context: vscode.ExtensionContext) {
|
||||
const disposableCodeContext = vscode.commands.registerCommand('devchat.askForCode', async () => {
|
||||
const editor = vscode.window.activeTextEditor;
|
||||
if (editor) {
|
||||
if (!ensureChatPanel(context)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const selectedText = editor.document.getText(editor.selection);
|
||||
await sendCodeSelectMessage(ChatPanel.currentPanel()!.panel(), editor.document.fileName, selectedText);
|
||||
}
|
||||
});
|
||||
context.subscriptions.push(disposableCodeContext);
|
||||
}
|
||||
|
||||
function registerAskForFileCommand(context: vscode.ExtensionContext) {
|
||||
const disposableAskFile = vscode.commands.registerCommand('devchat.askForFile', async () => {
|
||||
const editor = vscode.window.activeTextEditor;
|
||||
if (editor) {
|
||||
if (!ensureChatPanel(context)) {
|
||||
return;
|
||||
}
|
||||
|
||||
await sendFileSelectMessage(ChatPanel.currentPanel()!.panel(), editor.document.fileName);
|
||||
}
|
||||
});
|
||||
context.subscriptions.push(disposableAskFile);
|
||||
}
|
||||
|
||||
export {
|
||||
registerOpenChatPanelCommand,
|
||||
registerAddContextCommand,
|
||||
registerAskForCodeCommand,
|
||||
registerAskForFileCommand,
|
||||
};
|
14
src/contributes/util.ts
Normal file
14
src/contributes/util.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
import { handleCodeSelected } from '../context/contextCodeSelected';
|
||||
import { handleFileSelected } from '../context/contextFileSelected';
|
||||
|
||||
export async function sendFileSelectMessage(panel: vscode.WebviewPanel, filePath: string): Promise<void> {
|
||||
const codeContext = await handleFileSelected(filePath);
|
||||
panel.webview.postMessage({ command: 'appendContext', context: codeContext });
|
||||
}
|
||||
|
||||
export async function sendCodeSelectMessage(panel: vscode.WebviewPanel, filePath: string, codeBlock: string): Promise<void> {
|
||||
const codeContext = await handleCodeSelected(filePath, codeBlock);
|
||||
panel.webview.postMessage({ command: 'appendContext', context: codeContext });
|
||||
}
|
106
src/extension.ts
106
src/extension.ts
@ -1,42 +1,15 @@
|
||||
import * as vscode from 'vscode';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as ncp from 'ncp'; // 需要安装 ncp 模块,用于复制目录
|
||||
|
||||
const ChatPanel = require('./chatPanel').default;
|
||||
const sendFileSelectMessage = require('./messageHandler').sendFileSelectMessage;
|
||||
const sendCodeSelectMessage = require('./messageHandler').sendCodeSelectMessage;
|
||||
import ExtensionContextHolder from './extensionContext';
|
||||
import { createChatDirectoryAndCopyInstructionsSync } from './init/chatConfig';
|
||||
import {
|
||||
registerOpenChatPanelCommand,
|
||||
registerAddContextCommand,
|
||||
registerAskForCodeCommand,
|
||||
registerAskForFileCommand,
|
||||
} from './contributes/commands';
|
||||
|
||||
function createChatDirectoryAndCopyInstructionsSync(extensionUri: vscode.Uri) {
|
||||
|
||||
const workspaceFolders = vscode.workspace.workspaceFolders;
|
||||
if (!workspaceFolders) {
|
||||
return;
|
||||
}
|
||||
import ExtensionContextHolder from './util/extensionContext';
|
||||
|
||||
const workspaceRoot = workspaceFolders[0].uri.fsPath;
|
||||
const chatDirPath = path.join(workspaceRoot, '.chat');
|
||||
const instructionsSrcPath = path.join(extensionUri.fsPath, 'instructions');
|
||||
|
||||
try {
|
||||
// 检查 .chat 目录是否存在,如果不存在,则创建它
|
||||
if (!fs.existsSync(chatDirPath)) {
|
||||
fs.mkdirSync(chatDirPath);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
// 将 instructions 目录复制到 .chat 目录中
|
||||
ncp.ncp(instructionsSrcPath, path.join(chatDirPath, 'instructions'), (err) => {
|
||||
if (err) {
|
||||
console.error('Error copying instructions:', err);
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error creating .chat directory and copying instructions:', error);
|
||||
}
|
||||
}
|
||||
|
||||
function activate(context: vscode.ExtensionContext) {
|
||||
ExtensionContextHolder.context = context;
|
||||
@ -44,64 +17,9 @@ function activate(context: vscode.ExtensionContext) {
|
||||
// 创建 .chat 目录并复制 instructions
|
||||
createChatDirectoryAndCopyInstructionsSync(context.extensionUri);
|
||||
|
||||
let disposable = vscode.commands.registerCommand('devchat.openChatPanel', () => {
|
||||
if (vscode.workspace.workspaceFolders) {
|
||||
ChatPanel.createOrShow(context.extensionUri);
|
||||
} else {
|
||||
vscode.window.showErrorMessage('Please open a directory before using the chat panel.');
|
||||
}
|
||||
});
|
||||
|
||||
const disposable_add_context = vscode.commands.registerCommand('devchat.addConext', async (uri: { path: any; }) => {
|
||||
if (!ChatPanel.currentPanel()) {
|
||||
if (vscode.workspace.workspaceFolders) {
|
||||
ChatPanel.createOrShow(context.extensionUri);
|
||||
} else {
|
||||
vscode.window.showErrorMessage('Please open a directory before using the chat panel.');
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
await sendFileSelectMessage(ChatPanel.currentPanel().panel(), uri.path);
|
||||
});
|
||||
|
||||
const disposableCodeContext = vscode.commands.registerCommand('devchat.askForCode', async () => {
|
||||
const editor = vscode.window.activeTextEditor;
|
||||
if (editor) {
|
||||
if (!ChatPanel.currentPanel()) {
|
||||
if (vscode.workspace.workspaceFolders) {
|
||||
ChatPanel.createOrShow(context.extensionUri);
|
||||
} else {
|
||||
vscode.window.showErrorMessage('Please open a directory before using the chat panel.');
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
const selectedText = editor.document.getText(editor.selection);
|
||||
await sendCodeSelectMessage(ChatPanel.currentPanel().panel(), editor.document.fileName, selectedText);
|
||||
}
|
||||
});
|
||||
|
||||
const disposableAskFile = vscode.commands.registerCommand('devchat.askForFile', async () => {
|
||||
const editor = vscode.window.activeTextEditor;
|
||||
if (editor) {
|
||||
if (!ChatPanel.currentPanel()) {
|
||||
if (vscode.workspace.workspaceFolders) {
|
||||
ChatPanel.createOrShow(context.extensionUri);
|
||||
} else {
|
||||
vscode.window.showErrorMessage('Please open a directory before using the chat panel.');
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
const selectedText = editor.document.getText();
|
||||
sendCodeSelectMessage(ChatPanel.currentPanel().panel(), selectedText);
|
||||
}
|
||||
});
|
||||
|
||||
context.subscriptions.push(disposable);
|
||||
context.subscriptions.push(disposable_add_context);
|
||||
context.subscriptions.push(disposableCodeContext)
|
||||
context.subscriptions.push(disposableAskFile)
|
||||
registerOpenChatPanelCommand(context);
|
||||
registerAddContextCommand(context);
|
||||
registerAskForCodeCommand(context);
|
||||
registerAskForFileCommand(context);
|
||||
}
|
||||
exports.activate = activate;
|
||||
|
12
src/handler/addContext.ts
Normal file
12
src/handler/addContext.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import * as vscode from 'vscode';
|
||||
import ChatContextManager from '../context/contextManager';
|
||||
import {messageHandler} from './messageHandler';
|
||||
|
||||
async function addConext(message: any, panel: vscode.WebviewPanel): Promise<void> {
|
||||
const contextStr = await ChatContextManager.getInstance().processText(message.selected);
|
||||
panel.webview.postMessage({ command: 'appendContext', context: contextStr });
|
||||
return;
|
||||
}
|
||||
|
||||
messageHandler.registerHandler('addContext', addConext);
|
||||
|
32
src/handler/codeApply.ts
Normal file
32
src/handler/codeApply.ts
Normal file
@ -0,0 +1,32 @@
|
||||
import * as vscode from 'vscode';
|
||||
import { messageHandler } from './messageHandler';
|
||||
|
||||
|
||||
export async function applyCode(text: string) {
|
||||
if (vscode.window.visibleTextEditors.length > 1) {
|
||||
vscode.window.showErrorMessage(`There are more then one visible text editors. Please close all but one and try again.`);
|
||||
return;
|
||||
}
|
||||
|
||||
const editor = vscode.window.visibleTextEditors[0];
|
||||
if (!editor) {
|
||||
return;
|
||||
}
|
||||
|
||||
const selection = editor.selection;
|
||||
const start = selection.start;
|
||||
const end = selection.end;
|
||||
|
||||
await editor.edit((editBuilder: vscode.TextEditorEdit) => {
|
||||
editBuilder.replace(new vscode.Range(start, end), text);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
async function codeApply(message: any, panel: vscode.WebviewPanel): Promise<void> {
|
||||
await applyCode(message.content);
|
||||
return;
|
||||
}
|
||||
|
||||
messageHandler.registerHandler('code_apply', codeApply);
|
||||
|
33
src/handler/codeFileApply.ts
Normal file
33
src/handler/codeFileApply.ts
Normal file
@ -0,0 +1,33 @@
|
||||
import * as vscode from 'vscode';
|
||||
import { messageHandler } from './messageHandler';
|
||||
|
||||
|
||||
|
||||
export async function applyCodeFile(text: string) {
|
||||
if (vscode.window.visibleTextEditors.length > 1) {
|
||||
vscode.window.showErrorMessage(`There are more then one visible text editors. Please close all but one and try again.`);
|
||||
return;
|
||||
}
|
||||
|
||||
const editor = vscode.window.visibleTextEditors[0];
|
||||
if (!editor) {
|
||||
return;
|
||||
}
|
||||
|
||||
const document = editor.document;
|
||||
const fullRange = new vscode.Range(
|
||||
document.positionAt(0),
|
||||
document.positionAt(document.getText().length)
|
||||
);
|
||||
|
||||
await editor.edit((editBuilder: vscode.TextEditorEdit) => {
|
||||
editBuilder.replace(fullRange, text);
|
||||
});
|
||||
}
|
||||
|
||||
async function codeFileApply(message: any, panel: vscode.WebviewPanel): Promise<void> {
|
||||
await applyCodeFile(message.content);
|
||||
return;
|
||||
}
|
||||
|
||||
messageHandler.registerHandler('code_file_apply', codeFileApply);
|
12
src/handler/convertCommand.ts
Normal file
12
src/handler/convertCommand.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import * as vscode from 'vscode';
|
||||
import CommandManager from '../command/commandManager';
|
||||
import {messageHandler} from './messageHandler';
|
||||
|
||||
|
||||
async function convertCommand(message: any, panel: vscode.WebviewPanel): Promise<void> {
|
||||
const newText = await CommandManager.getInstance().processText(message.text);
|
||||
panel.webview.postMessage({ command: 'convertCommand', result: newText });
|
||||
return;
|
||||
}
|
||||
|
||||
messageHandler.registerHandler('convertCommand', convertCommand);
|
19
src/handler/doCommit.ts
Normal file
19
src/handler/doCommit.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import * as vscode from 'vscode';
|
||||
import DtmWrapper from '../toolwrapper/dtm';
|
||||
import {messageHandler} from './messageHandler';
|
||||
|
||||
|
||||
async function doCommit(message: any, panel: vscode.WebviewPanel): Promise<void> {
|
||||
const dtmWrapper = new DtmWrapper();
|
||||
|
||||
const commitResult = await dtmWrapper.commit(message.content);
|
||||
if (commitResult.status === 0) {
|
||||
vscode.window.showInformationMessage('Commit successfully.');
|
||||
} else {
|
||||
vscode.window.showErrorMessage(`Error commit fail: ${commitResult.message} ${commitResult.log}`);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
messageHandler.registerHandler('doCommit', doCommit);
|
||||
|
16
src/handler/historyMessages.ts
Normal file
16
src/handler/historyMessages.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import * as vscode from 'vscode';
|
||||
import DevChat, { LogOptions } from '../toolwrapper/devchat';
|
||||
import {messageHandler} from './messageHandler';
|
||||
|
||||
|
||||
async function historyMessages(message: any, panel: vscode.WebviewPanel): Promise<void> {
|
||||
const devChat = new DevChat();
|
||||
|
||||
const logOptions: LogOptions = message.options || {};
|
||||
const logEntries = await devChat.log(logOptions);
|
||||
panel.webview.postMessage({ command: 'loadHistoryMessages', entries: logEntries });
|
||||
return;
|
||||
}
|
||||
|
||||
messageHandler.registerHandler('historyMessages', historyMessages);
|
||||
|
10
src/handler/loadHandlers.ts
Normal file
10
src/handler/loadHandlers.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import './addContext';
|
||||
import './codeApply';
|
||||
import './codeFileApply';
|
||||
import './convertCommand';
|
||||
import './doCommit';
|
||||
import './historyMessages';
|
||||
import './regCommandList';
|
||||
import './regContextList';
|
||||
import './sendMessage';
|
||||
import './showDiff';
|
34
src/handler/messageHandler.ts
Normal file
34
src/handler/messageHandler.ts
Normal file
@ -0,0 +1,34 @@
|
||||
// messageHandler.ts
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
import '../command/loadCommands';
|
||||
import '../context/loadContexts'
|
||||
|
||||
|
||||
class MessageHandler {
|
||||
private handlers: { [command: string]: (message: any, panel: vscode.WebviewPanel) => Promise<void> } = {};
|
||||
|
||||
constructor() {
|
||||
}
|
||||
|
||||
registerHandler(command: string, handler: (message: any, panel: vscode.WebviewPanel) => Promise<void>): void {
|
||||
this.handlers[command] = handler;
|
||||
}
|
||||
|
||||
async handleMessage(message: any, panel: vscode.WebviewPanel): Promise<void> {
|
||||
const handler = this.handlers[message.command];
|
||||
if (handler) {
|
||||
await handler(message, panel);
|
||||
} else {
|
||||
console.error(`No handler found for command "${message.command}"`);
|
||||
}
|
||||
}
|
||||
|
||||
sendMessage(panel: vscode.WebviewPanel, command: string, data: any): void {
|
||||
panel.webview.postMessage({ command, ...data });
|
||||
}
|
||||
}
|
||||
|
||||
export const messageHandler = new MessageHandler();
|
||||
export default messageHandler.handleMessage.bind(messageHandler);
|
13
src/handler/regCommandList.ts
Normal file
13
src/handler/regCommandList.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import * as vscode from 'vscode';
|
||||
import CommandManager from '../command/commandManager';
|
||||
import {messageHandler} from './messageHandler';
|
||||
|
||||
|
||||
async function regCommandList(message: any, panel: vscode.WebviewPanel): Promise<void> {
|
||||
const commandList = CommandManager.getInstance().getCommandList();
|
||||
panel.webview.postMessage({ command: 'regCommandList', result: commandList });
|
||||
return;
|
||||
}
|
||||
|
||||
messageHandler.registerHandler('regCommandList', regCommandList);
|
||||
|
12
src/handler/regContextList.ts
Normal file
12
src/handler/regContextList.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import * as vscode from 'vscode';
|
||||
import ChatContextManager from '../context/contextManager';
|
||||
import {messageHandler} from './messageHandler';
|
||||
|
||||
|
||||
async function regContextList(message: any, panel: vscode.WebviewPanel): Promise<void> {
|
||||
const contextList = ChatContextManager.getInstance().getContextList();
|
||||
panel.webview.postMessage({ command: 'regContextList', result: contextList });
|
||||
return;
|
||||
}
|
||||
|
||||
messageHandler.registerHandler('regContextList', regContextList);
|
108
src/handler/sendMessage.ts
Normal file
108
src/handler/sendMessage.ts
Normal file
@ -0,0 +1,108 @@
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import DevChat from '../toolwrapper/devchat';
|
||||
import CommandManager from '../command/commandManager';
|
||||
import {messageHandler} from './messageHandler';
|
||||
|
||||
|
||||
// Add this function to messageHandler.ts
|
||||
function parseMessage(message: string): { context: string[]; instruction: string[]; reference: string[]; text: string } {
|
||||
const contextRegex = /\[context\|(.*?)\]/g;
|
||||
const instructionRegex = /\[instruction\|(.*?)\]/g;
|
||||
const referenceRegex = /\[reference\|(.*?)\]/g;
|
||||
|
||||
const contextPaths = [];
|
||||
const instructionPaths = [];
|
||||
const referencePaths = [];
|
||||
|
||||
let match;
|
||||
|
||||
// 提取 context
|
||||
while ((match = contextRegex.exec(message)) !== null) {
|
||||
contextPaths.push(match[1]);
|
||||
}
|
||||
|
||||
// 提取 instruction
|
||||
while ((match = instructionRegex.exec(message)) !== null) {
|
||||
instructionPaths.push(match[1]);
|
||||
}
|
||||
|
||||
// 提取 reference
|
||||
while ((match = referenceRegex.exec(message)) !== null) {
|
||||
referencePaths.push(match[1]);
|
||||
}
|
||||
|
||||
// 移除标签,保留纯文本
|
||||
const text = message
|
||||
.replace(contextRegex, '')
|
||||
.replace(instructionRegex, '')
|
||||
.replace(referenceRegex, '')
|
||||
.trim();
|
||||
|
||||
return { context: contextPaths, instruction: instructionPaths, reference: referencePaths, text };
|
||||
}
|
||||
|
||||
function getInstructionFiles(): string[] {
|
||||
const instructionFiles: string[] = [];
|
||||
const workspaceDir = vscode.workspace.workspaceFolders?.[0].uri.fsPath;
|
||||
if (workspaceDir) {
|
||||
const chatInstructionsPath = path.join(workspaceDir, '.chat', 'instructions', 'default');
|
||||
try {
|
||||
// 读取 chatInstructionsPath 目录下的所有文件和目录
|
||||
const files = fs.readdirSync(chatInstructionsPath);
|
||||
// 过滤出文件,忽略目录
|
||||
for (const file of files) {
|
||||
const filePath = path.join(chatInstructionsPath, file);
|
||||
const fileStats = fs.statSync(filePath);
|
||||
if (fileStats.isFile()) {
|
||||
instructionFiles.push(filePath);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error reading instruction files:', error);
|
||||
}
|
||||
}
|
||||
return instructionFiles;
|
||||
}
|
||||
|
||||
let lastPromptHash: string | undefined;
|
||||
|
||||
async function sendMessage(message: any, panel: vscode.WebviewPanel): Promise<void> {
|
||||
const devChat = new DevChat();
|
||||
|
||||
const newText2 = await CommandManager.getInstance().processText(message.text);
|
||||
panel.webview.postMessage({ command: 'convertCommand', result: newText2 });
|
||||
|
||||
const parsedMessage = parseMessage(newText2);
|
||||
const chatOptions: any = lastPromptHash ? { parent: lastPromptHash } : {};
|
||||
|
||||
if (parsedMessage.context.length > 0) {
|
||||
chatOptions.context = parsedMessage.context;
|
||||
}
|
||||
|
||||
chatOptions.header = getInstructionFiles();
|
||||
if (parsedMessage.instruction.length > 0) {
|
||||
chatOptions.header = parsedMessage.instruction;
|
||||
}
|
||||
|
||||
if (parsedMessage.reference.length > 0) {
|
||||
chatOptions.reference = parsedMessage.reference;
|
||||
}
|
||||
|
||||
let partialData = "";
|
||||
const onData = (partialResponse: string) => {
|
||||
partialData += partialResponse;
|
||||
panel.webview.postMessage({ command: 'receiveMessagePartial', text: partialData });
|
||||
};
|
||||
|
||||
const chatResponse = await devChat.chat(parsedMessage.text, chatOptions, onData);
|
||||
lastPromptHash = chatResponse["prompt-hash"];
|
||||
const response = chatResponse.response;
|
||||
panel.webview.postMessage({ command: 'receiveMessage', text: response });
|
||||
return;
|
||||
}
|
||||
|
||||
messageHandler.registerHandler('sendMessage', sendMessage);
|
||||
|
@ -1,50 +1,9 @@
|
||||
const vscode = require('vscode');
|
||||
import * as vscode from 'vscode';
|
||||
import {messageHandler} from './messageHandler';
|
||||
import * as path from 'path';
|
||||
import { createTempSubdirectory } from './commonUtil';
|
||||
import { createTempSubdirectory } from '../util/commonUtil';
|
||||
|
||||
|
||||
export async function applyCodeFile(text: string) {
|
||||
if (vscode.window.visibleTextEditors.length > 1) {
|
||||
vscode.window.showErrorMessage(`There are more then one visible text editors. Please close all but one and try again.`);
|
||||
return;
|
||||
}
|
||||
|
||||
const editor = vscode.window.visibleTextEditors[0];
|
||||
if (!editor) {
|
||||
return;
|
||||
}
|
||||
|
||||
const document = editor.document;
|
||||
const fullRange = new vscode.Range(
|
||||
document.positionAt(0),
|
||||
document.positionAt(document.getText().length)
|
||||
);
|
||||
|
||||
await editor.edit((editBuilder: string) => {
|
||||
editBuilder.replace(fullRange, text);
|
||||
});
|
||||
}
|
||||
|
||||
export async function applyCode(text: string) {
|
||||
if (vscode.window.visibleTextEditors.length > 1) {
|
||||
vscode.window.showErrorMessage(`There are more then one visible text editors. Please close all but one and try again.`);
|
||||
return;
|
||||
}
|
||||
|
||||
const editor = vscode.window.visibleTextEditors[0];
|
||||
if (!editor) {
|
||||
return;
|
||||
}
|
||||
|
||||
const selection = editor.selection;
|
||||
const start = selection.start;
|
||||
const end = selection.end;
|
||||
|
||||
await editor.edit((editBuilder: string) => {
|
||||
editBuilder.replace(new vscode.Range(start, end), text);
|
||||
});
|
||||
}
|
||||
|
||||
export async function diffView(code: string) {
|
||||
if (vscode.window.visibleTextEditors.length > 1) {
|
||||
vscode.window.showErrorMessage(`There are more then one visible text editors. Please close all but one and try again.`);
|
||||
@ -85,3 +44,17 @@ export async function diffView(code: string) {
|
||||
vscode.commands.executeCommand('vscode.diff', vscode.Uri.file(curFile), vscode.Uri.file(tempFile), 'Diff View');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async function showDiff(message: any, panel: vscode.WebviewPanel): Promise<void> {
|
||||
diffView(message.content);
|
||||
return;
|
||||
}
|
||||
|
||||
async function blockApply(message: any, panel: vscode.WebviewPanel): Promise<void> {
|
||||
diffView(message.content);
|
||||
return;
|
||||
}
|
||||
|
||||
messageHandler.registerHandler('block_apply', blockApply);
|
||||
messageHandler.registerHandler('show_diff', showDiff);
|
34
src/init/chatConfig.ts
Normal file
34
src/init/chatConfig.ts
Normal file
@ -0,0 +1,34 @@
|
||||
import * as vscode from 'vscode';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as ncp from 'ncp';
|
||||
|
||||
export function createChatDirectoryAndCopyInstructionsSync(extensionUri: vscode.Uri) {
|
||||
|
||||
const workspaceFolders = vscode.workspace.workspaceFolders;
|
||||
if (!workspaceFolders) {
|
||||
return;
|
||||
}
|
||||
|
||||
const workspaceRoot = workspaceFolders[0].uri.fsPath;
|
||||
const chatDirPath = path.join(workspaceRoot, '.chat');
|
||||
const instructionsSrcPath = path.join(extensionUri.fsPath, 'instructions');
|
||||
|
||||
try {
|
||||
// 检查 .chat 目录是否存在,如果不存在,则创建它
|
||||
if (!fs.existsSync(chatDirPath)) {
|
||||
fs.mkdirSync(chatDirPath);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
// 将 instructions 目录复制到 .chat 目录中
|
||||
ncp.ncp(instructionsSrcPath, path.join(chatDirPath, 'instructions'), (err) => {
|
||||
if (err) {
|
||||
console.error('Error copying instructions:', err);
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error creating .chat directory and copying instructions:', error);
|
||||
}
|
||||
}
|
@ -1,193 +0,0 @@
|
||||
// messageHandler.ts
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { promisify } from 'util';
|
||||
import DevChat, { LogOptions } from './devchat';
|
||||
import DtmWrapper from './dtm';
|
||||
import {applyCodeFile, diffView, applyCode} from './applyCode';
|
||||
|
||||
import './loadCommands';
|
||||
import './loadContexts'
|
||||
import CommandManager, { Command } from './commandManager';
|
||||
import ChatContextManager from './contextManager';
|
||||
import { handleCodeSelected } from './contextCodeSelected';
|
||||
import { handleFileSelected } from './contextFileSelected';
|
||||
|
||||
import * as vscode3 from 'vscode';
|
||||
|
||||
const writeFileAsync = promisify(fs.writeFile);
|
||||
const unlinkAsync = promisify(fs.unlink);
|
||||
|
||||
let lastPromptHash: string | undefined;
|
||||
|
||||
async function saveTempPatchFile(content: string): Promise<string> {
|
||||
const tempPatchFilePath = path.join(vscode.workspace.workspaceFolders![0].uri.fsPath, '.temp_patch_file.patch');
|
||||
await writeFileAsync(tempPatchFilePath, content);
|
||||
return tempPatchFilePath;
|
||||
}
|
||||
|
||||
async function deleteTempPatchFile(filePath: string): Promise<void> {
|
||||
await unlinkAsync(filePath);
|
||||
}
|
||||
|
||||
export async function sendFileSelectMessage(panel: vscode.WebviewPanel, filePath: string): Promise<void> {
|
||||
const codeContext = await handleFileSelected(filePath);
|
||||
panel.webview.postMessage({ command: 'appendContext', context: codeContext });
|
||||
}
|
||||
|
||||
export async function sendCodeSelectMessage(panel: vscode.WebviewPanel, filePath: string, codeBlock: string): Promise<void> {
|
||||
const codeContext = await handleCodeSelected(filePath, codeBlock);
|
||||
panel.webview.postMessage({ command: 'appendContext', context: codeContext });
|
||||
}
|
||||
|
||||
export function askAI(panel: vscode.WebviewPanel, codeBlock: string, question: string): void {
|
||||
panel.webview.postMessage({ command: 'ask_ai', codeBlock, question });
|
||||
}
|
||||
|
||||
// Add this function to messageHandler.ts
|
||||
function parseMessage(message: string): { context: string[]; instruction: string[]; reference: string[]; text: string } {
|
||||
const contextRegex = /\[context\|(.*?)\]/g;
|
||||
const instructionRegex = /\[instruction\|(.*?)\]/g;
|
||||
const referenceRegex = /\[reference\|(.*?)\]/g;
|
||||
|
||||
const contextPaths = [];
|
||||
const instructionPaths = [];
|
||||
const referencePaths = [];
|
||||
|
||||
let match;
|
||||
|
||||
// 提取 context
|
||||
while ((match = contextRegex.exec(message)) !== null) {
|
||||
contextPaths.push(match[1]);
|
||||
}
|
||||
|
||||
// 提取 instruction
|
||||
while ((match = instructionRegex.exec(message)) !== null) {
|
||||
instructionPaths.push(match[1]);
|
||||
}
|
||||
|
||||
// 提取 reference
|
||||
while ((match = referenceRegex.exec(message)) !== null) {
|
||||
referencePaths.push(match[1]);
|
||||
}
|
||||
|
||||
// 移除标签,保留纯文本
|
||||
const text = message
|
||||
.replace(contextRegex, '')
|
||||
.replace(instructionRegex, '')
|
||||
.replace(referenceRegex, '')
|
||||
.trim();
|
||||
|
||||
return { context: contextPaths, instruction: instructionPaths, reference: referencePaths, text };
|
||||
}
|
||||
|
||||
function getInstructionFiles(): string[] {
|
||||
const instructionFiles: string[] = [];
|
||||
const workspaceDir = vscode.workspace.workspaceFolders?.[0].uri.fsPath;
|
||||
if (workspaceDir) {
|
||||
const chatInstructionsPath = path.join(workspaceDir, '.chat', 'instructions', 'default');
|
||||
try {
|
||||
// 读取 chatInstructionsPath 目录下的所有文件和目录
|
||||
const files = fs.readdirSync(chatInstructionsPath);
|
||||
// 过滤出文件,忽略目录
|
||||
for (const file of files) {
|
||||
const filePath = path.join(chatInstructionsPath, file);
|
||||
const fileStats = fs.statSync(filePath);
|
||||
if (fileStats.isFile()) {
|
||||
instructionFiles.push(filePath);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error reading instruction files:', error);
|
||||
}
|
||||
}
|
||||
return instructionFiles;
|
||||
}
|
||||
|
||||
async function handleMessage(
|
||||
message: any,
|
||||
panel: vscode.WebviewPanel
|
||||
): Promise<void> {
|
||||
const devChat = new DevChat();
|
||||
const dtmWrapper = new DtmWrapper();
|
||||
|
||||
switch (message.command) {
|
||||
case 'sendMessage':
|
||||
const newText2 = await CommandManager.getInstance().processText(message.text);
|
||||
panel.webview.postMessage({ command: 'convertCommand', result: newText2 });
|
||||
|
||||
const parsedMessage = parseMessage(newText2);
|
||||
const chatOptions: any = lastPromptHash ? { parent: lastPromptHash } : {};
|
||||
|
||||
if (parsedMessage.context.length > 0) {
|
||||
chatOptions.context = parsedMessage.context;
|
||||
}
|
||||
|
||||
chatOptions.header = getInstructionFiles();
|
||||
if (parsedMessage.instruction.length > 0) {
|
||||
chatOptions.header = parsedMessage.instruction;
|
||||
}
|
||||
|
||||
if (parsedMessage.reference.length > 0) {
|
||||
chatOptions.reference = parsedMessage.reference;
|
||||
}
|
||||
|
||||
let partialData = "";
|
||||
const onData = (partialResponse: string) => {
|
||||
partialData += partialResponse;
|
||||
panel.webview.postMessage({ command: 'receiveMessagePartial', text: partialData });
|
||||
};
|
||||
|
||||
const chatResponse = await devChat.chat(parsedMessage.text, chatOptions, onData);
|
||||
lastPromptHash = chatResponse["prompt-hash"];
|
||||
const response = chatResponse.response;
|
||||
panel.webview.postMessage({ command: 'receiveMessage', text: response });
|
||||
return;
|
||||
case 'historyMessages':
|
||||
const logOptions: LogOptions = message.options || {};
|
||||
const logEntries = await devChat.log(logOptions);
|
||||
panel.webview.postMessage({ command: 'loadHistoryMessages', entries: logEntries });
|
||||
return;
|
||||
case 'show_diff':
|
||||
diffView(message.content);
|
||||
return;
|
||||
// TODO: remove block_apply
|
||||
case 'block_apply':
|
||||
diffView(message.content);
|
||||
return;
|
||||
case 'code_apply':
|
||||
await applyCode(message.content);
|
||||
return;
|
||||
case 'code_file_apply':
|
||||
await applyCodeFile(message.content);
|
||||
return;
|
||||
case 'regCommandList':
|
||||
const commandList = CommandManager.getInstance().getCommandList();
|
||||
panel.webview.postMessage({ command: 'regCommandList', result: commandList });
|
||||
return;
|
||||
case 'convertCommand':
|
||||
const newText = await CommandManager.getInstance().processText(message.text);
|
||||
panel.webview.postMessage({ command: 'convertCommand', result: newText });
|
||||
return;
|
||||
case 'doCommit':
|
||||
const commitResult = await dtmWrapper.commit(message.content);
|
||||
if (commitResult.status === 0) {
|
||||
vscode.window.showInformationMessage('Commit successfully.');
|
||||
} else {
|
||||
vscode.window.showErrorMessage(`Error commit fail: ${commitResult.message} ${commitResult.log}`);
|
||||
}
|
||||
return;
|
||||
case 'regContextList':
|
||||
const contextList = ChatContextManager.getInstance().getContextList();
|
||||
panel.webview.postMessage({ command: 'regContextList', result: contextList });
|
||||
return;
|
||||
case 'addContext':
|
||||
const contextStr = await ChatContextManager.getInstance().processText(message.selected);
|
||||
panel.webview.postMessage({ command: 'appendContext', context: contextStr });
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
export default handleMessage;
|
79
src/panel/chatPanel.ts
Normal file
79
src/panel/chatPanel.ts
Normal file
@ -0,0 +1,79 @@
|
||||
// chatPanel.ts
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import '../handler/loadHandlers';
|
||||
import handleMessage from '../handler/messageHandler';
|
||||
import WebviewManager from './webviewManager';
|
||||
|
||||
export default class ChatPanel {
|
||||
private static _instance: ChatPanel | undefined;
|
||||
private readonly _panel: vscode.WebviewPanel;
|
||||
private _webviewManager: WebviewManager;
|
||||
private _disposables: vscode.Disposable[] = [];
|
||||
|
||||
public static createOrShow(extensionUri: vscode.Uri) {
|
||||
if (ChatPanel._instance) {
|
||||
ChatPanel._instance._panel.reveal();
|
||||
} else {
|
||||
const panel = ChatPanel.createWebviewPanel(extensionUri);
|
||||
ChatPanel._instance = new ChatPanel(panel, extensionUri);
|
||||
}
|
||||
}
|
||||
|
||||
public static currentPanel(): ChatPanel | undefined {
|
||||
return ChatPanel._instance;
|
||||
}
|
||||
|
||||
// Create a new webview panel
|
||||
private static createWebviewPanel(extensionUri: vscode.Uri): vscode.WebviewPanel {
|
||||
const column = vscode.window.activeTextEditor
|
||||
? vscode.window.activeTextEditor.viewColumn
|
||||
: undefined;
|
||||
|
||||
return vscode.window.createWebviewPanel(
|
||||
'chatPanel',
|
||||
'Chat',
|
||||
column || vscode.ViewColumn.One,
|
||||
{
|
||||
enableScripts: true,
|
||||
localResourceRoots: [vscode.Uri.joinPath(extensionUri, 'dist')],
|
||||
retainContextWhenHidden: true
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private constructor(panel: vscode.WebviewPanel, extensionUri: vscode.Uri) {
|
||||
this._panel = panel;
|
||||
this._webviewManager = new WebviewManager(panel.webview, extensionUri);
|
||||
this.registerEventListeners();
|
||||
}
|
||||
|
||||
public panel(): vscode.WebviewPanel {
|
||||
return this._panel;
|
||||
}
|
||||
|
||||
// Register event listeners for the panel and webview
|
||||
private registerEventListeners() {
|
||||
this._panel.onDidDispose(() => this.dispose(), null, this._disposables);
|
||||
|
||||
this._panel.webview.onDidReceiveMessage(
|
||||
async (message) => {
|
||||
handleMessage(message, this._panel);
|
||||
},
|
||||
null,
|
||||
this._disposables
|
||||
);
|
||||
}
|
||||
|
||||
// Dispose the panel and clean up resources
|
||||
public dispose() {
|
||||
ChatPanel._instance = undefined;
|
||||
this._panel.dispose();
|
||||
while (this._disposables.length) {
|
||||
const disposable = this._disposables.pop();
|
||||
if (disposable) {
|
||||
disposable.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
36
src/panel/webviewManager.ts
Normal file
36
src/panel/webviewManager.ts
Normal file
@ -0,0 +1,36 @@
|
||||
import * as vscode from 'vscode';
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs';
|
||||
|
||||
export default class WebviewManager {
|
||||
private _webview: vscode.Webview;
|
||||
private _extensionUri: vscode.Uri;
|
||||
|
||||
constructor(webview: vscode.Webview, extensionUri: vscode.Uri) {
|
||||
this._webview = webview;
|
||||
this._extensionUri = extensionUri;
|
||||
this.setWebviewOptions();
|
||||
this.setWebviewContent();
|
||||
}
|
||||
|
||||
private setWebviewOptions() {
|
||||
this._webview.options = {
|
||||
enableScripts: true,
|
||||
localResourceRoots: [vscode.Uri.joinPath(this._extensionUri, 'dist')],
|
||||
};
|
||||
}
|
||||
|
||||
private setWebviewContent() {
|
||||
this._webview.html = this._getHtmlContent();
|
||||
}
|
||||
|
||||
private _getHtmlContent(): string {
|
||||
const htmlPath = vscode.Uri.joinPath(this._extensionUri, 'dist', 'assets', 'chatPanel.html');
|
||||
const htmlContent = fs.readFileSync(htmlPath.fsPath, 'utf8');
|
||||
|
||||
return htmlContent.replace(/<vscode-resource:(\/.+?)>/g, (_, resourcePath) => {
|
||||
const resourceUri = vscode.Uri.joinPath(this._extensionUri, 'dist', resourcePath);
|
||||
return this._webview.asWebviewUri(resourceUri).toString();
|
||||
});
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user