@elevo-ai/elevo-messenger-sdk 0.1.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.
@@ -0,0 +1,24 @@
1
+ export interface ElevoMessengerSDK {
2
+ /** Send a message to the main window. */
3
+ sendMessage(channel: string, data: unknown): Promise<unknown>;
4
+ /**
5
+ * Subscribe to messages pushed from the main window.
6
+ * Returns an unsubscribe function.
7
+ */
8
+ onMessage(channel: string, fn: (data: unknown) => void): () => void;
9
+ getLabel(): string;
10
+ close(): Promise<unknown>;
11
+ readonly modelContext: ModelContext;
12
+ }
13
+ export interface ModelContext {
14
+ registerTool(tool: ModelContextTool): void;
15
+ unregisterTool(toolName: string): void;
16
+ }
17
+ export interface ModelContextTool {
18
+ name: string;
19
+ description: string;
20
+ inputSchema: Record<string, unknown>;
21
+ execute: ToolExecuteCallback;
22
+ }
23
+ export type ToolExecuteCallback = (input: Record<string, unknown>) => Promise<unknown>;
24
+ export declare const elevoMessengerSDK: ElevoMessengerSDK;
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export var elevoMessengerSDK = window
2
+ .elevoMessengerSDK;
package/dist/sdk.d.ts ADDED
@@ -0,0 +1 @@
1
+ export {};
package/dist/sdk.js ADDED
@@ -0,0 +1,153 @@
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
+ var __generator = (this && this.__generator) || function (thisArg, body) {
11
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
12
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
13
+ function verb(n) { return function (v) { return step([n, v]); }; }
14
+ function step(op) {
15
+ if (f) throw new TypeError("Generator is already executing.");
16
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
17
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
18
+ if (y = 0, t) op = [op[0] & 2, t.value];
19
+ switch (op[0]) {
20
+ case 0: case 1: t = op; break;
21
+ case 4: _.label++; return { value: op[1], done: false };
22
+ case 5: _.label++; y = op[1]; op = [0]; continue;
23
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
24
+ default:
25
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
26
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
27
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
28
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
29
+ if (t[2]) _.ops.pop();
30
+ _.trys.pop(); continue;
31
+ }
32
+ op = body.call(thisArg, _);
33
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
34
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
35
+ }
36
+ };
37
+ (function () {
38
+ var global = window;
39
+ var tauriInternals = global.__TAURI_INTERNALS__;
40
+ if (global.elevoMessengerSDK ||
41
+ !tauriInternals)
42
+ return;
43
+ // __WEBVIEW_LABEL__ is replaced at runtime by Rust before injection.
44
+ var LABEL = __WEBVIEW_LABEL__;
45
+ var handlers = {};
46
+ // Called by Rust (via webview.eval) to push a message into this webview.
47
+ global.__ElevoMessengerSDK_receive__ = function (channel, data) {
48
+ var fns = handlers[channel] || [];
49
+ fns.forEach(function (fn) {
50
+ try {
51
+ fn(data);
52
+ }
53
+ catch (e) {
54
+ console.error("[ElevoMessengerSDK] handler error", e);
55
+ }
56
+ });
57
+ };
58
+ // Use postMessage transport directly to bypass ipc:// custom protocol,
59
+ // which is blocked by external-page CSP. Uses transformCallback so Tauri
60
+ // can route the response back to the correct promise.
61
+ var tauriInvoke = function (cmd, args) {
62
+ return new Promise(function (resolve, reject) {
63
+ var callback = tauriInternals.transformCallback(resolve, true);
64
+ var error = tauriInternals.transformCallback(reject, true);
65
+ tauriInternals.postMessage({ cmd: cmd, callback: callback, error: error, payload: args });
66
+ });
67
+ };
68
+ /** Send a message to the main window. */
69
+ var sendMessage = function (channel, data) {
70
+ return tauriInvoke("relay_sdk_message", {
71
+ sourceLabel: LABEL,
72
+ channel: channel,
73
+ data: data,
74
+ });
75
+ };
76
+ /**
77
+ * Subscribe to messages pushed from the main window.
78
+ * Returns an unsubscribe function.
79
+ */
80
+ var onMessage = function (channel, fn) {
81
+ if (!handlers[channel])
82
+ handlers[channel] = [];
83
+ handlers[channel].push(fn);
84
+ return function () {
85
+ handlers[channel] = (handlers[channel] || []).filter(function (h) {
86
+ return h !== fn;
87
+ });
88
+ };
89
+ };
90
+ var getLabel = function () {
91
+ return LABEL;
92
+ };
93
+ var close = function () {
94
+ return tauriInvoke("close_webview", { label: LABEL });
95
+ };
96
+ var modelContextTools = new Map();
97
+ var modelContext = Object.freeze({
98
+ registerTool: function (tool) {
99
+ var name = tool.name, description = tool.description, inputSchema = tool.inputSchema;
100
+ modelContextTools.set(name, tool);
101
+ sendMessage("client_tool_register", { name: name, description: description, inputSchema: inputSchema });
102
+ },
103
+ unregisterTool: function (toolName) {
104
+ modelContextTools.delete(toolName);
105
+ sendMessage("client_tool_unregister", toolName);
106
+ },
107
+ });
108
+ onMessage("client_tool_execute", function (data) {
109
+ return __awaiter(this, void 0, void 0, function () {
110
+ var _a, toolName, input, toolCallId, tool, output, e_1;
111
+ return __generator(this, function (_b) {
112
+ switch (_b.label) {
113
+ case 0:
114
+ _a = data, toolName = _a.toolName, input = _a.input, toolCallId = _a.toolCallId;
115
+ tool = modelContextTools.get(toolName);
116
+ if (!tool) {
117
+ return [2 /*return*/];
118
+ }
119
+ _b.label = 1;
120
+ case 1:
121
+ _b.trys.push([1, 3, , 4]);
122
+ return [4 /*yield*/, tool.execute(input)];
123
+ case 2:
124
+ output = _b.sent();
125
+ sendMessage("client_tool_output", {
126
+ toolCallId: toolCallId,
127
+ output: output,
128
+ success: true,
129
+ });
130
+ return [3 /*break*/, 4];
131
+ case 3:
132
+ e_1 = _b.sent();
133
+ sendMessage("client_tool_output", {
134
+ toolCallId: toolCallId,
135
+ output: e_1 instanceof Error ? e_1.message : String(e_1),
136
+ success: false,
137
+ });
138
+ return [3 /*break*/, 4];
139
+ case 4: return [2 /*return*/];
140
+ }
141
+ });
142
+ });
143
+ });
144
+ global.elevoMessengerSDK = Object.freeze({
145
+ sendMessage: sendMessage,
146
+ onMessage: onMessage,
147
+ getLabel: getLabel,
148
+ close: close,
149
+ modelContext: modelContext,
150
+ });
151
+ console.log("[ElevoMessengerSDK] initialized, label:", LABEL);
152
+ })();
153
+ export {};
package/package.json ADDED
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "@elevo-ai/elevo-messenger-sdk",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "default": "./dist/index.js"
11
+ }
12
+ },
13
+ "scripts": {
14
+ "build": "tsc"
15
+ },
16
+ "devDependencies": {
17
+ "typescript": "^5.9.3"
18
+ }
19
+ }
package/src/index.ts ADDED
@@ -0,0 +1,36 @@
1
+ export interface ElevoMessengerSDK {
2
+ /** Send a message to the main window. */
3
+ sendMessage(channel: string, data: unknown): Promise<unknown>;
4
+ /**
5
+ * Subscribe to messages pushed from the main window.
6
+ * Returns an unsubscribe function.
7
+ */
8
+ onMessage(channel: string, fn: (data: unknown) => void): () => void;
9
+ getLabel(): string;
10
+ close(): Promise<unknown>;
11
+
12
+ readonly modelContext: ModelContext;
13
+ }
14
+
15
+ export interface ModelContext {
16
+ registerTool(tool: ModelContextTool): void;
17
+ unregisterTool(toolName: string): void;
18
+ }
19
+
20
+ export interface ModelContextTool {
21
+ name: string;
22
+ description: string;
23
+ inputSchema: Record<string, unknown>;
24
+ execute: ToolExecuteCallback;
25
+ }
26
+
27
+ export type ToolExecuteCallback = (
28
+ input: Record<string, unknown>,
29
+ ) => Promise<unknown>;
30
+
31
+ interface WindowWithElevoMessengerSDK extends Window {
32
+ elevoMessengerSDK?: ElevoMessengerSDK;
33
+ }
34
+
35
+ export const elevoMessengerSDK = (window as WindowWithElevoMessengerSDK)
36
+ .elevoMessengerSDK!;
package/src/sdk.ts ADDED
@@ -0,0 +1,147 @@
1
+ import type {
2
+ ElevoMessengerSDK,
3
+ ModelContext,
4
+ ModelContextTool,
5
+ } from "./index";
6
+
7
+ interface WindowWithElevoMessengerSDK extends Window {
8
+ elevoMessengerSDK?: ElevoMessengerSDK;
9
+ /** @internal Called by Rust to push messages into this webview. */
10
+ __ElevoMessengerSDK_receive__?: (channel: string, data: unknown) => void;
11
+ readonly __TAURI_INTERNALS__?: TauriInternals;
12
+ }
13
+
14
+ interface TauriInternals {
15
+ transformCallback(fn: (value: unknown) => void, once?: boolean): number;
16
+ postMessage(msg: unknown): void;
17
+ }
18
+
19
+ /** @internal Replaced at runtime by Rust before injection. */
20
+ declare const __WEBVIEW_LABEL__: string;
21
+
22
+ (function () {
23
+ const global = window as WindowWithElevoMessengerSDK;
24
+ const tauriInternals = global.__TAURI_INTERNALS__;
25
+
26
+ if (
27
+ (global as WindowWithElevoMessengerSDK).elevoMessengerSDK ||
28
+ !tauriInternals
29
+ )
30
+ return;
31
+
32
+ // __WEBVIEW_LABEL__ is replaced at runtime by Rust before injection.
33
+ const LABEL: string = __WEBVIEW_LABEL__;
34
+
35
+ type Handler = (data: unknown) => void;
36
+ const handlers: Record<string, Handler[]> = {};
37
+
38
+ // Called by Rust (via webview.eval) to push a message into this webview.
39
+ global.__ElevoMessengerSDK_receive__ = function (
40
+ channel: string,
41
+ data: unknown,
42
+ ) {
43
+ const fns = handlers[channel] || [];
44
+ fns.forEach(function (fn) {
45
+ try {
46
+ fn(data);
47
+ } catch (e) {
48
+ console.error("[ElevoMessengerSDK] handler error", e);
49
+ }
50
+ });
51
+ };
52
+
53
+ // Use postMessage transport directly to bypass ipc:// custom protocol,
54
+ // which is blocked by external-page CSP. Uses transformCallback so Tauri
55
+ // can route the response back to the correct promise.
56
+ const tauriInvoke = (
57
+ cmd: string,
58
+ args: Record<string, unknown>,
59
+ ): Promise<unknown> => {
60
+ return new Promise(function (resolve, reject) {
61
+ const callback = tauriInternals.transformCallback(resolve, true);
62
+ const error = tauriInternals.transformCallback(reject, true);
63
+ tauriInternals.postMessage({ cmd, callback, error, payload: args });
64
+ });
65
+ };
66
+
67
+ /** Send a message to the main window. */
68
+ const sendMessage = (channel: string, data: unknown) => {
69
+ return tauriInvoke("relay_sdk_message", {
70
+ sourceLabel: LABEL,
71
+ channel,
72
+ data,
73
+ });
74
+ };
75
+
76
+ /**
77
+ * Subscribe to messages pushed from the main window.
78
+ * Returns an unsubscribe function.
79
+ */
80
+ const onMessage = (channel: string, fn: Handler) => {
81
+ if (!handlers[channel]) handlers[channel] = [];
82
+ handlers[channel].push(fn);
83
+ return function () {
84
+ handlers[channel] = (handlers[channel] || []).filter(function (h) {
85
+ return h !== fn;
86
+ });
87
+ };
88
+ };
89
+
90
+ const getLabel = () => {
91
+ return LABEL;
92
+ };
93
+
94
+ const close = () => {
95
+ return tauriInvoke("close_webview", { label: LABEL });
96
+ };
97
+
98
+ const modelContextTools = new Map<string, ModelContextTool>();
99
+
100
+ const modelContext: ModelContext = Object.freeze({
101
+ registerTool(tool: ModelContextTool) {
102
+ const { name, description, inputSchema } = tool;
103
+ modelContextTools.set(name, tool);
104
+ sendMessage("client_tool_register", { name, description, inputSchema });
105
+ },
106
+ unregisterTool(toolName: string) {
107
+ modelContextTools.delete(toolName);
108
+ sendMessage("client_tool_unregister", toolName);
109
+ },
110
+ });
111
+
112
+ onMessage("client_tool_execute", async function (data) {
113
+ const { toolName, input, toolCallId } = data as {
114
+ toolName: string;
115
+ input: Record<string, unknown>;
116
+ toolCallId: string;
117
+ };
118
+ const tool = modelContextTools.get(toolName);
119
+ if (!tool) {
120
+ return;
121
+ }
122
+ try {
123
+ const output = await tool.execute(input);
124
+ sendMessage("client_tool_output", {
125
+ toolCallId,
126
+ output,
127
+ success: true,
128
+ });
129
+ } catch (e) {
130
+ sendMessage("client_tool_output", {
131
+ toolCallId,
132
+ output: e instanceof Error ? e.message : String(e),
133
+ success: false,
134
+ });
135
+ }
136
+ });
137
+
138
+ global.elevoMessengerSDK = Object.freeze({
139
+ sendMessage,
140
+ onMessage,
141
+ getLabel,
142
+ close,
143
+ modelContext,
144
+ });
145
+
146
+ console.log("[ElevoMessengerSDK] initialized, label:", LABEL);
147
+ })();
package/tsconfig.json ADDED
@@ -0,0 +1,14 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES5",
4
+ "lib": ["ES2015", "DOM"],
5
+ "module": "ESNext",
6
+ "moduleResolution": "bundler",
7
+ "strict": true,
8
+ "noEmitOnError": true,
9
+ "outDir": "dist",
10
+ "declaration": true,
11
+ "removeComments": false
12
+ },
13
+ "include": ["src"]
14
+ }