@ebowwa/stack 0.2.0 → 0.3.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.
Files changed (3) hide show
  1. package/dist/index.js +63317 -3272
  2. package/package.json +7 -4
  3. package/src/index.ts +84 -18
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ebowwa/stack",
3
- "version": "0.2.0",
4
- "description": "Cross-channel AI stack with shared memory (SSH + Telegram)",
3
+ "version": "0.3.0",
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
- * │ AI Brain (GLM)
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,15 @@ 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 imports (services available but disabled)
42
+ import {
43
+ RalphService,
44
+ GitService,
45
+ ConsoleLoggerService,
46
+ initializeStateService,
47
+ getState,
48
+ } from "@ebowwa/node-agent/lib";
49
+
36
50
  // ============================================================
37
51
  // Types
38
52
  // ============================================================
@@ -64,6 +78,8 @@ export interface StackConfig {
64
78
  name: string;
65
79
  hostname?: string;
66
80
  };
81
+ /** Enable Node Agent features (Ralph, Git, etc.) */
82
+ enableNodeAgent?: boolean;
67
83
  }
68
84
 
69
85
  export interface StackState {
@@ -76,6 +92,9 @@ export interface StackState {
76
92
  enabled: boolean;
77
93
  port?: number;
78
94
  };
95
+ nodeAgent: {
96
+ enabled: boolean;
97
+ };
79
98
  }
80
99
 
81
100
  // ============================================================
@@ -92,6 +111,11 @@ export class Stack {
92
111
  private channels: Map<string, ChannelConnector> = new Map();
93
112
  private abortController: AbortController | null = null;
94
113
 
114
+ // Node Agent services (initialized but may not be used)
115
+ private ralphService: RalphService | null = null;
116
+ private gitService: GitService | null = null;
117
+ private consoleLogger: ConsoleLoggerService | null = null;
118
+
95
119
  constructor(config: StackConfig) {
96
120
  this.config = {
97
121
  ...config,
@@ -104,9 +128,10 @@ export class Stack {
104
128
  started: new Date(),
105
129
  channels: { ssh: false, telegram: false },
106
130
  api: { enabled: !!this.config.api, port: this.config.api?.port },
131
+ nodeAgent: { enabled: false },
107
132
  };
108
133
 
109
- // Build memory channels dynamically based on enabled channels
134
+ // Build memory channels dynamically
110
135
  const memoryChannels: Record<string, { memoryFile: string; maxMessages: number }> = {};
111
136
  const permissions: Record<string, { canRead: string[] }> = {};
112
137
  const enabledChannels: string[] = [];
@@ -120,30 +145,31 @@ export class Stack {
120
145
  enabledChannels.push("telegram");
121
146
  }
122
147
 
123
- // Set up cross-channel permissions
124
148
  for (const channel of enabledChannels) {
125
149
  permissions[channel] = { canRead: enabledChannels.filter(c => c !== channel) };
126
150
  }
127
151
 
128
- // Initialize shared memory
129
152
  this.memory = createPermissionMemory({
130
153
  channels: memoryChannels,
131
154
  permissions,
132
155
  });
133
156
 
134
- // Initialize router
135
157
  this.router = createChannelRouter({
136
158
  announcement: {
137
159
  serverName: this.config.node.name,
138
160
  hostname: this.config.node.hostname,
139
161
  packageName: "@ebowwa/stack",
140
- version: "0.2.0",
162
+ version: "0.3.0",
141
163
  },
142
164
  });
143
165
 
144
- // Initialize AI
145
166
  this.client = new GLMClient();
146
167
  this.executor = new ToolExecutor(this.client, [...BUILTIN_TOOLS]);
168
+
169
+ // Initialize Node Agent services (but don't enable features yet)
170
+ this.ralphService = new RalphService();
171
+ this.gitService = new GitService();
172
+ this.consoleLogger = new ConsoleLoggerService();
147
173
  }
148
174
 
149
175
  // ============================================================
@@ -183,6 +209,30 @@ export class Stack {
183
209
  console.log("[Stack] Telegram registered");
184
210
  }
185
211
 
212
+ // ============================================================
213
+ // Node Agent Initialization
214
+ // ============================================================
215
+
216
+ private async initializeNodeAgent(): Promise<void> {
217
+ console.log("[Stack] Initializing Node Agent services...");
218
+
219
+ // Initialize state service
220
+ try {
221
+ await initializeStateService();
222
+ console.log("[Stack] State service initialized");
223
+ } catch (error) {
224
+ console.warn("[Stack] State service initialization failed (non-critical):", error);
225
+ }
226
+
227
+ // Ralph and Git services are instantiated but features are DISABLED
228
+ // TODO: Enable when ready
229
+ // this.ralphService?.startMonitoring();
230
+ // this.gitService?.initialize();
231
+
232
+ this.state.nodeAgent.enabled = true;
233
+ console.log("[Stack] Node Agent services ready (Ralph/Git DISABLED)");
234
+ }
235
+
186
236
  // ============================================================
187
237
  // Message Handler
188
238
  // ============================================================
@@ -194,7 +244,7 @@ export class Stack {
194
244
 
195
245
  console.log(`[${channel}] ${text.slice(0, 50)}...`);
196
246
 
197
- // Start typing indicator for Telegram
247
+ // Typing indicator for Telegram
198
248
  const telegramChannel = this.channels.get("telegram") as { startTypingIndicator?: (chatId: string) => void; stopTypingIndicator?: (chatId: string) => void } | undefined;
199
249
  const chatId = channelId.metadata?.chatId as string | undefined;
200
250
  if (channel === "telegram" && telegramChannel?.startTypingIndicator && chatId) {
@@ -207,7 +257,7 @@ export class Stack {
207
257
  }
208
258
  };
209
259
 
210
- // Check for memory commands
260
+ // Memory commands
211
261
  const cmdResult = parseMemoryCommand(this.memory, channel, text);
212
262
  if (cmdResult.handled) {
213
263
  stopTyping();
@@ -217,7 +267,7 @@ export class Stack {
217
267
  };
218
268
  }
219
269
 
220
- // Check for status command
270
+ // Status command
221
271
  if (text.trim().toLowerCase() === "/status") {
222
272
  stopTyping();
223
273
  return {
@@ -226,10 +276,19 @@ export class Stack {
226
276
  };
227
277
  }
228
278
 
229
- // Add to shared memory
279
+ // Ralph commands (DISABLED for now)
280
+ // if (text.startsWith("/ralph")) {
281
+ // stopTyping();
282
+ // return {
283
+ // content: { text: await this.handleRalphCommand(text) },
284
+ // replyTo: { messageId: message.messageId, channelId: message.channelId },
285
+ // };
286
+ // }
287
+
288
+ // Add to memory
230
289
  this.memory.addMessage(channel, { role: "user", content: text });
231
290
 
232
- // Build messages with cross-channel context
291
+ // Build LLM messages
233
292
  const llmMessages = this.memory.buildLLMMessages(
234
293
  channel,
235
294
  this.buildSystemPrompt(),
@@ -283,6 +342,7 @@ export class Stack {
283
342
  ## Info
284
343
  - Node: ${this.config.node.name}
285
344
  - Channels: ${channelList}
345
+ - Node Agent: ${this.state.nodeAgent.enabled ? "ready (Ralph/Git disabled)" : "off"}
286
346
  - API: :${this.config.api?.port ?? 8911}`;
287
347
  }
288
348
 
@@ -290,13 +350,14 @@ export class Stack {
290
350
  const lines = [
291
351
  `**${this.config.node.name} Status**`,
292
352
  `Channels: SSH=${this.state.channels.ssh}, Telegram=${this.state.channels.telegram}`,
353
+ `Node Agent: ${this.state.nodeAgent.enabled ? "ready (Ralph/Git disabled)" : "off"}`,
293
354
  `Uptime: ${Math.floor((Date.now() - this.state.started.getTime()) / 1000)}s`,
294
355
  ];
295
356
  return lines.join("\n");
296
357
  }
297
358
 
298
359
  // ============================================================
299
- // HTTP API (minimal)
360
+ // HTTP API
300
361
  // ============================================================
301
362
 
302
363
  private startAPI(): void {
@@ -322,16 +383,15 @@ export class Stack {
322
383
  return new Response(null, { headers: corsHeaders });
323
384
  }
324
385
 
325
- // GET /api/status
326
386
  if (path === "/api/status" && req.method === "GET") {
327
387
  return Response.json({
328
388
  node: this.config.node.name,
329
389
  channels: this.state.channels,
390
+ nodeAgent: this.state.nodeAgent,
330
391
  uptime: Math.floor((Date.now() - this.state.started.getTime()) / 1000),
331
392
  }, { headers: corsHeaders });
332
393
  }
333
394
 
334
- // GET /health
335
395
  if (path === "/health") {
336
396
  return Response.json({ status: "ok" }, { headers: corsHeaders });
337
397
  }
@@ -352,6 +412,10 @@ export class Stack {
352
412
 
353
413
  this.abortController = new AbortController();
354
414
 
415
+ // Initialize Node Agent (services ready but features disabled)
416
+ await this.initializeNodeAgent();
417
+
418
+ // Register channels
355
419
  await this.registerSSH();
356
420
  await this.registerTelegram();
357
421
 
@@ -370,6 +434,7 @@ export class Stack {
370
434
  if (this.state.api.enabled) {
371
435
  console.log(` - API: :${this.state.api.port}`);
372
436
  }
437
+ console.log(" - Node Agent: ready (Ralph/Git disabled)");
373
438
  console.log(" - Commands: /status, /memory <cmd>");
374
439
 
375
440
  await new Promise(() => {});
@@ -415,6 +480,7 @@ async function main() {
415
480
  name: process.env.NODE_NAME || "stack",
416
481
  hostname: process.env.HOSTNAME || "localhost",
417
482
  },
483
+ enableNodeAgent: process.env.ENABLE_NODE_AGENT !== "false",
418
484
  };
419
485
 
420
486
  const stack = new Stack(config);