@rimori/client 2.5.5 → 2.5.6

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.
@@ -61,10 +61,12 @@ interface BaseTableStructure {
61
61
  created_by: DbColumnDefinition;
62
62
  }
63
63
  /**
64
- * Complete database table schema definition.
65
- * Defines the structure, constraints, and relationships for a database table.
64
+ * Normal database table schema definition.
65
+ * Defines the structure, constraints, and relationships for a standard database table.
66
66
  */
67
- export interface DbTableDefinition {
67
+ export interface DbNormalTableDefinition {
68
+ /** Type discriminator for normal tables */
69
+ type: 'table';
68
70
  /** Name of the database table */
69
71
  table_name: string;
70
72
  /** Description of the table's purpose and usage */
@@ -83,6 +85,37 @@ export interface DbTableDefinition {
83
85
  [column_name: string]: DbColumnDefinition;
84
86
  };
85
87
  }
88
+ /**
89
+ * Shared content table schema definition.
90
+ * Defines the structure for community-shared content tables with automatic columns and verification.
91
+ * Table naming: {pluginId}_sc_{table_name}
92
+ * Automatic columns: title (text), keywords (text[]), verified (boolean), embedding (vector)
93
+ * Hardcoded permissions: read ALL public+own, insert/update/delete OWN
94
+ */
95
+ export interface DbSharedContentTableDefinition {
96
+ /** Type discriminator for shared content tables */
97
+ type: 'shared_content';
98
+ /** Name of the database table (will become {pluginId}_sc_{table_name}) */
99
+ table_name: string;
100
+ /** Description of the table's purpose and usage */
101
+ description: string;
102
+ /** AI prompt for generating content. Supports placeholders like {{topic}}, {{level}}, etc. */
103
+ instructions: string;
104
+ /** Optional AI prompt to verify content quality before marking as verified */
105
+ verification_prompt: string;
106
+ /** Column definitions for the table (excluding auto-generated columns) */
107
+ columns: {
108
+ [column_name: string]: DbColumnDefinition & {
109
+ /** Whether the column is used for LLM generation. If not set, the column is not used for LLM generation. */
110
+ expose_to_llm?: boolean;
111
+ };
112
+ };
113
+ }
114
+ /**
115
+ * Complete database table schema definition.
116
+ * Can be either a normal table or a shared content table.
117
+ */
118
+ export type DbTableDefinition = DbNormalTableDefinition | DbSharedContentTableDefinition;
86
119
  /**
87
120
  * Permission definition for a database table.
88
121
  * NONE means the action is not allowed.
@@ -24,8 +24,19 @@ export declare class EventBusHandler {
24
24
  private static instance;
25
25
  private debugEnabled;
26
26
  private evName;
27
+ private generatedIds;
28
+ private cleanupInterval;
27
29
  private constructor();
28
30
  static getInstance(name?: string): EventBusHandler;
31
+ /**
32
+ * Starts the interval to cleanup the generated ids.
33
+ */
34
+ private startIdCleanup;
35
+ /**
36
+ * Generates a unique id.
37
+ * @returns A unique id.
38
+ */
39
+ private generateUniqueId;
29
40
  private createEvent;
30
41
  /**
31
42
  * Emits an event to the event bus. Can be a new event or a response to a request.
@@ -13,7 +13,10 @@ export class EventBusHandler {
13
13
  this.responseResolvers = new Map();
14
14
  this.debugEnabled = false;
15
15
  this.evName = '';
16
+ this.generatedIds = new Map(); // Map<id, timestamp>
17
+ this.cleanupInterval = null;
16
18
  //private constructor
19
+ this.startIdCleanup();
17
20
  }
18
21
  static getInstance(name) {
19
22
  if (!EventBusHandler.instance) {
@@ -28,8 +31,40 @@ export class EventBusHandler {
28
31
  }
29
32
  return EventBusHandler.instance;
30
33
  }
34
+ /**
35
+ * Starts the interval to cleanup the generated ids.
36
+ */
37
+ startIdCleanup() {
38
+ this.cleanupInterval = setInterval(() => {
39
+ const now = Date.now();
40
+ const oneMinuteAgo = now - 60000; // 60 seconds in milliseconds
41
+ for (const [id, timestamp] of this.generatedIds.entries()) {
42
+ if (timestamp < oneMinuteAgo) {
43
+ this.generatedIds.delete(id);
44
+ }
45
+ }
46
+ }, 10000); // Run every 10 seconds
47
+ }
48
+ /**
49
+ * Generates a unique id.
50
+ * @returns A unique id.
51
+ */
52
+ generateUniqueId() {
53
+ const now = Date.now();
54
+ const oneMinuteAgo = now - 60000;
55
+ const id = Math.floor(Math.random() * 10000000000);
56
+ // Check if ID was generated within the last minute
57
+ const existingTimestamp = this.generatedIds.get(id);
58
+ if (existingTimestamp && existingTimestamp > oneMinuteAgo) {
59
+ // ID was recently generated, generate a new one recursively
60
+ return this.generateUniqueId();
61
+ }
62
+ // Store the ID with current timestamp
63
+ this.generatedIds.set(id, now);
64
+ return id;
65
+ }
31
66
  createEvent(sender, topic, data, eventId) {
32
- const generatedEventId = eventId || Math.floor(Math.random() * 10000000000);
67
+ const generatedEventId = eventId || this.generateUniqueId();
33
68
  return {
34
69
  eventId: generatedEventId,
35
70
  timestamp: new Date().toISOString(),
@@ -101,7 +136,7 @@ export class EventBusHandler {
101
136
  if (!this.listeners.has(topic)) {
102
137
  this.listeners.set(topic, new Set());
103
138
  }
104
- const id = Math.floor(Math.random() * 10000000000);
139
+ const id = this.generateUniqueId();
105
140
  // To prevent infinite loops and processing the same eventId multiple times
106
141
  const blackListedEventIds = [];
107
142
  const eventHandler = (data) => {
@@ -32,15 +32,22 @@ export interface MenuEntry {
32
32
  action_key: string;
33
33
  text: string;
34
34
  iconUrl?: string;
35
+ args?: Record<string, unknown>;
35
36
  }
36
37
  export type MainPanelAction = {
37
38
  plugin_id: string;
38
39
  action_key: string;
39
40
  } & Record<string, string>;
41
+ export type SidebarAction = {
42
+ text: string;
43
+ action: string;
44
+ args?: Record<string, unknown>;
45
+ };
40
46
  export interface ContextMenuAction {
41
47
  text: string;
42
48
  plugin_id: string;
43
49
  action_key: string;
50
+ args?: Record<string, unknown>;
44
51
  }
45
52
  /**
46
53
  * Rimori plugin structure representing the complete configuration
@@ -79,7 +86,7 @@ export interface RimoriPluginConfig<T extends object = object> {
79
86
  /**
80
87
  * Context menu actions that the plugin registers to appear in right-click menus throughout the application.
81
88
  */
82
- context_menu_actions: Omit<MenuEntry, 'plugin_id'>[];
89
+ context_menu_actions: Omit<MenuEntry, 'plugin_id' | 'args'>[];
83
90
  /**
84
91
  * Documentation paths for different types of plugin documentation.
85
92
  */
@@ -150,6 +157,8 @@ interface ToolParameter {
150
157
  enum?: string[];
151
158
  /** Whether the parameter is optional */
152
159
  optional?: boolean;
160
+ /** Whether the parameter is an array */
161
+ isArray?: boolean;
153
162
  }
154
163
  /**
155
164
  * Union type defining all possible parameter types for LLM tools.
package/dist/index.d.ts CHANGED
@@ -9,7 +9,7 @@ export { setupWorker } from './worker/WorkerSetup';
9
9
  export { AudioController } from './controller/AudioController';
10
10
  export { Translator } from './controller/TranslationController';
11
11
  export type { TOptions } from 'i18next';
12
- export type { SharedContent, SharedContentObjectRequest } from './controller/SharedContentController';
12
+ export type { SharedContent, BasicSharedContent } from './plugin/module/SharedContentController';
13
13
  export type { Exercise } from './plugin/module/ExerciseModule';
14
14
  export type { UserInfo, Language, UserRole } from './controller/SettingsController';
15
15
  export type { Message, ToolInvocation } from './controller/AIController';
@@ -1,4 +1,4 @@
1
- import { SharedContent, SharedContentFilter, SharedContentObjectRequest } from '../controller/SharedContentController';
1
+ import { SharedContentController } from './module/SharedContentController';
2
2
  import { PluginModule } from './module/PluginModule';
3
3
  import { DbModule } from './module/DbModule';
4
4
  import { EventModule } from './module/EventModule';
@@ -6,8 +6,7 @@ import { AIModule } from './module/AIModule';
6
6
  import { ExerciseModule } from './module/ExerciseModule';
7
7
  export declare class RimoriClient {
8
8
  private static instance;
9
- private pluginController;
10
- private sharedContentController;
9
+ sharedContent: SharedContentController;
11
10
  db: DbModule;
12
11
  event: EventModule;
13
12
  plugin: PluginModule;
@@ -15,97 +14,11 @@ export declare class RimoriClient {
15
14
  exercise: ExerciseModule;
16
15
  private rimoriInfo;
17
16
  private constructor();
17
+ static getInstance(pluginId?: string): Promise<RimoriClient>;
18
18
  navigation: {
19
19
  toDashboard: () => void;
20
20
  };
21
- /**
22
- * Get a query parameter value that was passed via MessageChannel
23
- * @param key The query parameter key
24
- * @deprecated Use the plugin.applicationMode and plugin.theme properties instead
25
- * @returns The query parameter value or null if not found
26
- */
27
- getQueryParam(key: string): string | null;
28
- static getInstance(pluginId?: string): Promise<RimoriClient>;
29
21
  runtime: {
30
22
  fetchBackend: (url: string, options: RequestInit) => Promise<Response>;
31
23
  };
32
- community: {
33
- /**
34
- * Shared content is a way to share completable content with other users using this plugin.
35
- * Typical examples are assignments, exercises, stories, etc.
36
- * Users generate new shared content items and others can complete the content too.
37
- */
38
- sharedContent: {
39
- /**
40
- * Get one dedicated shared content item by id. It does not matter if it is completed or not.
41
- * @param contentType The type of shared content to get. E.g. assignments, exercises, etc.
42
- * @param id The id of the shared content item.
43
- * @returns The shared content item.
44
- */
45
- get: <T = any>(contentType: string, id: string) => Promise<SharedContent<T>>;
46
- /**
47
- * Get a list of shared content items.
48
- * @param contentType The type of shared content to get. E.g. assignments, exercises, etc.
49
- * @param filter The optional additional filter for checking new shared content based on a column and value. This is useful if the aditional information stored on the shared content is used to further narrow down the kind of shared content wanted to be received. E.g. only adjective grammar exercises.
50
- * @param limit The optional limit for the number of results.
51
- * @returns The list of shared content items.
52
- */
53
- getList: <T = any>(contentType: string, filter?: SharedContentFilter, limit?: number) => Promise<SharedContent<T>[]>;
54
- /**
55
- * Get new shared content.
56
- * @param contentType The type of shared content to fetch. E.g. assignments, exercises, etc.
57
- * @param generatorInstructions The instructions for the creation of new shared content. The object will automatically be extended with a tool property with a topic and keywords property to let a new unique topic be generated.
58
- * @param filter The optional additional filter for checking new shared content based on a column and value. This is useful if the aditional information stored on the shared content is used to further narrow down the kind of shared content wanted to be received. E.g. only adjective grammar exercises.
59
- * @param options An optional object with options for the new shared content.
60
- * @param options.privateTopic An optional flag to indicate if the topic should be private and only be visible to the user. This is useful if the topic is not meant to be shared with other users. Like for personal topics or if the content is based on the personal study goal.
61
- * @param options.skipDbSave An optional flag to indicate if the new shared content should not be saved to the database. This is useful if the new shared content is not meant to be saved to the database.
62
- * @param options.alwaysGenerateNew An optional flag to indicate if the new shared content should always be generated even if there is already a content with the same filter. This is useful if the new shared content is not meant to be saved to the database.
63
- * @param options.excludeIds An optional list of ids to exclude from the selection. This is useful if the new shared content is not meant to be saved to the database.
64
- * @returns The new shared content.
65
- */
66
- getNew: <T = any>(contentType: string, generatorInstructions: SharedContentObjectRequest, filter?: SharedContentFilter, options?: {
67
- privateTopic?: boolean;
68
- skipDbSave?: boolean;
69
- alwaysGenerateNew?: boolean;
70
- excludeIds?: string[];
71
- }) => Promise<SharedContent<T>>;
72
- /**
73
- * Create a new shared content item.
74
- * @param content The content to create.
75
- * @returns The new shared content item.
76
- */
77
- create: <T = any>(content: Omit<SharedContent<T>, "id">) => Promise<SharedContent<T>>;
78
- /**
79
- * Update a shared content item.
80
- * @param id The id of the shared content item to update.
81
- * @param content The content to update.
82
- * @returns The updated shared content item.
83
- */
84
- update: <T = any>(id: string, content: Partial<SharedContent<T>>) => Promise<SharedContent<T>>;
85
- /**
86
- * Complete a shared content item.
87
- * @param contentType The type of shared content to complete. E.g. assignments, exercises, etc.
88
- * @param assignmentId The id of the shared content item to complete.
89
- */
90
- complete: (contentType: string, assignmentId: string) => Promise<void>;
91
- /**
92
- /**
93
- * Update the state of a shared content item for a specific user.
94
- * Useful for marking content as completed, ongoing, hidden, liked, disliked, or bookmarked.
95
- */
96
- updateState: (params: {
97
- contentType: string;
98
- id: string;
99
- state?: "completed" | "ongoing" | "hidden";
100
- reaction?: "liked" | "disliked" | null;
101
- bookmarked?: boolean;
102
- }) => Promise<void>;
103
- /**
104
- * Remove a shared content item.
105
- * @param id The id of the shared content item to remove.
106
- * @returns The removed shared content item.
107
- */
108
- remove: (id: string) => Promise<SharedContent<any>>;
109
- };
110
- };
111
24
  }
@@ -7,7 +7,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
- import { SharedContentController, } from '../controller/SharedContentController';
10
+ import { SharedContentController } from './module/SharedContentController';
11
11
  import { RimoriCommunicationHandler } from './CommunicationHandler';
12
12
  import { Logger } from './Logger';
13
13
  import { PluginModule } from './module/PluginModule';
@@ -27,93 +27,8 @@ export class RimoriClient {
27
27
  return fetch(this.rimoriInfo.backendUrl + url, Object.assign(Object.assign({}, options), { headers: Object.assign(Object.assign({}, options.headers), { Authorization: `Bearer ${this.rimoriInfo.token}` }) }));
28
28
  }),
29
29
  };
30
- this.community = {
31
- /**
32
- * Shared content is a way to share completable content with other users using this plugin.
33
- * Typical examples are assignments, exercises, stories, etc.
34
- * Users generate new shared content items and others can complete the content too.
35
- */
36
- sharedContent: {
37
- /**
38
- * Get one dedicated shared content item by id. It does not matter if it is completed or not.
39
- * @param contentType The type of shared content to get. E.g. assignments, exercises, etc.
40
- * @param id The id of the shared content item.
41
- * @returns The shared content item.
42
- */
43
- get: (contentType, id) => __awaiter(this, void 0, void 0, function* () {
44
- return yield this.sharedContentController.getSharedContent(contentType, id);
45
- }),
46
- /**
47
- * Get a list of shared content items.
48
- * @param contentType The type of shared content to get. E.g. assignments, exercises, etc.
49
- * @param filter The optional additional filter for checking new shared content based on a column and value. This is useful if the aditional information stored on the shared content is used to further narrow down the kind of shared content wanted to be received. E.g. only adjective grammar exercises.
50
- * @param limit The optional limit for the number of results.
51
- * @returns The list of shared content items.
52
- */
53
- getList: (contentType, filter, limit) => __awaiter(this, void 0, void 0, function* () {
54
- return yield this.sharedContentController.getSharedContentList(contentType, filter, limit);
55
- }),
56
- /**
57
- * Get new shared content.
58
- * @param contentType The type of shared content to fetch. E.g. assignments, exercises, etc.
59
- * @param generatorInstructions The instructions for the creation of new shared content. The object will automatically be extended with a tool property with a topic and keywords property to let a new unique topic be generated.
60
- * @param filter The optional additional filter for checking new shared content based on a column and value. This is useful if the aditional information stored on the shared content is used to further narrow down the kind of shared content wanted to be received. E.g. only adjective grammar exercises.
61
- * @param options An optional object with options for the new shared content.
62
- * @param options.privateTopic An optional flag to indicate if the topic should be private and only be visible to the user. This is useful if the topic is not meant to be shared with other users. Like for personal topics or if the content is based on the personal study goal.
63
- * @param options.skipDbSave An optional flag to indicate if the new shared content should not be saved to the database. This is useful if the new shared content is not meant to be saved to the database.
64
- * @param options.alwaysGenerateNew An optional flag to indicate if the new shared content should always be generated even if there is already a content with the same filter. This is useful if the new shared content is not meant to be saved to the database.
65
- * @param options.excludeIds An optional list of ids to exclude from the selection. This is useful if the new shared content is not meant to be saved to the database.
66
- * @returns The new shared content.
67
- */
68
- getNew: (contentType, generatorInstructions, filter, options) => __awaiter(this, void 0, void 0, function* () {
69
- return yield this.sharedContentController.getNewSharedContent(contentType, generatorInstructions, filter, options);
70
- }),
71
- /**
72
- * Create a new shared content item.
73
- * @param content The content to create.
74
- * @returns The new shared content item.
75
- */
76
- create: (content) => __awaiter(this, void 0, void 0, function* () {
77
- return yield this.sharedContentController.createSharedContent(content);
78
- }),
79
- /**
80
- * Update a shared content item.
81
- * @param id The id of the shared content item to update.
82
- * @param content The content to update.
83
- * @returns The updated shared content item.
84
- */
85
- update: (id, content) => __awaiter(this, void 0, void 0, function* () {
86
- return yield this.sharedContentController.updateSharedContent(id, content);
87
- }),
88
- /**
89
- * Complete a shared content item.
90
- * @param contentType The type of shared content to complete. E.g. assignments, exercises, etc.
91
- * @param assignmentId The id of the shared content item to complete.
92
- */
93
- complete: (contentType, assignmentId) => __awaiter(this, void 0, void 0, function* () {
94
- return yield this.sharedContentController.completeSharedContent(contentType, assignmentId);
95
- }),
96
- /**
97
- /**
98
- * Update the state of a shared content item for a specific user.
99
- * Useful for marking content as completed, ongoing, hidden, liked, disliked, or bookmarked.
100
- */
101
- updateState: (params) => __awaiter(this, void 0, void 0, function* () {
102
- return yield this.sharedContentController.updateSharedContentState(params);
103
- }),
104
- /**
105
- * Remove a shared content item.
106
- * @param id The id of the shared content item to remove.
107
- * @returns The removed shared content item.
108
- */
109
- remove: (id) => __awaiter(this, void 0, void 0, function* () {
110
- return yield this.sharedContentController.removeSharedContent(id);
111
- }),
112
- },
113
- };
114
30
  this.rimoriInfo = info;
115
- this.pluginController = controller;
116
- this.sharedContentController = new SharedContentController(supabase, this);
31
+ this.sharedContent = new SharedContentController(supabase, this);
117
32
  this.ai = new AIModule(controller, info);
118
33
  this.event = new EventModule(info.pluginId);
119
34
  this.db = new DbModule(supabase, controller, info);
@@ -127,26 +42,12 @@ export class RimoriClient {
127
42
  Logger.getInstance(this);
128
43
  }
129
44
  }
130
- /**
131
- * Get a query parameter value that was passed via MessageChannel
132
- * @param key The query parameter key
133
- * @deprecated Use the plugin.applicationMode and plugin.theme properties instead
134
- * @returns The query parameter value or null if not found
135
- */
136
- getQueryParam(key) {
137
- return this.pluginController.getQueryParam(key);
138
- }
139
45
  static getInstance(pluginId) {
140
46
  return __awaiter(this, void 0, void 0, function* () {
141
47
  if (!RimoriClient.instance) {
142
48
  if (!pluginId)
143
49
  throw new Error('Plugin ID is required');
144
50
  const controller = new RimoriCommunicationHandler(pluginId, false);
145
- if (typeof WorkerGlobalScope === 'undefined') {
146
- // In standalone mode, use URL fallback. In iframe mode, theme will be set after MessageChannel init
147
- // setTheme();
148
- // await StandaloneClient.initListeners(pluginId);
149
- }
150
51
  const client = yield controller.getClient();
151
52
  RimoriClient.instance = new RimoriClient(controller, client.supabase, client.info);
152
53
  }
@@ -154,5 +55,3 @@ export class RimoriClient {
154
55
  });
155
56
  }
156
57
  }
157
- // test 123456
158
- // console.log('test 1234567890');
@@ -1,4 +1,4 @@
1
- import { MainPanelAction } from '../../fromRimori/PluginTypes';
1
+ import { MainPanelAction, SidebarAction } from '../../fromRimori/PluginTypes';
2
2
  import { AccomplishmentPayload } from '../../controller/AccomplishmentController';
3
3
  import { EventBusMessage, EventHandler, EventPayload, EventListener } from '../../fromRimori/EventBus';
4
4
  /**
@@ -64,7 +64,7 @@ export declare class EventModule {
64
64
  * @param actionKey The key of the action to trigger.
65
65
  * @param text Optional text to be used for the action like for example text that the translator would look up.
66
66
  */
67
- emitSidebarAction(pluginId: string, actionKey: string, text?: string): void;
67
+ emitSidebarAction(pluginId: string, actionKey: string, text?: string, args?: Record<string, unknown>): void;
68
68
  /**
69
69
  * Subscribe to main panel actions triggered by the user from the dashboard.
70
70
  * @param callback Handler function that receives the action data when a matching action is triggered.
@@ -95,5 +95,5 @@ export declare class EventModule {
95
95
  * @param actionsToListen Optional filter to listen only to specific action keys. If empty or not provided, all actions will trigger the callback.
96
96
  * @returns An EventListener object with an `off()` method for cleanup.
97
97
  */
98
- onSidePanelAction(callback: (data: MainPanelAction) => void, actionsToListen?: string | string[]): EventListener;
98
+ onSidePanelAction(callback: (data: SidebarAction) => void, actionsToListen?: string | string[]): EventListener;
99
99
  }
@@ -102,8 +102,8 @@ export class EventModule {
102
102
  * @param actionKey The key of the action to trigger.
103
103
  * @param text Optional text to be used for the action like for example text that the translator would look up.
104
104
  */
105
- emitSidebarAction(pluginId, actionKey, text) {
106
- this.emit('global.sidebar.triggerAction', { plugin_id: pluginId, action_key: actionKey, text });
105
+ emitSidebarAction(pluginId, actionKey, text, args) {
106
+ this.emit('global.sidebar.triggerAction', { plugin_id: pluginId, action_key: actionKey, text, args });
107
107
  }
108
108
  /**
109
109
  * Subscribe to main panel actions triggered by the user from the dashboard.
@@ -0,0 +1,142 @@
1
+ import { ObjectTool } from '../../fromRimori/PluginTypes';
2
+ import { SupabaseClient } from '../CommunicationHandler';
3
+ import { RimoriClient } from '../RimoriClient';
4
+ export type SharedContent<T> = BasicSharedContent & T;
5
+ export interface BasicSharedContent {
6
+ id: string;
7
+ title: string;
8
+ keywords: string[];
9
+ verified: boolean;
10
+ created_by: string;
11
+ created_at: string;
12
+ guild_id: string | null;
13
+ lang_id: string | null;
14
+ }
15
+ export interface SharedContentCompletionState {
16
+ content_id: string;
17
+ state: 'completed' | 'ongoing' | 'hidden';
18
+ reaction?: 'liked' | 'disliked' | null;
19
+ bookmarked: boolean;
20
+ created_at: string;
21
+ updated_at: string;
22
+ }
23
+ export declare class SharedContentController {
24
+ private supabase;
25
+ private rimoriClient;
26
+ constructor(supabase: SupabaseClient, rimoriClient: RimoriClient);
27
+ /**
28
+ * Get new shared content. First searches for existing content matching filters that hasn't been completed,
29
+ * then falls back to AI generation if nothing suitable is found.
30
+ * @param params - Parameters object
31
+ * @param params.table - Name of the shared content table (without plugin prefix)
32
+ * @param params.skillType - Type of skill this content is for (grammar, reading, writing, speaking, listening, understanding)
33
+ * @param params.placeholders - Placeholders for instructions template for AI generation (e.g., {topicAreas: "history"})
34
+ * @param params.filter - Filter to find existing content:
35
+ * - `exact`: Match field value exactly (e.g., {topic_category: {filterType: "exact", value: "history"}})
36
+ * - `exclude`: Exclude specific field value (e.g., {difficulty: {filterType: "exclude", value: "hard"}})
37
+ * - `rag`: Use semantic similarity search (e.g., {topic: {filterType: "rag", value: "japanese culture"}})
38
+ * @param params.customFields - Custom field values for AI-generated content (e.g., {topic_category: "history"})
39
+ * @param params.skipDbSave - If true, don't save generated content to database
40
+ * @param params.isPrivate - If true, content is guild-specific
41
+ * @returns Existing or newly generated shared content item
42
+ */
43
+ getNew<T>(params: {
44
+ table: string;
45
+ skillType: 'grammar' | 'reading' | 'writing' | 'speaking' | 'listening' | 'understanding';
46
+ placeholders?: Record<string, string>;
47
+ filter?: Record<string, {
48
+ filterType: 'rag' | 'exact' | 'exclude';
49
+ value: string;
50
+ }>;
51
+ customFields?: Record<string, string | number | boolean | null>;
52
+ tool?: ObjectTool;
53
+ skipDbSave?: boolean;
54
+ isPrivate?: boolean;
55
+ }): Promise<SharedContent<T>>;
56
+ /**
57
+ * Search for shared content by topic using RAG (semantic similarity).
58
+ * @param tableName - Name of the shared content table
59
+ * @param topic - Topic to search for
60
+ * @param limit - Maximum number of results
61
+ * @returns Array of similar shared content
62
+ */
63
+ searchByTopic<T>(tableName: string, topic: string, limit?: number): Promise<SharedContent<T>[]>;
64
+ /**
65
+ * Get bookmarked shared content.
66
+ * @param tableName - Name of the shared content table
67
+ * @param limit - Maximum number of results
68
+ * @returns Array of bookmarked content
69
+ */
70
+ getBookmarked<T>(tableName: string, limit?: number): Promise<SharedContent<T>[]>;
71
+ /**
72
+ * Get ongoing shared content.
73
+ * @param tableName - Name of the shared content table
74
+ * @param limit - Maximum number of results
75
+ * @returns Array of ongoing content
76
+ */
77
+ getOngoing<T>(tableName: string, limit?: number): Promise<SharedContent<T>[]>;
78
+ /**
79
+ * Get completed shared content.
80
+ * @param tableName - Name of the shared content table
81
+ * @param limit - Maximum number of results
82
+ * @returns Array of completed content
83
+ */
84
+ getCompleted<T>(tableName: string, limit?: number): Promise<SharedContent<T>[]>;
85
+ /**
86
+ * Mark shared content as completed.
87
+ * @param tableName - Name of the shared content table
88
+ * @param contentId - ID of the content to mark as completed
89
+ */
90
+ complete(tableName: string, contentId: string): Promise<void>;
91
+ /**
92
+ * Update the state of shared content.
93
+ * @param tableName - Name of the shared content table
94
+ * @param contentId - ID of the content
95
+ * @param state - New state
96
+ */
97
+ updateState(tableName: string, contentId: string, state: 'completed' | 'ongoing' | 'hidden'): Promise<void>;
98
+ /**
99
+ * Bookmark or unbookmark shared content.
100
+ * @param tableName - Name of the shared content table
101
+ * @param contentId - ID of the content
102
+ * @param bookmarked - Whether to bookmark or unbookmark
103
+ */
104
+ bookmark(tableName: string, contentId: string, bookmarked: boolean): Promise<void>;
105
+ /**
106
+ * React to shared content with like/dislike.
107
+ * @param tableName - Name of the shared content table
108
+ * @param contentId - ID of the content
109
+ * @param reaction - Reaction type or null to remove reaction
110
+ */
111
+ react(tableName: string, contentId: string, reaction: 'liked' | 'disliked' | null): Promise<void>;
112
+ /**
113
+ * Get a specific shared content item by ID.
114
+ * @param tableName - Name of the shared content table
115
+ * @param contentId - ID of the content
116
+ * @returns The shared content item
117
+ */
118
+ get<T = any>(tableName: string, contentId: string): Promise<SharedContent<T>>;
119
+ /**
120
+ * Create new shared content manually.
121
+ * @param tableName - Name of the shared content table
122
+ * @param content - Content to create
123
+ * @returns Created content
124
+ */
125
+ create<T = any>(tableName: string, content: Omit<SharedContent<T>, 'id' | 'created_at' | 'created_by'>): Promise<SharedContent<T>>;
126
+ /**
127
+ * Update existing shared content.
128
+ * @param tableName - Name of the shared content table
129
+ * @param contentId - ID of the content to update
130
+ * @param updates - Updates to apply
131
+ * @returns Updated content
132
+ */
133
+ update<T = any>(tableName: string, contentId: string, updates: Partial<SharedContent<T>>): Promise<SharedContent<T>>;
134
+ /**
135
+ * Delete shared content.
136
+ * @param tableName - Name of the shared content table
137
+ * @param contentId - ID of the content to delete
138
+ */
139
+ remove(tableName: string, contentId: string): Promise<void>;
140
+ private getCompletedTableName;
141
+ private getTableName;
142
+ }