@rimori/client 2.5.26 → 2.5.27-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/cli/scripts/release/release-prompts-upload.d.ts +8 -0
- package/dist/cli/scripts/release/release-prompts-upload.js +88 -0
- package/dist/cli/scripts/release/release.js +4 -3
- package/dist/cli/types/DatabaseTypes.d.ts +47 -4
- package/dist/cli/types/PromptTypes.d.ts +78 -0
- package/dist/cli/types/PromptTypes.js +3 -0
- package/dist/controller/TranslationController.js +6 -8
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/plugin/RimoriClient.js +1 -1
- package/dist/plugin/module/AIModule.d.ts +34 -15
- package/dist/plugin/module/AIModule.js +75 -37
- package/dist/plugin/module/DbModule.d.ts +22 -0
- package/dist/plugin/module/DbModule.js +22 -4
- package/dist/plugin/module/EventModule.d.ts +7 -0
- package/dist/plugin/module/EventModule.js +9 -0
- package/package.json +2 -2
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Config } from './release';
|
|
2
|
+
/**
|
|
3
|
+
* Read and send the prompts configuration to the release endpoint.
|
|
4
|
+
* Mirrors the pattern of release-db-update.ts.
|
|
5
|
+
* @param config - Configuration object
|
|
6
|
+
* @param release_id - The release ID
|
|
7
|
+
*/
|
|
8
|
+
export default function promptsUpload(config: Config, release_id: string): Promise<void>;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import fs from 'fs';
|
|
11
|
+
import path from 'path';
|
|
12
|
+
import ts from 'typescript';
|
|
13
|
+
/**
|
|
14
|
+
* Read and send the prompts configuration to the release endpoint.
|
|
15
|
+
* Mirrors the pattern of release-db-update.ts.
|
|
16
|
+
* @param config - Configuration object
|
|
17
|
+
* @param release_id - The release ID
|
|
18
|
+
*/
|
|
19
|
+
export default function promptsUpload(config, release_id) {
|
|
20
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
21
|
+
var _a, _b;
|
|
22
|
+
const promptsConfigPath = path.resolve('./rimori/prompts.config.ts');
|
|
23
|
+
// Check if prompts config file exists — optional, skip if not present
|
|
24
|
+
try {
|
|
25
|
+
yield fs.promises.access(promptsConfigPath);
|
|
26
|
+
}
|
|
27
|
+
catch (e) {
|
|
28
|
+
return; // No prompts.config.ts — silently skip
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
// Use TypeScript compiler to transpile and load
|
|
32
|
+
const promptsContent = yield fs.promises.readFile(promptsConfigPath, 'utf8');
|
|
33
|
+
// Transpile TypeScript to JavaScript
|
|
34
|
+
const result = ts.transpile(promptsContent, {
|
|
35
|
+
target: ts.ScriptTarget.ES2020,
|
|
36
|
+
module: ts.ModuleKind.ES2020,
|
|
37
|
+
});
|
|
38
|
+
// Create a temporary file to import the transpiled code
|
|
39
|
+
const tempFile = path.join(process.cwd(), 'temp_prompts_config.js');
|
|
40
|
+
yield fs.promises.writeFile(tempFile, result);
|
|
41
|
+
let prompts;
|
|
42
|
+
try {
|
|
43
|
+
const promptsModule = yield import(`file://${tempFile}`);
|
|
44
|
+
// Collect all named exports as individual prompt definitions
|
|
45
|
+
prompts = Object.values(promptsModule);
|
|
46
|
+
yield fs.promises.unlink(tempFile);
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
try {
|
|
50
|
+
yield fs.promises.unlink(tempFile);
|
|
51
|
+
}
|
|
52
|
+
catch (e) { }
|
|
53
|
+
throw error;
|
|
54
|
+
}
|
|
55
|
+
if (!Array.isArray(prompts) || prompts.length === 0) {
|
|
56
|
+
console.warn('⚠️ prompts.config.ts has no exports. Skipping.');
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
console.log(`📝 Sending ${prompts.length} prompt definitions...`);
|
|
60
|
+
const requestBody = {
|
|
61
|
+
prompts,
|
|
62
|
+
version: config.version,
|
|
63
|
+
release_channel: config.release_channel,
|
|
64
|
+
plugin_id: config.plugin_id,
|
|
65
|
+
};
|
|
66
|
+
const response = yield fetch(`${config.domain}/release/${release_id}/prompts`, {
|
|
67
|
+
method: 'POST',
|
|
68
|
+
headers: {
|
|
69
|
+
'Content-Type': 'application/json',
|
|
70
|
+
Authorization: `Bearer ${config.token}`,
|
|
71
|
+
},
|
|
72
|
+
body: JSON.stringify(requestBody),
|
|
73
|
+
});
|
|
74
|
+
if (response.ok) {
|
|
75
|
+
const data = yield response.json();
|
|
76
|
+
console.log(`✅ Prompts uploaded: ${(_b = (_a = data.prompt_names) === null || _a === void 0 ? void 0 : _a.join(', ')) !== null && _b !== void 0 ? _b : 'ok'}`);
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
const text = yield response.text().catch(() => 'unknown error');
|
|
80
|
+
throw new Error(`Failed to upload prompts: ${text}`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
console.error('❌ Error uploading prompts:', error.message);
|
|
85
|
+
throw error;
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
}
|
|
@@ -23,6 +23,7 @@ import 'dotenv/config';
|
|
|
23
23
|
import fs from 'fs';
|
|
24
24
|
import path from 'path';
|
|
25
25
|
import dbUpdate from './release-db-update.js';
|
|
26
|
+
import promptsUpload from './release-prompts-upload.js';
|
|
26
27
|
import { uploadDirectory } from './release-file-upload.js';
|
|
27
28
|
import { releasePlugin, sendConfiguration } from './release-config-upload.js';
|
|
28
29
|
// Read version from package.json
|
|
@@ -42,9 +43,6 @@ if (!releaseChannel) {
|
|
|
42
43
|
console.error('Usage: rimori-release <release_channel>');
|
|
43
44
|
process.exit(1);
|
|
44
45
|
}
|
|
45
|
-
if (process.env.RIMORI_BACKEND_URL) {
|
|
46
|
-
console.info('Using backend url:', process.env.RIMORI_BACKEND_URL);
|
|
47
|
-
}
|
|
48
46
|
const config = {
|
|
49
47
|
version,
|
|
50
48
|
release_channel: releaseChannel,
|
|
@@ -60,8 +58,11 @@ function releaseProcess() {
|
|
|
60
58
|
return __awaiter(this, void 0, void 0, function* () {
|
|
61
59
|
try {
|
|
62
60
|
console.log(`🚀 Releasing ${config.plugin_id} to ${config.release_channel}...`);
|
|
61
|
+
console.log(`📡 Deploying to: ${config.domain}`);
|
|
63
62
|
// First send the configuration
|
|
64
63
|
const release_id = yield sendConfiguration(config);
|
|
64
|
+
// Upload prompts (if prompts.config.ts exists)
|
|
65
|
+
yield promptsUpload(config, release_id);
|
|
65
66
|
yield dbUpdate(config, release_id);
|
|
66
67
|
// Then upload the files
|
|
67
68
|
yield uploadDirectory(config, release_id);
|
|
@@ -8,7 +8,15 @@
|
|
|
8
8
|
* 2. Add an `updated_at` trigger so the image-sync cron can detect recently
|
|
9
9
|
* modified entries. The cron derives which columns to scan from release.db_schema.
|
|
10
10
|
*/
|
|
11
|
-
|
|
11
|
+
/**
|
|
12
|
+
* 'vector' is stored as `vector(1536)` in the database (pgvector).
|
|
13
|
+
* Marking a column as 'vector' causes the migration system to:
|
|
14
|
+
* 1. Create the column as `vector(1536)` with nullable constraint.
|
|
15
|
+
* 2. Create an IVFFlat index for cosine similarity search.
|
|
16
|
+
* 3. The column MUST be named 'embedding' and only one per table is allowed.
|
|
17
|
+
* 4. Requires `source_column` — the column whose content is embedded async on insert.
|
|
18
|
+
*/
|
|
19
|
+
type DbColumnType = 'decimal' | 'integer' | 'text' | 'boolean' | 'json' | 'timestamp' | 'uuid' | 'markdown' | 'vector';
|
|
12
20
|
/**
|
|
13
21
|
* Foreign key relationship configuration with cascade delete support.
|
|
14
22
|
* Defines a relationship where the source record is deleted when the destination record is deleted.
|
|
@@ -22,11 +30,11 @@ interface ForeignKeyRelation {
|
|
|
22
30
|
on_delete_cascade: boolean;
|
|
23
31
|
}
|
|
24
32
|
/**
|
|
25
|
-
*
|
|
33
|
+
* Regular (non-vector) database column definition with support for types, constraints, and relationships.
|
|
26
34
|
*/
|
|
27
|
-
|
|
35
|
+
interface DbRegularColumnDefinition {
|
|
28
36
|
/** The data type of the column */
|
|
29
|
-
type: DbColumnType
|
|
37
|
+
type: Exclude<DbColumnType, 'vector'>;
|
|
30
38
|
/** Human-readable description of the column's purpose */
|
|
31
39
|
description: string;
|
|
32
40
|
/** Whether the column can contain null values */
|
|
@@ -36,6 +44,8 @@ export interface DbColumnDefinition {
|
|
|
36
44
|
/** Default value for the column. can also use sql functions like now(), auth.uid() or gen_random_uuid() */
|
|
37
45
|
default_value?: string | number | boolean;
|
|
38
46
|
/** Array of allowed values for enumerated columns */
|
|
47
|
+
/** Not allowed on non-vector columns */
|
|
48
|
+
source_column?: never;
|
|
39
49
|
/** Foreign key relationship configuration */
|
|
40
50
|
foreign_key?: ForeignKeyRelation;
|
|
41
51
|
/** The name of the column before it was renamed. */
|
|
@@ -55,6 +65,39 @@ export interface DbColumnDefinition {
|
|
|
55
65
|
lang_moderator?: Partial<Omit<DbPermissionDefinition, 'delete'>>;
|
|
56
66
|
};
|
|
57
67
|
}
|
|
68
|
+
/**
|
|
69
|
+
* Vector column definition for semantic search via pgvector.
|
|
70
|
+
* The column MUST be named 'embedding' and only one per table is allowed.
|
|
71
|
+
* The backend generates embeddings asynchronously from the source_column content.
|
|
72
|
+
*/
|
|
73
|
+
interface DbVectorColumnDefinition {
|
|
74
|
+
/** Must be 'vector' */
|
|
75
|
+
type: 'vector';
|
|
76
|
+
/** Human-readable description of the column's purpose */
|
|
77
|
+
description: string;
|
|
78
|
+
/** Vector columns must be nullable (embeddings are generated asynchronously) */
|
|
79
|
+
nullable: true;
|
|
80
|
+
/** The column whose content is embedded. Must reference an existing column in the same table. */
|
|
81
|
+
source_column: string;
|
|
82
|
+
/** Not applicable to vector columns */
|
|
83
|
+
unique?: never;
|
|
84
|
+
/** Not applicable to vector columns */
|
|
85
|
+
default_value?: never;
|
|
86
|
+
/** Not applicable to vector columns */
|
|
87
|
+
foreign_key?: never;
|
|
88
|
+
/** Not applicable to vector columns */
|
|
89
|
+
old_name?: never;
|
|
90
|
+
/** Not applicable to vector columns */
|
|
91
|
+
deprecated?: never;
|
|
92
|
+
/** Not applicable to vector columns */
|
|
93
|
+
restrict?: never;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Database column definition — discriminated union on `type`.
|
|
97
|
+
* Use `type: 'vector'` for embedding columns (enforces `nullable: true` and requires `source_column`).
|
|
98
|
+
* All other types forbid `source_column`.
|
|
99
|
+
*/
|
|
100
|
+
export type DbColumnDefinition = DbRegularColumnDefinition | DbVectorColumnDefinition;
|
|
58
101
|
/**
|
|
59
102
|
* Base table structure that all database tables inherit.
|
|
60
103
|
* Includes standard audit fields for tracking creation and ownership.
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Formatting options for string array variables when rendered into prompts.
|
|
3
|
+
*/
|
|
4
|
+
export type StringArrayFormat = 'numberedList' | 'bulletpointList' | 'commaList' | 'newlineList';
|
|
5
|
+
/**
|
|
6
|
+
* Enum variable resolved server-side from a fixed set of values.
|
|
7
|
+
* Supports conditional prompt text per value.
|
|
8
|
+
*/
|
|
9
|
+
export interface EnumVariable {
|
|
10
|
+
type: 'enum';
|
|
11
|
+
values: string[];
|
|
12
|
+
conditions?: Record<string, string>;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Numeric variable with min/max bounds.
|
|
16
|
+
* Supports conditional prompt text per value.
|
|
17
|
+
*/
|
|
18
|
+
export interface NumberVariable {
|
|
19
|
+
type: 'number';
|
|
20
|
+
min: number;
|
|
21
|
+
max: number;
|
|
22
|
+
conditions?: Record<string, string>;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Free-text string variable with optional prefix/suffix wrappers.
|
|
26
|
+
*/
|
|
27
|
+
export interface StringVariable {
|
|
28
|
+
type: 'string';
|
|
29
|
+
pre?: string;
|
|
30
|
+
after?: string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Array-of-strings variable with optional formatting and prefix/suffix wrappers.
|
|
34
|
+
*/
|
|
35
|
+
export interface StringArrayVariable {
|
|
36
|
+
type: 'string[]';
|
|
37
|
+
format?: StringArrayFormat;
|
|
38
|
+
pre?: string;
|
|
39
|
+
after?: string;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* UUID variable referencing a backend entity by ID.
|
|
43
|
+
* The backend resolves the UUID to a formatted string via a registered resolver.
|
|
44
|
+
* Safe in system instructions because the resolved content is backend-controlled.
|
|
45
|
+
*/
|
|
46
|
+
export interface UuidVariable {
|
|
47
|
+
type: 'uuid';
|
|
48
|
+
/** The resolver name that tells the backend how to look up and format this UUID. */
|
|
49
|
+
resolver: string;
|
|
50
|
+
pre?: string;
|
|
51
|
+
after?: string;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Variables allowed in system instruction blocks.
|
|
55
|
+
*/
|
|
56
|
+
export type SystemVariable = EnumVariable | NumberVariable | UuidVariable;
|
|
57
|
+
/**
|
|
58
|
+
* Variables allowed in user instruction blocks (superset of system variables).
|
|
59
|
+
*/
|
|
60
|
+
export type UserVariable = SystemVariable | StringVariable | StringArrayVariable;
|
|
61
|
+
/**
|
|
62
|
+
* A block of prompt text with typed template variables.
|
|
63
|
+
*/
|
|
64
|
+
export interface InstructionBlock<V> {
|
|
65
|
+
prompt: string;
|
|
66
|
+
variables?: Record<string, V>;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* A complete prompt definition uploaded to the backend during release.
|
|
70
|
+
*/
|
|
71
|
+
export interface PromptDefinition {
|
|
72
|
+
name: string;
|
|
73
|
+
systemInstructions?: InstructionBlock<SystemVariable>;
|
|
74
|
+
userInstructions?: InstructionBlock<UserVariable>;
|
|
75
|
+
schema?: Record<string, any>;
|
|
76
|
+
tools?: any[];
|
|
77
|
+
model?: string;
|
|
78
|
+
}
|
|
@@ -161,15 +161,13 @@ export class Translator {
|
|
|
161
161
|
if (!this.ai || this.currentLanguage === 'en')
|
|
162
162
|
return text;
|
|
163
163
|
const response = yield this.ai.getObject({
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
type: 'string',
|
|
170
|
-
description: `The translation of the input text into ${this.currentLanguage}.`,
|
|
171
|
-
},
|
|
164
|
+
prompt: 'global.translator.translate',
|
|
165
|
+
variables: {
|
|
166
|
+
additionalInstructions: additionalInstructions !== null && additionalInstructions !== void 0 ? additionalInstructions : '',
|
|
167
|
+
language: this.currentLanguage,
|
|
168
|
+
text,
|
|
172
169
|
},
|
|
170
|
+
cache: true,
|
|
173
171
|
});
|
|
174
172
|
const translation = response === null || response === void 0 ? void 0 : response.translation;
|
|
175
173
|
if (translation) {
|
package/dist/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export * from './plugin/RimoriClient';
|
|
|
3
3
|
export * from './fromRimori/PluginTypes';
|
|
4
4
|
export * from './plugin/StandaloneClient';
|
|
5
5
|
export * from './cli/types/DatabaseTypes';
|
|
6
|
+
export * from './cli/types/PromptTypes';
|
|
6
7
|
export * from './plugin/TTS/MessageSender';
|
|
7
8
|
export * from './utils/difficultyConverter';
|
|
8
9
|
export * from './plugin/CommunicationHandler';
|
package/dist/index.js
CHANGED
|
@@ -4,6 +4,7 @@ export * from './plugin/RimoriClient';
|
|
|
4
4
|
export * from './fromRimori/PluginTypes';
|
|
5
5
|
export * from './plugin/StandaloneClient';
|
|
6
6
|
export * from './cli/types/DatabaseTypes';
|
|
7
|
+
export * from './cli/types/PromptTypes';
|
|
7
8
|
export * from './plugin/TTS/MessageSender';
|
|
8
9
|
export * from './utils/difficultyConverter';
|
|
9
10
|
export * from './plugin/CommunicationHandler';
|
|
@@ -31,7 +31,7 @@ export class RimoriClient {
|
|
|
31
31
|
};
|
|
32
32
|
this.rimoriInfo = info;
|
|
33
33
|
this.sharedContent = new SharedContentController(supabase, this);
|
|
34
|
-
this.ai = new AIModule(info.backendUrl, () => this.rimoriInfo.token);
|
|
34
|
+
this.ai = new AIModule(info.backendUrl, () => this.rimoriInfo.token, info.pluginId);
|
|
35
35
|
this.ai.setOnRateLimited((exercisesRemaining) => {
|
|
36
36
|
EventBus.emit(info.pluginId, 'global.quota.triggerExceeded', { exercises_remaining: exercisesRemaining });
|
|
37
37
|
});
|
|
@@ -44,11 +44,13 @@ export interface ObjectRequest {
|
|
|
44
44
|
* High level instructions for the AI to follow. Behaviour, tone, restrictions, etc.
|
|
45
45
|
* Example: "Act like a recipe writer."
|
|
46
46
|
*/
|
|
47
|
+
/** @deprecated Use server-side prompt definitions (prompt + variables) instead of building requests client-side. */
|
|
47
48
|
behaviour?: string;
|
|
48
49
|
/**
|
|
49
50
|
* The specific instruction for the AI to follow.
|
|
50
51
|
* Example: "Generate a recipe using chicken, rice and vegetables."
|
|
51
52
|
*/
|
|
53
|
+
/** @deprecated Use server-side prompt definitions (prompt + variables) instead of building requests client-side. */
|
|
52
54
|
instructions: string;
|
|
53
55
|
}
|
|
54
56
|
/**
|
|
@@ -58,9 +60,16 @@ export interface ObjectRequest {
|
|
|
58
60
|
export declare class AIModule {
|
|
59
61
|
private getToken;
|
|
60
62
|
private backendUrl;
|
|
63
|
+
private pluginId;
|
|
61
64
|
private sessionTokenId;
|
|
62
65
|
private onRateLimitedCb?;
|
|
63
|
-
constructor(backendUrl: string, getToken: () => string);
|
|
66
|
+
constructor(backendUrl: string, getToken: () => string, pluginId?: string);
|
|
67
|
+
/**
|
|
68
|
+
* Resolves a prompt name following the event naming convention:
|
|
69
|
+
* - 2-segment names (e.g. 'storytelling.story') get prefixed with pluginId → '<pluginId>.storytelling.story'
|
|
70
|
+
* - 3+ segment names starting with 'global.' (e.g. 'global.translator.translate') are sent as-is
|
|
71
|
+
*/
|
|
72
|
+
private resolvePromptName;
|
|
64
73
|
/** Exercise session management. */
|
|
65
74
|
readonly session: {
|
|
66
75
|
/** Returns the current exercise session token ID (null if no active session). */
|
|
@@ -94,7 +103,9 @@ export declare class AIModule {
|
|
|
94
103
|
* @param cache Whether to cache the result (default: false).
|
|
95
104
|
* @param model The model to use for generation.
|
|
96
105
|
*/
|
|
97
|
-
getSteamedText(messages: Message[], onMessage: OnLLMResponse, tools?: Tool[], cache?: boolean, model?: string,
|
|
106
|
+
getSteamedText(messages: Message[], onMessage: OnLLMResponse, tools?: Tool[], cache?: boolean, model?: string,
|
|
107
|
+
/** @deprecated Use uuid variable with resolver 'knowledgeEntry' in prompt definitions instead. */
|
|
108
|
+
knowledgeId?: string, prompt?: string, variables?: Record<string, any>): Promise<string>;
|
|
98
109
|
/**
|
|
99
110
|
* Generate voice audio from text using AI.
|
|
100
111
|
* @param text The text to convert to voice.
|
|
@@ -112,48 +123,56 @@ export declare class AIModule {
|
|
|
112
123
|
* @returns The transcribed text.
|
|
113
124
|
*/
|
|
114
125
|
getTextFromVoice(file: Blob, language?: Language): Promise<string>;
|
|
126
|
+
/** @deprecated Used by legacy client-side prompt path. Will be removed once all plugins migrate to server-side prompt definitions. */
|
|
115
127
|
private getChatMessage;
|
|
116
128
|
/**
|
|
117
129
|
* Generate a structured object from a request using AI.
|
|
118
|
-
* @param request The object generation request.
|
|
119
|
-
* @param request.systemPrompt The system prompt to use for generation.
|
|
120
|
-
* @param request.responseSchema The response schema to use for generation.
|
|
121
|
-
* @param request.userPrompt The user prompt to use for generation.
|
|
122
130
|
* @param request.cache Whether to cache the result (default: false).
|
|
123
131
|
* @param request.tools The tools to use for generation.
|
|
124
132
|
* @param request.model The model to use for generation.
|
|
133
|
+
* @param request.prompt Server-side prompt name (e.g. 'writing.analysis').
|
|
134
|
+
* @param request.variables Variables for the server-side prompt template.
|
|
125
135
|
* @returns The generated object.
|
|
126
136
|
*/
|
|
127
137
|
getObject<T = any>(params: {
|
|
128
|
-
|
|
129
|
-
|
|
138
|
+
/** @deprecated Use prompt + variables instead of client-side system prompts. */
|
|
139
|
+
systemPrompt?: string;
|
|
140
|
+
/** @deprecated Use prompt + variables instead. Schema is loaded server-side from the prompt definition. */
|
|
141
|
+
responseSchema?: AIObjectTool;
|
|
142
|
+
/** @deprecated Use prompt + variables instead of client-side user prompts. */
|
|
130
143
|
userPrompt?: string;
|
|
131
144
|
cache?: boolean;
|
|
132
145
|
tools?: Tool[];
|
|
133
146
|
model?: string;
|
|
147
|
+
/** @deprecated Use uuid variable with resolver 'knowledgeEntry' in prompt definitions instead. */
|
|
134
148
|
knowledgeId?: string;
|
|
149
|
+
prompt?: string;
|
|
150
|
+
variables?: Record<string, any>;
|
|
135
151
|
}): Promise<T>;
|
|
136
152
|
/**
|
|
137
153
|
* Generate a streamed structured object from a request using AI.
|
|
138
|
-
* @param request The object generation request.
|
|
139
|
-
* @param request.systemPrompt The system prompt to use for generation.
|
|
140
|
-
* @param request.responseSchema The response schema to use for generation.
|
|
141
|
-
* @param request.userPrompt The user prompt to use for generation.
|
|
142
154
|
* @param request.onResult Callback for each result chunk.
|
|
143
155
|
* @param request.cache Whether to cache the result (default: false).
|
|
144
156
|
* @param request.tools The tools to use for generation.
|
|
145
157
|
* @param request.model The model to use for generation.
|
|
146
|
-
* @param request.
|
|
158
|
+
* @param request.prompt Server-side prompt name (e.g. 'writing.analysis').
|
|
159
|
+
* @param request.variables Variables for the server-side prompt template.
|
|
147
160
|
*/
|
|
148
161
|
getStreamedObject<T = any>(params: {
|
|
149
|
-
|
|
150
|
-
|
|
162
|
+
/** @deprecated Use prompt + variables instead of client-side system prompts. */
|
|
163
|
+
systemPrompt?: string;
|
|
164
|
+
/** @deprecated Use prompt + variables instead. Schema is loaded server-side from the prompt definition. */
|
|
165
|
+
responseSchema?: AIObjectTool;
|
|
166
|
+
/** @deprecated Use prompt + variables instead of client-side user prompts. */
|
|
151
167
|
userPrompt?: string;
|
|
152
168
|
onResult: OnStreamedObjectResult<T>;
|
|
153
169
|
cache?: boolean;
|
|
154
170
|
tools?: Tool[];
|
|
155
171
|
model?: string;
|
|
172
|
+
/** @deprecated Use uuid variable with resolver 'knowledgeEntry' in prompt definitions instead. */
|
|
156
173
|
knowledgeId?: string;
|
|
174
|
+
prompt?: string;
|
|
175
|
+
variables?: Record<string, any>;
|
|
157
176
|
}): Promise<T>;
|
|
158
177
|
private streamObject;
|
|
159
178
|
private sendToolResult;
|
|
@@ -12,7 +12,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
12
12
|
* Provides access to text generation, voice synthesis, and object generation.
|
|
13
13
|
*/
|
|
14
14
|
export class AIModule {
|
|
15
|
-
constructor(backendUrl, getToken) {
|
|
15
|
+
constructor(backendUrl, getToken, pluginId) {
|
|
16
16
|
this.sessionTokenId = null;
|
|
17
17
|
/** Exercise session management. */
|
|
18
18
|
this.session = {
|
|
@@ -53,6 +53,21 @@ export class AIModule {
|
|
|
53
53
|
};
|
|
54
54
|
this.backendUrl = backendUrl;
|
|
55
55
|
this.getToken = getToken;
|
|
56
|
+
this.pluginId = pluginId;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Resolves a prompt name following the event naming convention:
|
|
60
|
+
* - 2-segment names (e.g. 'storytelling.story') get prefixed with pluginId → '<pluginId>.storytelling.story'
|
|
61
|
+
* - 3+ segment names starting with 'global.' (e.g. 'global.translator.translate') are sent as-is
|
|
62
|
+
*/
|
|
63
|
+
resolvePromptName(name) {
|
|
64
|
+
if (name.startsWith('global.'))
|
|
65
|
+
return name;
|
|
66
|
+
const segments = name.split('.');
|
|
67
|
+
if (segments.length === 2 && this.pluginId) {
|
|
68
|
+
return `${this.pluginId}.${name}`;
|
|
69
|
+
}
|
|
70
|
+
return name;
|
|
56
71
|
}
|
|
57
72
|
/** Registers a callback invoked whenever a 429 rate-limit response is received. */
|
|
58
73
|
setOnRateLimited(cb) {
|
|
@@ -73,11 +88,6 @@ export class AIModule {
|
|
|
73
88
|
tools,
|
|
74
89
|
model,
|
|
75
90
|
messages,
|
|
76
|
-
responseSchema: {
|
|
77
|
-
result: {
|
|
78
|
-
type: 'string',
|
|
79
|
-
},
|
|
80
|
-
},
|
|
81
91
|
});
|
|
82
92
|
return result;
|
|
83
93
|
});
|
|
@@ -91,7 +101,9 @@ export class AIModule {
|
|
|
91
101
|
* @param model The model to use for generation.
|
|
92
102
|
*/
|
|
93
103
|
getSteamedText(messages_1, onMessage_1, tools_1) {
|
|
94
|
-
return __awaiter(this, arguments, void 0, function* (messages, onMessage, tools, cache = false, model,
|
|
104
|
+
return __awaiter(this, arguments, void 0, function* (messages, onMessage, tools, cache = false, model,
|
|
105
|
+
/** @deprecated Use uuid variable with resolver 'knowledgeEntry' in prompt definitions instead. */
|
|
106
|
+
knowledgeId, prompt, variables) {
|
|
95
107
|
const messageId = Math.random().toString(36).substring(3);
|
|
96
108
|
const { result } = yield this.streamObject({
|
|
97
109
|
cache,
|
|
@@ -99,11 +111,8 @@ export class AIModule {
|
|
|
99
111
|
model,
|
|
100
112
|
messages,
|
|
101
113
|
knowledgeId,
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
type: 'string',
|
|
105
|
-
},
|
|
106
|
-
},
|
|
114
|
+
prompt,
|
|
115
|
+
variables,
|
|
107
116
|
onResult: ({ result }) => onMessage(messageId, result, false),
|
|
108
117
|
});
|
|
109
118
|
onMessage(messageId, result, true);
|
|
@@ -129,7 +138,15 @@ export class AIModule {
|
|
|
129
138
|
'Content-Type': 'application/json',
|
|
130
139
|
Authorization: `Bearer ${this.getToken()}`,
|
|
131
140
|
},
|
|
132
|
-
body: JSON.stringify({
|
|
141
|
+
body: JSON.stringify({
|
|
142
|
+
input: text,
|
|
143
|
+
voice,
|
|
144
|
+
speed,
|
|
145
|
+
language,
|
|
146
|
+
cache,
|
|
147
|
+
instructions,
|
|
148
|
+
session_token_id: (_a = this.sessionTokenId) !== null && _a !== void 0 ? _a : undefined,
|
|
149
|
+
}),
|
|
133
150
|
}).then((r) => r.blob());
|
|
134
151
|
});
|
|
135
152
|
}
|
|
@@ -162,6 +179,7 @@ export class AIModule {
|
|
|
162
179
|
});
|
|
163
180
|
});
|
|
164
181
|
}
|
|
182
|
+
/** @deprecated Used by legacy client-side prompt path. Will be removed once all plugins migrate to server-side prompt definitions. */
|
|
165
183
|
getChatMessage(systemPrompt, userPrompt) {
|
|
166
184
|
const messages = [{ role: 'system', content: systemPrompt }];
|
|
167
185
|
if (userPrompt) {
|
|
@@ -171,70 +189,75 @@ export class AIModule {
|
|
|
171
189
|
}
|
|
172
190
|
/**
|
|
173
191
|
* Generate a structured object from a request using AI.
|
|
174
|
-
* @param request The object generation request.
|
|
175
|
-
* @param request.systemPrompt The system prompt to use for generation.
|
|
176
|
-
* @param request.responseSchema The response schema to use for generation.
|
|
177
|
-
* @param request.userPrompt The user prompt to use for generation.
|
|
178
192
|
* @param request.cache Whether to cache the result (default: false).
|
|
179
193
|
* @param request.tools The tools to use for generation.
|
|
180
194
|
* @param request.model The model to use for generation.
|
|
195
|
+
* @param request.prompt Server-side prompt name (e.g. 'writing.analysis').
|
|
196
|
+
* @param request.variables Variables for the server-side prompt template.
|
|
181
197
|
* @returns The generated object.
|
|
182
198
|
*/
|
|
183
199
|
getObject(params) {
|
|
184
200
|
return __awaiter(this, void 0, void 0, function* () {
|
|
185
|
-
const { systemPrompt, responseSchema, userPrompt, cache = false, tools = [], model = undefined, knowledgeId, } = params;
|
|
201
|
+
const { systemPrompt, responseSchema, userPrompt, cache = false, tools = [], model = undefined, knowledgeId, prompt, variables, } = params;
|
|
186
202
|
return yield this.streamObject({
|
|
187
203
|
responseSchema,
|
|
188
|
-
messages: this.getChatMessage(systemPrompt, userPrompt),
|
|
204
|
+
messages: systemPrompt ? this.getChatMessage(systemPrompt, userPrompt) : [],
|
|
189
205
|
cache,
|
|
190
206
|
tools,
|
|
191
207
|
model,
|
|
192
208
|
knowledgeId,
|
|
209
|
+
prompt,
|
|
210
|
+
variables,
|
|
193
211
|
});
|
|
194
212
|
});
|
|
195
213
|
}
|
|
196
214
|
/**
|
|
197
215
|
* Generate a streamed structured object from a request using AI.
|
|
198
|
-
* @param request The object generation request.
|
|
199
|
-
* @param request.systemPrompt The system prompt to use for generation.
|
|
200
|
-
* @param request.responseSchema The response schema to use for generation.
|
|
201
|
-
* @param request.userPrompt The user prompt to use for generation.
|
|
202
216
|
* @param request.onResult Callback for each result chunk.
|
|
203
217
|
* @param request.cache Whether to cache the result (default: false).
|
|
204
218
|
* @param request.tools The tools to use for generation.
|
|
205
219
|
* @param request.model The model to use for generation.
|
|
206
|
-
* @param request.
|
|
220
|
+
* @param request.prompt Server-side prompt name (e.g. 'writing.analysis').
|
|
221
|
+
* @param request.variables Variables for the server-side prompt template.
|
|
207
222
|
*/
|
|
208
223
|
getStreamedObject(params) {
|
|
209
224
|
return __awaiter(this, void 0, void 0, function* () {
|
|
210
|
-
const { systemPrompt, responseSchema, userPrompt, onResult, cache = false, tools = [], model = undefined, knowledgeId, } = params;
|
|
225
|
+
const { systemPrompt, responseSchema, userPrompt, onResult, cache = false, tools = [], model = undefined, knowledgeId, prompt, variables, } = params;
|
|
211
226
|
return yield this.streamObject({
|
|
212
227
|
responseSchema,
|
|
213
|
-
messages: this.getChatMessage(systemPrompt, userPrompt),
|
|
228
|
+
messages: systemPrompt ? this.getChatMessage(systemPrompt, userPrompt) : [],
|
|
214
229
|
onResult,
|
|
215
230
|
cache,
|
|
216
231
|
tools,
|
|
217
232
|
model,
|
|
218
233
|
knowledgeId,
|
|
234
|
+
prompt,
|
|
235
|
+
variables,
|
|
219
236
|
});
|
|
220
237
|
});
|
|
221
238
|
}
|
|
222
239
|
streamObject(params) {
|
|
223
240
|
return __awaiter(this, void 0, void 0, function* () {
|
|
224
241
|
var _a, _b, _c, _d, _e;
|
|
225
|
-
const { messages, responseSchema, onResult = () => null, cache = false, tools = [], model = undefined, knowledgeId, } = params;
|
|
242
|
+
const { messages, responseSchema, onResult = () => null, cache = false, tools = [], model = undefined, knowledgeId, prompt, variables, } = params;
|
|
226
243
|
const chatMessages = messages.map((message, index) => (Object.assign(Object.assign({}, message), { id: `${index + 1}` })));
|
|
244
|
+
const payload = {
|
|
245
|
+
cache,
|
|
246
|
+
tools,
|
|
247
|
+
stream: true,
|
|
248
|
+
messages: chatMessages,
|
|
249
|
+
model,
|
|
250
|
+
knowledge_id: knowledgeId,
|
|
251
|
+
session_token_id: (_a = this.sessionTokenId) !== null && _a !== void 0 ? _a : undefined,
|
|
252
|
+
};
|
|
253
|
+
if (prompt) {
|
|
254
|
+
payload.prompt = { name: this.resolvePromptName(prompt), variables: variables !== null && variables !== void 0 ? variables : {} };
|
|
255
|
+
}
|
|
256
|
+
if (responseSchema) {
|
|
257
|
+
payload.responseSchema = responseSchema;
|
|
258
|
+
}
|
|
227
259
|
const response = yield fetch(`${this.backendUrl}/ai/llm`, {
|
|
228
|
-
body: JSON.stringify(
|
|
229
|
-
cache,
|
|
230
|
-
tools,
|
|
231
|
-
stream: true,
|
|
232
|
-
responseSchema,
|
|
233
|
-
messages: chatMessages,
|
|
234
|
-
model,
|
|
235
|
-
knowledge_id: knowledgeId,
|
|
236
|
-
session_token_id: (_a = this.sessionTokenId) !== null && _a !== void 0 ? _a : undefined,
|
|
237
|
-
}),
|
|
260
|
+
body: JSON.stringify(payload),
|
|
238
261
|
method: 'POST',
|
|
239
262
|
headers: { Authorization: `Bearer ${this.getToken()}`, 'Content-Type': 'application/json' },
|
|
240
263
|
});
|
|
@@ -300,6 +323,21 @@ export class AIModule {
|
|
|
300
323
|
}
|
|
301
324
|
continue;
|
|
302
325
|
}
|
|
326
|
+
// Handle debug: line (prompt resolution debug info, dev/local only)
|
|
327
|
+
if (line.startsWith('debug:')) {
|
|
328
|
+
try {
|
|
329
|
+
const debug = JSON.parse(line.slice(6).trim());
|
|
330
|
+
console.group(`[Rimori Prompt] ${debug.promptName}`);
|
|
331
|
+
console.log('System prompt:\n', debug.system);
|
|
332
|
+
console.log('User prompt:\n', debug.user);
|
|
333
|
+
console.log('Variables:', debug.variables);
|
|
334
|
+
console.groupEnd();
|
|
335
|
+
}
|
|
336
|
+
catch (_g) {
|
|
337
|
+
// Ignore malformed debug lines
|
|
338
|
+
}
|
|
339
|
+
continue;
|
|
340
|
+
}
|
|
303
341
|
const command = line.substring(0, 5);
|
|
304
342
|
const dataStr = line.substring(5).trim();
|
|
305
343
|
if (dataStr === '[DONE]') {
|
|
@@ -25,6 +25,21 @@ export type PublicityLevel = 'own' | 'guild' | 'lang';
|
|
|
25
25
|
* Database module for plugin database operations.
|
|
26
26
|
* Provides access to plugin tables with automatic prefixing and schema management.
|
|
27
27
|
*/
|
|
28
|
+
export interface VectorSearchParams {
|
|
29
|
+
/** Table name without plugin prefix (e.g. 'pages') */
|
|
30
|
+
tableName: string;
|
|
31
|
+
/** The text query to search for */
|
|
32
|
+
query: string;
|
|
33
|
+
/** Maximum number of results (default: 5) */
|
|
34
|
+
limit?: number;
|
|
35
|
+
/** Similarity threshold 0-1 (default: 0.5) */
|
|
36
|
+
threshold?: number;
|
|
37
|
+
/** Which columns to return (default: all) */
|
|
38
|
+
selectColumns?: string[];
|
|
39
|
+
}
|
|
40
|
+
export type VectorSearchResult<T = Record<string, unknown>> = Array<T & {
|
|
41
|
+
similarity: number;
|
|
42
|
+
}>;
|
|
28
43
|
export declare class DbModule {
|
|
29
44
|
private supabase;
|
|
30
45
|
private rimoriInfo;
|
|
@@ -63,5 +78,12 @@ export declare class DbModule {
|
|
|
63
78
|
* @param publicity The desired publicity level
|
|
64
79
|
*/
|
|
65
80
|
setPublicity(table: string, entryId: string, publicity: PublicityLevel): Promise<void>;
|
|
81
|
+
/**
|
|
82
|
+
* Search a plugin table using vector similarity (cosine distance).
|
|
83
|
+
* The table must have a vector column named 'embedding' defined in db.config.ts.
|
|
84
|
+
* @param params Search parameters
|
|
85
|
+
* @returns Matching rows sorted by similarity
|
|
86
|
+
*/
|
|
87
|
+
vectorSearch<T = Record<string, unknown>>(params: VectorSearchParams): Promise<VectorSearchResult<T>>;
|
|
66
88
|
}
|
|
67
89
|
export {};
|
|
@@ -7,10 +7,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
7
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
|
-
/**
|
|
11
|
-
* Database module for plugin database operations.
|
|
12
|
-
* Provides access to plugin tables with automatic prefixing and schema management.
|
|
13
|
-
*/
|
|
14
10
|
export class DbModule {
|
|
15
11
|
constructor(supabase, communicationHandler, info) {
|
|
16
12
|
this.supabase = supabase;
|
|
@@ -86,4 +82,26 @@ export class DbModule {
|
|
|
86
82
|
});
|
|
87
83
|
});
|
|
88
84
|
}
|
|
85
|
+
/**
|
|
86
|
+
* Search a plugin table using vector similarity (cosine distance).
|
|
87
|
+
* The table must have a vector column named 'embedding' defined in db.config.ts.
|
|
88
|
+
* @param params Search parameters
|
|
89
|
+
* @returns Matching rows sorted by similarity
|
|
90
|
+
*/
|
|
91
|
+
vectorSearch(params) {
|
|
92
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
93
|
+
const response = yield fetch(`${this.rimoriInfo.backendUrl}/plugin-search/vector-search`, {
|
|
94
|
+
method: 'POST',
|
|
95
|
+
headers: {
|
|
96
|
+
'Content-Type': 'application/json',
|
|
97
|
+
Authorization: `Bearer ${this.rimoriInfo.token}`,
|
|
98
|
+
},
|
|
99
|
+
body: JSON.stringify(params),
|
|
100
|
+
});
|
|
101
|
+
if (!response.ok) {
|
|
102
|
+
throw new Error(`Vector search failed: ${response.statusText}`);
|
|
103
|
+
}
|
|
104
|
+
return yield response.json();
|
|
105
|
+
});
|
|
106
|
+
}
|
|
89
107
|
}
|
|
@@ -69,6 +69,13 @@ export declare class EventModule {
|
|
|
69
69
|
* @param text Optional text to be used for the action like for example text that the translator would look up.
|
|
70
70
|
*/
|
|
71
71
|
emitSidebarAction(pluginId: string, actionKey: string, text?: string, args?: Record<string, unknown>): void;
|
|
72
|
+
/**
|
|
73
|
+
* Trigger an action that opens a plugin in the main panel and triggers an action.
|
|
74
|
+
* @param pluginId The id of the plugin to trigger the action for.
|
|
75
|
+
* @param actionKey The key of the action to trigger.
|
|
76
|
+
* @param params Optional additional parameters to pass to the action.
|
|
77
|
+
*/
|
|
78
|
+
emitMainPanelAction(pluginId: string, actionKey: string, params?: Record<string, string>): void;
|
|
72
79
|
/**
|
|
73
80
|
* Subscribe to main panel actions triggered by the user from the dashboard.
|
|
74
81
|
* @param callback Handler function that receives the action data when a matching action is triggered.
|
|
@@ -167,6 +167,15 @@ export class EventModule {
|
|
|
167
167
|
emitSidebarAction(pluginId, actionKey, text, args) {
|
|
168
168
|
this.emit('global.sidebar.triggerAction', { plugin_id: pluginId, action_key: actionKey, text, args });
|
|
169
169
|
}
|
|
170
|
+
/**
|
|
171
|
+
* Trigger an action that opens a plugin in the main panel and triggers an action.
|
|
172
|
+
* @param pluginId The id of the plugin to trigger the action for.
|
|
173
|
+
* @param actionKey The key of the action to trigger.
|
|
174
|
+
* @param params Optional additional parameters to pass to the action.
|
|
175
|
+
*/
|
|
176
|
+
emitMainPanelAction(pluginId, actionKey, params) {
|
|
177
|
+
this.emit('global.mainPanel.triggerAction', Object.assign({ plugin_id: pluginId, action_key: actionKey }, params));
|
|
178
|
+
}
|
|
170
179
|
/**
|
|
171
180
|
* Subscribe to main panel actions triggered by the user from the dashboard.
|
|
172
181
|
* @param callback Handler function that receives the action data when a matching action is triggered.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rimori/client",
|
|
3
|
-
"version": "2.5.
|
|
3
|
+
"version": "2.5.27-next.1",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"repository": {
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
},
|
|
32
32
|
"scripts": {
|
|
33
33
|
"build": "tsc",
|
|
34
|
-
"dev": "tsc -w --preserveWatchOutput",
|
|
34
|
+
"dev": "git pull && tsc -w --preserveWatchOutput",
|
|
35
35
|
"lint": "eslint . --fix",
|
|
36
36
|
"format": "prettier --write ."
|
|
37
37
|
},
|