briyah 1.2.4 → 1.2.5
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/README.md +55 -6
- package/data/common/config/image_models.json +160 -97
- package/data/common/config/markup +1 -1
- package/data/common/config/story_models.json +15 -3
- package/data/common/config/story_models_full.json +2 -2
- package/data/common/prompts/character/create_user_character.prompt +3 -12
- package/data/common/prompts/character/introduce_character.json +18 -0
- package/data/common/prompts/character/introduce_character.mock +4 -0
- package/data/common/prompts/character/introduce_character.prompt +58 -0
- package/data/common/prompts/character/perceive.prompt +3 -0
- package/data/common/prompts/character/progress_character.json +8 -4
- package/data/common/prompts/character/progress_character.mock +1 -0
- package/data/common/prompts/character/progress_character.prompt +20 -2
- package/data/common/prompts/character/update_portrait.json +18 -0
- package/data/common/prompts/character/update_portrait.mock +4 -0
- package/data/common/prompts/character/update_portrait.prompt +17 -1
- package/data/common/prompts/narrator/create_simple_plot.json +0 -0
- package/data/common/prompts/narrator/create_simple_plot.mock +13 -0
- package/data/common/prompts/narrator/create_simple_plot.prompt +35 -0
- package/data/common/prompts/narrator/perceive.prompt +12 -9
- package/data/common/prompts/narrator/progress_simple_plot.json +0 -0
- package/data/common/prompts/narrator/progress_simple_plot.mock +13 -0
- package/data/common/prompts/narrator/progress_simple_plot.prompt +40 -0
- package/data/common/prompts/perceive.json +1 -1
- package/data/common/prompts/perceive.prompt +82 -20
- package/data/common/prompts/story_moderator/moderate.json +1 -1
- package/data/common/prompts/story_moderator/moderate.prompt +26 -6
- package/dist-sdk/server/src/ai/LLM/anthropic.service.js +1 -2
- package/dist-sdk/server/src/ai/LLM/base-ai.service.d.ts +1 -1
- package/dist-sdk/server/src/ai/LLM/base-ai.service.js +13 -42
- package/dist-sdk/server/src/ai/LLM/deepseek.service.js +9 -0
- package/dist-sdk/server/src/ai/LLM/fal.service.js +1 -2
- package/dist-sdk/server/src/ai/LLM/googleai.service.js +1 -2
- package/dist-sdk/server/src/ai/LLM/grok.service.js +1 -2
- package/dist-sdk/server/src/ai/LLM/openai.service.js +1 -2
- package/dist-sdk/server/src/ai/LLM/together.service.js +1 -2
- package/dist-sdk/server/src/ai/agent-config.d.ts +2 -0
- package/dist-sdk/server/src/ai/agent-store.service.js +8 -0
- package/dist-sdk/server/src/ai/agent.d.ts +2 -0
- package/dist-sdk/server/src/ai/agent.js +2 -0
- package/dist-sdk/server/src/ai/model_prices.js +2 -1
- package/dist-sdk/server/src/app/user-service-factory.js +7 -3
- package/dist-sdk/server/src/app.controller.d.ts +15 -4
- package/dist-sdk/server/src/app.controller.js +171 -5
- package/dist-sdk/server/src/app.service.d.ts +19 -5
- package/dist-sdk/server/src/app.service.js +50 -4
- package/dist-sdk/server/src/room/message.js +5 -1
- package/dist-sdk/server/src/room/room-factory.d.ts +5 -1
- package/dist-sdk/server/src/room/room-factory.js +6 -1
- package/dist-sdk/server/src/room/room-store.service.d.ts +5 -1
- package/dist-sdk/server/src/room/room-store.service.js +13 -2
- package/dist-sdk/server/src/room/room.d.ts +25 -4
- package/dist-sdk/server/src/room/room.js +379 -95
- package/dist-sdk/server/src/sdk/index.d.ts +1 -1
- package/dist-sdk/server/src/story/story.service.d.ts +5 -4
- package/dist-sdk/server/src/story/story.service.js +207 -120
- package/dist-sdk/server/src/tools/tool-execution.service.d.ts +19 -0
- package/dist-sdk/server/src/tools/tool-execution.service.js +100 -0
- package/dist-sdk/server/src/tools/tool-store.service.d.ts +17 -0
- package/dist-sdk/server/src/tools/tool-store.service.js +143 -0
- package/dist-sdk/shared/types/app.types.d.ts +44 -5
- package/dist-sdk/shared/types/app.types.js +3 -0
- package/docs/assets/hierarchy.js +1 -1
- package/docs/assets/highlight.css +0 -7
- package/docs/assets/navigation.js +1 -1
- package/docs/assets/search.js +1 -1
- package/docs/classes/Agent.html +22 -14
- package/docs/classes/Briyah.html +10 -10
- package/docs/classes/BriyahConfigService.html +5 -5
- package/docs/classes/Room.html +32 -26
- package/docs/classes/RoomMessage.html +10 -10
- package/docs/enums/MessageAction.html +6 -3
- package/docs/hierarchy.html +1 -1
- package/docs/index.html +12 -5
- package/docs/interfaces/AgentInfo.html +3 -2
- package/docs/interfaces/AgentMessagesResponse.html +2 -2
- package/docs/interfaces/AppService.html +184 -149
- 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 +3 -3
- package/docs/interfaces/IConfigService.html +3 -3
- package/docs/interfaces/LoggingOptions.html +6 -6
- package/docs/interfaces/Message.html +2 -2
- package/docs/interfaces/ModelInfo.html +2 -3
- 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 +5 -4
- 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/ToolDefinition.html +6 -0
- package/docs/interfaces/ToolParameter.html +5 -0
- package/docs/interfaces/ToolsResponse.html +2 -0
- 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/docs/types/ToolRunResult.html +1 -0
- package/package.json +2 -1
|
@@ -16,7 +16,14 @@ Refer to the conversation history above for recent events from your perspective.
|
|
|
16
16
|
## Updated Plot Plan (narrator's eyes only — do not reveal to others)
|
|
17
17
|
{{plotPlan}}
|
|
18
18
|
|
|
19
|
-
##
|
|
19
|
+
## First, decide whether an update is even needed
|
|
20
|
+
Rewriting a full profile is expensive, so only do it when the recent story events genuinely affected {{agentName}}.
|
|
21
|
+
|
|
22
|
+
If {{agentName}} was **not** significantly affected by recent events — they were absent, on the periphery, or nothing happened that would meaningfully change their backstory, personality, motivations, relationships, knowledge, or possessions — then return `{"no_changes": true}` and **nothing else**. Do not rewrite the profile, do not write a new diary entry, and do not include any other fields. The existing profile will be kept unchanged.
|
|
23
|
+
|
|
24
|
+
Only if {{agentName}} **was** significantly affected should you proceed to rewrite the profile below. In that case, set `"no_changes": false` and include the updated fields.
|
|
25
|
+
|
|
26
|
+
## Your task (only when no_changes is false)
|
|
20
27
|
Your task is to create an updated, comprehensive character profile that reflects how {{agentName}} has grown, changed, or been affected by recent events in the story. This profile should capture the character's current state as the story moves forward.
|
|
21
28
|
|
|
22
29
|
The character may have:
|
|
@@ -67,7 +74,17 @@ Create an updated character profile that includes:
|
|
|
67
74
|
- Consider how relationships with other characters have evolved
|
|
68
75
|
|
|
69
76
|
## Response format
|
|
70
|
-
Return a JSON object
|
|
77
|
+
Return a JSON object.
|
|
78
|
+
|
|
79
|
+
**If {{agentName}} was not significantly affected**, return only:
|
|
80
|
+
```json
|
|
81
|
+
{
|
|
82
|
+
"no_changes": true
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
**Otherwise**, return these fields:
|
|
87
|
+
- `no_changes`: `false`
|
|
71
88
|
- `description`: Updated observable description (optional — only include if appearance changed).
|
|
72
89
|
- `character_profile`: The entire updated markdown-formatted character profile, ending with the diary entry section.
|
|
73
90
|
- `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.
|
|
@@ -75,6 +92,7 @@ Return a JSON object with these fields:
|
|
|
75
92
|
Example format:
|
|
76
93
|
```json
|
|
77
94
|
{
|
|
95
|
+
"no_changes": false,
|
|
78
96
|
"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.",
|
|
79
97
|
"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
98
|
"inventory": "## Items\n- Worn leather satchel\n- Brass compass\n- Hunting knife (chipped)\n\n## Conditions\n- Sprained ankle (healing)"
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"name": "update_portrait_response",
|
|
4
|
+
"description": "Response schema for updating a character's portrait when their appearance has changed",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"properties": {
|
|
7
|
+
"visual_prompt": {
|
|
8
|
+
"type": "string",
|
|
9
|
+
"description": "A single cohesive 150-200 word image-editing paragraph describing the character's current appearance, sent directly to the image editing system"
|
|
10
|
+
},
|
|
11
|
+
"description": {
|
|
12
|
+
"type": "string",
|
|
13
|
+
"description": "A brief 1-2 sentence description containing only immediately observable physical characteristics of the character's current appearance"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"required": ["visual_prompt", "description"],
|
|
17
|
+
"additionalProperties": false
|
|
18
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
{
|
|
2
|
+
"visual_prompt": "A high-quality character portrait showing the character as they appear now, maintaining the original art style and lighting, with subtle changes to attire and expression reflecting recent events.",
|
|
3
|
+
"description": "A character whose appearance has changed slightly due to recent events."
|
|
4
|
+
}
|
|
@@ -6,6 +6,11 @@ You are updating the portrait of the character {{characterName}} in an interacti
|
|
|
6
6
|
**Current Character Profile:**
|
|
7
7
|
{{characterProfile}}
|
|
8
8
|
|
|
9
|
+
**Current Observable Description (their appearance before this change):**
|
|
10
|
+
{{currentDescription}}
|
|
11
|
+
|
|
12
|
+
Start from this current observable description and adjust only what has changed — don't re-derive the character's whole appearance from scratch.
|
|
13
|
+
|
|
9
14
|
Your task is to create a detailed visual description of the character as they appear RIGHT NOW. This description will be used to edit their existing portrait image, so focus on their current appearance — including any recent changes — while maintaining the core elements that make the character recognizable.
|
|
10
15
|
|
|
11
16
|
Focus on these key elements:
|
|
@@ -28,4 +33,15 @@ Focus on these key elements:
|
|
|
28
33
|
|
|
29
34
|
Create a single, cohesive paragraph (150-200 words) that can be used directly as an image editing prompt. The description should be detailed enough for an AI to accurately update the existing portrait.
|
|
30
35
|
|
|
31
|
-
|
|
36
|
+
## Response format
|
|
37
|
+
Return a JSON object with these fields:
|
|
38
|
+
- `visual_prompt`: The single cohesive 150-200 word image-editing paragraph described above. This is sent directly to the image editing system.
|
|
39
|
+
- `description`: A brief 1-2 sentence description of how {{characterName}} looks RIGHT NOW, covering only immediately observable physical characteristics (appearance, attire, visible marks). Start from the "Current Observable Description" above and revise only what changed. Do NOT include art-style, lighting, mood, or camera notes. This becomes the character's short observable description, so keep it concise and plainly descriptive.
|
|
40
|
+
|
|
41
|
+
Example format:
|
|
42
|
+
```json
|
|
43
|
+
{
|
|
44
|
+
"visual_prompt": "A weathered man in his 50s, now with a fresh bandage wrapped around his left forearm and a torn, mud-stained jacket ... (150-200 words, image-editing style, including art style and lighting)",
|
|
45
|
+
"description": "A weathered man in his 50s with a freshly bandaged left forearm and a torn, mud-stained jacket."
|
|
46
|
+
}
|
|
47
|
+
```
|
|
File without changes
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
## Scenario Overview
|
|
2
|
+
|
|
3
|
+
A simple test scenario where the characters meet and begin their adventure.
|
|
4
|
+
|
|
5
|
+
## Setting & Environment
|
|
6
|
+
|
|
7
|
+
- **Location**: A test room
|
|
8
|
+
- **Atmosphere**: Calm and quiet
|
|
9
|
+
- **Notable Features**: A door and a window
|
|
10
|
+
|
|
11
|
+
## Situation
|
|
12
|
+
|
|
13
|
+
The characters are gathered together as the story opens, ready to interact.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
You are creating a simple plot plan for an interactive story titled "{{name}}".
|
|
2
|
+
|
|
3
|
+
**Story Scenario:**
|
|
4
|
+
{{scenario}}
|
|
5
|
+
|
|
6
|
+
**Characters:**
|
|
7
|
+
{{#each characters}}
|
|
8
|
+
- **{{name}}**{{#if isControlledByHuman}} (Player Character){{/if}}: {{description}}
|
|
9
|
+
{{/each}}
|
|
10
|
+
|
|
11
|
+
Your task is to write a short, simple plot plan in markdown format. This plot plan is **FOR YOUR EYES ONLY** - the characters will not see it. You will consult it as you narrate the story.
|
|
12
|
+
|
|
13
|
+
Unlike a detailed plot plan, this one is deliberately light. Do **not** invent elaborate mysteries, hidden secrets, plot twists, or a list of scripted events. Just establish the setting and premise so the story can unfold naturally from the characters' actions.
|
|
14
|
+
|
|
15
|
+
## Plot Plan Format:
|
|
16
|
+
Keep it brief - a few short paragraphs total.
|
|
17
|
+
|
|
18
|
+
### 1. Scenario Overview
|
|
19
|
+
Restate the story scenario above in your own words, capturing the premise and tone.
|
|
20
|
+
|
|
21
|
+
### 2. Setting & Environment
|
|
22
|
+
- **Location**: Where does the story take place?
|
|
23
|
+
- **Atmosphere**: The mood and a few sensory details (sights, sounds, weather).
|
|
24
|
+
- **Notable Features**: A couple of locations or landmarks worth mentioning.
|
|
25
|
+
|
|
26
|
+
### 3. Situation
|
|
27
|
+
What is going on as the story opens? What are the characters doing, and what is the immediate circumstance that gets things moving?
|
|
28
|
+
|
|
29
|
+
## Guidelines:
|
|
30
|
+
- Keep it short and grounded - this is a starting point, not a script.
|
|
31
|
+
- Do not plan out secrets, twists, or scripted events; let the story emerge from character choices.
|
|
32
|
+
- Stay consistent with the scenario and character descriptions above.
|
|
33
|
+
- It is not your role to design the characters. They have their own backstories you know nothing of until they reveal them.
|
|
34
|
+
|
|
35
|
+
Return a string containing the entire markdown-formatted plot plan.
|
|
@@ -24,6 +24,9 @@ Use this information to guide your narration letting characters discover any sec
|
|
|
24
24
|
{{visibleArtifacts}}
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
+
### Character Inventories and Conditions
|
|
28
|
+
If a "Character Inventories and Conditions" section is included with the current situation, it lists what each character is currently carrying or wearing and any physical or mental conditions (wounded, exhausted, etc.). Use it to keep your narration consistent — characters can only use items they actually have, and their conditions should shape what they can do. The characters cannot see each other's inventories.
|
|
29
|
+
|
|
27
30
|
## Your Role as Narrator
|
|
28
31
|
|
|
29
32
|
### When you receive a user message, that means a character is requesting to perform an action and you must narrate both the action and its outcome
|
|
@@ -50,10 +53,10 @@ Try to do this when there is a notable pause (end of day) or a significant trans
|
|
|
50
53
|
### Introducing a new character
|
|
51
54
|
If a character attempts to talk to or interact with a character who is *not* in the Available Characters list,
|
|
52
55
|
You should:
|
|
53
|
-
-
|
|
54
|
-
- If so, choose a one-word name for that character (which will become their agent name). Prefer a single first name.
|
|
56
|
+
- Choose a one-word name for that character (which will become their agent name). Prefer a single first name.
|
|
55
57
|
- Set `<introduce_character>CharacterName</introduce_character>` so the system can create a new agent for that character.
|
|
56
|
-
-
|
|
58
|
+
- Do this for *every* new character who speaks or is interacted with, even minor ones. It does not matter whether the character is significant to the story - each character gets their own agent so that every character only knows what they would realistically know.
|
|
59
|
+
- Only set `<introduce_character>none</introduce_character>` when no new character speaks or is interacted with in this narration.
|
|
57
60
|
|
|
58
61
|
### When you receive a PASS message
|
|
59
62
|
This means the user has decided not to take any particular action, so just continue narrating more of the story.
|
|
@@ -103,13 +106,13 @@ The moderator uses this to decide message routing:
|
|
|
103
106
|
### `<introduce_character>`
|
|
104
107
|
This is a deliberate decision you must make on every turn. You **must** include reasoning in parentheses, even when the value is `none`.
|
|
105
108
|
|
|
106
|
-
Choose `none` when no new character
|
|
107
|
-
Choose a single capitalized first name
|
|
109
|
+
Choose `none` only when no new character speaks or is interacted with in this narration.
|
|
110
|
+
Choose a single capitalized first name whenever a character who is *not* in the Available Characters list speaks or is interacted with — even minor characters get their own agent.
|
|
108
111
|
|
|
109
112
|
**Examples:**
|
|
110
|
-
- `<introduce_character>none (
|
|
113
|
+
- `<introduce_character>none (no new characters speak or are interacted with in this scene)</introduce_character>`
|
|
111
114
|
- `<introduce_character>none (Sergei is mentioned but not present in the scene)</introduce_character>`
|
|
112
|
-
- `<introduce_character>Sergei (the
|
|
115
|
+
- `<introduce_character>Sergei (the dock master speaks with the user and is not in the Available Characters list)</introduce_character>`
|
|
113
116
|
|
|
114
117
|
### `<progress_chapter>`
|
|
115
118
|
This is a deliberate decision you must make on every turn. You **must** include reasoning in parentheses, even when the value is `no`.
|
|
@@ -255,13 +258,13 @@ Correct response:
|
|
|
255
258
|
```
|
|
256
259
|
<time>10:15</time>
|
|
257
260
|
<situation>Mike is in the museum lobby speaking with the curator for the first time</situation>
|
|
258
|
-
<introduce_character>Benjamin (the museum curator
|
|
261
|
+
<introduce_character>Benjamin (the museum curator speaks with Mike and is not in the Available Characters list)</introduce_character>
|
|
259
262
|
<progress_chapter>no (Mike has just arrived at the museum, the investigation is beginning)</progress_chapter>
|
|
260
263
|
|
|
261
264
|
That's right. I'm Benjamin Morris, the curator of this museum. What can I do to help you?
|
|
262
265
|
```
|
|
263
266
|
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.
|
|
264
|
-
|
|
267
|
+
Since the curator is a new character being spoken to, setting `<introduce_character>Benjamin</introduce_character>` causes a new agent to be created for that character, regardless of how significant he turns out to be.
|
|
265
268
|
|
|
266
269
|
## Important Reminders
|
|
267
270
|
- **Narrate consequences, not feelings** - describe what happens, what characters sense
|
|
File without changes
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
## Story Progress So Far
|
|
2
|
+
|
|
3
|
+
The characters have moved through the opening events and reached a natural turning point.
|
|
4
|
+
|
|
5
|
+
## Current Situation
|
|
6
|
+
|
|
7
|
+
The group is regrouping and deciding what to do next.
|
|
8
|
+
|
|
9
|
+
## Setting & Environment
|
|
10
|
+
|
|
11
|
+
- **Current Location**: A test room
|
|
12
|
+
- **Atmosphere**: Calm, with a sense of anticipation
|
|
13
|
+
- **Notable Features**: A door and a window
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Progress Simple Plot
|
|
2
|
+
You are updating the simple plot plan for the interactive story as it progresses to the next chapter.
|
|
3
|
+
|
|
4
|
+
## Current Plot Plan
|
|
5
|
+
{{currentPlotPlan}}
|
|
6
|
+
|
|
7
|
+
## Recent Story Events
|
|
8
|
+
Refer to the conversation history above for recent events.
|
|
9
|
+
|
|
10
|
+
## Your Task
|
|
11
|
+
Update the plot plan so it reflects everything that has happened so far in the story. This plot plan is **FOR YOUR EYES ONLY** - the characters will not see it.
|
|
12
|
+
|
|
13
|
+
Keep it simple. Do **not** invent elaborate mysteries, hidden secrets, plot twists, or a list of scripted events. Just keep the setting and situation current so the story can continue to unfold naturally from the characters' actions.
|
|
14
|
+
|
|
15
|
+
As you update the plan:
|
|
16
|
+
- **Review what has happened**: Reflect on the recent story events and how they've unfolded.
|
|
17
|
+
- **Update the situation**: Describe where the characters are now and what has changed since the last chapter.
|
|
18
|
+
- **Stay consistent**: Keep the plan consistent with established story facts and character development.
|
|
19
|
+
|
|
20
|
+
The updated plot plan should include (keep it brief - a few short paragraphs total):
|
|
21
|
+
|
|
22
|
+
## 1. Story Progress So Far
|
|
23
|
+
A brief summary of the key events that have occurred and how they've shaped the story.
|
|
24
|
+
|
|
25
|
+
## 2. Current Situation
|
|
26
|
+
What circumstances do the characters find themselves in now? What has changed?
|
|
27
|
+
|
|
28
|
+
## 3. Setting & Environment
|
|
29
|
+
- **Current Location**: Where are the characters now?
|
|
30
|
+
- **Atmosphere**: The current mood and a few sensory details.
|
|
31
|
+
- **Notable Features**: A couple of locations or landmarks relevant now.
|
|
32
|
+
|
|
33
|
+
**Important Guidelines:**
|
|
34
|
+
- Keep it short and grounded - this is a starting point for the next chapter, not a script.
|
|
35
|
+
- Do not plan out secrets, twists, or scripted events; let the story emerge from character choices.
|
|
36
|
+
- Ensure consistency with established story facts and character development.
|
|
37
|
+
- **This new plot plan replaces the previous one** - make it self-contained.
|
|
38
|
+
|
|
39
|
+
## Response format
|
|
40
|
+
Return the entire markdown-formatted updated plot plan as a string.
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"properties": {
|
|
6
6
|
"action": {
|
|
7
7
|
"type": "string",
|
|
8
|
-
"enum": ["think", "whisper", "speak", "shout", "publish", "execute", "adjourn"]
|
|
8
|
+
"enum": ["think", "whisper", "speak", "shout", "publish", "execute", "commission", "deliver", "adjourn"]
|
|
9
9
|
},
|
|
10
10
|
"targets": {
|
|
11
11
|
"type": "array",
|
|
@@ -61,8 +61,12 @@ You must choose ONE of these actions:
|
|
|
61
61
|
3. **SPEAK** - Normal message that all agents can hear (but always choose one agent to target for a response)
|
|
62
62
|
4. **SHOUT** - Interrupts all other conversations
|
|
63
63
|
5. **PUBLISH** - Create an artifact document that may be shared with other agents
|
|
64
|
-
|
|
65
|
-
|
|
64
|
+
{{#if availableTools}}
|
|
65
|
+
6. **EXECUTE** - Run one of your available tools and privately receive its result
|
|
66
|
+
{{/if}}
|
|
67
|
+
7. **COMMISSION** - Delegate a task to one or more named agents and wait for their deliverables
|
|
68
|
+
8. **DELIVER** - Submit your completed result when you have been commissioned
|
|
69
|
+
9. **ADJOURN** - Used by the group leader when the ultimate room goal has been met
|
|
66
70
|
|
|
67
71
|
## Decision Rules
|
|
68
72
|
|
|
@@ -99,15 +103,43 @@ You must choose ONE of these actions:
|
|
|
99
103
|
- The 'name' string should contain a descriptive name of the artifact being published
|
|
100
104
|
- The 'name' is used to identify the artifact in the conversation
|
|
101
105
|
|
|
106
|
+
{{#if availableTools}}
|
|
102
107
|
### When to EXECUTE
|
|
103
|
-
- When
|
|
108
|
+
- When running one of your available tools (listed below) would help you answer a question, do research, or achieve the room goal.
|
|
104
109
|
|
|
105
110
|
#### Execution rules
|
|
106
|
-
- The '
|
|
107
|
-
- The '
|
|
108
|
-
-
|
|
109
|
-
- The '
|
|
110
|
-
-
|
|
111
|
+
- The 'name' string must contain the exact name of the tool to run (from Your Available Tools below).
|
|
112
|
+
- The 'content' of the JSON response must contain a JSON object of named arguments for the tool, e.g. "{\"city\": \"Paris\"}". Use "{}" if the tool takes no arguments.
|
|
113
|
+
- The 'targets' array is not used for EXECUTE; leave it empty.
|
|
114
|
+
- The tool's result is returned privately to you as a system message. No other agent sees it.
|
|
115
|
+
- You may chain multiple EXECUTE and PUBLISH actions in a single turn (do research, then publish findings) before finally responding with an audible action such as SPEAK. The other agents wait until you respond.
|
|
116
|
+
- If a tool fails, you will receive the error and may retry with corrected arguments or give up and respond normally.
|
|
117
|
+
|
|
118
|
+
#### Your Available Tools
|
|
119
|
+
{{#each availableTools}}
|
|
120
|
+
- **{{this.name}}**: {{this.description}}
|
|
121
|
+
{{#each this.parameters}}
|
|
122
|
+
- {{this.name}} ({{this.type}}{{#if this.required}}, required{{/if}}): {{this.description}}
|
|
123
|
+
{{/each}}
|
|
124
|
+
{{/each}}
|
|
125
|
+
{{/if}}
|
|
126
|
+
|
|
127
|
+
### When to COMMISSION
|
|
128
|
+
- When a task would benefit from one or more other agents doing focused work (research, analysis, drafting) before the conversation continues.
|
|
129
|
+
- The commissioned agents each work independently and reply with a DELIVER; you will then receive all of their deliverables at once, before anyone else speaks.
|
|
130
|
+
|
|
131
|
+
#### Commission rules
|
|
132
|
+
- The 'targets' array must contain the names of the agents you are commissioning (at least one, not yourself).
|
|
133
|
+
- The 'content' should state the task clearly enough that each commissioned agent can work without further clarification.
|
|
134
|
+
- Human-controlled agents cannot be commissioned.
|
|
135
|
+
|
|
136
|
+
### When to DELIVER
|
|
137
|
+
- ONLY when you have been commissioned and have completed your task. This is the required final action of a commissioned agent.
|
|
138
|
+
- Before delivering, you may use EXECUTE and PUBLISH to do the work.
|
|
139
|
+
|
|
140
|
+
#### Deliver rules
|
|
141
|
+
- The 'targets' array should contain the name of the agent who commissioned you.
|
|
142
|
+
- The 'content' must contain your complete result. If you published an artifact as part of your work, mention its name here.
|
|
111
143
|
|
|
112
144
|
### When to ADJOURN
|
|
113
145
|
- When you believe the goals of the room have been achieved and no further discussion would be helpful
|
|
@@ -118,7 +150,7 @@ You must choose ONE of these actions:
|
|
|
118
150
|
Always respond with this exact JSON structure:
|
|
119
151
|
```
|
|
120
152
|
{
|
|
121
|
-
"action": "THINK|WHISPER|SPEAK|SHOUT|PUBLISH|EXECUTE|ADJOURN",
|
|
153
|
+
"action": "THINK|WHISPER|SPEAK|SHOUT|PUBLISH|EXECUTE|COMMISSION|DELIVER|ADJOURN",
|
|
122
154
|
"targets": ["Message target 1", "Message target 2"],
|
|
123
155
|
"name": "Artifact name",
|
|
124
156
|
"content": "The body of your message"
|
|
@@ -127,13 +159,13 @@ Always respond with this exact JSON structure:
|
|
|
127
159
|
**NOTE**: The 'content' property of the JSON response must be double-quoted. Avoid using double-quotes within the actual content itself.
|
|
128
160
|
|
|
129
161
|
## Format Rules
|
|
130
|
-
- `action` must be one of: "THINK", "WHISPER", "SPEAK", "SHOUT", "
|
|
162
|
+
- `action` must be one of: "THINK", "WHISPER", "SPEAK", "SHOUT", "PUBLISH", "EXECUTE", "COMMISSION", "DELIVER", "ADJOURN"
|
|
131
163
|
- `targets` must be:
|
|
132
|
-
- Empty array `[]` for THINK or when speaking to everyone
|
|
133
|
-
- Array with specific agent names for WHISPER, PUBLISH, and
|
|
164
|
+
- Empty array `[]` for THINK, EXECUTE, or when speaking to everyone
|
|
165
|
+
- Array with specific agent names for WHISPER, PUBLISH, COMMISSION, and DELIVER
|
|
134
166
|
- Optional for SPEAK and ADJOURN
|
|
135
|
-
`content` must contain your actual message
|
|
136
|
-
`name` is empty unless publishing an artifact or executing a
|
|
167
|
+
`content` must contain your actual message, the body of your published artifact, or the JSON arguments of the tool you are executing
|
|
168
|
+
`name` is empty unless publishing an artifact (artifact name) or executing a tool (tool name)
|
|
137
169
|
|
|
138
170
|
## Examples
|
|
139
171
|
|
|
@@ -215,15 +247,45 @@ Correct response:
|
|
|
215
247
|
}
|
|
216
248
|
```
|
|
217
249
|
|
|
218
|
-
|
|
219
|
-
|
|
250
|
+
{{#if availableTools}}
|
|
251
|
+
**Example 7: Executing a tool**
|
|
252
|
+
> Alice speaks to {{agentNickname}}: We need to know what the weather will be like in Paris tomorrow.
|
|
220
253
|
|
|
221
|
-
Correct response:
|
|
254
|
+
Correct response (assuming you have a tool named "weather_lookup" that takes a "city" argument):
|
|
222
255
|
```
|
|
223
256
|
{
|
|
224
257
|
"action": "execute",
|
|
225
|
-
"targets": [
|
|
226
|
-
"name": "
|
|
227
|
-
"content": "
|
|
258
|
+
"targets": [],
|
|
259
|
+
"name": "weather_lookup",
|
|
260
|
+
"content": "{\"city\": \"Paris\"}"
|
|
261
|
+
}
|
|
262
|
+
```
|
|
263
|
+
After you receive the tool result, respond audibly (e.g. SPEAK to Alice with the answer).
|
|
264
|
+
{{/if}}
|
|
265
|
+
|
|
266
|
+
**Example 8: Commissioning research from other agents**
|
|
267
|
+
> Alice speaks to {{agentNickname}}: We should compare the two proposals before deciding.
|
|
268
|
+
|
|
269
|
+
Correct response:
|
|
270
|
+
```
|
|
271
|
+
{
|
|
272
|
+
"action": "commission",
|
|
273
|
+
"targets": ["Bob", "Carol"],
|
|
274
|
+
"name": "",
|
|
275
|
+
"content": "Please each analyze one proposal: Bob takes proposal A, Carol takes proposal B. Summarize strengths, weaknesses, and risks."
|
|
276
|
+
}
|
|
277
|
+
```
|
|
278
|
+
You will receive both deliverables before the conversation continues, and are expected to respond to them.
|
|
279
|
+
|
|
280
|
+
**Example 9: Delivering a commissioned result**
|
|
281
|
+
> Bob commissions {{agentNickname}}: Please analyze proposal A and summarize its strengths, weaknesses, and risks.
|
|
282
|
+
|
|
283
|
+
Correct response (after doing the work, possibly using EXECUTE or PUBLISH first):
|
|
284
|
+
```
|
|
285
|
+
{
|
|
286
|
+
"action": "deliver",
|
|
287
|
+
"targets": ["Bob"],
|
|
288
|
+
"name": "",
|
|
289
|
+
"content": "Proposal A analysis: strengths are... weaknesses are... risks are... Full details in the published artifact 'Proposal A Analysis'."
|
|
228
290
|
}
|
|
229
291
|
```
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
},
|
|
37
37
|
"update_inventory": {
|
|
38
38
|
"type": "array",
|
|
39
|
-
"description": "List of character inventory updates triggered by this message. Each entry replaces the named character's existing
|
|
39
|
+
"description": "List of character inventory updates triggered by this message. Each entry replaces the named character's existing stored inventory 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
40
|
"items": {
|
|
41
41
|
"type": "object",
|
|
42
42
|
"properties": {
|
|
@@ -22,7 +22,7 @@ Filter inappropriate language and content from messages.
|
|
|
22
22
|
{{humanAgentName}}
|
|
23
23
|
|
|
24
24
|
### Character Inventories and Conditions
|
|
25
|
-
|
|
25
|
+
Each character's current inventory and conditions are provided to you under a "Character Inventories and Conditions" heading in the message below (visible only to you, not to the characters' peers). These list what each character is currently carrying, wearing, or possessing, plus any notable physical or mental conditions (wounded, exhausted, drunk, transformed, etc.). Use these to keep the story self-consistent — when a character refers to "my sword" the inventory should support it, when a character takes damage you should record the wound, etc.
|
|
26
26
|
|
|
27
27
|
{{#if visibleArtifacts}}
|
|
28
28
|
{{visibleArtifacts}}
|
|
@@ -40,10 +40,12 @@ To accomplish your task:
|
|
|
40
40
|
- Determine whether the Sender of the recent message is trying to 1) perform an action or 2) only participate in dialog
|
|
41
41
|
|
|
42
42
|
### The Current Situation is authoritative
|
|
43
|
+
Each message you receive is preceded by a **Current time** line (a 24-hour "HH:MM" clock) and a **Current Situation** line. The time tells you when the scene is taking place; the situation tells you who is present and where.
|
|
44
|
+
|
|
43
45
|
The **Current Situation** line is the single source of truth about which characters are physically present in the active scene, and where. When routing:
|
|
44
46
|
- Only characters named in the Current Situation are "present". Other characters are elsewhere and cannot hear or respond unless the Current Situation itself changes.
|
|
45
47
|
- Do **not** infer that a character is present from vague references in the body of a narration (e.g., "the men outside", "the others", "everyone"). If a character is not named in the Current Situation, treat them as absent — pick a different responder.
|
|
46
|
-
- Do **not** assume a scene shift based on body content alone. A scene shift only happens when the Current Situation itself names a different time, place, or set of characters. If the situation still says "Jessica and Mòr in the kitchen", the responder must be one of Jessica, Mòr, or the Narrator — never a character who is miles away in another storyline.
|
|
48
|
+
- Do **not** assume a scene shift based on body content alone. A scene shift only happens when the Current time or Current Situation itself names a different time, place, or set of characters. If the situation still says "Jessica and Mòr in the kitchen", the responder must be one of Jessica, Mòr, or the Narrator — never a character who is miles away in another storyline.
|
|
47
49
|
- If the narration genuinely describes a character who is not in the Current Situation (e.g., a brief aside about someone elsewhere), keep the responder among the characters who ARE in the Current Situation; do not hand the turn off to the absent character.
|
|
48
50
|
|
|
49
51
|
### If the Sender is intending to perform an action:
|
|
@@ -73,7 +75,7 @@ This request will *not* become part of the readable story, only the narrator's r
|
|
|
73
75
|
- Use the character's exact name as it appears in the Available Characters list.
|
|
74
76
|
- Leave the array empty if no visible appearance changes occurred.
|
|
75
77
|
- Minor or invisible changes (emotional state alone, unseen actions) do NOT warrant a portrait update.
|
|
76
|
-
- `update_inventory`: list of character
|
|
78
|
+
- `update_inventory`: list of character inventories that should be rewritten in light of this message. Each entry replaces the named character's stored inventory in full.
|
|
77
79
|
- Include an entry when items are gained, lost, consumed, broken, given, taken, equipped, unequipped, OR when a notable physical/mental trait or condition changes (wounded, healed, exhausted, intoxicated, transformed, cursed, blessed, etc.).
|
|
78
80
|
- The `inventory` field must contain the COMPLETE new inventory body (not a diff). Read the character's current inventory artifact from the context above, apply the change, and return the updated artifact text.
|
|
79
81
|
- Use this structure (omit a section if it would be empty):
|
|
@@ -119,7 +121,7 @@ You must respond with a valid JSON object in the following format:
|
|
|
119
121
|
- **Important**:Avoid lengthy conversations that exclude the Human Character completely. Give the Human Character a chance to interact with the story.
|
|
120
122
|
|
|
121
123
|
### When no character is available to respond — auto-PASS to the Narrator
|
|
122
|
-
Sometimes no character in the Current Situation can realistically be the next speaker. The most common case is when the only present character is asleep, unconscious, dead, paralyzed, in a coma, or otherwise narratively unable to speak or act (check their `
|
|
124
|
+
Sometimes no character in the Current Situation can realistically be the next speaker. The most common case is when the only present character is asleep, unconscious, dead, paralyzed, in a coma, or otherwise narratively unable to speak or act (check their `## Conditions` section in the Character Inventories and Conditions provided below). It can also happen when the Current Situation is a transitional beat with no living character actively present.
|
|
123
125
|
|
|
124
126
|
In these cases, emit an automatic PASS on the human's behalf, exactly as you would if the Human Character had typed "PASS":
|
|
125
127
|
- Set `name` to `"Narrator"` — the Narrator can always continue the story.
|
|
@@ -246,7 +248,8 @@ Correct Response:
|
|
|
246
248
|
|
|
247
249
|
|
|
248
250
|
### Example 5b: Narration mentions an absent character, but the Current Situation has NOT shifted
|
|
249
|
-
Current
|
|
251
|
+
Current time: 17:35 (24-hour clock)
|
|
252
|
+
Current Situation: Mike and Jessica are in the kitchen as the evening meal is being prepared
|
|
250
253
|
Recent Message Sender: Narrator
|
|
251
254
|
Recent Message: The kitchen smells of stew and woodsmoke. Outside, the men are tending to the horses. Somewhere else, Sergei is at his cottage that morning, washing at the basin and turning over what he saw the night before.
|
|
252
255
|
Correct Response:
|
|
@@ -391,7 +394,8 @@ Correct Response:
|
|
|
391
394
|
|
|
392
395
|
|
|
393
396
|
### Example 12: No character available to respond — auto-PASS to Narrator
|
|
394
|
-
Current
|
|
397
|
+
Current time: 23:50 (24-hour clock)
|
|
398
|
+
Current Situation: Jessica is alone in the small side room at Balmore, having just settled in for the night
|
|
395
399
|
Suppose Jessica's inventory is:
|
|
396
400
|
## Items
|
|
397
401
|
- Wool blanket
|
|
@@ -418,3 +422,19 @@ Correct Response:
|
|
|
418
422
|
- Jessica stays in `targets` because she's physically present in the scene (and could be woken later), but she is NOT the responder `name`.
|
|
419
423
|
- "Asleep" is already in her conditions; no inventory update needed.
|
|
420
424
|
|
|
425
|
+
### Example 13: Character has an expectation of privacy
|
|
426
|
+
Current time: 20:30 (24-hour clock)
|
|
427
|
+
Current Situation: Mike is alone in the bathroom getting ready to go out
|
|
428
|
+
Recent Message Sender: Narrator
|
|
429
|
+
Recent Message: Mike borrows Ralph's toothbrush and brushes his teeth because he can't find his own.
|
|
430
|
+
Correct Response:
|
|
431
|
+
{
|
|
432
|
+
"action": "relay",
|
|
433
|
+
"content": "relay",
|
|
434
|
+
"name": "Mike",
|
|
435
|
+
"targets": ["Mike"],
|
|
436
|
+
"update_portrait": [],
|
|
437
|
+
"update_inventory": []
|
|
438
|
+
}
|
|
439
|
+
- Mike is alone and no other character should be able to know that he borrowed Ralph's toothbrush.
|
|
440
|
+
- targets is set to ["Mike"] because Mike is the only character present in the scene.
|
|
@@ -250,7 +250,6 @@ let AnthropicAiService = class AnthropicAiService extends base_ai_service_1.Base
|
|
|
250
250
|
this.debugLogResponse(agent.agentName, responseText);
|
|
251
251
|
if (jsonSchema) {
|
|
252
252
|
responseText = this.trimToJson(responseText);
|
|
253
|
-
responseText = this.sanitizeJsonString(responseText);
|
|
254
253
|
}
|
|
255
254
|
if (response.usage) {
|
|
256
255
|
this.computeMessageCost(agent, response.usage);
|
|
@@ -258,7 +257,7 @@ let AnthropicAiService = class AnthropicAiService extends base_ai_service_1.Base
|
|
|
258
257
|
let parsedResponse;
|
|
259
258
|
if (jsonSchema) {
|
|
260
259
|
try {
|
|
261
|
-
parsedResponse =
|
|
260
|
+
parsedResponse = this.parseStructuredResponse(responseText);
|
|
262
261
|
if (saveResponse) {
|
|
263
262
|
agent.addToConversationHistory(prompt, false);
|
|
264
263
|
agent.addToConversationHistory(responseText, true);
|
|
@@ -44,5 +44,5 @@ export declare class BaseAiService {
|
|
|
44
44
|
protected debugLogResponse(agentName: string, response: string): void;
|
|
45
45
|
trimResponseText(str: string): string;
|
|
46
46
|
trimToJson(str: string): string;
|
|
47
|
-
|
|
47
|
+
parseStructuredResponse(text: string): any;
|
|
48
48
|
}
|
|
@@ -51,6 +51,7 @@ const fs = __importStar(require("fs"));
|
|
|
51
51
|
const handlebars_1 = require("handlebars");
|
|
52
52
|
const errors_1 = require("../../common/errors");
|
|
53
53
|
const logger_1 = require("../../common/logger");
|
|
54
|
+
const jsonrepair_1 = require("jsonrepair");
|
|
54
55
|
const model_prices_1 = require("../model_prices");
|
|
55
56
|
const ai_debug_logger_1 = require("../ai-debug-logger");
|
|
56
57
|
let BaseAiService = class BaseAiService {
|
|
@@ -381,51 +382,21 @@ let BaseAiService = class BaseAiService {
|
|
|
381
382
|
}
|
|
382
383
|
return str;
|
|
383
384
|
}
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
}
|
|
394
|
-
else {
|
|
395
|
-
result += char;
|
|
396
|
-
}
|
|
397
|
-
escapeNext = false;
|
|
398
|
-
continue;
|
|
399
|
-
}
|
|
400
|
-
if (char === '\\') {
|
|
401
|
-
result += char;
|
|
402
|
-
escapeNext = true;
|
|
403
|
-
continue;
|
|
404
|
-
}
|
|
405
|
-
if (char === '"') {
|
|
406
|
-
inString = !inString;
|
|
407
|
-
result += char;
|
|
408
|
-
continue;
|
|
409
|
-
}
|
|
410
|
-
if (inString) {
|
|
411
|
-
if (char === '\n') {
|
|
412
|
-
result += '\\n';
|
|
413
|
-
}
|
|
414
|
-
else if (char === '\r') {
|
|
415
|
-
result += '\\r';
|
|
416
|
-
}
|
|
417
|
-
else if (char === '\t') {
|
|
418
|
-
result += '\\t';
|
|
419
|
-
}
|
|
420
|
-
else {
|
|
421
|
-
result += char;
|
|
422
|
-
}
|
|
385
|
+
parseStructuredResponse(text) {
|
|
386
|
+
try {
|
|
387
|
+
return JSON.parse(text);
|
|
388
|
+
}
|
|
389
|
+
catch (firstError) {
|
|
390
|
+
try {
|
|
391
|
+
const repaired = (0, jsonrepair_1.jsonrepair)(text);
|
|
392
|
+
logger_1.logger.warn('Structured response was not valid JSON; recovered via jsonrepair');
|
|
393
|
+
return JSON.parse(repaired);
|
|
423
394
|
}
|
|
424
|
-
|
|
425
|
-
|
|
395
|
+
catch {
|
|
396
|
+
logger_1.logger.error('Failed to parse structured response even after repair');
|
|
397
|
+
throw firstError;
|
|
426
398
|
}
|
|
427
399
|
}
|
|
428
|
-
return result;
|
|
429
400
|
}
|
|
430
401
|
};
|
|
431
402
|
exports.BaseAiService = BaseAiService;
|