briyah 1.1.8 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. package/data/common/config/markup +1 -1
  2. package/data/common/config/model_prices.json +3775 -653
  3. package/data/common/prompts/character/create_character.json +33 -29
  4. package/data/common/prompts/character/create_character.prompt +13 -2
  5. package/data/common/prompts/character/create_user_character.json +32 -28
  6. package/data/common/prompts/character/create_user_character.prompt +13 -2
  7. package/data/common/prompts/character/progress_character.json +22 -18
  8. package/data/common/prompts/character/progress_character.prompt +6 -2
  9. package/data/common/prompts/illustrator/describe_character.prompt +31 -0
  10. package/data/common/prompts/illustrator/describe_scene.json +19 -1
  11. package/data/common/prompts/illustrator/describe_scene.prompt +2 -1
  12. package/data/common/prompts/narrator/perceive.prompt +96 -35
  13. package/data/common/prompts/story_moderator/moderate.json +33 -7
  14. package/data/common/prompts/story_moderator/moderate.prompt +166 -20
  15. package/dist-sdk/server/src/ai/LLM/anthropic.service.d.ts +5 -2
  16. package/dist-sdk/server/src/ai/LLM/anthropic.service.js +27 -15
  17. package/dist-sdk/server/src/ai/LLM/base-ai.service.d.ts +6 -2
  18. package/dist-sdk/server/src/ai/LLM/base-ai.service.js +20 -10
  19. package/dist-sdk/server/src/ai/LLM/deepseek.service.js +10 -0
  20. package/dist-sdk/server/src/ai/LLM/googleai.service.js +11 -8
  21. package/dist-sdk/server/src/ai/LLM/grok.service.js +8 -5
  22. package/dist-sdk/server/src/ai/LLM/openai.service.js +12 -11
  23. package/dist-sdk/server/src/ai/LLM/together.service.js +9 -6
  24. package/dist-sdk/server/src/ai/agent-factory.d.ts +5 -3
  25. package/dist-sdk/server/src/ai/agent-factory.js +6 -4
  26. package/dist-sdk/server/src/ai/agent-store.service.d.ts +5 -3
  27. package/dist-sdk/server/src/ai/agent-store.service.js +15 -15
  28. package/dist-sdk/server/src/ai/agent.d.ts +9 -6
  29. package/dist-sdk/server/src/ai/agent.js +22 -6
  30. package/dist-sdk/server/src/ai/ai-debug-logger.d.ts +10 -0
  31. package/dist-sdk/server/src/ai/ai-debug-logger.js +82 -0
  32. package/dist-sdk/server/src/ai/artifact.module.js +2 -2
  33. package/dist-sdk/server/src/ai/artifact.service.d.ts +3 -3
  34. package/dist-sdk/server/src/ai/artifact.service.js +6 -6
  35. package/dist-sdk/server/src/ai/attached-file.module.js +2 -2
  36. package/dist-sdk/server/src/ai/attached-file.service.d.ts +3 -3
  37. package/dist-sdk/server/src/ai/attached-file.service.js +6 -6
  38. package/dist-sdk/server/src/app/balance.service.d.ts +3 -3
  39. package/dist-sdk/server/src/app/balance.service.js +7 -7
  40. package/dist-sdk/server/src/app/transaction.service.d.ts +3 -3
  41. package/dist-sdk/server/src/app/transaction.service.js +4 -4
  42. package/dist-sdk/server/src/app/user-service-factory.d.ts +3 -1
  43. package/dist-sdk/server/src/app/user-service-factory.js +18 -14
  44. package/dist-sdk/server/src/app/user-service-manager.d.ts +1 -3
  45. package/dist-sdk/server/src/app.service.d.ts +3 -3
  46. package/dist-sdk/server/src/app.service.js +30 -30
  47. package/dist-sdk/server/src/config/env-config.d.ts +3 -0
  48. package/dist-sdk/server/src/config/env-config.js +2 -0
  49. package/dist-sdk/server/src/config/user-paths.module.d.ts +2 -0
  50. package/dist-sdk/server/src/config/{configuration.module.js → user-paths.module.js} +8 -8
  51. package/dist-sdk/server/src/config/{configuration.service.d.ts → user-paths.service.d.ts} +1 -1
  52. package/dist-sdk/server/src/config/{configuration.service.js → user-paths.service.js} +3 -3
  53. package/dist-sdk/server/src/room/message.d.ts +1 -1
  54. package/dist-sdk/server/src/room/message.js +1 -1
  55. package/dist-sdk/server/src/room/room-store.module.js +2 -2
  56. package/dist-sdk/server/src/room/room-store.service.d.ts +3 -3
  57. package/dist-sdk/server/src/room/room-store.service.js +6 -6
  58. package/dist-sdk/server/src/room/room.d.ts +1 -0
  59. package/dist-sdk/server/src/room/room.js +43 -19
  60. package/dist-sdk/server/src/sdk/briyah-config.d.ts +2 -1
  61. package/dist-sdk/server/src/sdk/briyah-config.js +4 -0
  62. package/dist-sdk/server/src/sdk/briyah.js +1 -1
  63. package/dist-sdk/server/src/story/story-store.service.d.ts +3 -3
  64. package/dist-sdk/server/src/story/story-store.service.js +6 -6
  65. package/dist-sdk/server/src/story/story.service.d.ts +10 -3
  66. package/dist-sdk/server/src/story/story.service.js +233 -99
  67. package/dist-sdk/shared/types/app.types.d.ts +1 -0
  68. package/docs/assets/hierarchy.js +1 -1
  69. package/docs/assets/search.js +1 -1
  70. package/docs/classes/Agent.html +16 -16
  71. package/docs/classes/Briyah.html +12 -12
  72. package/docs/classes/BriyahConfigService.html +5 -5
  73. package/docs/classes/Room.html +24 -24
  74. package/docs/classes/RoomMessage.html +11 -11
  75. package/docs/enums/MessageAction.html +3 -3
  76. package/docs/hierarchy.html +1 -1
  77. package/docs/index.html +2 -2
  78. package/docs/interfaces/AgentInfo.html +2 -2
  79. package/docs/interfaces/AgentMessagesResponse.html +2 -2
  80. package/docs/interfaces/AppService.html +154 -154
  81. package/docs/interfaces/Artifact.html +3 -3
  82. package/docs/interfaces/ArtifactMetadata.html +2 -2
  83. package/docs/interfaces/AttachDocumentResponse.html +2 -2
  84. package/docs/interfaces/BriyahConfigOptions.html +7 -7
  85. package/docs/interfaces/ChapterInfo.html +2 -2
  86. package/docs/interfaces/Character.html +2 -2
  87. package/docs/interfaces/CreateAgentResponse.html +2 -2
  88. package/docs/interfaces/CreateRoomResponse.html +2 -2
  89. package/docs/interfaces/CreateStoryResponse.html +2 -2
  90. package/docs/interfaces/FileList.html +2 -2
  91. package/docs/interfaces/LoggingOptions.html +10 -6
  92. package/docs/interfaces/Message.html +2 -2
  93. package/docs/interfaces/ModelInfo.html +2 -2
  94. package/docs/interfaces/PreparedPromptResponse.html +2 -2
  95. package/docs/interfaces/ProcessTextResponse.html +2 -2
  96. package/docs/interfaces/PromptFile.html +2 -2
  97. package/docs/interfaces/PromptFileContent.html +2 -2
  98. package/docs/interfaces/PromptFilesResponse.html +2 -2
  99. package/docs/interfaces/PromptFolder.html +2 -2
  100. package/docs/interfaces/PromptFoldersResponse.html +2 -2
  101. package/docs/interfaces/RoomDetails.html +2 -2
  102. package/docs/interfaces/RoomInfo.html +2 -2
  103. package/docs/interfaces/RoomMessagesResponse.html +2 -2
  104. package/docs/interfaces/StoryErrorEvent.html +3 -3
  105. package/docs/interfaces/StoryIdea.html +2 -2
  106. package/docs/interfaces/StoryInfo.html +3 -3
  107. package/docs/interfaces/StoryIntroduceCharacterEvent.html +3 -3
  108. package/docs/interfaces/StoryProgressChapterEvent.html +3 -3
  109. package/docs/interfaces/StoryState.html +5 -5
  110. package/docs/interfaces/StoryStateEvent.html +3 -3
  111. package/docs/interfaces/Transaction.html +2 -2
  112. package/docs/interfaces/TransactionHistoryResponse.html +2 -2
  113. package/docs/modules.html +1 -1
  114. package/docs/types/PromptScope.html +1 -1
  115. package/package.json +2 -1
  116. package/dist-sdk/server/src/config/configuration.module.d.ts +0 -2
@@ -55,7 +55,7 @@ const agent_factory_1 = require("../ai/agent-factory");
55
55
  const room_factory_1 = require("../room/room-factory");
56
56
  const room_store_service_1 = require("../room/room-store.service");
57
57
  const app_types_1 = require("../../../shared/types/app.types");
58
- const configuration_service_1 = require("../config/configuration.service");
58
+ const user_paths_service_1 = require("../config/user-paths.service");
59
59
  const artifact_service_1 = require("../ai/artifact.service");
60
60
  const path = __importStar(require("path"));
61
61
  const fs = __importStar(require("fs"));
@@ -70,18 +70,18 @@ let StoryService = class StoryService {
70
70
  roomStore;
71
71
  progressService;
72
72
  messageService;
73
- configService;
73
+ userPaths;
74
74
  agentFactory;
75
75
  roomFactory;
76
76
  storyArtifactServices = new Map();
77
77
  chaptersInProgress = new Set();
78
- constructor(storyStore, agentStore, roomStore, progressService, messageService, configService, agentFactory, roomFactory) {
78
+ constructor(storyStore, agentStore, roomStore, progressService, messageService, userPaths, agentFactory, roomFactory) {
79
79
  this.storyStore = storyStore;
80
80
  this.agentStore = agentStore;
81
81
  this.roomStore = roomStore;
82
82
  this.progressService = progressService;
83
83
  this.messageService = messageService;
84
- this.configService = configService;
84
+ this.userPaths = userPaths;
85
85
  this.agentFactory = agentFactory;
86
86
  this.roomFactory = roomFactory;
87
87
  }
@@ -101,7 +101,7 @@ let StoryService = class StoryService {
101
101
  let artifactService = this.storyArtifactServices.get(storyId);
102
102
  if (!artifactService) {
103
103
  const { artifactsDir } = this.getStoryStorageDirs(storyId);
104
- artifactService = new artifact_service_1.ArtifactService(this.configService, artifactsDir);
104
+ artifactService = new artifact_service_1.ArtifactService(this.userPaths, artifactsDir);
105
105
  this.storyArtifactServices.set(storyId, artifactService);
106
106
  }
107
107
  return artifactService;
@@ -168,14 +168,14 @@ let StoryService = class StoryService {
168
168
  this.messageService.emitError(storyId, error);
169
169
  }
170
170
  getRandomWord() {
171
- const randomWordsPath = path.join(this.configService.getCommonConfigDir(), 'random_words.txt');
171
+ const randomWordsPath = path.join(this.userPaths.getCommonConfigDir(), 'random_words.txt');
172
172
  const content = fs.readFileSync(randomWordsPath, 'utf-8');
173
173
  const words = content.split('\n').filter((word) => word.trim().length > 0);
174
174
  const randomIndex = Math.floor(Math.random() * words.length);
175
175
  return words[randomIndex];
176
176
  }
177
177
  getStoryStorageDirs(storyId) {
178
- const userStoriesDir = path.join(this.configService.getUserDataDir(), 'stories');
178
+ const userStoriesDir = path.join(this.userPaths.getUserDataDir(), 'stories');
179
179
  return {
180
180
  agentsDir: path.join(userStoriesDir, storyId, 'agents'),
181
181
  roomsDir: path.join(userStoriesDir, storyId, 'rooms'),
@@ -183,7 +183,7 @@ let StoryService = class StoryService {
183
183
  };
184
184
  }
185
185
  getStoryModelConfig(storyModel) {
186
- const storyModelsPath = path.join(this.configService.getCommonConfigDir(), 'story_models.json');
186
+ const storyModelsPath = path.join(this.userPaths.getCommonConfigDir(), 'story_models.json');
187
187
  try {
188
188
  const storyModels = JSON.parse(fs.readFileSync(storyModelsPath, 'utf8'));
189
189
  const modelConfig = storyModels.find((m) => m.name === storyModel);
@@ -242,8 +242,9 @@ let StoryService = class StoryService {
242
242
  this.updateStorySituation(storyId, situation);
243
243
  });
244
244
  room.setOnModeratorResponse((message) => {
245
- if (message.updatePortrait?.length) {
246
- for (const nickname of message.updatePortrait) {
245
+ const portraitsToUpdate = message.changes?.update_portrait ?? [];
246
+ if (portraitsToUpdate.length) {
247
+ for (const nickname of portraitsToUpdate) {
247
248
  const characterAgent = room
248
249
  .getAgents()
249
250
  .find((a) => a.agentNickname === nickname);
@@ -251,10 +252,11 @@ let StoryService = class StoryService {
251
252
  this.updateCharacterPortrait(room, characterAgent, storyId).catch((e) => logger_1.logger.error(`Error updating portrait for ${nickname}:`, e));
252
253
  }
253
254
  else {
254
- logger_1.logger.warn(`update_portrait: agent "${nickname}" not found in room`);
255
+ logger_1.logger.warn(`changes.update_portrait: agent "${nickname}" not found in room`);
255
256
  }
256
257
  }
257
258
  }
259
+ this.applyInventoryUpdates(room, message);
258
260
  });
259
261
  if (story.situation) {
260
262
  room.setSituation(story.situation);
@@ -311,6 +313,7 @@ let StoryService = class StoryService {
311
313
  let illustrator = null;
312
314
  if (artist) {
313
315
  illustrator = this.agentFactory.createAgent(process.env.MODERATOR_AI_SERVICE || aiServiceName, `${storyTitle} - Illustrator`, 'Illustrator', 'Visual artist for generating scene illustrations', 'illustrator', process.env.MODERATOR_AI_MODEL || aiModelName, storyAgentsDir, storyArtifactService);
316
+ illustrator.reasoningEffort = 'low';
314
317
  illustrator.maxHistoryMessages = 10;
315
318
  illustrator.promptCacheTTL = 60;
316
319
  illustrator.ownerRoomId = storyInfo.id;
@@ -440,8 +443,9 @@ let StoryService = class StoryService {
440
443
  this.updateStorySituation(storyInfo.id, situation);
441
444
  });
442
445
  room.setOnModeratorResponse((message) => {
443
- if (message.updatePortrait?.length) {
444
- for (const nickname of message.updatePortrait) {
446
+ const portraitsToUpdate = message.changes?.update_portrait ?? [];
447
+ if (portraitsToUpdate.length) {
448
+ for (const nickname of portraitsToUpdate) {
445
449
  const characterAgent = room
446
450
  .getAgents()
447
451
  .find((a) => a.agentNickname === nickname);
@@ -449,10 +453,11 @@ let StoryService = class StoryService {
449
453
  this.updateCharacterPortrait(room, characterAgent, storyInfo.id).catch((e) => logger_1.logger.error(`Error updating portrait for ${nickname}:`, e));
450
454
  }
451
455
  else {
452
- logger_1.logger.warn(`update_portrait: agent "${nickname}" not found in room`);
456
+ logger_1.logger.warn(`changes.update_portrait: agent "${nickname}" not found in room`);
453
457
  }
454
458
  }
455
459
  }
460
+ this.applyInventoryUpdates(room, message);
456
461
  });
457
462
  storyInfo.roomId = roomId;
458
463
  storyInfo.moderatorAgentId = moderator.id;
@@ -543,6 +548,9 @@ let StoryService = class StoryService {
543
548
  if (response.character?.character_profile) {
544
549
  room.publishArtifact(`Character Profile - ${userAgent.agentNickname}`, userAgent.agentNickname, response.character.character_profile, [narrator.agentNickname, userAgent.agentNickname]);
545
550
  logger_1.logger.log(`Published character profile for ${userCharacter.name} (human-controlled)`);
551
+ if (response.character.inventory) {
552
+ this.publishInventoryArtifact(room, userAgent.agentNickname, response.character.inventory);
553
+ }
546
554
  this.progressService.emitProgress(storyInfo.id, 'profiles', `Finished creating character profile for ${userCharacter.name}`);
547
555
  }
548
556
  else {
@@ -579,6 +587,9 @@ let StoryService = class StoryService {
579
587
  if (response.character?.character_profile) {
580
588
  room.publishArtifact(`Character Profile - ${agent.agentNickname}`, agent.agentNickname, response.character.character_profile, [agent.agentNickname]);
581
589
  logger_1.logger.log(`Published character profile for ${charInfo.name}`);
590
+ if (response.character.inventory) {
591
+ this.publishInventoryArtifact(room, agent.agentNickname, response.character.inventory);
592
+ }
582
593
  this.progressService.emitProgress(storyInfo.id, 'profiles', `Finished creating character profile for ${charInfo.name}`);
583
594
  }
584
595
  else {
@@ -813,7 +824,7 @@ let StoryService = class StoryService {
813
824
  });
814
825
  }
815
826
  async importStoryFromZip(zipBuffer) {
816
- const storiesDir = path.join(this.configService.getUserDataDir(), 'stories');
827
+ const storiesDir = path.join(this.userPaths.getUserDataDir(), 'stories');
817
828
  const importDir = path.join(storiesDir, 'import');
818
829
  try {
819
830
  if (fs.existsSync(importDir)) {
@@ -1057,6 +1068,7 @@ let StoryService = class StoryService {
1057
1068
  }
1058
1069
  else {
1059
1070
  logger_1.logger.log(`Skipping INTRODUCE message for ${characterName} (already introduced by narrator)`);
1071
+ room.setCurrentSpeaker(room.getHumanAgentName());
1060
1072
  }
1061
1073
  }
1062
1074
  async declineCharacter(storyId, characterName) {
@@ -1440,6 +1452,33 @@ let StoryService = class StoryService {
1440
1452
  }
1441
1453
  return '';
1442
1454
  }
1455
+ publishInventoryArtifact(room, characterNickname, body) {
1456
+ if (!body || !body.trim())
1457
+ return;
1458
+ room.publishArtifact(`${characterNickname} - Inventory`, characterNickname, body, [characterNickname, 'Narrator', 'Moderator']);
1459
+ logger_1.logger.log(`Published inventory for ${characterNickname}`);
1460
+ }
1461
+ applyInventoryUpdates(room, moderatorMessage) {
1462
+ const updates = moderatorMessage.changes?.update_inventory ?? [];
1463
+ if (!Array.isArray(updates) || updates.length === 0)
1464
+ return;
1465
+ for (const entry of updates) {
1466
+ const characterName = entry?.characterName?.trim();
1467
+ const inventory = entry?.inventory;
1468
+ if (!characterName || !inventory) {
1469
+ logger_1.logger.warn(`changes.update_inventory: skipping malformed entry: ${JSON.stringify(entry)}`);
1470
+ continue;
1471
+ }
1472
+ const characterAgent = room
1473
+ .getAgents()
1474
+ .find((a) => a.agentNickname === characterName);
1475
+ if (!characterAgent) {
1476
+ logger_1.logger.warn(`changes.update_inventory: character "${characterName}" not found in room`);
1477
+ continue;
1478
+ }
1479
+ this.publishInventoryArtifact(room, characterName, inventory);
1480
+ }
1481
+ }
1443
1482
  async updateCharacterProfiles(room, characterAgents, plotPlan = '') {
1444
1483
  const artifacts = room.getArtifacts();
1445
1484
  const updatePromises = characterAgents.map(async (character) => {
@@ -1467,6 +1506,9 @@ let StoryService = class StoryService {
1467
1506
  character.save();
1468
1507
  }
1469
1508
  room.publishArtifact(`Character Profile - ${character.agentNickname}`, character.agentNickname, progressCharacterResponse.character_profile, [character.agentNickname]);
1509
+ if (progressCharacterResponse.inventory) {
1510
+ this.publishInventoryArtifact(room, character.agentNickname, progressCharacterResponse.inventory);
1511
+ }
1470
1512
  }
1471
1513
  catch (error) {
1472
1514
  logger_1.logger.error(`Error updating character profile for ${character.agentNickname}:`, error);
@@ -1504,7 +1546,7 @@ let StoryService = class StoryService {
1504
1546
  if (!modelName) {
1505
1547
  return null;
1506
1548
  }
1507
- const imageModelsPath = path.join(this.configService.getCommonConfigDir(), 'image_models.json');
1549
+ const imageModelsPath = path.join(this.userPaths.getCommonConfigDir(), 'image_models.json');
1508
1550
  const imageModels = JSON.parse(fs.readFileSync(imageModelsPath, 'utf8'));
1509
1551
  const modelConfig = imageModels.find((m) => m.name === modelName);
1510
1552
  if (!modelConfig) {
@@ -1518,8 +1560,6 @@ let StoryService = class StoryService {
1518
1560
  return {
1519
1561
  service: modelConfig.service,
1520
1562
  model: modelConfig.model,
1521
- imageProperties: modelConfig.imageProperties,
1522
- centsPerImage: modelConfig.centsPerImage,
1523
1563
  };
1524
1564
  }
1525
1565
  catch (error) {
@@ -1527,6 +1567,27 @@ let StoryService = class StoryService {
1527
1567
  return null;
1528
1568
  }
1529
1569
  }
1570
+ getImagePropertiesForAgent(agent) {
1571
+ try {
1572
+ const imageModelsPath = path.join(this.userPaths.getCommonConfigDir(), 'image_models.json');
1573
+ const imageModels = JSON.parse(fs.readFileSync(imageModelsPath, 'utf8'));
1574
+ const modelConfig = imageModels.find((m) => m.model === agent.modelName);
1575
+ if (!modelConfig) {
1576
+ logger_1.logger.warn(`No image_models.json entry for "${agent.modelName}"; image generation may fail`);
1577
+ return {};
1578
+ }
1579
+ return {
1580
+ ...(modelConfig.imageProperties ?? {}),
1581
+ ...(modelConfig.centsPerImage != null
1582
+ ? { centsPerImage: modelConfig.centsPerImage }
1583
+ : {}),
1584
+ };
1585
+ }
1586
+ catch (error) {
1587
+ logger_1.logger.error('Error loading image properties for agent:', error);
1588
+ return {};
1589
+ }
1590
+ }
1530
1591
  createArtistAgent(storyId, storyAgentsDir, storyArtifactService, imageModelName, nickname = 'Artist') {
1531
1592
  const storyInfo = this.storyStore.getStory(storyId);
1532
1593
  const imageConfig = this.getImageModelConfig(imageModelName);
@@ -1537,26 +1598,26 @@ let StoryService = class StoryService {
1537
1598
  const artistAgent = this.agentFactory.createAgent(imageConfig.service, `${storyInfo.name} - ${nickname}`, nickname, 'AI artist for generating character portraits and scene illustrations', 'default', imageConfig.model, storyAgentsDir, storyArtifactService);
1538
1599
  artistAgent.maxHistoryMessages = 10;
1539
1600
  artistAgent.promptCacheTTL = 0;
1540
- artistAgent.imageProperties = {
1541
- ...(imageConfig?.imageProperties ?? {}),
1542
- ...(imageConfig?.centsPerImage != null ? { centsPerImage: imageConfig.centsPerImage } : {}),
1543
- };
1544
1601
  artistAgent.save();
1545
1602
  logger_1.logger.log(`Created artist agent: ${artistAgent.agentName} (${imageConfig.service}/${imageConfig.model})`);
1546
1603
  return artistAgent;
1547
1604
  }
1548
1605
  async generateCharacterPortrait(room, characterAgent, storyId) {
1606
+ const artifacts = room.getArtifacts();
1607
+ const profileArtifact = artifacts.find((a) => a.name === `Character Profile - ${characterAgent.agentNickname}`);
1608
+ const storyInfo = this.storyStore.getStory(storyId);
1609
+ const character = storyInfo.characters.find((c) => c.name === characterAgent.agentNickname);
1610
+ const characterProfile = profileArtifact?.body || character?.description || '';
1611
+ return this.generatePortraitForName(storyId, characterAgent.agentNickname, characterProfile, characterAgent);
1612
+ }
1613
+ async generatePortraitForName(storyId, characterName, characterProfile, promptAgent) {
1549
1614
  try {
1550
- const artifacts = room.getArtifacts();
1551
- const profileArtifact = artifacts.find((a) => a.name === `Character Profile - ${characterAgent.agentNickname}`);
1552
- const storyInfo = this.storyStore.getStory(storyId);
1553
- const scenario = storyInfo?.scenario || '';
1554
- const character = storyInfo.characters.find((c) => c.name === characterAgent.agentNickname);
1555
- let characterDescription = profileArtifact?.body || character?.description || '';
1556
- if (!characterDescription) {
1557
- logger_1.logger.warn(`No profile for ${characterAgent.agentNickname}, skipping portrait`);
1615
+ if (!characterProfile) {
1616
+ logger_1.logger.warn(`No profile for ${characterName}, skipping portrait`);
1558
1617
  return null;
1559
1618
  }
1619
+ const storyInfo = this.storyStore.getStory(storyId);
1620
+ const scenario = storyInfo?.scenario || '';
1560
1621
  const storyArtifactService = this.getStoryArtifactService(storyId);
1561
1622
  const artistAgent = await this.agentStore.getAgent(storyInfo.artistAgentId);
1562
1623
  if (!artistAgent) {
@@ -1564,28 +1625,29 @@ let StoryService = class StoryService {
1564
1625
  return null;
1565
1626
  }
1566
1627
  artistAgent.artifactService = storyArtifactService;
1567
- const visualDescription = await characterAgent.preparedPrompt('describe_character', {
1568
- characterName: characterAgent.agentNickname,
1569
- characterProfile: characterDescription,
1570
- scenario: scenario,
1628
+ const describeAgent = promptAgent || artistAgent;
1629
+ const visualDescription = await describeAgent.preparedPrompt('describe_character', {
1630
+ characterName,
1631
+ characterProfile,
1632
+ scenario,
1571
1633
  }, false);
1572
1634
  if (!visualDescription || typeof visualDescription !== 'string') {
1573
- logger_1.logger.warn(`Failed to generate visual description for ${characterAgent.agentNickname}`);
1635
+ logger_1.logger.warn(`Failed to generate visual description for ${characterName}`);
1574
1636
  return null;
1575
1637
  }
1576
- const imageResult = await artistAgent.generateImage(visualDescription);
1638
+ const imageResult = await artistAgent.generateImage(visualDescription, this.getImagePropertiesForAgent(artistAgent));
1577
1639
  if (imageResult.error) {
1578
1640
  return null;
1579
1641
  }
1580
1642
  artistAgent.save();
1581
1643
  const artifactId = imageResult.artifactId;
1582
- storyArtifactService.renameArtifact(artifactId, `Portrait - ${characterAgent.agentNickname}`);
1644
+ storyArtifactService.renameArtifact(artifactId, `Portrait - ${characterName}`);
1583
1645
  storyArtifactService.updateArtifactDescription(artifactId, visualDescription);
1584
- logger_1.logger.log(`Generated portrait for ${characterAgent.agentNickname}: ${artifactId}`);
1646
+ logger_1.logger.log(`Generated portrait for ${characterName}: ${artifactId}`);
1585
1647
  return artifactId;
1586
1648
  }
1587
1649
  catch (error) {
1588
- logger_1.logger.error(`Error generating portrait for ${characterAgent.agentNickname}:`, error);
1650
+ logger_1.logger.error(`Error generating portrait for ${characterName}:`, error);
1589
1651
  return null;
1590
1652
  }
1591
1653
  }
@@ -1617,8 +1679,8 @@ let StoryService = class StoryService {
1617
1679
  .listArtifacts()
1618
1680
  .find((a) => a.name === portraitName);
1619
1681
  if (!existingPortrait) {
1620
- logger_1.logger.warn(`No existing portrait for ${characterAgent.agentNickname}, cannot update`);
1621
- return null;
1682
+ logger_1.logger.warn(`No existing portrait for ${characterAgent.agentNickname}, generating from scratch`);
1683
+ return this.generateCharacterPortrait(room, characterAgent, storyId);
1622
1684
  }
1623
1685
  const visualDescription = await characterAgent.preparedPrompt('update_portrait', {
1624
1686
  characterName: characterAgent.agentNickname,
@@ -1629,9 +1691,7 @@ let StoryService = class StoryService {
1629
1691
  logger_1.logger.warn(`Failed to generate update description for ${characterAgent.agentNickname}`);
1630
1692
  return null;
1631
1693
  }
1632
- const imageResult = await artistEditAgent.editImage(visualDescription, [
1633
- existingPortrait.artifactId,
1634
- ]);
1694
+ const imageResult = await artistEditAgent.editImage(visualDescription, this.getImagePropertiesForAgent(artistEditAgent), [existingPortrait.artifactId]);
1635
1695
  if (imageResult.error) {
1636
1696
  return null;
1637
1697
  }
@@ -1674,6 +1734,12 @@ let StoryService = class StoryService {
1674
1734
  name: a.name.replace('Scene - ', ''),
1675
1735
  description: a.description || '',
1676
1736
  }));
1737
+ const portraitCharacters = allArtifacts
1738
+ .filter((a) => a.name.startsWith('Portrait - '))
1739
+ .map((a) => ({
1740
+ name: a.name.replace('Portrait - ', ''),
1741
+ description: a.description || '',
1742
+ }));
1677
1743
  let existingScenesString = existingScenes
1678
1744
  .map((s) => `- ${s.name}: ${s.description}`)
1679
1745
  .join('\n');
@@ -1682,7 +1748,7 @@ let StoryService = class StoryService {
1682
1748
  'No scene reference images have been created yet. (set isReference: true)';
1683
1749
  let prompt = `**Current Situation**:\n ${story.situation}\n\n**Existing Scenes**:\n ${existingScenesString}`;
1684
1750
  const sceneAnalysis = await illustrator.instructedPrompt(prompt, 'describe_scene', {
1685
- characters: story.characters,
1751
+ characters: portraitCharacters,
1686
1752
  }, true, true);
1687
1753
  illustrator.save();
1688
1754
  if (!sceneAnalysis || !sceneAnalysis.createImage) {
@@ -1694,10 +1760,13 @@ let StoryService = class StoryService {
1694
1760
  logger_1.logger.warn(`Illustrator requested another reference (${sceneAnalysis.sceneName}) after one was just created; skipping to avoid loop`);
1695
1761
  return;
1696
1762
  }
1697
- await this.generateSceneReference(storyId, sceneAnalysis.sceneName, sceneAnalysis.sceneDescription);
1698
- await this.generateSceneIllustration(storyId, situation, false);
1763
+ const referenceCreated = await this.generateSceneReference(storyId, sceneAnalysis.sceneName, sceneAnalysis.sceneDescription);
1764
+ if (referenceCreated) {
1765
+ await this.generateSceneIllustration(storyId, situation, false);
1766
+ }
1699
1767
  }
1700
1768
  else {
1769
+ await this.ensureMinorCharacterPortraits(storyId, sceneAnalysis.characterNames || [], sceneAnalysis.newCharacters || [], portraitCharacters.map((c) => c.name), illustrator);
1701
1770
  await this.generateStoryImage(storyId, story.turnNumber, sceneAnalysis.imageCaption, sceneAnalysis.sceneName, sceneAnalysis.sceneDescription, sceneAnalysis.characterNames);
1702
1771
  }
1703
1772
  }
@@ -1705,37 +1774,54 @@ let StoryService = class StoryService {
1705
1774
  logger_1.logger.error('Scene illustration error:', error);
1706
1775
  }
1707
1776
  }
1777
+ async ensureMinorCharacterPortraits(storyId, characterNames, newCharacters, existingPortraitNames, promptAgent) {
1778
+ const existing = new Set(existingPortraitNames);
1779
+ const descriptionsByName = new Map(newCharacters.map((c) => [c.name, c.briefDescription]));
1780
+ for (const name of characterNames) {
1781
+ if (existing.has(name))
1782
+ continue;
1783
+ const briefDescription = descriptionsByName.get(name);
1784
+ if (!briefDescription) {
1785
+ logger_1.logger.warn(`Illustrator named "${name}" but provided no newCharacters entry; portrait will be skipped`);
1786
+ continue;
1787
+ }
1788
+ await this.generatePortraitForName(storyId, name, briefDescription, promptAgent);
1789
+ }
1790
+ }
1708
1791
  async generateSceneReference(storyId, sceneName, sceneDescription) {
1709
1792
  try {
1710
1793
  logger_1.logger.log(`Generating scene reference: ${sceneName}`);
1711
1794
  const storyInfo = this.storyStore.getStory(storyId);
1712
1795
  if (!storyInfo || !storyInfo.artistAgentId) {
1713
1796
  logger_1.logger.error(`Cannot generate scene reference: story ${storyId} has no artist agent`);
1714
- return;
1797
+ return false;
1715
1798
  }
1716
1799
  const artistAgent = await this.agentStore.getAgent(storyInfo.artistAgentId);
1717
1800
  if (!artistAgent) {
1718
1801
  logger_1.logger.error(`Artist agent not found: ${storyInfo.artistAgentId}`);
1719
- return;
1802
+ return false;
1720
1803
  }
1721
1804
  const storyArtifactService = this.getStoryArtifactService(storyId);
1722
1805
  if (!storyArtifactService) {
1723
1806
  logger_1.logger.error(`Story artifact service not found: ${storyId}`);
1724
- return;
1807
+ return false;
1725
1808
  }
1726
1809
  artistAgent.artifactService = storyArtifactService;
1727
- const imageResult = await artistAgent.generateImage(sceneDescription);
1810
+ const imageResult = await artistAgent.generateImage(sceneDescription, this.getImagePropertiesForAgent(artistAgent));
1728
1811
  if (imageResult.error) {
1729
- return;
1812
+ logger_1.logger.error(`Scene reference image generation failed for "${sceneName}":`, imageResult.error);
1813
+ return false;
1730
1814
  }
1731
1815
  artistAgent.save();
1732
1816
  const artifactId = imageResult.artifactId;
1733
1817
  storyArtifactService.renameArtifact(artifactId, `Scene - ${sceneName}`);
1734
1818
  storyArtifactService.updateArtifactDescription(artifactId, sceneDescription);
1735
1819
  logger_1.logger.log(`Generated scene reference: ${sceneName} (${artifactId})`);
1820
+ return true;
1736
1821
  }
1737
1822
  catch (error) {
1738
1823
  logger_1.logger.error('Scene reference generation error:', error);
1824
+ return false;
1739
1825
  }
1740
1826
  }
1741
1827
  async generateStoryImage(storyId, turnNumber, imageCaption, sceneName, sceneDescription, characterNames) {
@@ -1748,17 +1834,6 @@ let StoryService = class StoryService {
1748
1834
  logger_1.logger.warn(`Scene not found: ${sceneName}`);
1749
1835
  return;
1750
1836
  }
1751
- const characterPortraitIds = [];
1752
- for (const charName of characterNames) {
1753
- const portrait = allArtifacts.find((a) => a.name === `Portrait - ${charName}`);
1754
- if (portrait) {
1755
- characterPortraitIds.push(portrait.artifactId);
1756
- }
1757
- else {
1758
- logger_1.logger.warn(`Portrait not found: ${charName}`);
1759
- }
1760
- }
1761
- const referenceImageIds = [sceneArtifact.artifactId, ...characterPortraitIds];
1762
1837
  const storyInfo = this.storyStore.getStory(storyId);
1763
1838
  if (!storyInfo || !storyInfo.artistAgentId) {
1764
1839
  logger_1.logger.error(`Cannot generate story image: story ${storyId} has no artist agent`);
@@ -1770,6 +1845,34 @@ let StoryService = class StoryService {
1770
1845
  return;
1771
1846
  }
1772
1847
  artistAgent.artifactService = storyArtifactService;
1848
+ const room = await this.getStoryRoom(storyId);
1849
+ const characterPortraitIds = [];
1850
+ for (const charName of characterNames) {
1851
+ const currentArtifacts = storyArtifactService.listArtifacts();
1852
+ const portrait = currentArtifacts.find((a) => a.name === `Portrait - ${charName}`);
1853
+ if (portrait) {
1854
+ characterPortraitIds.push(portrait.artifactId);
1855
+ }
1856
+ else {
1857
+ logger_1.logger.warn(`Portrait not found for ${charName}, generating now`);
1858
+ const characterAgent = room
1859
+ .getAgents()
1860
+ .find((a) => a.agentNickname === charName);
1861
+ if (characterAgent) {
1862
+ const newPortraitId = await this.generateCharacterPortrait(room, characterAgent, storyId);
1863
+ if (newPortraitId) {
1864
+ characterPortraitIds.push(newPortraitId);
1865
+ }
1866
+ else {
1867
+ logger_1.logger.warn(`Could not generate portrait for ${charName}, skipping`);
1868
+ }
1869
+ }
1870
+ else {
1871
+ logger_1.logger.warn(`No agent found for character ${charName}, skipping portrait`);
1872
+ }
1873
+ }
1874
+ }
1875
+ const referenceImageIds = [sceneArtifact.artifactId, ...characterPortraitIds];
1773
1876
  const editAgent = storyInfo.artistEditAgentId
1774
1877
  ? await this.agentStore.getAgent(storyInfo.artistEditAgentId)
1775
1878
  : null;
@@ -1777,8 +1880,8 @@ let StoryService = class StoryService {
1777
1880
  editAgent.artifactService = storyArtifactService;
1778
1881
  }
1779
1882
  const imageResult = referenceImageIds?.length && editAgent
1780
- ? await editAgent.editImage(sceneDescription, referenceImageIds)
1781
- : await artistAgent.generateImage(sceneDescription);
1883
+ ? await editAgent.editImage(sceneDescription, this.getImagePropertiesForAgent(editAgent), referenceImageIds)
1884
+ : await artistAgent.generateImage(sceneDescription, this.getImagePropertiesForAgent(artistAgent));
1782
1885
  if (imageResult.error) {
1783
1886
  return;
1784
1887
  }
@@ -1788,7 +1891,6 @@ let StoryService = class StoryService {
1788
1891
  storyArtifactService.updateArtifactDescription(artifactId, imageCaption);
1789
1892
  logger_1.logger.log(`Generated story image: ${imageCaption} (${artifactId})`);
1790
1893
  try {
1791
- const room = await this.getStoryRoom(storyId);
1792
1894
  const imgUrl = `/api/stories/${storyId}/artifacts/${artifactId}`;
1793
1895
  const imageMarkdown = `![${imageCaption}](${imgUrl})`;
1794
1896
  const imageMessage = new message_1.RoomMessage(imageCaption, app_types_1.MessageAction.SYSTEM, imageMarkdown);
@@ -1803,16 +1905,51 @@ let StoryService = class StoryService {
1803
1905
  logger_1.logger.error('Story image generation error:', error);
1804
1906
  }
1805
1907
  }
1806
- async updateStorySituation(storyId, situation) {
1908
+ parseNarratorPreamble(preamble) {
1909
+ const result = {};
1910
+ if (!preamble)
1911
+ return result;
1912
+ const extractTag = (raw, tag) => {
1913
+ const re = new RegExp(`<${tag}>([\\s\\S]*?)</${tag}>`, 'i');
1914
+ const m = raw.match(re);
1915
+ return m ? m[1].trim() : undefined;
1916
+ };
1917
+ const time = extractTag(preamble, 'time');
1918
+ const situation = extractTag(preamble, 'situation');
1919
+ const introduceRaw = extractTag(preamble, 'introduce_character');
1920
+ const progressRaw = extractTag(preamble, 'progress_chapter');
1921
+ if (time)
1922
+ result.time = time;
1923
+ if (situation)
1924
+ result.situation = situation;
1925
+ if (introduceRaw) {
1926
+ const firstToken = introduceRaw.split(/[\s(:,]/)[0];
1927
+ if (firstToken && firstToken.toLowerCase() !== 'none') {
1928
+ result.introduceCharacter = firstToken;
1929
+ }
1930
+ }
1931
+ if (progressRaw && /^\s*yes\b/i.test(progressRaw)) {
1932
+ result.progressChapter = true;
1933
+ }
1934
+ return result;
1935
+ }
1936
+ formatDisplaySituation(parsed, fallback) {
1937
+ if (parsed.time && parsed.situation)
1938
+ return `${parsed.time} - ${parsed.situation}`;
1939
+ if (parsed.situation)
1940
+ return parsed.situation;
1941
+ return fallback;
1942
+ }
1943
+ async updateStorySituation(storyId, preamble) {
1807
1944
  const story = this.storyStore.getStory(storyId);
1808
1945
  if (!story)
1809
1946
  return;
1810
1947
  const room = await this.getStoryRoom(storyId);
1811
- let progressChapter = situation.startsWith('PROGRESS');
1812
- if (progressChapter) {
1813
- if (story) {
1814
- story.declinedCharacters = [];
1815
- }
1948
+ const parsed = this.parseNarratorPreamble(preamble);
1949
+ const displaySituation = this.formatDisplaySituation(parsed, preamble);
1950
+ room.setSituation(displaySituation);
1951
+ if (parsed.progressChapter) {
1952
+ story.declinedCharacters = [];
1816
1953
  story.pendingSuggestion = {
1817
1954
  type: 'suggest-progress-chapter',
1818
1955
  timestamp: Date.now(),
@@ -1821,36 +1958,33 @@ let StoryService = class StoryService {
1821
1958
  this.messageService.emitProgressChapter(storyId);
1822
1959
  return;
1823
1960
  }
1824
- let agentCompactionThreshold = Number(process.env.AGENT_COMPACTION_THRESHOLD) || 150000;
1961
+ let agentCompactionThreshold = Number(process.env.AGENT_COMPACTION_THRESHOLD) || 100000;
1825
1962
  await this.compactAgentHistories(room.getAgents(), agentCompactionThreshold);
1826
- let introduce = situation.startsWith('INTRODUCE:');
1827
- if (introduce) {
1828
- let newCharacterName = situation.substring(11).trim();
1829
- if (newCharacterName) {
1830
- const existingAgent = room.getAgents().find((a) => room.checkAgentNicknameMatch(a.agentNickname, newCharacterName));
1831
- if (existingAgent) {
1832
- logger_1.logger.log(`INTRODUCE: ${newCharacterName} ignored — character already in story`);
1833
- return;
1834
- }
1835
- const declinedCharacters = story?.declinedCharacters || [];
1836
- if (declinedCharacters.includes(newCharacterName)) {
1837
- logger_1.logger.log(`Character ${newCharacterName} was declined, skipping prompt`);
1838
- return;
1839
- }
1840
- story.pendingSuggestion = {
1841
- type: 'suggest-introduce-character',
1842
- characterName: newCharacterName,
1843
- timestamp: Date.now(),
1844
- };
1845
- this.storyStore.updateStoryMetadata(storyId, story);
1846
- this.messageService.emitIntroduceCharacter(storyId, newCharacterName);
1963
+ if (parsed.introduceCharacter) {
1964
+ const newCharacterName = parsed.introduceCharacter;
1965
+ const existingAgent = room.getAgents().find((a) => room.checkAgentNicknameMatch(a.agentNickname, newCharacterName));
1966
+ if (existingAgent) {
1967
+ logger_1.logger.log(`INTRODUCE: ${newCharacterName} ignored - character already in story`);
1968
+ return;
1847
1969
  }
1970
+ const declinedCharacters = story?.declinedCharacters || [];
1971
+ if (declinedCharacters.includes(newCharacterName)) {
1972
+ logger_1.logger.log(`Character ${newCharacterName} was declined, skipping prompt`);
1973
+ return;
1974
+ }
1975
+ story.pendingSuggestion = {
1976
+ type: 'suggest-introduce-character',
1977
+ characterName: newCharacterName,
1978
+ timestamp: Date.now(),
1979
+ };
1980
+ this.storyStore.updateStoryMetadata(storyId, story);
1981
+ this.messageService.emitIntroduceCharacter(storyId, newCharacterName);
1848
1982
  return;
1849
1983
  }
1850
- story.situation = situation;
1984
+ story.situation = displaySituation;
1851
1985
  this.storyStore.updateStoryMetadata(storyId, story);
1852
- logger_1.logger.log(`Updated story ${storyId} situation: ${situation}`);
1853
- this.generateSceneIllustration(storyId, situation).catch((error) => {
1986
+ logger_1.logger.log(`Updated story ${storyId} situation: ${displaySituation}`);
1987
+ this.generateSceneIllustration(storyId, displaySituation).catch((error) => {
1854
1988
  logger_1.logger.error('Illustration generation error:', error);
1855
1989
  });
1856
1990
  }
@@ -1887,7 +2021,7 @@ let StoryService = class StoryService {
1887
2021
  if (!story) {
1888
2022
  throw new Error('Story not found');
1889
2023
  }
1890
- const userStoriesDir = path.join(this.configService.getUserDataDir(), 'stories');
2024
+ const userStoriesDir = path.join(this.userPaths.getUserDataDir(), 'stories');
1891
2025
  const storyFolderPath = path.join(userStoriesDir, storyId);
1892
2026
  if (!fs.existsSync(storyFolderPath)) {
1893
2027
  throw new Error('Story folder not found on disk');
@@ -1981,7 +2115,7 @@ exports.StoryService = StoryService = __decorate([
1981
2115
  room_store_service_1.RoomStoreService,
1982
2116
  story_progress_service_1.StoryProgressService,
1983
2117
  story_message_service_1.StoryMessageService,
1984
- configuration_service_1.ConfigurationService,
2118
+ user_paths_service_1.UserPathsService,
1985
2119
  agent_factory_1.AgentFactory,
1986
2120
  room_factory_1.RoomFactory])
1987
2121
  ], StoryService);
@@ -307,6 +307,7 @@ export interface ChaptersResponse {
307
307
  export interface ProgressCharacterResponse {
308
308
  description: string;
309
309
  character_profile: string;
310
+ inventory?: string;
310
311
  }
311
312
  export interface CreatePaymentIntentRequest {
312
313
  amount: number;
@@ -1 +1 @@
1
- window.hierarchyData = "eJx1jc0KgzAQhN9lzrESpWnJO/TSq3gIutbQmEA2niTvXtI/pNDTwM63822IISSG7lQre4FIk6Mh2eAZeoNqZQlvFoLGhZjNjSBwt36Ebo5KYI0OGtYnipMZiOs3dZjT4iAwOMMMjcRjVd6qL1rK2boxkofupDypPguU3DmvISy/XtmcP97nOnG9w/6KX4ec8wMB2FBE"
1
+ window.hierarchyData = "eJx1jc0KgzAQhN9lzmklSkX2HXrpVTwEXWtoTCCbniTvXtI/pNDTwM63822IISQB9W2jB4XIs+Mx2eAFtKFtdAlvVgbhzCLmylC4WT+B6lOrcI8OBOsTx9mMLNWbOi5pdVAYnREBIcl0KG+HL1rKxbopsgf1WnfdkBVK7pyXENZfr667j/e5zlLtsL/i1yHn/AAEMlBK"