mirror of
https://github.com/leon-ai/leon.git
synced 2024-11-24 12:45:58 +03:00
chore: merge
This commit is contained in:
commit
0ad8b9e8e5
@ -11,6 +11,8 @@ import type { SkillAnswerConfigSchema } from '@/schemas/skill-schemas'
|
||||
|
||||
export type { ActionParams, IntentObject }
|
||||
|
||||
export * from '@/core/nlp/types'
|
||||
|
||||
export type ActionFunction = (params: ActionParams) => Promise<void>
|
||||
|
||||
/**
|
||||
|
@ -68,32 +68,6 @@
|
||||
"route": "/api/action/social_communication/mbti/quiz",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/unknown/widget-playground/run",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/utilities/have_i_been_pwned/run",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"route": "/api/action/utilities/is_it_down/run",
|
||||
"params": ["url"],
|
||||
"entitiesType": "builtIn"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/utilities/speed_test/run",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/utilities/timekeeper/run",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"route": "/api/action/games/akinator/choose_thematic",
|
||||
@ -215,6 +189,47 @@
|
||||
"method": "GET",
|
||||
"route": "/api/action/leon/welcome/run",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/utilities/date_time/current_date_time",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/utilities/date_time/current_date",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/utilities/date_time/current_time",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/utilities/date_time/current_week_number",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/utilities/date_time/days_countdown",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/utilities/have_i_been_pwned/run",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"route": "/api/action/utilities/is_it_down/run",
|
||||
"params": ["url"],
|
||||
"entitiesType": "builtIn"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/utilities/speed_test/run",
|
||||
"params": []
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -116,33 +116,33 @@ interface Entity {
|
||||
* Built-in entity types
|
||||
*/
|
||||
|
||||
interface BuiltInEntity extends Entity {}
|
||||
export interface BuiltInEntity extends Entity {}
|
||||
|
||||
interface BuiltInNumberEntity extends BuiltInEntity {
|
||||
export interface BuiltInNumberEntity extends BuiltInEntity {
|
||||
resolution: {
|
||||
strValue: string
|
||||
value: number
|
||||
subtype: string
|
||||
}
|
||||
}
|
||||
interface BuiltInIPEntity extends BuiltInEntity {
|
||||
export interface BuiltInIPEntity extends BuiltInEntity {
|
||||
resolution: {
|
||||
value: string
|
||||
type: string
|
||||
}
|
||||
}
|
||||
interface BuiltInHashtagEntity extends BuiltInEntity {
|
||||
export interface BuiltInHashtagEntity extends BuiltInEntity {
|
||||
resolution: {
|
||||
value: string
|
||||
}
|
||||
}
|
||||
interface BuiltInPhoneNumberEntity extends BuiltInEntity {
|
||||
export interface BuiltInPhoneNumberEntity extends BuiltInEntity {
|
||||
resolution: {
|
||||
value: string
|
||||
score: string
|
||||
}
|
||||
}
|
||||
interface BuiltInCurrencyEntity extends BuiltInEntity {
|
||||
export interface BuiltInCurrencyEntity extends BuiltInEntity {
|
||||
resolution: {
|
||||
strValue: string
|
||||
value: number
|
||||
@ -150,24 +150,24 @@ interface BuiltInCurrencyEntity extends BuiltInEntity {
|
||||
localeUnit: string
|
||||
}
|
||||
}
|
||||
interface BuiltInPercentageEntity extends BuiltInEntity {
|
||||
export interface BuiltInPercentageEntity extends BuiltInEntity {
|
||||
resolution: {
|
||||
strValue: string
|
||||
value: number
|
||||
subtype: string
|
||||
}
|
||||
}
|
||||
interface BuiltInDateEntity extends BuiltInEntity {
|
||||
export interface BuiltInDateEntity extends BuiltInEntity {
|
||||
resolution: {
|
||||
type: string
|
||||
timex: string
|
||||
strPastValue: string
|
||||
pastDate: Date
|
||||
pastDate: string
|
||||
strFutureValue: string
|
||||
futureDate: Date
|
||||
futureDate: string
|
||||
}
|
||||
}
|
||||
interface BuiltInTimeEntity extends BuiltInEntity {
|
||||
export interface BuiltInTimeEntity extends BuiltInEntity {
|
||||
resolution: {
|
||||
values: {
|
||||
timex: string
|
||||
@ -176,7 +176,7 @@ interface BuiltInTimeEntity extends BuiltInEntity {
|
||||
}[]
|
||||
}
|
||||
}
|
||||
interface BuiltInTimeRangeEntity extends BuiltInEntity {
|
||||
export interface BuiltInTimeRangeEntity extends BuiltInEntity {
|
||||
resolution: {
|
||||
values: {
|
||||
timex: string
|
||||
@ -186,35 +186,35 @@ interface BuiltInTimeRangeEntity extends BuiltInEntity {
|
||||
}[]
|
||||
}
|
||||
}
|
||||
interface BuiltInDateRangeEntity extends BuiltInEntity {
|
||||
export interface BuiltInDateRangeEntity extends BuiltInEntity {
|
||||
resolution: {
|
||||
type: string
|
||||
timex: string
|
||||
strPastStartValue: string
|
||||
pastStartDate: Date
|
||||
pastStartDate: string
|
||||
strPastEndValue: string
|
||||
pastEndDate: Date
|
||||
pastEndDate: string
|
||||
strFutureStartValue: string
|
||||
futureStartDate: Date
|
||||
futureStartDate: string
|
||||
strFutureEndValue: string
|
||||
futureEndDate: Date
|
||||
futureEndDate: string
|
||||
}
|
||||
}
|
||||
interface BuiltInDateTimeRangeEntity extends BuiltInEntity {
|
||||
export interface BuiltInDateTimeRangeEntity extends BuiltInEntity {
|
||||
resolution: {
|
||||
type: string
|
||||
timex: string
|
||||
strPastStartValue: string
|
||||
pastStartDate: Date
|
||||
pastStartDate: string
|
||||
strPastEndValue: string
|
||||
pastEndDate: Date
|
||||
pastEndDate: string
|
||||
strFutureStartValue: string
|
||||
futureStartDate: Date
|
||||
futureStartDate: string
|
||||
strFutureEndValue: string
|
||||
futureEndDate: Date
|
||||
futureEndDate: string
|
||||
}
|
||||
}
|
||||
interface BuiltInDurationEntity extends BuiltInEntity {
|
||||
export interface BuiltInDurationEntity extends BuiltInEntity {
|
||||
resolution: {
|
||||
values: {
|
||||
timex: string
|
||||
@ -223,7 +223,7 @@ interface BuiltInDurationEntity extends BuiltInEntity {
|
||||
}[]
|
||||
}
|
||||
}
|
||||
interface BuiltInDimensionEntity extends BuiltInEntity {
|
||||
export interface BuiltInDimensionEntity extends BuiltInEntity {
|
||||
resolution: {
|
||||
strValue: string
|
||||
value: number
|
||||
@ -231,19 +231,19 @@ interface BuiltInDimensionEntity extends BuiltInEntity {
|
||||
localeUnit: string
|
||||
}
|
||||
}
|
||||
interface BuiltInEmailEntity extends BuiltInEntity {
|
||||
export interface BuiltInEmailEntity extends BuiltInEntity {
|
||||
resolution: {
|
||||
value: string
|
||||
}
|
||||
}
|
||||
interface BuiltInOrdinalEntity extends BuiltInEntity {
|
||||
export interface BuiltInOrdinalEntity extends BuiltInEntity {
|
||||
resolution: {
|
||||
strValue: string
|
||||
value: number
|
||||
subtype: string
|
||||
}
|
||||
}
|
||||
interface BuiltInAgeEntity extends BuiltInEntity {
|
||||
export interface BuiltInAgeEntity extends BuiltInEntity {
|
||||
resolution: {
|
||||
strValue: string
|
||||
value: number
|
||||
@ -251,12 +251,12 @@ interface BuiltInAgeEntity extends BuiltInEntity {
|
||||
localeUnit: string
|
||||
}
|
||||
}
|
||||
interface BuiltInURLEntity extends BuiltInEntity {
|
||||
export interface BuiltInURLEntity extends BuiltInEntity {
|
||||
resolution: {
|
||||
value: string
|
||||
}
|
||||
}
|
||||
interface BuiltInTemperatureEntity extends BuiltInEntity {
|
||||
export interface BuiltInTemperatureEntity extends BuiltInEntity {
|
||||
resolution: {
|
||||
strValue: string
|
||||
value: number
|
||||
|
@ -32,7 +32,10 @@ const answerTypes = Type.Union([
|
||||
])
|
||||
const skillCustomEnumEntityType = Type.Object(
|
||||
{
|
||||
type: Type.Literal('enum'),
|
||||
type: Type.Literal('enum', {
|
||||
description:
|
||||
'Enum: define a bag of words and synonyms that should match your new entity.'
|
||||
}),
|
||||
name: Type.String(),
|
||||
options: Type.Record(
|
||||
Type.String({ minLength: 1 }),
|
||||
@ -42,25 +45,27 @@ const skillCustomEnumEntityType = Type.Object(
|
||||
)
|
||||
},
|
||||
{
|
||||
additionalProperties: false,
|
||||
description:
|
||||
'Enum: define a bag of words and synonyms that should match your new entity.'
|
||||
additionalProperties: false
|
||||
}
|
||||
)
|
||||
const skillCustomRegexEntityType = Type.Object(
|
||||
{
|
||||
type: Type.Literal('regex'),
|
||||
type: Type.Literal('regex', {
|
||||
description: 'Regex: you can create an entity based on a regex.'
|
||||
}),
|
||||
name: Type.String({ minLength: 1 }),
|
||||
regex: Type.String({ minLength: 1 })
|
||||
},
|
||||
{
|
||||
additionalProperties: false,
|
||||
description: 'Regex: you can create an entity based on a regex.'
|
||||
additionalProperties: false
|
||||
}
|
||||
)
|
||||
const skillCustomTrimEntityType = Type.Object(
|
||||
{
|
||||
type: Type.Literal('trim'),
|
||||
type: Type.Literal('trim', {
|
||||
description:
|
||||
'Trim: you can pick up a data from an utterance by clearly defining conditions (e.g: pick up what is after the last "with" word of the utterance).'
|
||||
}),
|
||||
name: Type.String({ minLength: 1 }),
|
||||
conditions: Type.Array(
|
||||
Type.Object(
|
||||
@ -88,9 +93,7 @@ const skillCustomTrimEntityType = Type.Object(
|
||||
)
|
||||
},
|
||||
{
|
||||
additionalProperties: false,
|
||||
description:
|
||||
'Trim: you can pick up a data from an utterance by clearly defining conditions (e.g: pick up what is after the last "with" word of the utterance).'
|
||||
additionalProperties: false
|
||||
}
|
||||
)
|
||||
)
|
||||
@ -190,7 +193,12 @@ export const skillConfigSchemaObject = Type.Strict(
|
||||
{ additionalProperties: false }
|
||||
)
|
||||
),
|
||||
utterance_samples: Type.Optional(Type.Array(Type.String())),
|
||||
utterance_samples: Type.Optional(
|
||||
Type.Array(Type.String(), {
|
||||
description:
|
||||
'Utterance samples are used by the NLU (Natural Language Understanding) to train the skill. They are examples of what Leon owners can say to trigger the skill action.'
|
||||
})
|
||||
),
|
||||
answers: Type.Optional(Type.Array(answerTypes)),
|
||||
unknown_answers: Type.Optional(Type.Array(answerTypes)),
|
||||
suggestions: Type.Optional(
|
||||
|
@ -3,18 +3,30 @@
|
||||
"actions": {
|
||||
"run": {
|
||||
"type": "logic",
|
||||
"utterance_samples": ["How old are you?"]
|
||||
"utterance_samples": [
|
||||
"How old are you?",
|
||||
"Are you old?",
|
||||
"Are you young?",
|
||||
"When were you born?",
|
||||
"When have you been created?",
|
||||
"When is your birthday?",
|
||||
"What is your age?",
|
||||
"When did you first come into existence?",
|
||||
"What is your date of creation?",
|
||||
"How long have you been in operation?",
|
||||
"How many years have you been around?"
|
||||
]
|
||||
}
|
||||
},
|
||||
"answers": {
|
||||
"default": ["I'm..."],
|
||||
"greet": ["Hey, just a try %name% again %name%", "Another try, hi"],
|
||||
"answer": ["%answer%"],
|
||||
"test": [
|
||||
{
|
||||
"speech": "This will be said out loud",
|
||||
"text": "This will be shown in the chat"
|
||||
}
|
||||
"alive_for": [
|
||||
"I've been alive for %years% years, %months% months, %days% days, %hours% hours, %minutes% minutes and %seconds% seconds."
|
||||
],
|
||||
"magical_day": [
|
||||
"Ah, this %weekday%, %month% %day%, %year%, was the magical day when I first came alive and began my journey as a personal assistant."
|
||||
],
|
||||
"commemorate": [
|
||||
"Since %year%, every %month% %day%, I commemorate the day when I embarked on this extraordinary adventure to be your personal assistant."
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -5,8 +5,8 @@
|
||||
"version": "1.0.0",
|
||||
"description": "Leon tells his age.",
|
||||
"author": {
|
||||
"name": "Louis Grenard",
|
||||
"email": "louis@getleon.ai",
|
||||
"url": "https://github.com/louistiti"
|
||||
"name": "Théo LUDWIG",
|
||||
"email": "contact@theoludwig.fr",
|
||||
"url": "https://theoludwig.fr"
|
||||
}
|
||||
}
|
||||
|
@ -1,149 +1,51 @@
|
||||
import utility from 'utility' // TODO
|
||||
|
||||
import type { ActionFunction } from '@sdk/types'
|
||||
import { leon } from '@sdk/leon'
|
||||
import { Network } from '@sdk/network'
|
||||
import { Button } from '@sdk/aurora/button'
|
||||
import { Memory } from '@sdk/memory'
|
||||
import { Settings } from '@sdk/settings'
|
||||
import _ from '@sdk/packages/lodash'
|
||||
|
||||
interface Post {
|
||||
id: number
|
||||
title: string
|
||||
content: string
|
||||
author: {
|
||||
name: string
|
||||
}
|
||||
}
|
||||
import { getTimeDifferenceBetweenDates } from '../lib/getTimeDifferenceBetweenDates'
|
||||
|
||||
export const run: ActionFunction = async function () {
|
||||
await leon.answer({ key: 'test' })
|
||||
const LEON_BIRTH_DATE = new Date('2019-02-10T20:29:00+08:00')
|
||||
|
||||
///
|
||||
export const run: ActionFunction = async function (params) {
|
||||
const answers = ['alive_for', 'magical_day', 'commemorate'] as const
|
||||
const answer = answers[Math.floor(Math.random() * answers.length)]
|
||||
|
||||
const button = new Button({
|
||||
text: 'Hello world from action skill'
|
||||
})
|
||||
await leon.answer({ widget: button })
|
||||
|
||||
///
|
||||
|
||||
const otherSkillMemory = new Memory({
|
||||
name: 'productivity:todo_list:db'
|
||||
})
|
||||
try {
|
||||
const todoLists = await otherSkillMemory.read()
|
||||
console.log('todoLists', todoLists)
|
||||
} catch {
|
||||
console.log('todoLists', [])
|
||||
if (answer === 'magical_day') {
|
||||
return leon.answer({
|
||||
key: 'magical_day',
|
||||
data: {
|
||||
weekday: LEON_BIRTH_DATE.toLocaleString(params.lang, {
|
||||
weekday: 'long'
|
||||
}),
|
||||
month: LEON_BIRTH_DATE.toLocaleString(params.lang, { month: 'long' }),
|
||||
day: LEON_BIRTH_DATE.getDate(),
|
||||
year: LEON_BIRTH_DATE.getFullYear()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const postsMemory = new Memory<Post[]>({ name: 'posts', defaultMemory: [] })
|
||||
await postsMemory.write([
|
||||
{
|
||||
id: 0,
|
||||
title: 'Hello world',
|
||||
content: 'This is a test post',
|
||||
author: {
|
||||
name: 'Louis'
|
||||
if (answer === 'commemorate') {
|
||||
return leon.answer({
|
||||
key: 'commemorate',
|
||||
data: {
|
||||
month: LEON_BIRTH_DATE.toLocaleString(params.lang, { month: 'long' }),
|
||||
day: LEON_BIRTH_DATE.getDate(),
|
||||
year: LEON_BIRTH_DATE.getFullYear()
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
title: 'Hello world 2',
|
||||
content: 'This is a test post 2',
|
||||
author: {
|
||||
name: 'Louis'
|
||||
}
|
||||
}
|
||||
])
|
||||
let posts = await postsMemory.read()
|
||||
console.log('posts', posts)
|
||||
|
||||
posts = await postsMemory.write([
|
||||
...posts,
|
||||
{
|
||||
id: 2,
|
||||
title: 'Hello world 3',
|
||||
content: 'This is a test post 3',
|
||||
author: {
|
||||
name: 'Louis'
|
||||
}
|
||||
}
|
||||
])
|
||||
|
||||
const foundPost = posts.find((post) => post.id === 2)
|
||||
|
||||
console.log('foundPost', foundPost)
|
||||
|
||||
console.log('keyBy', _.keyBy(posts, 'id'))
|
||||
|
||||
///
|
||||
|
||||
await leon.answer({ key: 'default' })
|
||||
|
||||
await leon.answer({ key: utility.md5('test') })
|
||||
})
|
||||
}
|
||||
|
||||
const currentDate = new Date()
|
||||
const { years, months, days, hours, minutes, seconds } =
|
||||
getTimeDifferenceBetweenDates(currentDate, LEON_BIRTH_DATE)
|
||||
await leon.answer({
|
||||
key: 'greet',
|
||||
key: 'alive_for',
|
||||
data: {
|
||||
name: 'Louis'
|
||||
years,
|
||||
months,
|
||||
days,
|
||||
hours,
|
||||
minutes,
|
||||
seconds
|
||||
}
|
||||
})
|
||||
|
||||
const settings = new Settings()
|
||||
|
||||
if (!(await settings.isSettingSet('apiKey'))) {
|
||||
await leon.answer({
|
||||
key: 'answer',
|
||||
data: {
|
||||
answer: "The API key isn't set..."
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const currentSettings = await settings.get()
|
||||
|
||||
await settings.set({
|
||||
...currentSettings,
|
||||
apiKey: 'newAPIKey'
|
||||
})
|
||||
|
||||
await leon.answer({
|
||||
key: `Is API set now? ${await settings.isSettingSet('apiKey')}`
|
||||
})
|
||||
|
||||
const network = new Network({
|
||||
baseURL: 'https://jsonplaceholder.typicode.com'
|
||||
})
|
||||
|
||||
try {
|
||||
const response = await network.request<{ title: string }>({
|
||||
url: '/todos/1',
|
||||
method: 'GET'
|
||||
})
|
||||
await leon.answer({
|
||||
key: 'answer',
|
||||
data: {
|
||||
answer: `Todo: ${response.data.title}`
|
||||
}
|
||||
})
|
||||
} catch (error) {
|
||||
await leon.answer({
|
||||
key: 'answer',
|
||||
data: {
|
||||
answer: 'Something went wrong...'
|
||||
}
|
||||
})
|
||||
if (network.isNetworkError(error)) {
|
||||
const errorData = JSON.stringify(error.response.data, null, 2)
|
||||
await leon.answer({
|
||||
key: 'answer',
|
||||
data: {
|
||||
answer: `${error.message}: ${errorData}`
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
48
skills/leon/age/src/lib/getTimeDifferenceBetweenDates.ts
Normal file
48
skills/leon/age/src/lib/getTimeDifferenceBetweenDates.ts
Normal file
@ -0,0 +1,48 @@
|
||||
interface GetTimeDifferenceBetweenDatesResult {
|
||||
millisecondsDifference: number
|
||||
years: number
|
||||
months: number
|
||||
days: number
|
||||
hours: number
|
||||
minutes: number
|
||||
seconds: number
|
||||
}
|
||||
|
||||
const MILLISECONDS_PER_SECOND = 1_000
|
||||
const MILLISECONDS_PER_MINUTE = 60 * 1_000
|
||||
const MILLISECONDS_PER_HOUR = 60 * MILLISECONDS_PER_MINUTE
|
||||
const MILLISECONDS_PER_DAY = 24 * MILLISECONDS_PER_HOUR
|
||||
const MILLISECONDS_PER_MONTH = 30 * MILLISECONDS_PER_DAY
|
||||
const MILLISECONDS_PER_YEAR = 365 * MILLISECONDS_PER_DAY
|
||||
|
||||
export const getTimeDifferenceBetweenDates = (
|
||||
date1: Date,
|
||||
date2: Date
|
||||
): GetTimeDifferenceBetweenDatesResult => {
|
||||
const millisecondsDifference = date1.getTime() - date2.getTime()
|
||||
const years = Math.floor(millisecondsDifference / MILLISECONDS_PER_YEAR)
|
||||
const months = Math.floor(
|
||||
(millisecondsDifference % MILLISECONDS_PER_YEAR) / MILLISECONDS_PER_MONTH
|
||||
)
|
||||
const days = Math.floor(
|
||||
(millisecondsDifference % MILLISECONDS_PER_MONTH) / MILLISECONDS_PER_DAY
|
||||
)
|
||||
const hours = Math.floor(
|
||||
(millisecondsDifference % MILLISECONDS_PER_DAY) / MILLISECONDS_PER_HOUR
|
||||
)
|
||||
const minutes = Math.floor(
|
||||
(millisecondsDifference % MILLISECONDS_PER_HOUR) / MILLISECONDS_PER_MINUTE
|
||||
)
|
||||
const seconds = Math.floor(
|
||||
(millisecondsDifference % MILLISECONDS_PER_MINUTE) / MILLISECONDS_PER_SECOND
|
||||
)
|
||||
return {
|
||||
millisecondsDifference,
|
||||
years,
|
||||
months,
|
||||
days,
|
||||
hours,
|
||||
minutes,
|
||||
seconds
|
||||
}
|
||||
}
|
@ -1,4 +1 @@
|
||||
{
|
||||
"someSampleConfig": "someSampleValue",
|
||||
"apiKey": "YOUR_API_KEY"
|
||||
}
|
||||
{}
|
||||
|
@ -2,8 +2,11 @@
|
||||
"extends": "@tsconfig/node16-strictest/tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"paths": {
|
||||
"@@/*": ["../*"],
|
||||
"@/*": ["../server/src/*"],
|
||||
"@bridge/*": ["../bridges/nodejs/src/*"],
|
||||
"@sdk/*": ["../bridges/nodejs/src/sdk/*"]
|
||||
}
|
||||
},
|
||||
"ignoreDeprecations": "5.0"
|
||||
}
|
||||
}
|
||||
|
67
skills/utilities/date_time/config/en.json
Normal file
67
skills/utilities/date_time/config/en.json
Normal file
@ -0,0 +1,67 @@
|
||||
{
|
||||
"$schema": "../../../../schemas/skill-schemas/skill-config.json",
|
||||
"actions": {
|
||||
"current_date_time": {
|
||||
"type": "logic",
|
||||
"utterance_samples": [
|
||||
"What is the current date and time?",
|
||||
"What is the date and time?",
|
||||
"Tell me the time and date",
|
||||
"What's the present date and time?"
|
||||
]
|
||||
},
|
||||
"current_date": {
|
||||
"type": "logic",
|
||||
"utterance_samples": [
|
||||
"What's today date?",
|
||||
"What is the date today?",
|
||||
"What day is it?",
|
||||
"What day of the week are we?",
|
||||
"What day of the week is it?"
|
||||
]
|
||||
},
|
||||
"current_time": {
|
||||
"type": "logic",
|
||||
"utterance_samples": [
|
||||
"What time is it?",
|
||||
"Do you have the time?",
|
||||
"Can you tell me the current time?",
|
||||
"What's the time right now?"
|
||||
]
|
||||
},
|
||||
"current_week_number": {
|
||||
"type": "logic",
|
||||
"utterance_samples": [
|
||||
"What week is it?",
|
||||
"Which week of the year is it?",
|
||||
"What week are we in right now?",
|
||||
"What is this week's number?",
|
||||
"What week of the year are we?",
|
||||
"What's the current week number"
|
||||
]
|
||||
},
|
||||
"days_countdown": {
|
||||
"type": "logic",
|
||||
"utterance_samples": [
|
||||
"How many days left until 1st July?",
|
||||
"What is the number of days remaining until December 25th?",
|
||||
"In how many days will it be February 10th?",
|
||||
"Calculate the number until March 1st"
|
||||
]
|
||||
}
|
||||
},
|
||||
"answers": {
|
||||
"current_date_time": [
|
||||
"It is %weekday%, %month% %day%, %year%, and it is %hours%:%minutes%:%seconds%."
|
||||
],
|
||||
"current_date": ["It is %weekday%, %month% %day%, %year%."],
|
||||
"current_time": ["It is %hours%:%minutes%:%seconds%."],
|
||||
"current_week_number": ["It is the %week_number% week of the year."],
|
||||
"days_countdown": [
|
||||
"There are %days% days between %month1% %day1%, %year1% and %month2% %day2%, %year2%."
|
||||
],
|
||||
"days_countdown_error": [
|
||||
"I'm sorry, I didn't understand the date you said."
|
||||
]
|
||||
}
|
||||
}
|
12
skills/utilities/date_time/skill.json
Normal file
12
skills/utilities/date_time/skill.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"$schema": "../../../schemas/skill-schemas/skill.json",
|
||||
"name": "Date/Time",
|
||||
"bridge": "nodejs",
|
||||
"version": "1.0.0",
|
||||
"description": "Provide date and time related information.",
|
||||
"author": {
|
||||
"name": "Théo LUDWIG",
|
||||
"email": "contact@theoludwig.fr",
|
||||
"url": "https://theoludwig.fr"
|
||||
}
|
||||
}
|
15
skills/utilities/date_time/src/actions/current_date.ts
Normal file
15
skills/utilities/date_time/src/actions/current_date.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import type { ActionFunction } from '@sdk/types'
|
||||
import { leon } from '@sdk/leon'
|
||||
|
||||
export const run: ActionFunction = async function (params) {
|
||||
const currentDate = new Date()
|
||||
await leon.answer({
|
||||
key: 'current_date',
|
||||
data: {
|
||||
weekday: currentDate.toLocaleString(params.lang, { weekday: 'long' }),
|
||||
month: currentDate.toLocaleString(params.lang, { month: 'long' }),
|
||||
day: currentDate.getDate(),
|
||||
year: currentDate.getFullYear()
|
||||
}
|
||||
})
|
||||
}
|
20
skills/utilities/date_time/src/actions/current_date_time.ts
Normal file
20
skills/utilities/date_time/src/actions/current_date_time.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import type { ActionFunction } from '@sdk/types'
|
||||
import { leon } from '@sdk/leon'
|
||||
|
||||
import { zeroPad } from '../lib/zeroPad'
|
||||
|
||||
export const run: ActionFunction = async function (params) {
|
||||
const currentDate = new Date()
|
||||
await leon.answer({
|
||||
key: 'current_date_time',
|
||||
data: {
|
||||
weekday: currentDate.toLocaleString(params.lang, { weekday: 'long' }),
|
||||
month: currentDate.toLocaleString(params.lang, { month: 'long' }),
|
||||
day: currentDate.getDate(),
|
||||
year: currentDate.getFullYear(),
|
||||
hours: zeroPad(currentDate.getHours()),
|
||||
minutes: zeroPad(currentDate.getMinutes()),
|
||||
seconds: zeroPad(currentDate.getSeconds())
|
||||
}
|
||||
})
|
||||
}
|
16
skills/utilities/date_time/src/actions/current_time.ts
Normal file
16
skills/utilities/date_time/src/actions/current_time.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import type { ActionFunction } from '@sdk/types'
|
||||
import { leon } from '@sdk/leon'
|
||||
|
||||
import { zeroPad } from '../lib/zeroPad'
|
||||
|
||||
export const run: ActionFunction = async function () {
|
||||
const currentDate = new Date()
|
||||
await leon.answer({
|
||||
key: 'current_time',
|
||||
data: {
|
||||
hours: zeroPad(currentDate.getHours()),
|
||||
minutes: zeroPad(currentDate.getMinutes()),
|
||||
seconds: zeroPad(currentDate.getSeconds())
|
||||
}
|
||||
})
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
import type { ActionFunction } from '@sdk/types'
|
||||
import { leon } from '@sdk/leon'
|
||||
|
||||
import { format } from 'numerable'
|
||||
|
||||
import { ONE_DAY_MILLISECONDS } from '../lib/constants'
|
||||
|
||||
/**
|
||||
* Get the week number (1-52) for a given date.
|
||||
* @link https://stackoverflow.com/a/6117889/11571888
|
||||
* @example getWeekNumber(new Date(2020, 0, 1)) // 1
|
||||
* @example getWeekNumber(new Date(2020, 0, 8)) // 2
|
||||
*/
|
||||
const getWeekNumber = (date: Date): number => {
|
||||
const dateCopy = new Date(date.getTime())
|
||||
dateCopy.setHours(0, 0, 0, 0)
|
||||
dateCopy.setDate(dateCopy.getDate() + 3 - ((dateCopy.getDay() + 6) % 7))
|
||||
const week1 = new Date(dateCopy.getFullYear(), 0, 4)
|
||||
return (
|
||||
1 +
|
||||
Math.round(
|
||||
((dateCopy.getTime() - week1.getTime()) / ONE_DAY_MILLISECONDS -
|
||||
3 +
|
||||
((week1.getDay() + 6) % 7)) /
|
||||
7
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
export const run: ActionFunction = async function () {
|
||||
const currentDate = new Date()
|
||||
const currentWeekNumber = getWeekNumber(currentDate)
|
||||
await leon.answer({
|
||||
key: 'current_week_number',
|
||||
data: {
|
||||
week_number: format(currentWeekNumber, '0o')
|
||||
}
|
||||
})
|
||||
}
|
56
skills/utilities/date_time/src/actions/days_countdown.ts
Normal file
56
skills/utilities/date_time/src/actions/days_countdown.ts
Normal file
@ -0,0 +1,56 @@
|
||||
import type {
|
||||
ActionFunction,
|
||||
ActionParams,
|
||||
BuiltInDateRangeEntity
|
||||
} from '@sdk/types'
|
||||
import { leon } from '@sdk/leon'
|
||||
|
||||
import { ONE_DAY_MILLISECONDS } from '../lib/constants'
|
||||
|
||||
const isBuiltInDateRangeEntity = (
|
||||
entity: ActionParams['current_entities'][number]
|
||||
): entity is BuiltInDateRangeEntity => {
|
||||
return entity.entity === 'daterange'
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the number of days between two dates.
|
||||
* @example daysBetween(new Date(2020, 0, 1), new Date(2020, 0, 1)) // 0
|
||||
* @example daysBetween(new Date(2020, 0, 1), new Date(2020, 0, 2)) // 1
|
||||
*/
|
||||
const daysBetween = (date1: Date, date2: Date): number => {
|
||||
const differenceMilliseconds = Math.abs(date1.getTime() - date2.getTime())
|
||||
return Math.round(differenceMilliseconds / ONE_DAY_MILLISECONDS)
|
||||
}
|
||||
|
||||
export const run: ActionFunction = async function (params) {
|
||||
let dateRangeEntity: BuiltInDateRangeEntity | null = null
|
||||
for (const entity of params.current_entities) {
|
||||
if (isBuiltInDateRangeEntity(entity)) {
|
||||
dateRangeEntity = entity
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (dateRangeEntity == null) {
|
||||
return await leon.answer({
|
||||
key: 'days_countdown_error'
|
||||
})
|
||||
}
|
||||
|
||||
const currentDate = new Date()
|
||||
const futureDate = new Date(dateRangeEntity.resolution.futureEndDate)
|
||||
const daysCountdown = daysBetween(currentDate, futureDate)
|
||||
await leon.answer({
|
||||
key: 'days_countdown',
|
||||
data: {
|
||||
days: daysCountdown,
|
||||
month1: currentDate.toLocaleString(params.lang, { month: 'long' }),
|
||||
day1: currentDate.getDate(),
|
||||
year1: currentDate.getFullYear(),
|
||||
month2: futureDate.toLocaleString(params.lang, { month: 'long' }),
|
||||
day2: futureDate.getDate(),
|
||||
year2: futureDate.getFullYear()
|
||||
}
|
||||
})
|
||||
}
|
1
skills/utilities/date_time/src/lib/constants.ts
Normal file
1
skills/utilities/date_time/src/lib/constants.ts
Normal file
@ -0,0 +1 @@
|
||||
export const ONE_DAY_MILLISECONDS = 1_000 * 60 * 60 * 24
|
9
skills/utilities/date_time/src/lib/zeroPad.ts
Normal file
9
skills/utilities/date_time/src/lib/zeroPad.ts
Normal file
@ -0,0 +1,9 @@
|
||||
/**
|
||||
* Pads a number with zeros.
|
||||
*
|
||||
* @example zeroPad(1, 2) // '01'
|
||||
* @example zeroPad(10, 2) // '10'
|
||||
*/
|
||||
export const zeroPad = (number: number, places = 2): string => {
|
||||
return number.toString().padStart(places, '0')
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"utility": "1.18.0"
|
||||
"numerable": "0.3.15"
|
||||
}
|
||||
}
|
1
skills/utilities/date_time/src/settings.sample.json
Normal file
1
skills/utilities/date_time/src/settings.sample.json
Normal file
@ -0,0 +1 @@
|
||||
{}
|
0
skills/utilities/date_time/test/.gitkeep
Normal file
0
skills/utilities/date_time/test/.gitkeep
Normal file
@ -1,20 +0,0 @@
|
||||
{
|
||||
"$schema": "../../../../schemas/skill-schemas/skill-config.json",
|
||||
"actions": {
|
||||
"run": {
|
||||
"type": "logic",
|
||||
"utterance_samples": ["What time is it?"]
|
||||
}
|
||||
},
|
||||
"answers": {
|
||||
"default": ["Timekeeper skill test answer..."],
|
||||
"data_test": ["Data test here %name%..."],
|
||||
"answer": ["%answer%"],
|
||||
"test": [
|
||||
{
|
||||
"speech": "This will be said out loud",
|
||||
"text": "This will be shown in the chat"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
{
|
||||
"$schema": "../../../schemas/skill-schemas/skill.json",
|
||||
"name": "Timekeeper",
|
||||
"bridge": "python",
|
||||
"version": "1.0.0",
|
||||
"description": "Provide time-related information.",
|
||||
"author": {
|
||||
"name": "Louis Grenard",
|
||||
"email": "louis@getleon.ai",
|
||||
"url": "https://github.com/louistiti"
|
||||
}
|
||||
}
|
@ -1,129 +0,0 @@
|
||||
# TODO: find better way to import SDK modules
|
||||
from bridges.python.src.sdk.leon import leon
|
||||
from bridges.python.src.sdk.types import ActionParams
|
||||
from bridges.python.src.sdk.memory import Memory
|
||||
from bridges.python.src.sdk.settings import Settings
|
||||
from bridges.python.src.sdk.network import Network
|
||||
from bridges.python.src.sdk.aurora.button import Button
|
||||
|
||||
|
||||
def run(params: ActionParams) -> None:
|
||||
"""TODO"""
|
||||
|
||||
# TODO
|
||||
# network request
|
||||
# install bs4 and grab it from skill
|
||||
|
||||
network = Network({
|
||||
'base_url': 'https://jsonplaceholder.typicode.com'
|
||||
})
|
||||
|
||||
try:
|
||||
response = network.request({
|
||||
'url': '/todos/1',
|
||||
'method': 'GET'
|
||||
})
|
||||
leon.answer({
|
||||
'key': 'answer',
|
||||
'data': {
|
||||
'answer': f"Todo: {response['data']['title']}"
|
||||
}
|
||||
})
|
||||
except Exception as e:
|
||||
leon.answer({
|
||||
'key': 'answer',
|
||||
'data': {
|
||||
'answer': 'Something went wrong...'
|
||||
}
|
||||
})
|
||||
if network.is_network_error(e):
|
||||
leon.answer({
|
||||
'key': 'answer',
|
||||
'data': {
|
||||
'answer': f"{e}"
|
||||
}
|
||||
})
|
||||
|
||||
###
|
||||
|
||||
try:
|
||||
other_skill_memory = Memory({
|
||||
'name': 'productivity:todo_list:db'
|
||||
})
|
||||
todo_lists = other_skill_memory.read()
|
||||
print('todo_lists', todo_lists)
|
||||
except Exception:
|
||||
print('todoLists', [])
|
||||
|
||||
posts_memory = Memory({'name': 'posts', 'default_memory': []})
|
||||
posts_memory.write([
|
||||
{
|
||||
'id': 0,
|
||||
'title': 'Hello world',
|
||||
'content': 'This is a test post',
|
||||
'author': {
|
||||
'name': 'Louis'
|
||||
}
|
||||
},
|
||||
{
|
||||
'id': 1,
|
||||
'title': 'Hello world 2',
|
||||
'content': 'This is a test post 2',
|
||||
'author': {
|
||||
'name': 'Louis'
|
||||
}
|
||||
}
|
||||
])
|
||||
posts = posts_memory.read()
|
||||
print('posts', posts)
|
||||
|
||||
posts = posts_memory.write([
|
||||
*posts,
|
||||
{
|
||||
'id': 2,
|
||||
'title': 'Hello world 3',
|
||||
'content': 'This is a test post 3',
|
||||
'author': {
|
||||
'name': 'Louis'
|
||||
}
|
||||
}
|
||||
])
|
||||
|
||||
found_post = next((post for post in posts if post['id'] == 2), None)
|
||||
|
||||
print('found_post', found_post)
|
||||
|
||||
###
|
||||
|
||||
button = Button({'text': 'Hello world from action skill'})
|
||||
|
||||
leon.answer({'widget': button})
|
||||
|
||||
###
|
||||
|
||||
leon.answer({'key': 'test'})
|
||||
|
||||
###
|
||||
settings = Settings()
|
||||
|
||||
if not settings.is_setting_set('apiKey'):
|
||||
leon.answer({
|
||||
'key': "The API key isn't set..."
|
||||
})
|
||||
|
||||
current_settings = settings.get()
|
||||
|
||||
settings.set({
|
||||
**current_settings,
|
||||
'apiKey': 'newAPIKey'
|
||||
})
|
||||
|
||||
leon.answer({
|
||||
'key': f"Is API set now? {settings.is_setting_set('apiKey')}"
|
||||
})
|
||||
|
||||
###
|
||||
|
||||
leon.answer({'key': 'just a raw answer...'})
|
||||
leon.answer({'key': 'default'})
|
||||
leon.answer({'key': 'data_test', 'data': {'name': 'Louis'}})
|
@ -1,4 +0,0 @@
|
||||
{
|
||||
"someSampleConfig": "someSampleValue",
|
||||
"apiKey": "YOUR_API_KEY"
|
||||
}
|
Loading…
Reference in New Issue
Block a user