@rimori/client 2.5.16 → 2.5.17-next.1

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.
@@ -67,6 +67,11 @@ export declare class AIModule {
67
67
  setSessionToken(id: string): void;
68
68
  /** Clears the stored session token (called after macro accomplishment). */
69
69
  clearSessionToken(): void;
70
+ /**
71
+ * Ensures a session token exists, requesting one from the backend if needed.
72
+ * Mirrors the lazy-issuance pattern used by the AI/LLM endpoint.
73
+ */
74
+ private ensureSessionToken;
70
75
  /** Registers a callback invoked whenever a 429 rate-limit response is received. */
71
76
  setOnRateLimited(cb: (exercisesRemaining: number) => void): void;
72
77
  /**
@@ -29,6 +29,32 @@ export class AIModule {
29
29
  clearSessionToken() {
30
30
  this.sessionTokenId = null;
31
31
  }
32
+ /**
33
+ * Ensures a session token exists, requesting one from the backend if needed.
34
+ * Mirrors the lazy-issuance pattern used by the AI/LLM endpoint.
35
+ */
36
+ ensureSessionToken() {
37
+ return __awaiter(this, void 0, void 0, function* () {
38
+ var _a, _b, _c;
39
+ if (this.sessionTokenId)
40
+ return;
41
+ const response = yield fetch(`${this.backendUrl}/ai/session`, {
42
+ method: 'POST',
43
+ headers: { Authorization: `Bearer ${this.getToken()}` },
44
+ });
45
+ if (!response.ok) {
46
+ if (response.status === 429) {
47
+ const body = yield response.json().catch(() => ({}));
48
+ const remaining = (_a = body.exercises_remaining) !== null && _a !== void 0 ? _a : 0;
49
+ (_b = this.onRateLimitedCb) === null || _b === void 0 ? void 0 : _b.call(this, remaining);
50
+ throw new Error(`Rate limit exceeded: ${(_c = body.error) !== null && _c !== void 0 ? _c : 'Daily exercise limit reached'}. exercises_remaining: ${remaining}`);
51
+ }
52
+ throw new Error(`Failed to create session: ${response.status} ${response.statusText}`);
53
+ }
54
+ const { session_token_id } = yield response.json();
55
+ this.sessionTokenId = session_token_id;
56
+ });
57
+ }
32
58
  /** Registers a callback invoked whenever a 429 rate-limit response is received. */
33
59
  setOnRateLimited(cb) {
34
60
  this.onRateLimitedCb = cb;
@@ -96,6 +122,7 @@ export class AIModule {
96
122
  getVoice(text_1) {
97
123
  return __awaiter(this, arguments, void 0, function* (text, voice = 'alloy', speed = 1, language, cache = false) {
98
124
  var _a;
125
+ yield this.ensureSessionToken();
99
126
  return yield fetch(`${this.backendUrl}/voice/tts`, {
100
127
  method: 'POST',
101
128
  headers: {
@@ -114,6 +141,7 @@ export class AIModule {
114
141
  */
115
142
  getTextFromVoice(file, language) {
116
143
  return __awaiter(this, void 0, void 0, function* () {
144
+ yield this.ensureSessionToken();
117
145
  const formData = new FormData();
118
146
  formData.append('file', file);
119
147
  if (language) {
@@ -108,7 +108,7 @@ export type UserRole = 'user' | 'plugin_moderator' | 'lang_moderator' | 'admin';
108
108
  export declare const LEARNING_REASONS: readonly ["work", "partner", "friends", "study", "living", "culture", "growth", "citizenship", "other"];
109
109
  export type LearningReason = (typeof LEARNING_REASONS)[number];
110
110
  export type ExplicitUndefined<T> = {
111
- [K in keyof T]-?: T[K] | undefined;
111
+ [K in Exclude<keyof T, never>]-?: {} extends Pick<T, K> ? T[K] | undefined : T[K];
112
112
  };
113
113
  export interface UserInfo {
114
114
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rimori/client",
3
- "version": "2.5.16",
3
+ "version": "2.5.17-next.1",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "repository": {