briyah 1.0.9 → 1.1.0

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 (65) hide show
  1. package/README.md +109 -0
  2. package/dist/server/src/app/stripe.controller.js +3 -6
  3. package/dist/server/src/app/stripe.service.d.ts +2 -3
  4. package/dist/server/src/app/stripe.service.js +7 -9
  5. package/dist/server/src/app/transaction.service.d.ts +3 -3
  6. package/dist/server/src/app/transaction.service.js +11 -11
  7. package/dist/server/src/app.controller.js +8 -2
  8. package/dist/server/src/app.service.d.ts +5 -2
  9. package/dist/server/src/app.service.js +11 -2
  10. package/dist/server/src/sdk/index.d.ts +1 -1
  11. package/dist/server/src/story/story-message.service.d.ts +4 -2
  12. package/dist/server/src/story/story-message.service.js +27 -8
  13. package/dist/server/src/story/story.service.js +3 -19
  14. package/dist/shared/types/app.types.d.ts +17 -11
  15. package/docs/assets/hierarchy.js +1 -1
  16. package/docs/assets/navigation.js +1 -1
  17. package/docs/assets/search.js +1 -1
  18. package/docs/classes/Agent.html +13 -13
  19. package/docs/classes/Briyah.html +12 -12
  20. package/docs/classes/BriyahConfigService.html +5 -5
  21. package/docs/classes/Room.html +23 -23
  22. package/docs/classes/RoomMessage.html +10 -10
  23. package/docs/enums/MessageAction.html +3 -3
  24. package/docs/hierarchy.html +1 -1
  25. package/docs/index.html +16 -2
  26. package/docs/interfaces/AgentInfo.html +2 -2
  27. package/docs/interfaces/AgentMessagesResponse.html +2 -2
  28. package/docs/interfaces/AppService.html +162 -125
  29. package/docs/interfaces/Artifact.html +3 -3
  30. package/docs/interfaces/ArtifactMetadata.html +2 -2
  31. package/docs/interfaces/AttachDocumentResponse.html +2 -2
  32. package/docs/interfaces/BriyahConfigOptions.html +6 -6
  33. package/docs/interfaces/ChapterInfo.html +2 -2
  34. package/docs/interfaces/Character.html +2 -2
  35. package/docs/interfaces/CreateAgentResponse.html +2 -2
  36. package/docs/interfaces/CreateRoomResponse.html +2 -2
  37. package/docs/interfaces/CreateStoryResponse.html +2 -2
  38. package/docs/interfaces/FileList.html +2 -2
  39. package/docs/interfaces/LoggingOptions.html +5 -5
  40. package/docs/interfaces/Message.html +2 -2
  41. package/docs/interfaces/ModelInfo.html +2 -2
  42. package/docs/interfaces/PreparedPromptResponse.html +2 -2
  43. package/docs/interfaces/ProcessTextResponse.html +2 -2
  44. package/docs/interfaces/PromptFile.html +2 -2
  45. package/docs/interfaces/PromptFileContent.html +2 -2
  46. package/docs/interfaces/PromptFilesResponse.html +2 -2
  47. package/docs/interfaces/PromptFolder.html +2 -2
  48. package/docs/interfaces/PromptFoldersResponse.html +2 -2
  49. package/docs/interfaces/RoomDetails.html +2 -2
  50. package/docs/interfaces/RoomInfo.html +2 -2
  51. package/docs/interfaces/RoomMessagesResponse.html +2 -2
  52. package/docs/interfaces/StoryErrorEvent.html +12 -0
  53. package/docs/interfaces/StoryIdea.html +2 -2
  54. package/docs/interfaces/StoryInfo.html +2 -2
  55. package/docs/interfaces/StoryIntroduceCharacterEvent.html +12 -0
  56. package/docs/interfaces/StoryProgressChapterEvent.html +11 -0
  57. package/docs/interfaces/StoryState.html +5 -5
  58. package/docs/interfaces/StoryStateEvent.html +10 -0
  59. package/docs/interfaces/Transaction.html +10 -0
  60. package/docs/interfaces/TransactionHistoryResponse.html +3 -0
  61. package/docs/modules.html +1 -1
  62. package/docs/types/PromptScope.html +1 -1
  63. package/package.json +1 -1
  64. package/docs/interfaces/StoryMessageUpdate.html +0 -6
  65. package/docs/interfaces/StorySuggestion.html +0 -9
package/README.md CHANGED
@@ -352,6 +352,115 @@ const messages = await appService.getRoomMessages(room.roomId);
352
352
  console.log(`Messages: ${messages.messages.length}`);
353
353
  ```
354
354
 
355
+ ### Example 6: Story Message Emitter
356
+
357
+ The story message emitter delivers real-time events during gameplay. Subscribe to it after creating the story but before the first player turn, so no events are missed.
358
+
359
+ ```typescript
360
+ import type {
361
+ StoryStateEvent,
362
+ StoryIntroduceCharacterEvent,
363
+ StoryProgressChapterEvent,
364
+ StoryErrorEvent,
365
+ } from 'briyah';
366
+
367
+ const app = briyah.getAppService('user-123');
368
+
369
+ const story = await app.createStory(
370
+ 'The Lost Kingdom',
371
+ 'A medieval fantasy where ancient ruins hold a terrible secret',
372
+ 'A disgraced knight seeking redemption'
373
+ );
374
+
375
+ const emitter = app.getStoryMessageEmitter(story.id);
376
+
377
+ // Fires after every turn with the full updated game state.
378
+ emitter.on('story-state', async (event: StoryStateEvent) => {
379
+ const { state } = event;
380
+ console.log('Latest message:', state.latestRoomMessage?.content);
381
+
382
+ // Detect the player's turn by comparing speaker names.
383
+ // Do NOT use state.humanPrompt for this — it is a UI display string,
384
+ // not a reliable turn indicator.
385
+ if (state.currentSpeaker === state.userAgentName) {
386
+ const input = await promptPlayer(state.humanPrompt);
387
+ await app.respondToStory(story.id, input);
388
+ }
389
+ });
390
+
391
+ // Fires when the narrator wants to introduce a new character.
392
+ // The host app should present this to the player before acting.
393
+ // Accept by calling introduceCharacterToStory, or decline with declineCharacter.
394
+ emitter.on('suggest-introduce-character', async (event: StoryIntroduceCharacterEvent) => {
395
+ const accept = await askPlayer(`Add ${event.characterName} to the story?`);
396
+ if (accept) {
397
+ await app.introduceCharacterToStory(story.id, event.characterName!, '', undefined, true);
398
+ } else {
399
+ await app.declineCharacter(story.id, event.characterName!);
400
+ }
401
+ });
402
+
403
+ // Fires when the narrator wants to advance to the next chapter.
404
+ // Call progressStory to accept. Ignoring the event stays in the current chapter —
405
+ // there is no explicit rejection call.
406
+ emitter.on('suggest-progress-chapter', async (_event: StoryProgressChapterEvent) => {
407
+ const accept = await askPlayer('The narrator suggests ending this chapter. Continue?');
408
+ if (accept) {
409
+ await app.progressStory(story.id);
410
+ }
411
+ });
412
+
413
+ // Fires on fatal errors during room processing.
414
+ // Named 'story-error' rather than 'error' to avoid Node.js throwing when no
415
+ // listener is attached.
416
+ emitter.on('story-error', (event: StoryErrorEvent) => {
417
+ if (event.errorType === 'InsufficientBalanceError') {
418
+ console.error('Out of credits:', event.message);
419
+ } else {
420
+ console.error(`Story error [${event.errorType}]:`, event.message);
421
+ }
422
+ });
423
+ ```
424
+
425
+ ### Example 7: Recording Payments and Managing Balance
426
+
427
+ Briyah does not process payments itself — your application handles the payment provider interaction. Once a payment is confirmed, use `AppService` to record the transaction, credit the user's balance, and restart any stories that stalled due to insufficient funds.
428
+
429
+ ```typescript
430
+ const app = briyah.getAppService(userId);
431
+
432
+ // --- When your payment provider initiates a charge ---
433
+ // Record it as pending so the transaction log stays consistent.
434
+ await app.recordTransaction(amount, paymentIntentId, 'pending');
435
+
436
+ // --- When your payment provider webhook confirms success ---
437
+ await app.updateTransactionStatus(paymentIntentId, 'succeeded');
438
+ await app.addBalance(amount);
439
+
440
+ // Resume any stories that paused mid-turn due to InsufficientBalanceError.
441
+ await app.resumePausedStories();
442
+
443
+ // --- When a payment fails or is cancelled ---
444
+ await app.updateTransactionStatus(paymentIntentId, 'failed');
445
+
446
+ // --- Querying balance and history ---
447
+ const balance = app.getBalance();
448
+
449
+ const { transactions, total } = await app.getTransactions(50, 0);
450
+
451
+ const tx = await app.getTransactionByPaymentId(paymentIntentId);
452
+ console.log(tx?.status); // 'pending' | 'succeeded' | 'failed' | 'cancelled'
453
+ ```
454
+
455
+ To push real-time balance updates to a connected client (e.g. via SSE), subscribe to the balance emitter before crediting the user:
456
+
457
+ ```typescript
458
+ const emitter = app.getBalanceMessageEmitter(userId);
459
+ emitter.on('update', (newBalance: number) => {
460
+ // Push newBalance to the client
461
+ });
462
+ ```
463
+
355
464
  ## Data Storage
356
465
 
357
466
  Briyah stores data in the following structure:
@@ -30,16 +30,14 @@ let StripeController = class StripeController {
30
30
  const userId = req.user.userId;
31
31
  const { amount } = body;
32
32
  const appService = this.userServiceManager.getAppService(userId);
33
- const transactionService = appService.getTransactionService();
34
- const result = await this.stripeService.createPaymentIntent(userId, amount, transactionService);
33
+ const result = await this.stripeService.createPaymentIntent(userId, amount, appService);
35
34
  return result;
36
35
  }
37
36
  async createCheckoutSession(req, body) {
38
37
  const userId = req.user.userId;
39
38
  const { amount } = body;
40
39
  const appService = this.userServiceManager.getAppService(userId);
41
- const transactionService = appService.getTransactionService();
42
- const result = await this.stripeService.createCheckoutSession(userId, amount, transactionService);
40
+ const result = await this.stripeService.createCheckoutSession(userId, amount, appService);
43
41
  return result;
44
42
  }
45
43
  async getStripeConfig() {
@@ -95,8 +93,7 @@ let StripeController = class StripeController {
95
93
  const parsedLimit = limit ? parseInt(limit, 10) : 50;
96
94
  const parsedOffset = offset ? parseInt(offset, 10) : 0;
97
95
  const appService = this.userServiceManager.getAppService(userId);
98
- const transactionService = appService.getTransactionService();
99
- const result = await transactionService.getTransactions(parsedLimit, parsedOffset);
96
+ const result = await appService.getTransactions(parsedLimit, parsedOffset);
100
97
  return result;
101
98
  }
102
99
  };
@@ -1,5 +1,4 @@
1
1
  import Stripe from 'stripe';
2
- import { TransactionService } from './transaction.service';
3
2
  import { AppService } from '../app.service';
4
3
  type StripeInstance = ReturnType<typeof Stripe>;
5
4
  type StripeEvent = ReturnType<StripeInstance['webhooks']['constructEvent']>;
@@ -11,11 +10,11 @@ export declare class StripeService {
11
10
  private publishableKey;
12
11
  private webhookSecret;
13
12
  constructor();
14
- createPaymentIntent(userId: string, amount: number, transactionService: TransactionService): Promise<{
13
+ createPaymentIntent(userId: string, amount: number, appService: AppService): Promise<{
15
14
  clientSecret: string;
16
15
  publishableKey: string;
17
16
  }>;
18
- createCheckoutSession(userId: string, amount: number, transactionService: TransactionService): Promise<{
17
+ createCheckoutSession(userId: string, amount: number, appService: AppService): Promise<{
19
18
  url: string;
20
19
  }>;
21
20
  getStripeConfig(): {
@@ -40,7 +40,7 @@ let StripeService = class StripeService {
40
40
  this.minPaymentAmount = parseFloat(process.env.MIN_PAYMENT_AMOUNT || '5.00');
41
41
  this.maxPaymentAmount = parseFloat(process.env.MAX_PAYMENT_AMOUNT || '500.00');
42
42
  }
43
- async createPaymentIntent(userId, amount, transactionService) {
43
+ async createPaymentIntent(userId, amount, appService) {
44
44
  if (!amount || amount <= 0) {
45
45
  throw new common_1.BadRequestException('Amount must be greater than 0');
46
46
  }
@@ -62,7 +62,7 @@ let StripeService = class StripeService {
62
62
  enabled: true,
63
63
  },
64
64
  });
65
- await transactionService.recordTransaction(amount, paymentIntent.id, 'pending');
65
+ await appService.recordTransaction(amount, paymentIntent.id, 'pending');
66
66
  return {
67
67
  clientSecret: paymentIntent.client_secret,
68
68
  publishableKey: this.publishableKey,
@@ -73,7 +73,7 @@ let StripeService = class StripeService {
73
73
  throw new common_1.InternalServerErrorException('Failed to create payment intent');
74
74
  }
75
75
  }
76
- async createCheckoutSession(userId, amount, transactionService) {
76
+ async createCheckoutSession(userId, amount, appService) {
77
77
  if (!amount || amount <= 0) {
78
78
  throw new common_1.BadRequestException('Amount must be greater than 0');
79
79
  }
@@ -113,7 +113,7 @@ let StripeService = class StripeService {
113
113
  },
114
114
  });
115
115
  if (session.payment_intent) {
116
- await transactionService.recordTransaction(amount, session.payment_intent, 'pending');
116
+ await appService.recordTransaction(amount, session.payment_intent, 'pending');
117
117
  }
118
118
  return {
119
119
  url: session.url,
@@ -148,8 +148,7 @@ let StripeService = class StripeService {
148
148
  }
149
149
  const amount = paymentIntent.amount / 100;
150
150
  logger_1.logger.log(`[Stripe Webhook] Amount: $${amount.toFixed(2)}`);
151
- const transactionService = appService.getTransactionService();
152
- const existingTransaction = await transactionService.getTransactionByPaymentIntent(paymentIntent.id);
151
+ const existingTransaction = await appService.getTransactionByPaymentId(paymentIntent.id);
153
152
  logger_1.logger.log(`[Stripe Webhook] Existing transaction:`, existingTransaction);
154
153
  if (existingTransaction?.status === 'succeeded') {
155
154
  logger_1.logger.log(`Transaction ${paymentIntent.id} already processed, skipping`);
@@ -162,7 +161,7 @@ let StripeService = class StripeService {
162
161
  const balanceAfter = await appService.getBalance();
163
162
  logger_1.logger.log(`[Stripe Webhook] Balance after: $${balanceAfter.toFixed(2)}`);
164
163
  logger_1.logger.log(`[Stripe Webhook] Updating transaction status to 'succeeded'`);
165
- await transactionService.updateTransactionStatus(paymentIntent.id, 'succeeded');
164
+ await appService.updateTransactionStatus(paymentIntent.id, 'succeeded');
166
165
  logger_1.logger.log(`[Stripe Webhook] Checking for paused stories to resume...`);
167
166
  const resumedCount = await appService.resumePausedStories();
168
167
  if (resumedCount > 0) {
@@ -182,8 +181,7 @@ let StripeService = class StripeService {
182
181
  logger_1.logger.error('Payment Intent missing userId in metadata:', paymentIntent.id);
183
182
  return;
184
183
  }
185
- const transactionService = appService.getTransactionService();
186
- await transactionService.updateTransactionStatus(paymentIntent.id, 'failed');
184
+ await appService.updateTransactionStatus(paymentIntent.id, 'failed');
187
185
  logger_1.logger.log(`Payment failed for user ${userId}: ${paymentIntent.id}`);
188
186
  }
189
187
  catch (error) {
@@ -5,9 +5,9 @@ export declare class TransactionService {
5
5
  private configService;
6
6
  private transactionsDir;
7
7
  constructor(userId: string, configService: ConfigurationService);
8
- recordTransaction(amount: number, stripePaymentIntentId: string, status?: 'pending' | 'succeeded' | 'failed' | 'cancelled'): Promise<Transaction>;
9
- updateTransactionStatus(paymentIntentId: string, status: 'pending' | 'succeeded' | 'failed' | 'cancelled'): Promise<void>;
10
- getTransactionByPaymentIntent(paymentIntentId: string): Promise<Transaction | null>;
8
+ recordTransaction(amount: number, paymentId: string, status?: 'pending' | 'succeeded' | 'failed' | 'cancelled'): Promise<Transaction>;
9
+ updateTransactionStatus(paymentId: string, status: 'pending' | 'succeeded' | 'failed' | 'cancelled'): Promise<void>;
10
+ getTransactionByPaymentId(paymentId: string): Promise<Transaction | null>;
11
11
  getTransactions(limit?: number, offset?: number): Promise<{
12
12
  transactions: Transaction[];
13
13
  total: number;
@@ -51,19 +51,19 @@ class TransactionService {
51
51
  fs.mkdirSync(this.transactionsDir, { recursive: true });
52
52
  }
53
53
  }
54
- async recordTransaction(amount, stripePaymentIntentId, status = 'pending') {
54
+ async recordTransaction(amount, paymentId, status = 'pending') {
55
55
  const timestamp = Date.now();
56
56
  const transaction = {
57
57
  id: (0, zod_1.uuidv4)().toString(),
58
58
  userId: this.userId,
59
59
  amount,
60
60
  currency: 'usd',
61
- stripePaymentIntentId,
61
+ paymentId,
62
62
  status,
63
63
  createdAt: timestamp,
64
64
  updatedAt: timestamp,
65
65
  };
66
- const filename = `${timestamp}-${stripePaymentIntentId}.json`;
66
+ const filename = `${timestamp}-${paymentId}.json`;
67
67
  const filePath = path.join(this.transactionsDir, filename);
68
68
  try {
69
69
  fs.writeFileSync(filePath, JSON.stringify(transaction, null, 2), 'utf-8');
@@ -74,31 +74,31 @@ class TransactionService {
74
74
  throw error;
75
75
  }
76
76
  }
77
- async updateTransactionStatus(paymentIntentId, status) {
77
+ async updateTransactionStatus(paymentId, status) {
78
78
  try {
79
- const transaction = await this.getTransactionByPaymentIntent(paymentIntentId);
79
+ const transaction = await this.getTransactionByPaymentId(paymentId);
80
80
  if (!transaction) {
81
- logger_1.logger.error(`Transaction not found for payment intent ${paymentIntentId}`);
81
+ logger_1.logger.error(`Transaction not found for payment ID ${paymentId}`);
82
82
  return;
83
83
  }
84
84
  transaction.status = status;
85
85
  transaction.updatedAt = Date.now();
86
86
  const files = fs.readdirSync(this.transactionsDir);
87
- const matchingFile = files.find((file) => file.includes(paymentIntentId));
87
+ const matchingFile = files.find((file) => file.includes(paymentId));
88
88
  if (matchingFile) {
89
89
  const filePath = path.join(this.transactionsDir, matchingFile);
90
90
  fs.writeFileSync(filePath, JSON.stringify(transaction, null, 2), 'utf-8');
91
91
  }
92
92
  }
93
93
  catch (error) {
94
- logger_1.logger.error(`Error updating transaction status for ${paymentIntentId}:`, error);
94
+ logger_1.logger.error(`Error updating transaction status for ${paymentId}:`, error);
95
95
  throw error;
96
96
  }
97
97
  }
98
- async getTransactionByPaymentIntent(paymentIntentId) {
98
+ async getTransactionByPaymentId(paymentId) {
99
99
  try {
100
100
  const files = fs.readdirSync(this.transactionsDir);
101
- const matchingFile = files.find((file) => file.includes(paymentIntentId));
101
+ const matchingFile = files.find((file) => file.includes(paymentId));
102
102
  if (!matchingFile) {
103
103
  return null;
104
104
  }
@@ -107,7 +107,7 @@ class TransactionService {
107
107
  return JSON.parse(content);
108
108
  }
109
109
  catch (error) {
110
- logger_1.logger.error(`Error getting transaction for payment intent ${paymentIntentId}:`, error);
110
+ logger_1.logger.error(`Error getting transaction for payment ID ${paymentId}:`, error);
111
111
  return null;
112
112
  }
113
113
  }
@@ -1415,10 +1415,16 @@ let AppController = class AppController {
1415
1415
  const updateHandler = (data) => {
1416
1416
  subscriber.next({ data });
1417
1417
  };
1418
- emitter.on('update', updateHandler);
1418
+ emitter.on('story-state', updateHandler);
1419
+ emitter.on('suggest-introduce-character', updateHandler);
1420
+ emitter.on('suggest-progress-chapter', updateHandler);
1421
+ emitter.on('story-error', updateHandler);
1419
1422
  return () => {
1420
1423
  logger_1.logger.log(`[SSE] Cleanup for story ${storyId}`);
1421
- emitter.off('update', updateHandler);
1424
+ emitter.off('story-state', updateHandler);
1425
+ emitter.off('suggest-introduce-character', updateHandler);
1426
+ emitter.off('suggest-progress-chapter', updateHandler);
1427
+ emitter.off('story-error', updateHandler);
1422
1428
  };
1423
1429
  });
1424
1430
  }
@@ -21,7 +21,7 @@ import { TransactionService } from './app/transaction.service';
21
21
  import { AgentFactory } from './ai/agent-factory';
22
22
  import { RoomFactory } from './room/room-factory';
23
23
  import { EventEmitter } from 'events';
24
- import { AgentInfo, RoomInfo, RoomDetails, CreateRoomResponse, FileList, PromptFileContent, PromptFoldersResponse, PromptFilesResponse, PromptScope, ProcessTextResponse, PreparedPromptResponse, AttachDocumentResponse, AgentMessagesResponse, RoomMessagesResponse, StoryInfo, StoryState, Character } from '../../shared/types/app.types';
24
+ import { AgentInfo, RoomInfo, RoomDetails, CreateRoomResponse, FileList, PromptFileContent, PromptFoldersResponse, PromptFilesResponse, PromptScope, ProcessTextResponse, PreparedPromptResponse, AttachDocumentResponse, AgentMessagesResponse, RoomMessagesResponse, StoryInfo, StoryState, Character, Transaction, TransactionHistoryResponse } from '../../shared/types/app.types';
25
25
  import { RoomMessage } from './room/message';
26
26
  export declare class AppService {
27
27
  private readonly aiFactoryService;
@@ -166,7 +166,10 @@ export declare class AppService {
166
166
  savePlotPlan(storyId: string, content: string): Promise<void>;
167
167
  getBalance(): number;
168
168
  addBalance(amount: number): void;
169
- getTransactionService(): TransactionService;
169
+ recordTransaction(amount: number, paymentId: string, status?: 'pending' | 'succeeded' | 'failed' | 'cancelled'): Promise<Transaction>;
170
+ updateTransactionStatus(paymentId: string, status: 'pending' | 'succeeded' | 'failed' | 'cancelled'): Promise<void>;
171
+ getTransactionByPaymentId(paymentId: string): Promise<Transaction | null>;
172
+ getTransactions(limit?: number, offset?: number): Promise<TransactionHistoryResponse>;
170
173
  listUserArtifacts(): ArtifactMetadata[];
171
174
  getUserArtifact(artifactId: string): string | Buffer | null;
172
175
  createUserArtifact(name: string, content: string): string;
@@ -1155,8 +1155,17 @@ class AppService {
1155
1155
  addBalance(amount) {
1156
1156
  return this.balanceService.addBalance(amount);
1157
1157
  }
1158
- getTransactionService() {
1159
- return this.transactionService;
1158
+ async recordTransaction(amount, paymentId, status = 'pending') {
1159
+ return this.transactionService.recordTransaction(amount, paymentId, status);
1160
+ }
1161
+ async updateTransactionStatus(paymentId, status) {
1162
+ return this.transactionService.updateTransactionStatus(paymentId, status);
1163
+ }
1164
+ async getTransactionByPaymentId(paymentId) {
1165
+ return this.transactionService.getTransactionByPaymentId(paymentId);
1166
+ }
1167
+ async getTransactions(limit = 50, offset = 0) {
1168
+ return this.transactionService.getTransactions(limit, offset);
1160
1169
  }
1161
1170
  listUserArtifacts() {
1162
1171
  return this.artifactService.listArtifacts();
@@ -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, StorySuggestion, StoryMessageUpdate, 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, 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';
@@ -1,10 +1,12 @@
1
1
  import { EventEmitter } from 'events';
2
- import { StoryMessageUpdate } from '../../../shared/types/app.types';
2
+ import { StoryState } from '../../../shared/types/app.types';
3
3
  export declare class StoryMessageService {
4
4
  private messageEmitters;
5
5
  getOrCreateEmitter(storyId: string): EventEmitter;
6
6
  getEmitter(storyId: string): EventEmitter | undefined;
7
- emitUpdate(storyId: string, update: StoryMessageUpdate): void;
7
+ emitStoryState(storyId: string, state: StoryState): void;
8
+ emitIntroduceCharacter(storyId: string, characterName?: string): void;
9
+ emitProgressChapter(storyId: string): void;
8
10
  emitError(storyId: string, error: Error): void;
9
11
  cleanup(storyId: string): void;
10
12
  }
@@ -22,25 +22,44 @@ let StoryMessageService = class StoryMessageService {
22
22
  getEmitter(storyId) {
23
23
  return this.messageEmitters.get(storyId);
24
24
  }
25
- emitUpdate(storyId, update) {
25
+ emitStoryState(storyId, state) {
26
26
  const emitter = this.messageEmitters.get(storyId);
27
27
  if (emitter) {
28
- const updateWithTimestamp = {
28
+ const payload = { type: 'story-state', state, timestamp: Date.now() };
29
+ emitter.emit('story-state', payload);
30
+ }
31
+ }
32
+ emitIntroduceCharacter(storyId, characterName) {
33
+ const emitter = this.messageEmitters.get(storyId);
34
+ if (emitter) {
35
+ const payload = {
36
+ type: 'suggest-introduce-character',
37
+ characterName,
29
38
  timestamp: Date.now(),
30
- ...update
31
39
  };
32
- emitter.emit('update', updateWithTimestamp);
40
+ emitter.emit('suggest-introduce-character', payload);
33
41
  }
34
42
  }
35
- emitError(storyId, error) {
43
+ emitProgressChapter(storyId) {
36
44
  const emitter = this.messageEmitters.get(storyId);
37
45
  if (emitter) {
38
- emitter.emit('update', {
46
+ const payload = {
47
+ type: 'suggest-progress-chapter',
39
48
  timestamp: Date.now(),
40
- type: 'error',
49
+ };
50
+ emitter.emit('suggest-progress-chapter', payload);
51
+ }
52
+ }
53
+ emitError(storyId, error) {
54
+ const emitter = this.messageEmitters.get(storyId);
55
+ if (emitter) {
56
+ const payload = {
57
+ type: 'story-error',
41
58
  errorType: error.name,
42
59
  message: error.message,
43
- });
60
+ timestamp: Date.now(),
61
+ };
62
+ emitter.emit('story-error', payload);
44
63
  }
45
64
  }
46
65
  cleanup(storyId) {
@@ -138,10 +138,7 @@ let StoryService = class StoryService {
138
138
  totalInputTokens: story.totalInputTokens || 0,
139
139
  totalOutputTokens: story.totalOutputTokens || 0,
140
140
  };
141
- this.messageService.emitUpdate(storyId, {
142
- type: 'state',
143
- state: stateUpdate
144
- });
141
+ this.messageService.emitStoryState(storyId, stateUpdate);
145
142
  }
146
143
  catch (error) {
147
144
  logger_1.logger.error(`Error emitting story state update for ${storyId}:`, error);
@@ -1627,13 +1624,7 @@ let StoryService = class StoryService {
1627
1624
  story.declinedCharacters = [];
1628
1625
  this.storyStore.updateStoryMetadata(storyId, story);
1629
1626
  }
1630
- this.messageService.emitUpdate(storyId, {
1631
- type: 'suggestion',
1632
- suggestion: {
1633
- type: 'progress_chapter',
1634
- timestamp: Date.now()
1635
- }
1636
- });
1627
+ this.messageService.emitProgressChapter(storyId);
1637
1628
  return;
1638
1629
  }
1639
1630
  let agentCompactionThreshold = Number(process.env.AGENT_COMPACTION_THRESHOLD) || 150000;
@@ -1647,14 +1638,7 @@ let StoryService = class StoryService {
1647
1638
  logger_1.logger.log(`Character ${newCharacterName} was declined, skipping prompt`);
1648
1639
  return;
1649
1640
  }
1650
- this.messageService.emitUpdate(storyId, {
1651
- type: 'suggestion',
1652
- suggestion: {
1653
- type: 'introduce_character',
1654
- characterName: newCharacterName,
1655
- timestamp: Date.now()
1656
- }
1657
- });
1641
+ this.messageService.emitIntroduceCharacter(storyId, newCharacterName);
1658
1642
  }
1659
1643
  return;
1660
1644
  }
@@ -241,19 +241,25 @@ export interface StoryState {
241
241
  totalInputTokens: number;
242
242
  totalOutputTokens: number;
243
243
  }
244
- export interface StorySuggestion {
245
- type: 'introduce_character' | 'progress_chapter';
244
+ export interface StoryStateEvent {
245
+ type: 'story-state';
246
+ state: StoryState;
247
+ timestamp: number;
248
+ }
249
+ export interface StoryIntroduceCharacterEvent {
250
+ type: 'suggest-introduce-character';
246
251
  characterName?: string;
247
252
  timestamp: number;
248
253
  }
249
- export interface StoryMessageUpdate {
250
- type: 'state' | 'suggestion' | 'error';
251
- state?: StoryState;
252
- suggestion?: StorySuggestion;
253
- error?: {
254
- message: string;
255
- errorType?: string;
256
- };
254
+ export interface StoryProgressChapterEvent {
255
+ type: 'suggest-progress-chapter';
256
+ timestamp: number;
257
+ }
258
+ export interface StoryErrorEvent {
259
+ type: 'story-error';
260
+ message: string;
261
+ errorType?: string;
262
+ timestamp: number;
257
263
  }
258
264
  export interface ChaptersResponse {
259
265
  chapters: ChapterInfo[];
@@ -283,7 +289,7 @@ export interface Transaction {
283
289
  userId: string;
284
290
  amount: number;
285
291
  currency: string;
286
- stripePaymentIntentId: string;
292
+ paymentId: string;
287
293
  status: 'pending' | 'succeeded' | 'failed' | 'cancelled';
288
294
  createdAt: number;
289
295
  updatedAt: number;
@@ -1 +1 @@
1
- window.hierarchyData = "eJx1jc0KgzAQhN9lzrFWwWLyDr30Kh6CWWtoTCCbniTvXtI/pNDTwM63822IISSGGjopR4FIs6Mp2eAZakMnZQmvV4LCmZj1lSBws95Atd1J4B4dFKxPFGc9Eddv6rCk1UFgcpoZColNVd6qL1rKxToTyUMNzbHvxyxQcue8hLD+epu2/3if68T1Dvsrfh1yzg8aB1Bi"
1
+ window.hierarchyData = "eJx1jc0KwjAQhN9lzqklLRbdd/DitfQQ2tUG0wSy8VTy7hL/KIKngZ1v51sRQ0gC6jvdDgqRL47HZIMX0IpOtyW8WRiEE4uYK0PhZv0Eavadwj06EKxPHC9mZKnf1G5Oi4PC6IwICEmmqrxVX7SUs3VTZA/qtdbHISuU3DjPISy/Xt0cPt7nOku9wf6KX4ec8wP/YVA+"
@@ -1 +1 @@
1
- window.navigationData = "eJyN1sFO4zAQBuB38blalkrA0htbhIQEAtHdE+JgOdPEIrEte4qoEO+OEtJgN/bY1/y/v6buOOnzB0N4R7Zi9+Acr+FKoNSKLZjh2LAVA7Xr3EkQ/mqwa9mCvUpVsdWfz8VkXNWg8GetaLlz4E6Gy+Gq06W/7q+Ve97MF35fz69ca7WV9QbsmxSQYoISZT5p3c2R/mpu1bhN8cVjSBnDRt2qrf4RpEKwWy4O29inIbE8Oz8mxo9yT+CMVg7S3HGTpI2ZbbHvTTGJWJRbLjBOjGEJcA/IK46chA4lEkTkornWYteBQnrLolUK90fvwfSnx0XlSI9i1w03CDY5Kl6eYSwXCDaFfKckYYEjDLNEbl2kl2f7Y1Og+rU8ukFt9wVq0KPYG9nCnXTxkT6EFHCn61oqcj7CCoXNnkGeEn0EHS3XFbTJuZpSini0YLiF6tHqztBTEa/SuBbg3D94z8mzXobtDPY/Vkob4zJkrRUGr8KoNbbKSPphHukVsLqtEmffL5RCRXcYNim6P9XXgFy28SPh5TkmOc+HMAcUvVBjRQoeHjC3FcRfYVOaJ1LfbkqzxHjb/03FMf7l5rUsukESG+I8sqtrcOF/0pk0dfKjuhHaeDeFezPN5hAdCb8vL07Plp8vX/pW2ak="
1
+ window.navigationData = "eJyNlk1P4zAQhv+Lz9WyVAJ2e2MLCCTQVpQb4mA508QisS17iqhW/PdVQpo6iT321e87j5PJfOT1H0P4RLZiT+AcL+FaoNSKLZjhWLEVA7Vv3NlI/FFhU7MFe5eqYKtfX4uBcV2CwlOsqLlz4M6643HU+dKP+2PlgVfzwO/zdORaq50st2A/pIAYZmSimM9aN3NIe5qK6tMUDu5FitEl6kHt9IkgFYLdcXFMY6uOEcuLyymiv8o9gzNaOYjjpk4SbcwsxT5vkEmIRbnjAsOIXswBPAHygiMnQUcTCUTkorrRYt+AQjplQSsF90vvr2m7xwXJAR+FXVfcINhoqXh6AmO5QLAxyLdKIixwhK6WyNQFfGls2zYZVN+Whm5R20MGdeSjsHeyhkfpwiV9FCnAoy5Lqcj6GFso2GwGeZTgCJqE6wLqaF0NKoXYWDDcQrGxujF0VYStNFwLcO4FPlPkmS+BbQy2HytG6+U8yForHK3CIKt35SHpYR7wZWB1XUR63zfkgrKecOyk0G1X3wByWYdbwtNTmGg9H8UUIGuhhowUuBswt9Zqe/sRK5aJJ4l7KCC8EQc1jYgla1AzEGh1sRcwrJDEG0YCkhdtrC4tONfvu8QtIXfyii1yDH/vk5wHSTzdyUPhXixXjk9+0j2Up2di7qVLbsS4PT0ctkIbj4oHM0yDTpoQfv6+Or9Yfr39ByjAXqw="