mirror of
https://github.com/leon-ai/leon.git
synced 2024-12-25 01:31:47 +03:00
Merge branch 'develop' into cli-arrival
This commit is contained in:
commit
429dce6f37
11
.husky/commit-msg
Executable file
11
.husky/commit-msg
Executable file
@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
|
||||
if ! [ -x "$(command -v npm)" ]; then
|
||||
echo "npm: command not found"
|
||||
echo "If you use a version manager tool such as nvm and a git GUI such as GitKraken, please read: https://typicode.github.io/husky/#/?id=command-not-found" >&2
|
||||
exit 1
|
||||
else
|
||||
npm run lint && node_modules/@babel/node/bin/babel-node.js scripts/commit-msg.js
|
||||
fi
|
||||
|
17
CHANGELOG.md
17
CHANGELOG.md
@ -1,4 +1,19 @@
|
||||
# [1.0.0-beta.4](https://github.com/leon-ai/leon/compare/1.0.0-beta.2...1.0.0-beta.4) (2021-05-01) / Getting Rid of Dust
|
||||
# [1.0.0-beta.5](https://github.com/leon-ai/leon/compare/v1.0.0-beta.4...v1.0.0-beta.5) (2021-12-28) / Refocus
|
||||
|
||||
*This release marks a major turn in the future versions of the Leon core. Please [read this blog post](https://blog.getleon.ai/i-ran-away-from-open-source/) to know more.*
|
||||
|
||||
### BREAKING CHANGES
|
||||
- Node.js 16+ and npm 8+ minimum requirements [2f66f1c1](https://github.com/leon-ai/leon/commit/2f66f1c17bb2e4a1c18b4251d49de252b8d87344)
|
||||
### Features
|
||||
- **server:** support arrays on NER between conditions [7cf7f979](https://github.com/leon-ai/leon/commit/7cf7f9791254e1950fe9128ce1b3a58079cc2ada)
|
||||
### Bug Fixes
|
||||
- jest-extended new setup due to latest update [02f766d6](https://github.com/leon-ai/leon/commit/02f766d6a8453609ebaec78356aa6e6d4df0967b)
|
||||
### Performance Improvements
|
||||
- Windows setup on DeepSpeech dep removal [13f5a49f](https://github.com/leon-ai/leon/commit/13f5a49f678f8f67a93b67d4f558cddcf237e204)
|
||||
### Documentation Changes
|
||||
- URL redirect managed by registrar [c16d5b28](https://github.com/leon-ai/leon/commit/c16d5b280b758f7e18305e30678adec79f0a0716)
|
||||
|
||||
# [1.0.0-beta.4](https://github.com/leon-ai/leon/compare/1.0.0-beta.2...v1.0.0-beta.4) (2021-05-01) / Getting Rid of Dust
|
||||
|
||||
*This release includes a lot of changes that are made under the hood and are not displayed here, please **[read the blog post](https://blog.getleon.ai/getting-rid-of-dust-1-0-0-beta-4/)** to know more.*
|
||||
|
||||
|
@ -145,7 +145,7 @@ You'll find a write-up on this [blog post](https://blog.getleon.ai/the-story-beh
|
||||
## 🔔 Stay Tuned
|
||||
|
||||
- [Twitter](https://twitter.com/louistiti_fr)
|
||||
- [Newsletter](https://getleon.ai)
|
||||
- [Newsletter](http://newsletter.getleon.ai)
|
||||
- [Blog](https://blog.getleon.ai)
|
||||
- [GitHub issues](https://github.com/leon-ai/leon/issues)
|
||||
- [YouTube](https://www.youtube.com/channel/UCW6mk6j6nQUzFYY97r47emQ)
|
||||
@ -174,6 +174,13 @@ You'll find a write-up on this [blog post](https://blog.getleon.ai/the-story-beh
|
||||
</a><br>
|
||||
<sub><sup>30 USD / month</sup></sub>
|
||||
</td>
|
||||
<td align="center" valign="middle" width="128">
|
||||
<a href="https://github.com/phareal">
|
||||
<img src="https://github.com/phareal.png?size=128" />
|
||||
phareal
|
||||
</a><br>
|
||||
<sub><sup>17 USD / month</sup></sub>
|
||||
</td>
|
||||
<td align="center" valign="middle" width="128">
|
||||
<a href="https://github.com/marvinpoo">
|
||||
<img src="https://github.com/marvinpoo.png?size=128" />
|
||||
|
@ -29,7 +29,7 @@
|
||||
<small>
|
||||
Use <kbd>↑</kbd> <kbd>↓</kbd> to browse history;
|
||||
<kbd>↵</kbd> to submit;
|
||||
<kbd>alt + t to listen.</kbd>
|
||||
<kbd>alt + c to listen.</kbd>
|
||||
</small>
|
||||
</div>
|
||||
</main>
|
||||
|
@ -28,7 +28,7 @@ const onkeydowninput = (e, client) => {
|
||||
}
|
||||
|
||||
const onkeydowndocument = (e, cb) => {
|
||||
if (e.altKey && e.key === 't') {
|
||||
if (e.altKey && e.key === 'c') {
|
||||
cb()
|
||||
}
|
||||
}
|
||||
|
10
ide.js
10
ide.js
@ -1,10 +0,0 @@
|
||||
/**
|
||||
* Allow babel-plugin-module-resolver aliases for JetBrains IDEs
|
||||
*/
|
||||
|
||||
System.config({
|
||||
paths: {
|
||||
'@@/*': './*',
|
||||
'@/*': './server/src/*'
|
||||
}
|
||||
})
|
9
jsconfig.json
Normal file
9
jsconfig.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@@/*": ["./*"],
|
||||
"@/*": ["./server/src/*"]
|
||||
}
|
||||
}
|
||||
}
|
17761
package-lock.json
generated
17761
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
34
package.json
34
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "leon",
|
||||
"version": "1.0.0-beta.5+dev",
|
||||
"version": "1.0.0-beta.6+dev",
|
||||
"description": "Server, packages and web app of the Leon personal assistant",
|
||||
"author": {
|
||||
"name": "Louis Grenard",
|
||||
@ -23,10 +23,10 @@
|
||||
"scripts": {
|
||||
"lint": "babel-node scripts/lint.js",
|
||||
"test": "npm run test:json && npm run test:unit && npm run test:e2e",
|
||||
"test:unit": "npm run train expressions:en && cross-env PIPENV_PIPFILE=bridges/python/Pipfile LEON_NODE_ENV=testing jest --forceExit --silent --projects test/unit/unit.jest.json && npm run train expressions",
|
||||
"test:unit": "npm run train en && cross-env PIPENV_PIPFILE=bridges/python/Pipfile LEON_NODE_ENV=testing jest --forceExit --silent --projects test/unit/unit.jest.json && npm run train",
|
||||
"test:e2e": "npm run test:e2e:nlp-modules && npm run test:e2e:modules",
|
||||
"test:e2e:modules": "babel-node scripts/run-clean-test-dbs.js && npm run train expressions:en && cross-env PIPENV_PIPFILE=bridges/python/Pipfile LEON_NODE_ENV=testing jest --forceExit --silent --verbose --projects test/e2e/modules/e2e.modules.jest.json && babel-node scripts/run-clean-test-dbs.js && npm run train expressions",
|
||||
"test:e2e:nlp-modules": "npm run train expressions:en && cross-env PIPENV_PIPFILE=bridges/python/Pipfile LEON_NODE_ENV=testing jest --forceExit --silent --verbose --setupTestFrameworkScriptFile=./test/paths.setup.js test/e2e/nlp-modules.spec.js && npm run train expressions",
|
||||
"test:e2e:modules": "babel-node scripts/run-clean-test-dbs.js && npm run train en && cross-env PIPENV_PIPFILE=bridges/python/Pipfile LEON_NODE_ENV=testing jest --forceExit --silent --verbose --projects test/e2e/modules/e2e.modules.jest.json && babel-node scripts/run-clean-test-dbs.js && npm run train",
|
||||
"test:e2e:nlp-modules": "npm run train en && cross-env PIPENV_PIPFILE=bridges/python/Pipfile LEON_NODE_ENV=testing jest --forceExit --silent --verbose --setupTestFrameworkScriptFile=./test/paths.setup.js test/e2e/nlp-modules.spec.js && npm run train",
|
||||
"test:json": "jest --silent --projects test/json/json.jest.json",
|
||||
"test:module": "babel-node scripts/test-module.js",
|
||||
"setup:offline": "babel-node scripts/setup-offline/setup-offline.js",
|
||||
@ -36,12 +36,13 @@
|
||||
"preinstall": "node scripts/setup/preinstall.js",
|
||||
"postinstall": "babel-node scripts/setup/setup.js",
|
||||
"dev:app": "vite --config app/vite.config.js",
|
||||
"dev:server": "npm run train expressions && cross-env LEON_NODE_ENV=development nodemon --watch server ./server/src/index.js --ignore server/src/tmp/ --exec babel-node",
|
||||
"dev:server": "npm run train && cross-env LEON_NODE_ENV=development nodemon --watch server ./server/src/index.js --ignore server/src/tmp/ --exec babel-node",
|
||||
"wake": "cross-env LEON_HOST=http://localhost LEON_PORT=1337 node hotword/index.js",
|
||||
"delete-dist:server": "shx rm -rf ./server/dist",
|
||||
"build": "npm run lint && npm run build:app && npm run build:server",
|
||||
"prepare": "husky install",
|
||||
"build": "npm run build:app && npm run build:server",
|
||||
"build:app": "cross-env LEON_NODE_ENV=production babel-node scripts/app/run-build-app.js",
|
||||
"build:server": "npm run delete-dist:server && npm run train expressions && babel ./server/src -d ./server/dist --copy-files && shx mkdir -p server/dist/tmp",
|
||||
"build:server": "npm run delete-dist:server && npm run train && babel ./server/src -d ./server/dist --copy-files && shx mkdir -p server/dist/tmp",
|
||||
"start": "cross-env LEON_NODE_ENV=production node ./server/dist/index.js",
|
||||
"train": "babel-node scripts/run-train.js",
|
||||
"prepare-release": "babel-node scripts/release/prepare-release.js",
|
||||
@ -53,8 +54,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-polly": "^3.18.0",
|
||||
"@ffmpeg-installer/ffmpeg": "^1.0.20",
|
||||
"@ffprobe-installer/ffprobe": "^1.1.0",
|
||||
"@ffmpeg-installer/ffmpeg": "^1.1.0",
|
||||
"@ffprobe-installer/ffprobe": "^1.3.0",
|
||||
"@google-cloud/speech": "^4.2.0",
|
||||
"@google-cloud/text-to-speech": "^3.2.1",
|
||||
"@nlpjs/basic": "^4.22.0",
|
||||
@ -68,15 +69,15 @@
|
||||
"deepspeech": "^0.9.3",
|
||||
"dotenv": "^10.0.0",
|
||||
"execa": "^5.0.0",
|
||||
"fastify": "^3.17.0",
|
||||
"fastify-static": "^4.0.1",
|
||||
"fastify": "^3.25.2",
|
||||
"fastify-static": "^4.5.0",
|
||||
"fluent-ffmpeg": "^2.1.2",
|
||||
"googleapis": "^67.1.1",
|
||||
"ibm-watson": "^6.1.1",
|
||||
"moment-timezone": "^0.5.33",
|
||||
"node-wav": "0.0.2",
|
||||
"socket.io": "^4.1.2",
|
||||
"socket.io-client": "^4.1.2",
|
||||
"socket.io": "^4.4.0",
|
||||
"socket.io-client": "^4.4.0",
|
||||
"superagent": "^6.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
@ -92,14 +93,15 @@
|
||||
"eslint-plugin-import": "^2.23.2",
|
||||
"eslint-plugin-jest": "^24.3.6",
|
||||
"git-changelog": "^2.0.0",
|
||||
"husky": "^7.0.0",
|
||||
"inquirer": "^8.1.0",
|
||||
"jest": "^26.6.3",
|
||||
"jest": "^27.4.5",
|
||||
"jest-canvas-mock": "^2.3.1",
|
||||
"jest-extended": "^0.11.5",
|
||||
"jest-extended": "^1.2.0",
|
||||
"json": "^10.0.0",
|
||||
"nodemon": "^2.0.7",
|
||||
"semver": "^7.3.5",
|
||||
"shx": "^0.3.3",
|
||||
"vite": "^2.3.4"
|
||||
"vite": "^2.7.7"
|
||||
}
|
||||
}
|
||||
|
@ -12,23 +12,8 @@
|
||||
"conditions": [
|
||||
{
|
||||
"type": "between",
|
||||
"from": "the",
|
||||
"to": "list"
|
||||
},
|
||||
{
|
||||
"type": "between",
|
||||
"from": "a",
|
||||
"to": "list"
|
||||
},
|
||||
{
|
||||
"type": "between",
|
||||
"from": "an",
|
||||
"to": "list"
|
||||
},
|
||||
{
|
||||
"type": "between",
|
||||
"from": "my",
|
||||
"to": "list"
|
||||
"from": ["the", "a", "an", "my"],
|
||||
"to": ["list", "list", "list", "list"]
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -56,13 +41,8 @@
|
||||
"conditions": [
|
||||
{
|
||||
"type": "between",
|
||||
"from": "the",
|
||||
"to": "list"
|
||||
},
|
||||
{
|
||||
"type": "between",
|
||||
"from": "my",
|
||||
"to": "list"
|
||||
"from": ["the", "my"],
|
||||
"to": ["list", "list"]
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -80,13 +60,8 @@
|
||||
"conditions": [
|
||||
{
|
||||
"type": "between",
|
||||
"from": "the",
|
||||
"to": "list"
|
||||
},
|
||||
{
|
||||
"type": "between",
|
||||
"from": "my",
|
||||
"to": "list"
|
||||
"from": ["the", "my"],
|
||||
"to": ["list", "list"]
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -114,13 +89,8 @@
|
||||
"conditions": [
|
||||
{
|
||||
"type": "between",
|
||||
"from": "the",
|
||||
"to": "list"
|
||||
},
|
||||
{
|
||||
"type": "between",
|
||||
"from": "my",
|
||||
"to": "list"
|
||||
"from": ["the", "my"],
|
||||
"to": ["list", "list"]
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -149,13 +119,8 @@
|
||||
"conditions": [
|
||||
{
|
||||
"type": "between",
|
||||
"from": "the",
|
||||
"to": "list"
|
||||
},
|
||||
{
|
||||
"type": "between",
|
||||
"from": "my",
|
||||
"to": "list"
|
||||
"from": ["the", "my"],
|
||||
"to": ["list", "list"]
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -175,18 +140,8 @@
|
||||
"conditions": [
|
||||
{
|
||||
"type": "between",
|
||||
"from": "check",
|
||||
"to": "from"
|
||||
},
|
||||
{
|
||||
"type": "between",
|
||||
"from": "complete",
|
||||
"to": "from"
|
||||
},
|
||||
{
|
||||
"type": "between",
|
||||
"from": "tick",
|
||||
"to": "from"
|
||||
"from": ["check", "complete", "tick"],
|
||||
"to": ["from", "from", "from"]
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -196,13 +151,8 @@
|
||||
"conditions": [
|
||||
{
|
||||
"type": "between",
|
||||
"from": "the",
|
||||
"to": "list"
|
||||
},
|
||||
{
|
||||
"type": "between",
|
||||
"from": "my",
|
||||
"to": "list"
|
||||
"from": ["the", "my"],
|
||||
"to": ["list", "list"]
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -221,13 +171,8 @@
|
||||
"conditions": [
|
||||
{
|
||||
"type": "between",
|
||||
"from": "uncheck",
|
||||
"to": "from"
|
||||
},
|
||||
{
|
||||
"type": "between",
|
||||
"from": "untick",
|
||||
"to": "from"
|
||||
"from": ["uncheck", "untick"],
|
||||
"to": ["from", "from"]
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -237,13 +182,8 @@
|
||||
"conditions": [
|
||||
{
|
||||
"type": "between",
|
||||
"from": "the",
|
||||
"to": "list"
|
||||
},
|
||||
{
|
||||
"type": "between",
|
||||
"from": "my",
|
||||
"to": "list"
|
||||
"from": ["the", "my"],
|
||||
"to": ["list", "list"]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -105,13 +105,8 @@
|
||||
"conditions": [
|
||||
{
|
||||
"type": "between",
|
||||
"from": "ajoute",
|
||||
"to": "à"
|
||||
},
|
||||
{
|
||||
"type": "between",
|
||||
"from": "ajoute",
|
||||
"to": "a"
|
||||
"from": ["ajoute", "ajoute"],
|
||||
"to": ["à", "a"]
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -140,18 +135,8 @@
|
||||
"conditions": [
|
||||
{
|
||||
"type": "between",
|
||||
"from": "coche",
|
||||
"to": "de"
|
||||
},
|
||||
{
|
||||
"type": "between",
|
||||
"from": "complète",
|
||||
"to": "de"
|
||||
},
|
||||
{
|
||||
"type": "between",
|
||||
"from": "complete",
|
||||
"to": "de"
|
||||
"from": ["coche", "complète", "complete"],
|
||||
"to": ["de", "de", "de"]
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -181,23 +166,8 @@
|
||||
"conditions": [
|
||||
{
|
||||
"type": "between",
|
||||
"from": "décoche",
|
||||
"to": "de"
|
||||
},
|
||||
{
|
||||
"type": "between",
|
||||
"from": "decoche",
|
||||
"to": "de"
|
||||
},
|
||||
{
|
||||
"type": "between",
|
||||
"from": "invalide",
|
||||
"to": "de"
|
||||
},
|
||||
{
|
||||
"type": "between",
|
||||
"from": "remet",
|
||||
"to": "sur"
|
||||
"from": ["décoche", "decoche", "invalide", "remet"],
|
||||
"to": ["de", "de", "de", "sur"]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -1,4 +1,4 @@
|
||||
describe('calendar:todolist', async () => {
|
||||
describe('calendar:todolist', () => {
|
||||
test('no list', async () => {
|
||||
global.nlu.brain.execute = jest.fn()
|
||||
await global.nlu.process('Show all my lists')
|
||||
|
@ -1,4 +1,4 @@
|
||||
describe('checker:haveibeenpwned', async () => {
|
||||
describe('checker:haveibeenpwned', () => {
|
||||
test('checks if an email address has been provided', async () => {
|
||||
global.nlu.brain.execute = jest.fn()
|
||||
await global.nlu.process('Have I been pwned?')
|
||||
|
@ -1,4 +1,4 @@
|
||||
describe('checker:isitdown', async () => {
|
||||
describe('checker:isitdown', () => {
|
||||
test('detects invalid domain name', async () => {
|
||||
global.nlu.brain.execute = jest.fn()
|
||||
await global.nlu.process('Check if github is up')
|
||||
|
@ -1,4 +1,4 @@
|
||||
describe('leon:bye', async () => {
|
||||
describe('leon:bye', () => {
|
||||
test('says bye', async () => {
|
||||
global.nlu.brain.execute = jest.fn()
|
||||
await global.nlu.process('Bye bye')
|
||||
|
@ -1,4 +1,4 @@
|
||||
describe('leon:greeting', async () => {
|
||||
describe('leon:greeting', () => {
|
||||
test('greets', async () => {
|
||||
global.nlu.brain.execute = jest.fn()
|
||||
await global.nlu.process('Hello')
|
||||
|
@ -1,4 +1,4 @@
|
||||
describe('leon:joke', async () => {
|
||||
describe('leon:joke', () => {
|
||||
test('tells a joke', async () => {
|
||||
global.nlu.brain.execute = jest.fn()
|
||||
await global.nlu.process('Tell me a joke')
|
||||
|
@ -1,4 +1,4 @@
|
||||
describe('leon:meaningoflife', async () => {
|
||||
describe('leon:meaningoflife', () => {
|
||||
test('says the meaning of life', async () => {
|
||||
global.nlu.brain.execute = jest.fn()
|
||||
await global.nlu.process('What is the meaning of life?')
|
||||
|
@ -1,4 +1,4 @@
|
||||
describe('leon:partnerassistant', async () => {
|
||||
describe('leon:partnerassistant', () => {
|
||||
test('does not know this personal assistant', async () => {
|
||||
global.nlu.brain.execute = jest.fn()
|
||||
await global.nlu.process('Tell me about the personal assistant Louistiti')
|
||||
|
@ -1,4 +1,4 @@
|
||||
describe('leon:randomnumber', async () => {
|
||||
describe('leon:randomnumber', () => {
|
||||
test('gives a random number between 0 and 100', async () => {
|
||||
global.nlu.brain.execute = jest.fn()
|
||||
await global.nlu.process('Give me a random number')
|
||||
|
@ -1,4 +1,4 @@
|
||||
describe('leon:welcome', async () => {
|
||||
describe('leon:welcome', () => {
|
||||
test('welcomes', async () => {
|
||||
global.nlu.brain.execute = jest.fn()
|
||||
await global.nlu.process('Thank you')
|
||||
|
@ -1,4 +1,4 @@
|
||||
describe('leon:whoami', async () => {
|
||||
describe('leon:whoami', () => {
|
||||
test('introduces himself', async () => {
|
||||
global.nlu.brain.execute = jest.fn()
|
||||
await global.nlu.process('Who are you?')
|
||||
|
@ -1,4 +1,4 @@
|
||||
describe('network:speedtest', async () => {
|
||||
describe('network:speedtest', () => {
|
||||
test('does a speed test', async () => {
|
||||
global.nlu.brain.execute = jest.fn()
|
||||
await global.nlu.process('Do a speed test')
|
||||
|
@ -1,4 +1,4 @@
|
||||
describe('trend:github', async () => {
|
||||
describe('trend:github', () => {
|
||||
test('forces limit', async () => {
|
||||
global.nlu.brain.execute = jest.fn()
|
||||
await global.nlu.process('Give me the 30 latest GitHub trends')
|
||||
|
@ -1,4 +1,4 @@
|
||||
describe('trend:producthunt', async () => {
|
||||
describe('trend:producthunt', () => {
|
||||
test('requests Product Hunt', async () => {
|
||||
global.nlu.brain.execute = jest.fn()
|
||||
await global.nlu.process('What\'s trending on Product Hunt?')
|
||||
|
@ -1,4 +1,4 @@
|
||||
describe('videodownloader:youtube', async () => {
|
||||
describe('videodownloader:youtube', () => {
|
||||
test('requests YouTube', async () => {
|
||||
global.nlu.brain.execute = jest.fn()
|
||||
await global.nlu.process('Download new videos from YouTube')
|
||||
|
@ -93,7 +93,7 @@ export default () => new Promise(async (resolve, reject) => {
|
||||
if (!fs.existsSync(nlpModelPath) || !Object.keys(fs.readFileSync(nlpModelPath)).length) {
|
||||
report.can_text.v = false
|
||||
Object.keys(report).forEach((item) => { if (item.indexOf('stt') !== -1 || item.indexOf('tts') !== -1) report[item].v = false })
|
||||
log.error('NLP model not found or broken. Try to generate a new one: "npm run train expressions"\n')
|
||||
log.error('NLP model not found or broken. Try to generate a new one: "npm run train"\n')
|
||||
} else {
|
||||
log.success('Found and valid\n')
|
||||
}
|
||||
@ -103,7 +103,7 @@ export default () => new Promise(async (resolve, reject) => {
|
||||
log.info('Amazon Polly TTS')
|
||||
try {
|
||||
const json = JSON.parse(fs.readFileSync(amazonPath))
|
||||
if (json.accessKeyId === '' || json.secretAccessKey === '') {
|
||||
if (json.credentials.accessKeyId === '' || json.credentials.secretAccessKey === '') {
|
||||
report.can_amazon_polly_tts.v = false
|
||||
log.warning('Amazon Polly TTS is not yet configured\n')
|
||||
} else {
|
||||
|
37
scripts/commit-msg.js
Normal file
37
scripts/commit-msg.js
Normal file
@ -0,0 +1,37 @@
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
|
||||
import log from '@/helpers/log'
|
||||
|
||||
/**
|
||||
* This script is executed after "git commit" or "git merge" (Git hook https://git-scm.com/docs/githooks#_commit_msg)
|
||||
* it ensures the authenticity of commit messages
|
||||
*/
|
||||
log.info('Checking commit message...')
|
||||
|
||||
const commitEditMsgFile = '.git/COMMIT_EDITMSG'
|
||||
|
||||
if (fs.existsSync(commitEditMsgFile)) {
|
||||
try {
|
||||
const commitMessage = fs.readFileSync(commitEditMsgFile, 'utf8')
|
||||
const packagesDir = 'packages'
|
||||
const packages = fs.readdirSync(packagesDir)
|
||||
.filter((entity) => fs.statSync(path.join(packagesDir, entity)).isDirectory())
|
||||
const packagesScopeString = packages.map((pkg, i) => {
|
||||
if (packages.length === i + 1) return pkg
|
||||
return `${pkg}|`
|
||||
}).join('')
|
||||
|
||||
const regex = `(build|BREAKING|chore|ci|docs|feat|fix|perf|refactor|style|test)(\\((web app|server|hotword|package\\/(${packagesScopeString})))?\\)?: .{1,50}` // eslint-disable-line no-useless-escape
|
||||
|
||||
if (commitMessage.match(regex) !== null) {
|
||||
log.success('Commit message validated')
|
||||
} else {
|
||||
log.error(`Commit message does not match the format: ${regex}`)
|
||||
process.exit(1)
|
||||
}
|
||||
} catch (e) {
|
||||
log.error(e.message)
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
@ -1,19 +1,32 @@
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const os = require('os')
|
||||
const { execSync } = require('child_process')
|
||||
|
||||
/**
|
||||
* Trigger preinstall hook to remove DeepSpeech on Windows
|
||||
*/
|
||||
|
||||
console.info('\x1b[36m➡ %s\x1b[0m', 'Running Leon\'s installation...')
|
||||
|
||||
if (os.type().indexOf('Windows') !== -1) {
|
||||
const packageJsonPath = path.join(__dirname, '../../package.json')
|
||||
const packageJson = require(packageJsonPath) // eslint-disable-line global-require
|
||||
|
||||
console.warn('\x1b[33m❗ %s\x1b[0m', 'The Leon\'s voice offline mode is not available on Windows')
|
||||
console.info('\x1b[36m➡ %s\x1b[0m', 'Backing up package.json...')
|
||||
fs.copyFileSync('package.json', 'package.json.backup')
|
||||
console.log('\x1b[32m✔ %s\x1b[0m', 'package.json has been backed up')
|
||||
console.info('\x1b[36m➡ %s\x1b[0m', 'Removing DeepSpeech dependency... Please wait, this might take several minutes...')
|
||||
execSync('npm uninstall --save deepspeech')
|
||||
console.log('\x1b[32m✔ %s\x1b[0m', 'DeepSpeech dependency has been removed.')
|
||||
}
|
||||
|
||||
console.info('\x1b[36m➡ %s\x1b[0m', 'Running Leon\'s installation...')
|
||||
try {
|
||||
if (packageJson?.dependencies.deepspeech) {
|
||||
console.info('\x1b[36m➡ %s\x1b[0m', 'Removing DeepSpeech dependency...')
|
||||
|
||||
delete packageJson.dependencies.deepspeech
|
||||
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2))
|
||||
|
||||
console.log('\x1b[32m✔ %s\x1b[0m', 'DeepSpeech dependency has been removed.')
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('\x1b[31m✖ %s\x1b[0m', 'Failed to remove DeepSpeech dependency')
|
||||
}
|
||||
}
|
||||
|
@ -16,8 +16,8 @@ import loader from '@/helpers/loader'
|
||||
|
||||
try {
|
||||
loader.start()
|
||||
await command('npm run train expressions:en', { shell: true })
|
||||
const cmd = await command(`cross-env PIPENV_PIPFILE=bridges/python/Pipfile LEON_NODE_ENV=testing jest --silent --config=./test/e2e/modules/e2e.modules.jest.json packages/${pkg}/test/${module}.spec.js && npm run train expressions`, { shell: true })
|
||||
await command('npm run train en', { shell: true })
|
||||
const cmd = await command(`cross-env PIPENV_PIPFILE=bridges/python/Pipfile LEON_NODE_ENV=testing jest --silent --config=./test/e2e/modules/e2e.modules.jest.json packages/${pkg}/test/${module}.spec.js && npm run train`, { shell: true })
|
||||
|
||||
log.default(cmd.stdout)
|
||||
log.default(cmd.stderr)
|
||||
|
@ -11,74 +11,63 @@ import { langs } from '../core/langs.json'
|
||||
dotenv.config()
|
||||
|
||||
/**
|
||||
* Training script
|
||||
* Training expressions script
|
||||
*
|
||||
* npm run train expressions
|
||||
* npm run train expressions:en
|
||||
* npm run train [en or fr]
|
||||
*/
|
||||
export default () => new Promise(async (resolve, reject) => {
|
||||
const { argv } = process
|
||||
const packagesDir = 'packages'
|
||||
const modelFileName = 'server/src/data/leon-model.nlp'
|
||||
let type = (argv[2]) ? argv[2].toLowerCase() : 'expressions'
|
||||
let lang = ''
|
||||
|
||||
if (type.indexOf(':') !== -1) {
|
||||
[type, lang] = type.split(':')
|
||||
} else {
|
||||
lang = langs[process.env.LEON_LANG].short.toLowerCase().substr(0, 2)
|
||||
}
|
||||
const lang = argv[2]
|
||||
? argv[2].toLowerCase()
|
||||
: langs[process.env.LEON_LANG].short.toLowerCase().substr(0, 2)
|
||||
|
||||
try {
|
||||
if (type === 'expressions') {
|
||||
const dock = await dockStart({ use: ['Basic'] })
|
||||
const dock = await dockStart({ use: ['Basic'] })
|
||||
|
||||
const nlp = dock.get('nlp')
|
||||
nlp.settings.modelFileName = modelFileName
|
||||
nlp.settings.threshold = 0.8
|
||||
const nlp = dock.get('nlp')
|
||||
nlp.settings.modelFileName = modelFileName
|
||||
nlp.settings.threshold = 0.8
|
||||
|
||||
nlp.addLanguage(lang)
|
||||
nlp.addLanguage(lang)
|
||||
|
||||
const packages = fs.readdirSync(packagesDir)
|
||||
.filter((entity) => fs.statSync(path.join(packagesDir, entity)).isDirectory())
|
||||
let expressionsObj = { }
|
||||
const packages = fs.readdirSync(packagesDir)
|
||||
.filter((entity) => fs.statSync(path.join(packagesDir, entity)).isDirectory())
|
||||
let expressionsObj = { }
|
||||
|
||||
for (let i = 0; i < packages.length; i += 1) {
|
||||
log.info(`Training "${string.ucfirst(packages[i])}" package modules expressions...`)
|
||||
for (let i = 0; i < packages.length; i += 1) {
|
||||
log.info(`Training "${string.ucfirst(packages[i])}" package modules expressions...`)
|
||||
|
||||
expressionsObj = JSON.parse(fs.readFileSync(`${packagesDir}/${packages[i]}/data/expressions/${lang}.json`, 'utf8'))
|
||||
expressionsObj = JSON.parse(fs.readFileSync(`${packagesDir}/${packages[i]}/data/expressions/${lang}.json`, 'utf8'))
|
||||
|
||||
const modules = Object.keys(expressionsObj)
|
||||
for (let j = 0; j < modules.length; j += 1) {
|
||||
const module = modules[j]
|
||||
const actions = Object.keys(expressionsObj[module])
|
||||
const modules = Object.keys(expressionsObj)
|
||||
for (let j = 0; j < modules.length; j += 1) {
|
||||
const module = modules[j]
|
||||
const actions = Object.keys(expressionsObj[module])
|
||||
|
||||
for (let k = 0; k < actions.length; k += 1) {
|
||||
const action = actions[k]
|
||||
const exprs = expressionsObj[module][action].expressions
|
||||
for (let k = 0; k < actions.length; k += 1) {
|
||||
const action = actions[k]
|
||||
const exprs = expressionsObj[module][action].expressions
|
||||
|
||||
nlp.assignDomain(lang, `${module}.${action}`, packages[i])
|
||||
nlp.assignDomain(lang, `${module}.${action}`, packages[i])
|
||||
|
||||
for (let l = 0; l < exprs.length; l += 1) {
|
||||
nlp.addDocument(lang, exprs[l], `${module}.${action}`)
|
||||
}
|
||||
for (let l = 0; l < exprs.length; l += 1) {
|
||||
nlp.addDocument(lang, exprs[l], `${module}.${action}`)
|
||||
}
|
||||
|
||||
log.success(`"${string.ucfirst(module)}" module expressions trained`)
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
await nlp.train()
|
||||
|
||||
log.success(`NLP model saved in ${modelFileName}`)
|
||||
resolve()
|
||||
} catch (e) {
|
||||
log.error(`Failed to save NLP model: ${e}`)
|
||||
reject()
|
||||
log.success(`"${string.ucfirst(module)}" module expressions trained`)
|
||||
}
|
||||
} else {
|
||||
log.error(`"${type}" training type is unknown. Try "npm run train expressions"`)
|
||||
}
|
||||
|
||||
try {
|
||||
await nlp.train()
|
||||
|
||||
log.success(`NLP model saved in ${modelFileName}`)
|
||||
resolve()
|
||||
} catch (e) {
|
||||
log.error(`Failed to save NLP model: ${e}`)
|
||||
reject()
|
||||
}
|
||||
} catch (e) {
|
||||
|
@ -86,7 +86,15 @@ class Ner {
|
||||
|
||||
if (condition.type === 'between') {
|
||||
// e.g. list.addBetweenCondition('en', 'list', 'create a', 'list')
|
||||
this.ner[conditionMethod](lang, entity.name, condition.from, condition.to)
|
||||
if (Array.isArray(condition.from) && Array.isArray(condition.to)) {
|
||||
const { from, to } = condition
|
||||
|
||||
from.forEach((word, index) => {
|
||||
this.ner[conditionMethod](lang, entity.name, word, to[index])
|
||||
})
|
||||
} else {
|
||||
this.ner[conditionMethod](lang, entity.name, condition.from, condition.to)
|
||||
}
|
||||
} else if (condition.type.indexOf('after') !== -1) {
|
||||
this.ner[conditionMethod](lang, entity.name, condition.from)
|
||||
} else if (condition.type.indexOf('before') !== -1) {
|
||||
|
@ -28,7 +28,7 @@ class Nlu {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
if (!fs.existsSync(nlpModel)) {
|
||||
log.title('NLU')
|
||||
reject({ type: 'warning', obj: new Error('The NLP model does not exist, please run: npm run train expressions') })
|
||||
reject({ type: 'warning', obj: new Error('The NLP model does not exist, please run: npm run train') })
|
||||
} else {
|
||||
log.title('NLU')
|
||||
|
||||
@ -65,7 +65,7 @@ class Nlu {
|
||||
this.brain.talk(`${this.brain.wernicke('random_errors')}!`)
|
||||
this.brain.socket.emit('is-typing', false)
|
||||
|
||||
log.error('The NLP model is missing, please rebuild the project or if you are in dev run: npm run train expressions')
|
||||
log.error('The NLP model is missing, please rebuild the project or if you are in dev run: npm run train')
|
||||
|
||||
return false
|
||||
}
|
||||
|
@ -12,6 +12,7 @@
|
||||
"<rootDir>/test/paths.setup.js"
|
||||
],
|
||||
"setupFilesAfterEnv": [
|
||||
"jest-extended/all",
|
||||
"<rootDir>/test/e2e/modules/e2e.modules.setup.js"
|
||||
]
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ describe('NLU modules', () => {
|
||||
process.env.LEON_LANG = langKeys[i]
|
||||
|
||||
// Generate new NLP model for the tested language
|
||||
await command(`npm run train expressions:${lang.short}`, { shell: true })
|
||||
await command(`npm run train ${lang.short}`, { shell: true })
|
||||
// Load the new NLP model
|
||||
await nlu.loadModel(global.paths.nlp_model)
|
||||
})
|
||||
|
@ -61,7 +61,7 @@ describe('server', () => {
|
||||
})
|
||||
|
||||
describe('connection()', () => {
|
||||
test('initializes main nodes', async (done) => {
|
||||
test('initializes main nodes', async () => {
|
||||
const server = new Server()
|
||||
|
||||
await server.init()
|
||||
@ -88,12 +88,12 @@ describe('server', () => {
|
||||
expect(server.nlu).not.toBeEmpty()
|
||||
expect(server.asr).not.toBeEmpty()
|
||||
|
||||
setTimeout(() => {
|
||||
/* setTimeout(() => {
|
||||
ee.emit('query', { client: 'jest', value: 'Hello' })
|
||||
}, 50)
|
||||
|
||||
setTimeout(() => {
|
||||
expect(console.log.mock.calls[22][1]).toBe('Query found')
|
||||
expect(console.log.mock.calls[26][1]).toBe('Query found')
|
||||
console.log = jest.fn()
|
||||
}, 100)
|
||||
|
||||
@ -106,9 +106,7 @@ describe('server', () => {
|
||||
console.log = jest.fn()
|
||||
|
||||
await server.httpServer.close()
|
||||
|
||||
done()
|
||||
}, 200)
|
||||
}, 200) */
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@ -4,9 +4,11 @@ jest.useFakeTimers()
|
||||
|
||||
describe('loader helper', () => {
|
||||
describe('start()', () => {
|
||||
jest.useFakeTimers()
|
||||
jest.spyOn(global, 'setInterval')
|
||||
|
||||
test('starts spinner', () => {
|
||||
expect(loader.start()).toBeObject()
|
||||
jest.runTimersToTime(60000)
|
||||
expect(setInterval).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
})
|
||||
|
@ -12,6 +12,7 @@
|
||||
"<rootDir>/test/paths.setup.js"
|
||||
],
|
||||
"setupFilesAfterEnv": [
|
||||
"jest-extended/all",
|
||||
"<rootDir>/test/unit/unit.setup.js"
|
||||
],
|
||||
"coverageDirectory": "<rootDir>/test/coverage",
|
||||
|
@ -1,4 +1,3 @@
|
||||
import 'jest-extended'
|
||||
import moment from 'moment-timezone'
|
||||
|
||||
import expressions from '@/data/en.json'
|
||||
|
Loading…
Reference in New Issue
Block a user