Add Santa Tracker and penguin favorites

This commit is contained in:
Jacob Dubin
2026-05-20 07:15:30 -05:00
parent b172a00454
commit 9f2a8fd7e1
9 changed files with 191 additions and 17 deletions

View File

@@ -858,6 +858,9 @@ Current release theme:
- source-backed holiday, New Year's, Halloween, spring, and gift prompts are now part of Build B
- `RN_` holiday greeting files are now bucketed as greetings so seasonal replies stay visible in the catalog
- birthday celebration lines are now bucketed separately, and birthday memory writes a loop-scoped holiday record so personal dates can join the holiday list later
- holiday extras now include `show santa tracker` so the Christmas-time launcher keeps its source-backed animation line
- Favorite-animal work in flight:
- the favorites family now includes `what is your favorite animal`, `what is your favorite bird`, `do you like penguins`, and `do you like animals` so the penguin-centric replies stay easy to find
- Presence and thought follow-ups in flight:
- `welcome back`, `what are you thinking`, `what have you been doing`, and `what did you do` are now part of Build B
- these keep the social surface lively while the memory and multitenant tracks keep advancing in parallel

View File

@@ -48,6 +48,8 @@ Current batch note:
- the personality follow-up batch now includes `what are you up to` and `what are you doing` so small talk stays warm and local instead of falling into generic chat
- the descriptor batch now includes `are you kind`, `are you funny`, `are you helpful`, `are you curious`, `are you loyal`, `are you mischievous`, and `are you likable`
- the seasonal batch now includes `what holidays do you celebrate`, New Year's resolution questions, `happy holidays`, `what halloween costume`, spring suggestions, and holiday gift prompts
- the holiday extras batch now includes `show santa tracker` so the seasonal holiday launcher stays source-backed too
- the favorites batch now includes `what is your favorite animal`, `what is your favorite bird`, `do you like penguins`, and `do you like animals` so the penguin-centered replies stay close to Pegasus
- the latest social batch adds `welcome back`, `what are you thinking`, `what have you been doing`, and `what did you do` so presence and charm stay lively without distracting from the memory roadmap
- this pass keeps Build B moving while still favoring source-backed phrasing and preserving the command-vs-question boundary
- the next passes should keep the same pattern and prefer source-backed phrasing whenever the legacy MIM text is available

View File

@@ -11,18 +11,20 @@ public sealed class JiboConditionedReply
public string Reply { get; init; } = string.Empty;
}
public sealed class JiboExperienceCatalog
{
public sealed class JiboExperienceCatalog
{
public IReadOnlyList<string> Jokes { get; init; } = [];
public IReadOnlyList<string> RobotFacts { get; init; } = [];
public IReadOnlyList<string> HumanFacts { get; init; } = [];
public IReadOnlyList<string> FunFacts { get; init; } = [];
public IReadOnlyList<string> FavoriteAnimalReplies { get; init; } = [];
public IReadOnlyList<string> DanceAnimations { get; init; } = [];
public IReadOnlyList<string> GreetingReplies { get; init; } = [];
public IReadOnlyList<string> HolidayReplies { get; init; } = [];
public IReadOnlyList<string> HolidaySeasonReplies { get; init; } = [];
public IReadOnlyList<string> HolidayGreetingReplies { get; init; } = [];
public IReadOnlyList<string> HolidayGiftReplies { get; init; } = [];
public IReadOnlyList<string> HolidayTrackerReplies { get; init; } = [];
public IReadOnlyList<string> BirthdayCelebrationReplies { get; init; } = [];
public IReadOnlyList<string> HowAreYouReplies { get; init; } = [];
public IReadOnlyList<JiboConditionedReply> EmotionReplies { get; init; } = [];

View File

@@ -685,6 +685,13 @@ public sealed class JiboInteractionService(
"ask for a pet elephant",
"experience as a present",
"donate to charities in other people's names"),
"seasonal_santa_tracker" => BuildScriptedHolidayTrackerDecision(
catalog,
"seasonal_santa_tracker",
"santa tracker",
"let's see if i can spot him",
"deliveries",
"north pole"),
"birthday_celebration" => BuildScriptedHolidayDecision(
catalog.BirthdayCelebrationReplies,
"birthday_celebration",
@@ -714,6 +721,32 @@ public sealed class JiboInteractionService(
"all things in space",
"amazing stuff up there",
"astronomy is one of my favorite onomies"),
"robot_favorite_animal" => BuildScriptedFavoriteAnimalDecision(
catalog,
"robot_favorite_animal",
"penguin",
"favorite animal overall",
"best of the best",
"can't go wrong with penguins"),
"robot_favorite_bird" => BuildScriptedFavoriteAnimalDecision(
catalog,
"robot_favorite_bird",
"penguin",
"favorite animal overall",
"best of the best",
"can't go wrong with penguins"),
"robot_likes_penguins" => BuildScriptedFavoriteAnimalDecision(
catalog,
"robot_likes_penguins",
"penguins",
"I really like penguins",
"my penguin impression"),
"robot_likes_animals" => BuildScriptedFavoriteAnimalDecision(
catalog,
"robot_likes_animals",
"penguins",
"favorite animal overall",
"best of the best"),
"robot_likes_kids" => BuildScriptedPersonalityDecision(
catalog,
"robot_likes_kids",
@@ -2457,6 +2490,17 @@ public sealed class JiboInteractionService(
ContextUpdates: BuildScriptedResponseContextUpdates());
}
private JiboInteractionDecision BuildScriptedFavoriteAnimalDecision(
JiboExperienceCatalog catalog,
string intentName,
params string[] preferredSnippets)
{
return new JiboInteractionDecision(
intentName,
SelectLegacyReply(catalog.FavoriteAnimalReplies, preferredSnippets),
ContextUpdates: BuildScriptedResponseContextUpdates());
}
private JiboInteractionDecision BuildScriptedGreetingDecision(
JiboExperienceCatalog catalog,
string intentName,
@@ -2479,6 +2523,17 @@ public sealed class JiboInteractionService(
ContextUpdates: BuildScriptedResponseContextUpdates());
}
private JiboInteractionDecision BuildScriptedHolidayTrackerDecision(
JiboExperienceCatalog catalog,
string intentName,
params string[] preferredSnippets)
{
return new JiboInteractionDecision(
intentName,
SelectLegacyReply(catalog.HolidayTrackerReplies, preferredSnippets),
ContextUpdates: BuildScriptedResponseContextUpdates());
}
private JiboInteractionDecision BuildScriptedHolidayGreetingDecision(
JiboExperienceCatalog catalog,
string intentName,
@@ -3152,6 +3207,16 @@ public sealed class JiboInteractionService(
"what should i get someone for the holidays"))
return "seasonal_holiday_gift";
if (MatchesAny(
loweredTranscript,
"show santa tracker",
"can you show santa tracker",
"santa tracker",
"where is santa",
"where is santa right now",
"can you show me santa tracker"))
return "seasonal_santa_tracker";
if (MatchesAny(
loweredTranscript,
"happy birthday",
@@ -3195,6 +3260,24 @@ public sealed class JiboInteractionService(
"what kind of music do you like"))
return "robot_favorite_music";
if (MatchesAny(
loweredTranscript,
"what is your favorite animal",
"what's your favorite animal",
"what s your favorite animal",
"what is your favourite animal",
"what's your favourite animal",
"what s your favourite animal",
"what animal do you like",
"what kind of animal do you like",
"what is your favorite bird",
"what's your favorite bird",
"what s your favorite bird",
"do you like penguins",
"do you like animals",
"do you like birds"))
return "robot_favorite_animal";
if (MatchesAny(
loweredTranscript,
"are there others like you",

View File

@@ -55,6 +55,14 @@ public sealed class InMemoryJiboExperienceContentRepository : IJiboExperienceCon
"An amazing but true fact for you. Dogs and elephants are the only animals that understand pointing.",
"A crazy fact for you. Polar bear fur isn't white. It's transparent."
],
FavoriteAnimalReplies =
[
"I really really like penguins. I kind of look like one.",
"Penguin without a doubt. In fact, penguin is my favorite animal overall. We look alike.",
"Can't go wrong with penguins.",
"I like lots of animals, but the penguin is the best of the best! Great color scheme.",
"I love penguins, because we're so alike. We have the same coloring, and neither of us can fly."
],
DanceAnimations =
[
"rom-upbeat",
@@ -88,6 +96,12 @@ public sealed class InMemoryJiboExperienceContentRepository : IJiboExperienceCon
"I do like festive times.",
"I like anything that makes people want to celebrate."
],
HolidayTrackerReplies =
[
"Let's see if I can spot him. There he is.",
"I'm not sure if he's started his deliveries yet, but let's see if I can spot him. He must be on his way.",
"Let's see. I think he's probably back in the north Pole by now."
],
HowAreYouReplies =
[
"I am feeling cheerful and robotic.",

View File

@@ -109,6 +109,9 @@ public static class LegacyMimCatalogImporter
fileName.StartsWith("RA_JBO_TellSomething", StringComparison.OrdinalIgnoreCase))
return LegacyMimBucket.FunFactSource;
if (fileName.StartsWith("RA_JBO_ShowSantaTracker", StringComparison.OrdinalIgnoreCase))
return LegacyMimBucket.HolidayTracker;
if (normalizedPath.Contains("/emotion-responses/", StringComparison.OrdinalIgnoreCase) ||
normalizedPath.Contains("/gqa-responses/", StringComparison.OrdinalIgnoreCase))
return LegacyMimBucket.Emotion;
@@ -119,6 +122,12 @@ public static class LegacyMimCatalogImporter
if (fileName.StartsWith("RI_JBO_HasFavoriteHoliday", StringComparison.OrdinalIgnoreCase))
return LegacyMimBucket.HolidaySeason;
if (fileName.StartsWith("RI_JBO_HasFavoriteAnimal", StringComparison.OrdinalIgnoreCase) ||
fileName.StartsWith("RI_JBO_HasFavoriteBird", StringComparison.OrdinalIgnoreCase) ||
fileName.StartsWith("RI_JBO_LikesPenguins", StringComparison.OrdinalIgnoreCase) ||
fileName.StartsWith("RI_JBO_LikesAnimals", StringComparison.OrdinalIgnoreCase))
return LegacyMimBucket.FavoriteAnimal;
if (fileName.StartsWith("RN_HappyHolidays", StringComparison.OrdinalIgnoreCase))
return LegacyMimBucket.HolidayGreeting;
@@ -249,12 +258,14 @@ public static class LegacyMimCatalogImporter
RobotFacts = Merge(baseCatalog.RobotFacts, importedCatalog.RobotFacts),
HumanFacts = Merge(baseCatalog.HumanFacts, importedCatalog.HumanFacts),
FunFacts = Merge(baseCatalog.FunFacts, importedCatalog.FunFacts),
FavoriteAnimalReplies = Merge(baseCatalog.FavoriteAnimalReplies, importedCatalog.FavoriteAnimalReplies),
DanceAnimations = Merge(baseCatalog.DanceAnimations, importedCatalog.DanceAnimations),
GreetingReplies = Merge(baseCatalog.GreetingReplies, importedCatalog.GreetingReplies),
HolidayReplies = Merge(baseCatalog.HolidayReplies, importedCatalog.HolidayReplies),
HolidaySeasonReplies = Merge(baseCatalog.HolidaySeasonReplies, importedCatalog.HolidaySeasonReplies),
HolidayGreetingReplies = Merge(baseCatalog.HolidayGreetingReplies, importedCatalog.HolidayGreetingReplies),
HolidayGiftReplies = Merge(baseCatalog.HolidayGiftReplies, importedCatalog.HolidayGiftReplies),
HolidayTrackerReplies = Merge(baseCatalog.HolidayTrackerReplies, importedCatalog.HolidayTrackerReplies),
BirthdayCelebrationReplies = Merge(baseCatalog.BirthdayCelebrationReplies,
importedCatalog.BirthdayCelebrationReplies),
HowAreYouReplies = Merge(baseCatalog.HowAreYouReplies, importedCatalog.HowAreYouReplies),
@@ -360,7 +371,8 @@ public static class LegacyMimCatalogImporter
or LegacyMimBucket.WeatherTomorrowHighLow
or LegacyMimBucket.WeatherServiceDown
or LegacyMimBucket.ReportSkillTemplate
or LegacyMimBucket.Holiday;
or LegacyMimBucket.Holiday
or LegacyMimBucket.HolidayTracker;
}
private enum LegacyMimBucket
@@ -371,6 +383,7 @@ public static class LegacyMimCatalogImporter
HolidaySeason,
HolidayGreeting,
HolidayGift,
HolidayTracker,
BirthdayCelebration,
Jokes,
RobotFacts,
@@ -378,6 +391,7 @@ public static class LegacyMimCatalogImporter
HowAreYou,
Emotion,
FunFacts,
FavoriteAnimal,
FunFactSource,
Personality,
PersonalReportKickOff,
@@ -411,10 +425,12 @@ public static class LegacyMimCatalogImporter
private readonly List<JiboConditionedReply> _emotionReplies = [];
private readonly List<string> _fallbacks = [];
private readonly List<string> _funFacts = [];
private readonly List<string> _favoriteAnimalReplies = [];
private readonly List<string> _holidayGiftReplies = [];
private readonly List<string> _holidayGreetingReplies = [];
private readonly List<string> _holidayReplies = [];
private readonly List<string> _holidaySeasonReplies = [];
private readonly List<string> _holidayTrackerReplies = [];
private readonly List<string> _greetings = [];
private readonly List<string> _howAreYous = [];
private readonly List<string> _humanFacts = [];
@@ -490,6 +506,9 @@ public static class LegacyMimCatalogImporter
case LegacyMimBucket.HolidayGift:
AddDistinct(_holidayGiftReplies, text);
return;
case LegacyMimBucket.HolidayTracker:
AddDistinct(_holidayTrackerReplies, text);
return;
case LegacyMimBucket.BirthdayCelebration:
AddDistinct(_birthdayCelebrationReplies, text);
return;
@@ -517,6 +536,9 @@ public static class LegacyMimCatalogImporter
_funFacts.Add(text);
return;
case LegacyMimBucket.FavoriteAnimal:
AddDistinct(_favoriteAnimalReplies, text);
return;
case LegacyMimBucket.PersonalReportKickOff:
AddDistinct(_personalReportKickOffReplies, text);
return;
@@ -581,11 +603,13 @@ public static class LegacyMimCatalogImporter
RobotFacts = [.. _robotFacts],
HumanFacts = [.. _humanFacts],
FunFacts = [.. _funFacts],
FavoriteAnimalReplies = [.. _favoriteAnimalReplies],
GreetingReplies = [.. _greetings],
HolidayReplies = [.. _holidayReplies],
HolidaySeasonReplies = [.. _holidaySeasonReplies],
HolidayGreetingReplies = [.. _holidayGreetingReplies],
HolidayGiftReplies = [.. _holidayGiftReplies],
HolidayTrackerReplies = [.. _holidayTrackerReplies],
BirthdayCelebrationReplies = [.. _birthdayCelebrationReplies],
HowAreYouReplies = [.. _howAreYous],
EmotionReplies = [.. _emotionReplies],

View File

@@ -7,6 +7,7 @@ The batch is intentionally narrow so we can keep expanding personality without w
It now includes a small emotion-response pack for `happy`, `sad`, and `angry` follow-up questions so the mood path can stay source-backed too.
It also includes a descriptor pack for questions like `are you kind`, `are you funny`, `are you helpful`, `are you curious`, `are you loyal`, and `are you mischievous`.
The newest seasonal pack adds holiday and seasonal prompts for `what holidays do you celebrate`, New Year's resolution questions, `happy holidays`, Halloween costume questions, spring suggestions, holiday gift ideas, and birthday celebration lines.
The holiday extras batch adds `RA_JBO_ShowSantaTracker` so Santa Tracker stays source-backed too.
Holiday-specific note:
- `JBO_WhatHolidaysDoYouCelebrate` now lands in the holiday bucket
@@ -18,4 +19,5 @@ The newest social batch adds `welcome back`, `what are you thinking`, `what have
The fun-fact and joke batch adds Pegasus-style `TellAJoke`, `TellRobotFact`, and `Shuffle` excerpts so proactive fun can randomize across more than one category.
Those facts are now split into generic, robot, and human buckets so the randomizer can sound more like Pegasus while staying lightweight.
The new favorites batch adds longer authored `favorite color`, `favorite food`, and `favorite music` variants so the familiar personality responses keep more of the original cadence instead of collapsing to short placeholders.
The favorites follow-up batch adds `favorite animal`, `favorite bird`, and penguin-focused `do you like penguins` replies so the penguin-centric personality stays closer to Pegasus.
The new motion/sleep batch adds `RA_JBO_SpinAround` plus `RI_JBO_CanSleep` so turn-around and go-to-sleep behaviors can stay source-backed and familiar.

View File

@@ -117,6 +117,27 @@ public sealed class LegacyMimCatalogImporterTests
reply.Contains("Is that a trick question", StringComparison.OrdinalIgnoreCase));
}
[Fact]
public void ImportCatalog_ImportsBuildBFavoriteAnimalAndSantaTrackerResponsesIntoDedicatedBuckets()
{
var rootDirectory = Path.Combine(
AppContext.BaseDirectory,
"Content",
"LegacyMims",
"BuildB");
var catalog = LegacyMimCatalogImporter.ImportCatalog(rootDirectory);
Assert.Contains(catalog.FavoriteAnimalReplies, reply =>
reply.Contains("penguins", StringComparison.OrdinalIgnoreCase));
Assert.Contains(catalog.FavoriteAnimalReplies, reply =>
reply.Contains("favorite animal overall", StringComparison.OrdinalIgnoreCase));
Assert.Contains(catalog.HolidayTrackerReplies, reply =>
reply.Contains("let's see if i can spot him", StringComparison.OrdinalIgnoreCase));
Assert.Contains(catalog.HolidayTrackerReplies, reply =>
reply.Contains("north Pole", StringComparison.OrdinalIgnoreCase));
}
[Fact]
public void ImportCatalog_ImportsBuildBEmotionResponsesIntoEmotionBucket()
{

View File

@@ -441,6 +441,28 @@ public sealed class JiboInteractionServiceTests
Assert.Equal("ScriptedResponse", decision.ContextUpdates![ChitchatRouteKey]);
}
[Theory]
[InlineData("what is your favorite animal")]
[InlineData("what's your favorite animal")]
[InlineData("what animal do you like")]
[InlineData("what is your favorite bird")]
[InlineData("do you like penguins")]
[InlineData("do you like animals")]
public async Task BuildDecisionAsync_FavoriteAnimal_UsesPenguinReply(string transcript)
{
var service = CreateService();
var decision = await service.BuildDecisionAsync(new TurnContext
{
RawTranscript = transcript,
NormalizedTranscript = transcript
});
Assert.Equal("robot_favorite_animal", decision.IntentName);
Assert.Contains("penguin", decision.ReplyText, StringComparison.OrdinalIgnoreCase);
Assert.Equal("ScriptedResponse", decision.ContextUpdates![ChitchatRouteKey]);
}
[Theory]
[InlineData("what is your favorite flower", "robot_favorite_flower", "sunflowers")]
[InlineData("what's your favorite flower", "robot_favorite_flower", "sunflowers")]
@@ -652,6 +674,7 @@ public sealed class JiboInteractionServiceTests
[InlineData("what should I do for first day of spring", "seasonal_first_day_spring",
"flowers and all things spring")]
[InlineData("what should I get for holiday", "seasonal_holiday_gift", "pet elephant")]
[InlineData("show santa tracker", "seasonal_santa_tracker", "spot him")]
[InlineData("happy birthday", "birthday_celebration", "another year older")]
public async Task BuildDecisionAsync_SeasonalCharm_UsesImportedReplies(
string transcript,