@genesis-agent/channel-sdk 0.5.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/package.json ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "@genesis-agent/channel-sdk",
3
+ "version": "0.5.0",
4
+ "description": "SDK for building Genesis channel adapters in Node.js / TypeScript",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/deadraid/genesis.git",
9
+ "directory": "packaging/channel-sdk-node"
10
+ },
11
+ "main": "src/index.js",
12
+ "types": "src/index.d.ts",
13
+ "files": ["src/"],
14
+ "engines": {
15
+ "node": ">=16"
16
+ },
17
+ "keywords": [
18
+ "genesis",
19
+ "channel",
20
+ "sdk",
21
+ "ai",
22
+ "agent",
23
+ "telegram",
24
+ "discord",
25
+ "slack"
26
+ ]
27
+ }
package/src/index.d.ts ADDED
@@ -0,0 +1,65 @@
1
+ export interface Capabilities {
2
+ text?: boolean;
3
+ markdown?: boolean;
4
+ images?: boolean;
5
+ files?: boolean;
6
+ buttons?: boolean;
7
+ inline_buttons?: boolean;
8
+ typing_indicator?: boolean;
9
+ edit_message?: boolean;
10
+ delete_message?: boolean;
11
+ threads?: boolean;
12
+ reactions?: boolean;
13
+ voice?: boolean;
14
+ max_message_length?: number;
15
+ }
16
+
17
+ export interface SendParams {
18
+ to: { channel_identity: string };
19
+ content: { text?: string; format?: string; file?: { name: string; data: string } };
20
+ }
21
+
22
+ export interface TypingParams {
23
+ to: { channel_identity: string };
24
+ active: boolean;
25
+ }
26
+
27
+ export interface RequestAuthParams {
28
+ to: { channel_identity: string };
29
+ request_id: string;
30
+ prompt: string;
31
+ options?: Array<{ label: string; value: string }>;
32
+ timeout_ms?: number;
33
+ }
34
+
35
+ export interface ChannelConfig {
36
+ capabilities?: Capabilities;
37
+ systemPrompt?: string;
38
+ onSend?: (params: SendParams) => void | Promise<unknown>;
39
+ onEdit?: (params: SendParams) => void | Promise<unknown>;
40
+ onDelete?: (params: { to: { channel_identity: string } }) => void | Promise<unknown>;
41
+ onTyping?: (params: TypingParams) => void;
42
+ onRequestAuth?: (params: RequestAuthParams) => void | Promise<unknown>;
43
+ onStartup?: () => void | Promise<void>;
44
+ }
45
+
46
+ export interface Channel {
47
+ emitMessage(channelIdentity: string, displayName: string, text: string, timestamp?: number): void;
48
+ emitFileMessage(channelIdentity: string, displayName: string, fileName: string, fileDataB64: string, caption?: string, timestamp?: number): void;
49
+ emitEvent(channelIdentity: string, displayName: string, eventType: string, data: string): void;
50
+ sendStatus(state: string): void;
51
+ splitMessage(text: string, maxLen: number): string[];
52
+ respond(id: number | string, result?: object, error?: object): void;
53
+ }
54
+
55
+ export function createChannel(config: ChannelConfig): Channel;
56
+
57
+ export function writeJsonLine(obj: object): void;
58
+ export function notify(method: string, params: object): void;
59
+ export function respond(id: number | string, result?: object, error?: object): void;
60
+ export function sendHello(capabilities: Capabilities, systemPrompt?: string): void;
61
+ export function sendStatus(state: string): void;
62
+ export function emitMessage(channelIdentity: string, displayName: string, text: string, timestamp?: number): void;
63
+ export function emitFileMessage(channelIdentity: string, displayName: string, fileName: string, fileDataB64: string, caption?: string, timestamp?: number): void;
64
+ export function emitEvent(channelIdentity: string, displayName: string, eventType: string, data: string): void;
65
+ export function splitMessage(text: string, maxLen: number): string[];
package/src/index.js ADDED
@@ -0,0 +1,171 @@
1
+ "use strict";
2
+
3
+ const readline = require("readline");
4
+
5
+ function writeJsonLine(obj) {
6
+ process.stdout.write(JSON.stringify(obj) + "\n");
7
+ }
8
+
9
+ function notify(method, params) {
10
+ writeJsonLine({ jsonrpc: "2.0", method, params });
11
+ }
12
+
13
+ function respond(id, result, error) {
14
+ const msg = { jsonrpc: "2.0", id };
15
+ if (error) msg.error = error;
16
+ else msg.result = result || {};
17
+ writeJsonLine(msg);
18
+ }
19
+
20
+ function sendHello(capabilities, systemPrompt) {
21
+ const params = { capabilities };
22
+ if (systemPrompt) params.system_prompt = systemPrompt;
23
+ notify("channel.hello", params);
24
+ }
25
+
26
+ function sendStatus(state) {
27
+ notify("channel.status", { state });
28
+ }
29
+
30
+ function emitMessage(channelIdentity, displayName, text, timestamp) {
31
+ notify("channel.message", {
32
+ from: { channel_identity: channelIdentity, display_name: displayName },
33
+ text,
34
+ timestamp: timestamp || Math.floor(Date.now() / 1000),
35
+ });
36
+ }
37
+
38
+ function emitFileMessage(channelIdentity, displayName, fileName, fileDataB64, caption, timestamp) {
39
+ notify("channel.message", {
40
+ from: { channel_identity: channelIdentity, display_name: displayName },
41
+ text: caption || "",
42
+ timestamp: timestamp || Math.floor(Date.now() / 1000),
43
+ file: { name: fileName, data: fileDataB64 },
44
+ });
45
+ }
46
+
47
+ function emitEvent(channelIdentity, displayName, eventType, data) {
48
+ notify("channel.event", {
49
+ from: { channel_identity: channelIdentity, display_name: displayName },
50
+ type: eventType,
51
+ data,
52
+ });
53
+ }
54
+
55
+ function splitMessage(text, maxLen) {
56
+ const chunks = [];
57
+ let remaining = text;
58
+ while (remaining.length > 0) {
59
+ if (remaining.length <= maxLen) {
60
+ chunks.push(remaining);
61
+ break;
62
+ }
63
+ let splitAt = maxLen;
64
+ while (splitAt > 0 && remaining[splitAt - 1] !== "\n") splitAt--;
65
+ if (splitAt === 0) splitAt = maxLen;
66
+ chunks.push(remaining.slice(0, splitAt));
67
+ remaining = remaining.slice(splitAt);
68
+ }
69
+ return chunks;
70
+ }
71
+
72
+ function createChannel(config) {
73
+ const {
74
+ capabilities = { text: true, max_message_length: 4096 },
75
+ systemPrompt,
76
+ onSend,
77
+ onEdit,
78
+ onDelete,
79
+ onTyping,
80
+ onRequestAuth,
81
+ onStartup,
82
+ } = config;
83
+
84
+ sendHello(capabilities, systemPrompt);
85
+
86
+ if (onStartup) {
87
+ Promise.resolve(onStartup()).catch((err) => {
88
+ process.stderr.write(`[channel] startup error: ${err}\n`);
89
+ });
90
+ }
91
+
92
+ const rl = readline.createInterface({ input: process.stdin, terminal: false });
93
+
94
+ rl.on("line", (raw) => {
95
+ raw = raw.trim();
96
+ if (!raw) return;
97
+
98
+ let msg;
99
+ try {
100
+ msg = JSON.parse(raw);
101
+ } catch {
102
+ process.stderr.write(`[channel] invalid json: ${raw}\n`);
103
+ return;
104
+ }
105
+
106
+ const method = msg.method;
107
+ const params = msg.params || {};
108
+ const id = msg.id;
109
+
110
+ const handleResult = (promise, fallback) => {
111
+ if (!promise) {
112
+ if (id != null) respond(id, { ok: true });
113
+ return;
114
+ }
115
+ Promise.resolve(promise)
116
+ .then((result) => {
117
+ if (id != null) respond(id, result || { ok: true });
118
+ })
119
+ .catch((err) => {
120
+ process.stderr.write(`[channel] ${method}: ${err}\n`);
121
+ if (id != null) respond(id, null, { code: -32000, message: String(err) });
122
+ });
123
+ };
124
+
125
+ switch (method) {
126
+ case "channel.send":
127
+ handleResult(onSend ? onSend(params) : null);
128
+ break;
129
+ case "channel.edit":
130
+ handleResult(onEdit ? onEdit(params) : null);
131
+ break;
132
+ case "channel.delete":
133
+ handleResult(onDelete ? onDelete(params) : null);
134
+ break;
135
+ case "channel.typing":
136
+ if (onTyping) onTyping(params);
137
+ break;
138
+ case "channel.request_auth":
139
+ handleResult(onRequestAuth ? onRequestAuth(params) : null);
140
+ break;
141
+ default:
142
+ if (id != null) {
143
+ respond(id, null, { code: -32601, message: `Method not found: ${method}` });
144
+ }
145
+ }
146
+ });
147
+
148
+ rl.on("close", () => process.exit(0));
149
+
150
+ return {
151
+ emitMessage,
152
+ emitFileMessage,
153
+ emitEvent,
154
+ sendStatus,
155
+ splitMessage,
156
+ respond,
157
+ };
158
+ }
159
+
160
+ module.exports = {
161
+ createChannel,
162
+ writeJsonLine,
163
+ notify,
164
+ respond,
165
+ sendHello,
166
+ sendStatus,
167
+ emitMessage,
168
+ emitFileMessage,
169
+ emitEvent,
170
+ splitMessage,
171
+ };