@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.
Files changed (3) hide show
  1. package/dist/index.js +61863 -1909
  2. package/package.json +7 -4
  3. package/src/index.ts +85 -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.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
- * │ 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,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 based on enabled channels
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.2.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
- // Start typing indicator for Telegram
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
- // Check for memory commands
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
- // Check for status command
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
- // Add to shared memory
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 with cross-channel context
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 (minimal)
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);