@gendive/chatllm 0.1.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/dist/index.js ADDED
@@ -0,0 +1,2199 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ BaseProvider: () => BaseProvider,
24
+ ChatLLMError: () => ChatLLMError,
25
+ ConfigurationError: () => ConfigurationError,
26
+ DEFAULT_MODELS: () => DEFAULT_MODELS,
27
+ DEFAULT_OLLAMA_BASE_URL: () => DEFAULT_OLLAMA_BASE_URL,
28
+ DEFAULT_PERSONALIZATION: () => DEFAULT_PERSONALIZATION,
29
+ DEFAULT_STORAGE_PATH: () => DEFAULT_STORAGE_PATH,
30
+ FileStorage: () => FileStorage,
31
+ MemoryStorage: () => MemoryStorage,
32
+ OllamaProvider: () => OllamaProvider,
33
+ ProviderError: () => ProviderError,
34
+ ProviderRegistry: () => ProviderRegistry,
35
+ StorageError: () => StorageError,
36
+ StreamError: () => StreamError,
37
+ ToolExecutionError: () => ToolExecutionError,
38
+ ValidationError: () => ValidationError,
39
+ addSessionMessage: () => addMessage,
40
+ addSessionMessages: () => addMessages,
41
+ analyzeMessages: () => analyzeMessages,
42
+ applySkill: () => applySkill,
43
+ applySkillToSystemPrompt: () => applySkillToSystemPrompt,
44
+ buildSystemPromptWithMemory: () => buildSystemPromptWithMemory,
45
+ clearChatMemory: () => clearChatMemory,
46
+ clearGlobalMemory: () => clearGlobalMemory,
47
+ clearLearnedSkills: () => clearLearnedSkills,
48
+ clearMessages: () => clearMessages2,
49
+ clearObserverState: () => clearObserverState,
50
+ clearSessionMessages: () => clearMessages,
51
+ clearSkillApplicationHistory: () => clearSkillApplicationHistory,
52
+ cloneMessage: () => cloneMessage,
53
+ collectStreamContent: () => collectStreamContent,
54
+ createAssistantMessage: () => createAssistantMessage,
55
+ createChat: () => createChat,
56
+ createMessage: () => createMessage,
57
+ createSession: () => createSession,
58
+ createStreamEvent: () => createStreamEvent,
59
+ createSystemMessage: () => createSystemMessage,
60
+ createToolMessage: () => createToolMessage,
61
+ createUserMessage: () => createUserMessage,
62
+ deleteChatMemory: () => deleteChatMemory,
63
+ deleteGlobalMemory: () => deleteGlobalMemory,
64
+ deleteLearnedSkill: () => deleteLearnedSkill,
65
+ deserializeSession: () => deserializeSession,
66
+ destroyChat: () => destroyChat,
67
+ disableObserver: () => disableObserver,
68
+ enableObserver: () => enableObserver,
69
+ filterByProvider: () => filterByProvider,
70
+ filterByRole: () => filterByRole,
71
+ findRelevantSkills: () => findRelevantSkills,
72
+ formatMessagesForDisplay: () => formatMessagesForDisplay,
73
+ getBestSkill: () => getBestSkill,
74
+ getChatMemory: () => getChatMemory,
75
+ getChatMemoryContext: () => getChatMemoryContext,
76
+ getChatMemoryKeys: () => getChatMemoryKeys,
77
+ getDefaultModel: () => getDefaultModel,
78
+ getGlobalMemory: () => getGlobalMemory,
79
+ getGlobalMemoryContext: () => getGlobalMemoryContext,
80
+ getGlobalMemoryKeys: () => getGlobalMemoryKeys,
81
+ getGlobalMemoryStore: () => getGlobalMemoryStore,
82
+ getLastMessageByRole: () => getLastMessageByRole,
83
+ getLastMessages: () => getLastMessages,
84
+ getLearnedSkill: () => getLearnedSkill,
85
+ getLearnedSkills: () => getLearnedSkills,
86
+ getMemoryContext: () => getMemoryContext,
87
+ getMessages: () => getMessages,
88
+ getMessagesAfter: () => getMessagesAfter,
89
+ getMessagesForProvider: () => getMessagesForProvider,
90
+ getObservedPreferences: () => getObservedPreferences,
91
+ getObservedTasks: () => getObservedTasks,
92
+ getObserverConfig: () => getObserverConfig,
93
+ getObserverState: () => getObserverState,
94
+ getProviderBaseUrl: () => getProviderBaseUrl,
95
+ getSession: () => getSession,
96
+ getSessionSummary: () => getSessionSummary,
97
+ getSkillApplicationHistory: () => getSkillApplicationHistory,
98
+ getTools: () => getTools,
99
+ getTotalContentLength: () => getTotalContentLength,
100
+ hasChatMemory: () => hasChatMemory,
101
+ hasGlobalMemory: () => hasGlobalMemory,
102
+ initChatMemory: () => initChatMemory,
103
+ initGlobalMemory: () => initGlobalMemory,
104
+ initLearner: () => initLearner,
105
+ initMemory: () => initMemory,
106
+ isObserverEnabled: () => isObserverEnabled,
107
+ isProviderError: () => isProviderError,
108
+ isStorageError: () => isStorageError,
109
+ isToolExecutionError: () => isToolExecutionError,
110
+ learnFromConversation: () => learnFromConversation,
111
+ mergeConfig: () => mergeConfig,
112
+ onObserverEvent: () => onObserverEvent,
113
+ parseNDJSONStream: () => parseNDJSONStream,
114
+ parseSSEStream: () => parseSSEStream,
115
+ processMessages: () => processMessages,
116
+ recordSkillApplication: () => recordSkillApplication,
117
+ recordSkillUsage: () => recordSkillUsage,
118
+ registerTool: () => registerTool,
119
+ resetChat: () => resetChat,
120
+ searchLearnedSkills: () => searchLearnedSkills,
121
+ sendMessage: () => sendMessage,
122
+ sendMessageStream: () => sendMessageStream,
123
+ serializeSession: () => serializeSession,
124
+ setChatMemory: () => setChatMemory,
125
+ setGlobalMemory: () => setGlobalMemory,
126
+ setSessionMetadata: () => setSessionMetadata,
127
+ setSessionSystemPrompt: () => setSystemPrompt,
128
+ setSystemPrompt: () => setSystemPrompt2,
129
+ suggestSkills: () => suggestSkills,
130
+ syncChatMemory: () => syncChatMemory,
131
+ trackSkillApplication: () => trackSkillApplication,
132
+ truncateMessages: () => truncateMessages,
133
+ unregisterTool: () => unregisterTool,
134
+ updateSkillApplicationSuccess: () => updateSkillApplicationSuccess,
135
+ updateTaskStatus: () => updateTaskStatus,
136
+ validateProviderConfig: () => validateProviderConfig,
137
+ wrapProviderError: () => wrapProviderError
138
+ });
139
+ module.exports = __toCommonJS(index_exports);
140
+
141
+ // src/types.ts
142
+ var DEFAULT_PERSONALIZATION = {
143
+ responseStyle: {
144
+ warmth: "medium",
145
+ enthusiasm: "medium",
146
+ emojiUsage: "low",
147
+ formatting: "default",
148
+ verbosity: "balanced"
149
+ },
150
+ userProfile: {},
151
+ useMemory: true,
152
+ language: "auto"
153
+ };
154
+
155
+ // src/providers/base.ts
156
+ var BaseProvider = class {
157
+ constructor(config) {
158
+ this.config = config;
159
+ }
160
+ /**
161
+ * Generate a unique message ID
162
+ */
163
+ generateMessageId() {
164
+ return `msg_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
165
+ }
166
+ };
167
+ var ProviderRegistry = class {
168
+ providers = /* @__PURE__ */ new Map();
169
+ register(provider) {
170
+ this.providers.set(provider.name, provider);
171
+ }
172
+ get(name) {
173
+ return this.providers.get(name);
174
+ }
175
+ has(name) {
176
+ return this.providers.has(name);
177
+ }
178
+ getAll() {
179
+ return this.providers;
180
+ }
181
+ };
182
+
183
+ // src/config.ts
184
+ var import_path = require("path");
185
+ var import_os = require("os");
186
+ var DEFAULT_STORAGE_PATH = (0, import_path.join)((0, import_os.homedir)(), ".devdive-chat");
187
+ var DEFAULT_OLLAMA_BASE_URL = "http://localhost:11434";
188
+ var DEFAULT_MODELS = {
189
+ openai: "gpt-4",
190
+ anthropic: "claude-3-opus-20240229",
191
+ google: "gemini-pro",
192
+ naver: "HCX-003",
193
+ ollama: "llama2"
194
+ };
195
+ function validateProviderConfig(provider, config) {
196
+ const providerConfig = config.providers[provider];
197
+ if (!providerConfig) {
198
+ throw new Error(`Provider "${provider}" is not configured`);
199
+ }
200
+ switch (provider) {
201
+ case "openai":
202
+ if (!("apiKey" in providerConfig) || !providerConfig.apiKey) {
203
+ throw new Error("OpenAI provider requires apiKey");
204
+ }
205
+ break;
206
+ case "anthropic":
207
+ if (!("apiKey" in providerConfig) || !providerConfig.apiKey) {
208
+ throw new Error("Anthropic provider requires apiKey");
209
+ }
210
+ break;
211
+ case "google":
212
+ if (!("apiKey" in providerConfig) || !providerConfig.apiKey) {
213
+ throw new Error("Google provider requires apiKey");
214
+ }
215
+ break;
216
+ case "naver":
217
+ if (!("apiKey" in providerConfig) || !providerConfig.apiKey || !("apiGatewayKey" in providerConfig) || !providerConfig.apiGatewayKey) {
218
+ throw new Error("Naver provider requires apiKey and apiGatewayKey");
219
+ }
220
+ break;
221
+ case "ollama":
222
+ break;
223
+ }
224
+ }
225
+ function getProviderBaseUrl(provider, config) {
226
+ const providerConfig = config.providers[provider];
227
+ switch (provider) {
228
+ case "openai":
229
+ return providerConfig?.baseUrl ?? "https://api.openai.com/v1";
230
+ case "anthropic":
231
+ return providerConfig?.baseUrl ?? "https://api.anthropic.com";
232
+ case "google":
233
+ return "https://generativelanguage.googleapis.com";
234
+ case "naver":
235
+ return providerConfig?.baseUrl ?? "https://clovastudio.apigw.ntruss.com";
236
+ case "ollama":
237
+ return providerConfig?.baseUrl ?? DEFAULT_OLLAMA_BASE_URL;
238
+ }
239
+ }
240
+ function getDefaultModel(provider, config) {
241
+ return config.defaultModel ?? DEFAULT_MODELS[provider];
242
+ }
243
+ function mergeConfig(userConfig) {
244
+ return {
245
+ ...userConfig,
246
+ storagePath: userConfig.storagePath ?? DEFAULT_STORAGE_PATH
247
+ };
248
+ }
249
+
250
+ // src/utils/errors.ts
251
+ var ChatLLMError = class extends Error {
252
+ constructor(message) {
253
+ super(message);
254
+ this.name = "ChatLLMError";
255
+ }
256
+ };
257
+ var ProviderError = class extends ChatLLMError {
258
+ constructor(provider, message, statusCode, originalError) {
259
+ super(`[${provider}] ${message}`);
260
+ this.provider = provider;
261
+ this.statusCode = statusCode;
262
+ this.originalError = originalError;
263
+ this.name = "ProviderError";
264
+ }
265
+ };
266
+ var ConfigurationError = class extends ChatLLMError {
267
+ constructor(message) {
268
+ super(message);
269
+ this.name = "ConfigurationError";
270
+ }
271
+ };
272
+ var ToolExecutionError = class extends ChatLLMError {
273
+ constructor(toolName, message, originalError) {
274
+ super(`Tool "${toolName}" execution failed: ${message}`);
275
+ this.toolName = toolName;
276
+ this.originalError = originalError;
277
+ this.name = "ToolExecutionError";
278
+ }
279
+ };
280
+ var StorageError = class extends ChatLLMError {
281
+ constructor(operation, message, originalError) {
282
+ super(`Storage ${operation} failed: ${message}`);
283
+ this.operation = operation;
284
+ this.originalError = originalError;
285
+ this.name = "StorageError";
286
+ }
287
+ };
288
+ var StreamError = class extends ChatLLMError {
289
+ constructor(message, originalError) {
290
+ super(message);
291
+ this.originalError = originalError;
292
+ this.name = "StreamError";
293
+ }
294
+ };
295
+ var ValidationError = class extends ChatLLMError {
296
+ constructor(field, message) {
297
+ super(`Validation error for "${field}": ${message}`);
298
+ this.field = field;
299
+ this.name = "ValidationError";
300
+ }
301
+ };
302
+ function wrapProviderError(provider, error, statusCode) {
303
+ if (error instanceof ProviderError) {
304
+ return error;
305
+ }
306
+ const message = error instanceof Error ? error.message : String(error);
307
+ const originalError = error instanceof Error ? error : void 0;
308
+ return new ProviderError(provider, message, statusCode, originalError);
309
+ }
310
+ function isProviderError(error) {
311
+ return error instanceof ProviderError;
312
+ }
313
+ function isToolExecutionError(error) {
314
+ return error instanceof ToolExecutionError;
315
+ }
316
+ function isStorageError(error) {
317
+ return error instanceof StorageError;
318
+ }
319
+
320
+ // src/utils/stream.ts
321
+ async function* parseSSEStream(response) {
322
+ const reader = response.body?.getReader();
323
+ if (!reader) {
324
+ throw new StreamError("Response body is not readable");
325
+ }
326
+ const decoder = new TextDecoder();
327
+ let buffer = "";
328
+ try {
329
+ while (true) {
330
+ const { done, value } = await reader.read();
331
+ if (done) break;
332
+ buffer += decoder.decode(value, { stream: true });
333
+ const lines = buffer.split("\n");
334
+ buffer = lines.pop() || "";
335
+ for (const line of lines) {
336
+ const trimmed = line.trim();
337
+ if (trimmed.startsWith("data: ")) {
338
+ const data = trimmed.slice(6);
339
+ if (data !== "[DONE]") {
340
+ yield data;
341
+ }
342
+ }
343
+ }
344
+ }
345
+ if (buffer.trim()) {
346
+ const trimmed = buffer.trim();
347
+ if (trimmed.startsWith("data: ")) {
348
+ const data = trimmed.slice(6);
349
+ if (data !== "[DONE]") {
350
+ yield data;
351
+ }
352
+ }
353
+ }
354
+ } finally {
355
+ reader.releaseLock();
356
+ }
357
+ }
358
+ async function* parseNDJSONStream(response) {
359
+ const reader = response.body?.getReader();
360
+ if (!reader) {
361
+ throw new StreamError("Response body is not readable");
362
+ }
363
+ const decoder = new TextDecoder();
364
+ let buffer = "";
365
+ try {
366
+ while (true) {
367
+ const { done, value } = await reader.read();
368
+ if (done) break;
369
+ buffer += decoder.decode(value, { stream: true });
370
+ const lines = buffer.split("\n");
371
+ buffer = lines.pop() || "";
372
+ for (const line of lines) {
373
+ const trimmed = line.trim();
374
+ if (trimmed) {
375
+ try {
376
+ yield JSON.parse(trimmed);
377
+ } catch {
378
+ }
379
+ }
380
+ }
381
+ }
382
+ if (buffer.trim()) {
383
+ try {
384
+ yield JSON.parse(buffer.trim());
385
+ } catch {
386
+ }
387
+ }
388
+ } finally {
389
+ reader.releaseLock();
390
+ }
391
+ }
392
+ function createStreamEvent(type, data) {
393
+ return {
394
+ type,
395
+ ...data
396
+ };
397
+ }
398
+ async function collectStreamContent(stream) {
399
+ let content = "";
400
+ for await (const event of stream) {
401
+ if (event.type === "text" && event.content) {
402
+ content += event.content;
403
+ }
404
+ }
405
+ return content;
406
+ }
407
+
408
+ // src/providers/ollama.ts
409
+ var OllamaProvider = class extends BaseProvider {
410
+ name = "ollama";
411
+ baseUrl;
412
+ constructor(config) {
413
+ super(config);
414
+ this.baseUrl = getProviderBaseUrl("ollama", config);
415
+ }
416
+ /**
417
+ * Send a message and get a complete response
418
+ */
419
+ async sendMessage(messages, options) {
420
+ const formattedMessages = this.formatMessages(messages);
421
+ const tools = options.tools ? this.formatTools(options.tools) : void 0;
422
+ const body = this.buildRequestBody(formattedMessages, options, tools);
423
+ try {
424
+ const response = await fetch(this.getEndpoint(options.model || "llama2"), {
425
+ method: "POST",
426
+ headers: this.getHeaders(),
427
+ body: JSON.stringify(body)
428
+ });
429
+ if (!response.ok) {
430
+ const errorText = await response.text();
431
+ throw wrapProviderError("ollama", errorText, response.status);
432
+ }
433
+ const data = await response.json();
434
+ return this.parseResponse(data);
435
+ } catch (error) {
436
+ throw wrapProviderError("ollama", error);
437
+ }
438
+ }
439
+ /**
440
+ * Send a message and stream the response
441
+ */
442
+ async *sendMessageStream(messages, options) {
443
+ const formattedMessages = this.formatMessages(messages);
444
+ const tools = options.tools ? this.formatTools(options.tools) : void 0;
445
+ const body = this.buildRequestBody(formattedMessages, options, tools);
446
+ body.stream = true;
447
+ try {
448
+ const response = await fetch(this.getEndpoint(options.model || "llama2"), {
449
+ method: "POST",
450
+ headers: this.getHeaders(),
451
+ body: JSON.stringify(body)
452
+ });
453
+ if (!response.ok) {
454
+ const errorText = await response.text();
455
+ yield createStreamEvent("error", {
456
+ error: wrapProviderError("ollama", errorText, response.status)
457
+ });
458
+ return;
459
+ }
460
+ let fullContent = "";
461
+ const toolCalls = [];
462
+ for await (const chunk of parseNDJSONStream(response)) {
463
+ const data = chunk;
464
+ if (data.message?.content) {
465
+ fullContent += data.message.content;
466
+ yield createStreamEvent("text", { content: data.message.content });
467
+ }
468
+ if (data.message?.tool_calls) {
469
+ for (const tc of data.message.tool_calls) {
470
+ const toolCall = {
471
+ id: `call_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`,
472
+ name: tc.function.name,
473
+ arguments: tc.function.arguments
474
+ };
475
+ toolCalls.push(toolCall);
476
+ yield createStreamEvent("tool_call", { toolCall });
477
+ }
478
+ }
479
+ if (data.done) {
480
+ const message = {
481
+ id: this.generateMessageId(),
482
+ role: "assistant",
483
+ content: fullContent,
484
+ provider: "ollama",
485
+ model: data.model,
486
+ toolCalls: toolCalls.length > 0 ? toolCalls : void 0,
487
+ timestamp: Date.now()
488
+ };
489
+ yield createStreamEvent("done", { message });
490
+ return;
491
+ }
492
+ }
493
+ } catch (error) {
494
+ yield createStreamEvent("error", {
495
+ error: wrapProviderError("ollama", error)
496
+ });
497
+ }
498
+ }
499
+ /**
500
+ * Convert internal message format to Ollama format
501
+ */
502
+ formatMessages(messages) {
503
+ return messages.map((msg) => {
504
+ const formatted = {
505
+ role: msg.role,
506
+ content: msg.content
507
+ };
508
+ if (msg.toolCalls && msg.toolCalls.length > 0) {
509
+ formatted.tool_calls = msg.toolCalls.map((tc) => ({
510
+ function: {
511
+ name: tc.name,
512
+ arguments: tc.arguments
513
+ }
514
+ }));
515
+ }
516
+ return formatted;
517
+ });
518
+ }
519
+ /**
520
+ * Convert tool definitions to Ollama format
521
+ */
522
+ formatTools(tools) {
523
+ return tools.map((tool) => ({
524
+ type: "function",
525
+ function: {
526
+ name: tool.name,
527
+ description: tool.description,
528
+ parameters: {
529
+ type: "object",
530
+ properties: tool.parameters.properties,
531
+ required: tool.parameters.required
532
+ }
533
+ }
534
+ }));
535
+ }
536
+ /**
537
+ * Parse Ollama response into internal message format
538
+ */
539
+ parseResponse(response) {
540
+ const toolCalls = [];
541
+ if (response.message.tool_calls) {
542
+ for (const tc of response.message.tool_calls) {
543
+ toolCalls.push({
544
+ id: `call_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`,
545
+ name: tc.function.name,
546
+ arguments: tc.function.arguments
547
+ });
548
+ }
549
+ }
550
+ return {
551
+ id: this.generateMessageId(),
552
+ role: "assistant",
553
+ content: response.message.content,
554
+ provider: "ollama",
555
+ model: response.model,
556
+ toolCalls: toolCalls.length > 0 ? toolCalls : void 0,
557
+ timestamp: Date.now()
558
+ };
559
+ }
560
+ /**
561
+ * Get the Ollama API endpoint
562
+ */
563
+ getEndpoint(_model) {
564
+ return `${this.baseUrl}/api/chat`;
565
+ }
566
+ /**
567
+ * Get headers for Ollama API requests
568
+ */
569
+ getHeaders() {
570
+ return {
571
+ "Content-Type": "application/json"
572
+ };
573
+ }
574
+ /**
575
+ * Build request body for Ollama API
576
+ */
577
+ buildRequestBody(messages, options, tools) {
578
+ const body = {
579
+ model: options.model || "llama2",
580
+ messages,
581
+ stream: false
582
+ };
583
+ if (options.temperature !== void 0 || options.maxTokens !== void 0) {
584
+ body.options = {};
585
+ if (options.temperature !== void 0) {
586
+ body.options.temperature = options.temperature;
587
+ }
588
+ if (options.maxTokens !== void 0) {
589
+ body.options.num_predict = options.maxTokens;
590
+ }
591
+ }
592
+ if (tools && tools.length > 0) {
593
+ body.tools = tools;
594
+ }
595
+ return body;
596
+ }
597
+ /**
598
+ * List available models from Ollama
599
+ */
600
+ async listModels() {
601
+ try {
602
+ const response = await fetch(`${this.baseUrl}/api/tags`, {
603
+ method: "GET",
604
+ headers: this.getHeaders()
605
+ });
606
+ if (!response.ok) {
607
+ throw wrapProviderError("ollama", "Failed to list models", response.status);
608
+ }
609
+ const data = await response.json();
610
+ return data.models.map((m) => m.name);
611
+ } catch (error) {
612
+ throw wrapProviderError("ollama", error);
613
+ }
614
+ }
615
+ /**
616
+ * Check if Ollama server is available
617
+ */
618
+ async isAvailable() {
619
+ try {
620
+ const response = await fetch(`${this.baseUrl}/api/tags`, {
621
+ method: "GET",
622
+ headers: this.getHeaders()
623
+ });
624
+ return response.ok;
625
+ } catch {
626
+ return false;
627
+ }
628
+ }
629
+ };
630
+
631
+ // src/core/message.ts
632
+ function generateMessageId() {
633
+ return `msg_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
634
+ }
635
+ function createMessage(role, content, options) {
636
+ return {
637
+ id: generateMessageId(),
638
+ role,
639
+ content,
640
+ provider: options?.provider,
641
+ model: options?.model,
642
+ toolCalls: options?.toolCalls,
643
+ toolCallId: options?.toolCallId,
644
+ timestamp: Date.now(),
645
+ metadata: options?.metadata
646
+ };
647
+ }
648
+ function createUserMessage(content) {
649
+ return createMessage("user", content);
650
+ }
651
+ function createAssistantMessage(content, provider, model, toolCalls) {
652
+ return createMessage("assistant", content, { provider, model, toolCalls });
653
+ }
654
+ function createSystemMessage(content) {
655
+ return createMessage("system", content);
656
+ }
657
+ function createToolMessage(content, toolCallId) {
658
+ return createMessage("tool", content, { toolCallId });
659
+ }
660
+ function cloneMessage(message, overrides) {
661
+ return {
662
+ ...message,
663
+ ...overrides,
664
+ id: overrides?.id ?? generateMessageId(),
665
+ timestamp: overrides?.timestamp ?? Date.now()
666
+ };
667
+ }
668
+ function filterByRole(messages, role) {
669
+ return messages.filter((m) => m.role === role);
670
+ }
671
+ function filterByProvider(messages, provider) {
672
+ return messages.filter((m) => m.provider === provider);
673
+ }
674
+ function getLastMessageByRole(messages, role) {
675
+ for (let i = messages.length - 1; i >= 0; i--) {
676
+ if (messages[i].role === role) {
677
+ return messages[i];
678
+ }
679
+ }
680
+ return void 0;
681
+ }
682
+ function getTotalContentLength(messages) {
683
+ return messages.reduce((sum, msg) => sum + msg.content.length, 0);
684
+ }
685
+ function truncateMessages(messages, maxTokens, preserveSystem = true) {
686
+ const maxChars = maxTokens * 4;
687
+ const result = [];
688
+ let currentLength = 0;
689
+ if (preserveSystem) {
690
+ for (const msg of messages) {
691
+ if (msg.role === "system") {
692
+ result.push(msg);
693
+ currentLength += msg.content.length;
694
+ }
695
+ }
696
+ }
697
+ const nonSystemMessages = messages.filter((m) => m.role !== "system");
698
+ for (let i = nonSystemMessages.length - 1; i >= 0; i--) {
699
+ const msg = nonSystemMessages[i];
700
+ if (currentLength + msg.content.length <= maxChars) {
701
+ result.unshift(msg);
702
+ currentLength += msg.content.length;
703
+ } else {
704
+ break;
705
+ }
706
+ }
707
+ return result.sort((a, b) => {
708
+ if (a.role === "system" && b.role !== "system") return -1;
709
+ if (a.role !== "system" && b.role === "system") return 1;
710
+ return a.timestamp - b.timestamp;
711
+ });
712
+ }
713
+ function formatMessagesForDisplay(messages) {
714
+ return messages.map((msg) => {
715
+ const provider = msg.provider ? ` [${msg.provider}/${msg.model}]` : "";
716
+ const prefix = `[${msg.role.toUpperCase()}]${provider}`;
717
+ return `${prefix}: ${msg.content.substring(0, 100)}${msg.content.length > 100 ? "..." : ""}`;
718
+ }).join("\n");
719
+ }
720
+
721
+ // src/core/session.ts
722
+ function generateSessionId() {
723
+ return `session_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
724
+ }
725
+ function createSession(options) {
726
+ const now = Date.now();
727
+ return {
728
+ id: options?.id ?? generateSessionId(),
729
+ messages: [],
730
+ systemPrompt: options?.systemPrompt,
731
+ createdAt: now,
732
+ updatedAt: now,
733
+ metadata: options?.metadata ?? {}
734
+ };
735
+ }
736
+ function addMessage(session, message) {
737
+ return {
738
+ ...session,
739
+ messages: [...session.messages, message],
740
+ updatedAt: Date.now()
741
+ };
742
+ }
743
+ function addMessages(session, messages) {
744
+ return {
745
+ ...session,
746
+ messages: [...session.messages, ...messages],
747
+ updatedAt: Date.now()
748
+ };
749
+ }
750
+ function getMessagesForProvider(session, _provider) {
751
+ const messages = [];
752
+ if (session.systemPrompt) {
753
+ messages.push(createSystemMessage(session.systemPrompt));
754
+ }
755
+ messages.push(...session.messages);
756
+ return messages;
757
+ }
758
+ function setSystemPrompt(session, prompt) {
759
+ return {
760
+ ...session,
761
+ systemPrompt: prompt,
762
+ updatedAt: Date.now()
763
+ };
764
+ }
765
+ function clearMessages(session) {
766
+ return {
767
+ ...session,
768
+ messages: [],
769
+ updatedAt: Date.now()
770
+ };
771
+ }
772
+ function getLastMessages(session, count) {
773
+ return session.messages.slice(-count);
774
+ }
775
+ function getMessagesAfter(session, timestamp) {
776
+ return session.messages.filter((m) => m.timestamp > timestamp);
777
+ }
778
+ function getSessionSummary(session) {
779
+ const providers = /* @__PURE__ */ new Set();
780
+ let firstMessageAt = null;
781
+ let lastMessageAt = null;
782
+ for (const msg of session.messages) {
783
+ if (msg.provider) {
784
+ providers.add(msg.provider);
785
+ }
786
+ if (firstMessageAt === null || msg.timestamp < firstMessageAt) {
787
+ firstMessageAt = msg.timestamp;
788
+ }
789
+ if (lastMessageAt === null || msg.timestamp > lastMessageAt) {
790
+ lastMessageAt = msg.timestamp;
791
+ }
792
+ }
793
+ return {
794
+ id: session.id,
795
+ messageCount: session.messages.length,
796
+ providers: Array.from(providers),
797
+ firstMessageAt,
798
+ lastMessageAt
799
+ };
800
+ }
801
+ function setSessionMetadata(session, key, value) {
802
+ return {
803
+ ...session,
804
+ metadata: {
805
+ ...session.metadata,
806
+ [key]: value
807
+ },
808
+ updatedAt: Date.now()
809
+ };
810
+ }
811
+ function serializeSession(session) {
812
+ return {
813
+ id: session.id,
814
+ messages: session.messages,
815
+ systemPrompt: session.systemPrompt,
816
+ createdAt: session.createdAt,
817
+ updatedAt: session.updatedAt,
818
+ metadata: session.metadata
819
+ };
820
+ }
821
+ function deserializeSession(data) {
822
+ return {
823
+ id: data.id,
824
+ messages: data.messages,
825
+ systemPrompt: data.systemPrompt,
826
+ createdAt: data.createdAt,
827
+ updatedAt: data.updatedAt,
828
+ metadata: data.metadata ?? {}
829
+ };
830
+ }
831
+
832
+ // src/core/chat.ts
833
+ function generateChatId() {
834
+ return `chat_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
835
+ }
836
+ var chatStates = /* @__PURE__ */ new Map();
837
+ function createChat(config) {
838
+ const mergedConfig = mergeConfig(config);
839
+ const chatId = config.id ?? generateChatId();
840
+ const providerRegistry = new ProviderRegistry();
841
+ if (config.providers.ollama !== void 0 || config.defaultProvider === "ollama") {
842
+ providerRegistry.register(new OllamaProvider(mergedConfig));
843
+ }
844
+ if (!providerRegistry.has(config.defaultProvider)) {
845
+ if (config.defaultProvider === "ollama") {
846
+ providerRegistry.register(new OllamaProvider(mergedConfig));
847
+ } else {
848
+ throw new ConfigurationError(
849
+ `Default provider "${config.defaultProvider}" is not configured`
850
+ );
851
+ }
852
+ }
853
+ const now = Date.now();
854
+ const chat = {
855
+ id: chatId,
856
+ config: mergedConfig,
857
+ messages: [],
858
+ tools: /* @__PURE__ */ new Map(),
859
+ memory: /* @__PURE__ */ new Map(),
860
+ createdAt: now,
861
+ updatedAt: now
862
+ };
863
+ const session = createSession({
864
+ systemPrompt: config.systemPrompt
865
+ });
866
+ chatStates.set(chatId, {
867
+ chat,
868
+ session,
869
+ providerRegistry
870
+ });
871
+ return chat;
872
+ }
873
+ function getChatState(chat) {
874
+ const state = chatStates.get(chat.id);
875
+ if (!state) {
876
+ throw new ConfigurationError(`Chat "${chat.id}" not found`);
877
+ }
878
+ return state;
879
+ }
880
+ function getProvider(chat, providerType) {
881
+ const state = getChatState(chat);
882
+ const type = providerType ?? chat.config.defaultProvider;
883
+ const provider = state.providerRegistry.get(type);
884
+ if (!provider) {
885
+ throw new ConfigurationError(`Provider "${type}" is not available`);
886
+ }
887
+ return provider;
888
+ }
889
+ async function sendMessage(chat, content, options) {
890
+ const state = getChatState(chat);
891
+ const provider = getProvider(chat, options?.provider);
892
+ const model = options?.model ?? getDefaultModel(provider.name, chat.config);
893
+ const userMessage = createUserMessage(content);
894
+ state.session = addMessage(state.session, userMessage);
895
+ chat.messages.push(userMessage);
896
+ const messages = getMessagesForProvider(state.session, provider.name);
897
+ const tools = options?.tools ?? Array.from(chat.tools.values());
898
+ const sendOptions = {
899
+ ...options,
900
+ model,
901
+ tools: tools.length > 0 ? tools : void 0
902
+ };
903
+ const response = await provider.sendMessage(messages, sendOptions);
904
+ state.session = addMessage(state.session, response);
905
+ chat.messages.push(response);
906
+ chat.updatedAt = Date.now();
907
+ if (response.toolCalls && response.toolCalls.length > 0) {
908
+ return await handleToolCalls(chat, response, sendOptions);
909
+ }
910
+ return response;
911
+ }
912
+ async function* sendMessageStream(chat, content, options) {
913
+ const state = getChatState(chat);
914
+ const provider = getProvider(chat, options?.provider);
915
+ const model = options?.model ?? getDefaultModel(provider.name, chat.config);
916
+ const userMessage = createUserMessage(content);
917
+ state.session = addMessage(state.session, userMessage);
918
+ chat.messages.push(userMessage);
919
+ const messages = getMessagesForProvider(state.session, provider.name);
920
+ const tools = options?.tools ?? Array.from(chat.tools.values());
921
+ const sendOptions = {
922
+ ...options,
923
+ model,
924
+ tools: tools.length > 0 ? tools : void 0
925
+ };
926
+ for await (const event of provider.sendMessageStream(messages, sendOptions)) {
927
+ yield event;
928
+ if (event.type === "done" && event.message) {
929
+ state.session = addMessage(state.session, event.message);
930
+ chat.messages.push(event.message);
931
+ chat.updatedAt = Date.now();
932
+ }
933
+ }
934
+ }
935
+ async function handleToolCalls(chat, response, options) {
936
+ const state = getChatState(chat);
937
+ const provider = getProvider(chat, options.provider);
938
+ if (!response.toolCalls) {
939
+ return response;
940
+ }
941
+ for (const toolCall of response.toolCalls) {
942
+ const tool = chat.tools.get(toolCall.name);
943
+ if (!tool) {
944
+ const errorMessage = createAssistantMessage(
945
+ `Tool "${toolCall.name}" not found`,
946
+ provider.name,
947
+ options.model
948
+ );
949
+ state.session = addMessage(state.session, errorMessage);
950
+ continue;
951
+ }
952
+ try {
953
+ const result = await tool.handler(toolCall.arguments);
954
+ const toolResultMessage = {
955
+ id: `msg_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`,
956
+ role: "tool",
957
+ content: JSON.stringify(result),
958
+ toolCallId: toolCall.id,
959
+ timestamp: Date.now()
960
+ };
961
+ state.session = addMessage(state.session, toolResultMessage);
962
+ chat.messages.push(toolResultMessage);
963
+ } catch (error) {
964
+ const errorContent = error instanceof Error ? error.message : String(error);
965
+ const toolErrorMessage = {
966
+ id: `msg_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`,
967
+ role: "tool",
968
+ content: JSON.stringify({ error: errorContent }),
969
+ toolCallId: toolCall.id,
970
+ timestamp: Date.now()
971
+ };
972
+ state.session = addMessage(state.session, toolErrorMessage);
973
+ chat.messages.push(toolErrorMessage);
974
+ }
975
+ }
976
+ const messages = getMessagesForProvider(state.session, provider.name);
977
+ const finalResponse = await provider.sendMessage(messages, options);
978
+ state.session = addMessage(state.session, finalResponse);
979
+ chat.messages.push(finalResponse);
980
+ chat.updatedAt = Date.now();
981
+ if (finalResponse.toolCalls && finalResponse.toolCalls.length > 0) {
982
+ return handleToolCalls(chat, finalResponse, options);
983
+ }
984
+ return finalResponse;
985
+ }
986
+ function registerTool(chat, tool) {
987
+ chat.tools.set(tool.name, tool);
988
+ chat.updatedAt = Date.now();
989
+ }
990
+ function unregisterTool(chat, toolName) {
991
+ const deleted = chat.tools.delete(toolName);
992
+ if (deleted) {
993
+ chat.updatedAt = Date.now();
994
+ }
995
+ return deleted;
996
+ }
997
+ function getTools(chat) {
998
+ return Array.from(chat.tools.values());
999
+ }
1000
+ function setSystemPrompt2(chat, prompt) {
1001
+ const state = getChatState(chat);
1002
+ state.session.systemPrompt = prompt;
1003
+ chat.config.systemPrompt = prompt;
1004
+ chat.updatedAt = Date.now();
1005
+ }
1006
+ function getMessages(chat) {
1007
+ return [...chat.messages];
1008
+ }
1009
+ function clearMessages2(chat) {
1010
+ const state = getChatState(chat);
1011
+ chat.messages = [];
1012
+ state.session.messages = [];
1013
+ chat.updatedAt = Date.now();
1014
+ }
1015
+ function resetChat(chat) {
1016
+ const state = getChatState(chat);
1017
+ chat.messages = [];
1018
+ state.session.messages = [];
1019
+ chat.tools.clear();
1020
+ chat.memory.clear();
1021
+ const now = Date.now();
1022
+ chat.updatedAt = now;
1023
+ state.session.updatedAt = now;
1024
+ }
1025
+ function getSession(chat) {
1026
+ const state = getChatState(chat);
1027
+ return state.session;
1028
+ }
1029
+ function destroyChat(chat) {
1030
+ chatStates.delete(chat.id);
1031
+ }
1032
+
1033
+ // src/memory/storage.ts
1034
+ var import_fs = require("fs");
1035
+ var import_path2 = require("path");
1036
+ var FileStorage = class {
1037
+ basePath;
1038
+ constructor(basePath) {
1039
+ this.basePath = basePath;
1040
+ this.ensureDirectory(basePath);
1041
+ }
1042
+ /**
1043
+ * Ensure a directory exists
1044
+ */
1045
+ ensureDirectory(path) {
1046
+ if (!(0, import_fs.existsSync)(path)) {
1047
+ try {
1048
+ (0, import_fs.mkdirSync)(path, { recursive: true });
1049
+ } catch (error) {
1050
+ throw new StorageError(
1051
+ "write",
1052
+ `Failed to create directory: ${path}`,
1053
+ error instanceof Error ? error : void 0
1054
+ );
1055
+ }
1056
+ }
1057
+ }
1058
+ /**
1059
+ * Get the full path for a key
1060
+ */
1061
+ getFilePath(key) {
1062
+ const sanitizedKey = key.replace(/[^a-zA-Z0-9_-]/g, "_");
1063
+ return (0, import_path2.join)(this.basePath, `${sanitizedKey}.json`);
1064
+ }
1065
+ /**
1066
+ * Read data from storage
1067
+ */
1068
+ read(key) {
1069
+ const filePath = this.getFilePath(key);
1070
+ if (!(0, import_fs.existsSync)(filePath)) {
1071
+ return null;
1072
+ }
1073
+ try {
1074
+ const content = (0, import_fs.readFileSync)(filePath, "utf-8");
1075
+ return JSON.parse(content);
1076
+ } catch (error) {
1077
+ throw new StorageError(
1078
+ "read",
1079
+ `Failed to read key: ${key}`,
1080
+ error instanceof Error ? error : void 0
1081
+ );
1082
+ }
1083
+ }
1084
+ /**
1085
+ * Write data to storage
1086
+ */
1087
+ write(key, data) {
1088
+ const filePath = this.getFilePath(key);
1089
+ try {
1090
+ this.ensureDirectory((0, import_path2.dirname)(filePath));
1091
+ (0, import_fs.writeFileSync)(filePath, JSON.stringify(data, null, 2), "utf-8");
1092
+ } catch (error) {
1093
+ throw new StorageError(
1094
+ "write",
1095
+ `Failed to write key: ${key}`,
1096
+ error instanceof Error ? error : void 0
1097
+ );
1098
+ }
1099
+ }
1100
+ /**
1101
+ * Delete data from storage
1102
+ */
1103
+ delete(key) {
1104
+ const filePath = this.getFilePath(key);
1105
+ if (!(0, import_fs.existsSync)(filePath)) {
1106
+ return false;
1107
+ }
1108
+ try {
1109
+ (0, import_fs.unlinkSync)(filePath);
1110
+ return true;
1111
+ } catch (error) {
1112
+ throw new StorageError(
1113
+ "delete",
1114
+ `Failed to delete key: ${key}`,
1115
+ error instanceof Error ? error : void 0
1116
+ );
1117
+ }
1118
+ }
1119
+ /**
1120
+ * Check if a key exists
1121
+ */
1122
+ exists(key) {
1123
+ return (0, import_fs.existsSync)(this.getFilePath(key));
1124
+ }
1125
+ /**
1126
+ * Get the base path
1127
+ */
1128
+ getBasePath() {
1129
+ return this.basePath;
1130
+ }
1131
+ };
1132
+ var MemoryStorage = class {
1133
+ data = /* @__PURE__ */ new Map();
1134
+ read(key) {
1135
+ const value = this.data.get(key);
1136
+ return value !== void 0 ? value : null;
1137
+ }
1138
+ write(key, data) {
1139
+ this.data.set(key, data);
1140
+ }
1141
+ delete(key) {
1142
+ return this.data.delete(key);
1143
+ }
1144
+ exists(key) {
1145
+ return this.data.has(key);
1146
+ }
1147
+ clear() {
1148
+ this.data.clear();
1149
+ }
1150
+ getAll() {
1151
+ return new Map(this.data);
1152
+ }
1153
+ };
1154
+
1155
+ // src/memory/global.ts
1156
+ var import_path3 = require("path");
1157
+ var GlobalMemoryStore = class {
1158
+ entries = /* @__PURE__ */ new Map();
1159
+ storage;
1160
+ storageKey = "global_memory";
1161
+ autoSave;
1162
+ constructor(storagePath, autoSave = true) {
1163
+ this.autoSave = autoSave;
1164
+ if (storagePath) {
1165
+ this.storage = new FileStorage((0, import_path3.join)(storagePath, "memory"));
1166
+ this.load();
1167
+ } else {
1168
+ this.storage = new MemoryStorage();
1169
+ }
1170
+ }
1171
+ /**
1172
+ * Load entries from storage
1173
+ */
1174
+ load() {
1175
+ const data = this.storage.read(this.storageKey);
1176
+ if (data) {
1177
+ this.entries = new Map(Object.entries(data));
1178
+ }
1179
+ }
1180
+ /**
1181
+ * Save entries to storage
1182
+ */
1183
+ save() {
1184
+ if (!this.autoSave) return;
1185
+ const data = {};
1186
+ for (const [key, value] of this.entries) {
1187
+ data[key] = value;
1188
+ }
1189
+ this.storage.write(this.storageKey, data);
1190
+ }
1191
+ /**
1192
+ * Set a memory entry
1193
+ */
1194
+ set(key, value) {
1195
+ const now = Date.now();
1196
+ const existing = this.entries.get(key);
1197
+ this.entries.set(key, {
1198
+ key,
1199
+ value,
1200
+ createdAt: existing?.createdAt ?? now,
1201
+ updatedAt: now
1202
+ });
1203
+ this.save();
1204
+ }
1205
+ /**
1206
+ * Get a memory entry value
1207
+ */
1208
+ get(key) {
1209
+ const entry = this.entries.get(key);
1210
+ return entry?.value;
1211
+ }
1212
+ /**
1213
+ * Get a memory entry with metadata
1214
+ */
1215
+ getEntry(key) {
1216
+ return this.entries.get(key);
1217
+ }
1218
+ /**
1219
+ * Check if a key exists
1220
+ */
1221
+ has(key) {
1222
+ return this.entries.has(key);
1223
+ }
1224
+ /**
1225
+ * Delete a memory entry
1226
+ */
1227
+ delete(key) {
1228
+ const deleted = this.entries.delete(key);
1229
+ if (deleted) {
1230
+ this.save();
1231
+ }
1232
+ return deleted;
1233
+ }
1234
+ /**
1235
+ * Get all memory entries
1236
+ */
1237
+ getAll() {
1238
+ return new Map(this.entries);
1239
+ }
1240
+ /**
1241
+ * Get all keys
1242
+ */
1243
+ keys() {
1244
+ return Array.from(this.entries.keys());
1245
+ }
1246
+ /**
1247
+ * Clear all entries
1248
+ */
1249
+ clear() {
1250
+ this.entries.clear();
1251
+ this.save();
1252
+ }
1253
+ /**
1254
+ * Get entries count
1255
+ */
1256
+ size() {
1257
+ return this.entries.size;
1258
+ }
1259
+ /**
1260
+ * Force save to storage
1261
+ */
1262
+ forceSave() {
1263
+ const originalAutoSave = this.autoSave;
1264
+ this.autoSave = true;
1265
+ this.save();
1266
+ this.autoSave = originalAutoSave;
1267
+ }
1268
+ /**
1269
+ * Convert entries to a format suitable for system prompt injection
1270
+ */
1271
+ toPromptContext() {
1272
+ if (this.entries.size === 0) {
1273
+ return "";
1274
+ }
1275
+ const lines = ["[Global Memory]"];
1276
+ for (const [key, entry] of this.entries) {
1277
+ const valueStr = typeof entry.value === "object" ? JSON.stringify(entry.value) : String(entry.value);
1278
+ lines.push(`- ${key}: ${valueStr}`);
1279
+ }
1280
+ return lines.join("\n");
1281
+ }
1282
+ };
1283
+ var globalMemoryInstance = null;
1284
+ function initGlobalMemory(storagePath, autoSave = true) {
1285
+ globalMemoryInstance = new GlobalMemoryStore(storagePath ?? DEFAULT_STORAGE_PATH, autoSave);
1286
+ }
1287
+ function getGlobalMemoryStore() {
1288
+ if (!globalMemoryInstance) {
1289
+ globalMemoryInstance = new GlobalMemoryStore();
1290
+ }
1291
+ return globalMemoryInstance;
1292
+ }
1293
+ function setGlobalMemory(key, value) {
1294
+ getGlobalMemoryStore().set(key, value);
1295
+ }
1296
+ function getGlobalMemory(key) {
1297
+ return getGlobalMemoryStore().get(key);
1298
+ }
1299
+ function deleteGlobalMemory(key) {
1300
+ return getGlobalMemoryStore().delete(key);
1301
+ }
1302
+ function hasGlobalMemory(key) {
1303
+ return getGlobalMemoryStore().has(key);
1304
+ }
1305
+ function getGlobalMemoryKeys() {
1306
+ return getGlobalMemoryStore().keys();
1307
+ }
1308
+ function clearGlobalMemory() {
1309
+ getGlobalMemoryStore().clear();
1310
+ }
1311
+ function getGlobalMemoryContext() {
1312
+ return getGlobalMemoryStore().toPromptContext();
1313
+ }
1314
+
1315
+ // src/memory/chat.ts
1316
+ var import_path4 = require("path");
1317
+ var ChatMemoryStore = class {
1318
+ storage;
1319
+ autoSave;
1320
+ constructor(storagePath, autoSave = true) {
1321
+ this.autoSave = autoSave;
1322
+ if (storagePath) {
1323
+ this.storage = new FileStorage((0, import_path4.join)(storagePath, "chat_memory"));
1324
+ } else {
1325
+ this.storage = new MemoryStorage();
1326
+ }
1327
+ }
1328
+ /**
1329
+ * Get storage key for a chat
1330
+ */
1331
+ getChatKey(chatId) {
1332
+ return `chat_${chatId}`;
1333
+ }
1334
+ /**
1335
+ * Load chat memory from storage
1336
+ */
1337
+ loadChatMemory(chatId) {
1338
+ const data = this.storage.read(this.getChatKey(chatId));
1339
+ if (data) {
1340
+ return new Map(Object.entries(data));
1341
+ }
1342
+ return /* @__PURE__ */ new Map();
1343
+ }
1344
+ /**
1345
+ * Save chat memory to storage
1346
+ */
1347
+ saveChatMemory(chatId, entries) {
1348
+ if (!this.autoSave) return;
1349
+ const data = {};
1350
+ for (const [key, value] of entries) {
1351
+ data[key] = value;
1352
+ }
1353
+ this.storage.write(this.getChatKey(chatId), data);
1354
+ }
1355
+ /**
1356
+ * Set a memory entry for a chat
1357
+ */
1358
+ set(chatId, key, value) {
1359
+ const entries = this.loadChatMemory(chatId);
1360
+ const now = Date.now();
1361
+ const existing = entries.get(key);
1362
+ entries.set(key, {
1363
+ key,
1364
+ value,
1365
+ createdAt: existing?.createdAt ?? now,
1366
+ updatedAt: now
1367
+ });
1368
+ this.saveChatMemory(chatId, entries);
1369
+ }
1370
+ /**
1371
+ * Get a memory entry value for a chat
1372
+ */
1373
+ get(chatId, key) {
1374
+ const entries = this.loadChatMemory(chatId);
1375
+ const entry = entries.get(key);
1376
+ return entry?.value;
1377
+ }
1378
+ /**
1379
+ * Get a memory entry with metadata
1380
+ */
1381
+ getEntry(chatId, key) {
1382
+ const entries = this.loadChatMemory(chatId);
1383
+ return entries.get(key);
1384
+ }
1385
+ /**
1386
+ * Check if a key exists for a chat
1387
+ */
1388
+ has(chatId, key) {
1389
+ const entries = this.loadChatMemory(chatId);
1390
+ return entries.has(key);
1391
+ }
1392
+ /**
1393
+ * Delete a memory entry for a chat
1394
+ */
1395
+ delete(chatId, key) {
1396
+ const entries = this.loadChatMemory(chatId);
1397
+ const deleted = entries.delete(key);
1398
+ if (deleted) {
1399
+ this.saveChatMemory(chatId, entries);
1400
+ }
1401
+ return deleted;
1402
+ }
1403
+ /**
1404
+ * Get all memory entries for a chat
1405
+ */
1406
+ getAll(chatId) {
1407
+ return this.loadChatMemory(chatId);
1408
+ }
1409
+ /**
1410
+ * Get all keys for a chat
1411
+ */
1412
+ keys(chatId) {
1413
+ const entries = this.loadChatMemory(chatId);
1414
+ return Array.from(entries.keys());
1415
+ }
1416
+ /**
1417
+ * Clear all entries for a chat
1418
+ */
1419
+ clear(chatId) {
1420
+ this.storage.delete(this.getChatKey(chatId));
1421
+ }
1422
+ /**
1423
+ * Get entries count for a chat
1424
+ */
1425
+ size(chatId) {
1426
+ const entries = this.loadChatMemory(chatId);
1427
+ return entries.size;
1428
+ }
1429
+ /**
1430
+ * Convert chat memory to a format suitable for system prompt injection
1431
+ */
1432
+ toPromptContext(chatId) {
1433
+ const entries = this.loadChatMemory(chatId);
1434
+ if (entries.size === 0) {
1435
+ return "";
1436
+ }
1437
+ const lines = ["[Chat Memory]"];
1438
+ for (const [key, entry] of entries) {
1439
+ const valueStr = typeof entry.value === "object" ? JSON.stringify(entry.value) : String(entry.value);
1440
+ lines.push(`- ${key}: ${valueStr}`);
1441
+ }
1442
+ return lines.join("\n");
1443
+ }
1444
+ };
1445
+ var chatMemoryInstance = null;
1446
+ function initChatMemory(storagePath, autoSave = true) {
1447
+ chatMemoryInstance = new ChatMemoryStore(storagePath, autoSave);
1448
+ }
1449
+ function getChatMemoryStore() {
1450
+ if (!chatMemoryInstance) {
1451
+ chatMemoryInstance = new ChatMemoryStore();
1452
+ }
1453
+ return chatMemoryInstance;
1454
+ }
1455
+ function setChatMemory(chat, key, value) {
1456
+ getChatMemoryStore().set(chat.id, key, value);
1457
+ const now = Date.now();
1458
+ const existing = chat.memory.get(key);
1459
+ chat.memory.set(key, {
1460
+ key,
1461
+ value,
1462
+ createdAt: existing?.createdAt ?? now,
1463
+ updatedAt: now
1464
+ });
1465
+ }
1466
+ function getChatMemory(chat, key) {
1467
+ const internalEntry = chat.memory.get(key);
1468
+ if (internalEntry) {
1469
+ return internalEntry.value;
1470
+ }
1471
+ return getChatMemoryStore().get(chat.id, key);
1472
+ }
1473
+ function deleteChatMemory(chat, key) {
1474
+ chat.memory.delete(key);
1475
+ return getChatMemoryStore().delete(chat.id, key);
1476
+ }
1477
+ function hasChatMemory(chat, key) {
1478
+ return chat.memory.has(key) || getChatMemoryStore().has(chat.id, key);
1479
+ }
1480
+ function getChatMemoryKeys(chat) {
1481
+ const internalKeys = Array.from(chat.memory.keys());
1482
+ const storedKeys = getChatMemoryStore().keys(chat.id);
1483
+ return [.../* @__PURE__ */ new Set([...internalKeys, ...storedKeys])];
1484
+ }
1485
+ function clearChatMemory(chat) {
1486
+ chat.memory.clear();
1487
+ getChatMemoryStore().clear(chat.id);
1488
+ }
1489
+ function getChatMemoryContext(chat) {
1490
+ return getChatMemoryStore().toPromptContext(chat.id);
1491
+ }
1492
+ function syncChatMemory(chat) {
1493
+ for (const [key, entry] of chat.memory) {
1494
+ getChatMemoryStore().set(chat.id, key, entry.value);
1495
+ }
1496
+ }
1497
+
1498
+ // src/memory/manager.ts
1499
+ function initMemory(config = {}) {
1500
+ initGlobalMemory(config.storagePath, config.autoSave);
1501
+ initChatMemory(config.storagePath, config.autoSave);
1502
+ }
1503
+ function getMemoryContext(chat) {
1504
+ const globalContext = getGlobalMemoryContext();
1505
+ const chatContext = getChatMemoryContext(chat);
1506
+ const parts = [];
1507
+ if (globalContext) {
1508
+ parts.push(globalContext);
1509
+ }
1510
+ if (chatContext) {
1511
+ parts.push(chatContext);
1512
+ }
1513
+ return parts.join("\n\n");
1514
+ }
1515
+ function buildSystemPromptWithMemory(basePrompt, chat) {
1516
+ const memoryContext = getMemoryContext(chat);
1517
+ if (!memoryContext) {
1518
+ return basePrompt;
1519
+ }
1520
+ return `${basePrompt}
1521
+
1522
+ ---
1523
+ ${memoryContext}
1524
+ ---`;
1525
+ }
1526
+
1527
+ // src/acontext/observer.ts
1528
+ var observerStates = /* @__PURE__ */ new Map();
1529
+ var observerCallbacks = /* @__PURE__ */ new Map();
1530
+ var DEFAULT_OBSERVER_CONFIG = {
1531
+ extractTasks: true,
1532
+ extractPreferences: true,
1533
+ autoLearn: false
1534
+ };
1535
+ function generateId(prefix) {
1536
+ return `${prefix}_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
1537
+ }
1538
+ function getState(chatId) {
1539
+ let state = observerStates.get(chatId);
1540
+ if (!state) {
1541
+ state = {
1542
+ enabled: false,
1543
+ config: { ...DEFAULT_OBSERVER_CONFIG },
1544
+ tasks: [],
1545
+ preferences: []
1546
+ };
1547
+ observerStates.set(chatId, state);
1548
+ }
1549
+ return state;
1550
+ }
1551
+ function emitEvent(chatId, event) {
1552
+ const callbacks = observerCallbacks.get(chatId) || [];
1553
+ for (const callback of callbacks) {
1554
+ try {
1555
+ callback(event);
1556
+ } catch (error) {
1557
+ console.error("Observer callback error:", error);
1558
+ }
1559
+ }
1560
+ }
1561
+ function enableObserver(chat, config) {
1562
+ const state = getState(chat.id);
1563
+ state.enabled = true;
1564
+ state.config = { ...DEFAULT_OBSERVER_CONFIG, ...config };
1565
+ observerStates.set(chat.id, state);
1566
+ }
1567
+ function disableObserver(chat) {
1568
+ const state = getState(chat.id);
1569
+ state.enabled = false;
1570
+ observerStates.set(chat.id, state);
1571
+ }
1572
+ function isObserverEnabled(chat) {
1573
+ return getState(chat.id).enabled;
1574
+ }
1575
+ function getObserverConfig(chat) {
1576
+ return { ...getState(chat.id).config };
1577
+ }
1578
+ function onObserverEvent(chat, callback) {
1579
+ const callbacks = observerCallbacks.get(chat.id) || [];
1580
+ callbacks.push(callback);
1581
+ observerCallbacks.set(chat.id, callbacks);
1582
+ return () => {
1583
+ const currentCallbacks = observerCallbacks.get(chat.id) || [];
1584
+ const index = currentCallbacks.indexOf(callback);
1585
+ if (index > -1) {
1586
+ currentCallbacks.splice(index, 1);
1587
+ observerCallbacks.set(chat.id, currentCallbacks);
1588
+ }
1589
+ };
1590
+ }
1591
+ function analyzeMessages(chat, messages) {
1592
+ const state = getState(chat.id);
1593
+ if (!state.enabled) {
1594
+ return { tasks: [], preferences: [] };
1595
+ }
1596
+ const messagesToAnalyze = messages || chat.messages;
1597
+ const tasks = [];
1598
+ const preferences = [];
1599
+ for (const msg of messagesToAnalyze) {
1600
+ if (msg.role === "user") {
1601
+ const taskPatterns = [
1602
+ /(?:해줘|해주세요|만들어|작성해|구현해|추가해|수정해|삭제해|찾아)/,
1603
+ /(?:please|create|make|write|implement|add|update|delete|find)/i
1604
+ ];
1605
+ for (const pattern of taskPatterns) {
1606
+ if (pattern.test(msg.content)) {
1607
+ const description = msg.content.substring(0, 100).trim();
1608
+ tasks.push({
1609
+ description,
1610
+ status: "pending",
1611
+ progress: 0
1612
+ });
1613
+ break;
1614
+ }
1615
+ }
1616
+ const preferencePatterns = [
1617
+ { pattern: /한국어|korean/i, key: "language", value: "ko" },
1618
+ { pattern: /영어|english/i, key: "language", value: "en" },
1619
+ { pattern: /간단히|짧게|briefly/i, key: "response_length", value: "short" },
1620
+ { pattern: /자세히|상세히|in detail/i, key: "response_length", value: "detailed" },
1621
+ { pattern: /코드로|with code/i, key: "include_code", value: true }
1622
+ ];
1623
+ for (const { pattern, key, value } of preferencePatterns) {
1624
+ if (pattern.test(msg.content)) {
1625
+ preferences.push({
1626
+ key,
1627
+ value,
1628
+ confidence: 0.7
1629
+ });
1630
+ }
1631
+ }
1632
+ }
1633
+ if (msg.role === "assistant") {
1634
+ const completionPatterns = [
1635
+ /완료|완성|done|finished|completed/i
1636
+ ];
1637
+ for (const pattern of completionPatterns) {
1638
+ if (pattern.test(msg.content) && tasks.length > 0) {
1639
+ for (let i = tasks.length - 1; i >= 0; i--) {
1640
+ if (tasks[i].status === "pending") {
1641
+ tasks[i].status = "completed";
1642
+ tasks[i].progress = 100;
1643
+ break;
1644
+ }
1645
+ }
1646
+ }
1647
+ }
1648
+ }
1649
+ }
1650
+ return { tasks, preferences };
1651
+ }
1652
+ function processMessages(chat, newMessages) {
1653
+ const state = getState(chat.id);
1654
+ if (!state.enabled) return;
1655
+ const extraction = analyzeMessages(chat, newMessages);
1656
+ const now = Date.now();
1657
+ if (state.config.extractTasks) {
1658
+ for (const extractedTask of extraction.tasks) {
1659
+ const task = {
1660
+ id: generateId("task"),
1661
+ description: extractedTask.description,
1662
+ status: extractedTask.status,
1663
+ progress: extractedTask.progress,
1664
+ createdAt: now,
1665
+ updatedAt: now
1666
+ };
1667
+ state.tasks.push(task);
1668
+ emitEvent(chat.id, {
1669
+ type: "task_detected",
1670
+ timestamp: now,
1671
+ data: task
1672
+ });
1673
+ }
1674
+ }
1675
+ if (state.config.extractPreferences) {
1676
+ for (const extractedPref of extraction.preferences) {
1677
+ const existingIndex = state.preferences.findIndex((p) => p.key === extractedPref.key);
1678
+ const preference = {
1679
+ key: extractedPref.key,
1680
+ value: extractedPref.value,
1681
+ confidence: extractedPref.confidence,
1682
+ source: `message_${newMessages[0]?.id || "unknown"}`
1683
+ };
1684
+ if (existingIndex >= 0) {
1685
+ state.preferences[existingIndex] = preference;
1686
+ } else {
1687
+ state.preferences.push(preference);
1688
+ }
1689
+ emitEvent(chat.id, {
1690
+ type: "preference_detected",
1691
+ timestamp: now,
1692
+ data: preference
1693
+ });
1694
+ }
1695
+ }
1696
+ observerStates.set(chat.id, state);
1697
+ }
1698
+ function getObservedTasks(chat) {
1699
+ return [...getState(chat.id).tasks];
1700
+ }
1701
+ function getObservedPreferences(chat) {
1702
+ return [...getState(chat.id).preferences];
1703
+ }
1704
+ function updateTaskStatus(chat, taskId, status, progress) {
1705
+ const state = getState(chat.id);
1706
+ const task = state.tasks.find((t) => t.id === taskId);
1707
+ if (!task) return false;
1708
+ task.status = status;
1709
+ if (progress !== void 0) {
1710
+ task.progress = progress;
1711
+ }
1712
+ task.updatedAt = Date.now();
1713
+ emitEvent(chat.id, {
1714
+ type: "task_updated",
1715
+ timestamp: Date.now(),
1716
+ data: task
1717
+ });
1718
+ observerStates.set(chat.id, state);
1719
+ return true;
1720
+ }
1721
+ function clearObserverState(chat) {
1722
+ observerStates.delete(chat.id);
1723
+ observerCallbacks.delete(chat.id);
1724
+ }
1725
+ function getObserverState(chat) {
1726
+ return { ...getState(chat.id) };
1727
+ }
1728
+
1729
+ // src/acontext/learner.ts
1730
+ var import_path5 = require("path");
1731
+ var SkillLearner = class {
1732
+ storage;
1733
+ skills = /* @__PURE__ */ new Map();
1734
+ storageKey = "learned_skills";
1735
+ constructor(storagePath) {
1736
+ if (storagePath) {
1737
+ this.storage = new FileStorage((0, import_path5.join)(storagePath, "acontext"));
1738
+ this.load();
1739
+ } else {
1740
+ this.storage = new MemoryStorage();
1741
+ }
1742
+ }
1743
+ /**
1744
+ * Load skills from storage
1745
+ */
1746
+ load() {
1747
+ const data = this.storage.read(this.storageKey);
1748
+ if (data) {
1749
+ this.skills = new Map(Object.entries(data));
1750
+ }
1751
+ }
1752
+ /**
1753
+ * Save skills to storage
1754
+ */
1755
+ save() {
1756
+ const data = {};
1757
+ for (const [key, value] of this.skills) {
1758
+ data[key] = value;
1759
+ }
1760
+ this.storage.write(this.storageKey, data);
1761
+ }
1762
+ /**
1763
+ * Generate a unique skill ID
1764
+ */
1765
+ generateId() {
1766
+ return `skill_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
1767
+ }
1768
+ /**
1769
+ * Extract category from task description
1770
+ */
1771
+ extractCategory(description) {
1772
+ const categoryPatterns = [
1773
+ [/여행|travel|trip/i, "travel"],
1774
+ [/코드|code|programming|개발/i, "coding"],
1775
+ [/글|write|작성|문서/i, "writing"],
1776
+ [/분석|analyze|analysis/i, "analysis"],
1777
+ [/검색|search|find|찾/i, "search"],
1778
+ [/번역|translate/i, "translation"],
1779
+ [/요약|summarize|summary/i, "summarization"]
1780
+ ];
1781
+ for (const [pattern, category] of categoryPatterns) {
1782
+ if (pattern.test(description)) {
1783
+ return category;
1784
+ }
1785
+ }
1786
+ return "general";
1787
+ }
1788
+ /**
1789
+ * Learn from a completed conversation
1790
+ */
1791
+ learn(input) {
1792
+ const now = Date.now();
1793
+ const skillId = this.generateId();
1794
+ const category = this.extractCategory(input.taskDescription);
1795
+ const steps = input.steps.map((step, index) => ({
1796
+ order: index + 1,
1797
+ action: this.summarizeAction(step),
1798
+ expectedInput: this.extractInputPattern(step.userInput),
1799
+ expectedOutput: this.extractOutputPattern(step.assistantOutput)
1800
+ }));
1801
+ const skill = {
1802
+ id: skillId,
1803
+ name: this.generateSkillName(input.taskDescription),
1804
+ description: input.taskDescription,
1805
+ category,
1806
+ steps,
1807
+ successRate: input.outcome === "success" ? 1 : input.outcome === "partial" ? 0.5 : 0,
1808
+ usageCount: 0,
1809
+ createdAt: now,
1810
+ updatedAt: now
1811
+ };
1812
+ this.skills.set(skillId, skill);
1813
+ this.save();
1814
+ return skill;
1815
+ }
1816
+ /**
1817
+ * Summarize an action from a learning step
1818
+ */
1819
+ summarizeAction(step) {
1820
+ const summary = step.assistantOutput.substring(0, 100).trim();
1821
+ if (step.toolsUsed && step.toolsUsed.length > 0) {
1822
+ return `${summary} [Tools: ${step.toolsUsed.join(", ")}]`;
1823
+ }
1824
+ return summary;
1825
+ }
1826
+ /**
1827
+ * Extract input pattern from user input
1828
+ */
1829
+ extractInputPattern(input) {
1830
+ return input.substring(0, 50).trim();
1831
+ }
1832
+ /**
1833
+ * Extract output pattern from assistant output
1834
+ */
1835
+ extractOutputPattern(output) {
1836
+ return output.substring(0, 50).trim();
1837
+ }
1838
+ /**
1839
+ * Generate a skill name from task description
1840
+ */
1841
+ generateSkillName(description) {
1842
+ const name = description.substring(0, 30).trim();
1843
+ return name.replace(/[^a-zA-Z0-9가-힣\s]/g, "").trim() || "Unnamed Skill";
1844
+ }
1845
+ /**
1846
+ * Get a skill by ID
1847
+ */
1848
+ getSkill(skillId) {
1849
+ return this.skills.get(skillId);
1850
+ }
1851
+ /**
1852
+ * Get all skills
1853
+ */
1854
+ getAllSkills() {
1855
+ return Array.from(this.skills.values());
1856
+ }
1857
+ /**
1858
+ * Search skills by category
1859
+ */
1860
+ getSkillsByCategory(category) {
1861
+ return this.getAllSkills().filter((s) => s.category === category);
1862
+ }
1863
+ /**
1864
+ * Search skills by keyword
1865
+ */
1866
+ searchSkills(keyword) {
1867
+ const lowerKeyword = keyword.toLowerCase();
1868
+ return this.getAllSkills().filter(
1869
+ (s) => s.name.toLowerCase().includes(lowerKeyword) || s.description.toLowerCase().includes(lowerKeyword) || s.category.toLowerCase().includes(lowerKeyword)
1870
+ );
1871
+ }
1872
+ /**
1873
+ * Update skill success rate
1874
+ */
1875
+ updateSuccessRate(skillId, success) {
1876
+ const skill = this.skills.get(skillId);
1877
+ if (!skill) return;
1878
+ skill.usageCount += 1;
1879
+ skill.successRate = (skill.successRate * (skill.usageCount - 1) + (success ? 1 : 0)) / skill.usageCount;
1880
+ skill.updatedAt = Date.now();
1881
+ this.skills.set(skillId, skill);
1882
+ this.save();
1883
+ }
1884
+ /**
1885
+ * Delete a skill
1886
+ */
1887
+ deleteSkill(skillId) {
1888
+ const deleted = this.skills.delete(skillId);
1889
+ if (deleted) {
1890
+ this.save();
1891
+ }
1892
+ return deleted;
1893
+ }
1894
+ /**
1895
+ * Clear all skills
1896
+ */
1897
+ clearSkills() {
1898
+ this.skills.clear();
1899
+ this.save();
1900
+ }
1901
+ };
1902
+ var learnerInstance = null;
1903
+ function initLearner(storagePath) {
1904
+ learnerInstance = new SkillLearner(storagePath ?? DEFAULT_STORAGE_PATH);
1905
+ }
1906
+ function getLearner() {
1907
+ if (!learnerInstance) {
1908
+ learnerInstance = new SkillLearner();
1909
+ }
1910
+ return learnerInstance;
1911
+ }
1912
+ function learnFromConversation(chat, taskDescription, outcome = "success") {
1913
+ const steps = [];
1914
+ let currentUserInput = "";
1915
+ for (const msg of chat.messages) {
1916
+ if (msg.role === "user") {
1917
+ currentUserInput = msg.content;
1918
+ } else if (msg.role === "assistant" && currentUserInput) {
1919
+ steps.push({
1920
+ userInput: currentUserInput,
1921
+ assistantOutput: msg.content,
1922
+ toolsUsed: msg.toolCalls?.map((tc) => tc.name)
1923
+ });
1924
+ currentUserInput = "";
1925
+ }
1926
+ }
1927
+ return getLearner().learn({
1928
+ taskDescription,
1929
+ conversationSummary: `Conversation with ${chat.messages.length} messages`,
1930
+ outcome,
1931
+ steps
1932
+ });
1933
+ }
1934
+ function getLearnedSkills(category) {
1935
+ if (category) {
1936
+ return getLearner().getSkillsByCategory(category);
1937
+ }
1938
+ return getLearner().getAllSkills();
1939
+ }
1940
+ function searchLearnedSkills(keyword) {
1941
+ return getLearner().searchSkills(keyword);
1942
+ }
1943
+ function getLearnedSkill(skillId) {
1944
+ return getLearner().getSkill(skillId);
1945
+ }
1946
+ function recordSkillUsage(skillId, success) {
1947
+ getLearner().updateSuccessRate(skillId, success);
1948
+ }
1949
+ function deleteLearnedSkill(skillId) {
1950
+ return getLearner().deleteSkill(skillId);
1951
+ }
1952
+ function clearLearnedSkills() {
1953
+ getLearner().clearSkills();
1954
+ }
1955
+
1956
+ // src/acontext/skills.ts
1957
+ function findRelevantSkills(query, options = {}) {
1958
+ const { category, minSuccessRate = 0, limit = 10 } = options;
1959
+ let skills = getLearnedSkills(category);
1960
+ if (minSuccessRate > 0) {
1961
+ skills = skills.filter((s) => s.successRate >= minSuccessRate);
1962
+ }
1963
+ const scoredSkills = skills.map((skill) => ({
1964
+ skill,
1965
+ score: calculateRelevanceScore(query, skill)
1966
+ }));
1967
+ scoredSkills.sort((a, b) => b.score - a.score);
1968
+ return scoredSkills.filter((s) => s.score > 0).slice(0, limit).map((s) => s.skill);
1969
+ }
1970
+ function calculateRelevanceScore(query, skill) {
1971
+ const lowerQuery = query.toLowerCase();
1972
+ const words = lowerQuery.split(/\s+/).filter((w) => w.length > 1);
1973
+ let score = 0;
1974
+ const lowerName = skill.name.toLowerCase();
1975
+ for (const word of words) {
1976
+ if (lowerName.includes(word)) {
1977
+ score += 3;
1978
+ }
1979
+ }
1980
+ const lowerDesc = skill.description.toLowerCase();
1981
+ for (const word of words) {
1982
+ if (lowerDesc.includes(word)) {
1983
+ score += 2;
1984
+ }
1985
+ }
1986
+ if (lowerQuery.includes(skill.category)) {
1987
+ score += 2;
1988
+ }
1989
+ score *= 0.5 + skill.successRate * 0.5;
1990
+ score += Math.min(skill.usageCount * 0.1, 1);
1991
+ return score;
1992
+ }
1993
+ function applySkill(_chat, skill) {
1994
+ if (!skill || !skill.steps || skill.steps.length === 0) {
1995
+ return {
1996
+ applied: false,
1997
+ skillId: skill?.id || "unknown",
1998
+ error: "Invalid skill or no steps available"
1999
+ };
2000
+ }
2001
+ try {
2002
+ const suggestedPrompt = generateSkillPrompt(skill);
2003
+ return {
2004
+ applied: true,
2005
+ skillId: skill.id,
2006
+ suggestedPrompt
2007
+ };
2008
+ } catch (error) {
2009
+ return {
2010
+ applied: false,
2011
+ skillId: skill.id,
2012
+ error: error instanceof Error ? error.message : "Unknown error"
2013
+ };
2014
+ }
2015
+ }
2016
+ function generateSkillPrompt(skill) {
2017
+ const lines = [
2018
+ `[Skill: ${skill.name}]`,
2019
+ "",
2020
+ "Follow these steps:"
2021
+ ];
2022
+ for (const step of skill.steps) {
2023
+ lines.push(`${step.order}. ${step.action}`);
2024
+ if (step.expectedInput) {
2025
+ lines.push(` Input pattern: ${step.expectedInput}`);
2026
+ }
2027
+ }
2028
+ return lines.join("\n");
2029
+ }
2030
+ function applySkillToSystemPrompt(chat, skill, baseSystemPrompt) {
2031
+ const result = applySkill(chat, skill);
2032
+ if (!result.applied || !result.suggestedPrompt) {
2033
+ return baseSystemPrompt;
2034
+ }
2035
+ return `${baseSystemPrompt}
2036
+
2037
+ ---
2038
+ ${result.suggestedPrompt}
2039
+ ---`;
2040
+ }
2041
+ function getBestSkill(query, options = {}) {
2042
+ const skills = findRelevantSkills(query, { ...options, limit: 1 });
2043
+ return skills[0];
2044
+ }
2045
+ function suggestSkills(chat, limit = 3) {
2046
+ const recentMessages = chat.messages.slice(-5);
2047
+ const context = recentMessages.map((m) => m.content).join(" ");
2048
+ return findRelevantSkills(context, { limit, minSuccessRate: 0.3 });
2049
+ }
2050
+ function recordSkillApplication(skillId, success) {
2051
+ recordSkillUsage(skillId, success);
2052
+ }
2053
+ var skillApplicationHistory = /* @__PURE__ */ new Map();
2054
+ function trackSkillApplication(chatId, skillId) {
2055
+ const history = skillApplicationHistory.get(chatId) || [];
2056
+ history.push({
2057
+ skillId,
2058
+ appliedAt: Date.now()
2059
+ });
2060
+ skillApplicationHistory.set(chatId, history);
2061
+ }
2062
+ function updateSkillApplicationSuccess(chatId, skillId, success) {
2063
+ const history = skillApplicationHistory.get(chatId) || [];
2064
+ let application;
2065
+ for (let i = history.length - 1; i >= 0; i--) {
2066
+ if (history[i].skillId === skillId) {
2067
+ application = history[i];
2068
+ break;
2069
+ }
2070
+ }
2071
+ if (application) {
2072
+ application.success = success;
2073
+ recordSkillApplication(skillId, success);
2074
+ }
2075
+ }
2076
+ function getSkillApplicationHistory(chatId) {
2077
+ return [...skillApplicationHistory.get(chatId) || []];
2078
+ }
2079
+ function clearSkillApplicationHistory(chatId) {
2080
+ skillApplicationHistory.delete(chatId);
2081
+ }
2082
+ // Annotate the CommonJS export names for ESM import in node:
2083
+ 0 && (module.exports = {
2084
+ BaseProvider,
2085
+ ChatLLMError,
2086
+ ConfigurationError,
2087
+ DEFAULT_MODELS,
2088
+ DEFAULT_OLLAMA_BASE_URL,
2089
+ DEFAULT_PERSONALIZATION,
2090
+ DEFAULT_STORAGE_PATH,
2091
+ FileStorage,
2092
+ MemoryStorage,
2093
+ OllamaProvider,
2094
+ ProviderError,
2095
+ ProviderRegistry,
2096
+ StorageError,
2097
+ StreamError,
2098
+ ToolExecutionError,
2099
+ ValidationError,
2100
+ addSessionMessage,
2101
+ addSessionMessages,
2102
+ analyzeMessages,
2103
+ applySkill,
2104
+ applySkillToSystemPrompt,
2105
+ buildSystemPromptWithMemory,
2106
+ clearChatMemory,
2107
+ clearGlobalMemory,
2108
+ clearLearnedSkills,
2109
+ clearMessages,
2110
+ clearObserverState,
2111
+ clearSessionMessages,
2112
+ clearSkillApplicationHistory,
2113
+ cloneMessage,
2114
+ collectStreamContent,
2115
+ createAssistantMessage,
2116
+ createChat,
2117
+ createMessage,
2118
+ createSession,
2119
+ createStreamEvent,
2120
+ createSystemMessage,
2121
+ createToolMessage,
2122
+ createUserMessage,
2123
+ deleteChatMemory,
2124
+ deleteGlobalMemory,
2125
+ deleteLearnedSkill,
2126
+ deserializeSession,
2127
+ destroyChat,
2128
+ disableObserver,
2129
+ enableObserver,
2130
+ filterByProvider,
2131
+ filterByRole,
2132
+ findRelevantSkills,
2133
+ formatMessagesForDisplay,
2134
+ getBestSkill,
2135
+ getChatMemory,
2136
+ getChatMemoryContext,
2137
+ getChatMemoryKeys,
2138
+ getDefaultModel,
2139
+ getGlobalMemory,
2140
+ getGlobalMemoryContext,
2141
+ getGlobalMemoryKeys,
2142
+ getGlobalMemoryStore,
2143
+ getLastMessageByRole,
2144
+ getLastMessages,
2145
+ getLearnedSkill,
2146
+ getLearnedSkills,
2147
+ getMemoryContext,
2148
+ getMessages,
2149
+ getMessagesAfter,
2150
+ getMessagesForProvider,
2151
+ getObservedPreferences,
2152
+ getObservedTasks,
2153
+ getObserverConfig,
2154
+ getObserverState,
2155
+ getProviderBaseUrl,
2156
+ getSession,
2157
+ getSessionSummary,
2158
+ getSkillApplicationHistory,
2159
+ getTools,
2160
+ getTotalContentLength,
2161
+ hasChatMemory,
2162
+ hasGlobalMemory,
2163
+ initChatMemory,
2164
+ initGlobalMemory,
2165
+ initLearner,
2166
+ initMemory,
2167
+ isObserverEnabled,
2168
+ isProviderError,
2169
+ isStorageError,
2170
+ isToolExecutionError,
2171
+ learnFromConversation,
2172
+ mergeConfig,
2173
+ onObserverEvent,
2174
+ parseNDJSONStream,
2175
+ parseSSEStream,
2176
+ processMessages,
2177
+ recordSkillApplication,
2178
+ recordSkillUsage,
2179
+ registerTool,
2180
+ resetChat,
2181
+ searchLearnedSkills,
2182
+ sendMessage,
2183
+ sendMessageStream,
2184
+ serializeSession,
2185
+ setChatMemory,
2186
+ setGlobalMemory,
2187
+ setSessionMetadata,
2188
+ setSessionSystemPrompt,
2189
+ setSystemPrompt,
2190
+ suggestSkills,
2191
+ syncChatMemory,
2192
+ trackSkillApplication,
2193
+ truncateMessages,
2194
+ unregisterTool,
2195
+ updateSkillApplicationSuccess,
2196
+ updateTaskStatus,
2197
+ validateProviderConfig,
2198
+ wrapProviderError
2199
+ });