@rimori/client 1.2.0 → 1.3.0
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/README.md +61 -18
- package/dist/cli/scripts/init/dev-registration.js +0 -1
- package/dist/cli/scripts/init/main.d.ts +1 -1
- package/dist/cli/scripts/init/main.js +1 -0
- package/dist/components/LoggerExample.d.ts +6 -0
- package/dist/components/LoggerExample.js +79 -0
- package/dist/components/ai/Assistant.js +2 -2
- package/dist/components/ai/Avatar.js +2 -2
- package/dist/components/ai/EmbeddedAssistent/VoiceRecoder.js +41 -32
- package/dist/components/audio/Playbutton.js +2 -2
- package/dist/components/components/ContextMenu.js +48 -9
- package/dist/core/controller/AIController.js +202 -69
- package/dist/core/controller/AudioController.d.ts +0 -0
- package/dist/core/controller/AudioController.js +1 -0
- package/dist/core/controller/ObjectController.d.ts +2 -2
- package/dist/core/controller/ObjectController.js +8 -8
- package/dist/core/controller/SettingsController.d.ts +16 -0
- package/dist/core/controller/SharedContentController.d.ts +30 -2
- package/dist/core/controller/SharedContentController.js +74 -23
- package/dist/core/controller/VoiceController.d.ts +2 -3
- package/dist/core/controller/VoiceController.js +11 -4
- package/dist/core/core.d.ts +1 -0
- package/dist/fromRimori/EventBus.js +1 -1
- package/dist/fromRimori/PluginTypes.d.ts +7 -4
- package/dist/hooks/UseChatHook.js +6 -4
- package/dist/hooks/UseLogger.d.ts +30 -0
- package/dist/hooks/UseLogger.js +122 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/plugin/AudioController.d.ts +37 -0
- package/dist/plugin/AudioController.js +68 -0
- package/dist/plugin/Logger.d.ts +68 -0
- package/dist/plugin/Logger.js +256 -0
- package/dist/plugin/LoggerExample.d.ts +16 -0
- package/dist/plugin/LoggerExample.js +140 -0
- package/dist/plugin/PluginController.d.ts +15 -3
- package/dist/plugin/PluginController.js +162 -39
- package/dist/plugin/RimoriClient.d.ts +55 -13
- package/dist/plugin/RimoriClient.js +60 -23
- package/dist/plugin/StandaloneClient.d.ts +1 -0
- package/dist/plugin/StandaloneClient.js +16 -5
- package/dist/plugin/ThemeSetter.d.ts +2 -2
- package/dist/plugin/ThemeSetter.js +8 -5
- package/dist/providers/PluginProvider.d.ts +1 -1
- package/dist/providers/PluginProvider.js +36 -10
- package/dist/utils/audioFormats.d.ts +26 -0
- package/dist/utils/audioFormats.js +67 -0
- package/dist/worker/WorkerSetup.d.ts +3 -2
- package/dist/worker/WorkerSetup.js +22 -67
- package/package.json +2 -1
- package/src/cli/scripts/init/dev-registration.ts +0 -1
- package/src/cli/scripts/init/main.ts +1 -0
- package/src/components/ai/Assistant.tsx +2 -2
- package/src/components/ai/Avatar.tsx +2 -2
- package/src/components/ai/EmbeddedAssistent/VoiceRecoder.tsx +39 -32
- package/src/components/audio/Playbutton.tsx +2 -2
- package/src/components/components/ContextMenu.tsx +53 -9
- package/src/core/controller/AIController.ts +236 -75
- package/src/core/controller/ObjectController.ts +8 -8
- package/src/core/controller/SettingsController.ts +16 -0
- package/src/core/controller/SharedContentController.ts +87 -25
- package/src/core/controller/VoiceController.ts +24 -19
- package/src/core/core.ts +1 -0
- package/src/fromRimori/EventBus.ts +1 -1
- package/src/fromRimori/PluginTypes.ts +6 -4
- package/src/hooks/UseChatHook.ts +6 -4
- package/src/index.ts +1 -0
- package/src/plugin/AudioController.ts +58 -0
- package/src/plugin/Logger.ts +324 -0
- package/src/plugin/PluginController.ts +171 -43
- package/src/plugin/RimoriClient.ts +95 -30
- package/src/plugin/StandaloneClient.ts +22 -6
- package/src/plugin/ThemeSetter.ts +8 -5
- package/src/providers/PluginProvider.tsx +40 -10
- package/src/worker/WorkerSetup.ts +14 -63
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
export type Plugin = Omit<RimoriPluginConfig
|
|
1
|
+
export type Plugin<T extends {} = {}> = Omit<RimoriPluginConfig<T>, 'context_menu_actions'> & {
|
|
2
2
|
version: string;
|
|
3
3
|
endpoint: string;
|
|
4
4
|
assetEndpoint: string;
|
|
5
5
|
context_menu_actions: MenuEntry[];
|
|
6
6
|
release_channel: "alpha" | "beta" | "stable";
|
|
7
7
|
};
|
|
8
|
+
export type ActivePlugin = Plugin<{
|
|
9
|
+
active?: boolean;
|
|
10
|
+
}>;
|
|
8
11
|
export interface PluginPage {
|
|
9
12
|
id: string;
|
|
10
13
|
name: string;
|
|
@@ -43,7 +46,7 @@ export interface ContextMenuAction {
|
|
|
43
46
|
* Rimori plugin structure representing the complete configuration
|
|
44
47
|
* of a Rimori plugin with all metadata and configuration options.
|
|
45
48
|
*/
|
|
46
|
-
export interface RimoriPluginConfig {
|
|
49
|
+
export interface RimoriPluginConfig<T extends {} = {}> {
|
|
47
50
|
id: string;
|
|
48
51
|
/**
|
|
49
52
|
* Basic information about the plugin including branding and core details.
|
|
@@ -65,9 +68,9 @@ export interface RimoriPluginConfig {
|
|
|
65
68
|
/** Optional external URL where the plugin is hosted instead of the default CDN */
|
|
66
69
|
external_hosted_url?: string;
|
|
67
70
|
/** Array of main plugin pages that appear in the application's main navigation (can be disabled using the 'show' flag) */
|
|
68
|
-
main: PluginPage[];
|
|
71
|
+
main: (PluginPage & T)[];
|
|
69
72
|
/** Array of sidebar pages that appear in the sidebar for quick access (can be disabled using the 'show' flag) */
|
|
70
|
-
sidebar: SidebarPage[];
|
|
73
|
+
sidebar: (SidebarPage & T)[];
|
|
71
74
|
/** Optional path to the plugin's settings/configuration page */
|
|
72
75
|
settings?: string;
|
|
73
76
|
/** Optional array of event topics the plugin pages can listen to for cross-plugin communication */
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import {
|
|
2
|
+
import { useRimori } from "../providers/PluginProvider";
|
|
3
3
|
export function useChat(tools) {
|
|
4
4
|
const [messages, setMessages] = React.useState([]);
|
|
5
5
|
const [isLoading, setIsLoading] = React.useState(false);
|
|
6
|
-
const { ai } =
|
|
6
|
+
const { ai } = useRimori();
|
|
7
7
|
const append = (appendMessages) => {
|
|
8
|
-
|
|
8
|
+
const allMessages = [...messages, ...appendMessages];
|
|
9
|
+
setMessages(allMessages);
|
|
10
|
+
ai.getSteamedText(allMessages, (id, message, finished, toolInvocations) => {
|
|
9
11
|
const lastMessage = messages[messages.length - 1];
|
|
10
12
|
setIsLoading(!finished);
|
|
11
13
|
if ((lastMessage === null || lastMessage === void 0 ? void 0 : lastMessage.id) === id) {
|
|
@@ -13,7 +15,7 @@ export function useChat(tools) {
|
|
|
13
15
|
setMessages([...messages, lastMessage]);
|
|
14
16
|
}
|
|
15
17
|
else {
|
|
16
|
-
setMessages([...
|
|
18
|
+
setMessages([...allMessages, { id, role: 'assistant', content: message, toolCalls: toolInvocations }]);
|
|
17
19
|
}
|
|
18
20
|
}, tools);
|
|
19
21
|
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Logger } from '../plugin/Logger';
|
|
2
|
+
/**
|
|
3
|
+
* Hook for initializing the Logger singleton with automatic Rimori client integration.
|
|
4
|
+
* This hook should be called once at the top level of your plugin.
|
|
5
|
+
* @param isProduction - Whether the environment is production
|
|
6
|
+
* @returns Logger instance
|
|
7
|
+
*/
|
|
8
|
+
export declare function useLogger(isProduction: boolean): Logger;
|
|
9
|
+
/**
|
|
10
|
+
* Hook that provides a logger with automatic Rimori client integration.
|
|
11
|
+
* This hook should be used after the plugin is fully initialized.
|
|
12
|
+
* @param isProduction - Whether the environment is production
|
|
13
|
+
* @returns Logger instance with Rimori client set
|
|
14
|
+
*/
|
|
15
|
+
export declare function useLoggerWithRimori(isProduction: boolean): Logger;
|
|
16
|
+
/**
|
|
17
|
+
* Hook for managing logs with simplified interface.
|
|
18
|
+
* Since console methods are overridden globally, this provides utility functions for log management.
|
|
19
|
+
* @param isProduction - Whether the environment is production
|
|
20
|
+
* @returns Object with log management methods
|
|
21
|
+
*/
|
|
22
|
+
export declare function useLogging(isProduction: boolean): {
|
|
23
|
+
sendAllLogs: () => any;
|
|
24
|
+
sendRecentLogs: (count: number) => any;
|
|
25
|
+
sendLogsByLevel: (level: "debug" | "info" | "warn" | "error") => any;
|
|
26
|
+
getStats: () => any;
|
|
27
|
+
exportLogs: () => any;
|
|
28
|
+
clearLogs: () => any;
|
|
29
|
+
restoreConsole: () => any;
|
|
30
|
+
};
|
|
@@ -0,0 +1,122 @@
|
|
|
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 { useEffect, useRef } from 'react';
|
|
11
|
+
import { Logger } from '../plugin/Logger';
|
|
12
|
+
import { usePlugin } from './UseChatHook';
|
|
13
|
+
/**
|
|
14
|
+
* Hook for initializing the Logger singleton with automatic Rimori client integration.
|
|
15
|
+
* This hook should be called once at the top level of your plugin.
|
|
16
|
+
* @param isProduction - Whether the environment is production
|
|
17
|
+
* @returns Logger instance
|
|
18
|
+
*/
|
|
19
|
+
export function useLogger(isProduction) {
|
|
20
|
+
const { event } = usePlugin();
|
|
21
|
+
const loggerRef = useRef(null);
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
// Initialize logger if not already done
|
|
24
|
+
if (!loggerRef.current) {
|
|
25
|
+
loggerRef.current = Logger.getInstance(isProduction);
|
|
26
|
+
}
|
|
27
|
+
// Set up automatic log transmission on certain events
|
|
28
|
+
const handleBeforeUnload = () => {
|
|
29
|
+
if (loggerRef.current) {
|
|
30
|
+
// Send recent logs before page unload
|
|
31
|
+
loggerRef.current.sendRecentLogs(50);
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
const handleError = (event) => {
|
|
35
|
+
// The logger will automatically capture this via console.error override
|
|
36
|
+
console.error('Unhandled error', {
|
|
37
|
+
message: event.message,
|
|
38
|
+
filename: event.filename,
|
|
39
|
+
lineno: event.lineno,
|
|
40
|
+
colno: event.colno,
|
|
41
|
+
error: event.error
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
const handleUnhandledRejection = (event) => {
|
|
45
|
+
// The logger will automatically capture this via console.error override
|
|
46
|
+
console.error('Unhandled promise rejection', {
|
|
47
|
+
reason: event.reason
|
|
48
|
+
});
|
|
49
|
+
};
|
|
50
|
+
// Add event listeners
|
|
51
|
+
window.addEventListener('beforeunload', handleBeforeUnload);
|
|
52
|
+
window.addEventListener('error', handleError);
|
|
53
|
+
window.addEventListener('unhandledrejection', handleUnhandledRejection);
|
|
54
|
+
// Cleanup
|
|
55
|
+
return () => {
|
|
56
|
+
window.removeEventListener('beforeunload', handleBeforeUnload);
|
|
57
|
+
window.removeEventListener('error', handleError);
|
|
58
|
+
window.removeEventListener('unhandledrejection', handleUnhandledRejection);
|
|
59
|
+
};
|
|
60
|
+
}, [isProduction]);
|
|
61
|
+
// Return a proxy that ensures the logger is available
|
|
62
|
+
return new Proxy({}, {
|
|
63
|
+
get(target, prop) {
|
|
64
|
+
if (!loggerRef.current) {
|
|
65
|
+
throw new Error('Logger not initialized');
|
|
66
|
+
}
|
|
67
|
+
return loggerRef.current[prop];
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Hook that provides a logger with automatic Rimori client integration.
|
|
73
|
+
* This hook should be used after the plugin is fully initialized.
|
|
74
|
+
* @param isProduction - Whether the environment is production
|
|
75
|
+
* @returns Logger instance with Rimori client set
|
|
76
|
+
*/
|
|
77
|
+
export function useLoggerWithRimori(isProduction) {
|
|
78
|
+
const logger = useLogger(isProduction);
|
|
79
|
+
const { event } = usePlugin();
|
|
80
|
+
useEffect(() => {
|
|
81
|
+
// Set up Rimori client integration when the hook is used
|
|
82
|
+
const setupRimoriIntegration = () => __awaiter(this, void 0, void 0, function* () {
|
|
83
|
+
try {
|
|
84
|
+
// Get the plugin ID from the event bus context
|
|
85
|
+
// This is a simplified approach - in practice, you'd get this from your plugin context
|
|
86
|
+
const pluginId = 'your-plugin-id'; // This should come from your plugin configuration
|
|
87
|
+
// Set up a listener for log transmission
|
|
88
|
+
event.on('global.logger.sendLogs', (data) => __awaiter(this, void 0, void 0, function* () {
|
|
89
|
+
if (data.pluginId === pluginId) {
|
|
90
|
+
yield logger.sendAllLogs();
|
|
91
|
+
}
|
|
92
|
+
}));
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
console.warn('Failed to set up Logger with Rimori integration:', error);
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
setupRimoriIntegration();
|
|
99
|
+
}, [event, logger]);
|
|
100
|
+
return logger;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Hook for managing logs with simplified interface.
|
|
104
|
+
* Since console methods are overridden globally, this provides utility functions for log management.
|
|
105
|
+
* @param isProduction - Whether the environment is production
|
|
106
|
+
* @returns Object with log management methods
|
|
107
|
+
*/
|
|
108
|
+
export function useLogging(isProduction) {
|
|
109
|
+
const logger = useLogger(isProduction);
|
|
110
|
+
return {
|
|
111
|
+
// Log management
|
|
112
|
+
sendAllLogs: () => logger.sendAllLogs(),
|
|
113
|
+
sendRecentLogs: (count) => logger.sendRecentLogs(count),
|
|
114
|
+
sendLogsByLevel: (level) => logger.sendLogsByLevel(level),
|
|
115
|
+
// Statistics and export
|
|
116
|
+
getStats: () => logger.getStats(),
|
|
117
|
+
exportLogs: () => logger.exportLogs(),
|
|
118
|
+
clearLogs: () => logger.clearLogs(),
|
|
119
|
+
// Console restoration (use with caution)
|
|
120
|
+
restoreConsole: () => logger.restoreConsole()
|
|
121
|
+
};
|
|
122
|
+
}
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AudioController is a class that provides methods to record audio. It is a wrapper around the Capacitor Voice Recorder plugin. For more information, see https://github.com/tchvu3/capacitor-voice-recorder.
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* const audioController = new AudioController();
|
|
6
|
+
* await audioController.startRecording();
|
|
7
|
+
*/
|
|
8
|
+
export declare class AudioController {
|
|
9
|
+
private pluginId;
|
|
10
|
+
constructor(pluginId: string);
|
|
11
|
+
/**
|
|
12
|
+
* Start the recording.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* const audioController = new AudioController();
|
|
16
|
+
* await audioController.startRecording();
|
|
17
|
+
* @returns void
|
|
18
|
+
*/
|
|
19
|
+
startRecording(): Promise<void>;
|
|
20
|
+
/**
|
|
21
|
+
* Stop the recording and return the audio data.
|
|
22
|
+
* @returns The audio data.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* const audioRef = new Audio(`data:${mimeType};base64,${base64Sound}`)
|
|
26
|
+
* audioRef.oncanplaythrough = () => audioRef.play()
|
|
27
|
+
* audioRef.load()
|
|
28
|
+
*/
|
|
29
|
+
stopRecording(): Promise<{
|
|
30
|
+
recording: Blob;
|
|
31
|
+
msDuration: number;
|
|
32
|
+
mimeType: string;
|
|
33
|
+
}>;
|
|
34
|
+
pauseRecording(): Promise<boolean>;
|
|
35
|
+
resumeRecording(): Promise<boolean>;
|
|
36
|
+
getCurrentStatus(): Promise<"RECORDING" | "PAUSED" | "NONE">;
|
|
37
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
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 { EventBus } from "../fromRimori/EventBus";
|
|
11
|
+
/**
|
|
12
|
+
* AudioController is a class that provides methods to record audio. It is a wrapper around the Capacitor Voice Recorder plugin. For more information, see https://github.com/tchvu3/capacitor-voice-recorder.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* const audioController = new AudioController();
|
|
16
|
+
* await audioController.startRecording();
|
|
17
|
+
*/
|
|
18
|
+
export class AudioController {
|
|
19
|
+
constructor(pluginId) {
|
|
20
|
+
this.pluginId = pluginId;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Start the recording.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* const audioController = new AudioController();
|
|
27
|
+
* await audioController.startRecording();
|
|
28
|
+
* @returns void
|
|
29
|
+
*/
|
|
30
|
+
startRecording() {
|
|
31
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
32
|
+
EventBus.emit(this.pluginId, "global.microphone.triggerStartRecording");
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Stop the recording and return the audio data.
|
|
37
|
+
* @returns The audio data.
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* const audioRef = new Audio(`data:${mimeType};base64,${base64Sound}`)
|
|
41
|
+
* audioRef.oncanplaythrough = () => audioRef.play()
|
|
42
|
+
* audioRef.load()
|
|
43
|
+
*/
|
|
44
|
+
stopRecording() {
|
|
45
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
46
|
+
const result = yield EventBus.request(this.pluginId, "global.microphone.triggerStopRecording");
|
|
47
|
+
return result.data;
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
pauseRecording() {
|
|
51
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
52
|
+
const result = yield EventBus.request(this.pluginId, "global.microphone.triggerPauseRecording");
|
|
53
|
+
return result.data;
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
resumeRecording() {
|
|
57
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
58
|
+
const result = yield EventBus.request(this.pluginId, "global.microphone.triggerResumeRecording");
|
|
59
|
+
return result.data;
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
getCurrentStatus() {
|
|
63
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
64
|
+
const result = yield EventBus.request(this.pluginId, "global.microphone.triggerGetCurrentStatus");
|
|
65
|
+
return result.data;
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { RimoriClient } from './RimoriClient';
|
|
2
|
+
/**
|
|
3
|
+
* Singleton Logger class for Rimori client plugins.
|
|
4
|
+
* Handles all logging levels, production filtering, and log transmission to Rimori.
|
|
5
|
+
* Overrides console methods globally for seamless integration.
|
|
6
|
+
*/
|
|
7
|
+
export declare class Logger {
|
|
8
|
+
private static instance;
|
|
9
|
+
private isProduction;
|
|
10
|
+
private logs;
|
|
11
|
+
private logIdCounter;
|
|
12
|
+
private originalConsole;
|
|
13
|
+
private mousePosition;
|
|
14
|
+
private constructor();
|
|
15
|
+
/**
|
|
16
|
+
* Initialize the Logger singleton and override console methods globally.
|
|
17
|
+
* @param rimori - Rimori client instance
|
|
18
|
+
* @param isProduction - Whether the environment is production
|
|
19
|
+
* @returns Logger instance
|
|
20
|
+
*/
|
|
21
|
+
static getInstance(rimori: RimoriClient, isProduction?: boolean): Logger;
|
|
22
|
+
private validateIsProduction;
|
|
23
|
+
/**
|
|
24
|
+
* Expose log access to global scope for DevTools console access.
|
|
25
|
+
*/
|
|
26
|
+
private exposeToDevTools;
|
|
27
|
+
/**
|
|
28
|
+
* Set up navigation event listeners to clear logs on page changes.
|
|
29
|
+
*/
|
|
30
|
+
private setupNavigationClearing;
|
|
31
|
+
/**
|
|
32
|
+
* Override console methods globally to capture all console calls.
|
|
33
|
+
*/
|
|
34
|
+
private overrideConsoleMethods;
|
|
35
|
+
/**
|
|
36
|
+
* Track mouse position for screenshot context.
|
|
37
|
+
*/
|
|
38
|
+
private trackMousePosition;
|
|
39
|
+
/**
|
|
40
|
+
* Handle console method calls and create log entries.
|
|
41
|
+
* @param level - Log level
|
|
42
|
+
* @param args - Console arguments
|
|
43
|
+
*/
|
|
44
|
+
private handleConsoleCall;
|
|
45
|
+
/**
|
|
46
|
+
* Get browser and system information for debugging.
|
|
47
|
+
* @returns Object with browser and system information
|
|
48
|
+
*/
|
|
49
|
+
private getBrowserInfo;
|
|
50
|
+
/**
|
|
51
|
+
* Capture a screenshot of the current page.
|
|
52
|
+
* @returns Promise resolving to base64 screenshot or null if failed
|
|
53
|
+
*/
|
|
54
|
+
private captureScreenshot;
|
|
55
|
+
/**
|
|
56
|
+
* Create a log entry with context information.
|
|
57
|
+
* @param level - Log level
|
|
58
|
+
* @param message - Log message
|
|
59
|
+
* @param data - Additional data
|
|
60
|
+
* @returns Log entry
|
|
61
|
+
*/
|
|
62
|
+
private createLogEntry;
|
|
63
|
+
/**
|
|
64
|
+
* Add a log entry to the internal log array.
|
|
65
|
+
* @param entry - Log entry to add
|
|
66
|
+
*/
|
|
67
|
+
private addLogEntry;
|
|
68
|
+
}
|
|
@@ -0,0 +1,256 @@
|
|
|
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 html2canvas from 'html2canvas';
|
|
11
|
+
/**
|
|
12
|
+
* Singleton Logger class for Rimori client plugins.
|
|
13
|
+
* Handles all logging levels, production filtering, and log transmission to Rimori.
|
|
14
|
+
* Overrides console methods globally for seamless integration.
|
|
15
|
+
*/
|
|
16
|
+
export class Logger {
|
|
17
|
+
constructor(rimori, isProduction) {
|
|
18
|
+
this.logs = [];
|
|
19
|
+
this.logIdCounter = 0;
|
|
20
|
+
this.mousePosition = null;
|
|
21
|
+
this.isProduction = this.validateIsProduction(isProduction);
|
|
22
|
+
// Store original console methods
|
|
23
|
+
this.originalConsole = {
|
|
24
|
+
log: console.log,
|
|
25
|
+
info: console.info,
|
|
26
|
+
warn: console.warn,
|
|
27
|
+
error: console.error,
|
|
28
|
+
debug: console.debug
|
|
29
|
+
};
|
|
30
|
+
// Override console methods globally
|
|
31
|
+
this.overrideConsoleMethods();
|
|
32
|
+
// Track mouse position
|
|
33
|
+
this.trackMousePosition();
|
|
34
|
+
// Expose logs to global scope for DevTools access
|
|
35
|
+
this.exposeToDevTools();
|
|
36
|
+
// Set up navigation clearing
|
|
37
|
+
this.setupNavigationClearing();
|
|
38
|
+
rimori.event.respond('logging.requestPluginLogs', () => __awaiter(this, void 0, void 0, function* () {
|
|
39
|
+
this.addLogEntry(yield this.createLogEntry('info', 'Screenshot capture', undefined, true));
|
|
40
|
+
const logs = {
|
|
41
|
+
logs: this.logs,
|
|
42
|
+
pluginId: rimori.plugin.pluginId,
|
|
43
|
+
timestamp: new Date().toISOString()
|
|
44
|
+
};
|
|
45
|
+
this.logs = [];
|
|
46
|
+
this.logIdCounter = 0;
|
|
47
|
+
return logs;
|
|
48
|
+
}));
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Initialize the Logger singleton and override console methods globally.
|
|
52
|
+
* @param rimori - Rimori client instance
|
|
53
|
+
* @param isProduction - Whether the environment is production
|
|
54
|
+
* @returns Logger instance
|
|
55
|
+
*/
|
|
56
|
+
static getInstance(rimori, isProduction) {
|
|
57
|
+
if (!Logger.instance) {
|
|
58
|
+
Logger.instance = new Logger(rimori, isProduction);
|
|
59
|
+
}
|
|
60
|
+
return Logger.instance;
|
|
61
|
+
}
|
|
62
|
+
validateIsProduction(isProduction) {
|
|
63
|
+
if (isProduction !== undefined) {
|
|
64
|
+
return isProduction;
|
|
65
|
+
}
|
|
66
|
+
if (typeof window !== 'undefined' && window.location.href) {
|
|
67
|
+
return !window.location.href.includes('localhost');
|
|
68
|
+
}
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Expose log access to global scope for DevTools console access.
|
|
73
|
+
*/
|
|
74
|
+
exposeToDevTools() {
|
|
75
|
+
if (typeof window !== 'undefined') {
|
|
76
|
+
// Expose a global function to access logs from DevTools console
|
|
77
|
+
window.getRimoriLogs = () => this.logs;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Set up navigation event listeners to clear logs on page changes.
|
|
82
|
+
*/
|
|
83
|
+
setupNavigationClearing() {
|
|
84
|
+
if (typeof window === 'undefined' || typeof history === 'undefined')
|
|
85
|
+
return;
|
|
86
|
+
// Clear logs on browser back/forward
|
|
87
|
+
window.addEventListener('popstate', () => this.logs = []);
|
|
88
|
+
// Override history methods to clear logs on programmatic navigation
|
|
89
|
+
const originalPushState = history.pushState;
|
|
90
|
+
const originalReplaceState = history.replaceState;
|
|
91
|
+
history.pushState = (...args) => {
|
|
92
|
+
originalPushState.apply(history, args);
|
|
93
|
+
this.logs = [];
|
|
94
|
+
};
|
|
95
|
+
history.replaceState = (...args) => {
|
|
96
|
+
originalReplaceState.apply(history, args);
|
|
97
|
+
this.logs = [];
|
|
98
|
+
};
|
|
99
|
+
// Listen for URL changes (works with React Router and other SPAs)
|
|
100
|
+
let currentUrl = window.location.href;
|
|
101
|
+
const checkUrlChange = () => {
|
|
102
|
+
if (window.location.href !== currentUrl) {
|
|
103
|
+
currentUrl = window.location.href;
|
|
104
|
+
this.logs = [];
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
// Check for URL changes periodically
|
|
108
|
+
setInterval(checkUrlChange, 100);
|
|
109
|
+
// Also listen for hash changes (for hash-based routing)
|
|
110
|
+
window.addEventListener('hashchange', () => this.logs = []);
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Override console methods globally to capture all console calls.
|
|
114
|
+
*/
|
|
115
|
+
overrideConsoleMethods() {
|
|
116
|
+
// Override console.log
|
|
117
|
+
console.log = (...args) => {
|
|
118
|
+
this.originalConsole.log(...args);
|
|
119
|
+
this.handleConsoleCall('info', args);
|
|
120
|
+
};
|
|
121
|
+
// Override console.info
|
|
122
|
+
console.info = (...args) => {
|
|
123
|
+
this.originalConsole.info(...args);
|
|
124
|
+
this.handleConsoleCall('info', args);
|
|
125
|
+
};
|
|
126
|
+
// Override console.warn
|
|
127
|
+
console.warn = (...args) => {
|
|
128
|
+
this.originalConsole.warn(...args);
|
|
129
|
+
this.handleConsoleCall('warn', args);
|
|
130
|
+
};
|
|
131
|
+
// Override console.error
|
|
132
|
+
console.error = (...args) => {
|
|
133
|
+
this.originalConsole.error(...args);
|
|
134
|
+
this.handleConsoleCall('error', args);
|
|
135
|
+
};
|
|
136
|
+
// Override console.debug
|
|
137
|
+
console.debug = (...args) => {
|
|
138
|
+
this.originalConsole.debug(...args);
|
|
139
|
+
this.handleConsoleCall('debug', args);
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Track mouse position for screenshot context.
|
|
144
|
+
*/
|
|
145
|
+
trackMousePosition() {
|
|
146
|
+
if (typeof window !== 'undefined') {
|
|
147
|
+
const updateMousePosition = (event) => {
|
|
148
|
+
this.mousePosition = {
|
|
149
|
+
x: event.clientX,
|
|
150
|
+
y: event.clientY,
|
|
151
|
+
timestamp: new Date().toISOString()
|
|
152
|
+
};
|
|
153
|
+
};
|
|
154
|
+
window.addEventListener('mousemove', updateMousePosition);
|
|
155
|
+
window.addEventListener('click', updateMousePosition);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Handle console method calls and create log entries.
|
|
160
|
+
* @param level - Log level
|
|
161
|
+
* @param args - Console arguments
|
|
162
|
+
*/
|
|
163
|
+
handleConsoleCall(level, args) {
|
|
164
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
165
|
+
// Skip if this is a production log that shouldn't be stored
|
|
166
|
+
if (this.isProduction && (level === 'debug' || level === 'info')) {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
// Convert console arguments to message and data
|
|
170
|
+
const message = args.map(arg => typeof arg === 'object' ? JSON.stringify(arg) : String(arg)).join(' ');
|
|
171
|
+
const data = args.length > 1 ? args.slice(1) : undefined;
|
|
172
|
+
const entry = yield this.createLogEntry(level, message, data);
|
|
173
|
+
this.addLogEntry(entry);
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Get browser and system information for debugging.
|
|
178
|
+
* @returns Object with browser and system information
|
|
179
|
+
*/
|
|
180
|
+
getBrowserInfo() {
|
|
181
|
+
return {
|
|
182
|
+
userAgent: navigator.userAgent,
|
|
183
|
+
language: navigator.language,
|
|
184
|
+
cookieEnabled: navigator.cookieEnabled,
|
|
185
|
+
onLine: navigator.onLine,
|
|
186
|
+
screenResolution: `${screen.width}x${screen.height}`,
|
|
187
|
+
windowSize: `${window.innerWidth}x${window.innerHeight}`,
|
|
188
|
+
timestamp: new Date().toISOString()
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Capture a screenshot of the current page.
|
|
193
|
+
* @returns Promise resolving to base64 screenshot or null if failed
|
|
194
|
+
*/
|
|
195
|
+
captureScreenshot() {
|
|
196
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
197
|
+
if (typeof window !== 'undefined' && typeof document !== 'undefined') {
|
|
198
|
+
const canvas = yield html2canvas(document.body);
|
|
199
|
+
const screenshot = canvas.toDataURL('image/png');
|
|
200
|
+
// this.originalConsole.log("screenshot captured", screenshot)
|
|
201
|
+
return screenshot;
|
|
202
|
+
}
|
|
203
|
+
return null;
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Create a log entry with context information.
|
|
208
|
+
* @param level - Log level
|
|
209
|
+
* @param message - Log message
|
|
210
|
+
* @param data - Additional data
|
|
211
|
+
* @returns Log entry
|
|
212
|
+
*/
|
|
213
|
+
createLogEntry(level, message, data, forceScreenshot) {
|
|
214
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
215
|
+
const context = {};
|
|
216
|
+
// Add URL if available
|
|
217
|
+
if (typeof window === 'undefined' || typeof document === 'undefined') {
|
|
218
|
+
return {
|
|
219
|
+
id: `log_${++this.logIdCounter}_${Date.now()}`,
|
|
220
|
+
timestamp: new Date().toISOString(),
|
|
221
|
+
level,
|
|
222
|
+
message,
|
|
223
|
+
data,
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
context.url = window.location.href;
|
|
227
|
+
// Add browser info (this method now handles worker context internally)
|
|
228
|
+
context.browserInfo = this.getBrowserInfo();
|
|
229
|
+
context.userAgent = context.browserInfo.userAgent;
|
|
230
|
+
// Add screenshot and mouse position if level is error or warn
|
|
231
|
+
if (level === 'error' || level === 'warn' || forceScreenshot) {
|
|
232
|
+
context.screenshot = (yield this.captureScreenshot()) || undefined;
|
|
233
|
+
context.mousePosition = this.mousePosition || undefined;
|
|
234
|
+
}
|
|
235
|
+
return {
|
|
236
|
+
id: `log_${++this.logIdCounter}_${Date.now()}`,
|
|
237
|
+
timestamp: new Date().toISOString(),
|
|
238
|
+
level,
|
|
239
|
+
message,
|
|
240
|
+
data,
|
|
241
|
+
context: context
|
|
242
|
+
};
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Add a log entry to the internal log array.
|
|
247
|
+
* @param entry - Log entry to add
|
|
248
|
+
*/
|
|
249
|
+
addLogEntry(entry) {
|
|
250
|
+
this.logs.push(entry);
|
|
251
|
+
// Maintain log size limit (1000 entries)
|
|
252
|
+
if (this.logs.length > 1000) {
|
|
253
|
+
this.logs = this.logs.slice(-1000);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Example of how to integrate the Logger into a plugin's main entry point.
|
|
3
|
+
* This shows the complete setup process.
|
|
4
|
+
*/
|
|
5
|
+
export declare function initializePluginWithLogger(): Promise<void>;
|
|
6
|
+
export declare function exampleComponentUsage(): {
|
|
7
|
+
handleUserAction: () => void;
|
|
8
|
+
handleApiError: (error: Error) => void;
|
|
9
|
+
handleDeprecatedFeature: () => void;
|
|
10
|
+
};
|
|
11
|
+
export declare function exampleLogManagement(): {
|
|
12
|
+
sendLogsToRimori: () => Promise<void>;
|
|
13
|
+
getLogStatistics: () => any;
|
|
14
|
+
exportLogsForDebugging: () => void;
|
|
15
|
+
clearOldLogs: () => void;
|
|
16
|
+
};
|