Compare commits
200 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| bbb533f49f | |||
| bdff917e04 | |||
| 52cf4afbec | |||
| 0ef1ec9247 | |||
| aa862a6b5f | |||
| f10f310aef | |||
| 18b47f168a | |||
| f7ad05275b | |||
| d62e0cd56c | |||
| 1caa73a13a | |||
| 844af50008 | |||
| b26d924890 | |||
| da1b469f8d | |||
| 0189c74a0e | |||
| a0a4f9d7b0 | |||
| eeb1b07898 | |||
| 78e5f79bce | |||
| 764e815204 | |||
| 03d25f2a48 | |||
| aa36c8cb2a | |||
| 2146637022 | |||
| 0a4e0ed90d | |||
| ceeb5bd70e | |||
| f77343918d | |||
| e2984ea87e | |||
| 694d398d7b | |||
| a2bca433f6 | |||
| 60698704ca | |||
| 7d4e64d575 | |||
| 2c03efc167 | |||
| 539281110a | |||
| 3ed88544f8 | |||
| 9ee73ea5f9 | |||
| c934d0e30d | |||
| d9f0144e62 | |||
| 57923f83ee | |||
| a38eee71f0 | |||
| c8e03ec401 | |||
| 4ca32b5070 | |||
| d8660251af | |||
| 26af271edc | |||
| da49a4dd82 | |||
| cf02f0f91d | |||
| 2de95c4ef9 | |||
| 2434d36564 | |||
| 73d919868b | |||
| 39cbd7114e | |||
| a16ab4abfa | |||
| 6e12d2638d | |||
| 0d3c42beb2 | |||
| 66f65b25b4 | |||
| 3f85a93a03 | |||
| e9e9155366 | |||
| 30c9d3bce5 | |||
| dba5d90b94 | |||
| 0705659f3e | |||
| 4815651a1d | |||
| 71ebdc5d80 | |||
| 49ac3218f7 | |||
| 1c0c8080bf | |||
| 46f6c09739 | |||
| 93eb2d22b3 | |||
| c4d2524922 | |||
| 7482edde0a | |||
| 09b9a02284 | |||
| f895963ab9 | |||
| 637ab43626 | |||
| 811bb7ab44 | |||
| a65d330256 | |||
| 04cff622b2 | |||
| b2f260d04d | |||
| adda7bc6ac | |||
| fb936c45b6 | |||
| d0ade211ad | |||
| 90397f8029 | |||
| 7ee89d9e58 | |||
| 050fcec835 | |||
| f714a99108 | |||
| 5623c33d04 | |||
| 8d937b1e5f | |||
| 1613b12765 | |||
| db13c1b51e | |||
| 78e577114e | |||
| f5999bef99 | |||
| 1284a8f6aa | |||
| 1a89eec108 | |||
| dfb9b81c8b | |||
| 68ca55c82e | |||
| f68a338dec | |||
| 435170659e | |||
| 1a0e29e6dd | |||
| c9cf7d3ae8 | |||
| 0d4104b629 | |||
| c361682cab | |||
| 55b81a3c8f | |||
| c5e1ed8e86 | |||
| 4baf8f0d55 | |||
| 5a55397ef8 | |||
| 05200a195b | |||
| 7167849d6a | |||
| edfa90d820 | |||
| 3511452d93 | |||
| 1408f358c7 | |||
| 0297e1d22b | |||
| 10a17b0146 | |||
| bba60ea45d | |||
| 64e1e7da3e | |||
| 14e5bee7d6 | |||
| 2576987c44 | |||
| ea7d6c48db | |||
| 52f37fc3ed | |||
| 8cb0816f24 | |||
| ca59f02f4f | |||
| 7af761c5f6 | |||
| f2b75fc184 | |||
| 3bf457caef | |||
| 90b5596b76 | |||
| 93c0d6c83b | |||
| 9b5aa5f901 | |||
| bad92d3569 | |||
| 1f0e4d2260 | |||
| d460dc59f5 | |||
| eb64695697 | |||
| 308bebeb48 | |||
| bd71866342 | |||
| b55d58ec30 | |||
| 2cf4ef54c3 | |||
| 34a5e8bac1 | |||
| 502ec8ba2e | |||
| ac25897e9e | |||
| c44824c89d | |||
| 673de84936 | |||
| 78aa9c6ddc | |||
| ea2e5b9747 | |||
| ea1a33b51f | |||
| 7a441d50b9 | |||
| 364b74568e | |||
| 5f5cb1f55b | |||
| 4479fcd655 | |||
| ad56672819 | |||
| b4bcabbb9e | |||
| aaf1a1989b | |||
| 2025e366d2 | |||
| 201d1ce4e4 | |||
| 2d1e27926d | |||
| e449011f90 | |||
| 84b84453a7 | |||
| 00cee2d2fd | |||
| 78cce1970e | |||
| 977a822cc8 | |||
| 1558970619 | |||
| 86de211fa8 | |||
| 2923c6504b | |||
| 3e23950519 | |||
| 92eb32b4da | |||
| 754bd7380f | |||
| d32cda3663 | |||
| e175ea5c12 | |||
| 167c97120d | |||
| c8d2e8c985 | |||
| e73bd632f5 | |||
| 2a15434919 | |||
| b2c375861b | |||
| ae6fec335d | |||
| 16302ec6e4 | |||
| 4d03e1bb4e | |||
| 69ce669b4c | |||
| c512b422e7 | |||
| 2ad6541c3e | |||
| 379326d7c1 | |||
| 1359f5d210 | |||
| 64858ec6fe | |||
| 166175192d | |||
| 97de1d1c3f | |||
| 563792bd0a | |||
| 076db4c3eb | |||
| 02e1de8ffa | |||
| cc01bd18b2 | |||
| 2478adbaa2 | |||
| 45b177d0fb | |||
| f61e4f08a4 | |||
| c0deafcd69 | |||
| 0ad8b9e8e5 | |||
| eea6b0392d | |||
| 9845612c68 | |||
| d46ec1d3d5 | |||
| f1a65f53bc | |||
| 1410b72362 | |||
| e9245b522f | |||
| 636eb0f139 | |||
| 8645ef01fd | |||
| 18867bde89 | |||
| d061a6c4bf | |||
| e2ec76275a | |||
| 767bace201 | |||
| dbed559799 | |||
| 305d9cd581 | |||
| 212df695f2 | |||
| e70d0a0029 | |||
| 595fe78679 |
@@ -1,9 +0,0 @@
|
||||
__pycache__/
|
||||
**/dist/*
|
||||
**/build/
|
||||
**/node_modules/
|
||||
**/tmp/*
|
||||
**/src/.venv/*
|
||||
logs/*
|
||||
*.pyc
|
||||
.DS_Store
|
||||
@@ -8,6 +8,15 @@ LEON_LANG=en-US
|
||||
LEON_HOST=http://localhost
|
||||
LEON_PORT=1337
|
||||
|
||||
# Enable/disable LLM
|
||||
LEON_LLM=true
|
||||
# LLM provider
|
||||
LEON_LLM_PROVIDER=local
|
||||
# LLM provider API key (if not local)
|
||||
LEON_LLM_PROVIDER_API_KEY=
|
||||
# Enable/disable LLM Natural Language Generation
|
||||
LEON_LLM_NLG=true
|
||||
|
||||
# Time zone (current one by default)
|
||||
LEON_TIME_ZONE=
|
||||
|
||||
|
||||
+1
-4
@@ -18,10 +18,7 @@
|
||||
"browser": true
|
||||
},
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2021
|
||||
},
|
||||
"globals": {
|
||||
"io": true
|
||||
"ecmaVersion": "latest"
|
||||
},
|
||||
"plugins": ["@typescript-eslint", "unicorn", "import"],
|
||||
"ignorePatterns": "*.spec.js",
|
||||
|
||||
@@ -77,22 +77,6 @@ npm run dev:server
|
||||
npm run dev:app
|
||||
```
|
||||
|
||||
### Docker
|
||||
|
||||
```sh
|
||||
# Clone the repository
|
||||
git clone https://github.com/leon-ai/leon.git leon
|
||||
|
||||
# Go to the project root
|
||||
cd leon
|
||||
|
||||
# Build
|
||||
npm run docker:build
|
||||
|
||||
# Run the development server and the development web app
|
||||
npm run docker:dev
|
||||
```
|
||||
|
||||
## Versioning
|
||||
|
||||
- We use [Semantic Versioning](https://semver.org) for releases.
|
||||
@@ -125,7 +109,6 @@ Scopes define high-level nodes of Leon.
|
||||
|
||||
- bridge/python
|
||||
- bridge/nodejs
|
||||
- docker
|
||||
- hotword
|
||||
- scripts
|
||||
- server
|
||||
|
||||
@@ -16,7 +16,6 @@ If the bug is related to the setup, please submit the issue at: https://github.c
|
||||
- OS (or browser) version:
|
||||
- Node.js version:
|
||||
- Complete "leon check" (or "npm run check") output:
|
||||
- (if using Docker) Complete "npm run docker:check" output:
|
||||
- (optional) Leon skill version:
|
||||
|
||||
### Expected Behavior
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: 'npm'
|
||||
directory: '/'
|
||||
schedule:
|
||||
interval: 'weekly'
|
||||
day: 'friday'
|
||||
time: '22:00'
|
||||
commit-message:
|
||||
prefix: 'chore'
|
||||
include: 'scope'
|
||||
reviewers:
|
||||
- 'louistiti'
|
||||
@@ -13,7 +13,11 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-20.04, macos-latest, windows-latest]
|
||||
# @see https://github.com/actions/runner-images/tree/main/images/macos
|
||||
# Use macos-12 instead of macos-latest because the latter use ARM64 (M1) architecture
|
||||
os: [ubuntu-20.04, macos-12]
|
||||
# Temporarily disable Windows release
|
||||
# os: [ubuntu-20.04, macos-12, windows-latest]
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
|
||||
@@ -13,7 +13,9 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-20.04, macos-latest, windows-latest]
|
||||
# @see https://github.com/actions/runner-images/tree/main/images/macos
|
||||
# Use macos-12 instead of macos-latest because the latter use ARM64 (M1) architecture
|
||||
os: [ubuntu-20.04, macos-12, windows-latest]
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
|
||||
@@ -27,10 +27,12 @@ tcp_server/src/Pipfile.lock
|
||||
!tcp_server/**/.gitkeep
|
||||
!bridges/python/**/.gitkeep
|
||||
!bridges/nodejs/**/.gitkeep
|
||||
!core/data/models/llm/.gitkeep
|
||||
!**/*.sample*
|
||||
skills/**/src/settings.json
|
||||
skills/**/memory/*.json
|
||||
core/data/models/*.nlp
|
||||
core/data/models/llm/*
|
||||
package.json.backup
|
||||
.python-version
|
||||
schemas/**/*.json
|
||||
|
||||
+1
-1
@@ -6,6 +6,6 @@ if ! [ -x "$(command -v npm)" ]; then
|
||||
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
|
||||
npx ts-node scripts/commit-msg.js
|
||||
npx tsx scripts/commit-msg.js
|
||||
fi
|
||||
|
||||
|
||||
-60
@@ -1,60 +0,0 @@
|
||||
FROM ubuntu:20.04
|
||||
ENV IS_DOCKER true
|
||||
|
||||
# Replace shell with bash so we can source files
|
||||
RUN rm /bin/sh && ln -s /bin/bash /bin/sh
|
||||
|
||||
# Set debconf to run non-interactively
|
||||
RUN echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections
|
||||
|
||||
# Install base dependencies
|
||||
RUN apt-get update && apt-get install --yes -q --no-install-recommends \
|
||||
apt-transport-https \
|
||||
build-essential \
|
||||
ca-certificates \
|
||||
curl \
|
||||
git \
|
||||
wget \
|
||||
libssl-dev \
|
||||
openssl \
|
||||
libz-dev \
|
||||
zlib1g-dev \
|
||||
libbz2-dev \
|
||||
libreadline-dev \
|
||||
libsqlite3-dev \
|
||||
llvm \
|
||||
libncurses5-dev \
|
||||
xz-utils \
|
||||
tk-dev libxml2-dev \
|
||||
libxmlsec1-dev \
|
||||
libffi-dev \
|
||||
liblzma-dev \
|
||||
libgdbm-dev \
|
||||
libnss3-dev \
|
||||
libc6-dev
|
||||
|
||||
# Run the container as an unprivileged user
|
||||
RUN groupadd docker && useradd -g docker -s /bin/bash -m docker
|
||||
USER docker
|
||||
WORKDIR /home/docker
|
||||
|
||||
# Install Node.js with nvm
|
||||
ENV NVM_DIR /home/docker/.nvm
|
||||
ENV NODE_VERSION v16.18.0
|
||||
|
||||
RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.2/install.sh | bash
|
||||
RUN /bin/bash -c "source $NVM_DIR/nvm.sh && nvm install $NODE_VERSION && nvm use --delete-prefix $NODE_VERSION"
|
||||
|
||||
ENV NODE_PATH $NVM_DIR/versions/node/$NODE_VERSION/lib/node_modules
|
||||
ENV PATH $NVM_DIR/versions/node/$NODE_VERSION/bin:$PATH
|
||||
|
||||
# Install Leon
|
||||
WORKDIR /home/docker/leon
|
||||
USER root
|
||||
RUN chown -R docker /home/docker/leon
|
||||
USER docker
|
||||
COPY --chown=docker ./ ./
|
||||
RUN npm install
|
||||
RUN npm run build
|
||||
|
||||
CMD ["npm", "start"]
|
||||
@@ -50,7 +50,7 @@ Here is how LLMs may help Leon in the future:
|
||||
|
||||
- Intent fallback: when an utterance cannot match an intent, then rely on an LLM to provide results.
|
||||
- New named entity recognition engine: provide a better solution to extract entities from utterances such as fruits, numbers, cities, durations, persons, etc.
|
||||
- Skill features: let skills leverage LLMs to provide out-of-the-box NLP features such as summarization, translation, sentiment analysis and so on...
|
||||
- Skill features: let skills leverage LLMs to provide out-of-the-box NLP features such as summarization, knowledge base, translation, sentiment analysis and so on...
|
||||
- Skill building: LLMs can help to develop skills such as paraphrasing utterance samples, translate answers, convert code from our Python bridge to the upcoming JavaScript bridge and vice versa, etc.
|
||||
- More...
|
||||
|
||||
@@ -152,19 +152,6 @@ leon start
|
||||
# Hooray! Leon is running
|
||||
```
|
||||
|
||||
### Docker Installation
|
||||
|
||||
```sh
|
||||
# Install Leon
|
||||
leon create birth --docker
|
||||
|
||||
# Run
|
||||
leon start
|
||||
|
||||
# Go to http://localhost:1337
|
||||
# Hooray! Leon is running
|
||||
```
|
||||
|
||||
## 📚 Documentation
|
||||
|
||||
For full documentation, visit [docs.getleon.ai](https://docs.getleon.ai).
|
||||
|
||||
+37
-6
@@ -1,4 +1,4 @@
|
||||
@import url(https://fonts.googleapis.com/css?family=Open+Sans:400,600,700,800);
|
||||
@import url(https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,600,700);
|
||||
|
||||
html,
|
||||
body,
|
||||
@@ -83,7 +83,6 @@ video {
|
||||
padding: 0;
|
||||
border: 0;
|
||||
font-size: 100%;
|
||||
font: inherit;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
@@ -142,7 +141,21 @@ ul li {
|
||||
body {
|
||||
color: var(--white-color);
|
||||
background-color: var(--black-color);
|
||||
font-family: 'Open Sans', sans-serif;
|
||||
font-family:
|
||||
'Source Sans Pro',
|
||||
system-ui,
|
||||
-apple-system,
|
||||
BlinkMacSystemFont,
|
||||
'Segoe UI',
|
||||
Roboto,
|
||||
'Helvetica Neue',
|
||||
Arial,
|
||||
'Noto Sans',
|
||||
sans-serif,
|
||||
'Apple Color Emoji',
|
||||
'Segoe UI Emoji',
|
||||
'Segoe UI Symbol',
|
||||
'Noto Color Emoji';
|
||||
font-weight: 400;
|
||||
}
|
||||
body > * {
|
||||
@@ -187,6 +200,7 @@ footer {
|
||||
text-align: center;
|
||||
left: 50%;
|
||||
bottom: 0;
|
||||
line-height: 18px;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
@@ -202,9 +216,10 @@ input {
|
||||
padding-right: 39px;
|
||||
}
|
||||
|
||||
small {
|
||||
#tip {
|
||||
color: var(--white-color);
|
||||
font-size: 0.7em;
|
||||
line-height: 22px;
|
||||
font-size: 1.02em;
|
||||
}
|
||||
|
||||
.hide {
|
||||
@@ -287,6 +302,17 @@ small {
|
||||
.bubble-container.leon {
|
||||
text-align: left;
|
||||
}
|
||||
.show-more {
|
||||
margin: 3px;
|
||||
text-decoration: underline;
|
||||
}
|
||||
.show-more:hover {
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
}
|
||||
.show-all {
|
||||
max-height: 100% !important;
|
||||
}
|
||||
|
||||
.bubble {
|
||||
padding: 6px 12px;
|
||||
@@ -297,6 +323,9 @@ small {
|
||||
text-align: left;
|
||||
opacity: 0;
|
||||
animation: fadeIn 0.2s ease-in forwards;
|
||||
overflow: hidden;
|
||||
font-size: 1.4rem;
|
||||
line-height: 2rem;
|
||||
}
|
||||
#feed .me .bubble {
|
||||
background-color: #1c75db;
|
||||
@@ -331,7 +360,9 @@ small {
|
||||
padding: 2px 8px;
|
||||
font-size: inherit;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s, color 0.2s;
|
||||
transition:
|
||||
background-color 0.2s,
|
||||
color 0.2s;
|
||||
}
|
||||
.suggestion:hover {
|
||||
color: var(--black-color);
|
||||
|
||||
+5
-5
@@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
@@ -9,7 +9,6 @@
|
||||
</head>
|
||||
<body class="settingup">
|
||||
<main>
|
||||
<div id="root"></div>
|
||||
<div id="feed">
|
||||
<p id="no-bubble" class="hide">
|
||||
You can start to interact with Leon, don't be shy.
|
||||
@@ -28,15 +27,16 @@
|
||||
</div>
|
||||
<label for="utterance"></label>
|
||||
<input type="text" id="utterance" autocomplete="off" autofocus />
|
||||
<small>
|
||||
<span id="tip">
|
||||
Use <kbd>↑</kbd> <kbd>↓</kbd> to browse history; <kbd>↵</kbd> to
|
||||
submit;
|
||||
<kbd>alt + c to listen.</kbd>
|
||||
</small>
|
||||
<kbd>alt+c to listen.</kbd>
|
||||
</span>
|
||||
</div>
|
||||
</main>
|
||||
<footer>
|
||||
<div id="logo"></div>
|
||||
<br />
|
||||
<div id="version">
|
||||
<small>v</small>
|
||||
</div>
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
function App() {
|
||||
return (
|
||||
<>
|
||||
<p>Hello from React</p>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default App
|
||||
@@ -1,9 +0,0 @@
|
||||
import type React from 'react'
|
||||
|
||||
interface Props {
|
||||
children: React.ReactNode
|
||||
}
|
||||
|
||||
export function Button({ children }: Props) {
|
||||
return <button>{children}</button>
|
||||
}
|
||||
@@ -1,3 +1,16 @@
|
||||
import '@fontsource/source-sans-pro/200.css'
|
||||
import '@fontsource/source-sans-pro/300.css'
|
||||
import '@fontsource/source-sans-pro/400.css'
|
||||
import '@fontsource/source-sans-pro/600.css'
|
||||
import '@fontsource/source-sans-pro/700.css'
|
||||
import '@fontsource/source-sans-pro/900.css'
|
||||
import 'remixicon/fonts/remixicon.css'
|
||||
import '@leon-ai/aurora/style.css'
|
||||
|
||||
import { createRoot } from 'react-dom/client'
|
||||
import { createElement } from 'react'
|
||||
import * as auroraComponents from '@leon-ai/aurora'
|
||||
|
||||
export default class Chatbot {
|
||||
constructor() {
|
||||
this.et = new EventTarget()
|
||||
@@ -95,6 +108,29 @@ export default class Chatbot {
|
||||
|
||||
this.feed.appendChild(container).appendChild(bubble)
|
||||
|
||||
const root = createRoot(container)
|
||||
|
||||
const render = (component) => {
|
||||
if (component) {
|
||||
const reactComponent = auroraComponents[component.component]
|
||||
|
||||
if (
|
||||
component.props?.children &&
|
||||
Array.isArray(component.props.children)
|
||||
) {
|
||||
component.props.children = component.props.children.map((child) => {
|
||||
return render(child)
|
||||
})
|
||||
}
|
||||
|
||||
return createElement(reactComponent, component.props)
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof string === 'object') {
|
||||
root.render(render(string))
|
||||
}
|
||||
|
||||
if (save) {
|
||||
this.saveBubble(who, string)
|
||||
}
|
||||
+24
-24
@@ -1,9 +1,7 @@
|
||||
import { io } from 'socket.io-client'
|
||||
import React from 'react'
|
||||
import { createRoot } from 'react-dom/client'
|
||||
|
||||
import { Button } from './aurora/button'
|
||||
import Chatbot from './chatbot'
|
||||
import { INIT_MESSAGES } from './constants'
|
||||
|
||||
export default class Client {
|
||||
constructor(client, serverUrl, input, res) {
|
||||
@@ -34,6 +32,24 @@ export default class Client {
|
||||
return this._recorder
|
||||
}
|
||||
|
||||
async sendInitMessages() {
|
||||
for (let i = 0; i < INIT_MESSAGES.length; i++) {
|
||||
const messages = INIT_MESSAGES[i]
|
||||
const message = messages[Math.floor(Math.random() * messages.length)]
|
||||
const sendingDelay = Math.floor(Math.random() * 2000) + 1000
|
||||
const typingFactorDelay = Math.floor(Math.random() * 4) + 2
|
||||
|
||||
setTimeout(() => {
|
||||
this.chatbot.isTyping('leon', true)
|
||||
}, sendingDelay / typingFactorDelay)
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, sendingDelay))
|
||||
|
||||
this.chatbot.receivedFrom('leon', message)
|
||||
this.chatbot.isTyping('leon', false)
|
||||
}
|
||||
}
|
||||
|
||||
init(loader) {
|
||||
this.chatbot.init()
|
||||
|
||||
@@ -43,6 +59,10 @@ export default class Client {
|
||||
|
||||
this.socket.on('ready', () => {
|
||||
loader.stop()
|
||||
|
||||
if (this.chatbot.parsedBubbles?.length === 0) {
|
||||
this.sendInitMessages()
|
||||
}
|
||||
})
|
||||
|
||||
this.socket.on('answer', (data) => {
|
||||
@@ -67,27 +87,7 @@ export default class Client {
|
||||
})
|
||||
|
||||
this.socket.on('widget', (data) => {
|
||||
/**
|
||||
* TODO: widget: widget handler to core/skill; dynamic component rendering
|
||||
*/
|
||||
console.log('data', data)
|
||||
|
||||
const container = document.createElement('div')
|
||||
container.className = 'widget'
|
||||
this.chatbot.feed.appendChild(container)
|
||||
|
||||
const root = createRoot(container)
|
||||
|
||||
// TODO: widget: pass props and dynamic component loading according to type
|
||||
const widgets = {
|
||||
Button: (options) => {
|
||||
return Button({
|
||||
children: options.text
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
root.render(widgets[data.type](data.options))
|
||||
this.chatbot.createBubble('leon', data)
|
||||
})
|
||||
|
||||
this.socket.on('audio-forwarded', (data, cb) => {
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
export const INIT_MESSAGES = [
|
||||
[
|
||||
`Hello there! Glad to e-meet meet you, I'm Leon, your open-source personal assistant. While I'm still learning and improving, I promise to do my best to be helpful.`
|
||||
],
|
||||
[
|
||||
`<ul>
|
||||
<li>We've got lots in the works. Check out <a href="http://roadmap.getleon.ai/" target="_blank">our roadmap</a>.</li>
|
||||
<li>Stay updated on our progress by checking out our <a href="https://blog.getleon.ai/" target="_blank">blog</a>.</li>
|
||||
<li>You can also get updates straight to your inbox <a href="https://newsletter.getleon.ai/subscription/form" target="_blank">here</a>.</li>
|
||||
`
|
||||
],
|
||||
[
|
||||
`Come hang out with us <a href="https://discord.gg/MNQqqKg" target="_blank">on Discord</a>! Once we release our official version, our community will be working together to build new skills for me. You won't want to miss out on the fun!`
|
||||
],
|
||||
[
|
||||
`Just so you know, my creator is working tirelessly to improve my skills and features, dedicating 75% of his free time to the project on top of his full-time job. If you'd like to help speed up my development, you can sponsor his work by clicking on this link: <strong><a href='http://sponsor.getleon.ai/' target='_blank'>sponsor.getleon.ai</a></strong>. Your support would mean a lot to us. Thank you for choosing me as your assistant!`
|
||||
]
|
||||
]
|
||||
@@ -1,19 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"useDefineForClassFields": true,
|
||||
"skipLibCheck": true,
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"jsx": "react-jsx",
|
||||
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noFallthroughCasesInSwitch": true
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import { INTENT_OBJECT } from '@bridge/constants'
|
||||
action,
|
||||
lang,
|
||||
utterance,
|
||||
new_utterance,
|
||||
current_entities,
|
||||
entities,
|
||||
current_resolvers,
|
||||
@@ -20,6 +21,7 @@ import { INTENT_OBJECT } from '@bridge/constants'
|
||||
const params: ActionParams = {
|
||||
lang,
|
||||
utterance,
|
||||
new_utterance,
|
||||
current_entities,
|
||||
entities,
|
||||
current_resolvers,
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
import { Widget } from '../widget'
|
||||
import { type ButtonProps } from '@leon-ai/aurora'
|
||||
|
||||
// TODO: contains the button API. rendering engine <-> SDK
|
||||
interface ButtonOptions {
|
||||
text: string
|
||||
}
|
||||
import { WidgetComponent } from '../widget-component'
|
||||
|
||||
export class Button extends Widget<ButtonOptions> {
|
||||
public constructor(options: ButtonOptions) {
|
||||
super(options)
|
||||
export class Button extends WidgetComponent<ButtonProps> {
|
||||
constructor(props: ButtonProps) {
|
||||
super(props)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
import { type CardProps } from '@leon-ai/aurora'
|
||||
|
||||
import { WidgetComponent } from '../widget-component'
|
||||
|
||||
export class Card extends WidgetComponent<CardProps> {
|
||||
constructor(props: CardProps) {
|
||||
super(props)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import { type CheckboxProps } from '@leon-ai/aurora'
|
||||
|
||||
import { WidgetComponent } from '../widget-component'
|
||||
|
||||
export class Checkbox extends WidgetComponent<CheckboxProps> {
|
||||
constructor(props: CheckboxProps) {
|
||||
super(props)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import { type CircularProgressProps } from '@leon-ai/aurora'
|
||||
|
||||
import { WidgetComponent } from '../widget-component'
|
||||
|
||||
export class CircularProgress extends WidgetComponent<CircularProgressProps> {
|
||||
constructor(props: CircularProgressProps) {
|
||||
super(props)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import { type FlexboxProps } from '@leon-ai/aurora'
|
||||
|
||||
import { WidgetComponent } from '../widget-component'
|
||||
|
||||
export class Flexbox extends WidgetComponent<FlexboxProps> {
|
||||
constructor(props: FlexboxProps) {
|
||||
super(props)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import { type IconButtonProps } from '@leon-ai/aurora'
|
||||
|
||||
import { WidgetComponent } from '../widget-component'
|
||||
|
||||
export class IconButton extends WidgetComponent<IconButtonProps> {
|
||||
constructor(props: IconButtonProps) {
|
||||
super(props)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import { type IconProps } from '@leon-ai/aurora'
|
||||
|
||||
import { WidgetComponent } from '../widget-component'
|
||||
|
||||
export class Icon extends WidgetComponent<IconProps> {
|
||||
constructor(props: IconProps) {
|
||||
super(props)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import { type ImageProps } from '@leon-ai/aurora'
|
||||
|
||||
import { WidgetComponent } from '../widget-component'
|
||||
|
||||
export class Image extends WidgetComponent<ImageProps> {
|
||||
constructor(props: ImageProps) {
|
||||
super(props)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
export * from './button'
|
||||
export * from './card'
|
||||
export * from './checkbox'
|
||||
export * from './circular-progress'
|
||||
export * from './flexbox'
|
||||
export * from './icon'
|
||||
export * from './icon-button'
|
||||
export * from './image'
|
||||
export * from './link'
|
||||
export * from './list'
|
||||
export * from './list-header'
|
||||
export * from './list-item'
|
||||
export * from './loader'
|
||||
export * from './progress'
|
||||
export * from './radio'
|
||||
export * from './radio-group'
|
||||
export * from './scroll-container'
|
||||
export * from './select'
|
||||
export * from './select-option'
|
||||
export * from './slider'
|
||||
export * from './status'
|
||||
export * from './switch'
|
||||
export * from './tab'
|
||||
export * from './tab-content'
|
||||
export * from './tab-group'
|
||||
export * from './tab-list'
|
||||
export * from './text'
|
||||
export * from './text-input'
|
||||
export * from './widget-wrapper'
|
||||
@@ -0,0 +1,9 @@
|
||||
import { type LinkProps } from '@leon-ai/aurora'
|
||||
|
||||
import { WidgetComponent } from '../widget-component'
|
||||
|
||||
export class Link extends WidgetComponent<LinkProps> {
|
||||
constructor(props: LinkProps) {
|
||||
super(props)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import { type ListHeaderProps } from '@leon-ai/aurora'
|
||||
|
||||
import { WidgetComponent } from '../widget-component'
|
||||
|
||||
export class ListHeader extends WidgetComponent<ListHeaderProps> {
|
||||
constructor(props: ListHeaderProps) {
|
||||
super(props)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import { type ListItemProps } from '@leon-ai/aurora'
|
||||
|
||||
import { WidgetComponent } from '../widget-component'
|
||||
|
||||
export class ListItem extends WidgetComponent<ListItemProps> {
|
||||
constructor(props: ListItemProps) {
|
||||
super(props)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import { type ListProps } from '@leon-ai/aurora'
|
||||
|
||||
import { WidgetComponent } from '../widget-component'
|
||||
|
||||
export class List extends WidgetComponent<ListProps> {
|
||||
constructor(props: ListProps) {
|
||||
super(props)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import { type LoaderProps } from '@leon-ai/aurora'
|
||||
|
||||
import { WidgetComponent } from '../widget-component'
|
||||
|
||||
export class Loader extends WidgetComponent<LoaderProps> {
|
||||
constructor(props: LoaderProps) {
|
||||
super(props)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import { type ProgressProps } from '@leon-ai/aurora'
|
||||
|
||||
import { WidgetComponent } from '../widget-component'
|
||||
|
||||
export class Progress extends WidgetComponent<ProgressProps> {
|
||||
constructor(props: ProgressProps) {
|
||||
super(props)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import { type RadioGroupProps } from '@leon-ai/aurora'
|
||||
|
||||
import { WidgetComponent } from '../widget-component'
|
||||
|
||||
export class RadioGroup extends WidgetComponent<RadioGroupProps> {
|
||||
constructor(props: RadioGroupProps) {
|
||||
super(props)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import { type RadioProps } from '@leon-ai/aurora'
|
||||
|
||||
import { WidgetComponent } from '../widget-component'
|
||||
|
||||
export class Radio extends WidgetComponent<RadioProps> {
|
||||
constructor(props: RadioProps) {
|
||||
super(props)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import { type ScrollContainerProps } from '@leon-ai/aurora'
|
||||
|
||||
import { WidgetComponent } from '../widget-component'
|
||||
|
||||
export class ScrollContainer extends WidgetComponent<ScrollContainerProps> {
|
||||
constructor(props: ScrollContainerProps) {
|
||||
super(props)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import { type SelectOptionProps } from '@leon-ai/aurora'
|
||||
|
||||
import { WidgetComponent } from '../widget-component'
|
||||
|
||||
export class SelectOption extends WidgetComponent<SelectOptionProps> {
|
||||
constructor(props: SelectOptionProps) {
|
||||
super(props)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import { type SelectProps } from '@leon-ai/aurora'
|
||||
|
||||
import { WidgetComponent } from '../widget-component'
|
||||
|
||||
export class Select extends WidgetComponent<SelectProps> {
|
||||
constructor(props: SelectProps) {
|
||||
super(props)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import { type SliderProps } from '@leon-ai/aurora'
|
||||
|
||||
import { WidgetComponent } from '../widget-component'
|
||||
|
||||
export class Slider extends WidgetComponent<SliderProps> {
|
||||
constructor(props: SliderProps) {
|
||||
super(props)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import { type StatusProps } from '@leon-ai/aurora'
|
||||
|
||||
import { WidgetComponent } from '../widget-component'
|
||||
|
||||
export class Status extends WidgetComponent<StatusProps> {
|
||||
constructor(props: StatusProps) {
|
||||
super(props)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import { type SwitchProps } from '@leon-ai/aurora'
|
||||
|
||||
import { WidgetComponent } from '../widget-component'
|
||||
|
||||
export class Switch extends WidgetComponent<SwitchProps> {
|
||||
constructor(props: SwitchProps) {
|
||||
super(props)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import { type TabContentProps } from '@leon-ai/aurora'
|
||||
|
||||
import { WidgetComponent } from '../widget-component'
|
||||
|
||||
export class TabContent extends WidgetComponent<TabContentProps> {
|
||||
constructor(props: TabContentProps) {
|
||||
super(props)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import { type TabGroupProps } from '@leon-ai/aurora'
|
||||
|
||||
import { WidgetComponent } from '../widget-component'
|
||||
|
||||
export class TabGroup extends WidgetComponent<TabGroupProps> {
|
||||
constructor(props: TabGroupProps) {
|
||||
super(props)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import { type TabListProps } from '@leon-ai/aurora'
|
||||
|
||||
import { WidgetComponent } from '../widget-component'
|
||||
|
||||
export class TabList extends WidgetComponent<TabListProps> {
|
||||
constructor(props: TabListProps) {
|
||||
super(props)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import { type TabProps } from '@leon-ai/aurora'
|
||||
|
||||
import { WidgetComponent } from '../widget-component'
|
||||
|
||||
export class Tab extends WidgetComponent<TabProps> {
|
||||
constructor(props: TabProps) {
|
||||
super(props)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import { type TextInputProps } from '@leon-ai/aurora'
|
||||
|
||||
import { WidgetComponent } from '../widget-component'
|
||||
|
||||
export class TextInput extends WidgetComponent<TextInputProps> {
|
||||
constructor(props: TextInputProps) {
|
||||
super(props)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import { type TextProps } from '@leon-ai/aurora'
|
||||
|
||||
import { WidgetComponent } from '../widget-component'
|
||||
|
||||
export class Text extends WidgetComponent<TextProps> {
|
||||
constructor(props: TextProps) {
|
||||
super(props)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import { type WidgetWrapperProps } from '@leon-ai/aurora'
|
||||
|
||||
import { WidgetComponent } from '../widget-component'
|
||||
|
||||
export class WidgetWrapper extends WidgetComponent<WidgetWrapperProps> {
|
||||
constructor(props: WidgetWrapperProps) {
|
||||
super(props)
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import type {
|
||||
AnswerConfig
|
||||
} from '@sdk/types'
|
||||
import { INTENT_OBJECT, SKILL_CONFIG } from '@bridge/constants'
|
||||
import { WidgetWrapper } from '@sdk/aurora'
|
||||
|
||||
class Leon {
|
||||
private static instance: Leon
|
||||
@@ -22,78 +23,71 @@ class Leon {
|
||||
* @example setAnswerData('key', { name: 'Leon' })
|
||||
*/
|
||||
public setAnswerData(
|
||||
answerKey: string | undefined,
|
||||
answerKey: string,
|
||||
data: AnswerData = null
|
||||
): AnswerConfig | null | undefined {
|
||||
if (answerKey) {
|
||||
try {
|
||||
// In case the answer key is a raw answer
|
||||
if (SKILL_CONFIG.answers == null || !SKILL_CONFIG.answers[answerKey]) {
|
||||
return answerKey
|
||||
}
|
||||
|
||||
const answers = SKILL_CONFIG.answers[answerKey] ?? ''
|
||||
let answer: AnswerConfig
|
||||
|
||||
if (Array.isArray(answers)) {
|
||||
answer = answers[Math.floor(Math.random() * answers.length)] ?? ''
|
||||
} else {
|
||||
answer = answers
|
||||
}
|
||||
|
||||
if (data) {
|
||||
for (const key in data) {
|
||||
// In case the answer needs speech and text differentiation
|
||||
if (typeof answer !== 'string' && answer.text) {
|
||||
answer.text = answer.text.replaceAll(
|
||||
`%${key}%`,
|
||||
String(data[key])
|
||||
)
|
||||
answer.speech = answer.speech.replaceAll(
|
||||
`%${key}%`,
|
||||
String(data[key])
|
||||
)
|
||||
} else {
|
||||
answer = (answer as string).replaceAll(
|
||||
`%${key}%`,
|
||||
String(data[key])
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (SKILL_CONFIG.variables) {
|
||||
const { variables } = SKILL_CONFIG
|
||||
|
||||
for (const key in variables) {
|
||||
// In case the answer needs speech and text differentiation
|
||||
if (typeof answer !== 'string' && answer.text) {
|
||||
answer.text = answer.text.replaceAll(
|
||||
`%${key}%`,
|
||||
String(variables[key])
|
||||
)
|
||||
answer.speech = answer.speech.replaceAll(
|
||||
`%${key}%`,
|
||||
String(variables[key])
|
||||
)
|
||||
} else {
|
||||
answer = (answer as string).replaceAll(
|
||||
`%${key}%`,
|
||||
String(variables[key])
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return answer
|
||||
} catch (e) {
|
||||
console.error('Error while setting answer data:', e)
|
||||
|
||||
return null
|
||||
): AnswerConfig {
|
||||
try {
|
||||
// In case the answer key is a raw answer
|
||||
if (SKILL_CONFIG.answers == null || !SKILL_CONFIG.answers[answerKey]) {
|
||||
return answerKey
|
||||
}
|
||||
}
|
||||
|
||||
return undefined
|
||||
const answers = SKILL_CONFIG.answers[answerKey] ?? ''
|
||||
let answer: AnswerConfig
|
||||
|
||||
if (Array.isArray(answers)) {
|
||||
answer = answers[Math.floor(Math.random() * answers.length)] ?? ''
|
||||
} else {
|
||||
answer = answers
|
||||
}
|
||||
|
||||
if (data != null) {
|
||||
for (const key in data) {
|
||||
// In case the answer needs speech and text differentiation
|
||||
if (typeof answer !== 'string' && answer.text) {
|
||||
answer.text = answer.text.replaceAll(`%${key}%`, String(data[key]))
|
||||
answer.speech = answer.speech.replaceAll(
|
||||
`%${key}%`,
|
||||
String(data[key])
|
||||
)
|
||||
} else {
|
||||
answer = (answer as string).replaceAll(
|
||||
`%${key}%`,
|
||||
String(data[key])
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (SKILL_CONFIG.variables) {
|
||||
const { variables } = SKILL_CONFIG
|
||||
|
||||
for (const key in variables) {
|
||||
// In case the answer needs speech and text differentiation
|
||||
if (typeof answer !== 'string' && answer.text) {
|
||||
answer.text = answer.text.replaceAll(
|
||||
`%${key}%`,
|
||||
String(variables[key])
|
||||
)
|
||||
answer.speech = answer.speech.replaceAll(
|
||||
`%${key}%`,
|
||||
String(variables[key])
|
||||
)
|
||||
} else {
|
||||
answer = (answer as string).replaceAll(
|
||||
`%${key}%`,
|
||||
String(variables[key])
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return answer
|
||||
} catch (e) {
|
||||
console.error('Error while setting answer data:', e)
|
||||
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -112,13 +106,19 @@ class Leon {
|
||||
answerInput.widget && !answerInput.key
|
||||
? 'widget'
|
||||
: (answerInput.key as string),
|
||||
answer: this.setAnswerData(answerInput.key, answerInput.data) ?? '',
|
||||
answer:
|
||||
answerInput.key != null
|
||||
? this.setAnswerData(answerInput.key, answerInput.data)
|
||||
: '',
|
||||
core: answerInput.core
|
||||
}
|
||||
}
|
||||
|
||||
if (answerInput.widget) {
|
||||
answerObject.output.widget = answerInput.widget
|
||||
answerObject.output.widget = new WidgetWrapper({
|
||||
...answerInput.widget.wrapperProps,
|
||||
children: [answerInput.widget.render()]
|
||||
})
|
||||
}
|
||||
|
||||
// "Temporize" for the data buffer output on the core
|
||||
|
||||
@@ -24,6 +24,7 @@ export class Memory<T = unknown> {
|
||||
|
||||
if (this.name.includes(':') && this.name.split(':').length === 3) {
|
||||
this.isFromAnotherSkill = true
|
||||
|
||||
const [domainName, skillName, memoryName] = this.name.split(':')
|
||||
this.memoryPath = path.join(
|
||||
SKILLS_PATH,
|
||||
|
||||
@@ -38,7 +38,7 @@ interface NetworkResponse<ResponseData> {
|
||||
export class NetworkError<ResponseErrorData = unknown> extends Error {
|
||||
public readonly response: NetworkResponse<ResponseErrorData>
|
||||
|
||||
public constructor(response: NetworkResponse<ResponseErrorData>) {
|
||||
constructor(response: NetworkResponse<ResponseErrorData>) {
|
||||
super(`[NetworkError]: ${response.statusCode} ${response.data}`)
|
||||
this.response = response
|
||||
Object.setPrototypeOf(this, NetworkError.prototype)
|
||||
@@ -49,7 +49,7 @@ export class Network {
|
||||
private readonly options: NetworkOptions
|
||||
private axios: AxiosInstance
|
||||
|
||||
public constructor(options: NetworkOptions = {}) {
|
||||
constructor(options: NetworkOptions = {}) {
|
||||
this.options = options
|
||||
this.axios = axios.create({
|
||||
baseURL: this.options.baseURL
|
||||
|
||||
@@ -7,7 +7,7 @@ export class Settings<T extends Record<string, unknown>> {
|
||||
private readonly settingsPath: string
|
||||
private readonly settingsSamplePath: string
|
||||
|
||||
public constructor() {
|
||||
constructor() {
|
||||
this.settingsPath = path.join(SKILL_PATH, 'src', 'settings.json')
|
||||
this.settingsSamplePath = path.join(
|
||||
SKILL_PATH,
|
||||
|
||||
@@ -9,8 +9,12 @@ import type {
|
||||
} from '@/core/brain/types'
|
||||
import type { SkillAnswerConfigSchema } from '@/schemas/skill-schemas'
|
||||
|
||||
import type { Widget } from '@sdk/widget'
|
||||
|
||||
export type { ActionParams, IntentObject }
|
||||
|
||||
export * from '@/core/nlp/types'
|
||||
|
||||
export type ActionFunction = (params: ActionParams) => Promise<void>
|
||||
|
||||
/**
|
||||
@@ -18,7 +22,7 @@ export type ActionFunction = (params: ActionParams) => Promise<void>
|
||||
*/
|
||||
export interface Answer {
|
||||
key?: string
|
||||
widget?: unknown // TODO
|
||||
widget?: Widget
|
||||
data?: AnswerData
|
||||
core?: SkillAnswerCoreData
|
||||
}
|
||||
@@ -26,7 +30,7 @@ export interface TextAnswer extends Answer {
|
||||
key: string
|
||||
}
|
||||
export interface WidgetAnswer extends Answer {
|
||||
widget: unknown
|
||||
widget: Widget
|
||||
key?: string
|
||||
}
|
||||
export type AnswerData = Record<string, string | number> | null
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
export abstract class WidgetComponent<T = unknown> {
|
||||
public readonly component: string
|
||||
public readonly props: T
|
||||
|
||||
protected constructor(props: T) {
|
||||
this.component = this.constructor.name
|
||||
this.props = props
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,22 @@
|
||||
export abstract class Widget<T> {
|
||||
public readonly type: string
|
||||
public readonly options: T
|
||||
import { type WidgetWrapperProps } from '@leon-ai/aurora'
|
||||
|
||||
protected constructor(options: T) {
|
||||
this.type = this.constructor.name
|
||||
this.options = options
|
||||
}
|
||||
import { WidgetComponent } from '@sdk/widget-component'
|
||||
|
||||
export interface WidgetOptions<T = unknown> {
|
||||
wrapperProps?: Omit<WidgetWrapperProps, 'children'>
|
||||
params: T
|
||||
}
|
||||
|
||||
export abstract class Widget<T = unknown> {
|
||||
public wrapperProps: WidgetOptions<T>['wrapperProps']
|
||||
public params: WidgetOptions<T>['params']
|
||||
|
||||
protected constructor(options: WidgetOptions<T>) {
|
||||
if (options?.wrapperProps) {
|
||||
this.wrapperProps = options.wrapperProps
|
||||
}
|
||||
this.params = options.params
|
||||
}
|
||||
|
||||
public abstract render(): WidgetComponent<unknown>
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
export const VERSION = '1.0.0'
|
||||
export const VERSION = '1.2.0'
|
||||
|
||||
@@ -14,11 +14,6 @@
|
||||
"exactOptionalPropertyTypes": false,
|
||||
"declaration": true
|
||||
},
|
||||
"ts-node": {
|
||||
"swc": true,
|
||||
"require": ["tsconfig-paths/register"],
|
||||
"files": true
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ def main():
|
||||
params = {
|
||||
'lang': INTENT_OBJECT['lang'],
|
||||
'utterance': INTENT_OBJECT['utterance'],
|
||||
'new_utterance': INTENT_OBJECT['new_utterance'],
|
||||
'current_entities': INTENT_OBJECT['current_entities'],
|
||||
'entities': INTENT_OBJECT['entities'],
|
||||
'current_resolvers': INTENT_OBJECT['current_resolvers'],
|
||||
|
||||
@@ -1,9 +1,19 @@
|
||||
from ..widget import Widget
|
||||
from typing import Optional, TypedDict, Union, Literal, Any
|
||||
from ..widget_component import WidgetComponent
|
||||
|
||||
|
||||
# TODO: contains the button API. rendering engine <-> SDK
|
||||
class ButtonProps(TypedDict, total=False):
|
||||
type: Optional[Union[Literal['button'], Literal['submit'], Literal['reset']]]
|
||||
iconName: Optional[str]
|
||||
iconPosition: Optional[Union[Literal['left'], Literal['right']]]
|
||||
secondary: Optional[bool]
|
||||
danger: Optional[bool]
|
||||
light: Optional[bool]
|
||||
disabled: Optional[bool]
|
||||
loading: Optional[bool]
|
||||
children: Any
|
||||
|
||||
|
||||
class Button(Widget):
|
||||
def __init__(self, options):
|
||||
super().__init__(options)
|
||||
class Button(WidgetComponent[ButtonProps]):
|
||||
def __init__(self, props: ButtonProps):
|
||||
super().__init__(props)
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
from ..widget_component import WidgetComponent
|
||||
|
||||
|
||||
class Card(WidgetComponent[dict]):
|
||||
def __init__(self, props: dict):
|
||||
super().__init__(props)
|
||||
@@ -0,0 +1,6 @@
|
||||
from ..widget_component import WidgetComponent
|
||||
|
||||
|
||||
class Checkbox(WidgetComponent[dict]):
|
||||
def __init__(self, props: dict):
|
||||
super().__init__(props)
|
||||
@@ -0,0 +1,6 @@
|
||||
from ..widget_component import WidgetComponent
|
||||
|
||||
|
||||
class CircularProgress(WidgetComponent[dict]):
|
||||
def __init__(self, props: dict):
|
||||
super().__init__(props)
|
||||
@@ -0,0 +1,6 @@
|
||||
from ..widget_component import WidgetComponent
|
||||
|
||||
|
||||
class Flexbox(WidgetComponent[dict]):
|
||||
def __init__(self, props: dict):
|
||||
super().__init__(props)
|
||||
@@ -0,0 +1,6 @@
|
||||
from ..widget_component import WidgetComponent
|
||||
|
||||
|
||||
class Icon(WidgetComponent[dict]):
|
||||
def __init__(self, props: dict):
|
||||
super().__init__(props)
|
||||
@@ -0,0 +1,6 @@
|
||||
from ..widget_component import WidgetComponent
|
||||
|
||||
|
||||
class IconButton(WidgetComponent[dict]):
|
||||
def __init__(self, props: dict):
|
||||
super().__init__(props)
|
||||
@@ -0,0 +1,6 @@
|
||||
from ..widget_component import WidgetComponent
|
||||
|
||||
|
||||
class Image(WidgetComponent[dict]):
|
||||
def __init__(self, props: dict):
|
||||
super().__init__(props)
|
||||
@@ -0,0 +1,6 @@
|
||||
from ..widget_component import WidgetComponent
|
||||
|
||||
|
||||
class Link(WidgetComponent[dict]):
|
||||
def __init__(self, props: dict):
|
||||
super().__init__(props)
|
||||
@@ -0,0 +1,6 @@
|
||||
from ..widget_component import WidgetComponent
|
||||
|
||||
|
||||
class List(WidgetComponent[dict]):
|
||||
def __init__(self, props: dict):
|
||||
super().__init__(props)
|
||||
@@ -0,0 +1,6 @@
|
||||
from ..widget_component import WidgetComponent
|
||||
|
||||
|
||||
class ListHeader(WidgetComponent[dict]):
|
||||
def __init__(self, props: dict):
|
||||
super().__init__(props)
|
||||
@@ -0,0 +1,6 @@
|
||||
from ..widget_component import WidgetComponent
|
||||
|
||||
|
||||
class ListItem(WidgetComponent[dict]):
|
||||
def __init__(self, props: dict):
|
||||
super().__init__(props)
|
||||
@@ -0,0 +1,6 @@
|
||||
from ..widget_component import WidgetComponent
|
||||
|
||||
|
||||
class Loader(WidgetComponent[dict]):
|
||||
def __init__(self, props: dict):
|
||||
super().__init__(props)
|
||||
@@ -0,0 +1,6 @@
|
||||
from ..widget_component import WidgetComponent
|
||||
|
||||
|
||||
class Progress(WidgetComponent[dict]):
|
||||
def __init__(self, props: dict):
|
||||
super().__init__(props)
|
||||
@@ -0,0 +1,6 @@
|
||||
from ..widget_component import WidgetComponent
|
||||
|
||||
|
||||
class Radio(WidgetComponent[dict]):
|
||||
def __init__(self, props: dict):
|
||||
super().__init__(props)
|
||||
@@ -0,0 +1,6 @@
|
||||
from ..widget_component import WidgetComponent
|
||||
|
||||
|
||||
class RadioGroup(WidgetComponent[dict]):
|
||||
def __init__(self, props: dict):
|
||||
super().__init__(props)
|
||||
@@ -0,0 +1,6 @@
|
||||
from ..widget_component import WidgetComponent
|
||||
|
||||
|
||||
class ScrollContainer(WidgetComponent[dict]):
|
||||
def __init__(self, props: dict):
|
||||
super().__init__(props)
|
||||
@@ -0,0 +1,6 @@
|
||||
from ..widget_component import WidgetComponent
|
||||
|
||||
|
||||
class Select(WidgetComponent[dict]):
|
||||
def __init__(self, props: dict):
|
||||
super().__init__(props)
|
||||
@@ -0,0 +1,6 @@
|
||||
from ..widget_component import WidgetComponent
|
||||
|
||||
|
||||
class SelectOption(WidgetComponent[dict]):
|
||||
def __init__(self, props: dict):
|
||||
super().__init__(props)
|
||||
@@ -0,0 +1,6 @@
|
||||
from ..widget_component import WidgetComponent
|
||||
|
||||
|
||||
class Slider(WidgetComponent[dict]):
|
||||
def __init__(self, props: dict):
|
||||
super().__init__(props)
|
||||
@@ -0,0 +1,6 @@
|
||||
from ..widget_component import WidgetComponent
|
||||
|
||||
|
||||
class Switch(WidgetComponent[dict]):
|
||||
def __init__(self, props: dict):
|
||||
super().__init__(props)
|
||||
@@ -0,0 +1,6 @@
|
||||
from ..widget_component import WidgetComponent
|
||||
|
||||
|
||||
class Tab(WidgetComponent[dict]):
|
||||
def __init__(self, props: dict):
|
||||
super().__init__(props)
|
||||
@@ -0,0 +1,6 @@
|
||||
from ..widget_component import WidgetComponent
|
||||
|
||||
|
||||
class TabContent(WidgetComponent[dict]):
|
||||
def __init__(self, props: dict):
|
||||
super().__init__(props)
|
||||
@@ -0,0 +1,6 @@
|
||||
from ..widget_component import WidgetComponent
|
||||
|
||||
|
||||
class TabGroup(WidgetComponent[dict]):
|
||||
def __init__(self, props: dict):
|
||||
super().__init__(props)
|
||||
@@ -0,0 +1,6 @@
|
||||
from ..widget_component import WidgetComponent
|
||||
|
||||
|
||||
class TabList(WidgetComponent[dict]):
|
||||
def __init__(self, props: dict):
|
||||
super().__init__(props)
|
||||
@@ -0,0 +1,6 @@
|
||||
from ..widget_component import WidgetComponent
|
||||
|
||||
|
||||
class Text(WidgetComponent[dict]):
|
||||
def __init__(self, props: dict):
|
||||
super().__init__(props)
|
||||
@@ -0,0 +1,6 @@
|
||||
from ..widget_component import WidgetComponent
|
||||
|
||||
|
||||
class TextInput(WidgetComponent[dict]):
|
||||
def __init__(self, props: dict):
|
||||
super().__init__(props)
|
||||
@@ -0,0 +1,16 @@
|
||||
from typing import Optional, TypedDict, List
|
||||
from ..widget_component import WidgetComponent
|
||||
|
||||
|
||||
class WidgetWrapperProps(TypedDict, total=False):
|
||||
noPadding: Optional[bool]
|
||||
paddingTop: Optional[bool]
|
||||
paddingBottom: Optional[bool]
|
||||
paddingLeft: Optional[bool]
|
||||
paddingRight: Optional[bool]
|
||||
children: List[WidgetComponent]
|
||||
|
||||
|
||||
class WidgetWrapper(WidgetComponent[WidgetWrapperProps]):
|
||||
def __init__(self, props: WidgetWrapperProps):
|
||||
super().__init__(props)
|
||||
@@ -4,6 +4,8 @@ from typing import Union
|
||||
from time import sleep
|
||||
import json
|
||||
|
||||
from .aurora.widget_wrapper import WidgetWrapper
|
||||
|
||||
from .types import AnswerInput, AnswerData, AnswerConfig
|
||||
from ..constants import SKILL_CONFIG, INTENT_OBJECT
|
||||
|
||||
@@ -16,49 +18,45 @@ class Leon:
|
||||
Leon.instance = self
|
||||
|
||||
@staticmethod
|
||||
def set_answer_data(answer_key: Union[str, None], data: Union[AnswerData, None] = None) -> Union[str, AnswerConfig, None]:
|
||||
def set_answer_data(answer_key: str, data: Union[AnswerData, None] = None) -> Union[str, AnswerConfig]:
|
||||
"""
|
||||
Apply data to the answer
|
||||
:param answer_key: The answer key
|
||||
:param data: The data to apply
|
||||
"""
|
||||
if answer_key:
|
||||
try:
|
||||
# In case the answer key is a raw answer
|
||||
if SKILL_CONFIG.get('answers') is None or SKILL_CONFIG['answers'].get(answer_key) is None:
|
||||
return answer_key
|
||||
try:
|
||||
# In case the answer key is a raw answer
|
||||
if SKILL_CONFIG.get('answers') is None or SKILL_CONFIG['answers'].get(answer_key) is None:
|
||||
return answer_key
|
||||
|
||||
answers = SKILL_CONFIG['answers'].get(answer_key, '')
|
||||
if isinstance(answers, list):
|
||||
answer = answers[random.randrange(len(answers))]
|
||||
else:
|
||||
answer = answers
|
||||
answers = SKILL_CONFIG['answers'].get(answer_key, '')
|
||||
if isinstance(answers, list):
|
||||
answer = answers[random.randrange(len(answers))]
|
||||
else:
|
||||
answer = answers
|
||||
|
||||
if data:
|
||||
for key, value in data.items():
|
||||
# In case the answer needs speech and text differentiation
|
||||
if not isinstance(answer, str) and answer.get('text'):
|
||||
answer['text'] = answer['text'].replace('%{}%'.format(key), str(value))
|
||||
answer['speech'] = answer['speech'].replace('%{}%'.format(key), str(value))
|
||||
else:
|
||||
answer = answer.replace('%{}%'.format(key), str(value))
|
||||
if data:
|
||||
for key, value in data.items():
|
||||
# In case the answer needs speech and text differentiation
|
||||
if not isinstance(answer, str) and answer.get('text'):
|
||||
answer['text'] = answer['text'].replace('%{}%'.format(key), str(value))
|
||||
answer['speech'] = answer['speech'].replace('%{}%'.format(key), str(value))
|
||||
else:
|
||||
answer = answer.replace('%{}%'.format(key), str(value))
|
||||
|
||||
if SKILL_CONFIG.get('variables'):
|
||||
for key, value in SKILL_CONFIG['variables'].items():
|
||||
# In case the answer needs speech and text differentiation
|
||||
if not isinstance(answer, str) and answer.get('text'):
|
||||
answer['text'] = answer['text'].replace('%{}%'.format(key), str(value))
|
||||
answer['speech'] = answer['speech'].replace('%{}%'.format(key), str(value))
|
||||
else:
|
||||
answer = answer.replace('%{}%'.format(key), str(value))
|
||||
if SKILL_CONFIG.get('variables'):
|
||||
for key, value in SKILL_CONFIG['variables'].items():
|
||||
# In case the answer needs speech and text differentiation
|
||||
if not isinstance(answer, str) and answer.get('text'):
|
||||
answer['text'] = answer['text'].replace('%{}%'.format(key), str(value))
|
||||
answer['speech'] = answer['speech'].replace('%{}%'.format(key), str(value))
|
||||
else:
|
||||
answer = answer.replace('%{}%'.format(key), str(value))
|
||||
|
||||
return answer
|
||||
except Exception as e:
|
||||
print('Error while setting answer data:', e)
|
||||
|
||||
return None
|
||||
|
||||
return None
|
||||
return answer
|
||||
except Exception as e:
|
||||
print('Error while setting answer data:', e)
|
||||
raise e
|
||||
|
||||
def answer(self, answer_input: AnswerInput) -> None:
|
||||
"""
|
||||
@@ -66,23 +64,28 @@ class Leon:
|
||||
:param answer_input: The answer input
|
||||
"""
|
||||
try:
|
||||
key = answer_input.get('key')
|
||||
output = {
|
||||
'output': {
|
||||
'codes': 'widget' if answer_input.get('widget') and not answer_input.get('key') else answer_input.get('key'),
|
||||
'answer': self.set_answer_data(answer_input.get('key'), answer_input.get('data')) or '',
|
||||
'answer': self.set_answer_data(key, answer_input.get('data')) if key is not None else '',
|
||||
'core': answer_input.get('core')
|
||||
}
|
||||
}
|
||||
|
||||
if answer_input.get('widget'):
|
||||
output['output']['widget'] = answer_input['widget'].__dict__
|
||||
widget = answer_input.get('widget')
|
||||
if widget is not None:
|
||||
output['output']['widget'] = WidgetWrapper({
|
||||
**widget.wrapper_props,
|
||||
'children': [widget.render()]
|
||||
}).__dict__()
|
||||
|
||||
answer_object = {
|
||||
**INTENT_OBJECT,
|
||||
**output
|
||||
}
|
||||
|
||||
# Temporize for the data buffer output on the core
|
||||
# "Temporize" for the data buffer output on the core
|
||||
sleep(0.1)
|
||||
|
||||
sys.stdout.write(json.dumps(answer_object))
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
from typing import Dict, Any, Optional, Union, Literal, TypedDict
|
||||
|
||||
from .widget import Widget
|
||||
|
||||
|
||||
class NLUResultSentiment(TypedDict):
|
||||
vote: Optional[Union[Literal['positive'], Literal['neutral'], Literal['negative']]]
|
||||
@@ -19,6 +21,7 @@ class ExtraContextData(TypedDict):
|
||||
class ActionParams(TypedDict):
|
||||
lang: str
|
||||
utterance: str
|
||||
new_utterance: str
|
||||
current_entities: list[Any]
|
||||
entities: list[Any]
|
||||
current_resolvers: list[Any]
|
||||
@@ -39,7 +42,7 @@ class Answer(TypedDict):
|
||||
|
||||
class AnswerInput(TypedDict, total=False):
|
||||
key: Optional[str]
|
||||
widget: Any
|
||||
widget: Optional[Widget]
|
||||
data: Optional[AnswerData]
|
||||
core: Dict[str, Any]
|
||||
|
||||
|
||||
@@ -1,4 +1,24 @@
|
||||
class Widget:
|
||||
def __init__(self, options):
|
||||
self.type = type(self).__name__
|
||||
self.options = options
|
||||
from typing import Any, Optional, Generic, TypeVar
|
||||
from dataclasses import dataclass
|
||||
from abc import ABC, abstractmethod
|
||||
|
||||
from .widget_component import WidgetComponent
|
||||
from .aurora.widget_wrapper import WidgetWrapperProps
|
||||
|
||||
T = TypeVar('T')
|
||||
|
||||
|
||||
@dataclass
|
||||
class WidgetOptions(Generic[T]):
|
||||
wrapper_props: WidgetWrapperProps
|
||||
params: T
|
||||
|
||||
|
||||
class Widget(ABC, Generic[T]):
|
||||
def __init__(self, options: WidgetOptions[T]):
|
||||
self.wrapper_props = options.wrapper_props
|
||||
self.params = options.params
|
||||
|
||||
@abstractmethod
|
||||
def render(self) -> WidgetComponent:
|
||||
pass
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
from typing import TypeVar, Generic, TypedDict
|
||||
|
||||
T = TypeVar('T', TypedDict, dict)
|
||||
|
||||
|
||||
class WidgetComponent(Generic[T]):
|
||||
def __init__(self, props: T):
|
||||
self.component = type(self).__name__
|
||||
self.props = props
|
||||
|
||||
def __dict__(self):
|
||||
children_value = self.props.get('children')
|
||||
rest_of_values = {key: value for key, value in self.props.items() if key != 'children'}
|
||||
children = None
|
||||
if children_value is not None:
|
||||
if isinstance(children_value, list):
|
||||
children = []
|
||||
for child in children_value:
|
||||
if isinstance(child, WidgetComponent):
|
||||
children.append(child.__dict__())
|
||||
else:
|
||||
children.append(child)
|
||||
else:
|
||||
children = children_value
|
||||
result = {
|
||||
'component': self.component,
|
||||
'props': {
|
||||
**rest_of_values,
|
||||
'children': children
|
||||
}
|
||||
}
|
||||
return result
|
||||
@@ -9,7 +9,9 @@ options = {
|
||||
'includes': [
|
||||
'bs4',
|
||||
'requests',
|
||||
'timeit'
|
||||
'timeit',
|
||||
'dataclasses',
|
||||
'abc'
|
||||
],
|
||||
'include_files': [(requests.certs.where(), 'cacert.pem')]
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
__version__ = '1.1.0'
|
||||
__version__ = '1.3.0'
|
||||
|
||||
@@ -54,6 +54,19 @@
|
||||
"Sure, let's change the topic",
|
||||
"Aah, you want to change the subject, sure",
|
||||
"Mmmh, as you wish, let's switch conversation"
|
||||
],
|
||||
"llm_not_enabled": [
|
||||
"Sorry, I need my large language model to fulfill this request, but it's not enabled",
|
||||
"My large language model is not enabled, so I can't fulfill this request",
|
||||
"I can't fulfill this request because my large language model is not enabled",
|
||||
"Sorry, I need my large language model to answer this request, but it's not enabled",
|
||||
"My large language model is not enabled, so I can't answer this request"
|
||||
],
|
||||
"action_loop_stopped": [
|
||||
"Sure, let me know if you need anything else",
|
||||
"Alright, let me know what you need next",
|
||||
"Okay, let me know what I can do for you next",
|
||||
"Sure thing"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
{
|
||||
"$schema": "../../../../schemas/global-data/global-entity.json",
|
||||
"options": {
|
||||
"en-US": {
|
||||
"synonyms": ["English", "British", "American"]
|
||||
},
|
||||
"zh-CN": {
|
||||
"synonyms": ["Mandarin", "Chinese"]
|
||||
},
|
||||
"hi-IN": {
|
||||
"synonyms": ["Hindi", "Indian"]
|
||||
},
|
||||
"es-ES": {
|
||||
"synonyms": ["Spanish"]
|
||||
},
|
||||
"fr-FR": {
|
||||
"synonyms": ["French"]
|
||||
},
|
||||
"ar-SA": {
|
||||
"synonyms": ["Arabic"]
|
||||
},
|
||||
"ru-RU": {
|
||||
"synonyms": ["Russian"]
|
||||
},
|
||||
"pt-PT": {
|
||||
"synonyms": ["Portuguese"]
|
||||
},
|
||||
"bn-IN": {
|
||||
"synonyms": ["Bengali"]
|
||||
},
|
||||
"in-ID": {
|
||||
"synonyms": ["Indonesian"]
|
||||
},
|
||||
"ja-JP": {
|
||||
"synonyms": ["Japanese"]
|
||||
},
|
||||
"de-DE": {
|
||||
"synonyms": ["German"]
|
||||
},
|
||||
"ko-KR": {
|
||||
"synonyms": ["Korean"]
|
||||
},
|
||||
"tr-TR": {
|
||||
"synonyms": ["Turkish"]
|
||||
},
|
||||
"it-IT": {
|
||||
"synonyms": ["Italian"]
|
||||
},
|
||||
"vi-VN": {
|
||||
"synonyms": ["Vietnamese"]
|
||||
},
|
||||
"th-TH": {
|
||||
"synonyms": ["Thai"]
|
||||
},
|
||||
"nl-NL": {
|
||||
"synonyms": ["Dutch"]
|
||||
},
|
||||
"pl-PL": {
|
||||
"synonyms": ["Polish"]
|
||||
},
|
||||
"sv-SE": {
|
||||
"synonyms": ["Swedish"]
|
||||
},
|
||||
"da-DK": {
|
||||
"synonyms": ["Danish"]
|
||||
},
|
||||
"fi-FI": {
|
||||
"synonyms": ["Finnish"]
|
||||
},
|
||||
"no-NO": {
|
||||
"synonyms": ["Norwegian"]
|
||||
},
|
||||
"cs-CZ": {
|
||||
"synonyms": ["Czech"]
|
||||
},
|
||||
"hu-HU": {
|
||||
"synonyms": ["Hungarian"]
|
||||
},
|
||||
"el-GR": {
|
||||
"synonyms": ["Greek"]
|
||||
},
|
||||
"ro-RO": {
|
||||
"synonyms": ["Romanian"]
|
||||
},
|
||||
"uk-UA": {
|
||||
"synonyms": ["Ukrainian"]
|
||||
},
|
||||
"hr-HR": {
|
||||
"synonyms": ["Croatian"]
|
||||
},
|
||||
"sr-RS": {
|
||||
"synonyms": ["Serbian"]
|
||||
},
|
||||
"bg-BG": {
|
||||
"synonyms": ["Bulgarian"]
|
||||
},
|
||||
"sk-SK": {
|
||||
"synonyms": ["Slovak"]
|
||||
},
|
||||
"sl-SI": {
|
||||
"synonyms": ["Slovenian"]
|
||||
},
|
||||
"et-EE": {
|
||||
"synonyms": ["Estonian"]
|
||||
},
|
||||
"lv-LV": {
|
||||
"synonyms": ["Latvian"]
|
||||
},
|
||||
"lt-LT": {
|
||||
"synonyms": ["Lithuanian"]
|
||||
},
|
||||
"mt-MT": {
|
||||
"synonyms": ["Maltese"]
|
||||
},
|
||||
"is-IS": {
|
||||
"synonyms": ["Icelandic"]
|
||||
},
|
||||
"mk-MK": {
|
||||
"synonyms": ["Macedonian"]
|
||||
},
|
||||
"sq-AL": {
|
||||
"synonyms": ["Albanian"]
|
||||
},
|
||||
"bs-BA": {
|
||||
"synonyms": ["Bosnian"]
|
||||
},
|
||||
"ur-PK": {
|
||||
"synonyms": ["Urdu"]
|
||||
}
|
||||
}
|
||||
}
|
||||
+4
-2
@@ -3,7 +3,8 @@
|
||||
"en-US": {
|
||||
"short": "en",
|
||||
"min_confidence": 0.5,
|
||||
"fallbacks": []
|
||||
"fallbacks": [],
|
||||
"action_loop_stop_words": ["stop", "break", "exit"]
|
||||
},
|
||||
"fr-FR": {
|
||||
"short": "fr",
|
||||
@@ -15,7 +16,8 @@
|
||||
"skill": "welcome",
|
||||
"action": "run"
|
||||
}
|
||||
]
|
||||
],
|
||||
"action_loop_stop_words": ["stop", "break", "exit"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+143
-83
@@ -1,5 +1,57 @@
|
||||
{
|
||||
"endpoints": [
|
||||
{
|
||||
"method": "POST",
|
||||
"route": "/api/action/games/akinator/choose_thematic",
|
||||
"params": ["thematic"],
|
||||
"entitiesType": "trim"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/games/akinator/setup",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/games/akinator/guess",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/games/akinator/retry",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/games/guess_the_number/setup",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/games/guess_the_number/guess",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/games/guess_the_number/replay",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/games/rochambeau/start",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"route": "/api/action/games/rochambeau/play",
|
||||
"params": ["handsign"],
|
||||
"entitiesType": "trim"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/games/rochambeau/rematch",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"route": "/api/action/news/github_trends/run",
|
||||
@@ -58,89 +110,6 @@
|
||||
"params": ["todos", "list"],
|
||||
"entitiesType": "trim"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/social_communication/mbti/setup",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/social_communication/mbti/quiz",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/utilities/have_i_been_pwned/run",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"route": "/api/action/utilities/is_it_down/run",
|
||||
"params": ["url"],
|
||||
"entitiesType": "builtIn"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/utilities/speed_test/run",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/utilities/timekeeper/run",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"route": "/api/action/games/akinator/choose_thematic",
|
||||
"params": ["thematic"],
|
||||
"entitiesType": "trim"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/games/akinator/setup",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/games/akinator/guess",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/games/akinator/retry",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/games/guess_the_number/setup",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/games/guess_the_number/guess",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/games/guess_the_number/replay",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/games/rochambeau/start",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"route": "/api/action/games/rochambeau/play",
|
||||
"params": ["handsign"],
|
||||
"entitiesType": "trim"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/games/rochambeau/rematch",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/leon/age/run",
|
||||
@@ -171,6 +140,11 @@
|
||||
"route": "/api/action/leon/greeting/run",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/leon/help/help",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/leon/introduction/introduce_leon",
|
||||
@@ -210,6 +184,92 @@
|
||||
"method": "GET",
|
||||
"route": "/api/action/leon/welcome/run",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/unknown/widget-playground/run",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/social_communication/chit_chat/setup",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/social_communication/chit_chat/chat",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/social_communication/mbti/setup",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/social_communication/mbti/quiz",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/utilities/date_time/current_date_time",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/utilities/date_time/current_date",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/utilities/date_time/current_time",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/utilities/date_time/current_week_number",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/utilities/date_time/days_countdown",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/utilities/date_time/current_date_time_with_time_zone",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/utilities/have_i_been_pwned/run",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"route": "/api/action/utilities/is_it_down/run",
|
||||
"params": ["url"],
|
||||
"entitiesType": "builtIn"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/utilities/speed_test/run",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/utilities/translator-poc/setup",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/utilities/translator-poc/ready",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/utilities/translator-poc/translate",
|
||||
"params": []
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user