Merge branch 'covespace:main' into message-handler

This commit is contained in:
Rankin Zheng 2023-05-06 17:19:47 +08:00 committed by GitHub
commit d2c0ee9d02
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
42 changed files with 612 additions and 916 deletions

View 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.

View 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.

View 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
View File

@ -1,12 +1,12 @@
{ {
"name": "devchat", "name": "devchat",
"version": "0.0.1", "version": "0.0.3",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "devchat", "name": "devchat",
"version": "0.0.1", "version": "0.0.3",
"dependencies": { "dependencies": {
"@emotion/react": "^11.10.8", "@emotion/react": "^11.10.8",
"@mantine/core": "^6.0.10", "@mantine/core": "^6.0.10",
@ -36,7 +36,6 @@
"@babel/preset-typescript": "^7.21.5", "@babel/preset-typescript": "^7.21.5",
"@types/glob": "^8.1.0", "@types/glob": "^8.1.0",
"@types/jest": "^29.5.1", "@types/jest": "^29.5.1",
"@types/mocha": "^10.0.1",
"@types/ncp": "^2.0.5", "@types/ncp": "^2.0.5",
"@types/node": "16.x", "@types/node": "16.x",
"@types/react-dom": "^18.2.3", "@types/react-dom": "^18.2.3",
@ -55,7 +54,6 @@
"html-webpack-plugin": "^5.5.1", "html-webpack-plugin": "^5.5.1",
"jest": "^29.5.0", "jest": "^29.5.0",
"json-loader": "^0.5.7", "json-loader": "^0.5.7",
"mocha": "^10.2.0",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-redux": "^8.0.5", "react-redux": "^8.0.5",
@ -3770,12 +3768,6 @@
"integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==",
"dev": true "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": { "node_modules/@types/ncp": {
"version": "2.0.5", "version": "2.0.5",
"resolved": "https://registry.npmjs.org/@types/ncp/-/ncp-2.0.5.tgz", "resolved": "https://registry.npmjs.org/@types/ncp/-/ncp-2.0.5.tgz",
@ -4491,15 +4483,6 @@
"ajv": "^6.9.1" "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": { "node_modules/ansi-escapes": {
"version": "4.3.2", "version": "4.3.2",
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
@ -5007,12 +4990,6 @@
"node": ">=8" "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": { "node_modules/browserslist": {
"version": "4.21.5", "version": "4.21.5",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz",
@ -5289,17 +5266,6 @@
"node": ">= 10.0" "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": { "node_modules/clone-deep": {
"version": "4.0.1", "version": "4.0.1",
"resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", "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": { "node_modules/dedent": {
"version": "0.7.0", "version": "0.7.0",
"resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", "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", "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz",
"integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==" "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": { "node_modules/diff-sequences": {
"version": "29.4.3", "version": "29.4.3",
"resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz",
@ -6742,15 +6687,6 @@
"url": "https://github.com/sponsors/sindresorhus" "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": { "node_modules/flat-cache": {
"version": "3.0.4", "version": "3.0.4",
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
@ -7649,18 +7585,6 @@
"url": "https://github.com/sponsors/sindresorhus" "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": { "node_modules/is-wsl": {
"version": "2.2.0", "version": "2.2.0",
"resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
@ -8688,22 +8612,6 @@
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
"dev": true "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": { "node_modules/loose-envify": {
"version": "1.4.0", "version": "1.4.0",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
@ -9064,120 +8972,6 @@
"node": "*" "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": { "node_modules/ms": {
"version": "2.1.2", "version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@ -9196,18 +8990,6 @@
"multicast-dns": "cli.js" "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": { "node_modules/natural-compare": {
"version": "1.4.0", "version": "1.4.0",
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
@ -12597,12 +12379,6 @@
"node": ">=0.10.0" "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": { "node_modules/wrap-ansi": {
"version": "7.0.0", "version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
@ -12691,48 +12467,6 @@
"node": ">= 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": { "node_modules/yocto-queue": {
"version": "0.1.0", "version": "0.1.0",
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
@ -15449,12 +15183,6 @@
"integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==",
"dev": true "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": { "@types/ncp": {
"version": "2.0.5", "version": "2.0.5",
"resolved": "https://registry.npmjs.org/@types/ncp/-/ncp-2.0.5.tgz", "resolved": "https://registry.npmjs.org/@types/ncp/-/ncp-2.0.5.tgz",
@ -16023,12 +15751,6 @@
"dev": true, "dev": true,
"requires": {} "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": { "ansi-escapes": {
"version": "4.3.2", "version": "4.3.2",
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
@ -16425,12 +16147,6 @@
"fill-range": "^7.0.1" "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": { "browserslist": {
"version": "4.21.5", "version": "4.21.5",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz",
@ -16607,17 +16323,6 @@
"source-map": "~0.6.0" "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": { "clone-deep": {
"version": "4.0.1", "version": "4.0.1",
"resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz",
@ -16969,12 +16674,6 @@
"ms": "2.1.2" "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": { "dedent": {
"version": "0.7.0", "version": "0.7.0",
"resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", "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", "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz",
"integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==" "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": { "diff-sequences": {
"version": "29.4.3", "version": "29.4.3",
"resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz",
@ -17699,12 +17392,6 @@
"path-exists": "^4.0.0" "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": { "flat-cache": {
"version": "3.0.4", "version": "3.0.4",
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
@ -18337,12 +18024,6 @@
"integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
"dev": true "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": { "is-wsl": {
"version": "2.2.0", "version": "2.2.0",
"resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
@ -19151,16 +18832,6 @@
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
"dev": true "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": { "loose-envify": {
"version": "1.4.0", "version": "1.4.0",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
@ -19432,97 +19103,6 @@
"brace-expansion": "^1.1.7" "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": { "ms": {
"version": "2.1.2", "version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@ -19538,12 +19118,6 @@
"thunky": "^1.0.2" "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": { "natural-compare": {
"version": "1.4.0", "version": "1.4.0",
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "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==", "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
"dev": true "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": { "wrap-ansi": {
"version": "7.0.0", "version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "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", "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
"integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==" "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": { "yocto-queue": {
"version": "0.1.0", "version": "0.1.0",
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",

View File

@ -2,7 +2,7 @@
"name": "devchat", "name": "devchat",
"displayName": "devchat", "displayName": "devchat",
"description": "devchat", "description": "devchat",
"version": "0.0.1", "version": "0.0.3",
"engines": { "engines": {
"vscode": "^1.77.0" "vscode": "^1.77.0"
}, },
@ -24,7 +24,9 @@
"DevChat.llmModel": { "DevChat.llmModel": {
"type": "string", "type": "string",
"default": "OpenAI", "default": "OpenAI",
"enum": ["OpenAI"], "enum": [
"OpenAI"
],
"description": "Select whose llm to use." "description": "Select whose llm to use."
}, },
"DevChat.OpenAI.model": { "DevChat.OpenAI.model": {
@ -123,7 +125,6 @@
"@babel/preset-typescript": "^7.21.5", "@babel/preset-typescript": "^7.21.5",
"@types/glob": "^8.1.0", "@types/glob": "^8.1.0",
"@types/jest": "^29.5.1", "@types/jest": "^29.5.1",
"@types/mocha": "^10.0.1",
"@types/ncp": "^2.0.5", "@types/ncp": "^2.0.5",
"@types/node": "16.x", "@types/node": "16.x",
"@types/react-dom": "^18.2.3", "@types/react-dom": "^18.2.3",
@ -142,7 +143,6 @@
"html-webpack-plugin": "^5.5.1", "html-webpack-plugin": "^5.5.1",
"jest": "^29.5.0", "jest": "^29.5.0",
"json-loader": "^0.5.7", "json-loader": "^0.5.7",
"mocha": "^10.2.0",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-redux": "^8.0.5", "react-redux": "^8.0.5",

View File

@ -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();
}
}
}
}

View File

@ -7,8 +7,8 @@ import * as fs from 'fs';
import * as os from 'os'; import * as os from 'os';
import * as path from 'path'; import * as path from 'path';
import { promisify } from 'util'; import { promisify } from 'util';
import { createTempSubdirectory } from './commonUtil'; import { createTempSubdirectory } from '../util/commonUtil';
import ExtensionContextHolder from './extensionContext'; import ExtensionContextHolder from '../util/extensionContext';
const mkdirAsync = promisify(fs.mkdir); const mkdirAsync = promisify(fs.mkdir);
const execAsync = promisify(exec); const execAsync = promisify(exec);

View File

@ -1,7 +1,7 @@
import * as vscode from 'vscode'; import * as vscode from 'vscode';
import * as path from 'path'; import * as path from 'path';
import { createTempSubdirectory, getLanguageIdByFileName } from './commonUtil'; import { createTempSubdirectory, getLanguageIdByFileName } from '../util/commonUtil';
export async function handleCodeSelected(fileSelected: string, codeSelected: string) { export async function handleCodeSelected(fileSelected: string, codeSelected: string) {
// get file name from fileSelected // get file name from fileSelected

View File

@ -1,7 +1,7 @@
import * as path from 'path'; import * as path from 'path';
import * as vscode from 'vscode'; import * as vscode from 'vscode';
import { ChatContext } from './contextManager'; import { ChatContext } from './contextManager';
import { createTempSubdirectory, runCommandAndWriteOutput, runCommandStringAndWriteOutput } from './commonUtil'; import { createTempSubdirectory, runCommandAndWriteOutput, runCommandStringAndWriteOutput } from '../util/commonUtil';
export const customCommandContext: ChatContext = { export const customCommandContext: ChatContext = {
name: '<custom command>', name: '<custom command>',

View File

@ -1,7 +1,7 @@
import * as vscode from 'vscode'; import * as vscode from 'vscode';
import * as path from 'path'; import * as path from 'path';
import { createTempSubdirectory, getLanguageIdByFileName } from './commonUtil'; import { createTempSubdirectory, getLanguageIdByFileName } from '../util/commonUtil';
export async function handleFileSelected(fileSelected: string) { export async function handleFileSelected(fileSelected: string) {
// get file name from fileSelected // get file name from fileSelected

View File

@ -1,6 +1,6 @@
import * as path from 'path'; import * as path from 'path';
import { ChatContext } from './contextManager'; import { ChatContext } from './contextManager';
import { createTempSubdirectory, runCommandAndWriteOutput } from './commonUtil'; import { createTempSubdirectory, runCommandAndWriteOutput } from '../util/commonUtil';
export const gitDiffContext: ChatContext = { export const gitDiffContext: ChatContext = {
name: 'git diff', name: 'git diff',

View File

@ -1,6 +1,6 @@
import * as path from 'path'; import * as path from 'path';
import { ChatContext } from './contextManager'; import { ChatContext } from './contextManager';
import { createTempSubdirectory, runCommandAndWriteOutput } from './commonUtil'; import { createTempSubdirectory, runCommandAndWriteOutput } from '../util/commonUtil';
export const gitDiffCachedContext: ChatContext = { export const gitDiffCachedContext: ChatContext = {
name: 'git diff cached', name: 'git diff cached',

View 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
View 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 });
}

View File

@ -1,42 +1,15 @@
import * as vscode from 'vscode'; 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; import { createChatDirectoryAndCopyInstructionsSync } from './init/chatConfig';
const sendFileSelectMessage = require('./messageHandler').sendFileSelectMessage; import {
const sendCodeSelectMessage = require('./messageHandler').sendCodeSelectMessage; registerOpenChatPanelCommand,
import ExtensionContextHolder from './extensionContext'; registerAddContextCommand,
registerAskForCodeCommand,
registerAskForFileCommand,
} from './contributes/commands';
function createChatDirectoryAndCopyInstructionsSync(extensionUri: vscode.Uri) { import ExtensionContextHolder from './util/extensionContext';
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);
}
}
function activate(context: vscode.ExtensionContext) { function activate(context: vscode.ExtensionContext) {
ExtensionContextHolder.context = context; ExtensionContextHolder.context = context;
@ -44,64 +17,9 @@ function activate(context: vscode.ExtensionContext) {
// 创建 .chat 目录并复制 instructions // 创建 .chat 目录并复制 instructions
createChatDirectoryAndCopyInstructionsSync(context.extensionUri); createChatDirectoryAndCopyInstructionsSync(context.extensionUri);
let disposable = vscode.commands.registerCommand('devchat.openChatPanel', () => { registerOpenChatPanelCommand(context);
if (vscode.workspace.workspaceFolders) { registerAddContextCommand(context);
ChatPanel.createOrShow(context.extensionUri); registerAskForCodeCommand(context);
} else { registerAskForFileCommand(context);
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)
} }
exports.activate = activate; exports.activate = activate;

12
src/handler/addContext.ts Normal file
View 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
View 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);

View 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);

View 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
View 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);

View 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);

View 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';

View 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);

View 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);

View 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
View 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);

View File

@ -1,50 +1,9 @@
const vscode = require('vscode'); import * as vscode from 'vscode';
import {messageHandler} from './messageHandler';
import * as path from 'path'; 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) { export async function diffView(code: string) {
if (vscode.window.visibleTextEditors.length > 1) { 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.`); 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'); 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
View 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);
}
}

View File

@ -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
View 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();
}
}
}
}

View 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();
});
}
}