briyah 1.1.3 → 1.1.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 (70) hide show
  1. package/README.md +14 -1
  2. package/data/common/config/image_models.json +6 -0
  3. package/data/common/config/markup +1 -1
  4. package/data/common/config/story_models.json +7 -0
  5. package/dist-sdk/server/src/ai/LLM/anthropic.service.js +6 -3
  6. package/dist-sdk/server/src/ai/LLM/base-ai.service.js +2 -1
  7. package/dist-sdk/server/src/app.controller.d.ts +11 -2
  8. package/dist-sdk/server/src/app.controller.js +167 -3
  9. package/dist-sdk/server/src/app.service.d.ts +1 -0
  10. package/dist-sdk/server/src/app.service.js +23 -11
  11. package/dist-sdk/server/src/auth/users.service.js +2 -2
  12. package/dist-sdk/server/src/common/errors.d.ts +3 -0
  13. package/dist-sdk/server/src/common/errors.js +11 -1
  14. package/dist-sdk/server/src/config/configuration.service.d.ts +2 -0
  15. package/dist-sdk/server/src/config/configuration.service.js +8 -0
  16. package/dist-sdk/server/src/library/library.service.d.ts +14 -0
  17. package/dist-sdk/server/src/library/library.service.js +165 -0
  18. package/dist-sdk/server/src/room/room.d.ts +4 -2
  19. package/dist-sdk/server/src/room/room.js +40 -19
  20. package/dist-sdk/server/src/shared/shared.module.js +3 -0
  21. package/dist-sdk/server/src/story/story.service.js +2 -2
  22. package/dist-sdk/shared/types/app.types.d.ts +22 -0
  23. package/docs/assets/hierarchy.js +1 -1
  24. package/docs/assets/search.js +1 -1
  25. package/docs/classes/Agent.html +14 -14
  26. package/docs/classes/Briyah.html +12 -12
  27. package/docs/classes/BriyahConfigService.html +5 -5
  28. package/docs/classes/Room.html +31 -24
  29. package/docs/classes/RoomMessage.html +10 -10
  30. package/docs/enums/MessageAction.html +3 -3
  31. package/docs/hierarchy.html +1 -1
  32. package/docs/index.html +15 -3
  33. package/docs/interfaces/AgentInfo.html +2 -2
  34. package/docs/interfaces/AgentMessagesResponse.html +2 -2
  35. package/docs/interfaces/AppService.html +110 -107
  36. package/docs/interfaces/Artifact.html +3 -3
  37. package/docs/interfaces/ArtifactMetadata.html +2 -2
  38. package/docs/interfaces/AttachDocumentResponse.html +2 -2
  39. package/docs/interfaces/BriyahConfigOptions.html +6 -6
  40. package/docs/interfaces/ChapterInfo.html +2 -2
  41. package/docs/interfaces/Character.html +2 -2
  42. package/docs/interfaces/CreateAgentResponse.html +2 -2
  43. package/docs/interfaces/CreateRoomResponse.html +2 -2
  44. package/docs/interfaces/CreateStoryResponse.html +2 -2
  45. package/docs/interfaces/FileList.html +2 -2
  46. package/docs/interfaces/LoggingOptions.html +5 -5
  47. package/docs/interfaces/Message.html +2 -2
  48. package/docs/interfaces/ModelInfo.html +2 -2
  49. package/docs/interfaces/PreparedPromptResponse.html +2 -2
  50. package/docs/interfaces/ProcessTextResponse.html +2 -2
  51. package/docs/interfaces/PromptFile.html +2 -2
  52. package/docs/interfaces/PromptFileContent.html +2 -2
  53. package/docs/interfaces/PromptFilesResponse.html +2 -2
  54. package/docs/interfaces/PromptFolder.html +2 -2
  55. package/docs/interfaces/PromptFoldersResponse.html +2 -2
  56. package/docs/interfaces/RoomDetails.html +2 -2
  57. package/docs/interfaces/RoomInfo.html +2 -2
  58. package/docs/interfaces/RoomMessagesResponse.html +2 -2
  59. package/docs/interfaces/StoryErrorEvent.html +3 -3
  60. package/docs/interfaces/StoryIdea.html +2 -2
  61. package/docs/interfaces/StoryInfo.html +3 -3
  62. package/docs/interfaces/StoryIntroduceCharacterEvent.html +3 -3
  63. package/docs/interfaces/StoryProgressChapterEvent.html +3 -3
  64. package/docs/interfaces/StoryState.html +5 -5
  65. package/docs/interfaces/StoryStateEvent.html +3 -3
  66. package/docs/interfaces/Transaction.html +2 -2
  67. package/docs/interfaces/TransactionHistoryResponse.html +2 -2
  68. package/docs/modules.html +1 -1
  69. package/docs/types/PromptScope.html +1 -1
  70. package/package.json +1 -2
package/README.md CHANGED
@@ -1,6 +1,19 @@
1
1
  # Briyah SDK
2
2
 
3
- The Briyah SDK provides a clean, easy-to-use interface for integrating the Briyah multi-agent AI system into your applications without requiring NestJS dependency injection setup.
3
+ Briyah is an SDK for AI agents, multi-agent rooms, and interactive stories. It wraps the Briyah runtime as a single class with per-user data isolation and balance tracking, and supports Anthropic, OpenAI, Google, Grok, DeepSeek, Together, and Fal as LLM providers.
4
+
5
+ What's in the package:
6
+
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.
9
+ - **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
+ - **Text processing.** One-shot `processText` for non-conversational use, with cost and token counts on the result.
11
+ - **File attachments.** Attach documents to agents as context. Supported file types vary by LLM provider.
12
+ - **Per-user data.** Agents, rooms, stories, attached files, balances, and transactions are scoped to a userId the host controls. Per-user directories keep state isolated.
13
+ - **Balances and transactions.** Track per-user balances against usage cost. Record pending, succeeded, failed, or cancelled transactions when integrating with a payment provider, credit balances on webhook confirmation, and resume stories that paused on insufficient funds. Briyah does not process payments itself.
14
+ - **Real-time event emitters.** Story-state and balance updates can be forwarded to SSE or websockets.
15
+
16
+ State is persisted as JSON files under a configurable data path; no external database is required.
4
17
 
5
18
  ## Installation
6
19
 
@@ -11,5 +11,11 @@
11
11
  "description": "Mediocre quality; some character consistency",
12
12
  "service": "OpenAI",
13
13
  "model": "gpt-image-1-mini"
14
+ },
15
+ {
16
+ "name": "No images",
17
+ "description": "Disable image generation (no real API calls)",
18
+ "service": "",
19
+ "model": ""
14
20
  }
15
21
  ]
@@ -1 +1 @@
1
- 1.6219859999999993
1
+ 11.330019880000021
@@ -26,6 +26,13 @@
26
26
  "service": "Grok",
27
27
  "model": "grok-4.20-0309-reasoning",
28
28
  "cost": "300"
29
+ },
30
+ {
31
+ "name": "Mock",
32
+ "description": "Mock LLM for testing (no real API calls)",
33
+ "service": "Mock",
34
+ "model": "mock-fast-v1",
35
+ "cost": "0"
29
36
  }
30
37
 
31
38
  ]
@@ -155,11 +155,14 @@ let AnthropicAiService = class AnthropicAiService extends base_ai_service_1.Base
155
155
  const systemBlocks = [];
156
156
  if (instructionText)
157
157
  systemBlocks.push({ type: 'text', text: instructionText });
158
- systemBlocks.push({
158
+ const identityBlock = {
159
159
  type: 'text',
160
160
  text: `Your agent identity is ${agent.agentName}: ${agent.description}`,
161
- cache_control: cacheConfig,
162
- });
161
+ };
162
+ if (cacheConfig) {
163
+ identityBlock.cache_control = cacheConfig;
164
+ }
165
+ systemBlocks.push(identityBlock);
163
166
  const messageHistory = agent.history.map((msg) => ({
164
167
  role: msg.role,
165
168
  content: [{ type: 'text', text: msg.content }],
@@ -151,7 +151,8 @@ let BaseAiService = class BaseAiService {
151
151
  if (!agentName) {
152
152
  throw new Error('Agent name is required');
153
153
  }
154
- if (!(0, model_prices_1.isKnownModel)(modelName, this.getModelPricePrefix())) {
154
+ if (this.getServiceName() !== 'Mock' &&
155
+ !(0, model_prices_1.isKnownModel)(modelName, this.getModelPricePrefix())) {
155
156
  throw new Error(`Model '${modelName}' is not listed in model_prices.json for ${this.getServiceName()}. ` +
156
157
  `Add a pricing entry before using this model.`);
157
158
  }
@@ -4,13 +4,15 @@ import { Observable } from 'rxjs';
4
4
  import { UserServiceManager } from './app/user-service-manager';
5
5
  import { PublishedAgentsService } from './ai/published-agents.service';
6
6
  import { PublishedRoomsService } from './room/published-rooms.service';
7
- import { AgentInfo, CreateAgentResponse, UpdateAgentRequest, RoomInfo, RoomDetails, CreateRoomResponse, AgentMessagesResponse, RoomMessagesResponse, FileList, PromptFileContent, PromptFoldersResponse, PromptFilesResponse, PromptScope, CreatePromptFolderRequest, CreatePromptFileRequest, UpdatePromptFileRequest, ProcessTextResponse, PreparedPromptResponse, AttachDocumentResponse, StoryInfo, StoryState, Character, ModelInfo, StoryModelDefaults, ChapterInfo, StoryIdea } from '../../shared/types/app.types';
7
+ import { LibraryService } from './library/library.service';
8
+ import { AgentInfo, CreateAgentResponse, UpdateAgentRequest, RoomInfo, RoomDetails, CreateRoomResponse, AgentMessagesResponse, RoomMessagesResponse, FileList, PromptFileContent, PromptFoldersResponse, PromptFilesResponse, PromptScope, CreatePromptFolderRequest, CreatePromptFileRequest, UpdatePromptFileRequest, ProcessTextResponse, PreparedPromptResponse, AttachDocumentResponse, StoryInfo, StoryState, Character, ModelInfo, StoryModelDefaults, ChapterInfo, StoryIdea, LibraryPromptsResponse, LibraryFilesResponse, LibraryFileContent, LibraryDefaultUrlResponse, CopyFromLibraryRequest } from '../../shared/types/app.types';
8
9
  import { RoomMessage } from './room/message';
9
10
  export declare class AppController {
10
11
  private readonly userServiceManager;
11
12
  private readonly publishedAgentsService;
12
13
  private readonly publishedRoomsService;
13
- constructor(userServiceManager: UserServiceManager, publishedAgentsService: PublishedAgentsService, publishedRoomsService: PublishedRoomsService);
14
+ private readonly libraryService;
15
+ constructor(userServiceManager: UserServiceManager, publishedAgentsService: PublishedAgentsService, publishedRoomsService: PublishedRoomsService, libraryService: LibraryService);
14
16
  private getAppService;
15
17
  listServices(req: ExpressRequest): string[];
16
18
  listModels(req: ExpressRequest, aiServiceName: string): Promise<ModelInfo[]>;
@@ -44,6 +46,13 @@ export declare class AppController {
44
46
  createPromptFile(req: ExpressRequest, folderName: string, body: CreatePromptFileRequest): Promise<void>;
45
47
  updatePromptFile(req: ExpressRequest, folderName: string, fileName: string, body: UpdatePromptFileRequest): Promise<void>;
46
48
  deletePromptFile(req: ExpressRequest, folderName: string, fileName: string): Promise<void>;
49
+ listLibraryPrompts(): LibraryPromptsResponse;
50
+ listLibraryFiles(folder: string): LibraryFilesResponse;
51
+ getLibraryFile(folder: string, file: string): LibraryFileContent;
52
+ getLibraryDefaultUrl(): LibraryDefaultUrlResponse;
53
+ proxyListRemote(url: string): Promise<LibraryPromptsResponse>;
54
+ proxyPreviewRemote(url: string, folder: string): Promise<LibraryFileContent>;
55
+ copyPromptFromLibrary(req: ExpressRequest, body: CopyFromLibraryRequest): Promise<void>;
47
56
  listPromptFolders(req: ExpressRequest): string[];
48
57
  listPrompts(req: ExpressRequest, agentId: string): string[];
49
58
  runPreparedPrompt(req: ExpressRequest, agentId: string, promptName: string, body: {
@@ -50,11 +50,13 @@ const common_1 = require("@nestjs/common");
50
50
  const platform_express_1 = require("@nestjs/platform-express");
51
51
  const rxjs_1 = require("rxjs");
52
52
  const jwt_auth_guard_1 = require("./auth/jwt-auth.guard");
53
+ const public_decorator_1 = require("./auth/public.decorator");
53
54
  const agent_access_decorator_1 = require("./auth/agent-access.decorator");
54
55
  const room_access_decorator_1 = require("./auth/room-access.decorator");
55
56
  const user_service_manager_1 = require("./app/user-service-manager");
56
57
  const published_agents_service_1 = require("./ai/published-agents.service");
57
58
  const published_rooms_service_1 = require("./room/published-rooms.service");
59
+ const library_service_1 = require("./library/library.service");
58
60
  const errors_1 = require("./common/errors");
59
61
  const path = __importStar(require("path"));
60
62
  const logger_1 = require("./common/logger");
@@ -62,10 +64,12 @@ let AppController = class AppController {
62
64
  userServiceManager;
63
65
  publishedAgentsService;
64
66
  publishedRoomsService;
65
- constructor(userServiceManager, publishedAgentsService, publishedRoomsService) {
67
+ libraryService;
68
+ constructor(userServiceManager, publishedAgentsService, publishedRoomsService, libraryService) {
66
69
  this.userServiceManager = userServiceManager;
67
70
  this.publishedAgentsService = publishedAgentsService;
68
71
  this.publishedRoomsService = publishedRoomsService;
72
+ this.libraryService = libraryService;
69
73
  }
70
74
  getAppService(req, agentId, roomId) {
71
75
  let userId;
@@ -345,6 +349,105 @@ let AppController = class AppController {
345
349
  throw new common_1.HttpException('Failed to delete prompt file', common_1.HttpStatus.INTERNAL_SERVER_ERROR);
346
350
  }
347
351
  }
352
+ listLibraryPrompts() {
353
+ return { prompts: this.libraryService.listLocalPrompts() };
354
+ }
355
+ listLibraryFiles(folder) {
356
+ try {
357
+ return { files: this.libraryService.listLocalFiles(folder) };
358
+ }
359
+ catch (error) {
360
+ if (error instanceof errors_1.ValidationError) {
361
+ throw new common_1.BadRequestException(error.message);
362
+ }
363
+ if (error instanceof errors_1.NotFoundError) {
364
+ throw new common_1.NotFoundException(error.message);
365
+ }
366
+ throw error;
367
+ }
368
+ }
369
+ getLibraryFile(folder, file) {
370
+ try {
371
+ return { content: this.libraryService.getLocalFileContent(folder, file) };
372
+ }
373
+ catch (error) {
374
+ if (error instanceof errors_1.ValidationError) {
375
+ throw new common_1.BadRequestException(error.message);
376
+ }
377
+ if (error instanceof errors_1.NotFoundError) {
378
+ throw new common_1.NotFoundException(error.message);
379
+ }
380
+ throw error;
381
+ }
382
+ }
383
+ getLibraryDefaultUrl() {
384
+ return { url: process.env.WEB_URL ?? '' };
385
+ }
386
+ async proxyListRemote(url) {
387
+ if (!url)
388
+ throw new common_1.BadRequestException('url query param is required');
389
+ try {
390
+ return { prompts: await this.libraryService.listRemotePrompts(url) };
391
+ }
392
+ catch (error) {
393
+ if (error instanceof errors_1.ValidationError) {
394
+ throw new common_1.BadRequestException(error.message);
395
+ }
396
+ if (error instanceof errors_1.NotFoundError) {
397
+ throw new common_1.NotFoundException(error.message);
398
+ }
399
+ if (error instanceof errors_1.RemoteFetchError) {
400
+ throw new common_1.HttpException(error.message, common_1.HttpStatus.BAD_GATEWAY);
401
+ }
402
+ throw error;
403
+ }
404
+ }
405
+ async proxyPreviewRemote(url, folder) {
406
+ if (!url)
407
+ throw new common_1.BadRequestException('url query param is required');
408
+ try {
409
+ return {
410
+ content: await this.libraryService.getRemoteFileContent(url, folder, 'system_instruction.prompt'),
411
+ };
412
+ }
413
+ catch (error) {
414
+ if (error instanceof errors_1.ValidationError) {
415
+ throw new common_1.BadRequestException(error.message);
416
+ }
417
+ if (error instanceof errors_1.NotFoundError) {
418
+ throw new common_1.NotFoundException(error.message);
419
+ }
420
+ if (error instanceof errors_1.RemoteFetchError) {
421
+ throw new common_1.HttpException(error.message, common_1.HttpStatus.BAD_GATEWAY);
422
+ }
423
+ throw error;
424
+ }
425
+ }
426
+ async copyPromptFromLibrary(req, body) {
427
+ if (!body?.url || !body?.folder) {
428
+ throw new common_1.BadRequestException('url and folder are required');
429
+ }
430
+ const appService = this.getAppService(req);
431
+ try {
432
+ await this.libraryService.copyFromRemote(body.url, body.folder, appService.getUserPromptsDir());
433
+ }
434
+ catch (error) {
435
+ logger_1.logger.error(`[${req.user?.sub}] Error copying library prompt ${body.folder} from ${body.url}:`, error);
436
+ if (error instanceof errors_1.ValidationError) {
437
+ throw new common_1.BadRequestException(error.message);
438
+ }
439
+ if (error instanceof errors_1.NotFoundError) {
440
+ throw new common_1.NotFoundException(error.message);
441
+ }
442
+ if (error instanceof errors_1.RemoteFetchError) {
443
+ throw new common_1.HttpException(error.message, common_1.HttpStatus.BAD_GATEWAY);
444
+ }
445
+ if (error instanceof errors_1.OperationFailedError) {
446
+ throw new common_1.HttpException(error.message, common_1.HttpStatus.CONFLICT);
447
+ }
448
+ throw error;
449
+ }
450
+ }
348
451
  listPromptFolders(req) {
349
452
  try {
350
453
  const appService = this.getAppService(req);
@@ -556,6 +659,9 @@ let AppController = class AppController {
556
659
  if (!body.publishedAgentName) {
557
660
  throw new common_1.BadRequestException('publishedAgentName field is required');
558
661
  }
662
+ if (body.publishedAgentName.length > 200) {
663
+ throw new common_1.BadRequestException('publishedAgentName too long (max 200 characters)');
664
+ }
559
665
  try {
560
666
  const appService = this.getAppService(req);
561
667
  const result = await appService.publishAgentInstance(agentId, body.publishedAgentName);
@@ -875,6 +981,9 @@ let AppController = class AppController {
875
981
  }
876
982
  }
877
983
  async publishRoom(req, templateId, body) {
984
+ if (body.publishedName && body.publishedName.length > 200) {
985
+ throw new common_1.BadRequestException('publishedName too long (max 200 characters)');
986
+ }
878
987
  try {
879
988
  const appService = this.getAppService(req);
880
989
  const userId = req.user.sub;
@@ -1493,7 +1602,7 @@ let AppController = class AppController {
1493
1602
  if (!roomDetails) {
1494
1603
  throw new common_1.NotFoundException(`Room ${roomId} not found`);
1495
1604
  }
1496
- appService.ensureRoomStateCallback(roomId);
1605
+ await appService.ensureRoomStateCallback(roomId);
1497
1606
  const emitter = appService.getRoomMessageEmitter(roomId);
1498
1607
  return new rxjs_1.Observable((subscriber) => {
1499
1608
  const updateHandler = (data) => {
@@ -1834,6 +1943,60 @@ __decorate([
1834
1943
  __metadata("design:paramtypes", [Object, String, String]),
1835
1944
  __metadata("design:returntype", Promise)
1836
1945
  ], AppController.prototype, "deletePromptFile", null);
1946
+ __decorate([
1947
+ (0, common_1.Get)('library/prompts'),
1948
+ (0, public_decorator_1.Public)(),
1949
+ __metadata("design:type", Function),
1950
+ __metadata("design:paramtypes", []),
1951
+ __metadata("design:returntype", Object)
1952
+ ], AppController.prototype, "listLibraryPrompts", null);
1953
+ __decorate([
1954
+ (0, common_1.Get)('library/prompts/:folder/files'),
1955
+ (0, public_decorator_1.Public)(),
1956
+ __param(0, (0, common_1.Param)('folder')),
1957
+ __metadata("design:type", Function),
1958
+ __metadata("design:paramtypes", [String]),
1959
+ __metadata("design:returntype", Object)
1960
+ ], AppController.prototype, "listLibraryFiles", null);
1961
+ __decorate([
1962
+ (0, common_1.Get)('library/prompts/:folder/files/:file'),
1963
+ (0, public_decorator_1.Public)(),
1964
+ __param(0, (0, common_1.Param)('folder')),
1965
+ __param(1, (0, common_1.Param)('file')),
1966
+ __metadata("design:type", Function),
1967
+ __metadata("design:paramtypes", [String, String]),
1968
+ __metadata("design:returntype", Object)
1969
+ ], AppController.prototype, "getLibraryFile", null);
1970
+ __decorate([
1971
+ (0, common_1.Get)('library/default-url'),
1972
+ __metadata("design:type", Function),
1973
+ __metadata("design:paramtypes", []),
1974
+ __metadata("design:returntype", Object)
1975
+ ], AppController.prototype, "getLibraryDefaultUrl", null);
1976
+ __decorate([
1977
+ (0, common_1.Get)('library/proxy/prompts'),
1978
+ __param(0, (0, common_1.Query)('url')),
1979
+ __metadata("design:type", Function),
1980
+ __metadata("design:paramtypes", [String]),
1981
+ __metadata("design:returntype", Promise)
1982
+ ], AppController.prototype, "proxyListRemote", null);
1983
+ __decorate([
1984
+ (0, common_1.Get)('library/proxy/prompts/:folder/preview'),
1985
+ __param(0, (0, common_1.Query)('url')),
1986
+ __param(1, (0, common_1.Param)('folder')),
1987
+ __metadata("design:type", Function),
1988
+ __metadata("design:paramtypes", [String, String]),
1989
+ __metadata("design:returntype", Promise)
1990
+ ], AppController.prototype, "proxyPreviewRemote", null);
1991
+ __decorate([
1992
+ (0, common_1.Post)('prompts/from-library'),
1993
+ (0, common_1.HttpCode)(common_1.HttpStatus.CREATED),
1994
+ __param(0, (0, common_1.Request)()),
1995
+ __param(1, (0, common_1.Body)()),
1996
+ __metadata("design:type", Function),
1997
+ __metadata("design:paramtypes", [Object, Object]),
1998
+ __metadata("design:returntype", Promise)
1999
+ ], AppController.prototype, "copyPromptFromLibrary", null);
1837
2000
  __decorate([
1838
2001
  (0, common_1.Get)('list-prompt-folders'),
1839
2002
  __param(0, (0, common_1.Request)()),
@@ -2578,5 +2741,6 @@ exports.AppController = AppController = __decorate([
2578
2741
  (0, common_1.UseGuards)(jwt_auth_guard_1.JwtAuthGuard),
2579
2742
  __metadata("design:paramtypes", [user_service_manager_1.UserServiceManager,
2580
2743
  published_agents_service_1.PublishedAgentsService,
2581
- published_rooms_service_1.PublishedRoomsService])
2744
+ published_rooms_service_1.PublishedRoomsService,
2745
+ library_service_1.LibraryService])
2582
2746
  ], AppController);
@@ -95,6 +95,7 @@ export declare class AppService {
95
95
  artifacts: any[];
96
96
  }>;
97
97
  publishArtifact(roomId: string, name: string, creator: string, body: string, viewers?: string[]): Promise<void>;
98
+ getUserPromptsDir(): string;
98
99
  createPromptFolder(folderName: string): void;
99
100
  deletePromptFolder(folderName: string): void;
100
101
  updateAgent(agentId: string, updates: {
@@ -271,9 +271,7 @@ class AppService {
271
271
  if (!agent) {
272
272
  throw new errors_1.NotFoundError(`Agent with ID ${agentId} not found`);
273
273
  }
274
- const serviceName = agent.serviceName;
275
- let service = this.getAiServiceFromServiceName(serviceName);
276
- const result = await service.preparedPrompt(agent, promptName, variables || {}, true);
274
+ const result = await agent.preparedPrompt(promptName, variables || {}, true);
277
275
  return { result };
278
276
  }
279
277
  async listAgents() {
@@ -780,6 +778,9 @@ class AppService {
780
778
  throw new errors_1.OperationFailedError('Artifact name is required');
781
779
  room.publishArtifact(name, creator, body, viewers);
782
780
  }
781
+ getUserPromptsDir() {
782
+ return this.configService.getUserPromptsDir();
783
+ }
783
784
  createPromptFolder(folderName) {
784
785
  const targetDir = path.join(this.configService.getUserPromptsDir(), folderName);
785
786
  if (fs.existsSync(targetDir)) {
@@ -1033,7 +1034,7 @@ class AppService {
1033
1034
  logger_1.logger.warn('Cannot set up SSE callback for room without ID');
1034
1035
  return;
1035
1036
  }
1036
- room.setOnStateChange(() => {
1037
+ room.setOnStateChange('app-service', () => {
1037
1038
  const messages = room.getLatestRoomMessages(0, false);
1038
1039
  const latestMessage = messages.length > 0 ? messages[messages.length - 1] : undefined;
1039
1040
  const totalCost = room
@@ -1222,18 +1223,29 @@ class AppService {
1222
1223
  async convertLargePdfInBackground(artifactId, name, pdfDoc) {
1223
1224
  const pageCount = pdfDoc.getPageCount();
1224
1225
  logger_1.logger.log(`Converting large PDF with ${pageCount} pages concurrently for artifact ${artifactId}`);
1226
+ const perPageTimeoutMs = Number(process.env.PDF_CONVERT_PAGE_TIMEOUT_MS) || 2 * 60 * 1000;
1225
1227
  try {
1226
1228
  const conversionPromises = Array.from({ length: pageCount }, (_, pageIndex) => {
1227
1229
  const pageNum = pageIndex + 1;
1228
1230
  logger_1.logger.log(`Starting conversion for page ${pageNum}/${pageCount} for artifact ${artifactId}`);
1229
- return this.convertSinglePagePDF(pdfDoc, pageIndex)
1230
- .then((pageResponse) => ({
1231
- pageNum,
1232
- success: true,
1233
- cost: pageResponse.cost,
1234
- content: `**[Page ${pageNum}]** \n${pageResponse.markdownContent} \n`,
1235
- }))
1231
+ let timeoutHandle;
1232
+ const timeoutPromise = new Promise((_, reject) => {
1233
+ timeoutHandle = setTimeout(() => {
1234
+ reject(new Error(`Timed out after ${perPageTimeoutMs}ms waiting for page ${pageNum}`));
1235
+ }, perPageTimeoutMs);
1236
+ });
1237
+ return Promise.race([this.convertSinglePagePDF(pdfDoc, pageIndex), timeoutPromise])
1238
+ .then((pageResponse) => {
1239
+ clearTimeout(timeoutHandle);
1240
+ return {
1241
+ pageNum,
1242
+ success: true,
1243
+ cost: pageResponse.cost,
1244
+ content: `**[Page ${pageNum}]** \n${pageResponse.markdownContent} \n`,
1245
+ };
1246
+ })
1236
1247
  .catch((pageError) => {
1248
+ clearTimeout(timeoutHandle);
1237
1249
  logger_1.logger.error(`Error converting page ${pageNum}:`, pageError);
1238
1250
  return {
1239
1251
  pageNum,
@@ -46,7 +46,7 @@ exports.UsersService = void 0;
46
46
  const common_1 = require("@nestjs/common");
47
47
  const fs = __importStar(require("fs"));
48
48
  const path = __importStar(require("path"));
49
- const uuid_1 = require("uuid");
49
+ const crypto_1 = require("crypto");
50
50
  const logger_1 = require("../common/logger");
51
51
  let UsersService = class UsersService {
52
52
  usersFilePath;
@@ -80,7 +80,7 @@ let UsersService = class UsersService {
80
80
  fs.writeFileSync(this.usersFilePath, JSON.stringify(users, null, 2), 'utf-8');
81
81
  }
82
82
  generateUserId() {
83
- return (0, uuid_1.v4)();
83
+ return (0, crypto_1.randomUUID)();
84
84
  }
85
85
  createUser(phoneNumber) {
86
86
  const users = this.loadUsers();
@@ -7,6 +7,9 @@ export declare class ValidationError extends Error {
7
7
  export declare class OperationFailedError extends Error {
8
8
  constructor(message: string);
9
9
  }
10
+ export declare class RemoteFetchError extends Error {
11
+ constructor(message: string);
12
+ }
10
13
  export declare class InsufficientBalanceError extends Error {
11
14
  constructor(message: string);
12
15
  }
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.InsufficientBalanceError = exports.OperationFailedError = exports.ValidationError = exports.NotFoundError = void 0;
3
+ exports.InsufficientBalanceError = exports.RemoteFetchError = exports.OperationFailedError = exports.ValidationError = exports.NotFoundError = void 0;
4
4
  class NotFoundError extends Error {
5
5
  constructor(message) {
6
6
  super(message);
@@ -31,6 +31,16 @@ class OperationFailedError extends Error {
31
31
  }
32
32
  }
33
33
  exports.OperationFailedError = OperationFailedError;
34
+ class RemoteFetchError extends Error {
35
+ constructor(message) {
36
+ super(message);
37
+ this.name = 'RemoteFetchError';
38
+ if (Error.captureStackTrace) {
39
+ Error.captureStackTrace(this, RemoteFetchError);
40
+ }
41
+ }
42
+ }
43
+ exports.RemoteFetchError = RemoteFetchError;
34
44
  class InsufficientBalanceError extends Error {
35
45
  constructor(message) {
36
46
  super(message);
@@ -2,6 +2,7 @@ export declare class ConfigurationService {
2
2
  private dataDir;
3
3
  private promptsDir;
4
4
  private commonPromptsDir;
5
+ private commonLibraryDir;
5
6
  private userPromptsDir;
6
7
  private uploadDir;
7
8
  private userConfigDir;
@@ -19,6 +20,7 @@ export declare class ConfigurationService {
19
20
  exists(configName: string): boolean;
20
21
  getCommonPromptsDir(): string;
21
22
  getUserPromptsDir(): string;
23
+ getCommonLibraryDir(): string;
22
24
  getUserDataDir(): string;
23
25
  getUserId(): string;
24
26
  }
@@ -40,6 +40,7 @@ class ConfigurationService {
40
40
  dataDir;
41
41
  promptsDir;
42
42
  commonPromptsDir;
43
+ commonLibraryDir;
43
44
  userPromptsDir;
44
45
  uploadDir;
45
46
  userConfigDir;
@@ -62,6 +63,10 @@ class ConfigurationService {
62
63
  if (!fs.existsSync(this.commonPromptsDir)) {
63
64
  fs.mkdirSync(this.commonPromptsDir, { recursive: true });
64
65
  }
66
+ this.commonLibraryDir = path.resolve(commonDir, 'library');
67
+ if (!fs.existsSync(this.commonLibraryDir)) {
68
+ fs.mkdirSync(this.commonLibraryDir, { recursive: true });
69
+ }
65
70
  this.userDataDir = path.resolve(this.dataDir, 'user', this.userId);
66
71
  this.userPromptsDir = path.resolve(this.userDataDir, 'prompts');
67
72
  if (!fs.existsSync(this.userPromptsDir)) {
@@ -113,6 +118,9 @@ class ConfigurationService {
113
118
  getUserPromptsDir() {
114
119
  return this.userPromptsDir;
115
120
  }
121
+ getCommonLibraryDir() {
122
+ return this.commonLibraryDir;
123
+ }
116
124
  getUserDataDir() {
117
125
  return this.userDataDir;
118
126
  }
@@ -0,0 +1,14 @@
1
+ import { LibraryFile, LibraryPrompt } from '../../../shared/types/app.types';
2
+ export declare class LibraryService {
3
+ private getLibraryDir;
4
+ private assertSafeName;
5
+ private normalizeBaseUrl;
6
+ listLocalPrompts(): LibraryPrompt[];
7
+ listLocalFiles(folder: string): LibraryFile[];
8
+ getLocalFileContent(folder: string, file: string): string;
9
+ private fetchJson;
10
+ listRemotePrompts(baseUrl: string): Promise<LibraryPrompt[]>;
11
+ listRemoteFiles(baseUrl: string, folder: string): Promise<LibraryFile[]>;
12
+ getRemoteFileContent(baseUrl: string, folder: string, file: string): Promise<string>;
13
+ copyFromRemote(baseUrl: string, folder: string, userPromptsDir: string): Promise<void>;
14
+ }