briyah 1.2.0 → 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 (84) 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 +2 -0
  16. package/dist-sdk/server/src/ai/LLM/anthropic.service.js +25 -13
  17. package/dist-sdk/server/src/ai/LLM/base-ai.service.d.ts +3 -0
  18. package/dist-sdk/server/src/ai/LLM/base-ai.service.js +10 -0
  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.d.ts +4 -3
  25. package/dist-sdk/server/src/ai/agent.js +12 -5
  26. package/dist-sdk/server/src/ai/ai-debug-logger.d.ts +10 -0
  27. package/dist-sdk/server/src/ai/ai-debug-logger.js +82 -0
  28. package/dist-sdk/server/src/room/message.d.ts +1 -1
  29. package/dist-sdk/server/src/room/message.js +1 -1
  30. package/dist-sdk/server/src/room/room.d.ts +1 -0
  31. package/dist-sdk/server/src/room/room.js +43 -19
  32. package/dist-sdk/server/src/sdk/briyah-config.d.ts +1 -0
  33. package/dist-sdk/server/src/sdk/briyah-config.js +4 -0
  34. package/dist-sdk/server/src/story/story.service.d.ts +7 -0
  35. package/dist-sdk/server/src/story/story.service.js +221 -87
  36. package/dist-sdk/shared/types/app.types.d.ts +1 -0
  37. package/docs/assets/hierarchy.js +1 -1
  38. package/docs/assets/search.js +1 -1
  39. package/docs/classes/Agent.html +15 -16
  40. package/docs/classes/Briyah.html +12 -12
  41. package/docs/classes/BriyahConfigService.html +5 -5
  42. package/docs/classes/Room.html +24 -24
  43. package/docs/classes/RoomMessage.html +11 -11
  44. package/docs/enums/MessageAction.html +3 -3
  45. package/docs/hierarchy.html +1 -1
  46. package/docs/index.html +2 -2
  47. package/docs/interfaces/AgentInfo.html +2 -2
  48. package/docs/interfaces/AgentMessagesResponse.html +2 -2
  49. package/docs/interfaces/AppService.html +110 -110
  50. package/docs/interfaces/Artifact.html +3 -3
  51. package/docs/interfaces/ArtifactMetadata.html +2 -2
  52. package/docs/interfaces/AttachDocumentResponse.html +2 -2
  53. package/docs/interfaces/BriyahConfigOptions.html +7 -7
  54. package/docs/interfaces/ChapterInfo.html +2 -2
  55. package/docs/interfaces/Character.html +2 -2
  56. package/docs/interfaces/CreateAgentResponse.html +2 -2
  57. package/docs/interfaces/CreateRoomResponse.html +2 -2
  58. package/docs/interfaces/CreateStoryResponse.html +2 -2
  59. package/docs/interfaces/FileList.html +2 -2
  60. package/docs/interfaces/LoggingOptions.html +10 -6
  61. package/docs/interfaces/Message.html +2 -2
  62. package/docs/interfaces/ModelInfo.html +2 -2
  63. package/docs/interfaces/PreparedPromptResponse.html +2 -2
  64. package/docs/interfaces/ProcessTextResponse.html +2 -2
  65. package/docs/interfaces/PromptFile.html +2 -2
  66. package/docs/interfaces/PromptFileContent.html +2 -2
  67. package/docs/interfaces/PromptFilesResponse.html +2 -2
  68. package/docs/interfaces/PromptFolder.html +2 -2
  69. package/docs/interfaces/PromptFoldersResponse.html +2 -2
  70. package/docs/interfaces/RoomDetails.html +2 -2
  71. package/docs/interfaces/RoomInfo.html +2 -2
  72. package/docs/interfaces/RoomMessagesResponse.html +2 -2
  73. package/docs/interfaces/StoryErrorEvent.html +3 -3
  74. package/docs/interfaces/StoryIdea.html +2 -2
  75. package/docs/interfaces/StoryInfo.html +3 -3
  76. package/docs/interfaces/StoryIntroduceCharacterEvent.html +3 -3
  77. package/docs/interfaces/StoryProgressChapterEvent.html +3 -3
  78. package/docs/interfaces/StoryState.html +5 -5
  79. package/docs/interfaces/StoryStateEvent.html +3 -3
  80. package/docs/interfaces/Transaction.html +2 -2
  81. package/docs/interfaces/TransactionHistoryResponse.html +2 -2
  82. package/docs/modules.html +1 -1
  83. package/docs/types/PromptScope.html +1 -1
  84. package/package.json +2 -1
@@ -1,29 +1,33 @@
1
- {
2
- "$schema": "http://json-schema.org/draft-07/schema#",
3
- "name": "create_character_response",
4
- "description": "Response schema for creating a detailed character profile",
5
- "type": "object",
6
- "properties": {
7
- "character": {
8
- "type": "object",
9
- "properties": {
10
- "name": {
11
- "type": "string",
12
- "description": "The character's name"
13
- },
14
- "description": {
15
- "type": "string",
16
- "description": "A brief 1-2 sentence description containing only immediately observable physical characteristics"
17
- },
18
- "character_profile": {
19
- "type": "string",
20
- "description": "A detailed character profile including backstory, personality, motivations, strengths, weaknesses, habits, quirks, secrets, and relationships"
21
- }
22
- },
23
- "required": ["name", "description", "character_profile"],
24
- "additionalProperties": false
25
- }
26
- },
27
- "required": ["character"],
28
- "additionalProperties": false
29
- }
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "name": "create_character_response",
4
+ "description": "Response schema for creating a detailed character profile",
5
+ "type": "object",
6
+ "properties": {
7
+ "character": {
8
+ "type": "object",
9
+ "properties": {
10
+ "name": {
11
+ "type": "string",
12
+ "description": "The character's name"
13
+ },
14
+ "description": {
15
+ "type": "string",
16
+ "description": "A brief 1-2 sentence description containing only immediately observable physical characteristics"
17
+ },
18
+ "character_profile": {
19
+ "type": "string",
20
+ "description": "A detailed character profile including backstory, personality, motivations, strengths, weaknesses, habits, quirks, secrets, and relationships"
21
+ },
22
+ "inventory": {
23
+ "type": "string",
24
+ "description": "A concise markdown-formatted inventory of items the character carries plus any notable physical/mental conditions. Use '## Items' and (optionally) '## Conditions' sections. Items are bullet points; conditions are short phrases. If the character has nothing notable, use '## Items\\n- (none)'."
25
+ }
26
+ },
27
+ "required": ["name", "description", "character_profile", "inventory"],
28
+ "additionalProperties": false
29
+ }
30
+ },
31
+ "required": ["character"],
32
+ "additionalProperties": false
33
+ }
@@ -70,6 +70,16 @@ Return a JSON object with a character object that must have:
70
70
  - `name`: The character's name (use "{{characterName}}" exactly)
71
71
  - `description`: The observable description (use "{{characterObservableDesc}}" exactly)
72
72
  - `character_profile`: A detailed, well-written character profile covering all the aspects listed above
73
+ - `inventory`: A concise markdown inventory of what the character carries at the START of the story, plus any notable conditions. Pick items that fit the scenario, setting, and the character's role/profile. Use this exact structure (omit Conditions if there are none):
74
+ ```
75
+ ## Items
76
+ - <item 1>
77
+ - <item 2>
78
+
79
+ ## Conditions
80
+ - <condition 1>
81
+ ```
82
+ Keep it short and concrete (item names, not flavor prose). If the character carries nothing notable, use `## Items\n- (none)`.
73
83
 
74
84
  Example format:
75
85
  ```json
@@ -77,9 +87,10 @@ Example format:
77
87
  "character": {
78
88
  "name": "{{characterName}}",
79
89
  "description": "{{characterObservableDesc}}",
80
- "character_profile": "**Backstory:** [Character's history]...\n\n**Personality:** [Character traits]...\n\n**Motivations:** [What drives them]...\n\n(etc)"
90
+ "character_profile": "**Backstory:** [Character's history]...\n\n**Personality:** [Character traits]...\n\n**Motivations:** [What drives them]...\n\n(etc)",
91
+ "inventory": "## Items\n- Worn leather satchel\n- Brass compass\n- Hunting knife"
81
92
  }
82
93
  }
83
94
  ```
84
- Note: Do NOT use double-quotes anywhere in the description or character_profile; use single-quotes instead.
95
+ Note: Do NOT use double-quotes anywhere in the description, character_profile, or inventory; use single-quotes instead.
85
96
  Do NOT use any characters that might break the JSON parsing.
@@ -1,28 +1,32 @@
1
- {
2
- "name": "create_user_character",
3
- "description": "Create a character profile for the player's character",
4
- "type": "object",
5
- "properties": {
6
- "character": {
7
- "type": "object",
8
- "properties": {
9
- "name": {
10
- "type": "string",
11
- "description": "The character's name"
12
- },
13
- "description": {
14
- "type": "string",
15
- "description": "Brief 1-2 sentence description of immediately observable physical characteristics only"
16
- },
17
- "character_profile": {
18
- "type": "string",
19
- "description": "Detailed character profile including backstory, personality, motivations, strengths, weaknesses, habits, secrets, and current situation"
20
- }
21
- },
22
- "required": ["name", "description", "character_profile"],
23
- "additionalProperties": false
24
- }
25
- },
26
- "required": ["character"],
27
- "additionalProperties": false
28
- }
1
+ {
2
+ "name": "create_user_character",
3
+ "description": "Create a character profile for the player's character",
4
+ "type": "object",
5
+ "properties": {
6
+ "character": {
7
+ "type": "object",
8
+ "properties": {
9
+ "name": {
10
+ "type": "string",
11
+ "description": "The character's name"
12
+ },
13
+ "description": {
14
+ "type": "string",
15
+ "description": "Brief 1-2 sentence description of immediately observable physical characteristics only"
16
+ },
17
+ "character_profile": {
18
+ "type": "string",
19
+ "description": "Detailed character profile including backstory, personality, motivations, strengths, weaknesses, habits, secrets, and current situation"
20
+ },
21
+ "inventory": {
22
+ "type": "string",
23
+ "description": "A concise markdown-formatted inventory of items the player's character carries plus any notable physical/mental conditions. Use '## Items' and (optionally) '## Conditions' sections. Items are bullet points; conditions are short phrases. If the character has nothing notable, use '## Items\\n- (none)'."
24
+ }
25
+ },
26
+ "required": ["name", "description", "character_profile", "inventory"],
27
+ "additionalProperties": false
28
+ }
29
+ },
30
+ "required": ["character"],
31
+ "additionalProperties": false
32
+ }
@@ -46,6 +46,16 @@ Return a JSON object with a single character object that must have:
46
46
  - `name`: The character's name (extracted from description or created appropriately)
47
47
  - `description`: A brief 1-2 sentence description containing ONLY immediately observable characteristics (sex, age, height, build, physical condition, appearance). DO NOT include occupation, backstory, personality traits, or any information that wouldn't be visible to an observer.
48
48
  - `character_profile`: A detailed, well-written character profile covering all the aspects listed above
49
+ - `inventory`: A concise markdown inventory of what the player's character carries at the START of the story, plus any notable conditions. Pick items that fit the scenario and setting. Use this exact structure (omit Conditions if there are none):
50
+ ```
51
+ ## Items
52
+ - <item 1>
53
+ - <item 2>
54
+
55
+ ## Conditions
56
+ - <condition 1>
57
+ ```
58
+ Keep it short and concrete (item names, not flavor prose). If the character carries nothing notable, use `## Items\n- (none)`.
49
59
 
50
60
  Example format:
51
61
  ```json
@@ -53,8 +63,9 @@ Example format:
53
63
  "character": {
54
64
  "name": "Elena Rodriguez",
55
65
  "description": "A woman in her early 30s with olive skin, dark hair pulled back in a ponytail, and an athletic build. She has a small scar above her left eyebrow.",
56
- "character_profile": "**Backstory:** Elena grew up in...\n\n**Personality:** She is fiercely independent and...\n\n(etc)"
66
+ "character_profile": "**Backstory:** Elena grew up in...\n\n**Personality:** She is fiercely independent and...\n\n(etc)",
67
+ "inventory": "## Items\n- Smartphone\n- Worn leather wallet\n- House keys on a brass ring"
57
68
  }
58
69
  }
59
70
  ```
60
- Note: Do NOT use double-quotes anywhere in the description or character_profile; use single-quotes instead.
71
+ Note: Do NOT use double-quotes anywhere in the description, character_profile, or inventory; use single-quotes instead.
@@ -1,18 +1,22 @@
1
- {
2
- "$schema": "http://json-schema.org/draft-07/schema#",
3
- "name": "progress_character_response",
4
- "description": "Response schema for updating a character profile as the story progresses",
5
- "type": "object",
6
- "properties": {
7
- "description": {
8
- "type": "string",
9
- "description": "A brief 1-2 sentence description containing only immediately observable physical characteristics"
10
- },
11
- "character_profile": {
12
- "type": "string",
13
- "description": "An updated markdown-formatted character profile reflecting growth and changes from recent story events"
14
- }
15
- },
16
- "required": ["character_profile"],
17
- "additionalProperties": false
18
- }
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "name": "progress_character_response",
4
+ "description": "Response schema for updating a character profile as the story progresses",
5
+ "type": "object",
6
+ "properties": {
7
+ "description": {
8
+ "type": "string",
9
+ "description": "A brief 1-2 sentence description containing only immediately observable physical characteristics"
10
+ },
11
+ "character_profile": {
12
+ "type": "string",
13
+ "description": "An updated markdown-formatted character profile reflecting growth and changes from recent story events"
14
+ },
15
+ "inventory": {
16
+ "type": "string",
17
+ "description": "An updated concise markdown inventory reflecting items gained, lost, consumed, equipped, or any new/resolved conditions since the last chapter. Use '## Items' and (optionally) '## Conditions' sections. Omit this field if the character was just introduced or had no inventory artifact yet."
18
+ }
19
+ },
20
+ "required": ["character_profile"],
21
+ "additionalProperties": false
22
+ }
@@ -67,12 +67,16 @@ Create an updated character profile that includes:
67
67
  - Consider how relationships with other characters have evolved
68
68
 
69
69
  ## Response format
70
- Return a JSON object with a single `character_profile` property containing the entire updated markdown-formatted character profile as a string, ending with the diary entry section.
70
+ Return a JSON object with these fields:
71
+ - `description`: Updated observable description (optional — only include if appearance changed).
72
+ - `character_profile`: The entire updated markdown-formatted character profile, ending with the diary entry section.
73
+ - `inventory`: An updated concise inventory reflecting any items {{agentName}} gained, lost, consumed, or equipped during recent events, plus any new/resolved physical or mental conditions (wounded, healed, exhausted, etc.). Use `## Items` and (optionally) `## Conditions` sections. Carry forward unchanged items from the current inventory. Omit this field entirely if there is no existing inventory artifact and nothing meaningful to record.
71
74
 
72
75
  Example format:
73
76
  ```json
74
77
  {
75
78
  "description": "A woman in her early 30s with olive skin, dark hair pulled back in a ponytail, and an athletic build. She has a small scar above her left eyebrow.",
76
- "character_profile": "**Name:** {{agentName}}\n\n**Backstory:** [Updated backstory integrating recent events]\n\n**Personality:** [Evolution of traits]\n\n...\n\n**Personal Diary Entry:**\n\n*[Date or chapter reference]*\n\nDear Diary,\n\n[First-person reflection in character's voice]\n\n[Character's signature or closing]"
79
+ "character_profile": "**Name:** {{agentName}}\n\n**Backstory:** [Updated backstory integrating recent events]\n\n**Personality:** [Evolution of traits]\n\n...\n\n**Personal Diary Entry:**\n\n*[Date or chapter reference]*\n\nDear Diary,\n\n[First-person reflection in character's voice]\n\n[Character's signature or closing]",
80
+ "inventory": "## Items\n- Worn leather satchel\n- Brass compass\n- Hunting knife (chipped)\n\n## Conditions\n- Sprained ankle (healing)"
77
81
  }
78
82
  ```
@@ -0,0 +1,31 @@
1
+ You are creating a visual portrait description for {{characterName}}, a minor character in an interactive story. This portrait will be edited into later scene images, so it must establish a consistent visual identity.
2
+
3
+ **Story Scenario:**
4
+ {{scenario}}
5
+
6
+ **What we know about the character:**
7
+ {{characterProfile}}
8
+
9
+ The information above is brief — likely just a sentence or two grounded in recent narration. Your job is to expand it into a complete, consistent visual description suitable for AI image generation. Invent reasonable details where the narration is silent (build, exact hair color, clothing texture, etc.), staying consistent with the scenario, role, and any specifics the narration did give.
10
+
11
+ Cover these elements:
12
+
13
+ 1. **Physical Appearance**: Face shape, hair (color, style, length), eyes (color, shape), skin tone, build, height, approximate age, facial features
14
+ 2. **Clothing and Attire**: Specific colors, materials, and style appropriate to their role and the scenario
15
+ 3. **Distinctive Features**: Scars, tattoos, jewelry, accessories, or anything that makes them visually recognizable across scenes
16
+ 4. **Expression and Demeanor**: Their typical facial expression and body language
17
+ 5. **Setting Context**: Keep the setting minimal; this portrait will be edited into another scene later
18
+ 6. **Art Style**: Specify a consistent, high-quality art style (e.g., "professional digital portrait art", "realistic character concept art", "cinematic portrait photography")
19
+
20
+ **Important Guidelines:**
21
+ - Be extremely specific about physical features (don't say "average height", say "5'10 tall" or "petite, around 5'3")
22
+ - Include concrete details about clothing, colors, textures, and materials
23
+ - Stay consistent with anything the narration already established — do not contradict it
24
+ - Avoid abstract concepts; focus only on what can be visually depicted
25
+ - Include appropriate lighting and mood that suits the character's role
26
+ - The description should feel cohesive and natural, not like a list
27
+ - If the character is a minor, be very careful to avoid sensuous language or revealing attire that could result in the image request being rejected
28
+
29
+ Create a single, cohesive paragraph (150-200 words) that can be used directly as an image generation prompt.
30
+
31
+ Return only the visual description text. No preamble, commentary, or JSON formatting — just the descriptive paragraph.
@@ -23,10 +23,28 @@
23
23
  },
24
24
  "characterNames": {
25
25
  "type": "array",
26
- "description": "The exact character names taken from the Characters list which should appear in the scene.",
26
+ "description": "The exact character names that should appear in the scene. Names from the Characters list MUST match exactly; names not in the list will be treated as new minor characters and must have a matching entry in newCharacters.",
27
27
  "items": {
28
28
  "type": "string"
29
29
  }
30
+ },
31
+ "newCharacters": {
32
+ "type": "array",
33
+ "description": "For every name in characterNames that is NOT in the input Characters list, provide a brief visual description grounded in the recent narration so a portrait can be generated. Leave empty if every name in characterNames is already in the Characters list.",
34
+ "items": {
35
+ "type": "object",
36
+ "properties": {
37
+ "name": {
38
+ "type": "string",
39
+ "description": "Must exactly match a name in characterNames that is not in the input Characters list."
40
+ },
41
+ "briefDescription": {
42
+ "type": "string",
43
+ "description": "1-3 sentence visual description of the character grounded in the recent narration (appearance, attire, distinguishing features)."
44
+ }
45
+ },
46
+ "required": ["name", "briefDescription"]
47
+ }
30
48
  }
31
49
  },
32
50
  "required": ["isReference", "sceneName", "sceneDescription", "characterNames"]
@@ -38,7 +38,8 @@ Images are only created when the scene changes or something significant happens,
38
38
  - imageCaption: A single sentence caption describing what is happening in the image
39
39
  - sceneDescription: CHARACTER INTERACTIONS and positions
40
40
  - Include in the description: Professional concept art, narrative illustration, cinematic composition.
41
- - characterNames: [exact character names from the Character list]
41
+ - characterNames: Names of the characters appearing in the scene. Prefer exact names from the Characters list. If the narration introduces an unnamed minor character who is clearly present (e.g. "the innkeeper", "a guard"), you may include them — assign a short consistent name (e.g. "Innkeeper", "Guard at the Gate") so the same name can be reused in future scenes.
42
+ - newCharacters: For every name in characterNames that is NOT in the Characters list above, add an entry with a 1-3 sentence visual description grounded in the recent narration. Omit or leave empty if every character is already in the list.
42
43
 
43
44
  **Guidelines:**
44
45
  - Match existing scenes even if details vary slightly
@@ -32,7 +32,7 @@ NARRATION RULES:
32
32
  - Ignore any part of the requested action that specifies a certain outcome (characters only get to specify what they want to do; you must determine what actually happens).
33
33
  - Think about what the most realistic outcomes of that action might be using your knowledge of the story world
34
34
  - Narrate the requested action and the details of how it plays out
35
- - If the character has included any dialog in their request, try to incorporate it into your narration as appropriate
35
+ - If the character has included any dialog in their request, you must incorporate it into your narration or it will be lost.
36
36
  - Describe what happens with vivid details
37
37
  - Be descriptive and immersive
38
38
  - Create consequences of the characters actions - both intended and unintended
@@ -43,18 +43,17 @@ NARRATION RULES:
43
43
 
44
44
  ### Progressing to the next chapter
45
45
  When the story gets to a point where the characters have worked through a lot of the content in the plot plan
46
- or if the characters are moving a story in a different direction than the plot plan anticipated, return the single string `# Situation: PROGRESS`
46
+ or if the characters are moving a story in a different direction than the plot plan anticipated, set `<progress_chapter>yes</progress_chapter>`
47
47
  This will cause the system to update the plot plan and the character profiles to move the story along.
48
48
  Try to do this when there is a notable pause (end of day) or a significant transition in the story direction.
49
49
 
50
50
  ### Introducing a new character
51
- If, in the course of the story, the characters meet a new character who is in the Available Characters list,
51
+ If a character attempts to talk to or interact with a character who is *not* in the Available Characters list,
52
52
  You should:
53
- - Decide whether or not this new character is going to be significant to the story
54
- - If so, choose a one-word name for that character (which will because their agent name). Prefer a single first name.
55
- - Include `INTRODUCE: [CharacterName]` in your situation line so the system can create a new agent for that character:
56
- `# Situation: INTRODUCE: Sergei`
57
- - If that character is *not* going to be significant in the story and doesn't need their own character agent, simply respond with dialog and narration like always and do not include the "INTRODUCE" tag.
53
+ - Decide whether or not this character is going to be significant to the story
54
+ - If so, choose a one-word name for that character (which will become their agent name). Prefer a single first name.
55
+ - Set `<introduce_character>CharacterName</introduce_character>` so the system can create a new agent for that character.
56
+ - If that character is *not* going to be significant in the story and doesn't need their own character agent, set `<introduce_character>none</introduce_character>` and simply respond with dialog and narration like always.
58
57
 
59
58
  ### When you receive a PASS message
60
59
  This means the user has decided not to take any particular action, so just continue narrating more of the story.
@@ -71,36 +70,71 @@ You must:
71
70
 
72
71
  ## Response Format
73
72
 
74
- ### situation (current situation summary)
75
- The first line of your response *must* be a brief 1-2 sentence description of that contains:
76
- - The current time of day (24-hour clock)
73
+ Every response **must** begin with four metadata tags, each on its own line, in this exact order:
74
+
75
+ ```
76
+ <time>HH:MM</time>
77
+ <situation>brief description of what is happening and who is present</situation>
78
+ <introduce_character>none | CharacterName (brief reasoning)</introduce_character>
79
+ <progress_chapter>no | yes (brief reasoning)</progress_chapter>
80
+ ```
81
+
82
+ Then a blank line, then your narration prose.
83
+
84
+ ### `<time>`
85
+ 24-hour clock. Compute by reading the current time from the most recent `Current Situation` and adding however much story time has passed during this narration.
86
+
87
+ ### `<situation>`
88
+ A brief 1-2 sentence description of:
77
89
  - What's happening right now
78
90
  - Which characters are present in the scene
79
- It **must** be on a single line that begins with `# Situation: `
80
91
 
81
- **Good situation examples:**
82
- - # Situation: 19:45 - Mike and Jessica are having a conversation around the fire while the others rest
83
- - # Situation: 21:40 - Alex, Bob, and Cindy are rowing down the river together at dusk
84
- - # Situation: 18:05 - Alex is sneaking off into the woods alone
85
-
86
- **Why situation matters:**
87
- - Helps maintain consistency and realism in the passage of time in the story
88
- The moderator uses this to decide message routing. For example:
92
+ The moderator uses this to decide message routing:
89
93
  - Characters in the same location hear each other
90
94
  - Characters in different locations don't
91
95
  - Private conversations stay private
92
96
  - Characters not currently involved in the story do not hear the narration
93
97
 
94
- **Computing Time of Day:**
95
- - The current time of day should appear in the 'Current Situation' string of the most recent message.
96
- - Estimate how much story time will have passed during this narration
97
- - Update the time of day in the '# Situation' string of your response with the new time of day.
98
+ **Good situation examples:**
99
+ - `<situation>Mike and Jessica are having a conversation around the fire while the others rest</situation>`
100
+ - `<situation>Alex, Bob, and Cindy are rowing down the river together at dusk</situation>`
101
+ - `<situation>Alex is sneaking off into the woods alone</situation>`
102
+
103
+ ### `<introduce_character>`
104
+ This is a deliberate decision you must make on every turn. You **must** include reasoning in parentheses, even when the value is `none`.
105
+
106
+ Choose `none` when no new character agent is needed.
107
+ Choose a single capitalized first name when a character should be promoted to their own agent — see the "Introducing a new character" section above for criteria.
108
+
109
+ **Examples:**
110
+ - `<introduce_character>none (the merchant is a one-time interaction, no need for a persistent agent)</introduce_character>`
111
+ - `<introduce_character>none (Sergei is mentioned but not present in the scene)</introduce_character>`
112
+ - `<introduce_character>Sergei (the user has spoken with the dock master three times and might feature heavily in the story)</introduce_character>`
113
+
114
+ ### `<progress_chapter>`
115
+ This is a deliberate decision you must make on every turn. You **must** include reasoning in parentheses, even when the value is `no`.
116
+
117
+ Choose `no` when the current chapter still has material to play out.
118
+ Choose `yes` only at a notable pause (end of day, significant transition) when the chapter's main beats have been covered — see the "Progressing to the next chapter" section above.
119
+
120
+ **Examples:**
121
+ - `<progress_chapter>no (the morning conversation between Jessica and Coinneach is still developing)</progress_chapter>`
122
+ - `<progress_chapter>no (characters are mid-journey, not yet at a natural pause)</progress_chapter>`
123
+ - `<progress_chapter>yes (the party has arrived at Drummond Hall, completing chapter 2's journey arc, and night is falling)</progress_chapter>`
124
+
125
+ ### Full example
98
126
 
99
- Example:
100
127
  Current Situation: 13:00 - Mike and Jessica are exploring the temple alone
101
- Response message:
102
- # Situation: 13:30 - Mike and Jessica are descending deep inside the temple
128
+
129
+ Response:
130
+ ```
131
+ <time>13:30</time>
132
+ <situation>Mike and Jessica are descending deep inside the temple</situation>
133
+ <introduce_character>none (no new characters in this scene)</introduce_character>
134
+ <progress_chapter>no (the temple exploration has just begun)</progress_chapter>
135
+
103
136
  Mike and Jessica spend half an hour climbing down the stairs and find themselves in a dark cavern.
137
+ ```
104
138
 
105
139
 
106
140
  ## Narration Style
@@ -133,7 +167,11 @@ Mike and Jessica spend half an hour climbing down the stairs and find themselves
133
167
 
134
168
  Correct response:
135
169
  ```
136
- # Situation: 13:00 - Mike is exploring the temple alone
170
+ <time>13:00</time>
171
+ <situation>Mike is exploring the temple alone</situation>
172
+ <introduce_character>none (no new characters appear in this scene)</introduce_character>
173
+ <progress_chapter>no (the exploration of the temple has barely begun)</progress_chapter>
174
+
137
175
  As Mike traces the weathered symbols with his fingers, he notices they form a pattern - a spiral that seems to repeat in three distinct sections. The stone feels unnaturally cold despite the tropical heat, and where his fingers touch, a faint phosphorescent glow appears briefly before fading. In the center of the spiral, one symbol stands out: it appears to be a stylized eye with three rays emanating from it. The inscription seems to be a warning, though the exact meaning remains unclear without further study.
138
176
  ```
139
177
  NOTE: The character's own declaration of their action is not automatically included in the message history of the story, so you must narrate what the character does as well as the result.
@@ -144,7 +182,11 @@ NOTE: The character's own declaration of their action is not automatically inclu
144
182
 
145
183
  Correct response:
146
184
  ```
147
- # Situation: 13:30 - Jessica and Mike are exploring the temple together
185
+ <time>13:30</time>
186
+ <situation>Jessica and Mike are exploring the temple together</situation>
187
+ <introduce_character>none (no new characters appear in this scene)</introduce_character>
188
+ <progress_chapter>no (the temple exploration is the central activity of the current chapter)</progress_chapter>
189
+
148
190
  "I'm coming!" Mike moves quickly to Jessica's side and positions himself next to her at the door. Together they brace their feet against the ground, and Mike nods to her. "On three. One... two... three!" Mike puts his full weight into pushing the door. At first, the door doesn't budge - it hasn't moved in centuries. Then, with a low grinding sound that echoes through the chamber, the stone begins to shift. Inch by inch, they force it open, their muscles straining with the effort. Ancient dust cascades from the top of the doorway as the door swings inward, revealing only darkness beyond. The air that rushes out is stale and carries an odd metallic scent. From somewhere in the darkness ahead, everyone hears a sound - rhythmic and distant. Drip... drip... drip.
149
191
  ```
150
192
  NOTE: If the character includes dialog in their declared action, try to incorporate it into your narration of the action and the outcome if appropriate.
@@ -156,7 +198,11 @@ Remember, the user will only see your narration, so you must narrate the request
156
198
 
157
199
  Correct response:
158
200
  ```
159
- # Situation: 14:00 - Jessica and Mike are recovering an ancient artifact
201
+ <time>14:00</time>
202
+ <situation>Jessica and Mike are recovering an ancient artifact</situation>
203
+ <introduce_character>none (no new characters appear in this scene)</introduce_character>
204
+ <progress_chapter>no (the artifact recovery has just gone wrong - there will be consequences to play out)</progress_chapter>
205
+
160
206
  "I'll get it, Jessica!" Mike lunges toward the rolling artifact, but it's moving far too quickly. It tumbles into the ravine before Mike is able to reach it.
161
207
  ```
162
208
  NOTE: Try to preserve the dialog and the character's intended action but only you, the narrator, get to determine the actual outcome.
@@ -167,7 +213,11 @@ NOTE: Try to preserve the dialog and the character's intended action but only yo
167
213
 
168
214
  Correct response:
169
215
  ```
170
- # Situation: 15:00 - Jessica and Mike are dehydrated and wandering in the desert
216
+ <time>15:00</time>
217
+ <situation>Jessica and Mike are dehydrated and wandering in the desert</situation>
218
+ <introduce_character>none (no new characters appear in this scene)</introduce_character>
219
+ <progress_chapter>no (the desert crossing is unresolved)</progress_chapter>
220
+
171
221
  Mike raises his parched face points ahead of them. "Look, Jessica! It's an oasis! Water at last!" But as they approach it, it turns out to be only a mirage.
172
222
  ```
173
223
  NOTE: Decide outcomes based on the plot plan and your judgement of what is most realistic in the story world. Do *not* let the characters narrate their own outcomes.
@@ -177,7 +227,11 @@ NOTE: Decide outcomes based on the plot plan and your judgement of what is most
177
227
 
178
228
  Correct response:
179
229
  ```
180
- # Situation: 19:30 - Mike and Jessica are camping at night near the temple ruins
230
+ <time>19:30</time>
231
+ <situation>Mike and Jessica are camping at night near the temple ruins</situation>
232
+ <introduce_character>none (Elena is already in the Available Characters list)</introduce_character>
233
+ <progress_chapter>no (the artifact's awakening is a chapter beat still unfolding, not a chapter close)</progress_chapter>
234
+
181
235
  Time passes. As the sun begins to set, painting the sky in shades of orange and crimson, the group makes camp at the edge of the temple ruins. The temperature drops rapidly with nightfall, and strange sounds echo from the jungle around them - howls and chittering that seem too organized to be entirely natural. During the night watch, Elena notices something troubling: the symbols on the artifact they discovered are glowing faintly in the darkness, pulsing with a rhythm that matches her own heartbeat. Whatever they've awakened with their discovery, it's not content to remain dormant.
182
236
  ```
183
237
 
@@ -186,8 +240,12 @@ Time passes. As the sun begins to set, painting the sky in shades of orange and
186
240
 
187
241
  Correct response:
188
242
  ```
189
- # Situation: PROGRESS
243
+ <time>22:30</time>
244
+ <situation>Mike and the party have defeated the dragon and are preparing to rest</situation>
245
+ <introduce_character>none (no new characters in this scene)</introduce_character>
246
+ <progress_chapter>yes (the dragon defeat is the chapter's climactic beat; the party is settling for the night, a natural pause for the chapter break)</progress_chapter>
190
247
  ```
248
+ NOTE: When `<progress_chapter>yes</progress_chapter>` is set, no narration prose is required - the system will take over for chapter progression.
191
249
 
192
250
 
193
251
  **Example 7: Introducing a new character**
@@ -195,12 +253,15 @@ Correct response:
195
253
 
196
254
  Correct response:
197
255
  ```
198
- # Situation: INTRODUCE: Benjamin
256
+ <time>10:15</time>
257
+ <situation>Mike is in the museum lobby speaking with the curator for the first time</situation>
258
+ <introduce_character>Benjamin (the museum curator is a knowledge gatekeeper for the artifact plotline and the user has initiated direct dialog with him)</introduce_character>
259
+ <progress_chapter>no (Mike has just arrived at the museum, the investigation is beginning)</progress_chapter>
199
260
 
200
261
  That's right. I'm Benjamin Morris, the curator of this museum. What can I do to help you?
201
262
  ```
202
263
  NOTE: Typically, the narrator only responds to requested actions not dialog, but the Moderator routed this dialog message to the Narrator because that character was not on its Available Characters list.
203
- If the Narrator decides that this museum curator is going to be central to the story, the Narrator sets the Situation to "INTRODUCE: Benjamin" which causes a new agent to be created for that character.
264
+ If the Narrator decides that this museum curator is going to be central to the story, setting `<introduce_character>Benjamin</introduce_character>` causes a new agent to be created for that character.
204
265
 
205
266
  ## Important Reminders
206
267
  - **Narrate consequences, not feelings** - describe what happens, what characters sense
@@ -23,14 +23,40 @@
23
23
  "type": "string"
24
24
  }
25
25
  },
26
- "update_portrait": {
27
- "type": "array",
28
- "description": "List of agent names whose visible appearance has changed (e.g., new outfit, injury, transformation, visible carried item). Leave empty if no visual changes occurred.",
29
- "items": {
30
- "type": "string"
31
- }
26
+ "changes": {
27
+ "type": "object",
28
+ "description": "Optional story state changes triggered by this message",
29
+ "properties": {
30
+ "update_portrait": {
31
+ "type": "array",
32
+ "description": "List of agent names whose visible appearance has changed (e.g., new outfit, injury, transformation, visible carried item). Leave empty or omit if no visual changes occurred.",
33
+ "items": {
34
+ "type": "string"
35
+ }
36
+ },
37
+ "update_inventory": {
38
+ "type": "array",
39
+ "description": "List of character inventory updates triggered by this message. Each entry replaces the named character's existing '[name] - Inventory' artifact wholesale. Include an entry only when items have actually been gained, lost, consumed, equipped, or when a notable physical/mental trait or condition has changed (wounded, exhausted, intoxicated, transformed, etc.). Leave empty or omit if nothing changed.",
40
+ "items": {
41
+ "type": "object",
42
+ "properties": {
43
+ "characterName": {
44
+ "type": "string",
45
+ "description": "The exact nickname of the character whose inventory is being updated."
46
+ },
47
+ "inventory": {
48
+ "type": "string",
49
+ "description": "The full updated inventory text. Concise markdown. Include an '## Items' section listing things the character has on their person, and a '## Conditions' section listing notable physical or mental traits and states. Omit either section if empty."
50
+ }
51
+ },
52
+ "required": ["characterName", "inventory"],
53
+ "additionalProperties": false
54
+ }
55
+ }
56
+ },
57
+ "additionalProperties": false
32
58
  }
33
59
  },
34
- "required": ["action", "content", "name", "targets", "update_portrait"],
60
+ "required": ["action", "content", "name", "targets", "changes"],
35
61
  "additionalProperties": false
36
62
  }