@ebowwa/stack 0.2.0 → 0.3.1
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/dist/index.js +61863 -1909
- package/package.json +7 -4
- package/src/index.ts +85 -18
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ebowwa/stack",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Cross-channel AI stack with
|
|
3
|
+
"version": "0.3.1",
|
|
4
|
+
"description": "Cross-channel AI stack with node-agent integration (SSH + Telegram + Ralph/Git)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
@@ -25,7 +25,9 @@
|
|
|
25
25
|
"ssh",
|
|
26
26
|
"ai",
|
|
27
27
|
"cross-channel",
|
|
28
|
-
"memory"
|
|
28
|
+
"memory",
|
|
29
|
+
"ralph",
|
|
30
|
+
"node-agent"
|
|
29
31
|
],
|
|
30
32
|
"author": "Ebowwa Labs <labs@ebowwa.com>",
|
|
31
33
|
"license": "MIT",
|
|
@@ -40,7 +42,8 @@
|
|
|
40
42
|
"@ebowwa/channel-ssh": "^2.1.1",
|
|
41
43
|
"@ebowwa/channel-telegram": "^1.14.2",
|
|
42
44
|
"@ebowwa/channel-types": "^0.2.1",
|
|
43
|
-
"@ebowwa/codespaces-types": "^1.6.1"
|
|
45
|
+
"@ebowwa/codespaces-types": "^1.6.1",
|
|
46
|
+
"@ebowwa/node-agent": "^0.6.5"
|
|
44
47
|
},
|
|
45
48
|
"devDependencies": {
|
|
46
49
|
"@types/bun": "latest"
|
package/src/index.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
/**
|
|
3
|
-
* @ebowwa/stack - Cross-Channel AI Stack
|
|
3
|
+
* @ebowwa/stack - Cross-Channel AI Stack with Node Agent
|
|
4
4
|
*
|
|
5
5
|
* Features:
|
|
6
6
|
* - Unified Router: Cross-channel communication (SSH + Telegram)
|
|
7
7
|
* - Cross-channel memory with permission controls
|
|
8
8
|
* - AI-powered message handling
|
|
9
|
+
* - Node Agent: Ralph loops, Git, Monitoring (imported but disabled for now)
|
|
9
10
|
*
|
|
10
11
|
* Architecture:
|
|
11
12
|
* ┌──────────────────────────────────────────────────────────────┐
|
|
@@ -22,9 +23,13 @@
|
|
|
22
23
|
* │ │ (Cross-Context) │ │
|
|
23
24
|
* │ └─────────┬─────────┘ │
|
|
24
25
|
* │ │ │
|
|
25
|
-
* │
|
|
26
|
-
* │
|
|
27
|
-
* │
|
|
26
|
+
* │ ┌───────────────────┴───────────────────┐ │
|
|
27
|
+
* │ │ │ │
|
|
28
|
+
* │ ┌───────▼───────┐ ┌──────────▼───────┐ │
|
|
29
|
+
* │ │ AI Brain │ │ Node Agent │ │
|
|
30
|
+
* │ │ (GLM) │ │ (Ralph/Git/...) │ │
|
|
31
|
+
* │ └───────────────┘ │ [DISABLED] │ │
|
|
32
|
+
* │ └──────────────────┘ │
|
|
28
33
|
* └──────────────────────────────────────────────────────────────┘
|
|
29
34
|
*/
|
|
30
35
|
|
|
@@ -33,6 +38,11 @@ import type { ChannelConnector, ChannelMessage, ChannelResponse, ChannelId } fro
|
|
|
33
38
|
import { GLMClient } from "@ebowwa/ai";
|
|
34
39
|
import { ToolExecutor, BUILTIN_TOOLS } from "@ebowwa/ai/tools";
|
|
35
40
|
|
|
41
|
+
// Node Agent types (lazy import to avoid bundling issues)
|
|
42
|
+
type RalphServiceType = InstanceType<typeof import("@ebowwa/node-agent/lib").RalphService>;
|
|
43
|
+
type GitServiceType = InstanceType<typeof import("@ebowwa/node-agent/lib").GitService>;
|
|
44
|
+
type ConsoleLoggerServiceType = InstanceType<typeof import("@ebowwa/node-agent/lib").ConsoleLoggerService>;
|
|
45
|
+
|
|
36
46
|
// ============================================================
|
|
37
47
|
// Types
|
|
38
48
|
// ============================================================
|
|
@@ -64,6 +74,8 @@ export interface StackConfig {
|
|
|
64
74
|
name: string;
|
|
65
75
|
hostname?: string;
|
|
66
76
|
};
|
|
77
|
+
/** Enable Node Agent features (Ralph, Git, etc.) */
|
|
78
|
+
enableNodeAgent?: boolean;
|
|
67
79
|
}
|
|
68
80
|
|
|
69
81
|
export interface StackState {
|
|
@@ -76,6 +88,9 @@ export interface StackState {
|
|
|
76
88
|
enabled: boolean;
|
|
77
89
|
port?: number;
|
|
78
90
|
};
|
|
91
|
+
nodeAgent: {
|
|
92
|
+
enabled: boolean;
|
|
93
|
+
};
|
|
79
94
|
}
|
|
80
95
|
|
|
81
96
|
// ============================================================
|
|
@@ -92,6 +107,11 @@ export class Stack {
|
|
|
92
107
|
private channels: Map<string, ChannelConnector> = new Map();
|
|
93
108
|
private abortController: AbortController | null = null;
|
|
94
109
|
|
|
110
|
+
// Node Agent services (lazy loaded to avoid bundling issues)
|
|
111
|
+
private ralphService: RalphServiceType | null = null;
|
|
112
|
+
private gitService: GitServiceType | null = null;
|
|
113
|
+
private consoleLogger: ConsoleLoggerServiceType | null = null;
|
|
114
|
+
|
|
95
115
|
constructor(config: StackConfig) {
|
|
96
116
|
this.config = {
|
|
97
117
|
...config,
|
|
@@ -104,9 +124,10 @@ export class Stack {
|
|
|
104
124
|
started: new Date(),
|
|
105
125
|
channels: { ssh: false, telegram: false },
|
|
106
126
|
api: { enabled: !!this.config.api, port: this.config.api?.port },
|
|
127
|
+
nodeAgent: { enabled: false },
|
|
107
128
|
};
|
|
108
129
|
|
|
109
|
-
// Build memory channels dynamically
|
|
130
|
+
// Build memory channels dynamically
|
|
110
131
|
const memoryChannels: Record<string, { memoryFile: string; maxMessages: number }> = {};
|
|
111
132
|
const permissions: Record<string, { canRead: string[] }> = {};
|
|
112
133
|
const enabledChannels: string[] = [];
|
|
@@ -120,30 +141,28 @@ export class Stack {
|
|
|
120
141
|
enabledChannels.push("telegram");
|
|
121
142
|
}
|
|
122
143
|
|
|
123
|
-
// Set up cross-channel permissions
|
|
124
144
|
for (const channel of enabledChannels) {
|
|
125
145
|
permissions[channel] = { canRead: enabledChannels.filter(c => c !== channel) };
|
|
126
146
|
}
|
|
127
147
|
|
|
128
|
-
// Initialize shared memory
|
|
129
148
|
this.memory = createPermissionMemory({
|
|
130
149
|
channels: memoryChannels,
|
|
131
150
|
permissions,
|
|
132
151
|
});
|
|
133
152
|
|
|
134
|
-
// Initialize router
|
|
135
153
|
this.router = createChannelRouter({
|
|
136
154
|
announcement: {
|
|
137
155
|
serverName: this.config.node.name,
|
|
138
156
|
hostname: this.config.node.hostname,
|
|
139
157
|
packageName: "@ebowwa/stack",
|
|
140
|
-
version: "0.
|
|
158
|
+
version: "0.3.0",
|
|
141
159
|
},
|
|
142
160
|
});
|
|
143
161
|
|
|
144
|
-
// Initialize AI
|
|
145
162
|
this.client = new GLMClient();
|
|
146
163
|
this.executor = new ToolExecutor(this.client, [...BUILTIN_TOOLS]);
|
|
164
|
+
|
|
165
|
+
// Node Agent services initialized lazily in initializeNodeAgent()
|
|
147
166
|
}
|
|
148
167
|
|
|
149
168
|
// ============================================================
|
|
@@ -183,6 +202,38 @@ export class Stack {
|
|
|
183
202
|
console.log("[Stack] Telegram registered");
|
|
184
203
|
}
|
|
185
204
|
|
|
205
|
+
// ============================================================
|
|
206
|
+
// Node Agent Initialization
|
|
207
|
+
// ============================================================
|
|
208
|
+
|
|
209
|
+
private async initializeNodeAgent(): Promise<void> {
|
|
210
|
+
console.log("[Stack] Initializing Node Agent services...");
|
|
211
|
+
|
|
212
|
+
// Lazy import to avoid bundling issues with node-agent
|
|
213
|
+
try {
|
|
214
|
+
const nodeAgent = await import("@ebowwa/node-agent/lib");
|
|
215
|
+
|
|
216
|
+
// Initialize services (features disabled for now)
|
|
217
|
+
this.ralphService = new nodeAgent.RalphService();
|
|
218
|
+
this.gitService = new nodeAgent.GitService();
|
|
219
|
+
this.consoleLogger = new nodeAgent.ConsoleLoggerService();
|
|
220
|
+
|
|
221
|
+
// Initialize state service
|
|
222
|
+
await nodeAgent.initializeStateService();
|
|
223
|
+
console.log("[Stack] State service initialized");
|
|
224
|
+
|
|
225
|
+
// TODO: Enable Ralph/Git when ready
|
|
226
|
+
// this.ralphService?.startMonitoring();
|
|
227
|
+
// this.gitService?.initialize();
|
|
228
|
+
|
|
229
|
+
this.state.nodeAgent.enabled = true;
|
|
230
|
+
console.log("[Stack] Node Agent services ready (Ralph/Git DISABLED)");
|
|
231
|
+
} catch (error) {
|
|
232
|
+
console.warn("[Stack] Node Agent initialization failed (non-critical):", error);
|
|
233
|
+
console.warn("[Stack] Continuing without Node Agent services");
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
186
237
|
// ============================================================
|
|
187
238
|
// Message Handler
|
|
188
239
|
// ============================================================
|
|
@@ -194,7 +245,7 @@ export class Stack {
|
|
|
194
245
|
|
|
195
246
|
console.log(`[${channel}] ${text.slice(0, 50)}...`);
|
|
196
247
|
|
|
197
|
-
//
|
|
248
|
+
// Typing indicator for Telegram
|
|
198
249
|
const telegramChannel = this.channels.get("telegram") as { startTypingIndicator?: (chatId: string) => void; stopTypingIndicator?: (chatId: string) => void } | undefined;
|
|
199
250
|
const chatId = channelId.metadata?.chatId as string | undefined;
|
|
200
251
|
if (channel === "telegram" && telegramChannel?.startTypingIndicator && chatId) {
|
|
@@ -207,7 +258,7 @@ export class Stack {
|
|
|
207
258
|
}
|
|
208
259
|
};
|
|
209
260
|
|
|
210
|
-
//
|
|
261
|
+
// Memory commands
|
|
211
262
|
const cmdResult = parseMemoryCommand(this.memory, channel, text);
|
|
212
263
|
if (cmdResult.handled) {
|
|
213
264
|
stopTyping();
|
|
@@ -217,7 +268,7 @@ export class Stack {
|
|
|
217
268
|
};
|
|
218
269
|
}
|
|
219
270
|
|
|
220
|
-
//
|
|
271
|
+
// Status command
|
|
221
272
|
if (text.trim().toLowerCase() === "/status") {
|
|
222
273
|
stopTyping();
|
|
223
274
|
return {
|
|
@@ -226,10 +277,19 @@ export class Stack {
|
|
|
226
277
|
};
|
|
227
278
|
}
|
|
228
279
|
|
|
229
|
-
//
|
|
280
|
+
// Ralph commands (DISABLED for now)
|
|
281
|
+
// if (text.startsWith("/ralph")) {
|
|
282
|
+
// stopTyping();
|
|
283
|
+
// return {
|
|
284
|
+
// content: { text: await this.handleRalphCommand(text) },
|
|
285
|
+
// replyTo: { messageId: message.messageId, channelId: message.channelId },
|
|
286
|
+
// };
|
|
287
|
+
// }
|
|
288
|
+
|
|
289
|
+
// Add to memory
|
|
230
290
|
this.memory.addMessage(channel, { role: "user", content: text });
|
|
231
291
|
|
|
232
|
-
// Build messages
|
|
292
|
+
// Build LLM messages
|
|
233
293
|
const llmMessages = this.memory.buildLLMMessages(
|
|
234
294
|
channel,
|
|
235
295
|
this.buildSystemPrompt(),
|
|
@@ -283,6 +343,7 @@ export class Stack {
|
|
|
283
343
|
## Info
|
|
284
344
|
- Node: ${this.config.node.name}
|
|
285
345
|
- Channels: ${channelList}
|
|
346
|
+
- Node Agent: ${this.state.nodeAgent.enabled ? "ready (Ralph/Git disabled)" : "off"}
|
|
286
347
|
- API: :${this.config.api?.port ?? 8911}`;
|
|
287
348
|
}
|
|
288
349
|
|
|
@@ -290,13 +351,14 @@ export class Stack {
|
|
|
290
351
|
const lines = [
|
|
291
352
|
`**${this.config.node.name} Status**`,
|
|
292
353
|
`Channels: SSH=${this.state.channels.ssh}, Telegram=${this.state.channels.telegram}`,
|
|
354
|
+
`Node Agent: ${this.state.nodeAgent.enabled ? "ready (Ralph/Git disabled)" : "off"}`,
|
|
293
355
|
`Uptime: ${Math.floor((Date.now() - this.state.started.getTime()) / 1000)}s`,
|
|
294
356
|
];
|
|
295
357
|
return lines.join("\n");
|
|
296
358
|
}
|
|
297
359
|
|
|
298
360
|
// ============================================================
|
|
299
|
-
// HTTP API
|
|
361
|
+
// HTTP API
|
|
300
362
|
// ============================================================
|
|
301
363
|
|
|
302
364
|
private startAPI(): void {
|
|
@@ -322,16 +384,15 @@ export class Stack {
|
|
|
322
384
|
return new Response(null, { headers: corsHeaders });
|
|
323
385
|
}
|
|
324
386
|
|
|
325
|
-
// GET /api/status
|
|
326
387
|
if (path === "/api/status" && req.method === "GET") {
|
|
327
388
|
return Response.json({
|
|
328
389
|
node: this.config.node.name,
|
|
329
390
|
channels: this.state.channels,
|
|
391
|
+
nodeAgent: this.state.nodeAgent,
|
|
330
392
|
uptime: Math.floor((Date.now() - this.state.started.getTime()) / 1000),
|
|
331
393
|
}, { headers: corsHeaders });
|
|
332
394
|
}
|
|
333
395
|
|
|
334
|
-
// GET /health
|
|
335
396
|
if (path === "/health") {
|
|
336
397
|
return Response.json({ status: "ok" }, { headers: corsHeaders });
|
|
337
398
|
}
|
|
@@ -352,6 +413,10 @@ export class Stack {
|
|
|
352
413
|
|
|
353
414
|
this.abortController = new AbortController();
|
|
354
415
|
|
|
416
|
+
// Initialize Node Agent (services ready but features disabled)
|
|
417
|
+
await this.initializeNodeAgent();
|
|
418
|
+
|
|
419
|
+
// Register channels
|
|
355
420
|
await this.registerSSH();
|
|
356
421
|
await this.registerTelegram();
|
|
357
422
|
|
|
@@ -370,6 +435,7 @@ export class Stack {
|
|
|
370
435
|
if (this.state.api.enabled) {
|
|
371
436
|
console.log(` - API: :${this.state.api.port}`);
|
|
372
437
|
}
|
|
438
|
+
console.log(" - Node Agent: ready (Ralph/Git disabled)");
|
|
373
439
|
console.log(" - Commands: /status, /memory <cmd>");
|
|
374
440
|
|
|
375
441
|
await new Promise(() => {});
|
|
@@ -415,6 +481,7 @@ async function main() {
|
|
|
415
481
|
name: process.env.NODE_NAME || "stack",
|
|
416
482
|
hostname: process.env.HOSTNAME || "localhost",
|
|
417
483
|
},
|
|
484
|
+
enableNodeAgent: process.env.ENABLE_NODE_AGENT !== "false",
|
|
418
485
|
};
|
|
419
486
|
|
|
420
487
|
const stack = new Stack(config);
|