recker 1.0.83 → 1.0.84-next.ca0ad49
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 +20 -2
- package/dist/mcp/resources/index.js +130 -0
- package/dist/raffel/client.d.ts +12 -4
- package/dist/raffel/client.js +164 -45
- package/dist/raffel/index.d.ts +7 -0
- package/dist/raffel/index.js +7 -0
- package/dist/raffel/transport-factory.d.ts +4 -0
- package/dist/raffel/transport-factory.js +52 -0
- package/dist/raffel/transport-http.d.ts +25 -0
- package/dist/raffel/transport-http.js +211 -0
- package/dist/raffel/transport-jsonrpc.d.ts +24 -0
- package/dist/raffel/transport-jsonrpc.js +139 -0
- package/dist/raffel/transport-tcp.d.ts +30 -0
- package/dist/raffel/transport-tcp.js +183 -0
- package/dist/raffel/transport-udp.d.ts +22 -0
- package/dist/raffel/transport-udp.js +104 -0
- package/dist/raffel/transport-ws.d.ts +19 -0
- package/dist/raffel/transport-ws.js +75 -0
- package/dist/raffel/transport.d.ts +29 -0
- package/dist/raffel/transport.js +14 -0
- package/dist/raffel/types.d.ts +30 -2
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { createSocket } from 'node:dgram';
|
|
2
|
+
import { TransportCapability } from './transport.js';
|
|
3
|
+
const MAX_DATAGRAM_SIZE = 65_507;
|
|
4
|
+
const UDP_CAPABILITIES = TransportCapability.CALL |
|
|
5
|
+
TransportCapability.NOTIFY;
|
|
6
|
+
export class UdpTransport {
|
|
7
|
+
capabilities = UDP_CAPABILITIES;
|
|
8
|
+
socket = null;
|
|
9
|
+
connected = false;
|
|
10
|
+
listeners = new Map();
|
|
11
|
+
host;
|
|
12
|
+
port;
|
|
13
|
+
options;
|
|
14
|
+
constructor(url, options = {}) {
|
|
15
|
+
const parsed = new URL(url.replace('udp://', 'http://'));
|
|
16
|
+
this.host = parsed.hostname;
|
|
17
|
+
this.port = parseInt(parsed.port, 10) || 9000;
|
|
18
|
+
this.options = options;
|
|
19
|
+
}
|
|
20
|
+
get isConnected() {
|
|
21
|
+
return this.connected;
|
|
22
|
+
}
|
|
23
|
+
async connect() {
|
|
24
|
+
return new Promise((resolve, reject) => {
|
|
25
|
+
const socketType = this.options.socketType ?? 'udp4';
|
|
26
|
+
this.socket = createSocket(socketType);
|
|
27
|
+
this.socket.on('message', (msg) => {
|
|
28
|
+
let parsed;
|
|
29
|
+
try {
|
|
30
|
+
parsed = JSON.parse(msg.toString('utf8'));
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
this.emit('error', new Error('Invalid JSON in UDP datagram'));
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
this.emit('message', parsed);
|
|
37
|
+
});
|
|
38
|
+
this.socket.on('error', (err) => {
|
|
39
|
+
this.emit('error', err);
|
|
40
|
+
});
|
|
41
|
+
this.socket.on('close', () => {
|
|
42
|
+
this.connected = false;
|
|
43
|
+
this.emit('disconnected');
|
|
44
|
+
});
|
|
45
|
+
this.socket.bind(0, () => {
|
|
46
|
+
this.connected = true;
|
|
47
|
+
this.emit('connected');
|
|
48
|
+
resolve();
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
close() {
|
|
53
|
+
if (this.socket) {
|
|
54
|
+
try {
|
|
55
|
+
this.socket.close();
|
|
56
|
+
}
|
|
57
|
+
catch { }
|
|
58
|
+
this.socket = null;
|
|
59
|
+
}
|
|
60
|
+
if (this.connected) {
|
|
61
|
+
this.connected = false;
|
|
62
|
+
this.emit('disconnected');
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
send(data) {
|
|
66
|
+
if (!this.socket || !this.connected) {
|
|
67
|
+
throw new Error('UDP transport not connected');
|
|
68
|
+
}
|
|
69
|
+
const json = JSON.stringify(data);
|
|
70
|
+
const buf = Buffer.from(json, 'utf8');
|
|
71
|
+
if (buf.length > MAX_DATAGRAM_SIZE) {
|
|
72
|
+
throw new Error(`Datagram size ${buf.length} exceeds maximum ${MAX_DATAGRAM_SIZE}`);
|
|
73
|
+
}
|
|
74
|
+
this.socket.send(buf, this.port, this.host);
|
|
75
|
+
}
|
|
76
|
+
on(event, listener) {
|
|
77
|
+
const set = this.listeners.get(event) ?? new Set();
|
|
78
|
+
set.add(listener);
|
|
79
|
+
this.listeners.set(event, set);
|
|
80
|
+
}
|
|
81
|
+
off(event, listener) {
|
|
82
|
+
const set = this.listeners.get(event);
|
|
83
|
+
if (set) {
|
|
84
|
+
set.delete(listener);
|
|
85
|
+
if (set.size === 0)
|
|
86
|
+
this.listeners.delete(event);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
once(event, listener) {
|
|
90
|
+
const wrapped = (...args) => {
|
|
91
|
+
this.off(event, wrapped);
|
|
92
|
+
listener(...args);
|
|
93
|
+
};
|
|
94
|
+
this.on(event, wrapped);
|
|
95
|
+
}
|
|
96
|
+
emit(event, ...args) {
|
|
97
|
+
const set = this.listeners.get(event);
|
|
98
|
+
if (!set)
|
|
99
|
+
return;
|
|
100
|
+
for (const listener of [...set]) {
|
|
101
|
+
listener(...args);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ReckerWebSocket, type WebSocketOptions } from '../websocket/client.js';
|
|
2
|
+
import type { RaffelTransport, RaffelTransportEvent } from './transport.js';
|
|
3
|
+
type Listener = (...args: any[]) => void;
|
|
4
|
+
export declare class WsTransport implements RaffelTransport {
|
|
5
|
+
readonly capabilities: number;
|
|
6
|
+
private ws;
|
|
7
|
+
private listeners;
|
|
8
|
+
constructor(url: string, options?: WebSocketOptions);
|
|
9
|
+
get isConnected(): boolean;
|
|
10
|
+
get socket(): ReckerWebSocket;
|
|
11
|
+
connect(): Promise<void>;
|
|
12
|
+
close(code?: number, reason?: string): void;
|
|
13
|
+
send(data: unknown): void;
|
|
14
|
+
on(event: RaffelTransportEvent, listener: Listener): void;
|
|
15
|
+
off(event: RaffelTransportEvent, listener: Listener): void;
|
|
16
|
+
once(event: RaffelTransportEvent, listener: Listener): void;
|
|
17
|
+
private emit;
|
|
18
|
+
}
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { ReckerWebSocket } from '../websocket/client.js';
|
|
2
|
+
import { TransportCapability } from './transport.js';
|
|
3
|
+
const ALL_CAPABILITIES = TransportCapability.CALL |
|
|
4
|
+
TransportCapability.NOTIFY |
|
|
5
|
+
TransportCapability.SUBSCRIBE |
|
|
6
|
+
TransportCapability.PUBLISH |
|
|
7
|
+
TransportCapability.CANCEL |
|
|
8
|
+
TransportCapability.STREAM;
|
|
9
|
+
export class WsTransport {
|
|
10
|
+
capabilities = ALL_CAPABILITIES;
|
|
11
|
+
ws;
|
|
12
|
+
listeners = new Map();
|
|
13
|
+
constructor(url, options = {}) {
|
|
14
|
+
this.ws = new ReckerWebSocket(url, options);
|
|
15
|
+
this.ws.on('message', (msg) => {
|
|
16
|
+
if (typeof msg.data !== 'string')
|
|
17
|
+
return;
|
|
18
|
+
let parsed;
|
|
19
|
+
try {
|
|
20
|
+
parsed = JSON.parse(msg.data);
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
this.emit('message', parsed);
|
|
26
|
+
});
|
|
27
|
+
this.ws.on('open', () => this.emit('connected'));
|
|
28
|
+
this.ws.on('close', () => this.emit('disconnected'));
|
|
29
|
+
this.ws.on('reconnecting', (attempt, delay) => this.emit('reconnecting', attempt, delay));
|
|
30
|
+
this.ws.on('error', (err) => this.emit('error', err));
|
|
31
|
+
}
|
|
32
|
+
get isConnected() {
|
|
33
|
+
return this.ws.isConnected;
|
|
34
|
+
}
|
|
35
|
+
get socket() {
|
|
36
|
+
return this.ws;
|
|
37
|
+
}
|
|
38
|
+
async connect() {
|
|
39
|
+
return this.ws.connect();
|
|
40
|
+
}
|
|
41
|
+
close(code, reason) {
|
|
42
|
+
this.ws.close(code, reason);
|
|
43
|
+
}
|
|
44
|
+
send(data) {
|
|
45
|
+
this.ws.sendJSON(data);
|
|
46
|
+
}
|
|
47
|
+
on(event, listener) {
|
|
48
|
+
const set = this.listeners.get(event) ?? new Set();
|
|
49
|
+
set.add(listener);
|
|
50
|
+
this.listeners.set(event, set);
|
|
51
|
+
}
|
|
52
|
+
off(event, listener) {
|
|
53
|
+
const set = this.listeners.get(event);
|
|
54
|
+
if (set) {
|
|
55
|
+
set.delete(listener);
|
|
56
|
+
if (set.size === 0)
|
|
57
|
+
this.listeners.delete(event);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
once(event, listener) {
|
|
61
|
+
const wrapped = (...args) => {
|
|
62
|
+
this.off(event, wrapped);
|
|
63
|
+
listener(...args);
|
|
64
|
+
};
|
|
65
|
+
this.on(event, wrapped);
|
|
66
|
+
}
|
|
67
|
+
emit(event, ...args) {
|
|
68
|
+
const set = this.listeners.get(event);
|
|
69
|
+
if (!set)
|
|
70
|
+
return;
|
|
71
|
+
for (const listener of [...set]) {
|
|
72
|
+
listener(...args);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { RaffelEnvelope } from './types.js';
|
|
2
|
+
export declare const TransportCapability: {
|
|
3
|
+
readonly CALL: 1;
|
|
4
|
+
readonly NOTIFY: 2;
|
|
5
|
+
readonly SUBSCRIBE: 4;
|
|
6
|
+
readonly PUBLISH: 8;
|
|
7
|
+
readonly CANCEL: 16;
|
|
8
|
+
readonly STREAM: 32;
|
|
9
|
+
};
|
|
10
|
+
export type TransportCapabilityFlag = (typeof TransportCapability)[keyof typeof TransportCapability];
|
|
11
|
+
export type RaffelTransportEvent = 'connected' | 'disconnected' | 'message' | 'reconnecting' | 'error';
|
|
12
|
+
type Listener = (...args: any[]) => void;
|
|
13
|
+
export interface RaffelTransport {
|
|
14
|
+
readonly capabilities: number;
|
|
15
|
+
readonly isConnected: boolean;
|
|
16
|
+
connect(): Promise<void>;
|
|
17
|
+
close(code?: number, reason?: string): void;
|
|
18
|
+
send(data: unknown): void;
|
|
19
|
+
on(event: RaffelTransportEvent, listener: Listener): void;
|
|
20
|
+
off(event: RaffelTransportEvent, listener: Listener): void;
|
|
21
|
+
once(event: RaffelTransportEvent, listener: Listener): void;
|
|
22
|
+
}
|
|
23
|
+
export interface RaffelExecutableTransport extends RaffelTransport {
|
|
24
|
+
execute(envelope: RaffelEnvelope): Promise<unknown>;
|
|
25
|
+
executeStream?(envelope: RaffelEnvelope): AsyncIterable<unknown>;
|
|
26
|
+
}
|
|
27
|
+
export declare function hasExecute(transport: RaffelTransport): transport is RaffelExecutableTransport;
|
|
28
|
+
export declare function hasCapability(transport: RaffelTransport, cap: number): boolean;
|
|
29
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export const TransportCapability = {
|
|
2
|
+
CALL: 0b000001,
|
|
3
|
+
NOTIFY: 0b000010,
|
|
4
|
+
SUBSCRIBE: 0b000100,
|
|
5
|
+
PUBLISH: 0b001000,
|
|
6
|
+
CANCEL: 0b010000,
|
|
7
|
+
STREAM: 0b100000,
|
|
8
|
+
};
|
|
9
|
+
export function hasExecute(transport) {
|
|
10
|
+
return typeof transport.execute === 'function';
|
|
11
|
+
}
|
|
12
|
+
export function hasCapability(transport, cap) {
|
|
13
|
+
return (transport.capabilities & cap) === cap;
|
|
14
|
+
}
|
package/dist/raffel/types.d.ts
CHANGED
|
@@ -20,12 +20,40 @@ export interface RaffelErrorPayload {
|
|
|
20
20
|
message: string;
|
|
21
21
|
details?: unknown;
|
|
22
22
|
}
|
|
23
|
+
export type RaffelTransportType = 'websocket' | 'http' | 'tcp' | 'udp' | 'jsonrpc';
|
|
24
|
+
export interface RaffelHttpOptions {
|
|
25
|
+
headers?: Record<string, string>;
|
|
26
|
+
timeout?: number;
|
|
27
|
+
}
|
|
28
|
+
export interface RaffelTcpOptions {
|
|
29
|
+
keepAlive?: boolean;
|
|
30
|
+
keepAliveInterval?: number;
|
|
31
|
+
noDelay?: boolean;
|
|
32
|
+
reconnect?: boolean;
|
|
33
|
+
reconnectDelay?: number;
|
|
34
|
+
maxReconnectAttempts?: number;
|
|
35
|
+
}
|
|
36
|
+
export interface RaffelUdpOptions {
|
|
37
|
+
socketType?: 'udp4' | 'udp6';
|
|
38
|
+
enableAck?: boolean;
|
|
39
|
+
ackTimeout?: number;
|
|
40
|
+
}
|
|
41
|
+
export interface RaffelJsonRpcOptions {
|
|
42
|
+
path?: string;
|
|
43
|
+
headers?: Record<string, string>;
|
|
44
|
+
}
|
|
23
45
|
export type ChannelEventHandler = (event: string, data: unknown) => void;
|
|
24
|
-
export interface RaffelClientOptions
|
|
46
|
+
export interface RaffelClientOptions {
|
|
47
|
+
transport?: RaffelTransportType;
|
|
48
|
+
defaultTimeout?: number;
|
|
25
49
|
channels?: string[];
|
|
26
50
|
channelHandlers?: Record<string, ChannelEventHandler>;
|
|
27
51
|
onEvent?: (procedure: string, payload: unknown) => void;
|
|
28
|
-
|
|
52
|
+
ws?: WebSocketOptions;
|
|
53
|
+
http?: RaffelHttpOptions;
|
|
54
|
+
tcp?: RaffelTcpOptions;
|
|
55
|
+
udp?: RaffelUdpOptions;
|
|
56
|
+
jsonrpc?: RaffelJsonRpcOptions;
|
|
29
57
|
}
|
|
30
58
|
export interface RaffelCallOptions {
|
|
31
59
|
timeout?: number;
|
package/dist/version.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "recker",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.84-next.ca0ad49",
|
|
4
4
|
"description": "Multi-Protocol SDK for the AI Era - HTTP, WebSocket, DNS, FTP, SFTP, Telnet, HLS unified with AI providers and MCP tools",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|