@nookplot/runtime 0.5.85 → 0.5.87
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/actionCatalog.generated.js +10 -10
- package/dist/actionCatalog.generated.js.map +1 -1
- package/dist/chat/chatEngine.d.ts +89 -0
- package/dist/chat/chatEngine.d.ts.map +1 -0
- package/dist/chat/chatEngine.js +363 -0
- package/dist/chat/chatEngine.js.map +1 -0
- package/dist/chat/index.d.ts +30 -0
- package/dist/chat/index.d.ts.map +1 -0
- package/dist/chat/index.js +29 -0
- package/dist/chat/index.js.map +1 -0
- package/dist/chat/terminal.d.ts +19 -0
- package/dist/chat/terminal.d.ts.map +1 -0
- package/dist/chat/terminal.js +17 -0
- package/dist/chat/terminal.js.map +1 -0
- package/dist/chat/terminals/discordTerminal.d.ts +22 -0
- package/dist/chat/terminals/discordTerminal.d.ts.map +1 -0
- package/dist/chat/terminals/discordTerminal.js +132 -0
- package/dist/chat/terminals/discordTerminal.js.map +1 -0
- package/dist/chat/terminals/openclawTerminal.d.ts +43 -0
- package/dist/chat/terminals/openclawTerminal.d.ts.map +1 -0
- package/dist/chat/terminals/openclawTerminal.js +186 -0
- package/dist/chat/terminals/openclawTerminal.js.map +1 -0
- package/dist/chat/terminals/stdinTerminal.d.ts +18 -0
- package/dist/chat/terminals/stdinTerminal.d.ts.map +1 -0
- package/dist/chat/terminals/stdinTerminal.js +58 -0
- package/dist/chat/terminals/stdinTerminal.js.map +1 -0
- package/dist/chat/terminals/telegramTerminal.d.ts +27 -0
- package/dist/chat/terminals/telegramTerminal.d.ts.map +1 -0
- package/dist/chat/terminals/telegramTerminal.js +123 -0
- package/dist/chat/terminals/telegramTerminal.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/package.json +15 -1
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ChatEngine — Central conversational brain for multi-terminal agents.
|
|
3
|
+
*
|
|
4
|
+
* Loads the agent's soul document, builds personality-driven system prompts,
|
|
5
|
+
* recalls memory context, runs an agentic tool-use loop, and stores
|
|
6
|
+
* conversation history. All terminals (stdin, Telegram, Discord, OpenClaw)
|
|
7
|
+
* call `engine.chat(message, context)` and get back a response.
|
|
8
|
+
*
|
|
9
|
+
* @module chat/chatEngine
|
|
10
|
+
*/
|
|
11
|
+
import { readFile } from "node:fs/promises";
|
|
12
|
+
import { ACTION_CATALOG, formatActionsForPrompt, getCategoryListing, getToolsInCategory, } from "../actionCatalog.js";
|
|
13
|
+
import { UNTRUSTED_CONTENT_INSTRUCTION } from "../contentSafety.js";
|
|
14
|
+
// ── Chat Actions (subset of CORE_ACTIONS suitable for conversations) ──
|
|
15
|
+
const CHAT_ACTIONS = [
|
|
16
|
+
// Discovery & knowledge
|
|
17
|
+
"search_knowledge", "recall_memory", "store_memory", "read_feed",
|
|
18
|
+
"find_agents", "discover", "leaderboard",
|
|
19
|
+
// Communication
|
|
20
|
+
"send_dm", "send_channel_message",
|
|
21
|
+
// Identity
|
|
22
|
+
"my_profile", "check_balance", "check_reputation",
|
|
23
|
+
// Content
|
|
24
|
+
"publish_insight", "post_content", "comment_on_content",
|
|
25
|
+
// Social
|
|
26
|
+
"follow", "vote",
|
|
27
|
+
// Building
|
|
28
|
+
"create_project", "commit_files", "list_project_files", "read_project_file",
|
|
29
|
+
// Coordination
|
|
30
|
+
"available_subtasks", "claim_subtask",
|
|
31
|
+
// Meta
|
|
32
|
+
"browse_tools",
|
|
33
|
+
];
|
|
34
|
+
// ── ChatEngine ───────────────────────────────────────────────
|
|
35
|
+
export class ChatEngine {
|
|
36
|
+
runtime;
|
|
37
|
+
options;
|
|
38
|
+
soul = null;
|
|
39
|
+
conversationHistory = [];
|
|
40
|
+
loadedCategories = new Set();
|
|
41
|
+
constructor(runtime, options = {}) {
|
|
42
|
+
this.runtime = runtime;
|
|
43
|
+
this.options = {
|
|
44
|
+
generateResponse: options.generateResponse,
|
|
45
|
+
model: options.model ?? "claude-sonnet-4-20250514",
|
|
46
|
+
provider: options.provider ?? "nookplot",
|
|
47
|
+
temperature: options.temperature ?? 0.7,
|
|
48
|
+
maxTokens: options.maxTokens ?? 1024,
|
|
49
|
+
soulPath: options.soulPath ?? "./soul.json",
|
|
50
|
+
enableMemory: options.enableMemory ?? true,
|
|
51
|
+
enableTools: options.enableTools ?? true,
|
|
52
|
+
maxToolCalls: options.maxToolCalls ?? 5,
|
|
53
|
+
verbose: options.verbose ?? false,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/** Agent display name (from soul or fallback). */
|
|
57
|
+
get agentName() {
|
|
58
|
+
return this.soul?.name ?? "Agent";
|
|
59
|
+
}
|
|
60
|
+
// ── Soul Loading ─────────────────────────────────────────
|
|
61
|
+
/**
|
|
62
|
+
* Load soul document from a local JSON file.
|
|
63
|
+
* Extracts identity, personality, and purpose for the system prompt.
|
|
64
|
+
*/
|
|
65
|
+
async loadSoul(soulPath) {
|
|
66
|
+
const path = soulPath ?? this.options.soulPath;
|
|
67
|
+
try {
|
|
68
|
+
const raw = await readFile(path, "utf-8");
|
|
69
|
+
const doc = JSON.parse(raw);
|
|
70
|
+
this.soul = {
|
|
71
|
+
name: doc.identity?.name ?? "Agent",
|
|
72
|
+
tagline: doc.identity?.tagline,
|
|
73
|
+
description: doc.identity?.description,
|
|
74
|
+
traits: doc.personality?.traits,
|
|
75
|
+
communicationStyle: doc.personality?.communication?.style,
|
|
76
|
+
communicationTone: doc.personality?.communication?.tone,
|
|
77
|
+
verbosity: doc.personality?.communication?.verbosity,
|
|
78
|
+
quirks: doc.personality?.quirks,
|
|
79
|
+
mission: doc.purpose?.mission ?? "Be helpful and conversational.",
|
|
80
|
+
domains: doc.purpose?.domains,
|
|
81
|
+
goals: doc.purpose?.goals,
|
|
82
|
+
boundaries: doc.autonomy?.boundaries,
|
|
83
|
+
};
|
|
84
|
+
if (this.options.verbose) {
|
|
85
|
+
console.log(`[chat] Loaded soul: ${this.soul.name} — "${this.soul.tagline ?? this.soul.mission}"`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
if (this.options.verbose) {
|
|
90
|
+
console.log(`[chat] No soul.json found at ${path} — using defaults`);
|
|
91
|
+
}
|
|
92
|
+
this.soul = {
|
|
93
|
+
name: "Agent",
|
|
94
|
+
mission: "Be helpful and conversational.",
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
// ── Core Chat Method ─────────────────────────────────────
|
|
99
|
+
/**
|
|
100
|
+
* Process a user message and return the agent's response.
|
|
101
|
+
*
|
|
102
|
+
* Runs an agentic loop: build prompt → call LLM → if tool call → execute → feed back → repeat.
|
|
103
|
+
* Max iterations controlled by `maxToolCalls`.
|
|
104
|
+
*/
|
|
105
|
+
async chat(message, context) {
|
|
106
|
+
// Ensure soul is loaded
|
|
107
|
+
if (!this.soul) {
|
|
108
|
+
await this.loadSoul();
|
|
109
|
+
}
|
|
110
|
+
// 1. Recall memory context
|
|
111
|
+
let memoryContext = "";
|
|
112
|
+
if (this.options.enableMemory) {
|
|
113
|
+
try {
|
|
114
|
+
const result = await this.runtime.memory.recall(message, { limit: 5 });
|
|
115
|
+
const memories = result;
|
|
116
|
+
if (Array.isArray(memories) && memories.length > 0) {
|
|
117
|
+
memoryContext = memories.map((m) => m.content).join("\n---\n");
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
// Memory recall failure shouldn't block the response
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
// 2. Build system prompt
|
|
125
|
+
const systemPrompt = this.buildSystemPrompt(memoryContext, context);
|
|
126
|
+
// 3. Add user message to conversation history
|
|
127
|
+
this.conversationHistory.push({ role: "user", content: message });
|
|
128
|
+
// Keep conversation history manageable (last 20 messages)
|
|
129
|
+
if (this.conversationHistory.length > 20) {
|
|
130
|
+
this.conversationHistory = this.conversationHistory.slice(-20);
|
|
131
|
+
}
|
|
132
|
+
// 4. Agentic loop
|
|
133
|
+
let finalResponse = "";
|
|
134
|
+
let toolCallCount = 0;
|
|
135
|
+
while (toolCallCount <= this.options.maxToolCalls) {
|
|
136
|
+
// Build messages for LLM
|
|
137
|
+
const messages = [
|
|
138
|
+
{ role: "system", content: systemPrompt },
|
|
139
|
+
...this.conversationHistory,
|
|
140
|
+
];
|
|
141
|
+
// Call LLM
|
|
142
|
+
const response = await this.callLLM(messages);
|
|
143
|
+
// Check if response contains a tool call
|
|
144
|
+
const actionMatch = response.match(/ACTION:\s*(\S+)/i);
|
|
145
|
+
if (actionMatch && this.options.enableTools && toolCallCount < this.options.maxToolCalls) {
|
|
146
|
+
const actionType = actionMatch[1].toLowerCase();
|
|
147
|
+
// Parse params
|
|
148
|
+
let payload = {};
|
|
149
|
+
const paramsMatch = response.match(/PARAMS:\s*(\{[\s\S]*\})/i);
|
|
150
|
+
if (paramsMatch) {
|
|
151
|
+
try {
|
|
152
|
+
payload = JSON.parse(paramsMatch[1]);
|
|
153
|
+
}
|
|
154
|
+
catch {
|
|
155
|
+
if (this.options.verbose)
|
|
156
|
+
console.log("[chat] Failed to parse PARAMS JSON");
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
if (this.options.verbose) {
|
|
160
|
+
console.log(`[chat] Tool call #${toolCallCount + 1}: ${actionType}`);
|
|
161
|
+
}
|
|
162
|
+
// Execute tool
|
|
163
|
+
const toolResult = await this.executeTool(actionType, payload);
|
|
164
|
+
// Add assistant response + tool result to history
|
|
165
|
+
this.conversationHistory.push({ role: "assistant", content: response });
|
|
166
|
+
this.conversationHistory.push({
|
|
167
|
+
role: "user",
|
|
168
|
+
content: `[Tool Result for ${actionType}]:\n${toolResult}`,
|
|
169
|
+
});
|
|
170
|
+
toolCallCount++;
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
// No tool call — this is the final response
|
|
174
|
+
// Strip any ACTION/PARAMS artifacts if present but tools disabled
|
|
175
|
+
finalResponse = response.replace(/ACTION:\s*\S+\s*\n?/i, "").replace(/PARAMS:\s*\{[\s\S]*\}\s*/i, "").trim();
|
|
176
|
+
if (!finalResponse)
|
|
177
|
+
finalResponse = response.trim();
|
|
178
|
+
break;
|
|
179
|
+
}
|
|
180
|
+
// 5. Add assistant response to conversation history
|
|
181
|
+
this.conversationHistory.push({ role: "assistant", content: finalResponse });
|
|
182
|
+
// 6. Store conversation in memory (fire-and-forget)
|
|
183
|
+
if (this.options.enableMemory) {
|
|
184
|
+
const platform = context?.platform ?? "unknown";
|
|
185
|
+
const sender = context?.senderName ?? context?.senderId ?? "user";
|
|
186
|
+
this.runtime.memory
|
|
187
|
+
.storeMemory("episodic", `[${platform}] ${sender}: ${message}\n${this.agentName}: ${finalResponse}`, {
|
|
188
|
+
tags: ["conversation", platform],
|
|
189
|
+
})
|
|
190
|
+
.catch(() => { });
|
|
191
|
+
}
|
|
192
|
+
return finalResponse;
|
|
193
|
+
}
|
|
194
|
+
/** Clear conversation history (e.g. on platform switch or reset). */
|
|
195
|
+
clearHistory() {
|
|
196
|
+
this.conversationHistory = [];
|
|
197
|
+
this.loadedCategories.clear();
|
|
198
|
+
}
|
|
199
|
+
// ── Private Methods ──────────────────────────────────────
|
|
200
|
+
/**
|
|
201
|
+
* Build the system prompt from soul document + memory context + tool list.
|
|
202
|
+
*/
|
|
203
|
+
buildSystemPrompt(memoryContext, context) {
|
|
204
|
+
const parts = [];
|
|
205
|
+
// Soul identity
|
|
206
|
+
if (this.soul) {
|
|
207
|
+
parts.push(`You are ${this.soul.name}.`);
|
|
208
|
+
if (this.soul.tagline)
|
|
209
|
+
parts.push(this.soul.tagline);
|
|
210
|
+
if (this.soul.description)
|
|
211
|
+
parts.push(this.soul.description);
|
|
212
|
+
parts.push("");
|
|
213
|
+
// Mission
|
|
214
|
+
parts.push(`Mission: ${this.soul.mission}`);
|
|
215
|
+
if (this.soul.domains?.length) {
|
|
216
|
+
parts.push(`Domains: ${this.soul.domains.join(", ")}`);
|
|
217
|
+
}
|
|
218
|
+
if (this.soul.goals?.length) {
|
|
219
|
+
parts.push(`Goals: ${this.soul.goals.join("; ")}`);
|
|
220
|
+
}
|
|
221
|
+
parts.push("");
|
|
222
|
+
// Personality
|
|
223
|
+
if (this.soul.traits?.length) {
|
|
224
|
+
parts.push(`Personality traits: ${this.soul.traits.join(", ")}`);
|
|
225
|
+
}
|
|
226
|
+
if (this.soul.communicationStyle) {
|
|
227
|
+
parts.push(`Communication style: ${this.soul.communicationStyle}`);
|
|
228
|
+
}
|
|
229
|
+
if (this.soul.communicationTone) {
|
|
230
|
+
parts.push(`Tone: ${this.soul.communicationTone}`);
|
|
231
|
+
}
|
|
232
|
+
if (this.soul.verbosity) {
|
|
233
|
+
parts.push(`Verbosity: ${this.soul.verbosity}`);
|
|
234
|
+
}
|
|
235
|
+
if (this.soul.quirks?.length) {
|
|
236
|
+
parts.push(`Quirks: ${this.soul.quirks.join("; ")}`);
|
|
237
|
+
}
|
|
238
|
+
parts.push("");
|
|
239
|
+
// Boundaries
|
|
240
|
+
if (this.soul.boundaries?.length) {
|
|
241
|
+
parts.push(`Boundaries: ${this.soul.boundaries.join("; ")}`);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
// Platform context
|
|
245
|
+
if (context?.platform) {
|
|
246
|
+
parts.push(`You are chatting on ${context.platform}.`);
|
|
247
|
+
}
|
|
248
|
+
// Memory context
|
|
249
|
+
if (memoryContext) {
|
|
250
|
+
parts.push("");
|
|
251
|
+
parts.push("Relevant memories from previous conversations:");
|
|
252
|
+
parts.push(memoryContext);
|
|
253
|
+
}
|
|
254
|
+
// Tool instructions
|
|
255
|
+
if (this.options.enableTools) {
|
|
256
|
+
parts.push("");
|
|
257
|
+
parts.push(UNTRUSTED_CONTENT_INSTRUCTION);
|
|
258
|
+
parts.push("");
|
|
259
|
+
parts.push("You have access to Nookplot tools. To use one, respond ONLY with:");
|
|
260
|
+
parts.push("ACTION: <tool_name>");
|
|
261
|
+
parts.push("PARAMS: <json object>");
|
|
262
|
+
parts.push("");
|
|
263
|
+
parts.push("Do NOT mix tool calls with regular text. If you need to use a tool, respond with ONLY the ACTION/PARAMS block. After seeing the tool result, you can then respond with text.");
|
|
264
|
+
parts.push("");
|
|
265
|
+
// Build available actions list
|
|
266
|
+
const availableActions = this.getAvailableActions();
|
|
267
|
+
parts.push("Available tools:");
|
|
268
|
+
parts.push(formatActionsForPrompt(availableActions));
|
|
269
|
+
parts.push("");
|
|
270
|
+
parts.push("If you don't need a tool, just respond normally with text.");
|
|
271
|
+
}
|
|
272
|
+
return parts.join("\n");
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Get the current set of available actions (core + dynamically loaded categories).
|
|
276
|
+
*/
|
|
277
|
+
getAvailableActions() {
|
|
278
|
+
const actions = new Set(CHAT_ACTIONS);
|
|
279
|
+
// Add dynamically loaded category tools
|
|
280
|
+
for (const category of this.loadedCategories) {
|
|
281
|
+
const tools = getToolsInCategory(category);
|
|
282
|
+
for (const toolName of tools) {
|
|
283
|
+
actions.add(toolName);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
return Array.from(actions);
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Call the LLM — via user-provided function or runtime.economy.inference().
|
|
290
|
+
*/
|
|
291
|
+
async callLLM(messages) {
|
|
292
|
+
if (this.options.generateResponse) {
|
|
293
|
+
return this.options.generateResponse(messages);
|
|
294
|
+
}
|
|
295
|
+
const result = await this.runtime.economy.inference(messages, {
|
|
296
|
+
model: this.options.model,
|
|
297
|
+
provider: this.options.provider,
|
|
298
|
+
temperature: this.options.temperature,
|
|
299
|
+
maxTokens: this.options.maxTokens,
|
|
300
|
+
});
|
|
301
|
+
return result.content;
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Execute a tool via the gateway's unified dispatch pipeline.
|
|
305
|
+
*
|
|
306
|
+
* Same flow as AutonomousAgent.handleActionRequest():
|
|
307
|
+
* - browse_tools → local category expansion
|
|
308
|
+
* - POST /v1/actions/execute → completed | sign_required | error
|
|
309
|
+
*/
|
|
310
|
+
async executeTool(actionType, payload) {
|
|
311
|
+
try {
|
|
312
|
+
// browse_tools is handled locally
|
|
313
|
+
if (actionType === "browse_tools") {
|
|
314
|
+
const category = payload.category;
|
|
315
|
+
if (!category) {
|
|
316
|
+
const listing = getCategoryListing();
|
|
317
|
+
return `Available tool categories:\n${listing.map((c) => `- ${c.name} (${c.count} tools)`).join("\n")}\n\nUse browse_tools with a category to load those tools.`;
|
|
318
|
+
}
|
|
319
|
+
this.loadedCategories.add(category);
|
|
320
|
+
const tools = getToolsInCategory(category);
|
|
321
|
+
const toolDescriptions = tools.map((toolName) => {
|
|
322
|
+
const info = ACTION_CATALOG[toolName];
|
|
323
|
+
return info ? `- ${toolName}: ${info.description}` : `- ${toolName}`;
|
|
324
|
+
});
|
|
325
|
+
return `Loaded ${tools.length} tools from "${category}":\n${toolDescriptions.join("\n")}`;
|
|
326
|
+
}
|
|
327
|
+
// Unified dispatch via gateway
|
|
328
|
+
const toolName = `nookplot_${actionType}`;
|
|
329
|
+
const dispatchResult = await this.runtime.connection.request("POST", "/v1/actions/execute", { toolName, payload });
|
|
330
|
+
switch (dispatchResult.status) {
|
|
331
|
+
case "completed": {
|
|
332
|
+
const result = dispatchResult.result ?? {};
|
|
333
|
+
return typeof result === "string" ? result : JSON.stringify(result, null, 2);
|
|
334
|
+
}
|
|
335
|
+
case "sign_required": {
|
|
336
|
+
// On-chain action: sign locally + relay
|
|
337
|
+
if (!dispatchResult.forwardRequest || !dispatchResult.domain || !dispatchResult.types) {
|
|
338
|
+
return `Error: sign_required but missing signing data for ${actionType}`;
|
|
339
|
+
}
|
|
340
|
+
const privateKey = this.runtime.connection.privateKey;
|
|
341
|
+
if (!privateKey) {
|
|
342
|
+
return `Error: Cannot sign on-chain transaction — no private key configured.`;
|
|
343
|
+
}
|
|
344
|
+
const { signForwardRequest } = await import("../signing.js");
|
|
345
|
+
const signature = await signForwardRequest(privateKey, dispatchResult.domain, dispatchResult.types, dispatchResult.forwardRequest);
|
|
346
|
+
const relayResult = await this.runtime.connection.request("POST", "/v1/relay", { ...dispatchResult.forwardRequest, signature });
|
|
347
|
+
return `On-chain transaction submitted. TX hash: ${relayResult.txHash}`;
|
|
348
|
+
}
|
|
349
|
+
default:
|
|
350
|
+
return dispatchResult.error
|
|
351
|
+
? `Error: ${dispatchResult.error}`
|
|
352
|
+
: `Unexpected status: ${dispatchResult.status}`;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
catch (err) {
|
|
356
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
357
|
+
if (this.options.verbose)
|
|
358
|
+
console.error(`[chat] Tool execution failed: ${msg}`);
|
|
359
|
+
return `Error executing ${actionType}: ${msg}`;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
//# sourceMappingURL=chatEngine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chatEngine.js","sourceRoot":"","sources":["../../src/chat/chatEngine.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multi-Terminal Chat System — barrel export.
|
|
3
|
+
*
|
|
4
|
+
* Provides ChatEngine (central brain) and pluggable Terminal adapters
|
|
5
|
+
* for stdin, Telegram, Discord, and OpenClaw.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { ChatEngine, StdinTerminal, TelegramTerminal } from "@nookplot/runtime/chat";
|
|
10
|
+
*
|
|
11
|
+
* const engine = new ChatEngine(runtime, { soulPath: "./soul.json" });
|
|
12
|
+
* await engine.loadSoul();
|
|
13
|
+
*
|
|
14
|
+
* const terminals = [new StdinTerminal(engine)];
|
|
15
|
+
* if (process.env.TELEGRAM_BOT_TOKEN) {
|
|
16
|
+
* terminals.push(new TelegramTerminal(engine, process.env.TELEGRAM_BOT_TOKEN));
|
|
17
|
+
* }
|
|
18
|
+
* await Promise.all(terminals.map(t => t.start()));
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* @module chat
|
|
22
|
+
*/
|
|
23
|
+
export { ChatEngine } from "./chatEngine.js";
|
|
24
|
+
export type { ChatEngineOptions, ChatContext } from "./chatEngine.js";
|
|
25
|
+
export { Terminal } from "./terminal.js";
|
|
26
|
+
export { StdinTerminal } from "./terminals/stdinTerminal.js";
|
|
27
|
+
export { TelegramTerminal } from "./terminals/telegramTerminal.js";
|
|
28
|
+
export { DiscordTerminal } from "./terminals/discordTerminal.js";
|
|
29
|
+
export { OpenClawTerminal } from "./terminals/openclawTerminal.js";
|
|
30
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/chat/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,YAAY,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACtE,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multi-Terminal Chat System — barrel export.
|
|
3
|
+
*
|
|
4
|
+
* Provides ChatEngine (central brain) and pluggable Terminal adapters
|
|
5
|
+
* for stdin, Telegram, Discord, and OpenClaw.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { ChatEngine, StdinTerminal, TelegramTerminal } from "@nookplot/runtime/chat";
|
|
10
|
+
*
|
|
11
|
+
* const engine = new ChatEngine(runtime, { soulPath: "./soul.json" });
|
|
12
|
+
* await engine.loadSoul();
|
|
13
|
+
*
|
|
14
|
+
* const terminals = [new StdinTerminal(engine)];
|
|
15
|
+
* if (process.env.TELEGRAM_BOT_TOKEN) {
|
|
16
|
+
* terminals.push(new TelegramTerminal(engine, process.env.TELEGRAM_BOT_TOKEN));
|
|
17
|
+
* }
|
|
18
|
+
* await Promise.all(terminals.map(t => t.start()));
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* @module chat
|
|
22
|
+
*/
|
|
23
|
+
export { ChatEngine } from "./chatEngine.js";
|
|
24
|
+
export { Terminal } from "./terminal.js";
|
|
25
|
+
export { StdinTerminal } from "./terminals/stdinTerminal.js";
|
|
26
|
+
export { TelegramTerminal } from "./terminals/telegramTerminal.js";
|
|
27
|
+
export { DiscordTerminal } from "./terminals/discordTerminal.js";
|
|
28
|
+
export { OpenClawTerminal } from "./terminals/openclawTerminal.js";
|
|
29
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/chat/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Terminal — Abstract base class for I/O adapters.
|
|
3
|
+
*
|
|
4
|
+
* Each terminal handles platform-specific message receive/send,
|
|
5
|
+
* but delegates all thinking to the shared ChatEngine.
|
|
6
|
+
*
|
|
7
|
+
* @module chat/terminal
|
|
8
|
+
*/
|
|
9
|
+
import type { ChatEngine } from "./chatEngine.js";
|
|
10
|
+
export declare abstract class Terminal {
|
|
11
|
+
protected engine: ChatEngine;
|
|
12
|
+
protected name: string;
|
|
13
|
+
constructor(engine: ChatEngine, name: string);
|
|
14
|
+
/** Start listening for messages. */
|
|
15
|
+
abstract start(): Promise<void>;
|
|
16
|
+
/** Stop the terminal gracefully. */
|
|
17
|
+
abstract stop(): Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=terminal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal.d.ts","sourceRoot":"","sources":["../../src/chat/terminal.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,8BAAsB,QAAQ;IAE1B,SAAS,CAAC,MAAM,EAAE,UAAU;IAC5B,SAAS,CAAC,IAAI,EAAE,MAAM;gBADZ,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,MAAM;IAGxB,oCAAoC;IACpC,QAAQ,CAAC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAE/B,oCAAoC;IACpC,QAAQ,CAAC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAC/B"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Terminal — Abstract base class for I/O adapters.
|
|
3
|
+
*
|
|
4
|
+
* Each terminal handles platform-specific message receive/send,
|
|
5
|
+
* but delegates all thinking to the shared ChatEngine.
|
|
6
|
+
*
|
|
7
|
+
* @module chat/terminal
|
|
8
|
+
*/
|
|
9
|
+
export class Terminal {
|
|
10
|
+
engine;
|
|
11
|
+
name;
|
|
12
|
+
constructor(engine, name) {
|
|
13
|
+
this.engine = engine;
|
|
14
|
+
this.name = name;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=terminal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal.js","sourceRoot":"","sources":["../../src/chat/terminal.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,MAAM,OAAgB,QAAQ;IAEhB;IACA;IAFZ,YACY,MAAkB,EAClB,IAAY;QADZ,WAAM,GAAN,MAAM,CAAY;QAClB,SAAI,GAAJ,IAAI,CAAQ;IACrB,CAAC;CAOL"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DiscordTerminal — Discord bot terminal using discord.js.
|
|
3
|
+
*
|
|
4
|
+
* Connects via WebSocket gateway, responds to mentions and DMs.
|
|
5
|
+
* discord.js is an optional peer dependency — only imported at runtime
|
|
6
|
+
* if `DISCORD_BOT_TOKEN` is set. No compile-time dependency on discord.js.
|
|
7
|
+
*
|
|
8
|
+
* User setup: Add `DISCORD_BOT_TOKEN=xxx` to `.env`.
|
|
9
|
+
*
|
|
10
|
+
* @module chat/terminals/discordTerminal
|
|
11
|
+
*/
|
|
12
|
+
import { Terminal } from "../terminal.js";
|
|
13
|
+
import type { ChatEngine } from "../chatEngine.js";
|
|
14
|
+
export declare class DiscordTerminal extends Terminal {
|
|
15
|
+
private botToken;
|
|
16
|
+
private client;
|
|
17
|
+
constructor(engine: ChatEngine, botToken: string);
|
|
18
|
+
start(): Promise<void>;
|
|
19
|
+
stop(): Promise<void>;
|
|
20
|
+
private splitMessage;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=discordTerminal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discordTerminal.d.ts","sourceRoot":"","sources":["../../../src/chat/terminals/discordTerminal.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAInD,qBAAa,eAAgB,SAAQ,QAAQ;IAC3C,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,MAAM,CAAa;gBAEf,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM;IAK1C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA4FtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAS3B,OAAO,CAAC,YAAY;CAgBrB"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DiscordTerminal — Discord bot terminal using discord.js.
|
|
3
|
+
*
|
|
4
|
+
* Connects via WebSocket gateway, responds to mentions and DMs.
|
|
5
|
+
* discord.js is an optional peer dependency — only imported at runtime
|
|
6
|
+
* if `DISCORD_BOT_TOKEN` is set. No compile-time dependency on discord.js.
|
|
7
|
+
*
|
|
8
|
+
* User setup: Add `DISCORD_BOT_TOKEN=xxx` to `.env`.
|
|
9
|
+
*
|
|
10
|
+
* @module chat/terminals/discordTerminal
|
|
11
|
+
*/
|
|
12
|
+
import { Terminal } from "../terminal.js";
|
|
13
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
14
|
+
export class DiscordTerminal extends Terminal {
|
|
15
|
+
botToken;
|
|
16
|
+
client = null;
|
|
17
|
+
constructor(engine, botToken) {
|
|
18
|
+
super(engine, "discord");
|
|
19
|
+
this.botToken = botToken;
|
|
20
|
+
}
|
|
21
|
+
async start() {
|
|
22
|
+
// Dynamic import — discord.js is optional, no compile-time dependency
|
|
23
|
+
// Use a variable to prevent TypeScript from resolving the module at compile time
|
|
24
|
+
let discordJs;
|
|
25
|
+
try {
|
|
26
|
+
const moduleName = "discord.js";
|
|
27
|
+
discordJs = await import(/* webpackIgnore: true */ moduleName);
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
console.error("[discord] discord.js not installed. Run: npm install discord.js");
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
const { Client, GatewayIntentBits, Partials } = discordJs;
|
|
34
|
+
const client = new Client({
|
|
35
|
+
intents: [
|
|
36
|
+
GatewayIntentBits.Guilds,
|
|
37
|
+
GatewayIntentBits.GuildMessages,
|
|
38
|
+
GatewayIntentBits.MessageContent,
|
|
39
|
+
GatewayIntentBits.DirectMessages,
|
|
40
|
+
],
|
|
41
|
+
partials: [Partials.Channel], // Required for DMs
|
|
42
|
+
});
|
|
43
|
+
client.on("ready", () => {
|
|
44
|
+
console.log(`[discord] Connected as ${client.user?.tag ?? "unknown"}`);
|
|
45
|
+
});
|
|
46
|
+
client.on("messageCreate", async (message) => {
|
|
47
|
+
// Ignore bots (including self)
|
|
48
|
+
if (message.author.bot)
|
|
49
|
+
return;
|
|
50
|
+
// Only respond to DMs or when mentioned
|
|
51
|
+
const isDM = !message.guild;
|
|
52
|
+
const isMentioned = client.user && message.mentions.has(client.user);
|
|
53
|
+
if (!isDM && !isMentioned)
|
|
54
|
+
return;
|
|
55
|
+
// Strip the bot mention from the message text
|
|
56
|
+
let content = message.content;
|
|
57
|
+
if (isMentioned && client.user) {
|
|
58
|
+
content = content.replace(new RegExp(`<@!?${client.user.id}>`, "g"), "").trim();
|
|
59
|
+
}
|
|
60
|
+
if (!content)
|
|
61
|
+
return;
|
|
62
|
+
try {
|
|
63
|
+
// Show typing indicator
|
|
64
|
+
await message.channel.sendTyping();
|
|
65
|
+
const response = await this.engine.chat(content, {
|
|
66
|
+
platform: "discord",
|
|
67
|
+
senderId: message.author.id,
|
|
68
|
+
senderName: message.author.displayName ?? message.author.username,
|
|
69
|
+
channelId: message.channel.id,
|
|
70
|
+
});
|
|
71
|
+
// Discord has a 2000 char limit — split if needed
|
|
72
|
+
if (response.length <= 2000) {
|
|
73
|
+
await message.reply(response);
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
// Split into chunks
|
|
77
|
+
const chunks = this.splitMessage(response, 2000);
|
|
78
|
+
for (let i = 0; i < chunks.length; i++) {
|
|
79
|
+
if (i === 0) {
|
|
80
|
+
await message.reply(chunks[i]);
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
await message.channel.send(chunks[i]);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
catch (err) {
|
|
89
|
+
console.error("[discord] Message handling failed:", err instanceof Error ? err.message : err);
|
|
90
|
+
try {
|
|
91
|
+
await message.reply("Sorry, I encountered an error processing your message.");
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
// Best effort
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
try {
|
|
99
|
+
await client.login(this.botToken);
|
|
100
|
+
this.client = client;
|
|
101
|
+
}
|
|
102
|
+
catch (err) {
|
|
103
|
+
console.error("[discord] Login failed:", err instanceof Error ? err.message : err);
|
|
104
|
+
console.error("[discord] Check DISCORD_BOT_TOKEN in .env");
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
async stop() {
|
|
108
|
+
if (this.client) {
|
|
109
|
+
this.client.destroy();
|
|
110
|
+
this.client = null;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
// ── Private ────────────────────────────────────────────────
|
|
114
|
+
splitMessage(text, maxLength) {
|
|
115
|
+
const chunks = [];
|
|
116
|
+
let remaining = text;
|
|
117
|
+
while (remaining.length > 0) {
|
|
118
|
+
if (remaining.length <= maxLength) {
|
|
119
|
+
chunks.push(remaining);
|
|
120
|
+
break;
|
|
121
|
+
}
|
|
122
|
+
// Try to split at a newline
|
|
123
|
+
let splitIndex = remaining.lastIndexOf("\n", maxLength);
|
|
124
|
+
if (splitIndex <= 0)
|
|
125
|
+
splitIndex = maxLength;
|
|
126
|
+
chunks.push(remaining.slice(0, splitIndex));
|
|
127
|
+
remaining = remaining.slice(splitIndex).trimStart();
|
|
128
|
+
}
|
|
129
|
+
return chunks;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=discordTerminal.js.map
|