-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathexecbox-remote.ts
More file actions
108 lines (97 loc) · 2.72 KB
/
execbox-remote.ts
File metadata and controls
108 lines (97 loc) · 2.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import { resolveProvider } from "@execbox/core";
import { RemoteExecutor, attachQuickJsRemoteEndpoint } from "@execbox/remote";
import type {
DispatcherMessage,
HostTransport,
RunnerMessage,
TransportCloseReason,
} from "@execbox/protocol";
type CloseHandler = (reason?: TransportCloseReason) => void;
type ErrorHandler = (error: Error) => void;
type MessageHandler = (message: RunnerMessage) => void;
type RunnerMessageHandler = (message: DispatcherMessage) => void;
function createInMemoryRemoteTransport(): HostTransport {
const closeHandlers = new Set<CloseHandler>();
const errorHandlers = new Set<ErrorHandler>();
const messageHandlers = new Set<MessageHandler>();
const runnerHandlers = new Set<RunnerMessageHandler>();
let closed = false;
attachQuickJsRemoteEndpoint({
onClose(handler) {
closeHandlers.add(handler);
return () => closeHandlers.delete(handler);
},
onMessage(handler) {
runnerHandlers.add(handler as RunnerMessageHandler);
return () => runnerHandlers.delete(handler as RunnerMessageHandler);
},
send(message) {
queueMicrotask(() => {
for (const handler of messageHandlers) {
handler(message as RunnerMessage);
}
});
},
});
const emitClose = (reason?: TransportCloseReason) => {
closed = true;
for (const handler of closeHandlers) {
handler(reason);
}
};
return {
dispose() {
closed = true;
},
onClose(handler) {
closeHandlers.add(handler);
return () => closeHandlers.delete(handler);
},
onError(handler) {
errorHandlers.add(handler);
return () => errorHandlers.delete(handler);
},
onMessage(handler) {
messageHandlers.add(handler);
return () => messageHandlers.delete(handler);
},
send(message) {
if (closed) {
for (const handler of errorHandlers) {
handler(new Error("Remote transport closed"));
}
return;
}
queueMicrotask(() => {
for (const handler of runnerHandlers) {
handler(message);
}
});
},
terminate() {
emitClose({ message: "Remote transport terminated" });
},
};
}
async function main(): Promise<void> {
const provider = resolveProvider({
name: "tools",
tools: {
echo: {
execute: async (input) => input,
},
},
});
const executor = new RemoteExecutor({
connectTransport: () => createInMemoryRemoteTransport(),
timeoutMs: 1_000,
});
const result = await executor.execute(
"await tools.echo({ ok: true, via: 'remote' })",
[provider],
{ timeoutMs: 250 },
);
console.log("execbox remote example result");
console.log(JSON.stringify(result, null, 2));
}
void main();