@rimori/client 2.5.44-next.0 → 2.5.44

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.
@@ -42,6 +42,12 @@ export declare class Logger {
42
42
  * @param args - Console arguments
43
43
  */
44
44
  private handleConsoleCall;
45
+ /**
46
+ * Convert an Error into a plain, JSON-serializable object.
47
+ * @param error - Error to serialize
48
+ * @returns Plain object with the error's name, message and stack
49
+ */
50
+ private serializeError;
45
51
  /**
46
52
  * Get browser and system information for debugging.
47
53
  * @returns Object with browser and system information
@@ -183,8 +183,14 @@ export class Logger {
183
183
  // Convert console arguments to message and data
184
184
  const message = args
185
185
  .map((arg) => {
186
- if (typeof arg !== 'object')
186
+ if (typeof arg !== 'object' || arg === null)
187
187
  return arg;
188
+ // Error objects have non-enumerable message/stack/name, so JSON.stringify
189
+ // produces "{}". Serialize them explicitly so app logs (e.g. on mobile)
190
+ // keep the actual error message instead of an empty object.
191
+ if (arg instanceof Error) {
192
+ return arg.stack || `${arg.name}: ${arg.message}`;
193
+ }
188
194
  try {
189
195
  return JSON.stringify(arg);
190
196
  }
@@ -193,10 +199,23 @@ export class Logger {
193
199
  }
194
200
  })
195
201
  .join(' ');
196
- const data = args.length > 1 ? args.slice(1) : undefined;
202
+ // Convert any Error objects in `data` to plain objects so their
203
+ // message/stack survive JSON serialization over the event bus
204
+ // (raw Error objects serialize to "{}").
205
+ const data = args.length > 1
206
+ ? args.slice(1).map((arg) => (arg instanceof Error ? this.serializeError(arg) : arg))
207
+ : undefined;
197
208
  const entry = await this.createLogEntry(level, message, data);
198
209
  this.addLogEntry(entry);
199
210
  }
211
+ /**
212
+ * Convert an Error into a plain, JSON-serializable object.
213
+ * @param error - Error to serialize
214
+ * @returns Plain object with the error's name, message and stack
215
+ */
216
+ serializeError(error) {
217
+ return { name: error.name, message: error.message, stack: error.stack };
218
+ }
200
219
  /**
201
220
  * Get browser and system information for debugging.
202
221
  * @returns Object with browser and system information
@@ -2,6 +2,13 @@ import { Language } from './PluginModule';
2
2
  import { Tool } from '../../fromRimori/PluginTypes';
3
3
  import { RimoriCommunicationHandler } from '../CommunicationHandler';
4
4
  export type OnStreamedObjectResult<T = any> = (result: T, isLoading: boolean) => void;
5
+ /**
6
+ * Shape + size preset for generated images.
7
+ * Shape sets the aspect ratio (square 1:1, portrait 2:3, landscape 3:2); size sets the
8
+ * stored resolution — `small` ≈ 200px on the longest edge, `medium` ≈ 512px, `big` keeps
9
+ * the native HD resolution.
10
+ */
11
+ export type ImageAspectRatio = 'square_small' | 'square_medium' | 'square_big' | 'portrait_small' | 'portrait_medium' | 'portrait_big' | 'landscape_small' | 'landscape_medium' | 'landscape_big';
5
12
  type PrimitiveType = 'string' | 'number' | 'boolean';
6
13
  type ObjectToolParameterType = PrimitiveType | {
7
14
  [key: string]: ObjectToolParameter;
@@ -114,11 +121,14 @@ export declare class AIModule {
114
121
  * Generate an image from a text prompt using AI.
115
122
  * @param params.prompt The prompt describing the image to generate.
116
123
  * @param params.cache Whether to cache the result by prompt hash (default: true).
117
- * @returns `{ url, cached }` where `url` is either a data URL or a stored CDN URL.
124
+ * @param params.aspectRatio Shape + size preset for the image (default: 'square_medium').
125
+ * `small` ≈ 200px on the longest edge, `medium` ≈ 512px, `big` keeps native HD resolution.
126
+ * @returns `{ url, cached }` where `url` is a stored CDN URL.
118
127
  */
119
128
  getImage(params: {
120
129
  prompt: string;
121
130
  cache?: boolean;
131
+ aspectRatio?: ImageAspectRatio;
122
132
  }): Promise<{
123
133
  url: string;
124
134
  cached: boolean;
@@ -119,15 +119,18 @@ export class AIModule {
119
119
  * Generate an image from a text prompt using AI.
120
120
  * @param params.prompt The prompt describing the image to generate.
121
121
  * @param params.cache Whether to cache the result by prompt hash (default: true).
122
- * @returns `{ url, cached }` where `url` is either a data URL or a stored CDN URL.
122
+ * @param params.aspectRatio Shape + size preset for the image (default: 'square_medium').
123
+ * `small` ≈ 200px on the longest edge, `medium` ≈ 512px, `big` keeps native HD resolution.
124
+ * @returns `{ url, cached }` where `url` is a stored CDN URL.
123
125
  */
124
126
  async getImage(params) {
125
- const { prompt, cache = true } = params;
127
+ const { prompt, cache = true, aspectRatio = 'square_medium' } = params;
126
128
  const response = await this.controller.fetchBackend('/ai/image', {
127
129
  method: 'POST',
128
130
  body: JSON.stringify({
129
131
  prompt,
130
132
  cache,
133
+ aspectRatio,
131
134
  session_token_id: this.sessionTokenId ?? undefined,
132
135
  }),
133
136
  });
@@ -238,6 +241,18 @@ export class AIModule {
238
241
  const reader = response.body.getReader();
239
242
  const decoder = new TextDecoder('utf-8');
240
243
  let currentObject = {};
244
+ // When the backend emits a `debug:` line (dev/local only) we also log the
245
+ // final resolved result once streaming completes, so the whole prompt
246
+ // round-trip (system/user/variables + final output) lives in one place in
247
+ // the console. Holds the prompt name while debug logging is active.
248
+ let debugPromptName = null;
249
+ const logFinalResult = () => {
250
+ if (debugPromptName === null)
251
+ return;
252
+ console.group(`[Rimori Prompt] ${debugPromptName} — result`);
253
+ console.log('Result:', currentObject);
254
+ console.groupEnd();
255
+ };
241
256
  // Buffer for SSE lines that are split across network chunks.
242
257
  // TCP/IP does not guarantee that each `read()` call delivers a complete
243
258
  // logical line. For example, the `token:` line carrying the session token
@@ -258,6 +273,7 @@ export class AIModule {
258
273
  if (readerDone) {
259
274
  isLoading = false;
260
275
  onResult(currentObject, false);
276
+ logFinalResult();
261
277
  return currentObject;
262
278
  }
263
279
  //the check needs to be behind readerDone because in closed connections the value is undefined
@@ -289,6 +305,7 @@ export class AIModule {
289
305
  if (line.startsWith('debug:')) {
290
306
  try {
291
307
  const debug = JSON.parse(line.slice(6).trim());
308
+ debugPromptName = debug.promptName;
292
309
  console.group(`[Rimori Prompt] ${debug.promptName}`);
293
310
  console.log('System prompt:\n', debug.system);
294
311
  console.log('User prompt:\n', debug.user);
@@ -305,6 +322,7 @@ export class AIModule {
305
322
  if (dataStr === '[DONE]') {
306
323
  isLoading = false;
307
324
  onResult(currentObject, false);
325
+ logFinalResult();
308
326
  return currentObject;
309
327
  }
310
328
  if (command === 'data:') {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rimori/client",
3
- "version": "2.5.44-next.0",
3
+ "version": "2.5.44",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "repository": {