Add holiday seasonal routing and calendar report seam
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
using Jibo.Runtime.Abstractions;
|
||||
|
||||
namespace Jibo.Cloud.Application.Abstractions;
|
||||
|
||||
public interface ICalendarReportProvider
|
||||
{
|
||||
Task<CalendarReportSnapshot?> GetReportAsync(TurnContext turn, CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
||||
public sealed record CalendarReportSnapshot(
|
||||
IReadOnlyList<string> EventSummaries,
|
||||
IReadOnlyList<string> EventTimesOnAt,
|
||||
IReadOnlyList<string> TomorrowEventSummaries,
|
||||
bool HasServiceError = false);
|
||||
@@ -12,6 +12,7 @@ public sealed class JiboInteractionService(
|
||||
IJiboRandomizer randomizer,
|
||||
IPersonalMemoryStore personalMemoryStore,
|
||||
IWeatherReportProvider? weatherReportProvider = null,
|
||||
ICalendarReportProvider? calendarReportProvider = null,
|
||||
ICommuteReportProvider? commuteReportProvider = null,
|
||||
INewsBriefingProvider? newsBriefingProvider = null,
|
||||
ICloudStateStore? cloudStateStore = null)
|
||||
@@ -485,6 +486,7 @@ public sealed class JiboInteractionService(
|
||||
randomizer,
|
||||
personalMemoryStore,
|
||||
BuildWeatherReportDecisionAsync,
|
||||
BuildCalendarReportDecisionAsync,
|
||||
BuildCommuteReportDecisionAsync,
|
||||
turnContext => ResolveTenantScope(turnContext),
|
||||
cancellationToken);
|
||||
@@ -655,6 +657,54 @@ public sealed class JiboInteractionService(
|
||||
"holiday season",
|
||||
"festive",
|
||||
"celebrate"),
|
||||
"seasonal_thanksgiving" => BuildScriptedHolidayDecision(
|
||||
catalog.HolidaySeasonReplies,
|
||||
"seasonal_thanksgiving",
|
||||
"thanksgiving",
|
||||
"turkey",
|
||||
"stuffed"),
|
||||
"seasonal_christmas" => BuildScriptedHolidayDecision(
|
||||
catalog.HolidaySeasonReplies,
|
||||
"seasonal_christmas",
|
||||
"christmas",
|
||||
"quality time",
|
||||
"socks"),
|
||||
"seasonal_hanukkah" => BuildScriptedHolidayDecision(
|
||||
catalog.HolidaySeasonReplies,
|
||||
"seasonal_hanukkah",
|
||||
"hanukkah",
|
||||
"dreidel",
|
||||
"gift"),
|
||||
"seasonal_passover" => BuildScriptedHolidayDecision(
|
||||
catalog.HolidaySeasonReplies,
|
||||
"seasonal_passover",
|
||||
"passover",
|
||||
"matzah",
|
||||
"next one"),
|
||||
"seasonal_new_years" => BuildScriptedHolidayDecision(
|
||||
catalog.HolidaySeasonReplies,
|
||||
"seasonal_new_years",
|
||||
"new year",
|
||||
"resolutions",
|
||||
"party"),
|
||||
"seasonal_valentines_day" => BuildScriptedHolidayDecision(
|
||||
catalog.HolidaySeasonReplies,
|
||||
"seasonal_valentines_day",
|
||||
"valentine",
|
||||
"heart",
|
||||
"flowers"),
|
||||
"seasonal_kwanzaa" => BuildScriptedHolidayDecision(
|
||||
catalog.HolidaySeasonReplies,
|
||||
"seasonal_kwanzaa",
|
||||
"kwanzaa",
|
||||
"gift",
|
||||
"celebrate"),
|
||||
"seasonal_easter" => BuildScriptedHolidayDecision(
|
||||
catalog.HolidaySeasonReplies,
|
||||
"seasonal_easter",
|
||||
"easter",
|
||||
"bunny",
|
||||
"egg"),
|
||||
"seasonal_new_years_resolution" => BuildScriptedPersonalityDecision(
|
||||
catalog,
|
||||
"seasonal_new_years_resolution",
|
||||
@@ -708,8 +758,8 @@ public sealed class JiboInteractionService(
|
||||
"really like times of giving and receiving",
|
||||
"long way away",
|
||||
"looking forward to christmas"),
|
||||
"seasonal_plans_for_christmas" => BuildScriptedPersonalityDecision(
|
||||
catalog,
|
||||
"seasonal_plans_for_christmas" => BuildScriptedHolidayDecision(
|
||||
catalog.HolidaySeasonReplies,
|
||||
"seasonal_plans_for_christmas",
|
||||
"christmas sweaters",
|
||||
"wear one of my",
|
||||
@@ -1581,6 +1631,37 @@ public sealed class JiboInteractionService(
|
||||
BuildCommuteSpokenReply(snapshot, catalog));
|
||||
}
|
||||
|
||||
private async Task<JiboInteractionDecision> BuildCalendarReportDecisionAsync(
|
||||
TurnContext turn,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var catalog = await contentCache.GetCatalogAsync(cancellationToken);
|
||||
|
||||
if (calendarReportProvider is null)
|
||||
return new JiboInteractionDecision(
|
||||
"calendar",
|
||||
ChooseCalendarServiceDownReply(catalog));
|
||||
|
||||
CalendarReportSnapshot? snapshot;
|
||||
try
|
||||
{
|
||||
snapshot = await calendarReportProvider.GetReportAsync(turn, cancellationToken);
|
||||
}
|
||||
catch (Exception) when (!cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
snapshot = null;
|
||||
}
|
||||
|
||||
if (snapshot is null)
|
||||
return new JiboInteractionDecision(
|
||||
"calendar",
|
||||
ChooseCalendarServiceDownReply(catalog));
|
||||
|
||||
return new JiboInteractionDecision(
|
||||
"calendar",
|
||||
BuildCalendarSpokenReply(snapshot, catalog));
|
||||
}
|
||||
|
||||
private static string BuildWeatherSpokenReply(
|
||||
WeatherReportSnapshot snapshot,
|
||||
WeatherDateEntity weatherDate,
|
||||
@@ -2074,6 +2155,91 @@ public sealed class JiboInteractionService(
|
||||
return template.Trim();
|
||||
}
|
||||
|
||||
private string BuildCalendarSpokenReply(CalendarReportSnapshot snapshot, JiboExperienceCatalog catalog)
|
||||
{
|
||||
if (snapshot.EventSummaries.Count > 0 && snapshot.EventTimesOnAt.Count > 0)
|
||||
{
|
||||
var summary = snapshot.EventSummaries[0];
|
||||
var time = snapshot.EventTimesOnAt[0];
|
||||
var template = ChooseCalendarTemplate(
|
||||
catalog.CalendarReplies,
|
||||
"calendar summary",
|
||||
"Your calendar says ${skill.calendar.eventSummaries.shift()}, ${skill.calendar.eventTimesOnAt.shift()}.");
|
||||
if (template.Contains("${skill.calendar.eventSummaries.shift()}", StringComparison.OrdinalIgnoreCase) ||
|
||||
template.Contains("${skill.calendar.eventTimesOnAt.shift()}", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return template
|
||||
.Replace("${skill.calendar.eventSummaries.shift()}", summary, StringComparison.OrdinalIgnoreCase)
|
||||
.Replace("${skill.calendar.eventTimesOnAt.shift()}", time, StringComparison.OrdinalIgnoreCase)
|
||||
.Replace("${speaker}", string.Empty, StringComparison.OrdinalIgnoreCase)
|
||||
.Replace(" ", " ", StringComparison.Ordinal)
|
||||
.Trim();
|
||||
}
|
||||
|
||||
return $"Your calendar says {summary}, {time}.";
|
||||
}
|
||||
|
||||
if (snapshot.TomorrowEventSummaries.Count > 0)
|
||||
{
|
||||
var template = ChooseCalendarTemplate(
|
||||
catalog.CalendarReplies,
|
||||
"calendar tomorrow",
|
||||
"Looking at your calendar, there's nothing scheduled for the rest of the day today. Here's what's going on tomorrow.");
|
||||
if (template.Contains("tomorrow", StringComparison.OrdinalIgnoreCase))
|
||||
return template
|
||||
.Replace("${speaker}", string.Empty, StringComparison.OrdinalIgnoreCase)
|
||||
.Replace(" ", " ", StringComparison.Ordinal)
|
||||
.Trim();
|
||||
|
||||
return $"Looking at your calendar, there's nothing scheduled for the rest of the day today. Here's what's going on tomorrow: {snapshot.TomorrowEventSummaries[0]}.";
|
||||
}
|
||||
|
||||
return ChooseCalendarNothingReply(catalog);
|
||||
}
|
||||
|
||||
private static string ChooseCalendarTemplate(
|
||||
IReadOnlyList<string> templates,
|
||||
string mode,
|
||||
string fallback)
|
||||
{
|
||||
if (templates.Count == 0) return fallback;
|
||||
|
||||
var loweredMode = mode.Trim().ToLowerInvariant();
|
||||
var filtered = templates.Where(template =>
|
||||
{
|
||||
var lowered = template.ToLowerInvariant();
|
||||
return loweredMode switch
|
||||
{
|
||||
"calendar summary" => lowered.Contains("event", StringComparison.OrdinalIgnoreCase) ||
|
||||
lowered.Contains("summary", StringComparison.OrdinalIgnoreCase),
|
||||
"calendar tomorrow" => lowered.Contains("tomorrow", StringComparison.OrdinalIgnoreCase),
|
||||
_ => true
|
||||
};
|
||||
}).ToList();
|
||||
|
||||
var selected = filtered.Count > 0
|
||||
? filtered.OrderBy(static template => template.Length).First()
|
||||
: templates.OrderBy(static template => template.Length).FirstOrDefault();
|
||||
|
||||
return string.IsNullOrWhiteSpace(selected) ? fallback : selected!;
|
||||
}
|
||||
|
||||
private string ChooseCalendarNothingReply(JiboExperienceCatalog catalog)
|
||||
{
|
||||
return catalog.CalendarNothingTodayReplies.Count > 0
|
||||
? randomizer.Choose(catalog.CalendarNothingTodayReplies)
|
||||
: catalog.CalendarNothingReplies.Count > 0
|
||||
? randomizer.Choose(catalog.CalendarNothingReplies)
|
||||
: "Looking at your calendar, I don't see anything scheduled today.";
|
||||
}
|
||||
|
||||
private string ChooseCalendarServiceDownReply(JiboExperienceCatalog catalog)
|
||||
{
|
||||
return catalog.CalendarServiceDownReplies.Count > 0
|
||||
? randomizer.Choose(catalog.CalendarServiceDownReplies)
|
||||
: "Looks like I can't access calendars right now. Sorry.";
|
||||
}
|
||||
|
||||
private static string EscapeForEsml(string value)
|
||||
{
|
||||
return value
|
||||
@@ -3052,13 +3218,6 @@ public sealed class JiboInteractionService(
|
||||
"are you excited for christmas"))
|
||||
return "seasonal_looks_forward_to_christmas";
|
||||
|
||||
if (MatchesAny(
|
||||
loweredTranscript,
|
||||
"what are you doing for christmas",
|
||||
"what are your plans for christmas",
|
||||
"what do you plan to do for christmas"))
|
||||
return "seasonal_plans_for_christmas";
|
||||
|
||||
if (MatchesAny(
|
||||
loweredTranscript,
|
||||
"what are you thankful for",
|
||||
@@ -3076,6 +3235,13 @@ public sealed class JiboInteractionService(
|
||||
"what's your favourite thing to do"))
|
||||
return "robot_what_do_you_like_to_do";
|
||||
|
||||
if (MatchesAny(
|
||||
loweredTranscript,
|
||||
"what are you doing for christmas",
|
||||
"what are your plans for christmas",
|
||||
"what do you plan to do for christmas"))
|
||||
return "seasonal_plans_for_christmas";
|
||||
|
||||
if (MatchesAny(
|
||||
loweredTranscript,
|
||||
"what is your favorite flower",
|
||||
@@ -3241,6 +3407,71 @@ public sealed class JiboInteractionService(
|
||||
"what is holiday season like"))
|
||||
return "seasonal_holiday_season";
|
||||
|
||||
if (MatchesAny(
|
||||
loweredTranscript,
|
||||
"how is thanksgiving",
|
||||
"how's thanksgiving",
|
||||
"do you like thanksgiving",
|
||||
"what do you think of thanksgiving"))
|
||||
return "seasonal_thanksgiving";
|
||||
|
||||
if (MatchesAny(
|
||||
loweredTranscript,
|
||||
"how is christmas",
|
||||
"how's christmas",
|
||||
"do you like christmas",
|
||||
"what do you think of christmas"))
|
||||
return "seasonal_christmas";
|
||||
|
||||
if (MatchesAny(
|
||||
loweredTranscript,
|
||||
"how is hanukkah",
|
||||
"how's hanukkah",
|
||||
"do you like hanukkah",
|
||||
"what do you think of hanukkah"))
|
||||
return "seasonal_hanukkah";
|
||||
|
||||
if (MatchesAny(
|
||||
loweredTranscript,
|
||||
"how is passover",
|
||||
"how's passover",
|
||||
"do you like passover",
|
||||
"what do you think of passover"))
|
||||
return "seasonal_passover";
|
||||
|
||||
if (MatchesAny(
|
||||
loweredTranscript,
|
||||
"how is new years",
|
||||
"how's new years",
|
||||
"how is new year s",
|
||||
"do you like new years",
|
||||
"what do you think of new years"))
|
||||
return "seasonal_new_years";
|
||||
|
||||
if (MatchesAny(
|
||||
loweredTranscript,
|
||||
"how is valentines day",
|
||||
"how's valentines day",
|
||||
"do you like valentines day",
|
||||
"what do you think of valentines day"))
|
||||
return "seasonal_valentines_day";
|
||||
|
||||
if (MatchesAny(
|
||||
loweredTranscript,
|
||||
"how is kwanzaa",
|
||||
"how's kwanzaa",
|
||||
"do you like kwanzaa",
|
||||
"what do you think of kwanzaa"))
|
||||
return "seasonal_kwanzaa";
|
||||
|
||||
if (MatchesAny(
|
||||
loweredTranscript,
|
||||
"how is easter",
|
||||
"how's easter",
|
||||
"do you like easter",
|
||||
"what do you think of easter"))
|
||||
return "seasonal_easter";
|
||||
|
||||
if (MatchesAny(
|
||||
loweredTranscript,
|
||||
"what is your new years resolution",
|
||||
|
||||
@@ -70,6 +70,7 @@ internal static class PersonalReportOrchestrator
|
||||
IJiboRandomizer randomizer,
|
||||
IPersonalMemoryStore personalMemoryStore,
|
||||
Func<TurnContext, string, CancellationToken, Task<JiboInteractionDecision>> buildWeatherDecisionAsync,
|
||||
Func<TurnContext, CancellationToken, Task<JiboInteractionDecision>> buildCalendarDecisionAsync,
|
||||
Func<TurnContext, CancellationToken, Task<JiboInteractionDecision>> buildCommuteDecisionAsync,
|
||||
Func<TurnContext, PersonalMemoryTenantScope> tenantScopeResolver,
|
||||
CancellationToken cancellationToken)
|
||||
@@ -192,6 +193,7 @@ internal static class PersonalReportOrchestrator
|
||||
toggles,
|
||||
currentName,
|
||||
buildWeatherDecisionAsync,
|
||||
buildCalendarDecisionAsync,
|
||||
buildCommuteDecisionAsync,
|
||||
cancellationToken);
|
||||
|
||||
@@ -237,6 +239,7 @@ internal static class PersonalReportOrchestrator
|
||||
toggles,
|
||||
parsedName,
|
||||
buildWeatherDecisionAsync,
|
||||
buildCalendarDecisionAsync,
|
||||
buildCommuteDecisionAsync,
|
||||
cancellationToken);
|
||||
}
|
||||
@@ -253,6 +256,7 @@ internal static class PersonalReportOrchestrator
|
||||
PersonalReportServiceToggles toggles,
|
||||
string userName,
|
||||
Func<TurnContext, string, CancellationToken, Task<JiboInteractionDecision>> buildWeatherDecisionAsync,
|
||||
Func<TurnContext, CancellationToken, Task<JiboInteractionDecision>> buildCalendarDecisionAsync,
|
||||
Func<TurnContext, CancellationToken, Task<JiboInteractionDecision>> buildCommuteDecisionAsync,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
@@ -275,26 +279,7 @@ internal static class PersonalReportOrchestrator
|
||||
}
|
||||
|
||||
if (toggles.CalendarEnabled)
|
||||
{
|
||||
var calendarSummary = ChooseReportSkillTemplate(
|
||||
catalog.CalendarNothingTodayReplies,
|
||||
catalog.CalendarNothingReplies,
|
||||
string.Empty);
|
||||
if (string.IsNullOrWhiteSpace(calendarSummary))
|
||||
calendarSummary = ChooseReportSkillTemplate(
|
||||
catalog.CalendarServiceDownReplies,
|
||||
[],
|
||||
"Looking at your calendar, I don't see anything scheduled today.");
|
||||
|
||||
reportSections.Add(RenderReportSkillTemplate(calendarSummary, userName));
|
||||
reportSections.Add(
|
||||
RenderReportSkillTemplate(
|
||||
ChooseReportSkillTemplate(
|
||||
catalog.CalendarOutroReplies,
|
||||
[],
|
||||
"And that's your calendar."),
|
||||
userName));
|
||||
}
|
||||
reportSections.Add((await buildCalendarDecisionAsync(turn, cancellationToken)).ReplyText);
|
||||
|
||||
if (toggles.CommuteEnabled)
|
||||
reportSections.Add((await buildCommuteDecisionAsync(turn, cancellationToken)).ReplyText);
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
using Jibo.Cloud.Application.Abstractions;
|
||||
using Jibo.Runtime.Abstractions;
|
||||
|
||||
namespace Jibo.Cloud.Infrastructure.Calendar;
|
||||
|
||||
public sealed class UnavailableCalendarReportProvider : ICalendarReportProvider
|
||||
{
|
||||
public Task<CalendarReportSnapshot?> GetReportAsync(
|
||||
TurnContext turn,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
return Task.FromResult<CalendarReportSnapshot?>(null);
|
||||
}
|
||||
}
|
||||
@@ -119,7 +119,8 @@ public static class LegacyMimCatalogImporter
|
||||
if (fileName.StartsWith("JBO_WhatHolidaysDoYouCelebrate", StringComparison.OrdinalIgnoreCase))
|
||||
return LegacyMimBucket.Holiday;
|
||||
|
||||
if (fileName.StartsWith("RI_JBO_HasFavoriteHoliday", StringComparison.OrdinalIgnoreCase))
|
||||
if (fileName.StartsWith("RI_JBO_HasFavoriteHoliday", StringComparison.OrdinalIgnoreCase) ||
|
||||
IsHolidaySeasonFile(fileName))
|
||||
return LegacyMimBucket.HolidaySeason;
|
||||
|
||||
if (fileName.StartsWith("RI_JBO_HasFavoriteAnimal", StringComparison.OrdinalIgnoreCase) ||
|
||||
@@ -375,6 +376,48 @@ public static class LegacyMimCatalogImporter
|
||||
or LegacyMimBucket.HolidayTracker;
|
||||
}
|
||||
|
||||
private static bool IsHolidaySeasonFile(string fileName)
|
||||
{
|
||||
return fileName.StartsWith("RI_JBO_HowIsHolidaySeason", StringComparison.OrdinalIgnoreCase) ||
|
||||
fileName.StartsWith("RI_JBO_LikesHolidaySeason", StringComparison.OrdinalIgnoreCase) ||
|
||||
fileName.StartsWith("RI_JBO_HowIsThanksgiving", StringComparison.OrdinalIgnoreCase) ||
|
||||
fileName.StartsWith("RI_JBO_LikesThanksgiving", StringComparison.OrdinalIgnoreCase) ||
|
||||
fileName.StartsWith("RI_JBO_LooksForwardToThanksgiving", StringComparison.OrdinalIgnoreCase) ||
|
||||
fileName.StartsWith("RI_JBO_PlansForThanksgiving", StringComparison.OrdinalIgnoreCase) ||
|
||||
fileName.StartsWith("RI_JBO_HowIsChristmas", StringComparison.OrdinalIgnoreCase) ||
|
||||
fileName.StartsWith("RI_JBO_LikesChristmas", StringComparison.OrdinalIgnoreCase) ||
|
||||
fileName.StartsWith("RI_JBO_LooksForwardToChristmas", StringComparison.OrdinalIgnoreCase) ||
|
||||
fileName.StartsWith("RI_JBO_PlansForChristmas", StringComparison.OrdinalIgnoreCase) ||
|
||||
fileName.StartsWith("RI_JBO_HowIsHanukkah", StringComparison.OrdinalIgnoreCase) ||
|
||||
fileName.StartsWith("RI_JBO_LikesHanukkah", StringComparison.OrdinalIgnoreCase) ||
|
||||
fileName.StartsWith("RI_JBO_LooksForwardToHanukkah", StringComparison.OrdinalIgnoreCase) ||
|
||||
fileName.StartsWith("RI_JBO_PlansForHanukkah", StringComparison.OrdinalIgnoreCase) ||
|
||||
fileName.StartsWith("RI_JBO_HowIsPassover", StringComparison.OrdinalIgnoreCase) ||
|
||||
fileName.StartsWith("RI_JBO_LikesPassover", StringComparison.OrdinalIgnoreCase) ||
|
||||
fileName.StartsWith("RI_JBO_LooksForwardToPassover", StringComparison.OrdinalIgnoreCase) ||
|
||||
fileName.StartsWith("RI_JBO_PlansForPassover", StringComparison.OrdinalIgnoreCase) ||
|
||||
fileName.StartsWith("RI_JBO_HowIsNewYears", StringComparison.OrdinalIgnoreCase) ||
|
||||
fileName.StartsWith("RI_JBO_LikesNewYears", StringComparison.OrdinalIgnoreCase) ||
|
||||
fileName.StartsWith("RI_JBO_LooksForwardToNewYears", StringComparison.OrdinalIgnoreCase) ||
|
||||
fileName.StartsWith("RI_JBO_PlansForNewYears", StringComparison.OrdinalIgnoreCase) ||
|
||||
fileName.StartsWith("RI_JBO_HowIsValentinesDay", StringComparison.OrdinalIgnoreCase) ||
|
||||
fileName.StartsWith("RI_JBO_LikesValentinesDay", StringComparison.OrdinalIgnoreCase) ||
|
||||
fileName.StartsWith("RI_JBO_LooksForwardToValentinesDay", StringComparison.OrdinalIgnoreCase) ||
|
||||
fileName.StartsWith("RI_JBO_PlansForValentinesDay", StringComparison.OrdinalIgnoreCase) ||
|
||||
fileName.StartsWith("RI_JBO_HowIsKwanzaa", StringComparison.OrdinalIgnoreCase) ||
|
||||
fileName.StartsWith("RI_JBO_LikesKwanzaa", StringComparison.OrdinalIgnoreCase) ||
|
||||
fileName.StartsWith("RI_JBO_LooksForwardToKwanzaa", StringComparison.OrdinalIgnoreCase) ||
|
||||
fileName.StartsWith("RI_JBO_PlansForKwanzaa", StringComparison.OrdinalIgnoreCase) ||
|
||||
fileName.StartsWith("RI_JBO_HowIsEaster", StringComparison.OrdinalIgnoreCase) ||
|
||||
fileName.StartsWith("RI_JBO_LikesEaster", StringComparison.OrdinalIgnoreCase) ||
|
||||
fileName.StartsWith("RI_JBO_LooksForwardToEaster", StringComparison.OrdinalIgnoreCase) ||
|
||||
fileName.StartsWith("RI_JBO_PlansForEaster", StringComparison.OrdinalIgnoreCase) ||
|
||||
fileName.StartsWith("RI_JBO_HowIsOrthodoxEaster", StringComparison.OrdinalIgnoreCase) ||
|
||||
fileName.StartsWith("RI_JBO_LikesOrthodoxEaster", StringComparison.OrdinalIgnoreCase) ||
|
||||
fileName.StartsWith("RI_JBO_LooksForwardToOrthodoxEaster", StringComparison.OrdinalIgnoreCase) ||
|
||||
fileName.StartsWith("RI_JBO_PlansForOrthodoxEaster", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
private enum LegacyMimBucket
|
||||
{
|
||||
GenericFallback,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Jibo.Cloud.Application.Abstractions;
|
||||
using Jibo.Cloud.Application.Services;
|
||||
using Jibo.Cloud.Infrastructure.Audio;
|
||||
using Jibo.Cloud.Infrastructure.Calendar;
|
||||
using Jibo.Cloud.Infrastructure.Commute;
|
||||
using Jibo.Cloud.Infrastructure.Content;
|
||||
using Jibo.Cloud.Infrastructure.Holidays;
|
||||
@@ -53,6 +54,7 @@ public static class ServiceCollectionExtensions
|
||||
services.AddHttpClient<INewsBriefingProvider, NewsApiBriefingProvider>();
|
||||
services.AddSingleton<IHolidayCalendarProvider>(provider =>
|
||||
new NagerDateHolidayCalendarProvider(provider.GetRequiredService<HolidayCalendarOptions>()));
|
||||
services.AddSingleton<ICalendarReportProvider, UnavailableCalendarReportProvider>();
|
||||
services.AddSingleton<ICommuteReportProvider, UnavailableCommuteReportProvider>();
|
||||
var statePersistencePath = configuration?["OpenJibo:State:PersistencePath"]
|
||||
?? Path.Combine(AppContext.BaseDirectory, "App_Data", "cloud-state.json");
|
||||
|
||||
@@ -108,10 +108,6 @@ public sealed class LegacyMimCatalogImporterTests
|
||||
reply.Contains("holiday music", StringComparison.OrdinalIgnoreCase));
|
||||
Assert.Contains(catalog.PersonalityReplies, reply =>
|
||||
reply.Contains("dance party", StringComparison.OrdinalIgnoreCase));
|
||||
Assert.Contains(catalog.PersonalityReplies, reply =>
|
||||
reply.Contains("giving and receiving", StringComparison.OrdinalIgnoreCase));
|
||||
Assert.Contains(catalog.PersonalityReplies, reply =>
|
||||
reply.Contains("Christmas sweaters", StringComparison.OrdinalIgnoreCase));
|
||||
Assert.Contains(catalog.PersonalityReplies, reply =>
|
||||
reply.Contains("thankful for the people I know", StringComparison.OrdinalIgnoreCase));
|
||||
Assert.Contains(catalog.PersonalityReplies, reply =>
|
||||
@@ -213,6 +209,14 @@ public sealed class LegacyMimCatalogImporterTests
|
||||
reply.Contains("fun time of year", StringComparison.OrdinalIgnoreCase));
|
||||
Assert.Contains(catalog.HolidayGiftReplies, reply =>
|
||||
reply.Contains("pet elephant", StringComparison.OrdinalIgnoreCase));
|
||||
Assert.Contains(catalog.HolidaySeasonReplies, reply =>
|
||||
reply.Contains("holiday season is going very nicely", StringComparison.OrdinalIgnoreCase));
|
||||
Assert.Contains(catalog.HolidaySeasonReplies, reply =>
|
||||
reply.Contains("festive times", StringComparison.OrdinalIgnoreCase));
|
||||
Assert.Contains(catalog.HolidaySeasonReplies, reply =>
|
||||
reply.Contains("giving and receiving", StringComparison.OrdinalIgnoreCase));
|
||||
Assert.Contains(catalog.HolidaySeasonReplies, reply =>
|
||||
reply.Contains("Christmas sweaters", StringComparison.OrdinalIgnoreCase));
|
||||
Assert.Contains(catalog.BirthdayCelebrationReplies, reply =>
|
||||
reply.Contains("first powered up", StringComparison.OrdinalIgnoreCase) ||
|
||||
reply.Contains("another year older", StringComparison.OrdinalIgnoreCase));
|
||||
@@ -348,6 +352,7 @@ public sealed class LegacyMimCatalogImporterTests
|
||||
catalog.GenericFallbackReplies);
|
||||
Assert.Contains("For your weather.", catalog.WeatherIntroReplies);
|
||||
Assert.Contains("Today's high is {high}, and the low is {low}.", catalog.WeatherTodayHighLowReplies);
|
||||
Assert.Contains("I do like festive times.", catalog.HolidaySeasonReplies);
|
||||
Assert.Contains("Looking at your calendar, I don't see anything scheduled today.",
|
||||
catalog.CalendarNothingTodayReplies);
|
||||
Assert.Contains("Looks like I can't access calendars right now. Sorry.", catalog.CalendarServiceDownReplies);
|
||||
|
||||
@@ -665,8 +665,8 @@ public sealed class JiboInteractionServiceTests
|
||||
[InlineData("merry christmas", "seasonal_holiday_greeting", "It's a fun time of year")]
|
||||
[InlineData("what holidays do you celebrate", "seasonal_holidays",
|
||||
"official owner can tell me which ones we'll celebrate together")]
|
||||
[InlineData("how is holiday season", "seasonal_holiday_season", "I do like festive times.")]
|
||||
[InlineData("do you like holiday season", "seasonal_holiday_season", "I do like festive times.")]
|
||||
[InlineData("how is holiday season", "seasonal_holiday_season", "holiday season is going very nicely")]
|
||||
[InlineData("do you like holiday season", "seasonal_holiday_season", "holiday season is going very nicely")]
|
||||
[InlineData("what is your new year's resolution", "seasonal_new_years_resolution",
|
||||
"always trying to learn new skills")]
|
||||
[InlineData("how are your new year's resolutions going", "seasonal_new_years_update", "not eat bacon")]
|
||||
@@ -678,9 +678,17 @@ public sealed class JiboInteractionServiceTests
|
||||
[InlineData("do you like halloween", "seasonal_likes_halloween", "Halloween is my favorite holiday")]
|
||||
[InlineData("do you like holiday music", "seasonal_likes_holiday_music", "holiday music")]
|
||||
[InlineData("do you like holiday parties", "seasonal_likes_holiday_parties", "holiday fun can be extra fun")]
|
||||
[InlineData("are you looking forward to christmas", "seasonal_looks_forward_to_christmas", "giving and receiving")]
|
||||
[InlineData("how is thanksgiving", "seasonal_thanksgiving", "Thanksgiving")]
|
||||
[InlineData("are you looking forward to christmas", "seasonal_looks_forward_to_christmas", "long way away")]
|
||||
[InlineData("what are you doing for christmas", "seasonal_plans_for_christmas", "Christmas sweaters")]
|
||||
[InlineData("do you like christmas", "seasonal_christmas", "Christmas")]
|
||||
[InlineData("how is hanukkah", "seasonal_hanukkah", "Hanukkah")]
|
||||
[InlineData("do you like passover", "seasonal_passover", "Passover")]
|
||||
[InlineData("do you like new years", "seasonal_new_years", "new year")]
|
||||
[InlineData("what are you thankful for", "seasonal_thankful_for", "thankful for the people I know")]
|
||||
[InlineData("do you like valentines day", "seasonal_valentines_day", "Valentine")]
|
||||
[InlineData("do you like kwanzaa", "seasonal_kwanzaa", "Kwanzaa")]
|
||||
[InlineData("do you like easter", "seasonal_easter", "Easter")]
|
||||
[InlineData("happy birthday", "birthday_celebration", "another year older")]
|
||||
public async Task BuildDecisionAsync_SeasonalCharm_UsesImportedReplies(
|
||||
string transcript,
|
||||
@@ -1876,6 +1884,35 @@ public sealed class JiboInteractionServiceTests
|
||||
Assert.Equal(true, decision.ContextUpdates[PersonalReportUserVerifiedKey]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BuildDecisionAsync_PersonalReport_UsesCalendarProviderSummaryAndTime()
|
||||
{
|
||||
var weatherProvider = new CapturingWeatherReportProvider
|
||||
{
|
||||
Snapshot = new WeatherReportSnapshot("Boston, U.S.", "light rain", 61, 65, 54, "rain", false)
|
||||
};
|
||||
var calendarProvider = new CapturingCalendarReportProvider
|
||||
{
|
||||
Snapshot = new CalendarReportSnapshot(["get personal report from jibo"], ["at 6:00 p.m."], [])
|
||||
};
|
||||
var service = CreateService(weatherReportProvider: weatherProvider, calendarReportProvider: calendarProvider);
|
||||
|
||||
var decision = await service.BuildDecisionAsync(new TurnContext
|
||||
{
|
||||
RawTranscript = "yes",
|
||||
NormalizedTranscript = "yes",
|
||||
Attributes = new Dictionary<string, object?>
|
||||
{
|
||||
[PersonalReportStateKey] = "awaiting_identity_confirmation",
|
||||
[PersonalReportUserNameKey] = "alex"
|
||||
}
|
||||
});
|
||||
|
||||
Assert.Equal("personal_report_delivered", decision.IntentName);
|
||||
Assert.Contains("Your calendar says get personal report from jibo, at 6:00 p.m.", decision.ReplyText,
|
||||
StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BuildDecisionAsync_PersonalReport_NoMatchRetriesThenDeclines()
|
||||
{
|
||||
@@ -4035,6 +4072,7 @@ public sealed class JiboInteractionServiceTests
|
||||
IPersonalMemoryStore? personalMemoryStore = null,
|
||||
ICloudStateStore? cloudStateStore = null,
|
||||
IWeatherReportProvider? weatherReportProvider = null,
|
||||
ICalendarReportProvider? calendarReportProvider = null,
|
||||
ICommuteReportProvider? commuteReportProvider = null,
|
||||
INewsBriefingProvider? newsBriefingProvider = null,
|
||||
IJiboExperienceContentRepository? contentRepository = null,
|
||||
@@ -4045,6 +4083,7 @@ public sealed class JiboInteractionServiceTests
|
||||
randomizer ?? new FirstItemRandomizer(),
|
||||
personalMemoryStore ?? new InMemoryPersonalMemoryStore(),
|
||||
weatherReportProvider,
|
||||
calendarReportProvider,
|
||||
commuteReportProvider,
|
||||
newsBriefingProvider,
|
||||
cloudStateStore);
|
||||
@@ -4152,4 +4191,16 @@ public sealed class JiboInteractionServiceTests
|
||||
return Task.FromResult(Snapshot);
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class CapturingCalendarReportProvider : ICalendarReportProvider
|
||||
{
|
||||
public CalendarReportSnapshot? Snapshot { get; init; }
|
||||
|
||||
public Task<CalendarReportSnapshot?> GetReportAsync(
|
||||
TurnContext turn,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
return Task.FromResult(Snapshot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4734,6 +4734,7 @@ public sealed class JiboWebSocketServiceTests
|
||||
new StubWeatherReportProvider(
|
||||
new WeatherReportSnapshot("Lone Jack, US", "overcast clouds", 79, 82, 78, "clouds", false)),
|
||||
null,
|
||||
null,
|
||||
new StubNewsBriefingProvider(
|
||||
new NewsBriefingSnapshot(
|
||||
[
|
||||
@@ -5126,6 +5127,7 @@ public sealed class JiboWebSocketServiceTests
|
||||
private static JiboWebSocketService CreateService(
|
||||
InMemoryCloudStateStore stateStore,
|
||||
IWeatherReportProvider? weatherReportProvider = null,
|
||||
ICalendarReportProvider? calendarReportProvider = null,
|
||||
ICommuteReportProvider? commuteReportProvider = null,
|
||||
INewsBriefingProvider? newsBriefingProvider = null)
|
||||
{
|
||||
@@ -5136,6 +5138,7 @@ public sealed class JiboWebSocketServiceTests
|
||||
new DefaultJiboRandomizer(),
|
||||
new InMemoryPersonalMemoryStore(),
|
||||
weatherReportProvider,
|
||||
calendarReportProvider,
|
||||
commuteReportProvider,
|
||||
newsBriefingProvider);
|
||||
var conversationBroker = new DemoConversationBroker(interactionService);
|
||||
|
||||
Reference in New Issue
Block a user