briyah 1.2.0 → 1.2.2
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.
- package/data/common/config/markup +1 -1
- package/data/common/config/model_prices.json +3775 -653
- package/data/common/prompts/character/create_character.json +33 -29
- package/data/common/prompts/character/create_character.prompt +13 -2
- package/data/common/prompts/character/create_user_character.json +32 -28
- package/data/common/prompts/character/create_user_character.prompt +13 -2
- package/data/common/prompts/character/progress_character.json +22 -18
- package/data/common/prompts/character/progress_character.prompt +6 -2
- package/data/common/prompts/illustrator/describe_character.prompt +31 -0
- package/data/common/prompts/illustrator/describe_scene.json +19 -1
- package/data/common/prompts/illustrator/describe_scene.prompt +2 -1
- package/data/common/prompts/narrator/perceive.prompt +96 -35
- package/data/common/prompts/story_moderator/moderate.json +33 -7
- package/data/common/prompts/story_moderator/moderate.prompt +166 -20
- package/dist-sdk/server/src/ai/LLM/anthropic.service.d.ts +2 -0
- package/dist-sdk/server/src/ai/LLM/anthropic.service.js +25 -13
- package/dist-sdk/server/src/ai/LLM/base-ai.service.d.ts +3 -0
- package/dist-sdk/server/src/ai/LLM/base-ai.service.js +10 -0
- package/dist-sdk/server/src/ai/LLM/deepseek.service.js +10 -0
- package/dist-sdk/server/src/ai/LLM/googleai.service.js +11 -8
- package/dist-sdk/server/src/ai/LLM/grok.service.js +8 -5
- package/dist-sdk/server/src/ai/LLM/openai.service.d.ts +2 -0
- package/dist-sdk/server/src/ai/LLM/openai.service.js +46 -11
- package/dist-sdk/server/src/ai/LLM/together.service.js +9 -6
- package/dist-sdk/server/src/ai/agent.d.ts +4 -3
- package/dist-sdk/server/src/ai/agent.js +12 -5
- package/dist-sdk/server/src/ai/ai-debug-logger.d.ts +10 -0
- package/dist-sdk/server/src/ai/ai-debug-logger.js +82 -0
- package/dist-sdk/server/src/room/message.d.ts +1 -1
- package/dist-sdk/server/src/room/message.js +1 -1
- package/dist-sdk/server/src/room/room.d.ts +1 -0
- package/dist-sdk/server/src/room/room.js +43 -19
- package/dist-sdk/server/src/sdk/briyah-config.d.ts +1 -0
- package/dist-sdk/server/src/sdk/briyah-config.js +4 -0
- package/dist-sdk/server/src/sdk/index.d.ts +2 -0
- package/dist-sdk/server/src/story/story.service.d.ts +7 -0
- package/dist-sdk/server/src/story/story.service.js +221 -87
- package/dist-sdk/shared/types/app.types.d.ts +1 -0
- package/docs/assets/hierarchy.js +1 -1
- package/docs/assets/navigation.js +1 -1
- package/docs/assets/search.js +1 -1
- package/docs/classes/Agent.html +18 -23
- package/docs/classes/Briyah.html +11 -21
- package/docs/classes/BriyahConfigService.html +5 -5
- package/docs/classes/Room.html +24 -24
- package/docs/classes/RoomMessage.html +11 -11
- package/docs/enums/MessageAction.html +3 -3
- package/docs/hierarchy.html +1 -1
- package/docs/index.html +2 -2
- package/docs/interfaces/AgentInfo.html +2 -2
- package/docs/interfaces/AgentMessagesResponse.html +2 -2
- package/docs/interfaces/AppService.html +133 -138
- package/docs/interfaces/Artifact.html +3 -3
- package/docs/interfaces/ArtifactMetadata.html +2 -2
- package/docs/interfaces/AttachDocumentResponse.html +2 -2
- package/docs/interfaces/BriyahConfigOptions.html +7 -7
- package/docs/interfaces/ChapterInfo.html +2 -2
- package/docs/interfaces/Character.html +2 -2
- package/docs/interfaces/CreateAgentResponse.html +2 -2
- package/docs/interfaces/CreateRoomResponse.html +2 -2
- package/docs/interfaces/CreateStoryResponse.html +2 -2
- package/docs/interfaces/FileList.html +2 -2
- package/docs/interfaces/FileMetadata.html +8 -0
- package/docs/interfaces/IConfigService.html +6 -0
- package/docs/interfaces/LoggingOptions.html +10 -6
- package/docs/interfaces/Message.html +2 -2
- package/docs/interfaces/ModelInfo.html +2 -2
- package/docs/interfaces/PreparedPromptResponse.html +2 -2
- package/docs/interfaces/ProcessTextResponse.html +2 -2
- package/docs/interfaces/PromptFile.html +2 -2
- package/docs/interfaces/PromptFileContent.html +2 -2
- package/docs/interfaces/PromptFilesResponse.html +2 -2
- package/docs/interfaces/PromptFolder.html +2 -2
- package/docs/interfaces/PromptFoldersResponse.html +2 -2
- package/docs/interfaces/RoomDetails.html +2 -2
- package/docs/interfaces/RoomInfo.html +2 -2
- package/docs/interfaces/RoomMessagesResponse.html +2 -2
- package/docs/interfaces/StoryErrorEvent.html +3 -3
- package/docs/interfaces/StoryIdea.html +2 -2
- package/docs/interfaces/StoryInfo.html +3 -3
- package/docs/interfaces/StoryIntroduceCharacterEvent.html +3 -3
- package/docs/interfaces/StoryProgressChapterEvent.html +3 -3
- package/docs/interfaces/StoryState.html +5 -5
- package/docs/interfaces/StoryStateEvent.html +3 -3
- package/docs/interfaces/Transaction.html +2 -2
- package/docs/interfaces/TransactionHistoryResponse.html +2 -2
- package/docs/modules.html +1 -1
- package/docs/types/PromptScope.html +1 -1
- package/package.json +2 -1
|
@@ -242,8 +242,9 @@ let StoryService = class StoryService {
|
|
|
242
242
|
this.updateStorySituation(storyId, situation);
|
|
243
243
|
});
|
|
244
244
|
room.setOnModeratorResponse((message) => {
|
|
245
|
-
|
|
246
|
-
|
|
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
|
-
|
|
444
|
-
|
|
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 {
|
|
@@ -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);
|
|
@@ -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
|
-
|
|
1551
|
-
|
|
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
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
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 ${
|
|
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 - ${
|
|
1644
|
+
storyArtifactService.renameArtifact(artifactId, `Portrait - ${characterName}`);
|
|
1583
1645
|
storyArtifactService.updateArtifactDescription(artifactId, visualDescription);
|
|
1584
|
-
logger_1.logger.log(`Generated portrait for ${
|
|
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 ${
|
|
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},
|
|
1621
|
-
return
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
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 = ``;
|
|
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
|
-
|
|
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
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
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) ||
|
|
1961
|
+
let agentCompactionThreshold = Number(process.env.AGENT_COMPACTION_THRESHOLD) || 100000;
|
|
1825
1962
|
await this.compactAgentHistories(room.getAgents(), agentCompactionThreshold);
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
if (
|
|
1830
|
-
|
|
1831
|
-
|
|
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 =
|
|
1984
|
+
story.situation = displaySituation;
|
|
1851
1985
|
this.storyStore.updateStoryMetadata(storyId, story);
|
|
1852
|
-
logger_1.logger.log(`Updated story ${storyId} situation: ${
|
|
1853
|
-
this.generateSceneIllustration(storyId,
|
|
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
|
}
|
package/docs/assets/hierarchy.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
window.hierarchyData = "
|
|
1
|
+
window.hierarchyData = "eJyNkD1rwzAURf/LnZUGObUxGpspQ5Z0DB6E/RyLyBLoKYES9N+DyJcpDu0igXTfO5x7QfA+MtReFp9SVCvZCATqLbXReMdQF5Qyn06PBIWvYH70sPauN4dvCmfTEgSOxnVQsqgFTsFCobWamXg5E/8Y4mghbhEoRO4WeX5xe0gC1WpK3BKzPrwoRVk9KMZFCr1uiZf31Nvlz2j+HIztArlsLeu6SQL5njB33o+/uTN2k9jfVrngCWIz3+G83eZ/Db6RLGWTUroC1QKhaA=="
|
|
@@ -1 +1 @@
|
|
|
1
|
-
window.navigationData = "
|
|
1
|
+
window.navigationData = "eJyNl0FP4zAQhf+Lz9UClWDZ3tgC2kqgrSi31R4sZ5pYJLZlTxHViv++SkhTJ7HHvua9+ZxOnmfUP/8YwgeyFXsG53gJdwKlVmzBDMeKrRioQ+MuRuK3CpuaLdibVAVb3X4uBsZdCQrPtaLmzoG76B6Pq66Wft1PK4+8mhd+PU9XrrXay3IH9l0KiGFGJor5onUzh7RPU1V9m8LFvUgxukZt1F6fCVIh2D0Xpza26hixvL6ZIvqj3As4o5WDOG7qJNHGzFrs8waZhFiUey4wjOjFHMAzIC84chJ0MpFARC6qey0ODSikWxa0UnA/er9Ne3tckBzwUdh1xQ2CjUbF0xMYywWCjUG+VBJhgSN0WSJbF/Clse21yaD6tjR0h9oeM6gjH4V9lDU8SReO9ElMAcg4+wYKtIkMQg+1IcbgGPaky1IqMrVjCwWbTUaPEhyMk3JdQB1N+6BSiK0Fwy0UW6sbQ2c1bKXhWoBzr/CRIs98CWxjsP36MVov50HWWuFoQQdZvSsPSa+YgC8Dq+siMpF8Qy4o6w3HTgrdzpp7QC7r8JXw9BQmmueTmAJkrfmQkQJ3Y+/BWm0f3mNhmXiSuE0B4cE2qGlErFmDmoFAq4uDgGGxJX5hpCB50Nbq0oJz/RZOnBJyJ4/YIcfw9z7LeZDE2509FO7VcuX45K+Dh/L0TMwv6ZJ7Om5PD4ed0Maj4tEM06CTJoTLH9+vrpeff/8DO8aRoA=="
|