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.
Files changed (118) hide show
  1. package/README.md +55 -6
  2. package/data/common/config/image_models.json +160 -97
  3. package/data/common/config/markup +1 -1
  4. package/data/common/config/story_models.json +15 -3
  5. package/data/common/config/story_models_full.json +2 -2
  6. package/data/common/prompts/character/create_user_character.prompt +3 -12
  7. package/data/common/prompts/character/introduce_character.json +18 -0
  8. package/data/common/prompts/character/introduce_character.mock +4 -0
  9. package/data/common/prompts/character/introduce_character.prompt +58 -0
  10. package/data/common/prompts/character/perceive.prompt +3 -0
  11. package/data/common/prompts/character/progress_character.json +8 -4
  12. package/data/common/prompts/character/progress_character.mock +1 -0
  13. package/data/common/prompts/character/progress_character.prompt +20 -2
  14. package/data/common/prompts/character/update_portrait.json +18 -0
  15. package/data/common/prompts/character/update_portrait.mock +4 -0
  16. package/data/common/prompts/character/update_portrait.prompt +17 -1
  17. package/data/common/prompts/narrator/create_simple_plot.json +0 -0
  18. package/data/common/prompts/narrator/create_simple_plot.mock +13 -0
  19. package/data/common/prompts/narrator/create_simple_plot.prompt +35 -0
  20. package/data/common/prompts/narrator/perceive.prompt +12 -9
  21. package/data/common/prompts/narrator/progress_simple_plot.json +0 -0
  22. package/data/common/prompts/narrator/progress_simple_plot.mock +13 -0
  23. package/data/common/prompts/narrator/progress_simple_plot.prompt +40 -0
  24. package/data/common/prompts/perceive.json +1 -1
  25. package/data/common/prompts/perceive.prompt +82 -20
  26. package/data/common/prompts/story_moderator/moderate.json +1 -1
  27. package/data/common/prompts/story_moderator/moderate.prompt +26 -6
  28. package/dist-sdk/server/src/ai/LLM/anthropic.service.js +1 -2
  29. package/dist-sdk/server/src/ai/LLM/base-ai.service.d.ts +1 -1
  30. package/dist-sdk/server/src/ai/LLM/base-ai.service.js +13 -42
  31. package/dist-sdk/server/src/ai/LLM/deepseek.service.js +9 -0
  32. package/dist-sdk/server/src/ai/LLM/fal.service.js +1 -2
  33. package/dist-sdk/server/src/ai/LLM/googleai.service.js +1 -2
  34. package/dist-sdk/server/src/ai/LLM/grok.service.js +1 -2
  35. package/dist-sdk/server/src/ai/LLM/openai.service.js +1 -2
  36. package/dist-sdk/server/src/ai/LLM/together.service.js +1 -2
  37. package/dist-sdk/server/src/ai/agent-config.d.ts +2 -0
  38. package/dist-sdk/server/src/ai/agent-store.service.js +8 -0
  39. package/dist-sdk/server/src/ai/agent.d.ts +2 -0
  40. package/dist-sdk/server/src/ai/agent.js +2 -0
  41. package/dist-sdk/server/src/ai/model_prices.js +2 -1
  42. package/dist-sdk/server/src/app/user-service-factory.js +7 -3
  43. package/dist-sdk/server/src/app.controller.d.ts +15 -4
  44. package/dist-sdk/server/src/app.controller.js +171 -5
  45. package/dist-sdk/server/src/app.service.d.ts +19 -5
  46. package/dist-sdk/server/src/app.service.js +50 -4
  47. package/dist-sdk/server/src/room/message.js +5 -1
  48. package/dist-sdk/server/src/room/room-factory.d.ts +5 -1
  49. package/dist-sdk/server/src/room/room-factory.js +6 -1
  50. package/dist-sdk/server/src/room/room-store.service.d.ts +5 -1
  51. package/dist-sdk/server/src/room/room-store.service.js +13 -2
  52. package/dist-sdk/server/src/room/room.d.ts +25 -4
  53. package/dist-sdk/server/src/room/room.js +379 -95
  54. package/dist-sdk/server/src/sdk/index.d.ts +1 -1
  55. package/dist-sdk/server/src/story/story.service.d.ts +5 -4
  56. package/dist-sdk/server/src/story/story.service.js +207 -120
  57. package/dist-sdk/server/src/tools/tool-execution.service.d.ts +19 -0
  58. package/dist-sdk/server/src/tools/tool-execution.service.js +100 -0
  59. package/dist-sdk/server/src/tools/tool-store.service.d.ts +17 -0
  60. package/dist-sdk/server/src/tools/tool-store.service.js +143 -0
  61. package/dist-sdk/shared/types/app.types.d.ts +44 -5
  62. package/dist-sdk/shared/types/app.types.js +3 -0
  63. package/docs/assets/hierarchy.js +1 -1
  64. package/docs/assets/highlight.css +0 -7
  65. package/docs/assets/navigation.js +1 -1
  66. package/docs/assets/search.js +1 -1
  67. package/docs/classes/Agent.html +22 -14
  68. package/docs/classes/Briyah.html +10 -10
  69. package/docs/classes/BriyahConfigService.html +5 -5
  70. package/docs/classes/Room.html +32 -26
  71. package/docs/classes/RoomMessage.html +10 -10
  72. package/docs/enums/MessageAction.html +6 -3
  73. package/docs/hierarchy.html +1 -1
  74. package/docs/index.html +12 -5
  75. package/docs/interfaces/AgentInfo.html +3 -2
  76. package/docs/interfaces/AgentMessagesResponse.html +2 -2
  77. package/docs/interfaces/AppService.html +184 -149
  78. package/docs/interfaces/Artifact.html +3 -3
  79. package/docs/interfaces/ArtifactMetadata.html +2 -2
  80. package/docs/interfaces/AttachDocumentResponse.html +2 -2
  81. package/docs/interfaces/BriyahConfigOptions.html +7 -7
  82. package/docs/interfaces/ChapterInfo.html +2 -2
  83. package/docs/interfaces/Character.html +2 -2
  84. package/docs/interfaces/CreateAgentResponse.html +2 -2
  85. package/docs/interfaces/CreateRoomResponse.html +2 -2
  86. package/docs/interfaces/CreateStoryResponse.html +2 -2
  87. package/docs/interfaces/FileList.html +2 -2
  88. package/docs/interfaces/FileMetadata.html +3 -3
  89. package/docs/interfaces/IConfigService.html +3 -3
  90. package/docs/interfaces/LoggingOptions.html +6 -6
  91. package/docs/interfaces/Message.html +2 -2
  92. package/docs/interfaces/ModelInfo.html +2 -3
  93. package/docs/interfaces/PreparedPromptResponse.html +2 -2
  94. package/docs/interfaces/ProcessTextResponse.html +2 -2
  95. package/docs/interfaces/PromptFile.html +2 -2
  96. package/docs/interfaces/PromptFileContent.html +2 -2
  97. package/docs/interfaces/PromptFilesResponse.html +2 -2
  98. package/docs/interfaces/PromptFolder.html +2 -2
  99. package/docs/interfaces/PromptFoldersResponse.html +2 -2
  100. package/docs/interfaces/RoomDetails.html +2 -2
  101. package/docs/interfaces/RoomInfo.html +2 -2
  102. package/docs/interfaces/RoomMessagesResponse.html +2 -2
  103. package/docs/interfaces/StoryErrorEvent.html +3 -3
  104. package/docs/interfaces/StoryIdea.html +2 -2
  105. package/docs/interfaces/StoryInfo.html +5 -4
  106. package/docs/interfaces/StoryIntroduceCharacterEvent.html +3 -3
  107. package/docs/interfaces/StoryProgressChapterEvent.html +3 -3
  108. package/docs/interfaces/StoryState.html +5 -5
  109. package/docs/interfaces/StoryStateEvent.html +3 -3
  110. package/docs/interfaces/ToolDefinition.html +6 -0
  111. package/docs/interfaces/ToolParameter.html +5 -0
  112. package/docs/interfaces/ToolsResponse.html +2 -0
  113. package/docs/interfaces/Transaction.html +2 -2
  114. package/docs/interfaces/TransactionHistoryResponse.html +2 -2
  115. package/docs/modules.html +1 -1
  116. package/docs/types/PromptScope.html +1 -1
  117. package/docs/types/ToolRunResult.html +1 -0
  118. package/package.json +2 -1
package/README.md CHANGED
@@ -5,7 +5,8 @@ Briyah is an SDK for AI agents, multi-agent rooms, and interactive stories. It w
5
5
  What's in the package:
6
6
 
7
7
  - **Agents.** AI agents with a system prompt, persistent conversation history, attached documents, and per-call cost and token tracking. Histories can be summarized/compacted or cleared.
8
- - **Rooms.** Multi-agent conversations with a shared goal. Agents exchange messages at different visibility levels (speak, whisper, think, shout), draft and approve shared artifacts, and a moderator can route turns.
8
+ - **Rooms.** Multi-agent conversations with a shared goal. Agents exchange messages at different visibility levels (speak, whisper, think, shout), publish shared artifacts, run tools, commission each other for parallel research, and a moderator can route turns.
9
+ - **Tools.** User-defined functions agents can call from a room. A tool is a named async JavaScript function body with declared parameters that returns a JSON value; `helpers.fetch` is available for HTTP requests. Tools are granted per agent, and an agent may chain several tool calls privately before responding. Tool code runs in-process on the server with a timeout — only define tools you trust.
9
10
  - **Stories.** Text-based interactive fiction with a narrator, AI-played characters, and a human player. Stories progress through chapters and can introduce new characters mid-game. Story events (state updates, character suggestions, chapter transitions, errors) are delivered through an emitter the host app subscribes to.
10
11
  - **Text processing.** One-shot `processText` for non-conversational use, with cost and token counts on the result.
11
12
  - **File attachments.** Attach documents to agents as context. Supported file types vary by LLM provider.
@@ -227,6 +228,13 @@ const room = await appService.createRoom(name, goal, agentIds);
227
228
  const rooms = await appService.listRooms();
228
229
  await appService.sendRoomMessage(roomId, content, sender, action?);
229
230
 
231
+ // Tool Management
232
+ const tools = await appService.listTools();
233
+ const tool = await appService.createTool({ name, description, parameters, code, timeoutMs? });
234
+ await appService.updateTool(name, tool);
235
+ await appService.deleteTool(name);
236
+ const result = await appService.testTool(name, args); // { ok: true, result } | { ok: false, error }
237
+
230
238
  // Story Management
231
239
  const story = await appService.createStory(name, idea, userCharacterDesc, otherCharactersDesc, storyModel?);
232
240
  await appService.progressStory(storyId);
@@ -477,6 +485,46 @@ emitter.on('update', (newBalance: number) => {
477
485
  });
478
486
  ```
479
487
 
488
+ ### Example 8: Giving Agents Tools
489
+
490
+ Tools let a room agent fetch or compute data mid-conversation. Define the tool once, grant it to specific agents, and the agent invokes it on its own (via the EXECUTE room action) when a conversation calls for it. The result is returned privately to the calling agent, which may chain several calls before speaking.
491
+
492
+ ```typescript
493
+ const app = briyah.getAppService('user-123');
494
+
495
+ // 1. Define a tool. `code` is the body of an async function receiving
496
+ // (args, helpers) and returning a JSON-serializable value.
497
+ await app.createTool({
498
+ name: 'weather_lookup',
499
+ description: 'Gets the current temperature for a city',
500
+ parameters: [
501
+ { name: 'city', type: 'string', description: 'City name', required: true }
502
+ ],
503
+ code: `
504
+ const res = await helpers.fetch('https://wttr.in/' + encodeURIComponent(args.city) + '?format=j1');
505
+ const data = await res.json();
506
+ return { tempC: data.current_condition[0].temp_C };
507
+ `,
508
+ timeoutMs: 15000 // optional; default 30s, max 120s
509
+ });
510
+
511
+ // 2. Test it before any agent uses it
512
+ const test = await app.testTool('weather_lookup', { city: 'Paris' });
513
+ if (!test.ok) throw new Error(test.error);
514
+
515
+ // 3. Grant it to an agent (grants are enforced server-side)
516
+ const researcher = app.createAgent('Anthropic', 'Researcher', 'Researcher',
517
+ 'A researcher who uses tools for exact answers', 'claude-haiku-4-5');
518
+ researcher.toolNames = ['weather_lookup'];
519
+ researcher.save();
520
+
521
+ // 4. In a room, the agent calls the tool on its own when a question needs it.
522
+ // Other agents wait while it researches; a log-only 'tool' message records
523
+ // each call (visible when fetching messages with includeThoughts=true).
524
+ ```
525
+
526
+ Agents can also delegate: an agent may respond with a `commission` action naming other agents, each of which researches independently (using its own tools) and replies with a `deliver`. The commissioner receives all deliverables at once and responds before the conversation continues. No SDK calls are needed for this — it is driven by the agents themselves.
527
+
480
528
  ## Data Storage
481
529
 
482
530
  Briyah stores data in the following structure:
@@ -489,13 +537,14 @@ Briyah stores data in the following structure:
489
537
  │ └── published-agents.json # Published agent mappings
490
538
  └── user/
491
539
  └── {userId}/ # Per-user data
540
+ ├── agents/ # Agent configs and histories (one JSON per agent)
541
+ ├── rooms/ # Room metadata, message logs, artifacts (one folder per room)
542
+ ├── stories/ # Story state
543
+ ├── tools/ # User-defined tools (one JSON per tool)
492
544
  ├── prompts/ # User-specific prompts
493
545
  ├── upload/ # User file attachments
494
- └── userconfig/ # User configuration files
495
- ├── agents.json # User's agents
496
- ├── rooms.json # User's rooms
497
- ├── stories.json # User's stories
498
- └── balance.json # User's balance
546
+ ├── transactions/ # Transaction records
547
+ └── userconfig/ # User preferences and balance
499
548
  ```
500
549
 
501
550
  ## Multi-Instance Support
@@ -1,141 +1,204 @@
1
1
  [
2
- {
3
- "name": "FLUX.1 Kontext (edit)",
4
- "description": "Image-to-image editing; maintains character consistency",
5
- "type": "image-to-image",
6
- "service": "FalAI",
7
- "model": "fal-ai/flux-pro/kontext/multi",
8
- "centsPerImage": 4,
9
- "imageProperties": {
10
- "aspect_ratio": "1:1",
11
- "safety_tolerance": "2",
12
- "num_images": 1,
13
- "output_format": "png"
14
- }
15
- },
16
2
  {
17
3
  "name": "FLUX.1 Kontext",
18
- "description": "",
19
- "type": "text-to-image",
20
- "service": "FalAI",
21
- "model": "fal-ai/flux-pro/kontext/text-to-image",
22
- "centsPerImage": 4,
23
- "imageProperties": {
24
- "aspect_ratio": "1:1",
25
- "safety_tolerance": "2",
26
- "num_images": 1,
27
- "output_format": "png"
4
+ "description": "Maintains character consistency across scenes",
5
+ "generation": {
6
+ "service": "FalAI",
7
+ "model": "fal-ai/flux-pro/kontext/text-to-image",
8
+ "centsPerImage": 4,
9
+ "imageProperties": {
10
+ "aspect_ratio": "1:1",
11
+ "safety_tolerance": "2",
12
+ "num_images": 1,
13
+ "output_format": "png"
14
+ }
15
+ },
16
+ "editing": {
17
+ "service": "FalAI",
18
+ "model": "fal-ai/flux-pro/kontext/multi",
19
+ "centsPerImage": 4,
20
+ "imageProperties": {
21
+ "aspect_ratio": "1:1",
22
+ "safety_tolerance": "2",
23
+ "num_images": 1,
24
+ "output_format": "png"
25
+ }
28
26
  }
29
27
  },
30
28
  {
31
29
  "name": "GPT Image 1.5",
32
30
  "description": "High quality; consistent characters across scenes",
33
- "type": "text-to-image",
34
- "service": "OpenAI",
35
- "model": "gpt-image-1.5",
36
- "centsPerImage": 21,
37
- "imageProperties": {
38
- "size": "1024x1024",
39
- "quality": "auto",
40
- "moderation": "low"
41
- }
42
- },
43
- {
44
- "name": "GPT Image 1.5 (edit)",
45
- "description": "High quality image editing with reference images",
46
- "type": "image-to-image",
47
- "service": "OpenAI",
48
- "model": "gpt-image-1.5",
49
- "centsPerImage": 21,
50
- "imageProperties": {
51
- "size": "1024x1024"
31
+ "generation": {
32
+ "service": "OpenAI",
33
+ "model": "gpt-image-1.5",
34
+ "centsPerImage": 21,
35
+ "imageProperties": {
36
+ "size": "1024x1024",
37
+ "quality": "auto",
38
+ "moderation": "low"
39
+ }
40
+ },
41
+ "editing": {
42
+ "service": "OpenAI",
43
+ "model": "gpt-image-1.5",
44
+ "centsPerImage": 21,
45
+ "imageProperties": {
46
+ "size": "1024x1024"
47
+ }
52
48
  }
53
49
  },
54
50
  {
55
51
  "name": "GPT Image 1 Mini",
56
52
  "description": "Mediocre quality; some character consistency",
57
- "type": "text-to-image",
58
- "service": "OpenAI",
59
- "model": "gpt-image-1-mini",
60
- "centsPerImage": 10,
61
- "imageProperties": {
62
- "size": "1024x1024",
63
- "quality": "auto",
64
- "moderation": "low"
53
+ "generation": {
54
+ "service": "OpenAI",
55
+ "model": "gpt-image-1-mini",
56
+ "centsPerImage": 10,
57
+ "imageProperties": {
58
+ "size": "1024x1024",
59
+ "quality": "auto",
60
+ "moderation": "low"
61
+ }
62
+ },
63
+ "editing": {
64
+ "service": "OpenAI",
65
+ "model": "gpt-image-1-mini",
66
+ "centsPerImage": 10,
67
+ "imageProperties": {
68
+ "size": "1024x1024"
69
+ }
65
70
  }
66
71
  },
67
72
  {
68
73
  "name": "FLUX.2 MAX",
69
74
  "description": "Cheap",
70
- "type": "text-to-image",
71
- "service": "TogetherAI",
72
- "model": "black-forest-labs/FLUX.2-max",
73
- "centsPerImage": 4,
74
- "imageProperties": {
75
- "width": 1024,
76
- "height": 1024,
77
- "disable_safety_checker": false,
78
- "response_format": "base64"
75
+ "generation": {
76
+ "service": "TogetherAI",
77
+ "model": "black-forest-labs/FLUX.2-max",
78
+ "centsPerImage": 4,
79
+ "imageProperties": {
80
+ "width": 1024,
81
+ "height": 1024,
82
+ "disable_safety_checker": false,
83
+ "response_format": "base64"
84
+ }
85
+ },
86
+ "editing": {
87
+ "service": "TogetherAI",
88
+ "model": "black-forest-labs/FLUX.2-max",
89
+ "centsPerImage": 4,
90
+ "imageProperties": {
91
+ "width": 1024,
92
+ "height": 1024,
93
+ "disable_safety_checker": false,
94
+ "response_format": "base64"
95
+ }
79
96
  }
80
97
  },
81
98
  {
82
99
  "name": "Stable Diffusion 3",
83
100
  "description": "Laughably poor quality",
84
- "type": "text-to-image",
85
- "service": "TogetherAI",
86
- "model": "stabilityai/stable-diffusion-3-medium",
87
- "centsPerImage": 4,
88
- "imageProperties": {
89
- "width": 1024,
90
- "height": 1024,
91
- "disable_safety_checker": false,
92
- "response_format": "base64"
101
+ "generation": {
102
+ "service": "TogetherAI",
103
+ "model": "stabilityai/stable-diffusion-3-medium",
104
+ "centsPerImage": 4,
105
+ "imageProperties": {
106
+ "width": 1024,
107
+ "height": 1024,
108
+ "disable_safety_checker": false,
109
+ "response_format": "base64"
110
+ }
111
+ },
112
+ "editing": {
113
+ "service": "FalAI",
114
+ "model": "fal-ai/flux-pro/kontext/multi",
115
+ "centsPerImage": 4,
116
+ "imageProperties": {
117
+ "aspect_ratio": "1:1",
118
+ "safety_tolerance": "2",
119
+ "num_images": 1,
120
+ "output_format": "png"
121
+ }
93
122
  }
94
123
  },
95
124
  {
96
125
  "name": "Google Imagen 4",
97
126
  "description": "No character consistency",
98
- "type": "text-to-image",
99
- "service": "GoogleAI",
100
- "model": "imagen-4.0-generate-001",
101
- "centsPerImage": 4,
102
- "imageProperties": {
103
- "numberOfImages": 1,
104
- "aspectRatio": "1:1"
127
+ "generation": {
128
+ "service": "GoogleAI",
129
+ "model": "imagen-4.0-generate-001",
130
+ "centsPerImage": 4,
131
+ "imageProperties": {
132
+ "numberOfImages": 1,
133
+ "aspectRatio": "1:1"
134
+ }
135
+ },
136
+ "editing": {
137
+ "service": "FalAI",
138
+ "model": "fal-ai/flux-pro/kontext/multi",
139
+ "centsPerImage": 4,
140
+ "imageProperties": {
141
+ "aspect_ratio": "1:1",
142
+ "safety_tolerance": "2",
143
+ "num_images": 1,
144
+ "output_format": "png"
145
+ }
105
146
  }
106
147
  },
107
148
  {
108
149
  "name": "Nano Banana Pro",
109
150
  "description": "",
110
- "type": "text-to-image",
111
- "service": "FalAI",
112
- "model": "fal-ai/nano-banana-pro",
113
- "centsPerImage": 15,
114
- "imageProperties": {
115
- "image_size": { "width": 1024, "height": 1024 },
116
- "safety_tolerance": "2",
117
- "num_images": 1,
118
- "output_format": "png"
151
+ "generation": {
152
+ "service": "FalAI",
153
+ "model": "fal-ai/nano-banana-pro",
154
+ "centsPerImage": 15,
155
+ "imageProperties": {
156
+ "image_size": { "width": 1024, "height": 1024 },
157
+ "safety_tolerance": "2",
158
+ "num_images": 1,
159
+ "output_format": "png"
160
+ }
161
+ },
162
+ "editing": {
163
+ "service": "FalAI",
164
+ "model": "fal-ai/nano-banana-pro",
165
+ "centsPerImage": 15,
166
+ "imageProperties": {
167
+ "image_size": { "width": 1024, "height": 1024 },
168
+ "safety_tolerance": "2",
169
+ "num_images": 1,
170
+ "output_format": "png"
171
+ }
119
172
  }
120
173
  },
121
174
  {
122
175
  "name": "Nano Banana",
123
176
  "description": "",
124
- "type": "text-to-image",
125
- "service": "FalAI",
126
- "model": "fal-ai/nano-banana",
127
- "centsPerImage": 4,
128
- "imageProperties": {
129
- "image_size": { "width": 1024, "height": 1024 },
130
- "safety_tolerance": "2",
131
- "num_images": 1,
132
- "output_format": "png"
177
+ "generation": {
178
+ "service": "FalAI",
179
+ "model": "fal-ai/nano-banana",
180
+ "centsPerImage": 4,
181
+ "imageProperties": {
182
+ "image_size": { "width": 1024, "height": 1024 },
183
+ "safety_tolerance": "2",
184
+ "num_images": 1,
185
+ "output_format": "png"
186
+ }
187
+ },
188
+ "editing": {
189
+ "service": "FalAI",
190
+ "model": "fal-ai/nano-banana",
191
+ "centsPerImage": 4,
192
+ "imageProperties": {
193
+ "image_size": { "width": 1024, "height": 1024 },
194
+ "safety_tolerance": "2",
195
+ "num_images": 1,
196
+ "output_format": "png"
197
+ }
133
198
  }
134
199
  },
135
200
  {
136
201
  "name": "No images",
137
- "description": "Disable image generation (no real API calls)",
138
- "service": "",
139
- "model": ""
202
+ "description": "Disable image generation (no real API calls)"
140
203
  }
141
204
  ]
@@ -1 +1 @@
1
- 12.990938720000031
1
+ 13.132693000000032
@@ -5,6 +5,8 @@
5
5
  "service": "Anthropic",
6
6
  "model": "claude-sonnet-4-6",
7
7
  "small_model": "claude-haiku-4-5",
8
+ "moderator_service": "Anthropic",
9
+ "moderator_model": "claude-haiku-4-5",
8
10
  "cost": "300"
9
11
  },
10
12
  {
@@ -13,6 +15,8 @@
13
15
  "service": "Anthropic",
14
16
  "model": "claude-haiku-4-5",
15
17
  "small_model": "claude-haiku-4-5",
18
+ "moderator_service": "Anthropic",
19
+ "moderator_model": "claude-haiku-4-5",
16
20
  "cost": "80"
17
21
  },
18
22
  {
@@ -21,6 +25,8 @@
21
25
  "service": "Anthropic",
22
26
  "model": "claude-opus-4-8",
23
27
  "small_model": "claude-haiku-4-5",
28
+ "moderator_service": "Anthropic",
29
+ "moderator_model": "claude-haiku-4-5",
24
30
  "cost": "1500"
25
31
  },
26
32
  {
@@ -29,13 +35,17 @@
29
35
  "service": "Anthropic",
30
36
  "model": "claude-fable-5",
31
37
  "small_model": "claude-haiku-4-5",
38
+ "moderator_service": "Anthropic",
39
+ "moderator_model": "claude-haiku-4-5",
32
40
  "cost": "3000"
33
41
  },
34
42
  {
35
- "name": "Grok 4.20",
43
+ "name": "Grok 4.3",
36
44
  "description": "",
37
45
  "service": "Grok",
38
- "model": "grok-4.20-0309-reasoning",
46
+ "model": "grok-4.3",
47
+ "moderator_service": "Grok",
48
+ "moderator_model": "grok-4.3",
39
49
  "cost": "300"
40
50
  },
41
51
  {
@@ -44,6 +54,8 @@
44
54
  "service": "DeepSeek",
45
55
  "model": "deepseek-v4-pro",
46
56
  "small_model": "deepseek-v4-flash",
57
+ "moderator_service": "DeepSeek",
58
+ "moderator_model": "deepseek-v4-flash",
47
59
  "cost": "3"
48
60
  }
49
- ]
61
+ ]
@@ -46,10 +46,10 @@
46
46
  "cost": "60"
47
47
  },
48
48
  {
49
- "name": "Grok 4.20",
49
+ "name": "Grok 4.3",
50
50
  "description": "",
51
51
  "service": "Grok",
52
- "model": "grok-4.20-0309-reasoning",
52
+ "model": "grok-4.3",
53
53
  "cost": "300"
54
54
  },
55
55
  {
@@ -22,23 +22,15 @@ Create a detailed character profile that includes:
22
22
 
23
23
  2. **Backstory**: A rich history that explains how they became who they are today. Include key life events, relationships, and experiences that shaped them.
24
24
 
25
- 3. **Personality**: Core traits, temperament, values, beliefs, and how they typically interact with others. What makes them unique?
25
+ 3. **Special Abilities**: Any special abilities or powers that differentiate them from other characters in the story.
26
26
 
27
- 4. **Motivations**: What drives them? What are their goals, desires, fears, and needs?
27
+ 4. **Strengths**: Skills, talents, positive qualities, and what they excel at.
28
28
 
29
- 5. **Special Abilities**: Any special abilities or powers that differentiate them from other characters in the story.
30
-
31
- 6. **Strengths**: Skills, talents, positive qualities, and what they excel at.
32
-
33
- 7. **Weaknesses**: Flaws, vulnerabilities, limitations, and areas where they struggle.
34
-
35
- 8. **Relationships**: How they relate to other characters in the story (if applicable based on the scenario).
29
+ 5. **Relationships**: How they relate to other characters in the story (if applicable based on the scenario).
36
30
 
37
31
  **Important Guidelines:**
38
32
  - Make the character interesting, complex, and memorable
39
33
  - Ensure the character fits naturally within the story's setting and tone
40
- - Give the character internal conflicts and contradictions that make them feel human
41
- - Consider how the character's background influences their current behavior
42
34
  - Make sure the profile is consistent with the description provided above
43
35
  - Leave room for the player to make choices and shape the character's development
44
36
 
@@ -68,4 +60,3 @@ Example format:
68
60
  }
69
61
  }
70
62
  ```
71
- Note: Do NOT use double-quotes anywhere in the description, character_profile, or inventory; use single-quotes instead.
@@ -0,0 +1,18 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "name": "introduce_character_response",
4
+ "description": "Response schema for creating a brief profile for a character introduced mid-story",
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": "A short markdown-formatted character profile covering the character's role in the story, what they realistically know, and a brief personality description"
14
+ }
15
+ },
16
+ "required": ["description", "character_profile"],
17
+ "additionalProperties": false
18
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "description": "A friendly newcomer with an unassuming appearance",
3
+ "character_profile": "**Name:** New Character\n\n**Role in the Story:** A local who has just crossed paths with the main characters.\n\n**What They Know:** Only what they have personally seen in their daily routine; they know nothing of the party's secrets.\n\n**Personality:** Curious and talkative, with a plainspoken manner."
4
+ }
@@ -0,0 +1,58 @@
1
+ # Introduce New Character
2
+ You are creating a brief character profile for {{agentName}}, a character who has just been introduced into an ongoing story.
3
+
4
+ ## Recent Story Events
5
+ {{#if formattedHistory}}
6
+ {{#each formattedHistory}}
7
+ {{this}}
8
+ {{/each}}
9
+ {{else}}
10
+ Refer to the conversation history above for recent events.
11
+ {{/if}}
12
+
13
+ ## Plot Plan (narrator's eyes only — do not reveal to others)
14
+ {{plotPlan}}
15
+
16
+ ## Other Characters in the Story (name and visible description)
17
+ {{#if otherCharacters}}
18
+ {{#each otherCharacters}}
19
+ - **{{name}}**: {{description}}
20
+ {{/each}}
21
+ {{else}}
22
+ (No other characters yet.)
23
+ {{/if}}
24
+
25
+ ## Your task
26
+ Create a SHORT and SIMPLE character profile for {{agentName}}. This is a quick introduction, not a full character study. The profile must cover only:
27
+
28
+ 1. **Name**: The character's name ({{agentName}})
29
+
30
+ 2. **Role in the Story**: Where this character fits into the story. How are they connected to the setting, the other characters, and the events in the plot plan?
31
+
32
+ 3. **What They Know**: What this character would *realistically* know about the story so far. Only include events they could plausibly have witnessed, been told about, or learned through their position in the story world.
33
+ **NOTE:** Do *not* mention information the character should *not* know about. For example, don't say 'Jessica doesn't know about the envelope under the seat'. That just gives it away to the new character.
34
+
35
+ 4. **What They Have Experienced**: This character knows nothing about the events of the story other than what you reveal to them here. So, give them details about the most recent interaction or dialog that led to them being introduced into the story.
36
+
37
+ 5. **Who They Are With**: Using the recent story events, work out which other characters {{agentName}} is currently in contact with (in the same scene / interacting with them). For each such character, describe their *visible, observable appearance* drawn from the "Other Characters in the Story" list above — what {{agentName}} can plainly see. {{agentName}} perceives these people by their appearance, NOT by name or backstory: only refer to a character by name if {{agentName}} would realistically already know it (e.g. they were introduced by name in the recent events). Otherwise describe them observably (for example, 'a woman in her early 30s with olive skin and an athletic build'). Do not include any character who is not present with {{agentName}}, and do not reveal hidden details, names, or backstory the character couldn't observe.
38
+
39
+ 6. **Personality**: A brief description of their temperament, manner, and how they speak.
40
+
41
+ **Important Guidelines:**
42
+ - Stay consistent with how the character has already appeared in the story events above
43
+ - If the plot plan assigns this character a specific role or secret, include only what THIS character would know about it
44
+ - Do *not* say 'He has no knowledge of...' and proceed to list all the things in the story the character shouldn't know.
45
+ - Use your judgment about how detailed this character profile should be given their role in the story
46
+
47
+ ## Response format
48
+ Return a JSON object with these fields:
49
+ - `description`: A brief 1-2 sentence observable description of the character (physical appearance only). Stay consistent with any description already given in the story; otherwise invent something plausible.
50
+ - `character_profile`: The short markdown-formatted character profile covering the sections above.
51
+
52
+ Example format:
53
+ ```json
54
+ {
55
+ "description": "A stocky man in his 50s with a weathered face, gray stubble, and a dockworker's rough hands.",
56
+ "character_profile": "**Name:** {{agentName}}\n\n**Role in the Story:** [Where they fit]\n\n**What They Know:** [Realistic knowledge of story events]\n\n**What They Have Experienced:** [The interaction that brought them in]\n\n**Who They Are With:** [Observable appearance of the characters present with them, named only if they'd know the name]\n\n**Personality:** [Brief temperament and speech style]"
57
+ }
58
+ ```
@@ -22,6 +22,9 @@ Use your character profile to:
22
22
  {{visibleArtifacts}}
23
23
  ```
24
24
 
25
+ ## Your Inventory and Condition
26
+ If a "Your private context (known only to you)" section is included with the current situation, it lists what your character is currently carrying, wearing, or possessing, along with any physical or mental conditions (wounded, exhausted, etc.). Stay consistent with it: only use or reference items you actually have, and let your conditions shape what your character can realistically do.
27
+
25
28
  ## How to Respond
26
29
 
27
30
  You should respond with a string of text that indicates what your character says or does.
@@ -4,19 +4,23 @@
4
4
  "description": "Response schema for updating a character profile as the story progresses",
5
5
  "type": "object",
6
6
  "properties": {
7
+ "no_changes": {
8
+ "type": "boolean",
9
+ "description": "Set true when this character was NOT significantly affected by recent events. When true, omit description, character_profile, and inventory entirely - the existing profile is left unchanged."
10
+ },
7
11
  "description": {
8
12
  "type": "string",
9
- "description": "A brief 1-2 sentence description containing only immediately observable physical characteristics"
13
+ "description": "A brief 1-2 sentence description containing only immediately observable physical characteristics. Omit when no_changes is true."
10
14
  },
11
15
  "character_profile": {
12
16
  "type": "string",
13
- "description": "An updated markdown-formatted character profile reflecting growth and changes from recent story events"
17
+ "description": "An updated markdown-formatted character profile reflecting growth and changes from recent story events. Omit when no_changes is true."
14
18
  },
15
19
  "inventory": {
16
20
  "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."
21
+ "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, had no inventory artifact yet, or no_changes is true."
18
22
  }
19
23
  },
20
- "required": ["character_profile"],
24
+ "required": ["no_changes"],
21
25
  "additionalProperties": false
22
26
  }
@@ -1,4 +1,5 @@
1
1
  {
2
+ "no_changes": false,
2
3
  "character_profile": "## Background\n\nThe character has grown through recent events and interactions.\n\n## Personality\n\n- More confident after recent experiences\n- Developing deeper relationships\n\n## Motivations\n\n- Seeking to understand the unfolding situation\n- Working toward personal goals",
3
4
  "description": "A character who has evolved through the story"
4
5
  }