Skip to content

Commit 4a38c1f

Browse files
committed
resolves #1964 [Bot API] Call a story from an other story
Signed-off-by: Julien Buret <jburet@gmail.com>
1 parent b34bbfa commit 4a38c1f

File tree

8 files changed

+100
-9
lines changed

8 files changed

+100
-9
lines changed

bot/api/client/src/main/kotlin/ClientBus.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,14 @@ interface ClientBus : Bus<ClientBus> {
168168
}
169169
}
170170

171+
/**
172+
* Handles the action and switches the context to the specified story definition.
173+
*/
174+
fun handleAndSwitchStory(
175+
storyId: String,
176+
starterIntent: String? = null,
177+
)
178+
171179
/**
172180
* Creates a new [Card].
173181
*/

bot/api/client/src/main/kotlin/TockClientBus.kt

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,15 @@ import ai.tock.bot.api.model.context.Entity
2323
import ai.tock.bot.api.model.message.bot.BotMessage
2424
import ai.tock.bot.api.model.message.bot.Card
2525
import ai.tock.bot.api.model.message.bot.Carousel
26+
import ai.tock.bot.api.model.message.bot.CustomAction
27+
import ai.tock.bot.api.model.message.bot.CustomActionType
2628
import ai.tock.bot.api.model.message.bot.CustomMessage
2729
import ai.tock.bot.api.model.message.bot.Debug
2830
import ai.tock.bot.api.model.message.bot.Event
2931
import ai.tock.bot.api.model.message.bot.EventCategory
3032
import ai.tock.bot.api.model.message.bot.I18nText
33+
import ai.tock.bot.api.model.message.bot.STARTER_INTENT
34+
import ai.tock.bot.api.model.message.bot.SWITCH_STORY_ID
3135
import ai.tock.bot.api.model.message.bot.Sentence
3236
import ai.tock.bot.api.model.message.bot.Suggestion
3337
import ai.tock.bot.api.model.message.user.UserMessage
@@ -36,6 +40,7 @@ import ai.tock.bot.connector.ConnectorMessage
3640
import ai.tock.bot.connector.ConnectorType
3741
import ai.tock.bot.definition.Intent
3842
import ai.tock.bot.definition.IntentAware
43+
import ai.tock.bot.definition.StoryDefinition
3944
import ai.tock.bot.engine.event.MetadataEvent.Companion.STREAM_RESPONSE_METADATA
4045
import ai.tock.bot.engine.user.PlayerId
4146
import ai.tock.shared.jackson.ConstrainedValueWrapper
@@ -64,10 +69,10 @@ class TockClientBus(
6469
override val userLocale: Locale = request.context.language
6570
override val userInterfaceType: UserInterfaceType = request.context.userInterface
6671

67-
// Source connector : is the connector which initialize a conversation
72+
// Source connector: is the connector which initialize a conversation
6873
override val sourceConnectorType: ConnectorType = request.context.sourceConnectorType
6974

70-
// Target connector : is the connector for which the message is produced
75+
// Target connector: is the connector for which the message is produced
7176
override val targetConnectorType: ConnectorType = request.context.targetConnectorType
7277

7378
override val contextId: String = request.context.userId.id
@@ -290,4 +295,26 @@ class TockClientBus(
290295
args,
291296
)
292297
}
298+
299+
override fun handleAndSwitchStory(
300+
storyDefinition: StoryDefinition,
301+
starterIntent: Intent,
302+
) {
303+
handleAndSwitchStory(storyDefinition.id, starterIntent.wrappedIntent().name)
304+
}
305+
306+
override fun handleAndSwitchStory(
307+
storyId: String,
308+
starterIntent: String?,
309+
) {
310+
addMessage(
311+
CustomAction(
312+
CustomActionType.SWITCH_STORY,
313+
mapOf(
314+
SWITCH_STORY_ID to storyId,
315+
STARTER_INTENT to starterIntent,
316+
),
317+
),
318+
)
319+
}
293320
}

bot/api/model/src/main/kotlin/message/bot/BotMessage.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo
3131
JsonSubTypes.Type(value = Carousel::class, name = "carousel"),
3232
JsonSubTypes.Type(value = Debug::class, name = "debug"),
3333
JsonSubTypes.Type(value = Event::class, name = "event"),
34+
JsonSubTypes.Type(value = CustomAction::class, name = "action"),
3435
)
3536
interface BotMessage {
3637
/**
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* Copyright (C) 2017/2025 SNCF Connect & Tech
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package ai.tock.bot.api.model.message.bot
18+
19+
enum class CustomActionType {
20+
SWITCH_STORY,
21+
}
22+
23+
const val SWITCH_STORY_ID = "switch_story_id"
24+
const val STARTER_INTENT = "starter_intent"
25+
26+
data class CustomAction(
27+
val type: CustomActionType,
28+
val parameters: Map<String, String?> = emptyMap(),
29+
override val delay: Long = 0,
30+
) : BotMessage

bot/api/service/src/main/kotlin/BotApiHandler.kt

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,21 @@ import ai.tock.bot.api.model.configuration.ClientConfiguration
2424
import ai.tock.bot.api.model.message.bot.BotMessage
2525
import ai.tock.bot.api.model.message.bot.Card
2626
import ai.tock.bot.api.model.message.bot.Carousel
27+
import ai.tock.bot.api.model.message.bot.CustomAction
28+
import ai.tock.bot.api.model.message.bot.CustomActionType.SWITCH_STORY
2729
import ai.tock.bot.api.model.message.bot.CustomMessage
2830
import ai.tock.bot.api.model.message.bot.Debug
2931
import ai.tock.bot.api.model.message.bot.Event
3032
import ai.tock.bot.api.model.message.bot.EventCategory
3133
import ai.tock.bot.api.model.message.bot.I18nText
34+
import ai.tock.bot.api.model.message.bot.STARTER_INTENT
35+
import ai.tock.bot.api.model.message.bot.SWITCH_STORY_ID
3236
import ai.tock.bot.api.model.message.bot.Sentence
3337
import ai.tock.bot.connector.media.MediaAction
3438
import ai.tock.bot.connector.media.MediaCard
3539
import ai.tock.bot.connector.media.MediaCarousel
3640
import ai.tock.bot.connector.media.MediaFile
41+
import ai.tock.bot.definition.Intent
3742
import ai.tock.bot.definition.StoryDefinition
3843
import ai.tock.bot.definition.StoryStep
3944
import ai.tock.bot.engine.BotBus
@@ -82,7 +87,7 @@ internal class BotApiHandler(
8287
response: BotResponse?,
8388
) {
8489
if (response != null) {
85-
// Check if there is a configuration for Ending story
90+
// Check if there is a configuration for ending story
8691
val storySetting =
8792
storyDAO.getStoryDefinitionByNamespaceAndBotIdAndStoryId(
8893
botDefinition.namespace,
@@ -186,6 +191,19 @@ internal class BotApiHandler(
186191
return
187192
}
188193

194+
is CustomAction -> {
195+
when (message.type) {
196+
SWITCH_STORY -> {
197+
val storyId = message.parameters[SWITCH_STORY_ID] ?: error("no $SWITCH_STORY_ID parameter")
198+
199+
val story = botDefinition.findStoryDefinitionById(storyId, connectorId)
200+
val starterIntent = message.parameters[STARTER_INTENT]?.let { Intent(it) } ?: story.mainIntent()
201+
handleAndSwitchStory(story, starterIntent)
202+
return
203+
}
204+
}
205+
}
206+
189207
else -> error("unsupported message $message")
190208
}
191209

bot/engine/src/main/kotlin/definition/StoryDefinition.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import ai.tock.translator.UserInterfaceType
2222
* The definition of a "Story".
2323
* A story holds a list of actions of the same domain.
2424
* The story provides a set of starter intents.
25-
* When theses intents are detected, The story is started.
25+
* When these intents are detected, The story is started.
2626
*
2727
* Story definitions should usually not directly extend this class,
2828
* but instead extend [SimpleStoryHandlerBase] or [StoryDefinitionBase].

bot/engine/src/main/kotlin/engine/BotBus.kt

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -516,12 +516,9 @@ interface BotBus : Bus<BotBus>, DialogEntityAccess {
516516
currentDialog.state.currentIntent = starterIntent
517517
}
518518

519-
/**
520-
* Handles the action and switches the context to the specified story definition.
521-
*/
522-
fun handleAndSwitchStory(
519+
override fun handleAndSwitchStory(
523520
storyDefinition: StoryDefinition,
524-
starterIntent: Intent = storyDefinition.mainIntent(),
521+
starterIntent: Intent,
525522
) {
526523
switchStory(storyDefinition, starterIntent)
527524
hasCurrentSwitchStoryProcess = false

bot/engine/src/main/kotlin/engine/Bus.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ package ai.tock.bot.engine
1919
import ai.tock.bot.connector.ConnectorMessage
2020
import ai.tock.bot.connector.ConnectorMessageProvider
2121
import ai.tock.bot.connector.ConnectorType
22+
import ai.tock.bot.definition.Intent
2223
import ai.tock.bot.definition.IntentAware
24+
import ai.tock.bot.definition.StoryDefinition
2325
import ai.tock.bot.engine.user.PlayerId
2426

2527
/**
@@ -175,6 +177,14 @@ interface Bus<T : Bus<T>> : I18nTranslator {
175177
data: Any?,
176178
): T
177179

180+
/**
181+
* Handles the action and switches the context to the specified story definition.
182+
*/
183+
fun handleAndSwitchStory(
184+
storyDefinition: StoryDefinition,
185+
starterIntent: Intent = storyDefinition.mainIntent(),
186+
)
187+
178188
/**
179189
* Sends i18nText as last bot answer.
180190
*/

0 commit comments

Comments
 (0)