@rimori/client 2.5.29 → 2.5.30-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.
- package/dist/controller/AccomplishmentController.d.ts +3 -2
- package/dist/controller/AccomplishmentController.js +4 -3
- package/dist/controller/TranslationController.js +5 -4
- package/dist/fromRimori/EventBus.d.ts +9 -0
- package/dist/fromRimori/EventBus.js +22 -1
- package/dist/fromRimori/PluginTypes.d.ts +2 -0
- package/dist/plugin/CommunicationHandler.d.ts +2 -1
- package/dist/plugin/CommunicationHandler.js +4 -2
- package/dist/plugin/RimoriClient.d.ts +10 -0
- package/dist/plugin/RimoriClient.js +32 -4
- package/dist/plugin/module/AIModule.d.ts +0 -8
- package/dist/plugin/module/AIModule.js +5 -14
- package/dist/plugin/module/EventModule.d.ts +3 -2
- package/dist/plugin/module/EventModule.js +20 -13
- package/package.json +2 -4
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EventBusMessage } from '../fromRimori/EventBus';
|
|
1
|
+
import { EventBusHandler, EventBusMessage } from '../fromRimori/EventBus';
|
|
2
2
|
export type AccomplishmentMessage = EventBusMessage<MicroAccomplishmentPayload>;
|
|
3
3
|
export declare const skillCategories: readonly ["reading", "listening", "speaking", "writing", "learning", "community"];
|
|
4
4
|
interface BaseAccomplishmentPayload {
|
|
@@ -23,7 +23,8 @@ export interface MacroAccomplishmentPayload extends BaseAccomplishmentPayload {
|
|
|
23
23
|
export type AccomplishmentPayload = MicroAccomplishmentPayload | MacroAccomplishmentPayload;
|
|
24
24
|
export declare class AccomplishmentController {
|
|
25
25
|
private pluginId;
|
|
26
|
-
|
|
26
|
+
private eventBus;
|
|
27
|
+
constructor(pluginId: string, eventBus?: EventBusHandler);
|
|
27
28
|
emitAccomplishment(payload: Omit<AccomplishmentPayload, 'type'>): void;
|
|
28
29
|
private validateAccomplishment;
|
|
29
30
|
private sanitizeAccomplishment;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { EventBus } from '../fromRimori/EventBus';
|
|
2
2
|
export const skillCategories = ['reading', 'listening', 'speaking', 'writing', 'learning', 'community'];
|
|
3
3
|
export class AccomplishmentController {
|
|
4
|
-
constructor(pluginId) {
|
|
4
|
+
constructor(pluginId, eventBus) {
|
|
5
5
|
this.pluginId = pluginId;
|
|
6
|
+
this.eventBus = eventBus !== null && eventBus !== void 0 ? eventBus : EventBus;
|
|
6
7
|
}
|
|
7
8
|
emitAccomplishment(payload) {
|
|
8
9
|
const accomplishmentPayload = Object.assign(Object.assign({}, payload), { type: 'durationMinutes' in payload ? 'macro' : 'micro' });
|
|
@@ -11,7 +12,7 @@ export class AccomplishmentController {
|
|
|
11
12
|
}
|
|
12
13
|
const sanitizedPayload = this.sanitizeAccomplishment(accomplishmentPayload);
|
|
13
14
|
const topic = 'global.accomplishment.trigger' + (accomplishmentPayload.type === 'macro' ? 'Macro' : 'Micro');
|
|
14
|
-
|
|
15
|
+
this.eventBus.emit(this.pluginId, topic, sanitizedPayload);
|
|
15
16
|
}
|
|
16
17
|
validateAccomplishment(payload) {
|
|
17
18
|
if (!skillCategories.includes(payload.skillCategory)) {
|
|
@@ -85,7 +86,7 @@ export class AccomplishmentController {
|
|
|
85
86
|
else if (topicLength !== 3) {
|
|
86
87
|
throw new Error('Invalid accomplishment topic pattern. The pattern must be plugin.skillCategory.accomplishmentKeyword or an * as wildcard for any plugin, skill category or accomplishment keyword');
|
|
87
88
|
}
|
|
88
|
-
|
|
89
|
+
this.eventBus.on(['global.accomplishment.triggerMicro', 'global.accomplishment.triggerMacro'], (event) => {
|
|
89
90
|
const { plugin, skillCategory, accomplishmentKeyword } = this.getDecoupledTopic(accomplishmentTopic);
|
|
90
91
|
if (plugin !== '*' && event.sender !== plugin)
|
|
91
92
|
return;
|
|
@@ -79,12 +79,13 @@ export class Translator {
|
|
|
79
79
|
});
|
|
80
80
|
}
|
|
81
81
|
getTranslationUrl(language) {
|
|
82
|
+
const baseUrl = this.translationUrl || window.location.origin;
|
|
82
83
|
// For localhost development, use local- prefix for non-English languages
|
|
83
|
-
if (window.location.hostname === 'localhost') {
|
|
84
|
+
if (window.location.hostname === 'localhost' || new URL(baseUrl).hostname === 'localhost') {
|
|
84
85
|
const filename = language !== 'en' ? `local-${language}` : language;
|
|
85
|
-
return `${
|
|
86
|
+
return `${baseUrl}/locales/${filename}.json`;
|
|
86
87
|
}
|
|
87
|
-
return `${
|
|
88
|
+
return `${baseUrl}/locales/${language}.json`;
|
|
88
89
|
}
|
|
89
90
|
usePlugin(plugin) {
|
|
90
91
|
if (!this.i18n) {
|
|
@@ -134,7 +135,7 @@ export class Translator {
|
|
|
134
135
|
if (!this.i18n) {
|
|
135
136
|
throw new Error('Translator is not initialized');
|
|
136
137
|
}
|
|
137
|
-
// eslint-disable-next-line @typescript-eslint/no-
|
|
138
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
138
139
|
return this.i18n.t(key, options);
|
|
139
140
|
}
|
|
140
141
|
/**
|
|
@@ -29,6 +29,11 @@ export declare class EventBusHandler {
|
|
|
29
29
|
private generatedIds;
|
|
30
30
|
private cleanupInterval;
|
|
31
31
|
private constructor();
|
|
32
|
+
/**
|
|
33
|
+
* Creates a new non-singleton EventBusHandler instance.
|
|
34
|
+
* Used in federation mode where each plugin needs its own isolated EventBus.
|
|
35
|
+
*/
|
|
36
|
+
static create(name?: string): EventBusHandler;
|
|
32
37
|
static getInstance(name?: string): EventBusHandler;
|
|
33
38
|
/**
|
|
34
39
|
* Starts the interval to cleanup the generated ids.
|
|
@@ -109,6 +114,10 @@ export declare class EventBusHandler {
|
|
|
109
114
|
*/
|
|
110
115
|
private validateTopic;
|
|
111
116
|
private logIfDebug;
|
|
117
|
+
/**
|
|
118
|
+
* Destroys this EventBus instance, cleaning up all listeners and intervals.
|
|
119
|
+
*/
|
|
120
|
+
destroy(): void;
|
|
112
121
|
private logAndThrowError;
|
|
113
122
|
}
|
|
114
123
|
export declare const EventBus: EventBusHandler;
|
|
@@ -15,9 +15,18 @@ export class EventBusHandler {
|
|
|
15
15
|
this.evName = '';
|
|
16
16
|
this.generatedIds = new Map(); // Map<id, timestamp>
|
|
17
17
|
this.cleanupInterval = null;
|
|
18
|
-
//private constructor
|
|
19
18
|
this.startIdCleanup();
|
|
20
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* Creates a new non-singleton EventBusHandler instance.
|
|
22
|
+
* Used in federation mode where each plugin needs its own isolated EventBus.
|
|
23
|
+
*/
|
|
24
|
+
static create(name) {
|
|
25
|
+
const instance = new EventBusHandler();
|
|
26
|
+
if (name)
|
|
27
|
+
instance.evName = name;
|
|
28
|
+
return instance;
|
|
29
|
+
}
|
|
21
30
|
static getInstance(name) {
|
|
22
31
|
if (!EventBusHandler.instance) {
|
|
23
32
|
EventBusHandler.instance = new EventBusHandler();
|
|
@@ -307,6 +316,18 @@ export class EventBusHandler {
|
|
|
307
316
|
console.debug(`[${this.evName}] ` + args[0], ...args.slice(1));
|
|
308
317
|
}
|
|
309
318
|
}
|
|
319
|
+
/**
|
|
320
|
+
* Destroys this EventBus instance, cleaning up all listeners and intervals.
|
|
321
|
+
*/
|
|
322
|
+
destroy() {
|
|
323
|
+
this.listeners.clear();
|
|
324
|
+
this.responseResolvers.clear();
|
|
325
|
+
if (this.cleanupInterval) {
|
|
326
|
+
clearInterval(this.cleanupInterval);
|
|
327
|
+
this.cleanupInterval = null;
|
|
328
|
+
}
|
|
329
|
+
this.generatedIds.clear();
|
|
330
|
+
}
|
|
310
331
|
logAndThrowError(throwError, ...args) {
|
|
311
332
|
const message = `[${this.evName}] ` + args[0];
|
|
312
333
|
console.error(message, ...args.slice(1));
|
|
@@ -86,6 +86,8 @@ export interface RimoriPluginConfig<T extends object = object> {
|
|
|
86
86
|
sidebar: (SidebarPage & T)[];
|
|
87
87
|
/** Optional path to the plugin's settings/configuration page */
|
|
88
88
|
settings?: string;
|
|
89
|
+
/** When true, rimori-main loads this plugin via Module Federation instead of an iframe. */
|
|
90
|
+
federated?: boolean;
|
|
89
91
|
/** Optional array of event topics the plugin pages can listen to for cross-plugin communication */
|
|
90
92
|
topics?: string[];
|
|
91
93
|
};
|
|
@@ -67,8 +67,9 @@ export declare class RimoriCommunicationHandler {
|
|
|
67
67
|
/**
|
|
68
68
|
* Handles updates to RimoriInfo from rimori-main.
|
|
69
69
|
* Updates the cached info and Supabase client, then notifies all registered callbacks.
|
|
70
|
+
* Public so that federated mode can call it when the update event arrives via the plugin's isolated EventBus.
|
|
70
71
|
*/
|
|
71
|
-
|
|
72
|
+
handleRimoriInfoUpdate(newInfo: RimoriInfo): void;
|
|
72
73
|
/**
|
|
73
74
|
* Registers a callback to be called when RimoriInfo is updated.
|
|
74
75
|
* @param callback - Function to call with the new RimoriInfo
|
|
@@ -77,7 +77,7 @@ export class RimoriCommunicationHandler {
|
|
|
77
77
|
// Listen for updates from rimori-main (data changes, token refresh, etc.)
|
|
78
78
|
// Topic format: {pluginId}.supabase.triggerUpdate
|
|
79
79
|
EventBus.on(`${this.pluginId}.supabase.triggerUpdate`, (ev) => {
|
|
80
|
-
// console.log('[RimoriCommunicationHandler] Received
|
|
80
|
+
// console.log('[RimoriCommunicationHandler] Received triggerUpdate via MessageChannel for', this.pluginId);
|
|
81
81
|
this.handleRimoriInfoUpdate(ev.data);
|
|
82
82
|
});
|
|
83
83
|
// Mark MessageChannel as ready and process pending requests
|
|
@@ -205,12 +205,14 @@ export class RimoriCommunicationHandler {
|
|
|
205
205
|
/**
|
|
206
206
|
* Handles updates to RimoriInfo from rimori-main.
|
|
207
207
|
* Updates the cached info and Supabase client, then notifies all registered callbacks.
|
|
208
|
+
* Public so that federated mode can call it when the update event arrives via the plugin's isolated EventBus.
|
|
208
209
|
*/
|
|
209
210
|
handleRimoriInfoUpdate(newInfo) {
|
|
210
211
|
if (JSON.stringify(this.rimoriInfo) === JSON.stringify(newInfo)) {
|
|
211
|
-
// console.log('[RimoriCommunicationHandler] RimoriInfo update
|
|
212
|
+
// console.log('[RimoriCommunicationHandler] RimoriInfo update identical to cached info, skipping', this.pluginId);
|
|
212
213
|
return;
|
|
213
214
|
}
|
|
215
|
+
// console.log('[RimoriCommunicationHandler] Applying RimoriInfo update for', this.pluginId, '| ttsEnabled:', newInfo.ttsEnabled);
|
|
214
216
|
// Update cached rimoriInfo
|
|
215
217
|
this.rimoriInfo = newInfo;
|
|
216
218
|
// Update Supabase client with new token
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { SharedContentController } from './module/SharedContentController';
|
|
2
|
+
import { RimoriInfo } from './CommunicationHandler';
|
|
2
3
|
import { PluginModule } from './module/PluginModule';
|
|
3
4
|
import { DbModule } from './module/DbModule';
|
|
4
5
|
import { EventModule } from './module/EventModule';
|
|
5
6
|
import { AIModule } from './module/AIModule';
|
|
6
7
|
import { ExerciseModule } from './module/ExerciseModule';
|
|
7
8
|
import { StorageModule } from './module/StorageModule';
|
|
9
|
+
import { EventBusHandler } from '../fromRimori/EventBus';
|
|
8
10
|
export declare class RimoriClient {
|
|
9
11
|
private static instance;
|
|
10
12
|
sharedContent: SharedContentController;
|
|
@@ -16,7 +18,15 @@ export declare class RimoriClient {
|
|
|
16
18
|
/** Upload and manage images stored in Supabase via the backend. */
|
|
17
19
|
storage: StorageModule;
|
|
18
20
|
private rimoriInfo;
|
|
21
|
+
/** The EventBus instance used by this client. In federation mode this is a per-plugin instance. */
|
|
22
|
+
eventBus: EventBusHandler;
|
|
19
23
|
private constructor();
|
|
24
|
+
/**
|
|
25
|
+
* Creates a RimoriClient with pre-existing RimoriInfo (federation mode).
|
|
26
|
+
* Uses a fresh per-plugin EventBus instance instead of the global singleton.
|
|
27
|
+
* Creates the Supabase PostgrestClient internally from the info.
|
|
28
|
+
*/
|
|
29
|
+
static createWithInfo(info: RimoriInfo): RimoriClient;
|
|
20
30
|
static getInstance(pluginId?: string): Promise<RimoriClient>;
|
|
21
31
|
navigation: {
|
|
22
32
|
toDashboard: () => void;
|
|
@@ -16,9 +16,10 @@ import { EventModule } from './module/EventModule';
|
|
|
16
16
|
import { AIModule } from './module/AIModule';
|
|
17
17
|
import { ExerciseModule } from './module/ExerciseModule';
|
|
18
18
|
import { StorageModule } from './module/StorageModule';
|
|
19
|
-
import {
|
|
19
|
+
import { PostgrestClient } from '@supabase/postgrest-js';
|
|
20
|
+
import { EventBus, EventBusHandler } from '../fromRimori/EventBus';
|
|
20
21
|
export class RimoriClient {
|
|
21
|
-
constructor(controller, supabase, info) {
|
|
22
|
+
constructor(controller, supabase, info, eventBus) {
|
|
22
23
|
this.navigation = {
|
|
23
24
|
toDashboard: () => {
|
|
24
25
|
this.event.emit('global.navigation.triggerToDashboard');
|
|
@@ -30,12 +31,13 @@ export class RimoriClient {
|
|
|
30
31
|
}),
|
|
31
32
|
};
|
|
32
33
|
this.rimoriInfo = info;
|
|
34
|
+
this.eventBus = eventBus !== null && eventBus !== void 0 ? eventBus : EventBus;
|
|
33
35
|
this.sharedContent = new SharedContentController(supabase, this);
|
|
34
36
|
this.ai = new AIModule(info.backendUrl, () => this.rimoriInfo.token, info.pluginId);
|
|
35
37
|
this.ai.setOnRateLimited((exercisesRemaining) => {
|
|
36
|
-
|
|
38
|
+
this.eventBus.emit(info.pluginId, 'global.quota.triggerExceeded', { exercises_remaining: exercisesRemaining });
|
|
37
39
|
});
|
|
38
|
-
this.event = new EventModule(info.pluginId, info.backendUrl, () => this.rimoriInfo.token, this.ai);
|
|
40
|
+
this.event = new EventModule(info.pluginId, info.backendUrl, () => this.rimoriInfo.token, this.ai, this.eventBus);
|
|
39
41
|
this.db = new DbModule(supabase, controller, info);
|
|
40
42
|
this.plugin = new PluginModule(supabase, controller, info, this.ai);
|
|
41
43
|
this.exercise = new ExerciseModule(supabase, controller, info, this.event);
|
|
@@ -48,6 +50,32 @@ export class RimoriClient {
|
|
|
48
50
|
Logger.getInstance(this);
|
|
49
51
|
}
|
|
50
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* Creates a RimoriClient with pre-existing RimoriInfo (federation mode).
|
|
55
|
+
* Uses a fresh per-plugin EventBus instance instead of the global singleton.
|
|
56
|
+
* Creates the Supabase PostgrestClient internally from the info.
|
|
57
|
+
*/
|
|
58
|
+
static createWithInfo(info) {
|
|
59
|
+
const eventBus = EventBusHandler.create('Plugin EventBus ' + info.pluginId);
|
|
60
|
+
const controller = new RimoriCommunicationHandler(info.pluginId, true);
|
|
61
|
+
const supabase = new PostgrestClient(`${info.url}/rest/v1`, {
|
|
62
|
+
schema: info.dbSchema,
|
|
63
|
+
headers: {
|
|
64
|
+
apikey: info.key,
|
|
65
|
+
Authorization: `Bearer ${info.token}`,
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
const client = new RimoriClient(controller, supabase, info, eventBus);
|
|
69
|
+
// In federated mode, CommunicationHandler skips MessageChannel setup so it never
|
|
70
|
+
// subscribes to triggerUpdate events. PluginEventBridge forwards host-bus events to
|
|
71
|
+
// this plugin's isolated eventBus, so we listen here and hand off to the controller.
|
|
72
|
+
eventBus.on(`${info.pluginId}.supabase.triggerUpdate`, (ev) => {
|
|
73
|
+
var _a;
|
|
74
|
+
console.log('[RimoriClient] Federated triggerUpdate received for', info.pluginId, '| ttsEnabled:', (_a = ev.data) === null || _a === void 0 ? void 0 : _a.ttsEnabled);
|
|
75
|
+
controller.handleRimoriInfoUpdate(ev.data);
|
|
76
|
+
});
|
|
77
|
+
return client;
|
|
78
|
+
}
|
|
51
79
|
static getInstance(pluginId) {
|
|
52
80
|
return __awaiter(this, void 0, void 0, function* () {
|
|
53
81
|
if (!RimoriClient.instance) {
|
|
@@ -73,7 +73,6 @@ export declare class AIModule {
|
|
|
73
73
|
* @param params.messages The messages to generate text from.
|
|
74
74
|
* @param params.tools Optional tools to use for generation.
|
|
75
75
|
* @param params.cache Whether to cache the result (default: false).
|
|
76
|
-
* @param params.model The model to use for generation.
|
|
77
76
|
* @param params.prompt Server-side prompt name (e.g. 'writing.analysis').
|
|
78
77
|
* @param params.variables Variables for the server-side prompt template.
|
|
79
78
|
* @returns The generated text.
|
|
@@ -82,7 +81,6 @@ export declare class AIModule {
|
|
|
82
81
|
messages: Message[];
|
|
83
82
|
tools?: Tool[];
|
|
84
83
|
cache?: boolean;
|
|
85
|
-
model?: string;
|
|
86
84
|
prompt?: string;
|
|
87
85
|
variables?: Record<string, any>;
|
|
88
86
|
}): Promise<string>;
|
|
@@ -92,7 +90,6 @@ export declare class AIModule {
|
|
|
92
90
|
* @param params.onMessage Callback for each message chunk.
|
|
93
91
|
* @param params.tools Optional tools to use for generation.
|
|
94
92
|
* @param params.cache Whether to cache the result (default: false).
|
|
95
|
-
* @param params.model The model to use for generation.
|
|
96
93
|
* @param params.prompt Server-side prompt name (e.g. 'writing.analysis').
|
|
97
94
|
* @param params.variables Variables for the server-side prompt template.
|
|
98
95
|
*/
|
|
@@ -101,7 +98,6 @@ export declare class AIModule {
|
|
|
101
98
|
onMessage: OnLLMResponse;
|
|
102
99
|
tools?: Tool[];
|
|
103
100
|
cache?: boolean;
|
|
104
|
-
model?: string;
|
|
105
101
|
prompt?: string;
|
|
106
102
|
variables?: Record<string, any>;
|
|
107
103
|
}): Promise<string>;
|
|
@@ -126,7 +122,6 @@ export declare class AIModule {
|
|
|
126
122
|
* Generate a structured object from a request using AI.
|
|
127
123
|
* @param request.cache Whether to cache the result (default: false).
|
|
128
124
|
* @param request.tools The tools to use for generation.
|
|
129
|
-
* @param request.model The model to use for generation.
|
|
130
125
|
* @param request.prompt Server-side prompt name (e.g. 'writing.analysis').
|
|
131
126
|
* @param request.variables Variables for the server-side prompt template.
|
|
132
127
|
* @returns The generated object.
|
|
@@ -134,7 +129,6 @@ export declare class AIModule {
|
|
|
134
129
|
getObject<T = any>(params: {
|
|
135
130
|
cache?: boolean;
|
|
136
131
|
tools?: Tool[];
|
|
137
|
-
model?: string;
|
|
138
132
|
prompt?: string;
|
|
139
133
|
variables?: Record<string, any>;
|
|
140
134
|
}): Promise<T>;
|
|
@@ -143,7 +137,6 @@ export declare class AIModule {
|
|
|
143
137
|
* @param request.onResult Callback for each result chunk.
|
|
144
138
|
* @param request.cache Whether to cache the result (default: false).
|
|
145
139
|
* @param request.tools The tools to use for generation.
|
|
146
|
-
* @param request.model The model to use for generation.
|
|
147
140
|
* @param request.prompt Server-side prompt name (e.g. 'writing.analysis').
|
|
148
141
|
* @param request.variables Variables for the server-side prompt template.
|
|
149
142
|
*/
|
|
@@ -151,7 +144,6 @@ export declare class AIModule {
|
|
|
151
144
|
onResult: OnStreamedObjectResult<T>;
|
|
152
145
|
cache?: boolean;
|
|
153
146
|
tools?: Tool[];
|
|
154
|
-
model?: string;
|
|
155
147
|
prompt?: string;
|
|
156
148
|
variables?: Record<string, any>;
|
|
157
149
|
}): Promise<T>;
|
|
@@ -78,18 +78,16 @@ export class AIModule {
|
|
|
78
78
|
* @param params.messages The messages to generate text from.
|
|
79
79
|
* @param params.tools Optional tools to use for generation.
|
|
80
80
|
* @param params.cache Whether to cache the result (default: false).
|
|
81
|
-
* @param params.model The model to use for generation.
|
|
82
81
|
* @param params.prompt Server-side prompt name (e.g. 'writing.analysis').
|
|
83
82
|
* @param params.variables Variables for the server-side prompt template.
|
|
84
83
|
* @returns The generated text.
|
|
85
84
|
*/
|
|
86
85
|
getText(params) {
|
|
87
86
|
return __awaiter(this, void 0, void 0, function* () {
|
|
88
|
-
const { messages, tools, cache = false,
|
|
87
|
+
const { messages, tools, cache = false, prompt, variables } = params;
|
|
89
88
|
const { result } = yield this.streamObject({
|
|
90
89
|
cache,
|
|
91
90
|
tools,
|
|
92
|
-
model,
|
|
93
91
|
messages,
|
|
94
92
|
prompt,
|
|
95
93
|
variables,
|
|
@@ -103,18 +101,16 @@ export class AIModule {
|
|
|
103
101
|
* @param params.onMessage Callback for each message chunk.
|
|
104
102
|
* @param params.tools Optional tools to use for generation.
|
|
105
103
|
* @param params.cache Whether to cache the result (default: false).
|
|
106
|
-
* @param params.model The model to use for generation.
|
|
107
104
|
* @param params.prompt Server-side prompt name (e.g. 'writing.analysis').
|
|
108
105
|
* @param params.variables Variables for the server-side prompt template.
|
|
109
106
|
*/
|
|
110
107
|
getStreamedText(params) {
|
|
111
108
|
return __awaiter(this, void 0, void 0, function* () {
|
|
112
|
-
const { messages, onMessage, tools, cache = false,
|
|
109
|
+
const { messages, onMessage, tools, cache = false, prompt, variables, } = params;
|
|
113
110
|
const messageId = Math.random().toString(36).substring(3);
|
|
114
111
|
const { result } = yield this.streamObject({
|
|
115
112
|
cache,
|
|
116
113
|
tools,
|
|
117
|
-
model,
|
|
118
114
|
messages,
|
|
119
115
|
prompt,
|
|
120
116
|
variables,
|
|
@@ -188,19 +184,17 @@ export class AIModule {
|
|
|
188
184
|
* Generate a structured object from a request using AI.
|
|
189
185
|
* @param request.cache Whether to cache the result (default: false).
|
|
190
186
|
* @param request.tools The tools to use for generation.
|
|
191
|
-
* @param request.model The model to use for generation.
|
|
192
187
|
* @param request.prompt Server-side prompt name (e.g. 'writing.analysis').
|
|
193
188
|
* @param request.variables Variables for the server-side prompt template.
|
|
194
189
|
* @returns The generated object.
|
|
195
190
|
*/
|
|
196
191
|
getObject(params) {
|
|
197
192
|
return __awaiter(this, void 0, void 0, function* () {
|
|
198
|
-
const { cache = false, tools = [],
|
|
193
|
+
const { cache = false, tools = [], prompt, variables } = params;
|
|
199
194
|
return yield this.streamObject({
|
|
200
195
|
messages: [],
|
|
201
196
|
cache,
|
|
202
197
|
tools,
|
|
203
|
-
model,
|
|
204
198
|
prompt,
|
|
205
199
|
variables,
|
|
206
200
|
});
|
|
@@ -211,19 +205,17 @@ export class AIModule {
|
|
|
211
205
|
* @param request.onResult Callback for each result chunk.
|
|
212
206
|
* @param request.cache Whether to cache the result (default: false).
|
|
213
207
|
* @param request.tools The tools to use for generation.
|
|
214
|
-
* @param request.model The model to use for generation.
|
|
215
208
|
* @param request.prompt Server-side prompt name (e.g. 'writing.analysis').
|
|
216
209
|
* @param request.variables Variables for the server-side prompt template.
|
|
217
210
|
*/
|
|
218
211
|
getStreamedObject(params) {
|
|
219
212
|
return __awaiter(this, void 0, void 0, function* () {
|
|
220
|
-
const { onResult, cache = false, tools = [],
|
|
213
|
+
const { onResult, cache = false, tools = [], prompt, variables } = params;
|
|
221
214
|
return yield this.streamObject({
|
|
222
215
|
messages: [],
|
|
223
216
|
onResult,
|
|
224
217
|
cache,
|
|
225
218
|
tools,
|
|
226
|
-
model,
|
|
227
219
|
prompt,
|
|
228
220
|
variables,
|
|
229
221
|
});
|
|
@@ -232,14 +224,13 @@ export class AIModule {
|
|
|
232
224
|
streamObject(params) {
|
|
233
225
|
return __awaiter(this, void 0, void 0, function* () {
|
|
234
226
|
var _a, _b, _c, _d, _e;
|
|
235
|
-
const { messages, onResult = () => null, cache = false, tools = [],
|
|
227
|
+
const { messages, onResult = () => null, cache = false, tools = [], prompt, variables, } = params;
|
|
236
228
|
const chatMessages = messages.map((message, index) => (Object.assign(Object.assign({}, message), { id: `${index + 1}` })));
|
|
237
229
|
const payload = {
|
|
238
230
|
cache,
|
|
239
231
|
tools,
|
|
240
232
|
stream: true,
|
|
241
233
|
messages: chatMessages,
|
|
242
|
-
model,
|
|
243
234
|
session_token_id: (_a = this.sessionTokenId) !== null && _a !== void 0 ? _a : undefined,
|
|
244
235
|
};
|
|
245
236
|
if (prompt) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { MainPanelAction, SidebarAction } from '../../fromRimori/PluginTypes';
|
|
2
2
|
import { AccomplishmentPayload } from '../../controller/AccomplishmentController';
|
|
3
|
-
import { EventBusMessage, EventHandler, EventPayload, EventListener } from '../../fromRimori/EventBus';
|
|
3
|
+
import { EventBusHandler, EventBusMessage, EventHandler, EventPayload, EventListener } from '../../fromRimori/EventBus';
|
|
4
4
|
import { AIModule } from './AIModule';
|
|
5
5
|
/**
|
|
6
6
|
* Event module for plugin event bus operations.
|
|
@@ -12,7 +12,8 @@ export declare class EventModule {
|
|
|
12
12
|
private aiModule;
|
|
13
13
|
private backendUrl;
|
|
14
14
|
private getToken;
|
|
15
|
-
|
|
15
|
+
private eventBus;
|
|
16
|
+
constructor(pluginId: string, backendUrl: string, getToken: () => string, aiModule: AIModule, eventBus?: EventBusHandler);
|
|
16
17
|
getGlobalEventTopic(preliminaryTopic: string): string;
|
|
17
18
|
/**
|
|
18
19
|
* Emit an event to Rimori or a plugin.
|
|
@@ -14,12 +14,13 @@ import { EventBus } from '../../fromRimori/EventBus';
|
|
|
14
14
|
* Provides methods for emitting, listening to, and responding to events.
|
|
15
15
|
*/
|
|
16
16
|
export class EventModule {
|
|
17
|
-
constructor(pluginId, backendUrl, getToken, aiModule) {
|
|
17
|
+
constructor(pluginId, backendUrl, getToken, aiModule, eventBus) {
|
|
18
18
|
this.pluginId = pluginId;
|
|
19
19
|
this.backendUrl = backendUrl;
|
|
20
20
|
this.getToken = getToken;
|
|
21
21
|
this.aiModule = aiModule;
|
|
22
|
-
this.
|
|
22
|
+
this.eventBus = eventBus !== null && eventBus !== void 0 ? eventBus : EventBus;
|
|
23
|
+
this.accomplishmentController = new AccomplishmentController(pluginId, this.eventBus);
|
|
23
24
|
}
|
|
24
25
|
getGlobalEventTopic(preliminaryTopic) {
|
|
25
26
|
var _a;
|
|
@@ -54,7 +55,7 @@ export class EventModule {
|
|
|
54
55
|
*/
|
|
55
56
|
emit(topic, data, eventId) {
|
|
56
57
|
const globalTopic = this.getGlobalEventTopic(topic);
|
|
57
|
-
|
|
58
|
+
this.eventBus.emit(this.pluginId, globalTopic, data, eventId);
|
|
58
59
|
}
|
|
59
60
|
/**
|
|
60
61
|
* Request an event.
|
|
@@ -68,7 +69,7 @@ export class EventModule {
|
|
|
68
69
|
const globalTopic = this.getGlobalEventTopic(topic);
|
|
69
70
|
yield this.aiModule.session.ensure();
|
|
70
71
|
const sessionToken = (_a = this.aiModule.session.get()) !== null && _a !== void 0 ? _a : undefined;
|
|
71
|
-
return
|
|
72
|
+
return this.eventBus.request(this.pluginId, globalTopic, data, sessionToken);
|
|
72
73
|
});
|
|
73
74
|
}
|
|
74
75
|
/**
|
|
@@ -79,7 +80,7 @@ export class EventModule {
|
|
|
79
80
|
*/
|
|
80
81
|
on(topic, callback) {
|
|
81
82
|
const topics = Array.isArray(topic) ? topic : [topic];
|
|
82
|
-
return
|
|
83
|
+
return this.eventBus.on(topics.map((t) => this.getGlobalEventTopic(t)), (event) => {
|
|
83
84
|
if (event.ai_session_token && !this.aiModule.session.get()) {
|
|
84
85
|
this.aiModule.session.set(event.ai_session_token);
|
|
85
86
|
}
|
|
@@ -92,7 +93,7 @@ export class EventModule {
|
|
|
92
93
|
* @param callback The callback to call when the event is emitted.
|
|
93
94
|
*/
|
|
94
95
|
once(topic, callback) {
|
|
95
|
-
|
|
96
|
+
this.eventBus.once(this.getGlobalEventTopic(topic), callback);
|
|
96
97
|
}
|
|
97
98
|
/**
|
|
98
99
|
* Respond to an event.
|
|
@@ -124,7 +125,7 @@ export class EventModule {
|
|
|
124
125
|
}
|
|
125
126
|
});
|
|
126
127
|
}
|
|
127
|
-
|
|
128
|
+
this.eventBus.respond(this.pluginId, topics.map((t) => this.getGlobalEventTopic(t)), wrappedData);
|
|
128
129
|
}
|
|
129
130
|
/**
|
|
130
131
|
* Emit an accomplishment.
|
|
@@ -219,15 +220,21 @@ export class EventModule {
|
|
|
219
220
|
*/
|
|
220
221
|
onSidePanelAction(callback, actionsToListen = []) {
|
|
221
222
|
const listeningActions = Array.isArray(actionsToListen) ? actionsToListen : [actionsToListen];
|
|
222
|
-
//
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
// console.log('Listening to actions', listeningActions);
|
|
223
|
+
// Register the listener BEFORE emitting the request, so the synchronous response
|
|
224
|
+
// from the bridge/responder is captured (emit → bridge outbound → host respond → bridge inbound is synchronous).
|
|
225
|
+
console.log('[EventModule] onSidePanelAction: setting up listener for', this.pluginId, 'listening to:', listeningActions);
|
|
226
|
+
const listener = this.on('action.requestSidebar', ({ data }) => {
|
|
227
|
+
console.log('[EventModule] onSidePanelAction: received event', { data, listeningActions });
|
|
228
228
|
if (listeningActions.length === 0 || listeningActions.includes(data.action)) {
|
|
229
|
+
console.log('[EventModule] onSidePanelAction: action matched, calling callback');
|
|
229
230
|
callback(data);
|
|
230
231
|
}
|
|
232
|
+
else {
|
|
233
|
+
console.log('[EventModule] onSidePanelAction: action NOT matched. Got:', data.action, 'expected:', listeningActions);
|
|
234
|
+
}
|
|
231
235
|
});
|
|
236
|
+
console.log('[EventModule] onSidePanelAction: emitting action.requestSidebar for', this.pluginId);
|
|
237
|
+
this.emit('action.requestSidebar');
|
|
238
|
+
return listener;
|
|
232
239
|
}
|
|
233
240
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rimori/client",
|
|
3
|
-
"version": "2.5.
|
|
3
|
+
"version": "2.5.30-next.1",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"repository": {
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"scripts": {
|
|
33
33
|
"build": "tsc",
|
|
34
34
|
"dev": "tsc -w --preserveWatchOutput",
|
|
35
|
-
"lint": "eslint . --fix",
|
|
35
|
+
"lint": "npx eslint . --fix",
|
|
36
36
|
"format": "prettier --write ."
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
@@ -41,10 +41,8 @@
|
|
|
41
41
|
"i18next": "^25.10.10"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
|
-
"@eslint/js": "^9.37.0",
|
|
45
44
|
"@types/node": "^25.0.1",
|
|
46
45
|
"eslint-config-prettier": "^10.1.8",
|
|
47
|
-
"eslint-plugin-prettier": "^5.5.4",
|
|
48
46
|
"html2canvas": "^1.4.1",
|
|
49
47
|
"globals": "^16.4.0",
|
|
50
48
|
"prettier": "^3.6.2",
|