@agent-glue/glue 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.
- package/.turbo/turbo-build.log +5 -0
- package/.turbo/turbo-clean$colon$build.log +1 -0
- package/.turbo/turbo-format$colon$fix.log +46 -0
- package/.turbo/turbo-format.log +13 -0
- package/.turbo/turbo-lint$colon$fix.log +9 -0
- package/.turbo/turbo-lint.log +5 -0
- package/.turbo/turbo-test.log +27 -0
- package/.turbo/turbo-typecheck.log +5 -0
- package/CHANGELOG.md +7 -0
- package/LICENSE +21 -0
- package/dist/Actor.d.ts +51 -0
- package/dist/Actor.js +30 -0
- package/dist/actor.js +32 -0
- package/dist/actors/examples/timer.d.ts +1 -0
- package/dist/actors/examples/timer.js +1 -0
- package/dist/actors/langchain/llm.d.ts +40 -0
- package/dist/actors/langchain/llm.js +52 -0
- package/dist/constructors.js +1 -0
- package/dist/effects.js +66 -0
- package/dist/emitter.js +19 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/message.js +18 -0
- package/dist/message.test.js +37 -0
- package/dist/server/memory.js +46 -0
- package/dist/server/protocol.js +4 -0
- package/dist/server/websocket.js +72 -0
- package/dist/server.js +3 -0
- package/dist/transformers.d.ts +41 -0
- package/dist/transformers.js +17 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/types.js +1 -0
- package/dist/utils/TypedEmitter.d.ts +15 -0
- package/dist/utils/TypedEmitter.js +16 -0
- package/eslint.config.js +4 -0
- package/nodemon.json +7 -0
- package/package.json +75 -0
- package/src/actor.ts +69 -0
- package/src/effects.ts +88 -0
- package/src/emitter.ts +22 -0
- package/src/index.ts +1 -0
- package/src/message.test.ts +52 -0
- package/src/message.ts +54 -0
- package/src/server/memory.ts +77 -0
- package/src/server/protocol.ts +36 -0
- package/src/server/websocket.ts +137 -0
- package/src/server.ts +3 -0
- package/src/transformers.ts +66 -0
- package/src/types.ts +7 -0
- package/src/utils/TypedEmitter.ts +30 -0
- package/tsconfig.json +8 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { Actor, ActorInterface } from "../actor.js";
|
|
2
|
+
import { defineMessage, Message } from "../message.js";
|
|
3
|
+
import {
|
|
4
|
+
Commands,
|
|
5
|
+
Connect,
|
|
6
|
+
event,
|
|
7
|
+
Events,
|
|
8
|
+
isConnect,
|
|
9
|
+
isSend,
|
|
10
|
+
Send
|
|
11
|
+
} from "./protocol.js";
|
|
12
|
+
|
|
13
|
+
export interface LocalConnect extends Connect {
|
|
14
|
+
destination: string;
|
|
15
|
+
callback: (msg: Message) => void;
|
|
16
|
+
}
|
|
17
|
+
export const {
|
|
18
|
+
message: localConnect,
|
|
19
|
+
isMessage: isLocalConnect,
|
|
20
|
+
type: LocalConnectType
|
|
21
|
+
} = defineMessage<LocalConnect>("local-connect");
|
|
22
|
+
|
|
23
|
+
export interface LocalRegister extends Message {
|
|
24
|
+
name: string;
|
|
25
|
+
actor: Actor<Message, Message>;
|
|
26
|
+
}
|
|
27
|
+
export const {
|
|
28
|
+
message: localRegister,
|
|
29
|
+
isMessage: isLocalRegister,
|
|
30
|
+
type: LocalRegisterType
|
|
31
|
+
} = defineMessage<LocalRegister>("local-register");
|
|
32
|
+
|
|
33
|
+
export type LocalCommands = Send | LocalConnect | LocalRegister;
|
|
34
|
+
export type LocalServerActor = ActorInterface<LocalCommands, never>;
|
|
35
|
+
|
|
36
|
+
export class LocalServer extends Actor<LocalCommands, never> {
|
|
37
|
+
private store = new Map<string, Actor<Message, Message>>();
|
|
38
|
+
|
|
39
|
+
send(command: LocalCommands) {
|
|
40
|
+
if (isSend(command)) {
|
|
41
|
+
const { destination, message } = command;
|
|
42
|
+
const actor = this.store.get(destination);
|
|
43
|
+
if (actor) {
|
|
44
|
+
actor.send(message);
|
|
45
|
+
}
|
|
46
|
+
} else if (isLocalConnect(command)) {
|
|
47
|
+
const { destination, callback } = command;
|
|
48
|
+
const actor = this.store.get(destination);
|
|
49
|
+
if (actor) {
|
|
50
|
+
actor.connect(callback);
|
|
51
|
+
}
|
|
52
|
+
} else if (isLocalRegister(command)) {
|
|
53
|
+
const { name, actor } = command;
|
|
54
|
+
this.store.set(name, actor);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export class MemoryClient extends Actor<Commands, Events> {
|
|
60
|
+
constructor(private server: LocalServerActor) {
|
|
61
|
+
super();
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
send(command: Commands): void {
|
|
65
|
+
if (isSend(command)) {
|
|
66
|
+
this.server.send(command);
|
|
67
|
+
} else if (isConnect(command)) {
|
|
68
|
+
this.server.send(
|
|
69
|
+
localConnect({
|
|
70
|
+
destination: command.destination,
|
|
71
|
+
callback: (msg) =>
|
|
72
|
+
this.emit(event({ origin: command.destination, message: msg }))
|
|
73
|
+
})
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { ActorInterface } from "../actor.js";
|
|
2
|
+
import { defineMessage, Message } from "../message.js";
|
|
3
|
+
|
|
4
|
+
export interface Send extends Message {
|
|
5
|
+
destination: string;
|
|
6
|
+
message: Message;
|
|
7
|
+
}
|
|
8
|
+
export const {
|
|
9
|
+
message: send,
|
|
10
|
+
isMessage: isSend,
|
|
11
|
+
type: SendType
|
|
12
|
+
} = defineMessage<Send>("send");
|
|
13
|
+
|
|
14
|
+
export interface Connect extends Message {
|
|
15
|
+
destination: string;
|
|
16
|
+
}
|
|
17
|
+
export const {
|
|
18
|
+
message: connect,
|
|
19
|
+
isMessage: isConnect,
|
|
20
|
+
type: ConnectType
|
|
21
|
+
} = defineMessage<Connect>("connect");
|
|
22
|
+
|
|
23
|
+
export interface Event extends Message {
|
|
24
|
+
origin: string;
|
|
25
|
+
message: Message;
|
|
26
|
+
}
|
|
27
|
+
export const {
|
|
28
|
+
message: event,
|
|
29
|
+
isMessage: isEvent,
|
|
30
|
+
type: EventType
|
|
31
|
+
} = defineMessage<Event>("event");
|
|
32
|
+
|
|
33
|
+
export type Commands = Send | Connect;
|
|
34
|
+
export type Events = Event;
|
|
35
|
+
|
|
36
|
+
export type ServerActor = ActorInterface<Commands, Events>;
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { Actor, ActorInterface } from "../actor.js";
|
|
2
|
+
import { defineMessage, Message } from "../message.js";
|
|
3
|
+
import type {
|
|
4
|
+
WebSocketServer as NodeWebSocketServer,
|
|
5
|
+
WebSocket as NodeWebsocket
|
|
6
|
+
} from "ws";
|
|
7
|
+
|
|
8
|
+
export interface SendCommand extends Message {
|
|
9
|
+
message: string;
|
|
10
|
+
}
|
|
11
|
+
export const {
|
|
12
|
+
message: sendCommand,
|
|
13
|
+
isMessage: isSendCommand,
|
|
14
|
+
type: SendCommandType
|
|
15
|
+
} = defineMessage<SendCommand>("send-command");
|
|
16
|
+
|
|
17
|
+
type OpenEvent = Message;
|
|
18
|
+
export const {
|
|
19
|
+
message: openEvent,
|
|
20
|
+
isMessage: isOpenEvent,
|
|
21
|
+
type: OpenEventType
|
|
22
|
+
} = defineMessage<OpenEvent>("open-event");
|
|
23
|
+
|
|
24
|
+
type CloseEvent = Message;
|
|
25
|
+
export const {
|
|
26
|
+
message: closeEvent,
|
|
27
|
+
isMessage: isCloseEvent,
|
|
28
|
+
type: CloseEventType
|
|
29
|
+
} = defineMessage<CloseEvent>("close-event");
|
|
30
|
+
|
|
31
|
+
export interface ErrorEvent extends Message {
|
|
32
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
33
|
+
error: any;
|
|
34
|
+
}
|
|
35
|
+
export const {
|
|
36
|
+
message: errorEvent,
|
|
37
|
+
isMessage: isErrorEvent,
|
|
38
|
+
type: ErrorEventType
|
|
39
|
+
} = defineMessage<ErrorEvent>("error-event");
|
|
40
|
+
export interface MessageEvent extends Message {
|
|
41
|
+
message: string;
|
|
42
|
+
}
|
|
43
|
+
export const {
|
|
44
|
+
message: messageEvent,
|
|
45
|
+
isMessage: isMessageEvent,
|
|
46
|
+
type: MessageEventType
|
|
47
|
+
} = defineMessage<MessageEvent>("message-event");
|
|
48
|
+
|
|
49
|
+
export type WebsocketCommands = SendCommand;
|
|
50
|
+
export type WebsocketEvents =
|
|
51
|
+
| OpenEvent
|
|
52
|
+
| CloseEvent
|
|
53
|
+
| ErrorEvent
|
|
54
|
+
| MessageEvent;
|
|
55
|
+
|
|
56
|
+
export class WebsocketClient extends Actor<WebsocketCommands, WebsocketEvents> {
|
|
57
|
+
constructor(private readonly ws: WebSocket | NodeWebsocket) {
|
|
58
|
+
super();
|
|
59
|
+
|
|
60
|
+
ws.addEventListener("open", () => {
|
|
61
|
+
this.emit(openEvent({}));
|
|
62
|
+
});
|
|
63
|
+
ws.addEventListener("message", (event) => {
|
|
64
|
+
this.emit(messageEvent({ message: event.data }));
|
|
65
|
+
});
|
|
66
|
+
ws.addEventListener("close", () => {
|
|
67
|
+
this.emit(closeEvent({}));
|
|
68
|
+
});
|
|
69
|
+
ws.addEventListener("error", (event) => {
|
|
70
|
+
this.emit(errorEvent({ error: event }));
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
send(command: WebsocketCommands) {
|
|
75
|
+
if (isSendCommand(command)) {
|
|
76
|
+
this.ws.send(command.message);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export class WebsocketClientWrapper<
|
|
82
|
+
Commands extends Message,
|
|
83
|
+
Events extends Message
|
|
84
|
+
> extends Actor<Commands, Events> {
|
|
85
|
+
private readonly client: WebsocketClient;
|
|
86
|
+
|
|
87
|
+
constructor(private readonly ws: WebSocket | NodeWebsocket) {
|
|
88
|
+
super();
|
|
89
|
+
this.client = new WebsocketClient(ws);
|
|
90
|
+
|
|
91
|
+
this.client.connect((event) => {
|
|
92
|
+
if (isMessageEvent(event)) {
|
|
93
|
+
const message = JSON.parse(event.message) as Events;
|
|
94
|
+
this.emit(message);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
send(command: Commands) {
|
|
100
|
+
this.client.send(sendCommand({ message: JSON.stringify(command) }));
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export interface ConnectionEvent extends Message {
|
|
105
|
+
ws: NodeWebsocket;
|
|
106
|
+
}
|
|
107
|
+
export const {
|
|
108
|
+
message: connectionEvent,
|
|
109
|
+
isMessage: isConnectionEvent,
|
|
110
|
+
type: ConnectionEventType
|
|
111
|
+
} = defineMessage<ConnectionEvent>("connection-event");
|
|
112
|
+
|
|
113
|
+
export class WebsocketServer extends Actor<WebsocketCommands, WebsocketEvents> {
|
|
114
|
+
constructor(private readonly wss: NodeWebSocketServer) {
|
|
115
|
+
super();
|
|
116
|
+
|
|
117
|
+
this.wss.on("connection", (ws) => {
|
|
118
|
+
this.emit(connectionEvent({ ws }));
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export class WebsocketServerWrapper<
|
|
124
|
+
Commands extends Message,
|
|
125
|
+
Events extends Message
|
|
126
|
+
> {
|
|
127
|
+
constructor(ws: NodeWebsocket, actor: ActorInterface<Commands, Events>) {
|
|
128
|
+
//const client = new WebsocketClient(ws);
|
|
129
|
+
const wrapper = new WebsocketClientWrapper<Events, Commands>(ws);
|
|
130
|
+
wrapper.connect((command) => {
|
|
131
|
+
actor.send(command);
|
|
132
|
+
});
|
|
133
|
+
actor.connect((event) => {
|
|
134
|
+
wrapper.send(event);
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
}
|
package/src/server.ts
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { ActorInterface, actor } from "./actor.js";
|
|
2
|
+
import { Message } from "./message.js";
|
|
3
|
+
|
|
4
|
+
export type Replace<U, A, B> = Exclude<U, A> | B;
|
|
5
|
+
|
|
6
|
+
export type ActorTransformer<
|
|
7
|
+
A extends ActorInterface<C1, E1>,
|
|
8
|
+
B extends ActorInterface<C2, E2>,
|
|
9
|
+
C1 extends Message = never,
|
|
10
|
+
C2 extends Message = never,
|
|
11
|
+
E1 extends Message = never,
|
|
12
|
+
E2 extends Message = never
|
|
13
|
+
> = (a: A) => B;
|
|
14
|
+
|
|
15
|
+
export type CommandTransformer<
|
|
16
|
+
OldCommands extends Message,
|
|
17
|
+
NewCommands extends Message,
|
|
18
|
+
E extends Message = never,
|
|
19
|
+
A extends ActorInterface<OldCommands, E> = ActorInterface<OldCommands, E>,
|
|
20
|
+
B extends ActorInterface<NewCommands, E> = ActorInterface<NewCommands, E>
|
|
21
|
+
> = ActorTransformer<A, B, OldCommands, NewCommands, E, E>;
|
|
22
|
+
|
|
23
|
+
export type EventTransformer<
|
|
24
|
+
NewEvents extends Message,
|
|
25
|
+
OldEvents extends Message,
|
|
26
|
+
C extends Message = never,
|
|
27
|
+
A extends ActorInterface<C, OldEvents> = ActorInterface<C, OldEvents>,
|
|
28
|
+
B extends ActorInterface<C, NewEvents> = ActorInterface<C, NewEvents>
|
|
29
|
+
> = ActorTransformer<A, B, C, C, OldEvents, NewEvents>;
|
|
30
|
+
|
|
31
|
+
export type TransformerFunction<A extends Message, B extends Message> = (
|
|
32
|
+
message: A
|
|
33
|
+
) => B;
|
|
34
|
+
|
|
35
|
+
export function commandTransformer<
|
|
36
|
+
OldCommands extends Message,
|
|
37
|
+
NewCommands extends Message,
|
|
38
|
+
Events extends Message = never
|
|
39
|
+
>(
|
|
40
|
+
fn: TransformerFunction<NewCommands, OldCommands>
|
|
41
|
+
): CommandTransformer<OldCommands, NewCommands, Events> {
|
|
42
|
+
return (wrapped: ActorInterface<OldCommands, Events>) =>
|
|
43
|
+
actor((emit) => {
|
|
44
|
+
wrapped.connect(emit);
|
|
45
|
+
|
|
46
|
+
return (command) => {
|
|
47
|
+
wrapped.send(fn(command));
|
|
48
|
+
};
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function eventTransformer<
|
|
53
|
+
OldEvents extends Message,
|
|
54
|
+
NewEvents extends Message,
|
|
55
|
+
Commands extends Message = never
|
|
56
|
+
>(
|
|
57
|
+
fn: TransformerFunction<OldEvents, NewEvents>
|
|
58
|
+
): EventTransformer<NewEvents, OldEvents, Commands> {
|
|
59
|
+
return (wrapped: ActorInterface<Commands, OldEvents>) =>
|
|
60
|
+
actor((emit) => {
|
|
61
|
+
wrapped.connect((msg) => {
|
|
62
|
+
emit(fn(msg));
|
|
63
|
+
});
|
|
64
|
+
return (command) => wrapped.send(command);
|
|
65
|
+
});
|
|
66
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import EventEmitter from "node:events";
|
|
2
|
+
|
|
3
|
+
export class TypedEmitter<TEvents extends Record<string, unknown>> {
|
|
4
|
+
private emitter = new EventEmitter();
|
|
5
|
+
|
|
6
|
+
emit<TEventName extends keyof TEvents & string>(
|
|
7
|
+
eventName: TEventName,
|
|
8
|
+
eventArg: TEvents[TEventName]
|
|
9
|
+
) {
|
|
10
|
+
this.emitter.emit(eventName, eventArg);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
on<TEventName extends keyof TEvents & string>(
|
|
14
|
+
eventName: TEventName,
|
|
15
|
+
handler: (eventArg: TEvents[TEventName]) => void
|
|
16
|
+
) {
|
|
17
|
+
this.emitter.on(eventName, handler);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
off<TEventName extends keyof TEvents & string>(
|
|
21
|
+
eventName: TEventName,
|
|
22
|
+
handler: (eventArg: TEvents[TEventName]) => void
|
|
23
|
+
) {
|
|
24
|
+
this.emitter.off(eventName, handler);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
removeAllListeners() {
|
|
28
|
+
this.emitter.removeAllListeners();
|
|
29
|
+
}
|
|
30
|
+
}
|