Compare commits

..

395 Commits

Author SHA1 Message Date
louistiti bbb533f49f ci(bridge/python): tmp disable Windows build 2024-05-09 00:14:03 +08:00
louistiti bdff917e04 feat(scripts): avoid LLM setup when running in CI 2024-05-08 19:21:52 +08:00
louistiti 52cf4afbec ci(python tcp server): set macOS runner to macos-12 2024-05-08 19:13:35 +08:00
louistiti 0ef1ec9247 ci(bridge/python): set macOS runner to macos-12 2024-05-08 19:12:51 +08:00
louistiti aa862a6b5f fix(scripts): TCP_SERVER_SRC_PATH to PYTHON_TCP_SERVER_SRC_PATH to set up Python env 2024-05-08 19:04:15 +08:00
louistiti f10f310aef build(bridge/nodejs): bump to 1.2.0 2024-05-08 18:53:30 +08:00
louistiti 18b47f168a build(bridge/python): bump to 1.3.0 2024-05-08 18:53:01 +08:00
louistiti f7ad05275b chore(server): clean up comments 2024-05-08 01:39:01 +08:00
louistiti d62e0cd56c feat(server): Groq support as LLM provider; agnostic LLM provider 2024-05-08 01:37:47 +08:00
louistiti 1caa73a13a fix(server): init LLM provider; completed 2024-05-07 18:53:37 +08:00
louistiti 844af50008 feat(server): LLM provider architecture (WIP) 2024-05-07 02:51:18 +08:00
louistiti b26d924890 feat(server): improve Paraphrase duty accuracy 2024-05-06 11:22:28 +08:00
louistiti da1b469f8d chore(server): remove unused countTokens method 2024-05-06 01:00:31 +08:00
louistiti 0189c74a0e feat(server): finalize Leon's personality and optimize LLM duties 2024-05-06 00:57:20 +08:00
louistiti a0a4f9d7b0 feat(server): emit socket message when a new update is available 2024-05-05 11:08:16 +08:00
louistiti eeb1b07898 feat(server): chit-chat duty and skill and more 2024-05-05 00:20:59 +08:00
louistiti 78e5f79bce feat(server): make Leon's personality more lively 2024-05-04 00:24:21 +08:00
louistiti 764e815204 feat(server): switch LLM duties back to using ChatWrapper instead of completions 2024-05-03 23:23:46 +08:00
louistiti 03d25f2a48 feat(server): Leon's personality done 2024-05-03 23:00:32 +08:00
louistiti aa36c8cb2a feat(server): personality support kick off; answer queue 2024-05-02 16:40:05 +08:00
louistiti 2146637022 feat(server): add paraphrase LLM duty to kick off personality attribution 2024-05-01 01:04:29 +08:00
louistiti 0a4e0ed90d feat(server): add confidence value in logs 2024-04-30 11:48:09 +08:00
louistiti ceeb5bd70e feat(server): use Lexi-Llama-3-8B-Uncensored-Q5_K_S as default LLM 2024-04-30 09:58:30 +08:00
louistiti f77343918d chore: upgrade socket.io-client to latest 2024-04-29 21:28:20 +08:00
louistiti e2984ea87e chore: upgrade socket.io to latest 2024-04-29 21:27:16 +08:00
louistiti 694d398d7b chore: upgrade fastify to latest 2024-04-29 21:25:25 +08:00
louistiti a2bca433f6 chore: upgrade dotenv to latest 2024-04-29 21:24:21 +08:00
louistiti 60698704ca chore: uninstall async npm package 2024-04-29 21:15:47 +08:00
louistiti 7d4e64d575 chore: upgrade tsc-watch to latest 2024-04-29 21:08:49 +08:00
louistiti 2c03efc167 refactor(server): warning message on explicit deactivation of LLM 2024-04-29 19:33:30 +08:00
louistiti 539281110a feat(server): allow explicit deactivation of LLM 2024-04-29 19:31:57 +08:00
louistiti 3ed88544f8 fix(server): specify correct minimem total/free RAM for LLM 2024-04-29 19:18:27 +08:00
louistiti 9ee73ea5f9 feat(server): map resolved slots to dialog answers 2024-04-29 18:37:20 +08:00
louistiti c934d0e30d feat(server): support dialog type action after slots filled 2024-04-29 18:02:41 +08:00
louistiti d9f0144e62 feat(server): action loop support 2024-04-29 11:25:18 +08:00
louistiti 57923f83ee fix(scripts): always update manifest on LLM setup 2024-04-28 10:10:57 +08:00
louistiti a38eee71f0 feat(server): set Phi-3 as default LLM 2024-04-26 15:14:28 +08:00
louistiti c8e03ec401 fix(server): utterance as expected_item loop indefinitely 2024-04-22 23:29:30 +08:00
louistiti 4ca32b5070 feat(scripts): fallback to mirror in case of error to download LLM 2024-04-22 00:00:46 +08:00
louistiti d8660251af feat: use mistral-7b-instruct-v0.2.Q4_K_S as final choice 2024-04-20 14:33:37 +08:00
louistiti 26af271edc feat(server): add utterance as expected_item type 2024-04-20 14:29:00 +08:00
louistiti da49a4dd82 feat(scripts): llama.cpp compatible build 2024-04-18 20:38:02 +08:00
louistiti cf02f0f91d feat(server): final LLM setup 2024-04-17 00:10:41 +08:00
louistiti 2de95c4ef9 feat(server): Gemma support (prototype) 2024-04-16 20:18:18 +08:00
louistiti 2434d36564 feat(skill/translator-poc): short translate action kick off 2024-04-15 20:42:11 +08:00
louistiti 73d919868b feat(server): LLM entities support 2024-04-14 17:41:39 +08:00
Théo LUDWIG 39cbd7114e fix(bridge/python): usage of dict instead of empty TypedDict to avoid types errors
We might in the future generate automatically from the TypeScript types, generate the Python types.
For the moment, it is not typed, so we use a dict.
2024-02-25 20:57:02 +01:00
louistiti a16ab4abfa feat(server): add response data to LLM inference endpoint 2024-02-19 18:31:56 +08:00
louistiti 6e12d2638d feat(server): verify whether LLM is enabled on inference 2024-02-19 18:30:10 +08:00
louistiti 0d3c42beb2 feat(server): implement PoC skill to validate LLM execution 2024-02-19 18:01:41 +08:00
louistiti 66f65b25b4 feat(server): expose LLM duties behind HTTP endpoint 2024-02-19 17:00:14 +08:00
louistiti 3f85a93a03 feat(server): LLM duties architecture + custom NER, summarization and translation duties 2024-02-18 23:43:25 +08:00
Louis Grenard e9e9155366 feat(server): bootstrap LLM TCP server <> LLM duties <> TCP client (tmp) 2024-02-15 00:13:16 +08:00
Louis Grenard 30c9d3bce5 feat(server): create updater 2024-02-14 17:37:21 +08:00
Louis Grenard dba5d90b94 chore: add LLM TCP server to Git commit message 2024-02-14 09:45:26 +08:00
Louis Grenard 0705659f3e fix(scripts): Python TCP server setup 2024-02-14 09:44:50 +08:00
louistiti 4815651a1d feat(server): bootstrap LLM TCP server (tmp) 2024-02-14 09:27:22 +08:00
louistiti 71ebdc5d80 refactor(server): prepare LLM TCP client connection 2024-02-13 18:51:45 +08:00
louistiti 49ac3218f7 feat(server): preparing LLM TCP server loading 2024-02-13 16:22:32 +08:00
louistiti 1c0c8080bf feat(scripts): download and compile llama.cpp 2024-02-08 21:05:06 +08:00
louistiti 46f6c09739 scripts(setup-llm): tell when LLM is up-to-date 2024-01-30 00:09:20 +08:00
louistiti 93eb2d22b3 scripts(setup-llm): set up LLM 2024-01-29 23:57:23 +08:00
louistiti c4d2524922 scripts(setup-llm): kick off LLM setup and unify common functions 2024-01-29 00:20:38 +08:00
louistiti 7482edde0a Merge branch 'widget-backbone' into mistral-llm-ner 2024-01-28 22:22:48 +08:00
louistiti 09b9a02284 feat(skill/random_number): widget rendering 2024-01-28 17:16:10 +08:00
Théo LUDWIG f895963ab9 feat(bridge/python): add Text component 2023-12-12 19:48:03 +01:00
Théo LUDWIG 637ab43626 feat(bridge/python): add TextInput component 2023-12-12 19:47:44 +01:00
Théo LUDWIG 811bb7ab44 feat(bridge/python): add Tab component 2023-12-12 19:47:22 +01:00
Théo LUDWIG a65d330256 feat(bridge/python): add TabList component 2023-12-12 19:47:02 +01:00
Théo LUDWIG 04cff622b2 feat(bridge/python): add TabGroup component 2023-12-12 19:46:04 +01:00
Théo LUDWIG b2f260d04d feat(bridge/python): add TabContent component 2023-12-12 19:45:29 +01:00
Théo LUDWIG adda7bc6ac feat(bridge/python): add Switch component 2023-12-12 19:45:03 +01:00
Théo LUDWIG fb936c45b6 feat(bridge/python): add Slider component 2023-12-12 19:44:33 +01:00
Théo LUDWIG d0ade211ad feat(bridge/python): add Select component 2023-12-12 19:44:11 +01:00
Théo LUDWIG 90397f8029 feat(bridge/python): add SelectOption component 2023-12-12 19:43:48 +01:00
Théo LUDWIG 7ee89d9e58 feat(bridge/python): add ScrollContainer component 2023-12-12 19:43:14 +01:00
Théo LUDWIG 050fcec835 feat(bridge/python): add Radio component 2023-12-12 19:42:32 +01:00
Théo LUDWIG f714a99108 feat(bridge/python): add RadioGroup component 2023-12-12 19:42:10 +01:00
Théo LUDWIG 5623c33d04 feat(bridge/python): add Progress component 2023-12-12 19:41:42 +01:00
Théo LUDWIG 8d937b1e5f feat(bridge/python): add Loader component 2023-12-12 19:41:16 +01:00
Théo LUDWIG 1613b12765 feat(bridge/python): add List component 2023-12-12 19:40:54 +01:00
Théo LUDWIG db13c1b51e feat(bridge/python): add ListItem component 2023-12-12 19:40:33 +01:00
Théo LUDWIG 78e577114e feat(bridge/python): add ListHeader component 2023-12-12 19:40:02 +01:00
Théo LUDWIG f5999bef99 feat(bridge/python): add Link component 2023-12-12 19:39:30 +01:00
Théo LUDWIG 1284a8f6aa feat(bridge/python): add Image component 2023-12-12 19:38:57 +01:00
Théo LUDWIG 1a89eec108 feat(bridge/python): add Icon component 2023-12-12 19:38:33 +01:00
Théo LUDWIG dfb9b81c8b feat(bridge/python): add IconButton component 2023-12-12 19:37:24 +01:00
Théo LUDWIG 68ca55c82e feat(bridge/python): add Flexbox component 2023-12-12 19:36:55 +01:00
Théo LUDWIG f68a338dec feat(bridge/python): add CircularProgress component 2023-12-12 19:36:11 +01:00
Théo LUDWIG 435170659e feat(bridge/python): add Checkbox component 2023-12-12 19:34:12 +01:00
Théo LUDWIG 1a0e29e6dd feat(bridge/python): add Card component 2023-12-12 19:33:25 +01:00
Théo LUDWIG c9cf7d3ae8 style: format python with autopep8 2023-12-12 19:30:54 +01:00
Théo LUDWIG 0d4104b629 feat(bridge/python): render widgets 2023-12-10 18:33:07 +01:00
Théo LUDWIG c361682cab fix(bridge/nodejs): types improvements 2023-12-10 16:44:25 +01:00
louistiti 55b81a3c8f feat(bridge/python): widget renderer kick off 2023-12-10 23:06:44 +08:00
louistiti c5e1ed8e86 chore: remove html-react-parser 2023-12-10 10:47:23 +08:00
louistiti 4baf8f0d55 feat: add widgets folder to skills 2023-12-10 10:02:34 +08:00
louistiti 5a55397ef8 refactor(bridge/nodejs): render return type 2023-12-10 08:59:19 +08:00
louistiti 05200a195b feat: final widget new structure 2023-12-10 08:48:13 +08:00
louistiti 7167849d6a feat: widget new structure 2023-12-09 23:07:34 +08:00
louistiti edfa90d820 refactor(skill/widget-playground): flexbox component usage 2023-12-03 22:48:24 +08:00
louistiti 3511452d93 chore: upgrade Aurora to 1.0.0-beta.9 2023-12-03 22:31:31 +08:00
louistiti 1408f358c7 feat(bridge/nodejs): add Text component 2023-12-03 22:07:12 +08:00
louistiti 0297e1d22b feat(bridge/nodejs): add TabList component 2023-12-03 22:06:30 +08:00
louistiti 10a17b0146 feat(bridge/nodejs): add TabGroup component 2023-12-03 22:05:52 +08:00
louistiti bba60ea45d feat(bridge/nodejs): add TabContent component 2023-12-03 22:05:02 +08:00
louistiti 64e1e7da3e feat(bridge/nodejs): add Tab component 2023-12-03 22:04:27 +08:00
louistiti 14e5bee7d6 feat(bridge/nodejs): add Switch component 2023-12-03 22:03:53 +08:00
louistiti 2576987c44 feat(bridge/nodejs): add Status component 2023-12-03 22:03:15 +08:00
louistiti ea7d6c48db feat(bridge/nodejs): add Slider component 2023-12-03 22:02:37 +08:00
louistiti 52f37fc3ed feat(bridge/nodejs): add SelectOption component 2023-12-03 22:02:04 +08:00
louistiti 8cb0816f24 feat(bridge/nodejs): add Select component 2023-12-03 22:01:28 +08:00
louistiti ca59f02f4f feat(bridge/nodejs): add ScrollContainer component 2023-12-03 22:00:50 +08:00
louistiti 7af761c5f6 feat(bridge/nodejs): add RadioGroup component 2023-12-03 22:00:11 +08:00
louistiti f2b75fc184 feat(bridge/nodejs): add Radio component 2023-12-03 21:59:41 +08:00
louistiti 3bf457caef feat(bridge/nodejs): add Progress component 2023-12-03 21:58:55 +08:00
louistiti 90b5596b76 feat(bridge/nodejs): add Loader component 2023-12-03 21:58:01 +08:00
louistiti 93c0d6c83b chore: upgrade Aurora to1.0.0-beta.8 2023-12-03 21:57:10 +08:00
louistiti 9b5aa5f901 feat(bridge/nodejs): add ListItem component 2023-12-03 21:49:00 +08:00
louistiti bad92d3569 feat(bridge/nodejs): add ListHeader component 2023-12-03 21:48:23 +08:00
louistiti 1f0e4d2260 feat(bridge/nodejs): add List component 2023-12-03 21:47:41 +08:00
louistiti d460dc59f5 feat(bridge/nodejs): add Link component 2023-12-03 21:46:47 +08:00
louistiti eb64695697 feat(bridge/nodejs): add TextInput component 2023-12-03 21:44:00 +08:00
louistiti 308bebeb48 feat(bridge/nodejs): add Image component 2023-12-03 21:41:08 +08:00
louistiti bd71866342 feat(bridge/nodejs): add IconButton component 2023-12-03 21:40:21 +08:00
louistiti b55d58ec30 feat(bridge/nodejs): add Icon component 2023-12-03 21:39:34 +08:00
louistiti 2cf4ef54c3 feat(bridge/nodejs): add Flexbox component 2023-12-03 21:38:36 +08:00
louistiti 34a5e8bac1 feat(bridge/nodejs): add CircularProgress component 2023-12-03 21:37:10 +08:00
louistiti 502ec8ba2e feat(bridge/nodejs): add Checkbox component 2023-12-03 21:35:56 +08:00
louistiti ac25897e9e feat(bridge/nodejs): add Card component 2023-12-03 21:32:38 +08:00
louistiti c44824c89d feat: Aurora components auto mapping of types 2023-11-27 23:17:51 +08:00
louistiti 673de84936 chore: upgrade @leon-ai/aurora to latest (component types exports) 2023-11-27 22:41:19 +08:00
louistiti 78aa9c6ddc feat: new rendering engine prototype on widgets 2023-11-26 23:22:32 +08:00
Théo LUDWIG ea2e5b9747 chore: bump @leon-ai/aurora to v1.0.0-beta.5 2023-11-22 18:10:45 +01:00
louistiti ea1a33b51f refactor(web app): fonts change 2023-11-22 21:39:38 +08:00
louistiti 7a441d50b9 chore: remove ark-ui from core 2023-11-22 20:51:26 +08:00
Théo LUDWIG 364b74568e chore: usage of @leon-ai/aurora 2023-11-21 23:09:12 +01:00
Théo LUDWIG 5f5cb1f55b chore: remove aurora 2023-11-21 23:04:17 +01:00
louistiti 4479fcd655 feat: tmp understanding of the JSX parser 2023-11-21 22:19:06 +08:00
louistiti ad56672819 feat: add checkbox component to skill renderer test 2023-11-21 20:48:05 +08:00
louistiti b4bcabbb9e feat: use TSX template for widget format 2023-11-20 21:52:44 +08:00
louistiti aaf1a1989b feat(web app): cast props value as boolean when necessary 2023-11-18 17:05:29 +08:00
louistiti 2025e366d2 feat(web app): widget components tmp case parsing 2023-11-17 00:33:27 +08:00
louistiti 201d1ce4e4 feat(web app): widget PoC 2023-11-17 00:06:30 +08:00
louistiti 2d1e27926d chore: add classnames npm dep 2023-11-16 23:20:01 +08:00
louistiti e449011f90 chore: merge branch 'develop' into widget-backbone 2023-11-16 23:18:25 +08:00
louistiti 84b84453a7 Merge branch 'chore/clean-up' into develop 2023-11-15 22:38:53 +08:00
louistiti 00cee2d2fd ci: remove macOS ARM64 test runner 2023-11-15 21:56:59 +08:00
Louis Grenard 78cce1970e ci: macOS ARM64 runner test 2023-11-15 21:46:51 +08:00
louistiti 977a822cc8 fix(scripts): clone intent-object JSON files for bridges on check command 2023-11-15 21:15:29 +08:00
Théo LUDWIG 1558970619 chore: forgotten tsconfig.json to update 2023-11-15 02:00:57 +01:00
Théo LUDWIG 86de211fa8 BREAKING: drop support for Docker 2023-11-15 01:23:05 +01:00
Théo LUDWIG 2923c6504b chore: update dependencies + usage of tsx instead of ts-node 2023-11-15 01:10:06 +01:00
Théo LUDWIG 3e23950519 chore: remove dependabot 2023-11-14 23:59:10 +01:00
louistiti 92eb32b4da build(tcp server): 1.1.0 2023-11-14 23:31:10 +08:00
louistiti 754bd7380f build(bridge/python): 1.2.0 2023-11-14 22:38:34 +08:00
louistiti d32cda3663 build(bridge/nodejs): 1.1.0 2023-11-14 22:35:27 +08:00
louistiti e175ea5c12 feat(web app): widget PoC beginning 2023-11-12 23:19:51 +08:00
louistiti 167c97120d Merge branch 'develop' into widget-backbone 2023-11-12 22:23:18 +08:00
louistiti c8d2e8c985 chore: bump to 1.0.0-beta.10+dev 2023-11-12 22:22:56 +08:00
louistiti e73bd632f5 feat: progress on widget brainstorming 2023-11-12 18:34:09 +08:00
louistiti 2a15434919 Merge branch 'feat-improve-ner-types' into develop 2023-11-12 18:16:37 +08:00
louistiti b2c375861b feat: identify entities from utterance samples for a better prioritization of classifications 2023-11-12 18:14:16 +08:00
Théo LUDWIG ae6fec335d fix(skill/date_time): add follow up utterance samples 2023-07-24 23:00:30 +02:00
louistiti 16302ec6e4 Merge branch 'develop' into feat-improve-ner-types 2023-07-23 11:26:38 +08:00
Louis Grenard 4d03e1bb4e docs(README): add knowledge base LLM scenario 2023-07-23 11:15:23 +08:00
Théo LUDWIG 69ce669b4c feat(tcp server): remove unnecessary data from entity + detect most populated city 2023-07-02 11:09:22 +02:00
Théo LUDWIG c512b422e7 feat(web app): add "Show more" when answer is "too big" 2023-07-01 23:33:41 +02:00
Théo LUDWIG 2ad6541c3e feat(skill/help): helps you get started with Leon 2023-07-01 23:28:55 +02:00
Théo LUDWIG 379326d7c1 feat(bridge/nodejs): simplify leon.setAnswerData 2023-07-01 23:24:29 +02:00
Théo LUDWIG 1359f5d210 feat(bridge/python): simplify leon.set_answer_data 2023-07-01 23:23:34 +02:00
Théo LUDWIG 64858ec6fe feat(tcp server): add Country information to City 2023-07-01 19:01:57 +02:00
Théo LUDWIG 166175192d feat(tcp server): better detect cities thanks to alternate names 2023-07-01 19:00:34 +02:00
Théo LUDWIG 97de1d1c3f fix(skill/date_time): correct time zone with toLocaleString method 2023-07-01 18:24:19 +02:00
louistiti 563792bd0a fix(tcp server): use root path for the time_zones.txt file 2023-06-30 22:35:58 +08:00
Théo LUDWIG 076db4c3eb fix(skill/date_time): determine correctly isDaylightSavingTime 2023-06-30 15:11:17 +02:00
Théo LUDWIG 02e1de8ffa fix: precise units used in time zone data 2023-06-29 23:14:14 +02:00
Théo LUDWIG cc01bd18b2 feat(skill/date_time): time zone 2023-06-29 23:03:03 +02:00
Théo LUDWIG 2478adbaa2 feat(server): add spacy data in entity resolution 2023-06-29 22:33:25 +02:00
Théo LUDWIG 45b177d0fb feat(tcp server): add support for time zone and more city/country data 2023-06-29 22:32:12 +02:00
louistiti f61e4f08a4 feat(web app): import Aurora 2023-06-29 22:18:46 +08:00
Théo LUDWIG c0deafcd69 feat(server): improve NER types 2023-06-29 00:04:37 +02:00
louistiti 0ad8b9e8e5 chore: merge 2023-06-29 00:28:39 +08:00
louistiti eea6b0392d feat(skill/date_time): add new utterance samples 2023-06-29 00:17:29 +08:00
louistiti 9845612c68 Merge branch 'feat/skill-utilities-date-time' into develop 2023-06-28 23:39:25 +08:00
louistiti d46ec1d3d5 Merge branch 'feat/skill-leon-age' into develop 2023-06-28 23:39:15 +08:00
louistiti f1a65f53bc feat(skill/age): add new utterance samples 2023-06-28 23:39:07 +08:00
Théo LUDWIG 1410b72362 chore(skill/date_time): add test folder 2023-06-27 18:35:03 +02:00
Théo LUDWIG e9245b522f fix(skill/date_time): separate current date and current time 2023-06-25 22:46:10 +02:00
Théo LUDWIG 636eb0f139 feat(skill/date_time): days countdown 2023-06-25 12:27:30 +02:00
Théo LUDWIG 8645ef01fd fix: improve types for Node.js skill SDK 2023-06-25 12:08:36 +02:00
Théo LUDWIG 18867bde89 fix(server): improve json schema description for skill config 2023-06-25 12:07:41 +02:00
Théo LUDWIG d061a6c4bf feat(skill/date_time): get current week number of the year 2023-06-24 19:57:47 +02:00
Théo LUDWIG e2ec76275a feat(skill/date_time): get current date and time 2023-06-24 19:30:55 +02:00
Théo LUDWIG 767bace201 feat(skill/age): ask Leon his age 2023-06-24 13:23:19 +02:00
louistiti dbed559799 feat(skill/widget-playground): forecast backbone draft 2023-06-04 17:47:29 +08:00
louistiti 305d9cd581 feat(skill/widget-playground): first widget components draft structure 2023-06-04 17:06:24 +08:00
louistiti 212df695f2 feat(skill/widget-playground): tmp skill to develop widgets 2023-06-04 15:51:35 +08:00
louistiti e70d0a0029 feat(web app): add init messages 2023-05-30 23:52:35 +08:00
louistiti 595fe78679 Merge branch 'python-sdk' into develop 2023-05-29 22:55:36 +08:00
louistiti 69cb6a610f build(bridge/nodejs): bump to 1.0.0 2023-05-29 22:01:32 +08:00
louistiti 10a03d90e3 build(bridge/python): bump to 1.1.0 2023-05-29 22:01:06 +08:00
louistiti 251950384e refactor(server): rename obj to skillAnswer 2023-05-28 12:53:44 +08:00
louistiti 8c91d245e8 refactor(server): remove speech prop from skill output backward compatibility 2023-05-28 12:49:56 +08:00
louistiti df343ce94f fix(skill/akinator): typo ShowNextActionSuggestions to showNextActionSuggestions 2023-05-28 10:12:40 +08:00
louistiti 7c73f435af fix(skill/akinator): disable urllib3 cert warning 2023-05-28 10:07:23 +08:00
louistiti b5ef7242af fix(skill/have_i_been_pwned): use current_entities instead of entities 2023-05-28 09:23:50 +08:00
Divlo 16e1f7a34a chore: remove dead code 2023-05-28 01:32:57 +02:00
Divlo e42a54d593 refactor(skill/akinator): usage of new SDK 2023-05-28 01:10:03 +02:00
Divlo cd3bcd5d6e refactor(server): leon over http with /api/utterance 2023-05-28 00:31:40 +02:00
Divlo 2ea6237b1f chore: remove /api/downloads 2023-05-27 23:53:20 +02:00
Divlo 9782526c42 chore: remove legacy Python bridge/utils 2023-05-27 23:48:39 +02:00
Divlo 3bf7150387 refactor(skill/have_i_been_pwned): usage of new SDK 2023-05-27 23:34:15 +02:00
Divlo c00c85fd4f fix(bridge): better types and network error 2023-05-27 20:29:01 +02:00
Divlo a76d05f68a refactor(skill/product_hunt_trends): usage of new SDK 2023-05-27 20:21:03 +02:00
Divlo f17a4d3a2a refactor(skill/github_trends): usage of new SDK 2023-05-27 18:06:31 +02:00
Divlo 850ea46ec6 style(skill/mbti): add missing space for consistency (oops) 2023-05-27 12:54:16 +02:00
Divlo a540307241 refactor(skill/mbti): usage of new SDK 2023-05-27 12:43:19 +02:00
Divlo e440e4f715 refactor(skill/speed_test): usage of new SDK 2023-05-27 12:00:13 +02:00
louistiti d1fe81ddc6 refactor: modify settings method from isAlreadySet to isSettingSet 2023-05-27 09:47:09 +08:00
louistiti 3648fef5fb refactor(bridge/python): add key to settings.isAlreadySet 2023-05-27 09:00:00 +08:00
louistiti 1f9137bb20 refactor(bridge/nodejs): add key to setting.isAlreadySet 2023-05-27 08:47:24 +08:00
louistiti 2e6abef507 chore: lint 2023-05-27 08:06:11 +08:00
louistiti a55fbcd532 fix: ignore error if skill.json isn't found when getting skill info 2023-05-27 08:05:22 +08:00
Divlo 924317c614 refactor(skill/is_it_down): usage of new SDK 2023-05-27 00:14:51 +02:00
Divlo 0c44916aa2 chore(bridge): add comments (jsdoc/docstring) for settings 2023-05-26 23:50:36 +02:00
Divlo 2a0cc0644e chore: remove youtube_downloader skill 2023-05-26 23:34:37 +02:00
Divlo 4f5b385fd7 chore: rename config.json to settings.json 2023-05-26 23:31:25 +02:00
Divlo 30e405bbe3 feat(bridge/python): add Settings module 2023-05-26 23:03:02 +02:00
Divlo 8c105a043d feat(bridge/nodejs): add Settings module 2023-05-26 23:01:54 +02:00
Divlo 99b5e7ab6d chore: remove synchronization capability 2023-05-26 22:58:26 +02:00
Divlo b9dbc5012c Revert "chore: add __init__.py files to avoid mypy linting error"
This reverts commit 0b16eebfbd.
2023-05-26 10:12:43 +02:00
Divlo 0b16eebfbd chore: add __init__.py files to avoid mypy linting error
Ref: https://github.com/python/mypy/issues/8686#issuecomment-1178977365
2023-05-25 22:56:38 +02:00
Divlo c078505846 refactor(skill/todo_list): usage of new SDK 2023-05-25 22:47:58 +02:00
Divlo 421232a6dc refactor(skills): usage of datetime ISO 8601 string format instead of timestamp 2023-05-25 19:05:51 +02:00
louistiti c62368ddad chore: comments and French punctuation 2023-05-25 08:34:20 +08:00
Divlo f956e1abc6 fix(bridge): memory path always defined 2023-05-25 01:04:28 +02:00
Divlo dc88ac244d perf(skill/guess_the_number): only store one game at a time to avoid increasing the size of memory unnecessarily 2023-05-25 00:38:34 +02:00
Divlo 4cd01a4baf refactor(skill/random_number): usage of new SDK 2023-05-25 00:12:59 +02:00
Divlo 06cda4a1f0 fix(bridge/nodejs): allow memory that stores null value 2023-05-25 00:04:25 +02:00
Divlo dc7615723d fix(bridge/python): allow memory that stores null value 2023-05-24 23:57:44 +02:00
Divlo 14275be5f7 refactor(skill/introduction): usage of new SDK 2023-05-24 23:57:18 +02:00
Divlo 158df2f0f1 refactor(skill/greeting): usage of new SDK 2023-05-24 23:57:05 +02:00
Divlo 6bed516f89 refactor(skill/rochambeau): usage of new SDK 2023-05-24 23:22:43 +02:00
Divlo 7e72928ad6 refactor(skill/guess_the_number): usage of new SDK 2023-05-24 23:10:14 +02:00
louistiti 4a7e77141e refactor: remove Python shebangs 2023-05-24 20:32:43 +08:00
louistiti 25ab60e5a2 feat: add Leon user agent from bridges 2023-05-24 19:53:34 +08:00
Divlo f8e6012cbe fix(bridge/python): add types 2023-05-23 19:50:19 +02:00
louistiti 1c5d2874b0 refactor(bridge/python): add memory comments 2023-05-23 21:37:12 +08:00
louistiti 3449c14d47 feat(bridge/python): functional memory 2023-05-23 21:27:35 +08:00
louistiti 51f57e3255 feat(bridge/python): memory write method 2023-05-23 20:10:48 +08:00
louistiti 7fd4be1248 feat(bridge/python): memory read method 2023-05-23 20:09:09 +08:00
louistiti 3b77d64d4f feat(bridge/python): memory clear method 2023-05-23 20:06:35 +08:00
louistiti ab7e2a9b10 refactor(bridge/nodejs): remove Aurora index file 2023-05-22 22:54:00 +08:00
louistiti b2e4ebf1be feat(bridge/python): support widget answer 2023-05-22 22:17:53 +08:00
louistiti 3c9a210081 feat(bridge/python): leon.answer usage 2023-05-22 21:14:52 +08:00
louistiti 7a9068283b refactor(bridge/python): new bridge main file 2023-05-22 20:32:36 +08:00
louistiti 66dc0aab0f feat(skill/timekeeper): boilerplate 2023-05-22 20:18:13 +08:00
Divlo 91e48af263 feat(bridge/python): add Network module (WIP) 2023-05-21 23:20:58 +02:00
louistiti 3a230633d8 feat(bridge/python): memory kick off 2023-05-21 19:12:30 +08:00
louistiti 6c3a03d16a feat(bridge/python): add widget class 2023-05-21 19:03:54 +08:00
louistiti 8a60b3d0d3 Merge branch 'python-sdk-fixes' into python-sdk 2023-05-21 18:51:42 +08:00
Divlo cb3d3bf5a8 fix(bridge/nodejs): add lang to action params 2023-05-20 20:34:12 +02:00
Divlo f3257ad7b0 style(bridge/python): format with autopep8 2023-05-20 20:33:37 +02:00
Divlo cb29848f45 fix(bridge/python): better typings 2023-05-20 19:49:56 +02:00
Divlo ebaa3c4f9b fix(bridge/python): inconsistent indentation TabError 2023-05-20 19:49:07 +02:00
louistiti de17719537 feat(bridge/python): typing (WIP) 2023-05-20 23:28:44 +08:00
louistiti 47d5a48ac9 fix(bridge/python): import INTENT_OBJECT to leon 2023-05-20 23:17:42 +08:00
louistiti e8ceed62eb feat(bridge/python): leon.answer 2023-05-20 23:16:50 +08:00
louistiti bbc1f8a79c feat(bridge/python): leon.set_answer_data 2023-05-20 23:09:45 +08:00
louistiti 289efb5610 feat(bridge/python): leon.get_src_config 2023-05-20 22:49:17 +08:00
louistiti 05a4b2c773 feat(bridge/python): Leon singleton 2023-05-20 22:42:30 +08:00
louistiti a32ad86342 feat(bridge/python): add constants 2023-05-20 22:40:38 +08:00
louistiti a2eacc3930 fix(server): add lang back to the intent object till Python bridge is updated 2023-05-19 22:09:01 +08:00
louistiti a8c079fd5c feat: provide built-in context data to skills 2023-05-19 21:47:23 +08:00
louistiti b389bdd8c6 feat(server): provide sentiment analysis to NLU result 2023-05-19 21:40:24 +08:00
louistiti 750d1de8b4 chore: merge branch 'skill-text-n-speech-difference' into develop 2023-05-18 21:14:09 +08:00
louistiti d295105fa6 chore: disable import/order ESLint rule for skills 2023-05-18 21:06:04 +08:00
louistiti e2899c8d9a refactor(skill/good_bye): rollback as speech/text answer is only supported in logic skills 2023-05-18 20:38:26 +08:00
louistiti 7f9b60a6cd feat(server): differentiate skill text answer from speech answer (WIP) 2023-05-18 00:00:40 +08:00
louistiti 9e77953976 refactor(bridge/nodejs): use AnswerConfig type from core schema 2023-05-17 22:21:11 +08:00
louistiti cb6462b749 feat: define new skill answer format 2023-05-17 18:31:39 +08:00
Louis Grenard 07a3b1701d docs: update README.md 2023-05-16 23:14:02 +08:00
Louis Grenard f6300a3fb8 docs: update README.md 2023-05-16 23:14:02 +08:00
louistiti 46299ef4eb Merge branch 'skill-widget-ideas' into develop 2023-05-16 23:08:00 +08:00
louistiti 259dc53213 Merge branch 'skill-widget-ideas' into develop 2023-05-16 23:08:00 +08:00
louistiti 51152a0fe3 refactor(bridge/nodejs): protected memory constructor 2023-05-16 23:07:12 +08:00
louistiti 01305af669 refactor(bridge/nodejs): protected memory constructor 2023-05-16 23:07:12 +08:00
Divlo 5539130dd9 fix: typo missing "GB" for Free RAM 2023-05-15 23:42:27 +02:00
Divlo efd1061f30 fix: typo missing "GB" for Free RAM 2023-05-15 23:42:27 +02:00
Divlo f6a501d4e1 fix(bridge/nodejs): improve Memory types with external skill memory 2023-05-15 22:58:40 +02:00
Divlo 839c7bfc3c fix(bridge/nodejs): improve Memory types with external skill memory 2023-05-15 22:58:40 +02:00
Divlo d3ba85cb36 feat(bridge/nodejs): add Widget abstract class 2023-05-15 21:18:54 +02:00
Divlo 623039415a feat(bridge/nodejs): add Widget abstract class 2023-05-15 21:18:54 +02:00
louistiti 7a75c985e0 Merge branch 'skill-widget-poc' into develop 2023-05-15 21:31:02 +08:00
louistiti 0f2a579a66 refactor(web app): remove original app rendering 2023-05-15 21:30:42 +08:00
louistiti 63573083fa feat(web app): render widget 2023-05-15 21:25:20 +08:00
louistiti 34aa188643 feat: skill -> core -> client widget support 2023-05-15 01:13:18 +08:00
louistiti 76dfe72f5f feat(web app): kick off Aurora structure 2023-05-15 00:00:21 +08:00
louistiti 7a31158497 feat(web app): set up React 2023-05-14 23:43:42 +08:00
louistiti 96145bb2f7 feat(web app): add vite React plugin 2023-05-14 23:23:17 +08:00
louistiti 17cb808aab chore: install required npm deps 2023-05-14 23:22:01 +08:00
louistiti b757d2d4ae chore: upgrade vite to latest 2023-05-14 23:20:41 +08:00
louistiti ce001c2e65 feat(bridge/nodejs): support read memory from other skills 2023-05-14 21:00:52 +08:00
louistiti a3b8c40714 refactor(scripts): unify skills setup over one iteration only 2023-05-14 12:10:55 +08:00
louistiti 0283878a90 refactor(bridge/nodejs): force run to be the skill action entry point 2023-05-14 09:15:05 +08:00
louistiti 3ed19bd6d0 Merge branch 'nodejs-bridge-memory' into develop 2023-05-14 08:58:28 +08:00
louistiti c163f5971c feat(bridge/nodejs): sync return new memory value on write 2023-05-14 08:58:19 +08:00
louistiti 6a01e1e743 Merge branch 'nodejs-bridge-improvements' into nodejs-bridge-memory 2023-05-14 08:52:03 +08:00
louistiti b06eab9107 style(bridge/nodejs): memory exception/error renaming 2023-05-14 08:51:52 +08:00
Divlo 12ce47b937 fix(bridge/nodejs): usage of getleon.ai to try network available 2023-05-14 00:39:56 +02:00
Divlo c8fc0068d1 feat(bridge/nodejs): improvements to memory 2023-05-14 00:39:30 +02:00
louistiti e32bf370db Merge branch 'nodejs-bridge-memory' into develop 2023-05-14 00:11:10 +08:00
louistiti 9ef4f234b8 Merge branch 'develop' into nodejs-bridge-memory 2023-05-14 00:08:18 +08:00
louistiti 6d2292f508 fix(server): pre-check add process.cwd() to all constant paths 2023-05-14 00:06:43 +08:00
louistiti b897ae160f feat(bridge/nodejs): simple get / set memory 2023-05-13 23:52:54 +08:00
louistiti a51d92bf08 refactor(bridge/nodejs): remove Prisma 2023-05-13 19:04:54 +08:00
louistiti 6d495cf43c refactor(scripts): explicit Node.js bridge npm packages install 2023-05-13 00:30:15 +08:00
louistiti d6933a9e35 refactor(bridge/nodejs): remove lowdb and tiny custom ORM in favor of Prisma 2023-05-13 00:26:51 +08:00
louistiti 127a10f8ed feat(scripts): install Node.js bridge npm packages on setup 2023-05-12 23:54:57 +08:00
louistiti ef223a2901 feat(bridge/nodejs): make use of Prisma from skill action (PoC) 2023-05-11 23:39:17 +08:00
louistiti 9a06c64a5d feat(bridge/nodejs): Prisma SQLite setup 2023-05-11 23:26:42 +08:00
louistiti ad5edb5ad5 feat(bridge/nodejs): support nested props find in memory 2023-05-11 22:30:22 +08:00
louistiti ee0b080522 feat(bridge/nodejs): support updateOne memory method 2023-05-11 21:50:29 +08:00
louistiti be04b10645 feat(bridge/nodejs): support findMany memory method 2023-05-11 21:41:51 +08:00
louistiti ab62a65e57 feat(bridge/nodejs): support findOne memory method 2023-05-11 21:40:22 +08:00
louistiti 99ac5f18c8 feat(bridge/nodejs): give public access to Low instance 2023-05-11 21:21:26 +08:00
louistiti 87a7077854 refactor(bridge/nodejs): rename create with createOne 2023-05-11 21:04:18 +08:00
louistiti af2a124165 refactor(bridge/nodejs): rename insert to create 2023-05-11 20:59:26 +08:00
louistiti 8e55c481d4 feat(bridge/nodejs): support insertMany memory method 2023-05-11 20:51:19 +08:00
louistiti d7b814761f feat(bridge/nodejs): tiny ORM kick off 2023-05-11 20:49:40 +08:00
louistiti 4dde49e545 feat(bridge/nodejs): memory database pattern (WIP) 2023-05-10 23:29:41 +08:00
Divlo 34b29d0e61 fix(bridge/nodejs): memory ESM dynamic imports 2023-05-10 00:45:21 +02:00
louistiti 954126315f refactor(bridge/nodejs): TSConfig ESM NCC 2023-05-09 21:48:07 +08:00
louistiti e240a2db3c feat(bridge/nodejs): memory ESM debugging (WIP) 2023-05-09 21:39:18 +08:00
louistiti 4abb68c1b3 Merge branch 'nodejs-bridge' into develop 2023-05-08 22:05:42 +08:00
louistiti 3ea1a3666b feat(bridge/nodejs): add isNetworkAvailable network method 2023-05-08 22:03:30 +08:00
louistiti d3e0810298 fix(bridge/nodejs): temporize data buffer on output 2023-05-08 22:01:46 +08:00
louistiti ef6d46cf8e refactor(scripts): remove cmd output on install Node.js skills packages 2023-05-08 21:57:41 +08:00
louistiti e65ecd5b67 fix(scripts): install Node.js skills packages timestamp comparison 2023-05-08 21:45:06 +08:00
louistiti 5946a00427 feat(scripts): skill package install/uninstall package script 2023-05-08 21:35:14 +08:00
louistiti 6b239ae38b style(scripts): fix linting 2023-05-08 21:24:26 +08:00
louistiti 224158812f feat(scripts): install Node.js skills packages 2023-05-08 21:23:33 +08:00
Divlo ee9794cd9f Revert "feat(bridge/nodejs): add leon.getVersions"
This reverts commit ec819e1765.
2023-05-08 10:58:31 +02:00
Divlo ad497d36c3 style: fix linting 2023-05-07 21:44:55 +02:00
Divlo 5eb62ddcf5 chore: add leon-nodejs-bridge as local dependency 2023-05-07 21:43:03 +02:00
Divlo ec819e1765 feat(bridge/nodejs): add leon.getVersions 2023-05-07 21:38:09 +02:00
louistiti 2c2f49290a Merge branch 'nodejs-bridge' into develop 2023-05-07 21:28:28 +08:00
louistiti f936652007 Merge branch 'nodejs-bridge-improvements' into nodejs-bridge 2023-05-07 21:26:12 +08:00
Divlo 950985ca86 feat(bridge/nodejs): finish network implementation 2023-05-07 15:07:20 +02:00
louistiti 8147d8423b feat(scripts): add Node.js bridge on check script 2023-05-07 20:09:37 +08:00
louistiti 3f556494c2 Merge branch 'nodejs-bridge-improvements' into nodejs-bridge 2023-05-07 19:07:05 +08:00
Divlo 426c816ca4 build(bridge/nodejs): avoid installing dependencies each time we build 2023-05-07 01:14:44 +02:00
louistiti dd0eab51b6 Merge branch 'HEAD' into nodejs-bridge 2023-05-06 22:47:36 +08:00
Divlo 07e253f663 build(bridge/nodejs): usage of ncc 2023-05-06 15:38:49 +02:00
Divlo de08807f1a feat(bridge/nodejs): add Network module (WIP) 2023-05-06 14:21:24 +02:00
Divlo 2cb030f47b fix(bridge/nodejs): usage of types from server/core/brain/types 2023-05-06 14:03:56 +02:00
Divlo 673cf0426f fix(bridge/nodejs): build error 2023-05-06 13:55:43 +02:00
louistiti e89b5b0ea3 refactor(bridge/nodejs): isolate types from bridge 2023-05-06 18:26:22 +08:00
Divlo 6b76e6a102 fix(bridge/nodejs): stricter leon.getSRCConfig types 2023-05-05 20:24:01 +02:00
Divlo 1625aaf3cd fix(bridge/nodejs): typings improvements 2023-05-05 20:00:51 +02:00
louistiti b65cfb70d6 feat(bridge/nodejs): final answer bridge 2023-05-05 21:21:27 +08:00
louistiti 89a6c04a1e refactor(bridge/nodejs): new answer types (WIP) 2023-05-05 00:34:16 +08:00
louistiti e42655a5ff refactor(server): remove skill answer type complexity 2023-05-04 22:34:29 +08:00
louistiti c9678fe34f refactor(bridge/python): flush standard output every time 2023-05-04 21:40:11 +08:00
louistiti 8349e41205 feat(bridge/nodejs): answers 2023-05-03 23:28:12 +08:00
louistiti 759e67ac40 fix(bridge/nodejs): SDK mapping 2023-05-03 16:02:57 +08:00
louistiti fc1fa56eab Merge branch 'develop' into nodejs-bridge 2023-05-03 14:54:51 +08:00
louistiti 8f5bd3a9a5 feat: add free RAM check 2023-05-03 14:54:23 +08:00
louistiti a836a7cc8c feat(bridge/nodejs): resolve SDK mapping 2023-05-03 09:27:23 +08:00
louistiti 2df22770e0 refactor(bridge/nodejs): SDK mapping 2023-05-03 08:39:06 +08:00
louistiti 9b839d3e66 feat(bridge/nodejs): first draft 2023-05-02 23:53:41 +08:00
louistiti 2e3796642d refactor(server): send heartbeat every 6 hours instead 2023-05-02 16:43:04 +08:00
louistiti b027905ed0 refactor(bridge/nodejs): package.json new dist entry point path 2023-05-01 23:01:46 +08:00
louistiti 4c9dfe667b build(bridge/nodejs): bump 0.0.1-alpha.0 2023-05-01 22:49:32 +08:00
louistiti ed215feb81 refactor(scripts): Node.js bridge bin dist 2023-05-01 22:48:31 +08:00
louistiti cd82a3a11b chore: bump to 1.0.0-beta.9+dev 2023-05-01 10:23:19 +08:00
louistiti b7a4f69565 build: release 1.0.0-beta.8 2023-05-01 10:09:29 +08:00
louistiti 7b8a324658 fix(server): catch error on start for telemetry client 2023-05-01 01:54:19 +08:00
louistiti 59cfded2bb feat(server): send Node.js bridge version to telemetry 2023-05-01 01:26:28 +08:00
louistiti 8dc8c05d7d refactor(scripts): add bin level for Node.js bridge 2023-05-01 01:13:19 +08:00
louistiti 0e4ec4fb97 refactor(scripts): exclude current Node.js bridge archive from new archive 2023-05-01 00:49:35 +08:00
louistiti bb00677568 feat(scripts): add build for Node.js bridge 2023-05-01 00:36:03 +08:00
louistiti 308b63f576 fix(scripts): tmp setup Node.js bridge removal 2023-04-30 23:49:21 +08:00
louistiti 40819e8e17 feat(bridge/nodejs): release process 2023-04-30 23:39:39 +08:00
louistiti 0fba50905f feat(bridge/nodejs): entry point build 2023-04-30 21:36:07 +08:00
louistiti 419bfe3d78 refactor(scripts): commit-msg scopes 2023-04-30 20:35:56 +08:00
louistiti 1847248f12 feat: add instanceID on check script 2023-04-30 10:45:51 +08:00
louistiti eed4a9597c refactor(server): get Node.js version from process.versions.node 2023-04-30 10:32:01 +08:00
louistiti c3452d2170 feat(server): add minimum RAM requirement on pre-check 2023-04-30 10:31:18 +08:00
louistiti 0a14567776 refactor: round up total RAM on check script 2023-04-30 10:13:41 +08:00
louistiti 71573b78d1 refactor: instance ID log on postinstall 2023-04-29 21:04:29 +08:00
louistiti 722dba875b feat: do not download binaries if the latest version is already installed 2023-04-29 20:58:10 +08:00
louistiti 593419639e refactor: naming 2023-04-27 20:24:16 +08:00
louistiti 8b2f06e305 feat(server): bootstrap Node.js bridge entry point 2023-04-27 20:16:08 +08:00
362 changed files with 10630 additions and 4868 deletions
-9
View File
@@ -1,9 +0,0 @@
__pycache__/
**/dist/*
**/build/
**/node_modules/
**/tmp/*
**/src/.venv/*
logs/*
*.pyc
.DS_Store
-1
View File
@@ -12,5 +12,4 @@ end_of_line = lf
insert_final_newline = true
[*.py]
indent_style = tab
indent_size = 4
+9
View File
@@ -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=
+7 -4
View File
@@ -18,10 +18,7 @@
"browser": true
},
"parserOptions": {
"ecmaVersion": 2021
},
"globals": {
"io": true
"ecmaVersion": "latest"
},
"plugins": ["@typescript-eslint", "unicorn", "import"],
"ignorePatterns": "*.spec.js",
@@ -67,6 +64,12 @@
]
},
"overrides": [
{
"files": ["skills/**/*.ts"],
"rules": {
"import/order": "off"
}
},
{
"files": ["*.ts"],
"rules": {
+5 -19
View File
@@ -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.
@@ -123,11 +107,13 @@ Types define which kind of changes you made to the project.
Scopes define high-level nodes of Leon.
- web app
- bridge/python
- bridge/nodejs
- hotword
- scripts
- server
- tcp server
- python bridge
- hotword
- web app
- skill/skill_name
### Examples
-1
View File
@@ -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
-13
View File
@@ -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'
@@ -0,0 +1,76 @@
name: Pre-release Node.js bridge
on: workflow_dispatch
jobs:
build:
name: Build
strategy:
fail-fast: false
matrix:
os: [ubuntu-20.04]
runs-on: ${{ matrix.os }}
steps:
- name: Clone repository
uses: actions/checkout@v3
- name: Install Node.js
uses: actions/setup-node@v3
with:
node-version: lts/*
- name: Set Node.js bridge version
working-directory: bridges/nodejs/src
run: |
echo "NODEJS_BRIDGE_VERSION=$(node --require fs --eval "const fs = require('node:fs'); const [, VERSION] = fs.readFileSync('version.ts', 'utf8').split(\"'\"); console.log(VERSION)")" >> $GITHUB_ENV
- name: Display Node.js bridge version
run: |
echo "Node.js bridge version: ${{ env.NODEJS_BRIDGE_VERSION }}"
- name: Install core
run: npm install
- name: Build Node.js bridge
run: npm run build:nodejs-bridge
- name: Upload Node.js bridge
uses: actions/upload-artifact@v3
with:
path: bridges/nodejs/dist/*.zip
draft-release:
name: Draft-release
needs: [build]
runs-on: ubuntu-20.04
steps:
- name: Clone repository
uses: actions/checkout@v3
- name: Install Node.js
uses: actions/setup-node@v3
with:
node-version: lts/*
- name: Set Node.js bridge version
working-directory: bridges/nodejs/src
run: |
echo "NODEJS_BRIDGE_VERSION=$(node --require fs --eval "const fs = require('node:fs'); const [, VERSION] = fs.readFileSync('version.ts', 'utf8').split(\"'\"); console.log(VERSION)")" >> $GITHUB_ENV
- name: Download Node.js bridge
uses: actions/download-artifact@v3
with:
path: bridges/nodejs/dist
- uses: marvinpinto/action-automatic-releases@latest
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
automatic_release_tag: nodejs-bridge_v${{ env.NODEJS_BRIDGE_VERSION }}
draft: true
prerelease: false
title: Node.js Bridge ${{ env.NODEJS_BRIDGE_VERSION }}
files: bridges/nodejs/dist/artifact/*.zip
@@ -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 }}
+3 -1
View File
@@ -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 }}
+5 -4
View File
@@ -8,7 +8,6 @@ __pycache__/
test/coverage/
**/tmp/*
**/src/.venv/*
downloads/*
logs/*
core/config/**/*.json
bin/coqui/*
@@ -21,17 +20,19 @@ package-lock.json
npm-debug.log
debug.log
.env
.last-skill-npm-install
leon.json
bridges/python/src/Pipfile.lock
tcp_server/src/Pipfile.lock
!tcp_server/**/.gitkeep
!bridges/python/**/.gitkeep
!bridges/nodejs/**/.gitkeep
!core/data/models/llm/.gitkeep
!**/*.sample*
packages/**/config/config.json
skills/**/src/config.json
packages/**/data/db/*.json
skills/**/src/settings.json
skills/**/memory/*.json
core/data/models/*.nlp
core/data/models/llm/*
package.json.backup
.python-version
schemas/**/*.json
+1 -1
View File
@@ -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
+4
View File
@@ -1,3 +1,7 @@
# [1.0.0-beta.8](https://github.com/leon-ai/leon/compare/v1.0.0-beta.7...v1.0.0-beta.8) (2023-05-01) / Binaries and TypeScript Rewrite
_Please refer to [our latest blog post](https://blog.getleon.ai/binaries-and-typescript-rewrite-1-0-0-beta-8/) for more information on the new release of our dear Leon._
# [1.0.0-beta.7](https://github.com/leon-ai/leon/compare/v1.0.0-beta.6...v1.0.0-beta.7) (2022-08-24) / A Much Better NLP
_Please [read this blog post](https://blog.getleon.ai/a-much-better-nlp-and-future-1-0-0-beta-7/) to know more about all the new features and the exciting future of Leon._
-60
View File
@@ -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"]
+12 -24
View File
@@ -36,7 +36,7 @@ _<p align="center">Your open-source personal assistant.</p>_
I'm taking a lot of time to work on the new core of Leon due to personal reasons. I can only work on it after work and on weekends. Hence, **I'm blocking any potential contribution as the whole core of Leon is coming with many breaking changes**. Many of you are willing to contribute in Leon (create new skills, help to improve the core, translations and so on...), a big thanks to every one of you!
I wish one day I could work on Leon full time, but it's not possible at the moment as I need to pay my bills. I have some ideas about how to monetize Leon in the future (Leon's core will always remain open source), but before to get there there is still a long way to go.
While I would love to devote more time to Leon, I'm currently unable to do so because I have bills to pay. I have some ideas about how to monetize Leon in the future (Leon's core will always remain open source), but before to get there there is still a long way to go.
Until then, any financial support by [sponsoring Leon](http://sponsor.getleon.ai) is much appreciated 🙂
@@ -50,24 +50,25 @@ 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...
### What's Next?
Once the new core released, we'll work on the community aspect of Leon. For example, better organize our [Discord](https://discord.gg/MNQqqKg), planify regular calls, work on skills together, etc. It is very important for Leon to have a real community. At that moment, the skills platform will already be online, so it'll be easier to sync our progress and publish new skills.
Once the new core released, we'll work on the community aspect of Leon. For example, better organize [our Discord](https://discord.gg/MNQqqKg), planify regular calls, work on skills together, etc. It is very important for Leon to have a real community. At that moment, the skills platform will already be online, so it'll be easier to sync our progress and publish new skills.
- Feel free to check out the Git development branches and our [next major milestones](https://blog.getleon.ai/a-much-better-nlp-and-future-1-0-0-beta-7/#whats-next).
- And the [detailed roadmap](http://roadmap.getleon.ai).
- Many exciting things are coming up, hence no new documentation and test are going to be written until the official release of Leon.
<h2 align="center">📢 Notice 📢</h2>
<p align="center">
<a href="https://blog.getleon.ai/a-much-better-nlp-and-future-1-0-0-beta-7/"><img width="400" src="https://blog.getleon.ai/static/a62ac28a01cb6898e299dced40875a68/c1b63/beta-7.png" /></a>
<br>
Many exciting things are coming up, hence no new documentation and test are going to be written until the official release of Leon. Feel free to <a href="https://discord.gg/MNQqqKg"><b>join us on Discord</b></a> to know more and to read the <a href="https://blog.getleon.ai/a-much-better-nlp-and-future-1-0-0-beta-7/"><b>"A Much Better NLP and Future" blog post</b></a>.
</p>
<br><br>
---
## Latest Release
Check out the [latest release blog post](https://blog.getleon.ai/binaries-and-typescript-rewrite-1-0-0-beta-8/).
<a href="https://blog.getleon.ai/binaries-and-typescript-rewrite-1-0-0-beta-8/"><img width="400" src="https://blog.getleon.ai/static/a0d1cbafd1968e7531dc17e229f8cc61/aa440/beta-8.png" /></a>
---
@@ -151,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).
@@ -225,7 +213,7 @@ You'll find a write-up on this [blog post](https://blog.getleon.ai/the-story-beh
<sub><sup>10 USD / month</sup></sub>
</td>
<td align="center" valign="middle" width="128">
<a href="http://sponsor.getleon.ai/">
<a href="http://sponsor.getleon.ai/">
You?
</a>
</td>
+37 -6
View File
@@ -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 -4
View File
@@ -1,4 +1,4 @@
<!DOCTYPE html>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
@@ -27,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,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()
@@ -60,6 +73,9 @@ export default class Chatbot {
}
loadFeed() {
/**
* TODO: widget: load widget from local storage
*/
return new Promise((resolve) => {
if (this.parsedBubbles === null || this.parsedBubbles.length === 0) {
this.noBubbleMessage.classList.remove('hide')
@@ -92,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)
}
+27 -4
View File
@@ -1,6 +1,7 @@
import { io } from 'socket.io-client'
import Chatbot from './chatbot'
import { INIT_MESSAGES } from './constants'
export default class Client {
constructor(client, serverUrl, input, res) {
@@ -31,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()
@@ -40,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) => {
@@ -63,6 +86,10 @@ export default class Client {
cb('string-received')
})
this.socket.on('widget', (data) => {
this.chatbot.createBubble('leon', data)
})
this.socket.on('audio-forwarded', (data, cb) => {
const ctx = new AudioContext()
const source = ctx.createBufferSource()
@@ -108,10 +135,6 @@ export default class Client {
cb('audio-received')
})
this.socket.on('download', (data) => {
window.location = `${this.serverUrl}/api/v1/downloads?domain=${data.domain}&skill=${data.skill}`
})
if (this.history !== null) {
this.parsedHistory = JSON.parse(this.history)
}
+18
View File
@@ -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!`
]
]
+3 -1
View File
@@ -2,6 +2,7 @@ import dns from 'node:dns'
import dotenv from 'dotenv'
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
dotenv.config()
@@ -20,5 +21,6 @@ export default defineConfig({
},
server: {
port: 3000
}
},
plugins: [react()]
})
+2
View File
@@ -0,0 +1,2 @@
package-lock=false
save-exact=true
+22
View File
@@ -0,0 +1,22 @@
{
"name": "leon-nodejs-bridge",
"description": "Leon's Node.js bridge to communicate between the core and skills made with JavaScript",
"main": "dist/bin/leon-nodejs-bridge.js",
"author": {
"name": "Louis Grenard",
"email": "louis@getleon.ai",
"url": "https://twitter.com/grenlouis"
},
"license": "MIT",
"homepage": "https://getleon.ai",
"bugs": {
"url": "https://github.com/leon-ai/leon/issues"
},
"dependencies": {
"axios": "1.4.0",
"lodash": "4.17.21"
},
"devDependencies": {
"@types/lodash": "4.14.194"
}
}
+32
View File
@@ -0,0 +1,32 @@
import fs from 'node:fs'
import path from 'node:path'
import { SKILLS_PATH as SKILLS_ROOT_PATH } from '@/constants'
import type { SkillConfigSchema } from '@server/schemas/skill-schemas'
import type { IntentObject } from '@sdk/types'
const {
argv: [, , INTENT_OBJ_FILE_PATH]
} = process
export const INTENT_OBJECT: IntentObject = JSON.parse(
fs.readFileSync(INTENT_OBJ_FILE_PATH as string, 'utf8')
)
export const SKILL_PATH = path.join(
SKILLS_ROOT_PATH,
INTENT_OBJECT.domain,
INTENT_OBJECT.skill
)
export const SKILLS_PATH = SKILLS_ROOT_PATH
export const SKILL_CONFIG: SkillConfigSchema = JSON.parse(
fs.readFileSync(
path.join(
SKILL_PATH,
'config',
INTENT_OBJECT.extra_context_data.lang + '.json'
),
'utf8'
)
)
export { LEON_VERSION, NODEJS_BRIDGE_VERSION } from '@/constants'
+51
View File
@@ -0,0 +1,51 @@
import path from 'node:path'
import type { ActionFunction, ActionParams } from '@sdk/types'
import { INTENT_OBJECT } from '@bridge/constants'
;(async (): Promise<void> => {
const {
domain,
skill,
action,
lang,
utterance,
new_utterance,
current_entities,
entities,
current_resolvers,
resolvers,
slots,
extra_context_data
} = INTENT_OBJECT
const params: ActionParams = {
lang,
utterance,
new_utterance,
current_entities,
entities,
current_resolvers,
resolvers,
slots,
extra_context_data
}
try {
const actionModule = await import(
path.join(
process.cwd(),
'skills',
domain,
skill,
'src',
'actions',
`${action}.ts`
)
)
const actionFunction: ActionFunction = actionModule.run
await actionFunction(params)
} catch (e) {
console.error(`Error while running "${skill}" skill "${action}" action:`, e)
}
})()
+9
View File
@@ -0,0 +1,9 @@
import { type ButtonProps } from '@leon-ai/aurora'
import { WidgetComponent } from '../widget-component'
export class Button extends WidgetComponent<ButtonProps> {
constructor(props: ButtonProps) {
super(props)
}
}
+9
View File
@@ -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)
}
}
+9
View File
@@ -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)
}
}
+9
View File
@@ -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)
}
}
+9
View File
@@ -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)
}
}
+29
View File
@@ -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'
+9
View File
@@ -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)
}
}
+9
View File
@@ -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)
}
}
+9
View File
@@ -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)
}
}
+9
View File
@@ -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)
}
}
+9
View File
@@ -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)
}
}
+9
View File
@@ -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)
}
}
+9
View File
@@ -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)
}
}
+9
View File
@@ -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)
}
}
+9
View File
@@ -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)
}
}
+9
View File
@@ -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)
}
}
+134
View File
@@ -0,0 +1,134 @@
import type {
AnswerData,
AnswerInput,
AnswerOutput,
AnswerConfig
} from '@sdk/types'
import { INTENT_OBJECT, SKILL_CONFIG } from '@bridge/constants'
import { WidgetWrapper } from '@sdk/aurora'
class Leon {
private static instance: Leon
constructor() {
if (!Leon.instance) {
Leon.instance = this
}
}
/**
* Apply data to the answer
* @param answerKey The answer key
* @param data The data to apply
* @example setAnswerData('key', { name: 'Leon' })
*/
public setAnswerData(
answerKey: string,
data: AnswerData = null
): AnswerConfig {
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 != 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
}
}
/**
* Send an answer to the core
* @param answerInput The answer input
* @example answer({ key: 'greet' }) // 'Hello world'
* @example answer({ key: 'welcome', data: { name: 'Louis' } }) // 'Welcome Louis'
* @example answer({ key: 'confirm', core: { restart: true } }) // 'Would you like to retry?'
*/
public async answer(answerInput: AnswerInput): Promise<void> {
try {
const answerObject: AnswerOutput = {
...INTENT_OBJECT,
output: {
codes:
answerInput.widget && !answerInput.key
? 'widget'
: (answerInput.key as string),
answer:
answerInput.key != null
? this.setAnswerData(answerInput.key, answerInput.data)
: '',
core: answerInput.core
}
}
if (answerInput.widget) {
answerObject.output.widget = new WidgetWrapper({
...answerInput.widget.wrapperProps,
children: [answerInput.widget.render()]
})
}
// "Temporize" for the data buffer output on the core
await new Promise((r) => setTimeout(r, 100))
process.stdout.write(JSON.stringify(answerObject))
} catch (e) {
console.error('Error while creating answer:', e)
}
}
}
export const leon = new Leon()
+100
View File
@@ -0,0 +1,100 @@
import path from 'node:path'
import fs from 'node:fs'
import { SKILL_PATH, SKILLS_PATH } from '@bridge/constants'
interface MemoryOptions<T> {
name: string
defaultMemory?: T
}
export class Memory<T = unknown> {
private readonly memoryPath: string
private readonly name: string
private readonly defaultMemory: T | undefined
private isFromAnotherSkill: boolean
constructor(options: MemoryOptions<T>) {
const { name, defaultMemory } = options
this.name = name
this.defaultMemory = defaultMemory
this.memoryPath = path.join(SKILL_PATH, 'memory', `${this.name}.json`)
this.isFromAnotherSkill = false
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,
domainName as string,
skillName as string,
'memory',
`${memoryName}.json`
)
}
}
/**
* Clear the memory and set it to the default memory value
* @example clear()
*/
public async clear(): Promise<void> {
if (!this.isFromAnotherSkill) {
await this.write(this.defaultMemory as T)
} else {
throw new Error(
`You cannot clear the memory "${this.name}" as it belongs to another skill`
)
}
}
/**
* Read the memory
* @example read()
*/
public async read(): Promise<T> {
if (this.isFromAnotherSkill && !fs.existsSync(this.memoryPath)) {
throw new Error(
`You cannot read the memory "${this.name}" as it belongs to another skill which haven't written to this memory yet`
)
}
try {
if (!fs.existsSync(this.memoryPath)) {
await this.clear()
}
return JSON.parse(await fs.promises.readFile(this.memoryPath, 'utf-8'))
} catch (e) {
console.error(`Error while reading memory for "${this.name}":`, e)
throw e
}
}
/**
* Write the memory
* @param memory The memory to write
* @example write({ foo: 'bar' }) // { foo: 'bar' }
*/
public async write(memory: T): Promise<T> {
if (!this.isFromAnotherSkill) {
try {
await fs.promises.writeFile(
this.memoryPath,
JSON.stringify(memory, null, 2)
)
return memory
} catch (e) {
console.error(`Error while writing memory for "${this.name}":`, e)
throw e
}
} else {
throw new Error(
`You cannot write into the memory "${this.name}" as it belongs to another skill`
)
}
}
}
+147
View File
@@ -0,0 +1,147 @@
import dns from 'node:dns'
import type { AxiosInstance } from 'axios'
import axios from 'axios'
import { LEON_VERSION, NODEJS_BRIDGE_VERSION } from '@bridge/constants'
interface NetworkOptions {
/** `baseURL` will be prepended to `url`. It can be convenient to set `baseURL` for an instance of `Network` to pass relative URLs. */
baseURL?: string
}
interface NetworkRequestOptions {
/** Server URL that will be used for the request. */
url: string
/** Request method to be used when making the request. */
method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'
/** Data to be sent as the request body. */
data?: Record<string, unknown>
/** Custom headers to be sent. */
headers?: Record<string, string>
}
interface NetworkResponse<ResponseData> {
/** Data provided by the server. */
data: ResponseData
/** HTTP status code from the server response. */
statusCode: number
/** Options that was provided for the request. */
options: NetworkRequestOptions & NetworkOptions
}
export class NetworkError<ResponseErrorData = unknown> extends Error {
public readonly response: NetworkResponse<ResponseErrorData>
constructor(response: NetworkResponse<ResponseErrorData>) {
super(`[NetworkError]: ${response.statusCode} ${response.data}`)
this.response = response
Object.setPrototypeOf(this, NetworkError.prototype)
}
}
export class Network {
private readonly options: NetworkOptions
private axios: AxiosInstance
constructor(options: NetworkOptions = {}) {
this.options = options
this.axios = axios.create({
baseURL: this.options.baseURL
})
}
/**
* Send HTTP request
* @param options Request options
* @example request({ url: '/send', method: 'POST', data: { message: 'Hi' } })
*/
public async request<ResponseData = unknown, ResponseErrorData = unknown>(
options: NetworkRequestOptions
): Promise<NetworkResponse<ResponseData>> {
try {
const response = await this.axios.request<string>({
url: options.url,
method: options.method.toLowerCase(),
data: options.data,
transformResponse: (data) => {
return data
},
headers: {
'User-Agent': `Leon Personal Assistant ${LEON_VERSION} - Node.js Bridge ${NODEJS_BRIDGE_VERSION}`,
...options.headers
}
})
let data = {} as ResponseData
try {
data = JSON.parse(response.data)
} catch {
data = response.data as ResponseData
}
return {
data,
statusCode: response.status,
options: {
...this.options,
...options
}
}
} catch (error) {
let statusCode = 500
let dataRawText = ''
if (axios.isAxiosError(error)) {
dataRawText = error?.response?.data ?? ''
statusCode = error?.response?.status ?? 500
}
let data: ResponseErrorData
try {
data = JSON.parse(dataRawText)
} catch {
data = dataRawText as ResponseErrorData
}
throw new NetworkError<ResponseErrorData>({
data,
statusCode,
options: {
...this.options,
...options
}
})
}
}
/**
* Check if error is a network error
* @param error Error to check
* @example isNetworkError(error) // false
*/
public isNetworkError<ResponseErrorData = unknown>(
error: unknown
): error is NetworkError<ResponseErrorData> {
return error instanceof NetworkError
}
/**
* Verify whether there is an Internet connectivity
* @example isNetworkAvailable() // true
*/
public async isNetworkAvailable(): Promise<boolean> {
try {
await dns.promises.resolve('getleon.ai')
return true
} catch {
return false
}
}
}
@@ -0,0 +1 @@
export { default } from 'lodash'
+125
View File
@@ -0,0 +1,125 @@
import path from 'node:path'
import fs from 'node:fs'
import { SKILL_PATH } from '@bridge/constants'
export class Settings<T extends Record<string, unknown>> {
private readonly settingsPath: string
private readonly settingsSamplePath: string
constructor() {
this.settingsPath = path.join(SKILL_PATH, 'src', 'settings.json')
this.settingsSamplePath = path.join(
SKILL_PATH,
'src',
'settings.sample.json'
)
}
/**
* Check if a setting is already set
* @param key The key to verify whether its value is set
* @returns isSettingSet('apiKey') // true
*/
public async isSettingSet(key: string): Promise<boolean> {
const settingsSample = await this.getSettingsSample()
const settings = await this.get()
return (
!!settings[key] &&
JSON.stringify(settings[key]) !== JSON.stringify(settingsSample[key])
)
}
/**
* Clear the settings and set it to the default settings.sample.json file
* @example clear()
*/
public async clear(): Promise<void> {
const settingsSample = await this.getSettingsSample()
await this.set(settingsSample)
}
private async getSettingsSample(): Promise<T> {
try {
return JSON.parse(
await fs.promises.readFile(this.settingsSamplePath, 'utf8')
)
} catch (e) {
console.error(
`Error while reading settings sample at "${this.settingsSamplePath}":`,
e
)
throw e
}
}
/**
* Get the settings
* @param key The key of the setting to get
* @example get('API_KEY') // 'value'
* @example get() // { API_KEY: 'value' }
*/
public async get<Key extends keyof T>(key: Key): Promise<T[Key]>
public async get(): Promise<T>
public async get<Key extends keyof T>(key?: Key): Promise<T | T[Key]> {
try {
if (!fs.existsSync(this.settingsPath)) {
await this.clear()
}
const settings = JSON.parse(
await fs.promises.readFile(this.settingsPath, 'utf8')
)
if (key != null) {
return settings[key]
}
return settings
} catch (e) {
console.error(
`Error while reading settings at "${this.settingsPath}":`,
e
)
throw e
}
}
/**
* Set the settings
* @param key The key of the setting to set
* @param value The value of the setting to set
* @example set({ API_KEY: 'value' }) // { API_KEY: 'value' }
*/
public async set<Key extends keyof T>(key: Key, value: T[Key]): Promise<T>
public async set(settings: T): Promise<T>
public async set<Key extends keyof T>(
keyOrSettings: Key | T,
value?: T[Key]
): Promise<T> {
try {
const settings = await this.get()
const newSettings =
typeof keyOrSettings === 'object'
? keyOrSettings
: { ...settings, [keyOrSettings]: value }
await fs.promises.writeFile(
this.settingsPath,
JSON.stringify(newSettings, null, 2)
)
return newSettings
} catch (e) {
console.error(
`Error while writing settings at "${this.settingsPath}":`,
e
)
throw e
}
}
}
+39
View File
@@ -0,0 +1,39 @@
/**
* Action types
*/
import type {
ActionParams,
IntentObject,
SkillAnswerCoreData,
SkillAnswerOutput
} 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>
/**
* Answer types
*/
export interface Answer {
key?: string
widget?: Widget
data?: AnswerData
core?: SkillAnswerCoreData
}
export interface TextAnswer extends Answer {
key: string
}
export interface WidgetAnswer extends Answer {
widget: Widget
key?: string
}
export type AnswerData = Record<string, string | number> | null
export type AnswerInput = TextAnswer | WidgetAnswer
export type AnswerOutput = SkillAnswerOutput
export type AnswerConfig = SkillAnswerConfigSchema
@@ -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
}
}
+22
View File
@@ -0,0 +1,22 @@
import { type WidgetWrapperProps } from '@leon-ai/aurora'
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
View File
@@ -0,0 +1 @@
export const VERSION = '1.2.0'
+19
View File
@@ -0,0 +1,19 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "./dist/bin",
"rootDir": "../../",
"baseUrl": ".",
"paths": {
"@@/*": ["../../*"],
"@/*": ["../../server/src/*"],
"@server/*": ["../../server/src/*"],
"@bridge/*": ["./src/*"],
"@sdk/*": ["./src/sdk/*"]
},
"exactOptionalPropertyTypes": false,
"declaration": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
-2
View File
@@ -11,6 +11,4 @@ setuptools = "*"
wheel = "*"
cx-freeze = "==6.11.1"
requests = "==2.28.1"
pytube = "==9.5.0"
tinydb = "==4.7.0"
beautifulsoup4 = "==4.7.1"
+30
View File
@@ -0,0 +1,30 @@
import sys
import json
import os
import version
INTENT_OBJ_FILE_PATH = sys.argv[1]
with open(INTENT_OBJ_FILE_PATH, 'r') as f:
INTENT_OBJECT = json.load(f)
SKILLS_ROOT_PATH = os.path.join(
os.getcwd(),
'skills'
)
SKILL_PATH = os.path.join(
SKILLS_ROOT_PATH,
INTENT_OBJECT['domain'],
INTENT_OBJECT['skill']
)
SKILLS_PATH = SKILLS_ROOT_PATH
with open(os.path.join(SKILL_PATH, 'config', INTENT_OBJECT['extra_context_data']['lang'] + '.json'), 'r') as f:
SKILL_CONFIG = json.load(f)
LEON_VERSION = os.getenv('npm_package_version')
PYTHON_BRIDGE_VERSION = version.__version__
+35 -27
View File
@@ -1,37 +1,45 @@
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import utils
import sys
from traceback import print_exc
from sys import path
from json import dumps, loads
from importlib import import_module
from constants import INTENT_OBJECT
def main():
"""Dynamically import skills related to the args and print the output"""
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'],
'resolvers': INTENT_OBJECT['resolvers'],
'slots': INTENT_OBJECT['slots'],
'extra_context_data': INTENT_OBJECT['extra_context_data']
}
path.append('.')
try:
sys.path.append('.')
intent_obj = utils.get_intent_obj()
skill_action_module = import_module(
'skills.'
+ INTENT_OBJECT['domain']
+ '.'
+ INTENT_OBJECT['skill']
+ '.src.actions.'
+ INTENT_OBJECT['action']
)
skill = import_module('skills.' + intent_obj['domain'] + '.' + intent_obj['skill'] + '.src.actions.' + intent_obj['action'])
getattr(skill_action_module, 'run')(params)
except Exception as e:
print(f"Error while running {INTENT_OBJECT['skill']} skill {INTENT_OBJECT['action']} action: {e}")
print_exc()
params = {
'lang': intent_obj['lang'],
'utterance': intent_obj['utterance'],
'current_entities': intent_obj['current_entities'],
'entities': intent_obj['entities'],
'current_resolvers': intent_obj['current_resolvers'],
'resolvers': intent_obj['resolvers'],
'slots': intent_obj['slots']
}
return getattr(skill, intent_obj['action'])(params)
if __name__ == '__main__':
try:
raise main()
except Exception as e:
# Print full traceback error report if skills triggers an error from the call stack
if 'exceptions must derive from BaseException' not in str(e):
print_exc()
try:
raise main()
except Exception as e:
# Print full traceback error report if skills triggers an error from the call stack
if 'exceptions must derive from BaseException' not in str(e):
print_exc()
+19
View File
@@ -0,0 +1,19 @@
from typing import Optional, TypedDict, Union, Literal, Any
from ..widget_component import WidgetComponent
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(WidgetComponent[ButtonProps]):
def __init__(self, props: ButtonProps):
super().__init__(props)
+6
View File
@@ -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)
+6
View File
@@ -0,0 +1,6 @@
from ..widget_component import WidgetComponent
class Flexbox(WidgetComponent[dict]):
def __init__(self, props: dict):
super().__init__(props)
+6
View File
@@ -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)
+6
View File
@@ -0,0 +1,6 @@
from ..widget_component import WidgetComponent
class Image(WidgetComponent[dict]):
def __init__(self, props: dict):
super().__init__(props)
+6
View File
@@ -0,0 +1,6 @@
from ..widget_component import WidgetComponent
class Link(WidgetComponent[dict]):
def __init__(self, props: dict):
super().__init__(props)
+6
View File
@@ -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)
+6
View File
@@ -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)
+6
View File
@@ -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)
+6
View File
@@ -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)
+6
View File
@@ -0,0 +1,6 @@
from ..widget_component import WidgetComponent
class Slider(WidgetComponent[dict]):
def __init__(self, props: dict):
super().__init__(props)
+6
View File
@@ -0,0 +1,6 @@
from ..widget_component import WidgetComponent
class Switch(WidgetComponent[dict]):
def __init__(self, props: dict):
super().__init__(props)
+6
View File
@@ -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)
+6
View File
@@ -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)
+98
View File
@@ -0,0 +1,98 @@
import random
import sys
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
class Leon:
instance: 'Leon' = None
def __init__(self) -> None:
if not Leon.instance:
Leon.instance = self
@staticmethod
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
"""
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
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))
return answer
except Exception as e:
print('Error while setting answer data:', e)
raise e
def answer(self, answer_input: AnswerInput) -> None:
"""
Send an answer to the core
: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(key, answer_input.get('data')) if key is not None else '',
'core': answer_input.get('core')
}
}
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
sleep(0.1)
sys.stdout.write(json.dumps(answer_object))
sys.stdout.flush()
except Exception as e:
print('Error while creating answer:', e)
leon = Leon()
+76
View File
@@ -0,0 +1,76 @@
import json
import os
from typing import TypedDict, Any
from ..constants import SKILL_PATH, SKILLS_PATH
class MemoryOptions(TypedDict, total=False):
name: str
default_memory: Any
class Memory:
def __init__(self, options: MemoryOptions):
self.name = options['name']
self.default_memory = options['default_memory'] if 'default_memory' in options else None
self.memory_path = self.memory_path = os.path.join(
SKILL_PATH,
'memory',
f'{self.name}.json'
)
self.__is_from_another_skill = False
if ':' in self.name and self.name.count(':') == 2:
self.__is_from_another_skill = True
domain_name, skill_name, memory_name = self.name.split(':')
self.memory_path = os.path.join(
SKILLS_PATH,
domain_name,
skill_name,
'memory',
memory_name + '.json'
)
def clear(self) -> None:
"""
Clear the memory and set it to the default memory value
"""
if not self.__is_from_another_skill:
self.write(self.default_memory)
else:
raise ValueError(f'You cannot clear the memory "{self.name}" as it belongs to another skill')
def read(self):
"""
Read the memory
"""
if self.__is_from_another_skill and not os.path.exists(self.memory_path):
raise ValueError(f'You cannot read the memory "{self.name}" as it belongs to another skill which hasn\'t written to this memory yet')
try:
if not os.path.exists(self.memory_path):
self.clear()
with open(self.memory_path, 'r') as f:
return json.load(f)
except Exception as e:
print(f'Error while reading memory for "{self.name}": {e}')
raise e
def write(self, memory):
"""
Write the memory
:param memory: The memory to write
"""
if not self.__is_from_another_skill:
try:
with open(self.memory_path, 'w') as f:
json.dump(memory, f, indent=2)
return memory
except Exception as e:
print(f'Error while writing memory for "{self.name}": {e}')
raise e
else:
raise ValueError(f'You cannot write into the memory "{self.name}" as it belongs to another skill')
+92
View File
@@ -0,0 +1,92 @@
import requests
import socket
from typing import Any, Dict, TypedDict, Union, Literal, Optional
from ..constants import LEON_VERSION, PYTHON_BRIDGE_VERSION
class NetworkOptions(TypedDict, total=False):
base_url: Optional[str]
class NetworkResponse(TypedDict):
data: Any
status_code: int
options: Dict[str, Any]
class NetworkError(Exception):
def __init__(self, response: NetworkResponse) -> None:
self.response = response
super().__init__(f"[NetworkError]: {response['status_code']} {response['data']}")
class NetworkRequestOptions(TypedDict, total=False):
url: str
method: Union[Literal['GET'], Literal['POST'], Literal['PUT'], Literal['PATCH'], Literal['DELETE']]
data: Dict[str, Any]
headers: Dict[str, str]
class Network:
def __init__(self, options: NetworkOptions = {'base_url': None}) -> None:
self.options = options
def request(self, options: NetworkRequestOptions) -> NetworkResponse:
try:
url = options['url']
if self.options['base_url'] is not None:
url = self.options['base_url'] + url
method = options['method']
data = options.get('data', {})
headers = options.get('headers', {})
response = requests.request(
method,
url,
json=data,
headers={
'User-Agent': f"Leon Personal Assistant {LEON_VERSION} - Python Bridge {PYTHON_BRIDGE_VERSION}",
**headers
}
)
data = {}
try:
data = response.json()
except Exception:
data = response.text
network_response: NetworkResponse = {
'data': data,
'status_code': response.status_code,
'options': {**self.options, **options}
}
if response.ok:
return network_response
else:
raise NetworkError(network_response)
except requests.exceptions.RequestException as error:
data = {}
try:
data = error.response.json()
except Exception:
data = error.response.text
raise NetworkError({
'data': data,
'status_code': error.response.status_code,
'options': {**self.options, **options}
}) from error
def is_network_error(self, error: Exception) -> bool:
return isinstance(error, NetworkError)
def is_network_available(self) -> bool:
try:
socket.gethostbyname('getleon.ai')
return True
except socket.error:
return False

Some files were not shown because too many files have changed in this diff Show More