briyah 1.2.3 → 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/model_prices.json +31 -0
- package/data/common/config/story_models.json +31 -11
- package/data/common/config/story_models_full.json +25 -7
- 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 +6 -4
- 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 +10 -1
- 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 +393 -96
- 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
|
@@ -5,9 +5,9 @@ const app_types_1 = require("../../../shared/types/app.types");
|
|
|
5
5
|
const message_1 = require("./message");
|
|
6
6
|
const crypto_1 = require("crypto");
|
|
7
7
|
const errors_1 = require("../common/errors");
|
|
8
|
-
const child_process_1 = require("child_process");
|
|
9
8
|
const logger_1 = require("../common/logger");
|
|
10
9
|
class Room {
|
|
10
|
+
static MAX_TOOL_ITERATIONS = 5;
|
|
11
11
|
id;
|
|
12
12
|
name;
|
|
13
13
|
goal;
|
|
@@ -28,11 +28,14 @@ class Room {
|
|
|
28
28
|
onStateChangeCallbacks = new Map();
|
|
29
29
|
onError;
|
|
30
30
|
currentSituation = '';
|
|
31
|
+
currentSituationTime = '';
|
|
31
32
|
onSituationUpdate;
|
|
32
33
|
onModeratorResponseCallback;
|
|
33
34
|
templateRoomId;
|
|
34
35
|
storageDir;
|
|
35
36
|
roomStoreService;
|
|
37
|
+
toolStoreService;
|
|
38
|
+
toolExecutionService;
|
|
36
39
|
constructor(id, name, goal, baseRoomDir = '', storageDir = '', roomStoreService = null) {
|
|
37
40
|
this.name = name;
|
|
38
41
|
this.goal = goal;
|
|
@@ -147,7 +150,7 @@ class Room {
|
|
|
147
150
|
getLatestRoomMessages(fromIndex = 0, includeThoughts = false) {
|
|
148
151
|
const messages = this.roomMessages.filter((msg) => msg.index >= fromIndex);
|
|
149
152
|
if (!includeThoughts) {
|
|
150
|
-
return messages.filter((msg) => msg.action !== app_types_1.MessageAction.THINK);
|
|
153
|
+
return messages.filter((msg) => msg.action !== app_types_1.MessageAction.THINK && msg.action !== app_types_1.MessageAction.TOOL);
|
|
151
154
|
}
|
|
152
155
|
return messages;
|
|
153
156
|
}
|
|
@@ -158,12 +161,12 @@ class Room {
|
|
|
158
161
|
});
|
|
159
162
|
this.nextMessageIndex = this.roomMessages.length;
|
|
160
163
|
}
|
|
161
|
-
addRoomMessage(message) {
|
|
164
|
+
addRoomMessage(message, options) {
|
|
162
165
|
message.index = this.nextMessageIndex++;
|
|
163
166
|
this.roomMessages.push(message);
|
|
164
167
|
this.saveMessages([message]);
|
|
165
|
-
if (message.situation) {
|
|
166
|
-
this.handleSituationUpdate(message.situation);
|
|
168
|
+
if (message.situation && !options?.suppressSituationUpdate) {
|
|
169
|
+
void this.handleSituationUpdate(message.situation);
|
|
167
170
|
}
|
|
168
171
|
this.notifyStateChange();
|
|
169
172
|
}
|
|
@@ -233,6 +236,12 @@ class Room {
|
|
|
233
236
|
}
|
|
234
237
|
}
|
|
235
238
|
}
|
|
239
|
+
if (normalizedAction === app_types_1.MessageAction.EXECUTE && (!response.name || !response.name.trim())) {
|
|
240
|
+
needsModeration = true;
|
|
241
|
+
}
|
|
242
|
+
if (normalizedAction === app_types_1.MessageAction.COMMISSION && targets.length === 0) {
|
|
243
|
+
needsModeration = true;
|
|
244
|
+
}
|
|
236
245
|
}
|
|
237
246
|
if (needsModeration) {
|
|
238
247
|
return new message_1.RoomMessage(agent.agentNickname, app_types_1.MessageAction.MODERATE, content, [], null, situation);
|
|
@@ -249,6 +258,10 @@ class Room {
|
|
|
249
258
|
let i = 0;
|
|
250
259
|
while (i < lines.length && lines[i].trim() === '')
|
|
251
260
|
i++;
|
|
261
|
+
const fenceRe = /^\s*```\w*\s*$/;
|
|
262
|
+
const hadLeadingFence = i < lines.length && fenceRe.test(lines[i]);
|
|
263
|
+
if (hadLeadingFence)
|
|
264
|
+
i++;
|
|
252
265
|
const tagLineRe = /^\s*<\w+>[\s\S]*?<\/\w+>\s*$/;
|
|
253
266
|
if (i >= lines.length || !tagLineRe.test(lines[i]))
|
|
254
267
|
return null;
|
|
@@ -261,7 +274,16 @@ class Room {
|
|
|
261
274
|
const preamble = preambleLines.join('\n');
|
|
262
275
|
if (j < lines.length && lines[j].trim() === '')
|
|
263
276
|
j++;
|
|
264
|
-
|
|
277
|
+
let contentLines = lines.slice(j);
|
|
278
|
+
if (hadLeadingFence) {
|
|
279
|
+
let k = contentLines.length - 1;
|
|
280
|
+
while (k >= 0 && contentLines[k].trim() === '')
|
|
281
|
+
k--;
|
|
282
|
+
if (k >= 0 && fenceRe.test(contentLines[k])) {
|
|
283
|
+
contentLines = contentLines.slice(0, k);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
const content = contentLines.join('\n').trimStart();
|
|
265
287
|
return { preamble, content };
|
|
266
288
|
}
|
|
267
289
|
static coerceMessageAction(raw) {
|
|
@@ -271,45 +293,162 @@ class Room {
|
|
|
271
293
|
const values = Object.values(app_types_1.MessageAction);
|
|
272
294
|
return values.includes(lowered) ? lowered : undefined;
|
|
273
295
|
}
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
296
|
+
getPresentCharacters(perceivingAgent, message) {
|
|
297
|
+
const audienceNames = message.getTargets();
|
|
298
|
+
const senderName = message.getSender();
|
|
299
|
+
return this.agents.filter((a) => {
|
|
300
|
+
if (a.promptFolder !== 'character')
|
|
301
|
+
return false;
|
|
302
|
+
if (a.agentNickname === perceivingAgent.agentNickname)
|
|
303
|
+
return false;
|
|
304
|
+
if (this.checkAgentNicknameMatch(a.agentNickname, senderName))
|
|
305
|
+
return true;
|
|
306
|
+
if (audienceNames.some((name) => this.checkAgentNicknameMatch(a.agentNickname, name)))
|
|
307
|
+
return true;
|
|
308
|
+
if (audienceNames.length === 0 && message.canHear(a.agentNickname))
|
|
309
|
+
return true;
|
|
310
|
+
return false;
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
buildCharacterPrivateContextDigest() {
|
|
314
|
+
return this.agents
|
|
315
|
+
.filter((a) => a.promptFolder === 'character' && a.privateContext && a.privateContext.trim())
|
|
316
|
+
.map((a) => `### ${a.agentNickname}\n${a.privateContext}`)
|
|
317
|
+
.join('\n\n');
|
|
318
|
+
}
|
|
319
|
+
async buildAvailableTools(agent) {
|
|
320
|
+
if (!this.toolStoreService || !agent.toolNames || agent.toolNames.length === 0) {
|
|
321
|
+
return [];
|
|
322
|
+
}
|
|
323
|
+
const tools = [];
|
|
324
|
+
for (const name of agent.toolNames) {
|
|
325
|
+
const tool = await this.toolStoreService.getTool(name);
|
|
326
|
+
if (tool) {
|
|
327
|
+
tools.push({
|
|
328
|
+
name: tool.name,
|
|
329
|
+
description: tool.description,
|
|
330
|
+
parameters: tool.parameters || [],
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
return tools;
|
|
335
|
+
}
|
|
336
|
+
async buildPerceiveVariables(agent) {
|
|
337
|
+
const visibleArtifacts = this.getVisibleArtifacts(agent.agentNickname)
|
|
338
|
+
.map((a) => `${a.name} (by ${a.creator}): ${a.body}`)
|
|
339
|
+
.join('\n\n');
|
|
340
|
+
const allArtifacts = this.getArtifacts();
|
|
341
|
+
const invisibleArtifactNames = allArtifacts
|
|
342
|
+
.filter((a) => !this.getVisibleArtifacts(agent.agentNickname).includes(a))
|
|
343
|
+
.map((a) => a.name)
|
|
344
|
+
.join(', ');
|
|
345
|
+
const humanAgent = this.getAgents().find((a) => a.isControlledByHuman);
|
|
346
|
+
const humanCharacterName = humanAgent ? humanAgent.agentNickname : 'Player';
|
|
347
|
+
const maxOutputChars = 4096;
|
|
348
|
+
return {
|
|
349
|
+
agentName: agent.agentName,
|
|
350
|
+
agentNickname: agent.agentNickname,
|
|
351
|
+
agentDescription: agent.description,
|
|
352
|
+
otherAgents: this.agents.filter((a) => a.agentNickname !== agent.agentNickname),
|
|
353
|
+
roomLeader: this.getRoomLeader(),
|
|
354
|
+
roomGoal: this.getGoal(),
|
|
355
|
+
scenario: this.getGoal(),
|
|
356
|
+
situation: this.getSituation() || 'Story beginning',
|
|
357
|
+
visibleArtifacts: visibleArtifacts,
|
|
358
|
+
invisibleArtifactNames: invisibleArtifactNames,
|
|
359
|
+
humanCharacterName: humanCharacterName,
|
|
360
|
+
humanAgentName: humanCharacterName,
|
|
361
|
+
maxOutputChars: maxOutputChars,
|
|
362
|
+
availableTools: await this.buildAvailableTools(agent),
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
buildTransientPrompt(agent, message) {
|
|
366
|
+
let prompt = this.buildSituationHeader() || null;
|
|
367
|
+
if (message) {
|
|
368
|
+
const presentCharacters = this.getPresentCharacters(agent, message);
|
|
369
|
+
if (presentCharacters.length > 0) {
|
|
370
|
+
const descriptions = presentCharacters
|
|
371
|
+
.map((c) => `- ${c.agentNickname}: ${c.description}`)
|
|
372
|
+
.join('\n');
|
|
373
|
+
const charactersPresent = `Characters present (how they currently appear to you):\n${descriptions}`;
|
|
374
|
+
prompt = prompt ? `${prompt}\n\n${charactersPresent}` : charactersPresent;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
if (agent.privateContext && agent.privateContext.trim()) {
|
|
378
|
+
const privateBlock = `Your private context (known only to you):\n${agent.privateContext}`;
|
|
379
|
+
prompt = prompt ? `${prompt}\n\n${privateBlock}` : privateBlock;
|
|
380
|
+
}
|
|
381
|
+
if (agent.agentNickname === this.getRoomLeader()) {
|
|
382
|
+
const digest = this.buildCharacterPrivateContextDigest();
|
|
383
|
+
if (digest) {
|
|
384
|
+
const digestBlock = `Character Inventories and Conditions:\n${digest}`;
|
|
385
|
+
prompt = prompt ? `${prompt}\n\n${digestBlock}` : digestBlock;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
return prompt;
|
|
389
|
+
}
|
|
390
|
+
async promptAgentOnce(agent, transientPrompt, variables) {
|
|
391
|
+
const response = await agent.instructedPrompt(transientPrompt, 'perceive', variables, false, true, variables.maxOutputChars);
|
|
392
|
+
const answer = this.parseAgentResponse(agent, response);
|
|
393
|
+
agent.addToConversationHistory(response, true);
|
|
394
|
+
agent.save();
|
|
395
|
+
return answer;
|
|
396
|
+
}
|
|
397
|
+
async runAgentTurn(agent, heardMessage, opts = {}) {
|
|
398
|
+
const variables = await this.buildPerceiveVariables(agent);
|
|
399
|
+
let response = await this.promptAgentOnce(agent, this.buildTransientPrompt(agent, heardMessage), variables);
|
|
400
|
+
for (let i = 0; i < Room.MAX_TOOL_ITERATIONS; i++) {
|
|
401
|
+
if (this.isPaused || this.isAdjourned)
|
|
402
|
+
return null;
|
|
403
|
+
let feedback;
|
|
404
|
+
if (response.action === app_types_1.MessageAction.PUBLISH && response.name) {
|
|
405
|
+
this.publishArtifact(response.name, agent.agentNickname, response.content, response.targets);
|
|
406
|
+
const wasDeleted = !response.content || !response.content.trim();
|
|
407
|
+
feedback = `From system: Artifact "${response.name}" was ${wasDeleted ? 'deleted' : 'published'}.`;
|
|
408
|
+
}
|
|
409
|
+
else if (response.action === app_types_1.MessageAction.EXECUTE) {
|
|
410
|
+
feedback = await this.executeToolForAgent(agent, response);
|
|
411
|
+
}
|
|
412
|
+
else if (opts.inCommission && response.action === app_types_1.MessageAction.COMMISSION) {
|
|
413
|
+
feedback = `From system: Nested commissions are not permitted. Complete your own task and respond with action "deliver".`;
|
|
414
|
+
}
|
|
415
|
+
else {
|
|
416
|
+
if (!opts.inCommission && response.action === app_types_1.MessageAction.DELIVER) {
|
|
417
|
+
response.action = app_types_1.MessageAction.SPEAK;
|
|
418
|
+
}
|
|
419
|
+
return response;
|
|
420
|
+
}
|
|
421
|
+
agent.addToConversationHistory(feedback, false);
|
|
310
422
|
agent.save();
|
|
423
|
+
response = await this.promptAgentOnce(agent, this.buildTransientPrompt(agent, null), variables);
|
|
311
424
|
}
|
|
312
|
-
|
|
425
|
+
if (this.isPaused || this.isAdjourned)
|
|
426
|
+
return null;
|
|
427
|
+
agent.addToConversationHistory(`From system: You have reached the tool-call limit for this turn. Respond now with an audible action (speak, whisper, think, ...).`, false);
|
|
428
|
+
agent.save();
|
|
429
|
+
response = await this.promptAgentOnce(agent, this.buildTransientPrompt(agent, null), variables);
|
|
430
|
+
if (response.action === app_types_1.MessageAction.EXECUTE ||
|
|
431
|
+
response.action === app_types_1.MessageAction.PUBLISH) {
|
|
432
|
+
response = new message_1.RoomMessage(agent.agentNickname, app_types_1.MessageAction.THINK, response.content, []);
|
|
433
|
+
}
|
|
434
|
+
return response;
|
|
435
|
+
}
|
|
436
|
+
async executeToolForAgent(agent, message) {
|
|
437
|
+
const toolName = message.name;
|
|
438
|
+
const result = this.toolExecutionService
|
|
439
|
+
? await this.toolExecutionService.runForAgent(toolName, message.content, agent.toolNames || [])
|
|
440
|
+
: { ok: false, error: 'Tool execution is not available in this room' };
|
|
441
|
+
const argsPreview = message.content && message.content.length > 200
|
|
442
|
+
? `${message.content.slice(0, 200)}...`
|
|
443
|
+
: message.content || '';
|
|
444
|
+
const statusText = 'error' in result ? `error: ${result.error}` : 'ok';
|
|
445
|
+
this.addRoomMessage(new message_1.RoomMessage(agent.agentNickname, app_types_1.MessageAction.TOOL, `${toolName}(${argsPreview}) → ${statusText}`));
|
|
446
|
+
return `From system: Result of tool "${toolName}":\n${JSON.stringify(result)}`;
|
|
447
|
+
}
|
|
448
|
+
getAgentAiResponse(agent, message, onResponse) {
|
|
449
|
+
this.runAgentTurn(agent, message)
|
|
450
|
+
.then((answer) => onResponse(answer))
|
|
451
|
+
.catch((e) => {
|
|
313
452
|
if (e instanceof errors_1.InsufficientBalanceError) {
|
|
314
453
|
this.handleInsufficientBalance(e);
|
|
315
454
|
}
|
|
@@ -317,8 +456,8 @@ class Room {
|
|
|
317
456
|
let internalizedError = `${agent.agentNickname} thinks: No one heard me because ${e.message}`;
|
|
318
457
|
agent.addToConversationHistory(internalizedError, true);
|
|
319
458
|
}
|
|
320
|
-
|
|
321
|
-
|
|
459
|
+
onResponse(null);
|
|
460
|
+
});
|
|
322
461
|
}
|
|
323
462
|
perceive(agent, message, onResponse) {
|
|
324
463
|
if (!message.canHear(agent.agentNickname)) {
|
|
@@ -334,7 +473,7 @@ class Room {
|
|
|
334
473
|
if (agent.isControlledByHuman) {
|
|
335
474
|
return;
|
|
336
475
|
}
|
|
337
|
-
this.getAgentAiResponse(agent, onResponse);
|
|
476
|
+
this.getAgentAiResponse(agent, message, onResponse);
|
|
338
477
|
}
|
|
339
478
|
async moderate(moderatorAgent, message, onResponse) {
|
|
340
479
|
const humanAgent = this.getAgents().find((agent) => agent.isControlledByHuman);
|
|
@@ -361,10 +500,14 @@ class Room {
|
|
|
361
500
|
invisibleArtifactNames: invisibleArtifactNames,
|
|
362
501
|
};
|
|
363
502
|
let prompt = `
|
|
364
|
-
|
|
503
|
+
${this.buildSituationHeader()}
|
|
365
504
|
Sender: ${message.getSender()}
|
|
366
505
|
Recent Message: ${message.getContent()}
|
|
367
506
|
`;
|
|
507
|
+
const characterContexts = this.buildCharacterPrivateContextDigest();
|
|
508
|
+
if (characterContexts) {
|
|
509
|
+
prompt += `\nCharacter Inventories and Conditions:\n${characterContexts}\n`;
|
|
510
|
+
}
|
|
368
511
|
try {
|
|
369
512
|
let response = await moderatorAgent.instructedPrompt(prompt, 'moderate', variables, false, true);
|
|
370
513
|
let answer = this.parseAgentResponse(moderatorAgent, response);
|
|
@@ -458,6 +601,10 @@ Recent Message: ${message.getContent()}
|
|
|
458
601
|
setRoomStoreService(service) {
|
|
459
602
|
this.roomStoreService = service;
|
|
460
603
|
}
|
|
604
|
+
setToolServices(toolStore, toolExecution) {
|
|
605
|
+
this.toolStoreService = toolStore;
|
|
606
|
+
this.toolExecutionService = toolExecution;
|
|
607
|
+
}
|
|
461
608
|
saveMessages(messages) {
|
|
462
609
|
if (!this.roomStoreService || !this.storageDir || !this.id) {
|
|
463
610
|
return;
|
|
@@ -507,6 +654,22 @@ Recent Message: ${message.getContent()}
|
|
|
507
654
|
getSituation() {
|
|
508
655
|
return this.currentSituation;
|
|
509
656
|
}
|
|
657
|
+
getSituationTime() {
|
|
658
|
+
return this.currentSituationTime;
|
|
659
|
+
}
|
|
660
|
+
setSituationTime(time) {
|
|
661
|
+
this.currentSituationTime = time || '';
|
|
662
|
+
}
|
|
663
|
+
buildSituationHeader() {
|
|
664
|
+
const lines = [];
|
|
665
|
+
if (this.currentSituationTime) {
|
|
666
|
+
lines.push(`Current time: ${this.currentSituationTime} (24-hour clock)`);
|
|
667
|
+
}
|
|
668
|
+
if (this.currentSituation) {
|
|
669
|
+
lines.push(`Current Situation: ${this.currentSituation}`);
|
|
670
|
+
}
|
|
671
|
+
return lines.join('\n');
|
|
672
|
+
}
|
|
510
673
|
setSituation(situation) {
|
|
511
674
|
this.currentSituation = situation;
|
|
512
675
|
}
|
|
@@ -516,11 +679,11 @@ Recent Message: ${message.getContent()}
|
|
|
516
679
|
setOnModeratorResponse(callback) {
|
|
517
680
|
this.onModeratorResponseCallback = callback;
|
|
518
681
|
}
|
|
519
|
-
handleSituationUpdate(situation) {
|
|
682
|
+
async handleSituationUpdate(situation, messageBody) {
|
|
520
683
|
logger_1.logger.log(`Situation updated: ${situation}`);
|
|
521
684
|
this.currentSituation = situation;
|
|
522
685
|
if (this.onSituationUpdate) {
|
|
523
|
-
this.onSituationUpdate(situation);
|
|
686
|
+
await this.onSituationUpdate(situation, messageBody);
|
|
524
687
|
}
|
|
525
688
|
}
|
|
526
689
|
handlePublishMessages(messages) {
|
|
@@ -534,37 +697,6 @@ Recent Message: ${message.getContent()}
|
|
|
534
697
|
}
|
|
535
698
|
}
|
|
536
699
|
}
|
|
537
|
-
handleExecuteMessages(messages) {
|
|
538
|
-
for (const message of messages) {
|
|
539
|
-
if (message.content && message.content.trim()) {
|
|
540
|
-
const command = message.content.trim();
|
|
541
|
-
const creator = message.sender;
|
|
542
|
-
const description = message.name || 'Command execution';
|
|
543
|
-
const resultViewers = message.targets;
|
|
544
|
-
this.executeCommand(command, creator, description, resultViewers);
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
}
|
|
548
|
-
executeCommand(command, creator, description, resultViewers = []) {
|
|
549
|
-
const workingDir = this.baseRoomDir || process.cwd();
|
|
550
|
-
logger_1.logger.log(`FEATURE DISABLED -- Executing command: ${command} in directory: ${workingDir} by agent: ${creator}`);
|
|
551
|
-
return;
|
|
552
|
-
(0, child_process_1.exec)(command, { cwd: workingDir }, (error, stdout, stderr) => {
|
|
553
|
-
let result = '';
|
|
554
|
-
if (error) {
|
|
555
|
-
result = `Error: ${error.message}\n${stderr}`;
|
|
556
|
-
logger_1.logger.error(`Command execution error: ${error.message}`);
|
|
557
|
-
}
|
|
558
|
-
else if (stderr) {
|
|
559
|
-
result = `${stdout}\n\nStderr: ${stderr}`;
|
|
560
|
-
}
|
|
561
|
-
else {
|
|
562
|
-
result = stdout;
|
|
563
|
-
}
|
|
564
|
-
const artifactBody = `Command: ${command}\nWorking Directory: ${workingDir}\n\n${result}`;
|
|
565
|
-
this.publishArtifact(description, creator, artifactBody, resultViewers);
|
|
566
|
-
});
|
|
567
|
-
}
|
|
568
700
|
handleAdjournMessages(messages) {
|
|
569
701
|
if (messages.length === 0) {
|
|
570
702
|
return;
|
|
@@ -680,7 +812,7 @@ Recent Message: ${message.getContent()}
|
|
|
680
812
|
}
|
|
681
813
|
logger_1.logger.log(`Moderator routing: sender=${originalMessage.sender} action=${moderatorMessage.action}, name=${responderNickname}, targets=${targets.join(', ')}`);
|
|
682
814
|
if (moderatorMessage.action === app_types_1.MessageAction.RELAY) {
|
|
683
|
-
this.addRoomMessage(new message_1.RoomMessage(originalMessage.sender, originalMessage.action, content, originalMessage.targets, originalMessage.name, originalMessage.situation));
|
|
815
|
+
this.addRoomMessage(new message_1.RoomMessage(originalMessage.sender, originalMessage.action, content, originalMessage.targets, originalMessage.name, originalMessage.situation), { suppressSituationUpdate: true });
|
|
684
816
|
}
|
|
685
817
|
for (const recipientName of targets) {
|
|
686
818
|
if (recipientName === responderNickname)
|
|
@@ -711,6 +843,7 @@ Recent Message: ${message.getContent()}
|
|
|
711
843
|
return;
|
|
712
844
|
}
|
|
713
845
|
this.setCurrentSpeaker(responderNickname);
|
|
846
|
+
originalMessage.targets = targets;
|
|
714
847
|
this.perceive(responderAgent, originalMessage, (response) => {
|
|
715
848
|
if (this.isPaused) {
|
|
716
849
|
this.processingInProgress = false;
|
|
@@ -738,6 +871,149 @@ Recent Message: ${message.getContent()}
|
|
|
738
871
|
}
|
|
739
872
|
}
|
|
740
873
|
}
|
|
874
|
+
async runDeliverTurn(agent, commission) {
|
|
875
|
+
try {
|
|
876
|
+
let response = await this.runAgentTurn(agent, commission, { inCommission: true });
|
|
877
|
+
if (response === null)
|
|
878
|
+
return null;
|
|
879
|
+
if (response.action !== app_types_1.MessageAction.DELIVER) {
|
|
880
|
+
agent.addToConversationHistory(`From system: You were commissioned by ${commission.sender}. Respond now with action "deliver" targeting ${commission.sender}, containing your complete result.`, false);
|
|
881
|
+
agent.save();
|
|
882
|
+
const variables = await this.buildPerceiveVariables(agent);
|
|
883
|
+
response = await this.promptAgentOnce(agent, this.buildTransientPrompt(agent, null), variables);
|
|
884
|
+
}
|
|
885
|
+
if (response.action !== app_types_1.MessageAction.DELIVER) {
|
|
886
|
+
return new message_1.RoomMessage(agent.agentNickname, app_types_1.MessageAction.DELIVER, response.content, [commission.sender]);
|
|
887
|
+
}
|
|
888
|
+
response.sender = agent.agentNickname;
|
|
889
|
+
response.targets = [commission.sender];
|
|
890
|
+
return response;
|
|
891
|
+
}
|
|
892
|
+
catch (e) {
|
|
893
|
+
if (e instanceof errors_1.InsufficientBalanceError) {
|
|
894
|
+
this.handleInsufficientBalance(e);
|
|
895
|
+
return null;
|
|
896
|
+
}
|
|
897
|
+
logger_1.logger.error(`Commissioned agent ${agent.agentNickname} failed:`, e);
|
|
898
|
+
return new message_1.RoomMessage(agent.agentNickname, app_types_1.MessageAction.DELIVER, `(No deliverable: ${agent.agentNickname} encountered an error: ${e.message})`, [commission.sender]);
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
async handleCommissionMessage(msg) {
|
|
902
|
+
try {
|
|
903
|
+
const aiTargets = [];
|
|
904
|
+
const humanTargetNames = [];
|
|
905
|
+
const unknownNames = [];
|
|
906
|
+
for (const name of [...new Set(msg.getTargets())]) {
|
|
907
|
+
const agent = this.agents.find((a) => this.checkAgentNicknameMatch(a.agentNickname, name));
|
|
908
|
+
if (!agent) {
|
|
909
|
+
unknownNames.push(name);
|
|
910
|
+
}
|
|
911
|
+
else if (agent.agentNickname === msg.sender) {
|
|
912
|
+
}
|
|
913
|
+
else if (agent.isControlledByHuman) {
|
|
914
|
+
humanTargetNames.push(agent.agentNickname);
|
|
915
|
+
}
|
|
916
|
+
else if (!aiTargets.includes(agent)) {
|
|
917
|
+
aiTargets.push(agent);
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
for (const agent of this.agents) {
|
|
921
|
+
if (agent.agentNickname === msg.sender)
|
|
922
|
+
continue;
|
|
923
|
+
agent.addToConversationHistory(msg, false);
|
|
924
|
+
agent.save();
|
|
925
|
+
}
|
|
926
|
+
const commissioner = this.agents.find((a) => this.checkAgentNicknameMatch(a.agentNickname, msg.sender));
|
|
927
|
+
if (aiTargets.length === 0) {
|
|
928
|
+
const reasons = [];
|
|
929
|
+
if (unknownNames.length > 0)
|
|
930
|
+
reasons.push(`unknown agents: ${unknownNames.join(', ')}`);
|
|
931
|
+
if (humanTargetNames.length > 0)
|
|
932
|
+
reasons.push(`human-controlled agents cannot be commissioned: ${humanTargetNames.join(', ')}`);
|
|
933
|
+
const note = `From system: Your commission could not be delivered (${reasons.join('; ') || 'no valid targets'}).`;
|
|
934
|
+
await this.respondToCommissioner(commissioner, note);
|
|
935
|
+
return;
|
|
936
|
+
}
|
|
937
|
+
const settled = await Promise.allSettled(aiTargets.map((t) => this.runDeliverTurn(t, msg)));
|
|
938
|
+
if (this.isPaused || this.isAdjourned || !this.processingInProgress) {
|
|
939
|
+
if (this.processingInProgress) {
|
|
940
|
+
this.processingInProgress = false;
|
|
941
|
+
this.notifyStateChange();
|
|
942
|
+
}
|
|
943
|
+
return;
|
|
944
|
+
}
|
|
945
|
+
const delivers = settled.map((result, i) => {
|
|
946
|
+
if (result.status === 'fulfilled' && result.value)
|
|
947
|
+
return result.value;
|
|
948
|
+
return new message_1.RoomMessage(aiTargets[i].agentNickname, app_types_1.MessageAction.DELIVER, `(No deliverable: ${aiTargets[i].agentNickname} did not complete the commission)`, [msg.sender]);
|
|
949
|
+
});
|
|
950
|
+
for (const deliver of delivers) {
|
|
951
|
+
this.addRoomMessage(deliver);
|
|
952
|
+
for (const agent of this.agents) {
|
|
953
|
+
if (agent.agentNickname === deliver.sender)
|
|
954
|
+
continue;
|
|
955
|
+
if (this.checkAgentNicknameMatch(agent.agentNickname, msg.sender))
|
|
956
|
+
continue;
|
|
957
|
+
agent.addToConversationHistory(deliver, false);
|
|
958
|
+
agent.save();
|
|
959
|
+
}
|
|
960
|
+
}
|
|
961
|
+
const sections = delivers.map((d) => `## From ${d.sender}\n${d.content}`);
|
|
962
|
+
if (humanTargetNames.length > 0) {
|
|
963
|
+
sections.push(`(Skipped: ${humanTargetNames.join(', ')} — human-controlled agents cannot be commissioned)`);
|
|
964
|
+
}
|
|
965
|
+
if (unknownNames.length > 0) {
|
|
966
|
+
sections.push(`(Unknown agents: ${unknownNames.join(', ')})`);
|
|
967
|
+
}
|
|
968
|
+
const aggregate = `From system: Deliverables for your commission:\n\n${sections.join('\n\n')}`;
|
|
969
|
+
await this.respondToCommissioner(commissioner, aggregate);
|
|
970
|
+
}
|
|
971
|
+
catch (error) {
|
|
972
|
+
logger_1.logger.error('Error handling commission message:', error);
|
|
973
|
+
this.processingInProgress = false;
|
|
974
|
+
this.notifyStateChange();
|
|
975
|
+
if (this.pendingMessages && this.pendingMessages.length > 0) {
|
|
976
|
+
this.processPendingMessages();
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
async respondToCommissioner(commissioner, note) {
|
|
981
|
+
if (!commissioner) {
|
|
982
|
+
logger_1.logger.warn('Commissioner not found in room; dropping commission results');
|
|
983
|
+
}
|
|
984
|
+
else {
|
|
985
|
+
commissioner.addToConversationHistory(note, false);
|
|
986
|
+
commissioner.save();
|
|
987
|
+
if (commissioner.isControlledByHuman) {
|
|
988
|
+
this.addRoomMessage(new message_1.RoomMessage('system', app_types_1.MessageAction.SYSTEM, note, [
|
|
989
|
+
commissioner.agentNickname,
|
|
990
|
+
]));
|
|
991
|
+
this.processingInProgress = false;
|
|
992
|
+
this.notifyStateChange();
|
|
993
|
+
this.setCurrentSpeaker(commissioner.agentNickname);
|
|
994
|
+
return;
|
|
995
|
+
}
|
|
996
|
+
let reply = null;
|
|
997
|
+
try {
|
|
998
|
+
reply = await this.runAgentTurn(commissioner, null);
|
|
999
|
+
}
|
|
1000
|
+
catch (e) {
|
|
1001
|
+
if (e instanceof errors_1.InsufficientBalanceError) {
|
|
1002
|
+
this.handleInsufficientBalance(e);
|
|
1003
|
+
return;
|
|
1004
|
+
}
|
|
1005
|
+
throw e;
|
|
1006
|
+
}
|
|
1007
|
+
if (reply !== null && !this.isPaused && !this.isAdjourned) {
|
|
1008
|
+
this.pendingMessages = [...(this.pendingMessages || []), reply];
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
1011
|
+
this.processingInProgress = false;
|
|
1012
|
+
this.notifyStateChange();
|
|
1013
|
+
if (this.pendingMessages && this.pendingMessages.length > 0) {
|
|
1014
|
+
this.processPendingMessages();
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
741
1017
|
processPendingMessages() {
|
|
742
1018
|
if (this.isPaused ||
|
|
743
1019
|
this.processingInProgress ||
|
|
@@ -750,7 +1026,10 @@ Recent Message: ${message.getContent()}
|
|
|
750
1026
|
const messages = [...this.pendingMessages];
|
|
751
1027
|
this.pendingMessages = [];
|
|
752
1028
|
this.handlePublishMessages(messages.filter((m) => m.getAction() === app_types_1.MessageAction.PUBLISH));
|
|
753
|
-
|
|
1029
|
+
const strayExecuteMessages = messages.filter((m) => m.getAction() === app_types_1.MessageAction.EXECUTE);
|
|
1030
|
+
if (strayExecuteMessages.length > 0) {
|
|
1031
|
+
logger_1.logger.warn(`Dropping ${strayExecuteMessages.length} queued EXECUTE message(s); tool calls are handled within the sender's turn`);
|
|
1032
|
+
}
|
|
754
1033
|
this.handleAdjournMessages(messages.filter((m) => m.getAction() === app_types_1.MessageAction.ADJOURN));
|
|
755
1034
|
if (this.isAdjourned) {
|
|
756
1035
|
logger_1.logger.log(`Room ${this.name} has been adjourned. Message processing stopped.`);
|
|
@@ -776,21 +1055,34 @@ Recent Message: ${message.getContent()}
|
|
|
776
1055
|
if (moderateMessages.length > 1) {
|
|
777
1056
|
this.pendingMessages = [...moderateMessages.slice(1), ...this.pendingMessages];
|
|
778
1057
|
}
|
|
779
|
-
|
|
780
|
-
if (
|
|
781
|
-
this.
|
|
782
|
-
this.notifyStateChange();
|
|
783
|
-
return;
|
|
1058
|
+
const dispatchToModerator = async () => {
|
|
1059
|
+
if (originalMessage.situation) {
|
|
1060
|
+
await this.handleSituationUpdate(originalMessage.situation, originalMessage.getContent());
|
|
784
1061
|
}
|
|
785
|
-
|
|
786
|
-
this.
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
if (
|
|
792
|
-
this.
|
|
1062
|
+
await this.moderate(moderator, originalMessage, (response) => {
|
|
1063
|
+
if (this.isPaused) {
|
|
1064
|
+
this.processingInProgress = false;
|
|
1065
|
+
this.notifyStateChange();
|
|
1066
|
+
return;
|
|
1067
|
+
}
|
|
1068
|
+
if (response !== null) {
|
|
1069
|
+
this.handleModeratorResponse(response, originalMessage);
|
|
793
1070
|
}
|
|
1071
|
+
else {
|
|
1072
|
+
this.processingInProgress = false;
|
|
1073
|
+
this.notifyStateChange();
|
|
1074
|
+
if (this.pendingMessages && this.pendingMessages.length > 0) {
|
|
1075
|
+
this.processPendingMessages();
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
});
|
|
1079
|
+
};
|
|
1080
|
+
dispatchToModerator().catch((error) => {
|
|
1081
|
+
logger_1.logger.error('Error dispatching message to moderator:', error);
|
|
1082
|
+
this.processingInProgress = false;
|
|
1083
|
+
this.notifyStateChange();
|
|
1084
|
+
if (this.pendingMessages && this.pendingMessages.length > 0) {
|
|
1085
|
+
this.processPendingMessages();
|
|
794
1086
|
}
|
|
795
1087
|
});
|
|
796
1088
|
return;
|
|
@@ -812,6 +1104,10 @@ Recent Message: ${message.getContent()}
|
|
|
812
1104
|
nextMessage = filteredMessage;
|
|
813
1105
|
}
|
|
814
1106
|
this.addRoomMessage(nextMessage);
|
|
1107
|
+
if (nextMessage.getAction() === app_types_1.MessageAction.COMMISSION) {
|
|
1108
|
+
void this.handleCommissionMessage(nextMessage);
|
|
1109
|
+
return;
|
|
1110
|
+
}
|
|
815
1111
|
this.setCurrentSpeaker(nextMessage.targets[0]);
|
|
816
1112
|
let agentsInProgress = this.agents.length;
|
|
817
1113
|
if (agentsInProgress === 0) {
|
|
@@ -859,7 +1155,8 @@ Recent Message: ${message.getContent()}
|
|
|
859
1155
|
filtered = shoutMessages;
|
|
860
1156
|
}
|
|
861
1157
|
if (filtered.length > 1) {
|
|
862
|
-
const speakMessages = filtered.filter((m) => m.getAction() === app_types_1.MessageAction.SPEAK
|
|
1158
|
+
const speakMessages = filtered.filter((m) => m.getAction() === app_types_1.MessageAction.SPEAK ||
|
|
1159
|
+
m.getAction() === app_types_1.MessageAction.COMMISSION);
|
|
863
1160
|
const whisperMessages = filtered.filter((m) => m.getAction() === app_types_1.MessageAction.WHISPER);
|
|
864
1161
|
if (speakMessages.length > 0) {
|
|
865
1162
|
filtered = speakMessages;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { Briyah } from './briyah';
|
|
2
2
|
export { BriyahConfigService, BriyahConfigOptions } from './briyah-config';
|
|
3
3
|
export type { AppService } from '../app.service';
|
|
4
|
-
export type { AgentInfo, CreateAgentResponse, RoomInfo, RoomDetails, CreateRoomResponse, StoryInfo, CreateStoryResponse, ProcessTextResponse, FileList, PromptFileContent, AttachDocumentResponse, AgentMessagesResponse, RoomMessagesResponse, StoryState, Message, MessageAction, ModelInfo, ArtifactMetadata, PreparedPromptResponse, PromptScope, PromptFolder, PromptFoldersResponse, PromptFile, PromptFilesResponse, StoryIdea, Transaction, TransactionHistoryResponse, StoryStateEvent, StoryIntroduceCharacterEvent, StoryProgressChapterEvent, StoryErrorEvent, Character, ChapterInfo, } from '../../../shared/types/app.types';
|
|
4
|
+
export type { AgentInfo, CreateAgentResponse, RoomInfo, RoomDetails, CreateRoomResponse, StoryInfo, CreateStoryResponse, ProcessTextResponse, FileList, PromptFileContent, AttachDocumentResponse, AgentMessagesResponse, RoomMessagesResponse, StoryState, Message, MessageAction, ModelInfo, ArtifactMetadata, PreparedPromptResponse, PromptScope, PromptFolder, PromptFoldersResponse, PromptFile, PromptFilesResponse, StoryIdea, Transaction, TransactionHistoryResponse, ToolDefinition, ToolParameter, ToolsResponse, ToolRunResult, StoryStateEvent, StoryIntroduceCharacterEvent, StoryProgressChapterEvent, StoryErrorEvent, Character, ChapterInfo, } from '../../../shared/types/app.types';
|
|
5
5
|
export type { LoggingOptions } from './briyah-config';
|
|
6
6
|
export { Agent } from '../ai/agent';
|
|
7
7
|
export { Room } from '../room/room';
|