@wabot-dev/framework 0.9.17 → 0.9.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (26) hide show
  1. package/dist/src/addon/async/in-memory/InMemoryCronJobRepository.js +74 -3
  2. package/dist/src/addon/async/in-memory/InMemoryJobRepository.js +75 -3
  3. package/dist/src/addon/async/pg/PgCronJobRepository.js +1 -2
  4. package/dist/src/addon/async/pg/PgJobRepository.js +1 -2
  5. package/dist/src/addon/async/pg/PgTransactionAdapter.js +3 -2
  6. package/dist/src/addon/auth/api-key/PgApiKeyRepository.js +3 -3
  7. package/dist/src/addon/auth/jwt/PgJwtRefreshTokenRepository.js +1 -1
  8. package/dist/src/addon/chat-bot/anthropic/AnthropicChatAdapter.js +2 -5
  9. package/dist/src/addon/chat-bot/deepseek/DeepSeekChatAdapter.js +2 -6
  10. package/dist/src/addon/chat-bot/google/GoogleChatAdapter.js +2 -5
  11. package/dist/src/addon/chat-bot/in-memory/InMemoryChatRepository.js +1 -1
  12. package/dist/src/addon/chat-bot/openia/OpenaiChatAdapter.js +4 -6
  13. package/dist/src/addon/chat-bot/openrouter/OpenRouterChatAdapter.js +2 -6
  14. package/dist/src/addon/chat-bot/pg/PgChatMemory.js +2 -2
  15. package/dist/src/addon/chat-bot/pg/PgChatRepository.js +2 -2
  16. package/dist/src/addon/chat-controller/telegram/@telegram.js +3 -1
  17. package/dist/src/addon/chat-controller/telegram/TelegramChannel.js +4 -1
  18. package/dist/src/addon/chat-controller/telegram/markdownToTelegramHtml.js +45 -0
  19. package/dist/src/feature/chat-bot/ChatBot.js +22 -3
  20. package/dist/src/feature/mindset/MindsetOperator.js +87 -27
  21. package/dist/src/feature/mindset/buildParameterSchema.js +155 -0
  22. package/dist/src/feature/pg/@pgExtension.js +1 -2
  23. package/dist/src/feature/repository/MemoryRepositoryAdapter.js +93 -7
  24. package/dist/src/index.d.ts +47 -8
  25. package/dist/src/index.js +1 -0
  26. package/package.json +1 -1
@@ -1,9 +1,29 @@
1
- import { __decorate } from 'tslib';
1
+ import { __decorate, __metadata } from 'tslib';
2
+ import * as fs from 'node:fs';
3
+ import * as path from 'node:path';
2
4
  import { generate } from 'short-uuid';
3
5
  import { singleton } from '../../../core/injection/index.js';
6
+ import { Logger } from '../../../core/logger/Logger.js';
7
+ import '../../../feature/async/AsyncMetadataStore.js';
8
+ import '../../../feature/async/TransactionMetadataStore.js';
9
+ import '../../../feature/async/Async.js';
10
+ import { CronJob } from '../../../feature/async/CronJob.js';
11
+ import '../../../core/error/setupErrorHandlers.js';
12
+ import '../../../feature/async/JobRepository.js';
13
+ import '../../../feature/async/JobRunner.js';
14
+ import '../../../feature/async/JobScheduler.js';
15
+ import '../../../feature/async/JobWatchdog.js';
16
+ import '../../../feature/async/CronScheduler.js';
4
17
 
18
+ const CRON_JOBS_FILE = '.wabot/in-memory/cron-jobs.json';
19
+ const MAX_CRON_JOBS = 32;
20
+ const logger = new Logger('wabot:in-memory-cron-job-repository');
5
21
  let InMemoryCronJobRepository = class InMemoryCronJobRepository {
22
+ // Insertion order acts as LRU: most-recently-touched at the end.
6
23
  items = new Map();
24
+ constructor() {
25
+ this.load();
26
+ }
7
27
  async create(cronJob) {
8
28
  if (cronJob.wasCreated())
9
29
  throw new Error('CronJob already created');
@@ -11,6 +31,8 @@ let InMemoryCronJobRepository = class InMemoryCronJobRepository {
11
31
  cronJob['data'].createdAt = new Date().getTime();
12
32
  cronJob.validate();
13
33
  this.items.set(cronJob.id, cronJob);
34
+ this.enforceLimit();
35
+ this.persist();
14
36
  }
15
37
  async findDue(date) {
16
38
  const now = (date ?? new Date()).getTime();
@@ -28,7 +50,8 @@ let InMemoryCronJobRepository = class InMemoryCronJobRepository {
28
50
  if (!cronJob.wasCreated())
29
51
  throw new Error('CronJob was not created');
30
52
  cronJob.validate();
31
- this.items.set(cronJob.id, cronJob);
53
+ this.touch(cronJob);
54
+ this.persist();
32
55
  }
33
56
  async findByName(name) {
34
57
  for (const c of this.items.values()) {
@@ -37,9 +60,57 @@ let InMemoryCronJobRepository = class InMemoryCronJobRepository {
37
60
  }
38
61
  return null;
39
62
  }
63
+ touch(item) {
64
+ this.items.delete(item.id);
65
+ this.items.set(item.id, item);
66
+ }
67
+ enforceLimit() {
68
+ while (this.items.size > MAX_CRON_JOBS) {
69
+ const oldestKey = this.items.keys().next().value;
70
+ if (oldestKey === undefined)
71
+ break;
72
+ this.items.delete(oldestKey);
73
+ }
74
+ }
75
+ filePath() {
76
+ return path.resolve(process.cwd(), CRON_JOBS_FILE);
77
+ }
78
+ load() {
79
+ const file = this.filePath();
80
+ if (!fs.existsSync(file))
81
+ return;
82
+ try {
83
+ const raw = fs.readFileSync(file, 'utf-8');
84
+ const parsed = JSON.parse(raw);
85
+ if (!Array.isArray(parsed))
86
+ return;
87
+ for (const data of parsed) {
88
+ if (!data?.id)
89
+ continue;
90
+ const cronJob = new CronJob(data);
91
+ this.items.set(cronJob.id, cronJob);
92
+ }
93
+ this.enforceLimit();
94
+ }
95
+ catch (err) {
96
+ logger.warn(`Failed to load ${file}:`, err);
97
+ }
98
+ }
99
+ persist() {
100
+ const file = this.filePath();
101
+ try {
102
+ fs.mkdirSync(path.dirname(file), { recursive: true });
103
+ const data = [...this.items.values()].map((c) => c['data']);
104
+ fs.writeFileSync(file, JSON.stringify(data, null, 2), 'utf-8');
105
+ }
106
+ catch (err) {
107
+ logger.warn(`Failed to persist ${file}:`, err);
108
+ }
109
+ }
40
110
  };
41
111
  InMemoryCronJobRepository = __decorate([
42
- singleton()
112
+ singleton(),
113
+ __metadata("design:paramtypes", [])
43
114
  ], InMemoryCronJobRepository);
44
115
 
45
116
  export { InMemoryCronJobRepository };
@@ -1,9 +1,29 @@
1
- import { __decorate } from 'tslib';
1
+ import { __decorate, __metadata } from 'tslib';
2
+ import * as fs from 'node:fs';
3
+ import * as path from 'node:path';
2
4
  import { generate } from 'short-uuid';
3
5
  import { singleton } from '../../../core/injection/index.js';
6
+ import { Logger } from '../../../core/logger/Logger.js';
7
+ import '../../../feature/async/AsyncMetadataStore.js';
8
+ import '../../../feature/async/TransactionMetadataStore.js';
9
+ import '../../../feature/async/Async.js';
10
+ import '../../../_virtual/index.js';
11
+ import { Job } from '../../../feature/async/Job.js';
12
+ import '../../../feature/async/JobRepository.js';
13
+ import '../../../feature/async/JobRunner.js';
14
+ import '../../../feature/async/JobScheduler.js';
15
+ import '../../../feature/async/JobWatchdog.js';
16
+ import '../../../feature/async/CronScheduler.js';
4
17
 
18
+ const JOBS_FILE = '.wabot/in-memory/jobs.json';
19
+ const MAX_JOBS = 32;
20
+ const logger = new Logger('wabot:in-memory-job-repository');
5
21
  let InMemoryJobRepository = class InMemoryJobRepository {
22
+ // Insertion order acts as LRU: most-recently-touched at the end.
6
23
  items = new Map();
24
+ constructor() {
25
+ this.load();
26
+ }
7
27
  async find(id) {
8
28
  return this.items.get(id) ?? null;
9
29
  }
@@ -26,15 +46,19 @@ let InMemoryJobRepository = class InMemoryJobRepository {
26
46
  item['data'].createdAt = new Date().getTime();
27
47
  item.validate();
28
48
  this.items.set(item.id, item);
49
+ this.enforceLimit();
50
+ this.persist();
29
51
  }
30
52
  async update(item) {
31
53
  if (!item.wasCreated())
32
54
  throw new Error('Job was not created');
33
55
  item.validate();
34
- this.items.set(item.id, item);
56
+ this.touch(item);
57
+ this.persist();
35
58
  }
36
59
  async delete(item) {
37
60
  this.items.delete(item.id);
61
+ this.persist();
38
62
  }
39
63
  async findPendingForRunFrom(date, limit) {
40
64
  const now = date.getTime();
@@ -67,9 +91,57 @@ let InMemoryJobRepository = class InMemoryJobRepository {
67
91
  }
68
92
  return count;
69
93
  }
94
+ touch(item) {
95
+ this.items.delete(item.id);
96
+ this.items.set(item.id, item);
97
+ }
98
+ enforceLimit() {
99
+ while (this.items.size > MAX_JOBS) {
100
+ const oldestKey = this.items.keys().next().value;
101
+ if (oldestKey === undefined)
102
+ break;
103
+ this.items.delete(oldestKey);
104
+ }
105
+ }
106
+ filePath() {
107
+ return path.resolve(process.cwd(), JOBS_FILE);
108
+ }
109
+ load() {
110
+ const file = this.filePath();
111
+ if (!fs.existsSync(file))
112
+ return;
113
+ try {
114
+ const raw = fs.readFileSync(file, 'utf-8');
115
+ const parsed = JSON.parse(raw);
116
+ if (!Array.isArray(parsed))
117
+ return;
118
+ for (const data of parsed) {
119
+ if (!data?.id)
120
+ continue;
121
+ const job = new Job(data);
122
+ this.items.set(job.id, job);
123
+ }
124
+ this.enforceLimit();
125
+ }
126
+ catch (err) {
127
+ logger.warn(`Failed to load ${file}:`, err);
128
+ }
129
+ }
130
+ persist() {
131
+ const file = this.filePath();
132
+ try {
133
+ fs.mkdirSync(path.dirname(file), { recursive: true });
134
+ const data = [...this.items.values()].map((j) => j['data']);
135
+ fs.writeFileSync(file, JSON.stringify(data, null, 2), 'utf-8');
136
+ }
137
+ catch (err) {
138
+ logger.warn(`Failed to persist ${file}:`, err);
139
+ }
140
+ }
70
141
  };
71
142
  InMemoryJobRepository = __decorate([
72
- singleton()
143
+ singleton(),
144
+ __metadata("design:paramtypes", [])
73
145
  ], InMemoryJobRepository);
74
146
 
75
147
  export { InMemoryJobRepository };
@@ -1,8 +1,7 @@
1
1
  import { __decorate, __metadata } from 'tslib';
2
2
  import { singleton } from '../../../core/injection/index.js';
3
3
  import { CronJob } from '../../../feature/async/CronJob.js';
4
- import 'short-uuid';
5
- import '../../../core/error/setupErrorHandlers.js';
4
+ import '../../../feature/repository/MemoryRepositoryAdapter.js';
6
5
  import '../../../feature/repository/RepositoryMetadataStore.js';
7
6
  import '../../../feature/repository/RepositoryAdapterRegistry.js';
8
7
  import '../../../feature/pg/withPgClient.js';
@@ -1,8 +1,7 @@
1
1
  import { __decorate, __metadata } from 'tslib';
2
2
  import { Pool } from 'pg';
3
3
  import { singleton } from '../../../core/injection/index.js';
4
- import 'short-uuid';
5
- import '../../../core/error/setupErrorHandlers.js';
4
+ import '../../../feature/repository/MemoryRepositoryAdapter.js';
6
5
  import '../../../feature/repository/RepositoryMetadataStore.js';
7
6
  import '../../../feature/repository/RepositoryAdapterRegistry.js';
8
7
  import { withPgClient } from '../../../feature/pg/withPgClient.js';
@@ -1,11 +1,12 @@
1
1
  import '../../../core/injection/index.js';
2
- import 'short-uuid';
3
- import '../../../core/error/setupErrorHandlers.js';
2
+ import '../../../feature/repository/MemoryRepositoryAdapter.js';
4
3
  import '../../../feature/repository/RepositoryMetadataStore.js';
5
4
  import '../../../feature/repository/RepositoryAdapterRegistry.js';
6
5
  import { withPgClient } from '../../../feature/pg/withPgClient.js';
7
6
  import 'debug';
8
7
  import '../../../feature/pg/PgLocker.js';
8
+ import 'short-uuid';
9
+ import '../../../core/error/setupErrorHandlers.js';
9
10
  import 'node:crypto';
10
11
  import '../../../feature/pg/pgStorage.js';
11
12
  import { withPgTransaction } from '../../../feature/pg/withPgTransaction.js';
@@ -1,18 +1,18 @@
1
1
  import { __decorate, __metadata } from 'tslib';
2
2
  import { singleton } from '../../../core/injection/index.js';
3
- import 'short-uuid';
4
- import { CustomError } from '../../../core/error/CustomError.js';
5
- import '../../../core/error/setupErrorHandlers.js';
3
+ import '../../../feature/repository/MemoryRepositoryAdapter.js';
6
4
  import '../../../feature/repository/RepositoryMetadataStore.js';
7
5
  import '../../../feature/repository/RepositoryAdapterRegistry.js';
8
6
  import '../../../feature/pg/withPgClient.js';
9
7
  import 'debug';
8
+ import { CustomError } from '../../../core/error/CustomError.js';
10
9
  import '../../../feature/pg/PgLocker.js';
11
10
  import { PgCrudRepository } from '../../../feature/pg/PgCrudRepository.js';
12
11
  import 'node:crypto';
13
12
  import '../../../feature/pg/pgStorage.js';
14
13
  import { Pool } from 'pg';
15
14
  import { ApiKey } from './ApiKey.js';
15
+ import '../../../core/error/setupErrorHandlers.js';
16
16
 
17
17
  let PgApiKeyRepository = class PgApiKeyRepository extends PgCrudRepository {
18
18
  constructor(pool) {
@@ -2,7 +2,7 @@ import { __decorate, __metadata } from 'tslib';
2
2
  import { singleton } from '../../../core/injection/index.js';
3
3
  import { CustomError } from '../../../core/error/CustomError.js';
4
4
  import '../../../core/error/setupErrorHandlers.js';
5
- import 'short-uuid';
5
+ import '../../../feature/repository/MemoryRepositoryAdapter.js';
6
6
  import '../../../feature/repository/RepositoryMetadataStore.js';
7
7
  import '../../../feature/repository/RepositoryAdapterRegistry.js';
8
8
  import '../../../feature/pg/withPgClient.js';
@@ -167,11 +167,8 @@ let AnthropicChatAdapter = class AnthropicChatAdapter {
167
167
  description: tool.description,
168
168
  input_schema: {
169
169
  type: 'object',
170
- properties: tool.parameters.reduce((prev, param) => ({
171
- ...prev,
172
- [param.name]: { type: param.type, description: param.description },
173
- }), {}),
174
- required: tool.parameters.map((param) => param.name),
170
+ properties: tool.parameters.reduce((prev, param) => ({ ...prev, [param.name]: param.schema }), {}),
171
+ required: tool.parameters.filter((p) => p.required).map((p) => p.name),
175
172
  },
176
173
  };
177
174
  }
@@ -122,14 +122,10 @@ let DeepSeekChatAdapter = class DeepSeekChatAdapter {
122
122
  description: tool.description,
123
123
  parameters: {
124
124
  type: 'object',
125
- properties: tool.parameters.reduce((prev, param) => ({
126
- ...prev,
127
- [param.name]: { type: param.type, description: param.description },
128
- }), {}),
129
- required: tool.parameters.map((param) => param.name),
125
+ properties: tool.parameters.reduce((prev, param) => ({ ...prev, [param.name]: param.schema }), {}),
126
+ required: tool.parameters.filter((p) => p.required).map((p) => p.name),
130
127
  additionalProperties: false,
131
128
  },
132
- strict: true,
133
129
  },
134
130
  };
135
131
  }
@@ -169,11 +169,8 @@ let GoogleChatAdapter = class GoogleChatAdapter {
169
169
  description: tool.description,
170
170
  parametersJsonSchema: {
171
171
  type: 'object',
172
- properties: tool.parameters.reduce((prev, param) => ({
173
- ...prev,
174
- [param.name]: { type: param.type, description: param.description },
175
- }), {}),
176
- required: tool.parameters.map((param) => param.name),
172
+ properties: tool.parameters.reduce((prev, param) => ({ ...prev, [param.name]: param.schema }), {}),
173
+ required: tool.parameters.filter((p) => p.required).map((p) => p.name),
177
174
  additionalProperties: false,
178
175
  },
179
176
  };
@@ -16,7 +16,7 @@ import '../../../core/error/setupErrorHandlers.js';
16
16
 
17
17
  const CHATS_FILE = '.wabot/in-memory/chats.json';
18
18
  const MEMORY_DIR = '.wabot/in-memory';
19
- const MAX_CHATS = 10;
19
+ const MAX_CHATS = 32;
20
20
  const logger = new Logger('wabot:in-memory-chat-repository');
21
21
  let InMemoryChatRepository = class InMemoryChatRepository {
22
22
  // Ordered least-recently-active first, most-recent last.
@@ -129,20 +129,18 @@ let OpenaiChatAdapter = class OpenaiChatAdapter {
129
129
  ];
130
130
  }
131
131
  mapTool(tool) {
132
+ const allRequired = tool.parameters.every((p) => p.required);
132
133
  return {
133
134
  type: 'function',
134
135
  name: tool.name,
135
136
  description: tool.description,
136
137
  parameters: {
137
138
  type: 'object',
138
- properties: tool.parameters.reduce((prev, param) => ({
139
- ...prev,
140
- [param.name]: { type: param.type, description: param.description },
141
- }), {}),
142
- required: tool.parameters.map((param) => param.name),
139
+ properties: tool.parameters.reduce((prev, param) => ({ ...prev, [param.name]: param.schema }), {}),
140
+ required: tool.parameters.filter((p) => p.required).map((p) => p.name),
143
141
  additionalProperties: false,
144
142
  },
145
- strict: true,
143
+ strict: allRequired,
146
144
  };
147
145
  }
148
146
  mapResponse(response, modelName) {
@@ -146,14 +146,10 @@ let OpenRouterChatAdapter = class OpenRouterChatAdapter {
146
146
  description: tool.description,
147
147
  parameters: {
148
148
  type: 'object',
149
- properties: tool.parameters.reduce((prev, param) => ({
150
- ...prev,
151
- [param.name]: { type: param.type, description: param.description },
152
- }), {}),
153
- required: tool.parameters.map((param) => param.name),
149
+ properties: tool.parameters.reduce((prev, param) => ({ ...prev, [param.name]: param.schema }), {}),
150
+ required: tool.parameters.filter((p) => p.required).map((p) => p.name),
154
151
  additionalProperties: false,
155
152
  },
156
- strict: true,
157
153
  },
158
154
  };
159
155
  }
@@ -1,6 +1,5 @@
1
1
  import '../../../core/injection/index.js';
2
- import 'short-uuid';
3
- import '../../../core/error/setupErrorHandlers.js';
2
+ import '../../../feature/repository/MemoryRepositoryAdapter.js';
4
3
  import '../../../feature/repository/RepositoryMetadataStore.js';
5
4
  import '../../../feature/repository/RepositoryAdapterRegistry.js';
6
5
  import '../../../feature/pg/withPgClient.js';
@@ -17,6 +16,7 @@ import '../../../feature/chat-bot/UnionChatAdapter.js';
17
16
  import '../../../feature/chat-bot/metadata/ChatAdapterMetadataStore.js';
18
17
  import 'uuid';
19
18
  import '../../../feature/chat-bot/metadata/ChatBotMetadataStore.js';
19
+ import '../../../core/error/setupErrorHandlers.js';
20
20
 
21
21
  class PgChatMemory extends PgCrudRepository {
22
22
  chatId;
@@ -2,8 +2,7 @@ import { __decorate, __metadata } from 'tslib';
2
2
  import { Pool } from 'pg';
3
3
  import { PgChatMemory } from './PgChatMemory.js';
4
4
  import { singleton } from '../../../core/injection/index.js';
5
- import 'short-uuid';
6
- import '../../../core/error/setupErrorHandlers.js';
5
+ import '../../../feature/repository/MemoryRepositoryAdapter.js';
7
6
  import '../../../feature/repository/RepositoryMetadataStore.js';
8
7
  import '../../../feature/repository/RepositoryAdapterRegistry.js';
9
8
  import '../../../feature/pg/withPgClient.js';
@@ -20,6 +19,7 @@ import '../../../feature/chat-bot/UnionChatAdapter.js';
20
19
  import '../../../feature/chat-bot/metadata/ChatAdapterMetadataStore.js';
21
20
  import 'uuid';
22
21
  import '../../../feature/chat-bot/metadata/ChatBotMetadataStore.js';
22
+ import '../../../core/error/setupErrorHandlers.js';
23
23
 
24
24
  let PgChatRepository = class PgChatRepository extends PgCrudRepository {
25
25
  constructor(pool) {
@@ -1,4 +1,5 @@
1
1
  import { container } from '../../../core/injection/index.js';
2
+ import { resolveConfigReferences } from '../../../core/config/resolver.js';
2
3
  import { ControllerMetadataStore } from '../../../feature/chat-controller/metadata/ControllerMetadataStore.js';
3
4
  import '../../../feature/chat-controller/ChatResolver.js';
4
5
  import '../../../feature/chat-controller/runChatControllers.js';
@@ -7,12 +8,13 @@ import { TelegramChannelConfig } from './TelegramChannelConfig.js';
7
8
 
8
9
  function telegram(config) {
9
10
  return function (target, propertyKey) {
11
+ const resolved = resolveConfigReferences(config);
10
12
  const store = container.resolve(ControllerMetadataStore);
11
13
  store.saveChannelMetadata({
12
14
  channelConstructor: TelegramChannel,
13
15
  functionName: propertyKey.toString(),
14
16
  controllerConstructor: target.constructor,
15
- channelConfig: new TelegramChannelConfig(config.botToken),
17
+ channelConfig: new TelegramChannelConfig(resolved.botToken),
16
18
  });
17
19
  };
18
20
  }
@@ -2,6 +2,7 @@ import { __decorate, __metadata } from 'tslib';
2
2
  import { Bot } from 'grammy';
3
3
  import { TelegramChannelConfig } from './TelegramChannelConfig.js';
4
4
  import { injectable } from '../../../core/injection/index.js';
5
+ import { markdownToTelegramHtml } from './markdownToTelegramHtml.js';
5
6
  import { telegramChannelName } from './telegramChannelName.js';
6
7
 
7
8
  var TelegramChannel_1;
@@ -35,7 +36,9 @@ let TelegramChannel = class TelegramChannel {
35
36
  reply: async (replyMessage) => {
36
37
  if (!replyMessage.text)
37
38
  return;
38
- await ctx.reply(replyMessage.text);
39
+ await ctx.reply(markdownToTelegramHtml(replyMessage.text), {
40
+ parse_mode: 'HTML',
41
+ });
39
42
  },
40
43
  });
41
44
  });
@@ -0,0 +1,45 @@
1
+ const PH_OPEN = '';
2
+ const PH_CLOSE = '';
3
+ function escapeHtml(text) {
4
+ return text
5
+ .replace(/&/g, '&')
6
+ .replace(/</g, '&lt;')
7
+ .replace(/>/g, '&gt;');
8
+ }
9
+ function markdownToTelegramHtml(input) {
10
+ if (!input)
11
+ return input;
12
+ const reserved = [];
13
+ const reserve = (html) => {
14
+ const token = `${PH_OPEN}${reserved.length}${PH_CLOSE}`;
15
+ reserved.push(html);
16
+ return token;
17
+ };
18
+ let text = input.replace(/\r\n/g, '\n');
19
+ text = text.replace(/```(\w+)?\n?([\s\S]*?)```/g, (_, lang, code) => {
20
+ const escaped = escapeHtml(code.replace(/\n$/, ''));
21
+ if (lang)
22
+ return reserve(`<pre><code class="language-${lang}">${escaped}</code></pre>`);
23
+ return reserve(`<pre>${escaped}</pre>`);
24
+ });
25
+ text = text.replace(/`([^`\n]+)`/g, (_, code) => {
26
+ return reserve(`<code>${escapeHtml(code)}</code>`);
27
+ });
28
+ text = text.replace(/\[([^\]]+)\]\(([^)\s]+)\)/g, (_, label, url) => {
29
+ return reserve(`<a href="${escapeHtml(url)}">${escapeHtml(label)}</a>`);
30
+ });
31
+ text = escapeHtml(text);
32
+ text = text.replace(/^(#{1,6})\s+(.+)$/gm, (_, _hashes, content) => `<b>${content.trim()}</b>`);
33
+ text = text.replace(/^&gt;\s?(.*)$/gm, '<blockquote>$1</blockquote>');
34
+ text = text.replace(/<\/blockquote>\n<blockquote>/g, '\n');
35
+ text = text.replace(/\*\*([^\n*]+?)\*\*/g, '<b>$1</b>');
36
+ text = text.replace(/__([^\n_]+?)__/g, '<b>$1</b>');
37
+ text = text.replace(/(^|[\s(>])\*([^\s*][^*\n]*?)\*(?=[\s).,!?:;]|$)/g, '$1<i>$2</i>');
38
+ text = text.replace(/(^|[\s(>])_([^\s_][^_\n]*?)_(?=[\s).,!?:;]|$)/g, '$1<i>$2</i>');
39
+ text = text.replace(/~~([^\n~]+?)~~/g, '<s>$1</s>');
40
+ text = text.replace(/^[ \t]*[-*+]\s+(.+)$/gm, '• $1');
41
+ text = text.replace(new RegExp(`${PH_OPEN}(\\d+)${PH_CLOSE}`, 'g'), (_, idx) => reserved[Number(idx)]);
42
+ return text;
43
+ }
44
+
45
+ export { markdownToTelegramHtml };
@@ -5,11 +5,20 @@ import { MindsetOperator } from '../mindset/MindsetOperator.js';
5
5
  import { ChatAdapter } from './ChatAdapter.js';
6
6
  import { ChatItem } from './ChatItem.js';
7
7
  import { ChatMemory } from './ChatMemory.js';
8
+ import { Logger } from '../../core/logger/Logger.js';
8
9
 
10
+ const MAX_CONSECUTIVE_INVALID_ARGS = 2;
11
+ function isInvalidArgsResult(result) {
12
+ if (!result)
13
+ return false;
14
+ return (result.startsWith('{"error":"INVALID_ARGUMENTS"') ||
15
+ result.startsWith('{"error":"INVALID_JSON_ARGUMENTS"'));
16
+ }
9
17
  let ChatBot = class ChatBot {
10
18
  memory;
11
19
  adapter;
12
20
  mindset;
21
+ logger = new Logger('wabot:chat-bot');
13
22
  constructor(memory, adapter, mindset) {
14
23
  this.memory = memory;
15
24
  this.adapter = adapter;
@@ -21,9 +30,9 @@ let ChatBot = class ChatBot {
21
30
  humanMessage: message,
22
31
  });
23
32
  await this.memory.create(newChatItem);
24
- await this.processLoop(callback);
33
+ await this.processLoop(callback, 0);
25
34
  }
26
- async processLoop(callback) {
35
+ async processLoop(callback, invalidArgsCount) {
27
36
  const prevItems = await this.memory.findLastItems(16);
28
37
  if (prevItems.length === 0) {
29
38
  return;
@@ -53,6 +62,12 @@ let ChatBot = class ChatBot {
53
62
  for (const newItemData of newItemsData) {
54
63
  if (newItemData.type === 'functionCall') {
55
64
  newItemData.functionCall.result = await this.mindset.callFunction(newItemData.functionCall.name, newItemData.functionCall.arguments ?? '{}');
65
+ if (isInvalidArgsResult(newItemData.functionCall.result)) {
66
+ invalidArgsCount++;
67
+ }
68
+ else {
69
+ invalidArgsCount = 0;
70
+ }
56
71
  }
57
72
  else if (newItemData.type === 'botMessage') {
58
73
  newItemData.botMessage.senderName = identity.name;
@@ -63,10 +78,14 @@ let ChatBot = class ChatBot {
63
78
  await callback(newChatItem.botMessage);
64
79
  }
65
80
  }
81
+ if (invalidArgsCount >= MAX_CONSECUTIVE_INVALID_ARGS) {
82
+ this.logger.warn(`Aborting chat loop after ${invalidArgsCount} consecutive invalid-argument function calls`);
83
+ return;
84
+ }
66
85
  if (newItemsData.length == 0 || newItemsData[newItemsData.length - 1].type === 'botMessage') {
67
86
  return;
68
87
  }
69
- await this.processLoop(callback);
88
+ await this.processLoop(callback, invalidArgsCount);
70
89
  }
71
90
  };
72
91
  ChatBot = __decorate([
@@ -7,6 +7,8 @@ import '../../core/validation/metadata/ValidationMetadataStore.js';
7
7
  import { CustomError, errorToPlainObject } from '../../core/error/CustomError.js';
8
8
  import '../../core/error/setupErrorHandlers.js';
9
9
  import { Logger } from '../../core/logger/Logger.js';
10
+ import { DescriptionMetadataStore } from '../../core/description/metadata/DescriptionMetadataStore.js';
11
+ import { buildPropertySchema } from './buildParameterSchema.js';
10
12
  import { Container } from '../../core/injection/Container.js';
11
13
 
12
14
  const MODEL_KIND_FALLBACK = {
@@ -16,11 +18,13 @@ const MODEL_KIND_FALLBACK = {
16
18
  let MindsetOperator = class MindsetOperator {
17
19
  mindset;
18
20
  container;
21
+ descriptionStore;
19
22
  logger = new Logger('wabot:mindset-operator');
20
23
  metadata;
21
- constructor(mindset, container, metadataStore) {
24
+ constructor(mindset, container, metadataStore, descriptionStore) {
22
25
  this.mindset = mindset;
23
26
  this.container = container;
27
+ this.descriptionStore = descriptionStore;
24
28
  this.metadata = metadataStore.getMindsetInfo(this.mindset.constructor);
25
29
  }
26
30
  context() {
@@ -107,38 +111,37 @@ let MindsetOperator = class MindsetOperator {
107
111
  return systemPrompt;
108
112
  }
109
113
  tools() {
114
+ const deps = {
115
+ descriptionStore: this.descriptionStore,
116
+ };
110
117
  return this.metadata.modules
111
118
  .map((module) => module.functions.map((fn) => {
119
+ const argsValidatorsInfo = fn.argsValidatorsInfo;
120
+ const propertyValidators = argsValidatorsInfo?.properties ?? {};
112
121
  return {
113
122
  language: module.config?.language ?? 'english',
114
123
  name: fn.name,
115
124
  description: fn.description,
116
- parameters: fn.argsDescriptions.map((x) => ({
117
- type: this.paramType(x.typeDescriptor),
118
- name: x.propertyName,
119
- description: this.paramDescription(x.description, x.typeDescriptor),
120
- })),
125
+ parameters: fn.argsDescriptions.map((arg) => {
126
+ const propInfo = propertyValidators[arg.propertyName];
127
+ const schema = buildPropertySchema(propInfo?.validators ?? [], this.paramDescription(arg.description, arg.typeDescriptor), deps);
128
+ return {
129
+ name: arg.propertyName,
130
+ required: !propInfo?.isOptional,
131
+ schema,
132
+ };
133
+ }),
121
134
  };
122
135
  }))
123
136
  .flat();
124
137
  }
125
138
  paramDescription(rawDescription, rawType) {
126
- let description = `
127
- ### description (in your main language)
128
- ${rawDescription.replaceAll('#', ' ')}
129
- `;
139
+ let description = rawDescription.replaceAll('#', ' ').trim();
130
140
  if (rawType === 'date') {
131
- description = `${description}
132
- ### format: ISO 8681 - YYYY-MM-DDTHH:mm:ssZ
133
- `;
141
+ description = `${description}\nFormat: ISO 8601 - YYYY-MM-DDTHH:mm:ssZ`;
134
142
  }
135
143
  return description;
136
144
  }
137
- paramType(rawType) {
138
- if (rawType === 'date')
139
- return 'string';
140
- return rawType;
141
- }
142
145
  async callFunction(name, params) {
143
146
  const fnMetadata = this.metadata.modules
144
147
  .map((module) => module.functions)
@@ -151,16 +154,37 @@ let MindsetOperator = class MindsetOperator {
151
154
  message: `Function '${name}' is not registered in mindset tools`,
152
155
  });
153
156
  }
157
+ let paramsObj;
154
158
  try {
155
- let paramsObj = JSON.parse(params);
156
- const modelValidationInfo = fnMetadata.argsValidatorsInfo;
157
- if (modelValidationInfo) {
158
- const validation = validateModel(paramsObj, modelValidationInfo);
159
- if (validation.error) {
160
- throw new CustomError({ message: 'IA Params Are invalid', info: validation.error });
161
- }
162
- paramsObj = validation.value;
159
+ paramsObj = JSON.parse(params);
160
+ }
161
+ catch (parseError) {
162
+ const aiResponse = JSON.stringify({
163
+ error: 'INVALID_JSON_ARGUMENTS',
164
+ message: 'The function call arguments are not valid JSON. Re-issue the call with a valid JSON object.',
165
+ details: parseError instanceof Error ? parseError.message : String(parseError),
166
+ });
167
+ this.logger.error(`Function '${name}' received non-JSON arguments`, { params, parseError });
168
+ return aiResponse;
169
+ }
170
+ const modelValidationInfo = fnMetadata.argsValidatorsInfo;
171
+ if (modelValidationInfo) {
172
+ const validation = validateModel(paramsObj, modelValidationInfo);
173
+ if (validation.error) {
174
+ const aiResponse = JSON.stringify({
175
+ error: 'INVALID_ARGUMENTS',
176
+ message: 'The provided arguments did not pass validation. Inspect the errors below and re-issue the call with corrected arguments.',
177
+ details: this.flattenValidationError(validation.error),
178
+ });
179
+ this.logger.warn(`Function '${name}' received invalid arguments`, {
180
+ params,
181
+ errors: validation.error,
182
+ });
183
+ return aiResponse;
163
184
  }
185
+ paramsObj = validation.value;
186
+ }
187
+ try {
164
188
  const module = this.container.resolve(fnMetadata.moduleConstructor);
165
189
  const response = await module[name](paramsObj);
166
190
  if (!response) {
@@ -179,6 +203,41 @@ let MindsetOperator = class MindsetOperator {
179
203
  return aiResponse;
180
204
  }
181
205
  }
206
+ flattenValidationError(error, path = '') {
207
+ const out = [];
208
+ if (!error)
209
+ return out;
210
+ if (Array.isArray(error?.items)) {
211
+ error.items.forEach((itemErrors, idx) => {
212
+ if (!itemErrors)
213
+ return;
214
+ const itemPath = `${path}[${idx}]`;
215
+ if (Array.isArray(itemErrors)) {
216
+ itemErrors.forEach((ie) => out.push(...this.flattenValidationError(ie, itemPath)));
217
+ }
218
+ else {
219
+ out.push(...this.flattenValidationError(itemErrors, itemPath));
220
+ }
221
+ });
222
+ if (out.length > 0)
223
+ return out;
224
+ }
225
+ if (error?.properties && typeof error.properties === 'object') {
226
+ for (const propName in error.properties) {
227
+ const propErrors = error.properties[propName];
228
+ const propPath = path ? `${path}.${propName}` : propName;
229
+ if (Array.isArray(propErrors)) {
230
+ propErrors.forEach((pe) => out.push(...this.flattenValidationError(pe, propPath)));
231
+ }
232
+ }
233
+ if (out.length > 0)
234
+ return out;
235
+ }
236
+ if (typeof error.description === 'string') {
237
+ out.push({ path: path || '(root)', message: error.description });
238
+ }
239
+ return out;
240
+ }
182
241
  async functionResponseToString(response) {
183
242
  if (response instanceof Response) {
184
243
  const contentType = response.headers.get('Content-Type') || '';
@@ -232,7 +291,8 @@ MindsetOperator = __decorate([
232
291
  injectable(),
233
292
  __metadata("design:paramtypes", [Mindset,
234
293
  Container,
235
- MindsetMetadataStore])
294
+ MindsetMetadataStore,
295
+ DescriptionMetadataStore])
236
296
  ], MindsetOperator);
237
297
 
238
298
  export { MindsetOperator };
@@ -0,0 +1,155 @@
1
+ import '../../core/injection/index.js';
2
+ import { validateModel } from '../../core/validation/core/validateModel.js';
3
+ import '../../core/validation/metadata/ValidationMetadataStore.js';
4
+ import { validateArray } from '../../core/validation/core/validateArray.js';
5
+ import { validateIsBoolean } from '../../core/validation/validators/is-boolean/validateIsBoolean.js';
6
+ import { validateIsDate } from '../../core/validation/validators/is-date/validateIsDate.js';
7
+ import { validateIsIn } from '../../core/validation/validators/is-in/validateIsIn.js';
8
+ import { validateIsNotEmpty } from '../../core/validation/validators/is-not-empty/validateIsNotEmpty.js';
9
+ import { validateIsNumber } from '../../core/validation/validators/is-number/validateIsNumber.js';
10
+ import { validateIsString } from '../../core/validation/validators/is-string/validateIsString.js';
11
+ import { validateMax } from '../../core/validation/validators/max/validateMax.js';
12
+ import { validateMin } from '../../core/validation/validators/min/validateMin.js';
13
+ import { validateIsRecord } from '../../core/validation/validators/is-record/validateIsRecord.js';
14
+
15
+ function buildPropertySchema(validators, description, deps) {
16
+ const schema = { type: 'string' };
17
+ if (description)
18
+ schema.description = description;
19
+ let typeAssigned = false;
20
+ for (const v of validators) {
21
+ const { validator, validatorOptions } = v;
22
+ if (validator === validateIsString) {
23
+ schema.type = 'string';
24
+ typeAssigned = true;
25
+ }
26
+ else if (validator === validateIsNumber) {
27
+ schema.type = 'number';
28
+ typeAssigned = true;
29
+ }
30
+ else if (validator === validateIsBoolean) {
31
+ schema.type = 'boolean';
32
+ typeAssigned = true;
33
+ }
34
+ else if (validator === validateIsDate) {
35
+ schema.type = 'string';
36
+ schema.format = 'date-time';
37
+ typeAssigned = true;
38
+ }
39
+ else if (validator === validateArray) {
40
+ schema.type = 'array';
41
+ typeAssigned = true;
42
+ const arrOpts = validatorOptions;
43
+ if (arrOpts?.minLength != null)
44
+ schema.minItems = arrOpts.minLength;
45
+ if (arrOpts?.maxLength != null)
46
+ schema.maxItems = arrOpts.maxLength;
47
+ if (arrOpts?.itemsValidator && arrOpts.itemsValidator.length > 0) {
48
+ const itemValidatorInfos = arrOpts.itemsValidator.map((iv, idx) => ({
49
+ propertyName: `__item_${idx}`,
50
+ validator: iv.validator,
51
+ validatorOptions: iv.options,
52
+ }));
53
+ schema.items = buildPropertySchema(itemValidatorInfos, undefined, deps);
54
+ }
55
+ else {
56
+ schema.items = { type: 'string' };
57
+ }
58
+ }
59
+ else if (validator === validateModel) {
60
+ const modelInfo = validatorOptions;
61
+ schema.type = 'object';
62
+ typeAssigned = true;
63
+ if (modelInfo) {
64
+ const built = buildModelSchema(modelInfo, deps);
65
+ schema.properties = built.properties;
66
+ if (built.required && built.required.length > 0) {
67
+ schema.required = built.required;
68
+ }
69
+ schema.additionalProperties = false;
70
+ }
71
+ }
72
+ else if (validator === validateIsRecord) {
73
+ schema.type = 'object';
74
+ typeAssigned = true;
75
+ const opts = validatorOptions;
76
+ if (opts) {
77
+ schema.additionalProperties = { type: opts.valueType };
78
+ }
79
+ }
80
+ else if (validator === validateIsIn) {
81
+ const opts = validatorOptions;
82
+ if (opts) {
83
+ schema.enum = [...opts.values];
84
+ if (!typeAssigned) {
85
+ const sample = opts.values.find((x) => x != null);
86
+ const t = typeof sample;
87
+ if (t === 'string' || t === 'number' || t === 'boolean') {
88
+ schema.type = t;
89
+ typeAssigned = true;
90
+ }
91
+ }
92
+ }
93
+ }
94
+ else if (validator === validateMin) {
95
+ const opts = validatorOptions;
96
+ const limit = opts && Number(opts.limit);
97
+ if (limit != null && !Number.isNaN(limit)) {
98
+ if (schema.type === 'string') {
99
+ schema.minLength = limit;
100
+ }
101
+ else if (schema.type === 'array') {
102
+ schema.minItems = limit;
103
+ }
104
+ else {
105
+ schema.minimum = limit;
106
+ }
107
+ }
108
+ }
109
+ else if (validator === validateMax) {
110
+ const opts = validatorOptions;
111
+ const limit = opts && Number(opts.limit);
112
+ if (limit != null && !Number.isNaN(limit)) {
113
+ if (schema.type === 'string') {
114
+ schema.maxLength = limit;
115
+ }
116
+ else if (schema.type === 'array') {
117
+ schema.maxItems = limit;
118
+ }
119
+ else {
120
+ schema.maximum = limit;
121
+ }
122
+ }
123
+ }
124
+ else if (validator === validateIsNotEmpty) {
125
+ if (schema.type === 'array') {
126
+ if (schema.minItems == null || schema.minItems < 1)
127
+ schema.minItems = 1;
128
+ }
129
+ else {
130
+ if (schema.minLength == null || schema.minLength < 1)
131
+ schema.minLength = 1;
132
+ }
133
+ }
134
+ }
135
+ return schema;
136
+ }
137
+ function buildModelSchema(modelInfo, deps) {
138
+ const properties = {};
139
+ const required = [];
140
+ const descriptions = deps.descriptionStore.getModelDescriptions(modelInfo.modelConstructor);
141
+ const descByName = new Map(descriptions.map((d) => [d.propertyName, d]));
142
+ for (const propertyName in modelInfo.properties) {
143
+ const propInfo = modelInfo.properties[propertyName];
144
+ if (!propInfo)
145
+ continue;
146
+ const desc = descByName.get(propertyName)?.description;
147
+ const schema = buildPropertySchema(propInfo.validators ?? [], desc, deps);
148
+ properties[propertyName] = schema;
149
+ if (!propInfo.isOptional)
150
+ required.push(propertyName);
151
+ }
152
+ return { properties, required };
153
+ }
154
+
155
+ export { buildModelSchema, buildPropertySchema };
@@ -1,6 +1,5 @@
1
1
  import { container } from '../../core/injection/index.js';
2
- import 'short-uuid';
3
- import '../../core/error/setupErrorHandlers.js';
2
+ import '../repository/MemoryRepositoryAdapter.js';
4
3
  import { RepositoryMetadataStore } from '../repository/RepositoryMetadataStore.js';
5
4
  import '../repository/RepositoryAdapterRegistry.js';
6
5
  import { PgRepositoryBase } from './PgRepositoryBase.js';
@@ -1,12 +1,80 @@
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
1
3
  import { generate } from 'short-uuid';
2
4
  import { CustomError } from '../../core/error/CustomError.js';
3
5
  import '../../core/error/setupErrorHandlers.js';
6
+ import { Logger } from '../../core/logger/Logger.js';
4
7
  import { evaluateQueryAst } from './evaluateQueryAst.js';
5
8
 
9
+ const DEFAULT_PERSIST_DIR = '.wabot/in-memory';
10
+ const DEFAULT_MAX_ITEMS = 32;
11
+ const logger = new Logger('wabot:memory-repository-adapter');
6
12
  function cloneEntity(config, item) {
7
13
  const data = JSON.parse(JSON.stringify(item['data']));
8
14
  return new config.constructor(data);
9
15
  }
16
+ class MemoryStore {
17
+ config;
18
+ persistOptions;
19
+ // Insertion order acts as LRU: most-recently-touched at the end.
20
+ items = new Map();
21
+ constructor(config, persistOptions) {
22
+ this.config = config;
23
+ this.persistOptions = persistOptions;
24
+ this.load();
25
+ }
26
+ touch(item) {
27
+ this.items.delete(item.id);
28
+ this.items.set(item.id, item);
29
+ }
30
+ enforceLimit() {
31
+ while (this.items.size > this.persistOptions.maxItems) {
32
+ const oldest = this.items.keys().next().value;
33
+ if (oldest === undefined)
34
+ break;
35
+ this.items.delete(oldest);
36
+ }
37
+ }
38
+ persist() {
39
+ if (!this.persistOptions.enabled)
40
+ return;
41
+ const file = this.filePath();
42
+ try {
43
+ fs.mkdirSync(path.dirname(file), { recursive: true });
44
+ const data = [...this.items.values()].map((i) => i['data']);
45
+ fs.writeFileSync(file, JSON.stringify(data, null, 2), 'utf-8');
46
+ }
47
+ catch (err) {
48
+ logger.warn(`Failed to persist ${file}:`, err);
49
+ }
50
+ }
51
+ load() {
52
+ if (!this.persistOptions.enabled)
53
+ return;
54
+ const file = this.filePath();
55
+ if (!fs.existsSync(file))
56
+ return;
57
+ try {
58
+ const raw = fs.readFileSync(file, 'utf-8');
59
+ const parsed = JSON.parse(raw);
60
+ if (!Array.isArray(parsed))
61
+ return;
62
+ for (const data of parsed) {
63
+ if (!data?.id)
64
+ continue;
65
+ const item = new this.config.constructor(data);
66
+ this.items.set(data.id, item);
67
+ }
68
+ this.enforceLimit();
69
+ }
70
+ catch (err) {
71
+ logger.warn(`Failed to load ${file}:`, err);
72
+ }
73
+ }
74
+ filePath() {
75
+ return path.resolve(process.cwd(), this.persistOptions.dir, `${this.config.table}.json`);
76
+ }
77
+ }
10
78
  class MemoryRepositoryExtension {
11
79
  items;
12
80
  config;
@@ -19,12 +87,15 @@ class MemoryRepositoryExtension {
19
87
  }
20
88
  }
21
89
  class MemoryRepositoryRuntime {
22
- items;
90
+ store;
23
91
  config;
24
- constructor(items, config) {
25
- this.items = items;
92
+ constructor(store, config) {
93
+ this.store = store;
26
94
  this.config = config;
27
95
  }
96
+ get items() {
97
+ return this.store.items;
98
+ }
28
99
  async find(id) {
29
100
  const item = this.items.get(id);
30
101
  return item ? cloneEntity(this.config, item) : null;
@@ -58,17 +129,22 @@ class MemoryRepositoryRuntime {
58
129
  item['data'].id = generate();
59
130
  item['data'].createdAt = new Date().getTime();
60
131
  item.validate();
61
- this.items.set(item.id, cloneEntity(this.config, item));
132
+ const stored = cloneEntity(this.config, item);
133
+ this.store.touch(stored);
134
+ this.store.enforceLimit();
135
+ this.store.persist();
62
136
  }
63
137
  async update(item) {
64
138
  item.validate();
65
139
  if (!this.items.has(item.id)) {
66
140
  throw new Error(`Update failed: no affected rows`);
67
141
  }
68
- this.items.set(item.id, cloneEntity(this.config, item));
142
+ this.store.touch(cloneEntity(this.config, item));
143
+ this.store.persist();
69
144
  }
70
145
  async delete(item) {
71
146
  this.items.delete(item.id);
147
+ this.store.persist();
72
148
  }
73
149
  async runQuery(ast, args) {
74
150
  const result = evaluateQueryAst(this.items.values(), ast, args);
@@ -85,16 +161,26 @@ class MemoryRepositoryRuntime {
85
161
  for (const item of matched) {
86
162
  this.items.delete(item.id);
87
163
  }
164
+ if (matched.length > 0)
165
+ this.store.persist();
88
166
  }
89
167
  }
90
168
  const MEMORY_ADAPTER_ID = Symbol('wabot:memory-adapter');
91
169
  class MemoryRepositoryAdapter {
92
170
  id = MEMORY_ADAPTER_ID;
93
171
  stores = new Map();
172
+ persistOptions;
173
+ constructor(options = {}) {
174
+ this.persistOptions = {
175
+ enabled: options.persist ?? true,
176
+ dir: options.dir ?? DEFAULT_PERSIST_DIR,
177
+ maxItems: options.maxItems ?? DEFAULT_MAX_ITEMS,
178
+ };
179
+ }
94
180
  getStore(config) {
95
181
  let store = this.stores.get(config);
96
182
  if (!store) {
97
- store = new Map();
183
+ store = new MemoryStore(config, this.persistOptions);
98
184
  this.stores.set(config, store);
99
185
  }
100
186
  return store;
@@ -103,7 +189,7 @@ class MemoryRepositoryAdapter {
103
189
  return new MemoryRepositoryRuntime(this.getStore(config), config);
104
190
  }
105
191
  buildExtension(config, ExtensionCtor) {
106
- return new ExtensionCtor(this.getStore(config), config);
192
+ return new ExtensionCtor(this.getStore(config).items, config);
107
193
  }
108
194
  }
109
195
 
@@ -867,10 +867,26 @@ declare class MindsetMetadataStore {
867
867
  };
868
868
  }
869
869
 
870
+ interface IMindsetParameterSchema {
871
+ type: 'string' | 'number' | 'integer' | 'boolean' | 'array' | 'object';
872
+ description?: string;
873
+ enum?: (string | number | boolean | null)[];
874
+ format?: string;
875
+ minimum?: number;
876
+ maximum?: number;
877
+ minLength?: number;
878
+ maxLength?: number;
879
+ minItems?: number;
880
+ maxItems?: number;
881
+ items?: IMindsetParameterSchema;
882
+ properties?: Record<string, IMindsetParameterSchema>;
883
+ required?: string[];
884
+ additionalProperties?: boolean | IMindsetParameterSchema;
885
+ }
870
886
  interface IMindsetToolParameter {
871
- type: string;
872
887
  name: string;
873
- description: string;
888
+ required: boolean;
889
+ schema: IMindsetParameterSchema;
874
890
  }
875
891
 
876
892
  interface IMindsetTool {
@@ -883,9 +899,10 @@ interface IMindsetTool {
883
899
  declare class MindsetOperator implements IMindset {
884
900
  private mindset;
885
901
  private container;
902
+ private descriptionStore;
886
903
  private logger;
887
904
  private metadata;
888
- constructor(mindset: Mindset, container: Container, metadataStore: MindsetMetadataStore);
905
+ constructor(mindset: Mindset, container: Container, metadataStore: MindsetMetadataStore, descriptionStore: DescriptionMetadataStore);
889
906
  context(): Promise<string>;
890
907
  identity(): Promise<IMindsetIdentity>;
891
908
  skills(): Promise<string>;
@@ -898,8 +915,8 @@ declare class MindsetOperator implements IMindset {
898
915
  systemPrompt(): Promise<string>;
899
916
  tools(): IMindsetTool[];
900
917
  protected paramDescription(rawDescription: string, rawType: string): string;
901
- protected paramType(rawType: string): string;
902
918
  callFunction(name: string, params: string): Promise<string>;
919
+ private flattenValidationError;
903
920
  functionResponseToString(response: any): Promise<string>;
904
921
  functionErrorToString(error: any): Promise<string>;
905
922
  }
@@ -1028,9 +1045,10 @@ declare class ChatBot implements IChatBot {
1028
1045
  private memory;
1029
1046
  private adapter;
1030
1047
  private mindset;
1048
+ private logger;
1031
1049
  constructor(memory: ChatMemory, adapter: ChatAdapter, mindset: MindsetOperator);
1032
1050
  sendMessage(message: IChatMessage, callback: (message: IChatMessage) => Promise<void>): Promise<void>;
1033
- protected processLoop(callback: (message: IChatMessage) => Promise<void>): Promise<void>;
1051
+ protected processLoop(callback: (message: IChatMessage) => Promise<void>, invalidArgsCount: number): Promise<void>;
1034
1052
  }
1035
1053
 
1036
1054
  interface IChatRepository {
@@ -1373,6 +1391,11 @@ interface IRepositoryAdapter {
1373
1391
  buildExtension?<E>(config: IRepositoryConfig<any>, ExtensionCtor: IConstructor<E>): E;
1374
1392
  }
1375
1393
 
1394
+ interface IMemoryRepositoryAdapterOptions {
1395
+ persist?: boolean;
1396
+ dir?: string;
1397
+ maxItems?: number;
1398
+ }
1376
1399
  declare class MemoryRepositoryExtension<P extends Entity<IEntityData>> {
1377
1400
  protected readonly items: Map<string, P>;
1378
1401
  protected readonly config: IRepositoryConfig<P>;
@@ -1383,6 +1406,8 @@ declare const MEMORY_ADAPTER_ID: unique symbol;
1383
1406
  declare class MemoryRepositoryAdapter implements IRepositoryAdapter {
1384
1407
  readonly id: symbol;
1385
1408
  private stores;
1409
+ private readonly persistOptions;
1410
+ constructor(options?: IMemoryRepositoryAdapterOptions);
1386
1411
  private getStore;
1387
1412
  build<P extends Entity<IEntityData>>(config: IRepositoryConfig<P>): IRepositoryRuntime<P>;
1388
1413
  buildExtension<E>(config: IRepositoryConfig<any>, ExtensionCtor: IConstructor<E>): E;
@@ -1645,6 +1670,7 @@ declare class PgTransactionAdapter implements ITransactionAdapter {
1645
1670
 
1646
1671
  declare class InMemoryJobRepository implements IJobRepository {
1647
1672
  private items;
1673
+ constructor();
1648
1674
  find(id: string): Promise<Job | null>;
1649
1675
  findOrThrow(id: string): Promise<Job>;
1650
1676
  findByIds(ids: string[]): Promise<Job[]>;
@@ -1655,15 +1681,26 @@ declare class InMemoryJobRepository implements IJobRepository {
1655
1681
  findPendingForRunFrom(date: Date, limit: number): Promise<Job[]>;
1656
1682
  findRunningJobs(): Promise<Job[]>;
1657
1683
  countRunningByCommand(commandName: string): Promise<number>;
1684
+ private touch;
1685
+ private enforceLimit;
1686
+ private filePath;
1687
+ private load;
1688
+ private persist;
1658
1689
  }
1659
1690
 
1660
1691
  declare class InMemoryCronJobRepository implements ICronJobRepository {
1661
1692
  private items;
1693
+ constructor();
1662
1694
  create(cronJob: CronJob): Promise<void>;
1663
1695
  findDue(date?: Date): Promise<CronJob[]>;
1664
1696
  findOrThrow(id: string): Promise<CronJob>;
1665
1697
  update(cronJob: CronJob): Promise<void>;
1666
1698
  findByName(name: string): Promise<CronJob | null>;
1699
+ private touch;
1700
+ private enforceLimit;
1701
+ private filePath;
1702
+ private load;
1703
+ private persist;
1667
1704
  }
1668
1705
 
1669
1706
  declare function apiKeyHandshakeGuard(): (target: IConstructor<any>) => void;
@@ -2138,9 +2175,9 @@ declare class SocketChannel implements IChatChannel {
2138
2175
  }
2139
2176
 
2140
2177
  interface ITelegramChannelConfig {
2141
- botToken: string;
2178
+ botToken: string | ConfigReference<string>;
2142
2179
  }
2143
- declare class TelegramChannelConfig implements ITelegramChannelConfig {
2180
+ declare class TelegramChannelConfig {
2144
2181
  botToken: string;
2145
2182
  constructor(botToken: string);
2146
2183
  }
@@ -2168,6 +2205,8 @@ declare class TelegramChannel implements IChatChannel {
2168
2205
  disconnect(): void;
2169
2206
  }
2170
2207
 
2208
+ declare function markdownToTelegramHtml(input: string): string;
2209
+
2171
2210
  interface IWhatsAppCloudTemplateResponse {
2172
2211
  data: IWhatsAppCloudTemplate[];
2173
2212
  paging: IWhatsAppCloudApiPaging;
@@ -2485,4 +2524,4 @@ declare function HtmlModule(options: IHtmlModuleOptions): {
2485
2524
  new (): {};
2486
2525
  };
2487
2526
 
2488
- export { AnthropicChatAdapter, ApiKey, ApiKeyGuardMiddleware, ApiKeyHandshakeGuardMiddleware, ApiKeyRepository, Async, AsyncMetadataStore, Auth, Chat, ChatAdapter, ChatAdapterMetadataStore, ChatAdapterRegistry, ChatBot, ChatBotMetadataStore, ChatItem, ChatMemory, ChatOperator, ChatRepository, ChatResolver, type ClientMap, CmdChannel, CmdChannelConfig, CmdChannelServer, type CmdClientMessage, type CmdServerMessage, type ConfigReference, type ConfigReferenceType, ConfigResolver, Container, ControllerMetadataStore, CronJob, CronJobRepository, CrudRepository, CustomError, DeepSeekChatAdapter, DescriptionMetadataStore, EXPRESS_REQ, EXPRESS_RES, Entity, Env, type ErrorSeverity, ExpressProvider, GoogleChatAdapter, type GoogleChatAdapterV2Options, HtmlModule, HttpServerProvider, type IApiKeyData, type IApiKeyRepository, type IArrayValidationError, type IArrayValidationResult, type IBotMessageItem, type IBuiltQuery, type IChannelMessage, type IChannelMetadata, type IChatAdapter, type IChatAdapterDecoratorConfig, type IChatAdapterMetadata, type IChatAdapterNextItemsReq, type IChatAdapterNextItemsRes, type IChatAssociation, type IChatBot, type IChatBotMetadata, type IChatChannel, type IChatConnection, type IChatControllerMetadata, type IChatData, type IChatItem, type IChatItemData, type IChatItemType, type IChatMemory, type IChatMessage, type IChatMessageDocument, type IChatMessageFile, type IChatMessageImage, type IChatMessagesPrivateFile, type IChatMessagesPublicFile, type IChatRepository, type IChatType, type ICmdChannelEntry, type ICmdChannelHandlers, type ICmdChannelMessage, type ICmdReceivedMessage, type ICommandConfig, type ICommandHandler, type ICommandHandlerConfig, type IConstructor, type ICronConfig, type ICronHandler, type ICronJobData, type ICronJobRepository, type ICrudRepository, type ICustomErrorData, type IDescriptionMetadata, type IEndPointConfig, type IEndPointMetadata, type IEntityData, type IEnvType, type IErrorHandlersConfig, type IErrorMonitor, type IErrorMonitorContext, type IExtractChatMessageTextOptions, type IFunctionCall, type IFunctionCallItem, type IGenerateApiKeyReq, type IGenerateApiKeyRes, type IHandshakeMiddleware, type IHandshakeMiddlewareMetadata, type IHtmlModuleOptions, type IHumanMessageItem, type IJobData, type IJobRepository, type IJwtRefreshTokenData, type IJwtRefreshTokenRepository, type ILanguageModelUsage, type ILockKey, type ILocker, type ILockerKey, type IMessageContext, type IMiddleware, type IMiddlewareMetadata, type IMindset, type IMindsetConfig, type IMindsetIdentity, type IMindsetLlm, type IMindsetMetadata, type IMindsetModelKind, type IMindsetModelRef, type IMindsetModels, type IMindsetModuleConfig, type IMindsetModuleMetadata, type IMindsetTool, type IMindsetToolParameter, type IModelValidationError, type IModelValidationResult, type IModelValidatorsInfo, type IMoneyData, type IPersistentData, type IPgRepositoryConfig, type IProjectRunnerConfig, type IPropertyValidatorInfo, type IQueryAst, type IQueryCondition, type IQueryMethodMetadata, type IQueryOrderBy, type IReceivedMessage, type IRemoteApiKeyFetcher, type IRepositoryAdapter, type IRepositoryConfig, type IRepositoryRuntime, type IRestControllerConfig, type IRestControllerMetadata, type IScanProjectFilesOptions, type IScheduleAt, type IScheduleDelay, type ISendWhatsAppMessageReq, type ISendWhatsAppTemplateReq, type ISocketChannelConfig, type ISocketChannelMessage, type ISocketChannelReceivedMessage, type ISocketControllerConfig, type ISocketControllerMetadata, type ISocketEventConfig, type ISocketEventMetadata, type ISocketReceivedMessage, type IStorableData, type ITelegramChannelConfig, type ITelegramChannelMessage, type ITelegramReceivedMessage, type ITransactionAdapter, type IValidateArrayOptions, type IValidateArrayOptionsWithItemsValidators, type IValidateInputShape, type IValidateIsInOptions, type IValidateIsRecordOptions, type IValidateMaxOptions, type IValidateMinOptions, type IValidationError, type IValidationResult, type IValidator, type IValidatorMetadata, type IWasenderChannelConfig, type IWasenderChannelMessageListener, type IWasenderDeviceListMetadata, type IWasenderEvent, type IWasenderMessageContent, type IWasenderMessageContextInfo, type IWasenderMessageKey, type IWasenderMessageReceivedData, type IWasenderMessageReceivedEvent, type IWasenderQrUpdatedEvent, type IWasenderReceivedMessage, type IWhatsAppCloudContact, type IWhatsAppCloudMessage, type IWhatsAppCloudMessageMetadata, type IWhatsAppCloudTemplate, type IWhatsAppCloudTemplateComponent, type IWhatsAppCloudTemplateResponse, type IWhatsAppCloudWebhookPayload, type IWhatsAppSender, type IWhatsAppTemplateData, type IWhatsAppTemplateParameter, type IchatControllerConfig, InMemoryChatMemory, InMemoryChatRepository, InMemoryCronJobRepository, InMemoryJobRepository, InMemoryLockKey, InMemoryLocker, Job, JobRepository, JobRunner, Jwt, JwtAccessAndRefreshTokenDto, JwtConfig, JwtGuardMiddleware, JwtHandshakeGuardMiddleware, JwtRefreshToken, JwtRefreshTokenRepository, JwtSigner, JwtTokenDto, Lifecycle, Locker, Logger, MEMORY_ADAPTER_ID, Mapper, MemoryRepositoryAdapter, MemoryRepositoryExtension, Mindset, MindsetMetadataStore, MindsetOperator, Money, MoneyDto, OpenRouterChatAdapter, OpenaiChatAdapter, PG_ADAPTER_ID, Password, type PasswordHashOptions, Persistent, PgApiKeyRepository, PgChatMemory, PgChatRepository, PgCronJobRepository, PgCrudRepository, PgJobRepository, PgJsonRepositoryAdapter, PgJwtRefreshTokenRepository, PgLockKey, PgLocker, PgRepositoryBase, PgRepositoryBase as PgRepositoryExtension, PgTransactionAdapter, ProjectRunner, type QueryConnector, type QueryOperator, type QueryPrefix, Random, RemoteApiKeyRepository, RepositoryAdapterRegistry, RepositoryMetadataStore, type ResolvedConfig, RestControllerMetadataStore, RestRequest, SocketChannel, SocketChannelConfig, SocketChannelMessageFile, SocketChannelReceivedMessage, SocketControllerMetadataStore, SocketServerConfig, SocketServerProvider, Storable, TelegramChannel, TelegramChannelConfig, TransactionMetadataStore, UnionChatAdapter, ValidationMetadataStore, WabotChatAdapter, WasenderChannel, WasenderChannelConfig, WasenderReceiver, WasenderSender, WasenderWebhookController, WhatsAppApiSender, WhatsAppReceiverByCloudApi, WhatsAppSender, apiKeyGuard, apiKeyHandshakeGuard, bool, boolArr, buildQuerySql, chatAdapter, chatBot, chatController, chatItemTypeOptions, cmd, cmdChannelName, cmdChannelSocketPath, command, commandHandler, container, cronHandler, description, errorToPlainObject, evaluateQueryAst, extractChatMessageText, extractNumberFromWasenderMessageKey, getClientMap, getPgClient, handshakeMiddlewares, inject, injectable, isArray, isBoolean, isChatMessageEmpty, isDate, isIn, isModel, isNotEmpty, isNumber, isOptional, isPresent, isRecord, isRetryableError, isString, jwtGuard, jwtHandshakeGuard, max, memExtension, middleware, min, mindset, mindsetModule, modelInfo, num, numArr, obj, onDelete, onGet, onPost, onPut, onSocketEvent, parseQueryMethodName, pgExtension, pgStorage, query, queryExtension, readJsonFromFile, repository, resolveConfigReferences, restController, run, runChatAdapters, runChatControllers, runCmdClient, runCommandHandlers, runCronHandlers, runRestControllers, runSocketControllers, safeJsonParse, scanProjectFiles, scoped, setupErrorHandlers, singleton, socket, socketChannelName, socketController, stopCommandHandlers, stopCronHandlers, str, strArr, telegram, telegramChannelName, transaction, validateAndTransform, validateArray, validateIsBoolean, validateIsDate, validateIsIn, validateIsNotEmpty, validateIsNumber, validateIsPresent, validateIsRecord, validateIsString, validateMax, validateMin, validateModel, wasender, wasenderChannelName, withPgClient, withPgTransaction, writeJsonToFile };
2527
+ export { AnthropicChatAdapter, ApiKey, ApiKeyGuardMiddleware, ApiKeyHandshakeGuardMiddleware, ApiKeyRepository, Async, AsyncMetadataStore, Auth, Chat, ChatAdapter, ChatAdapterMetadataStore, ChatAdapterRegistry, ChatBot, ChatBotMetadataStore, ChatItem, ChatMemory, ChatOperator, ChatRepository, ChatResolver, type ClientMap, CmdChannel, CmdChannelConfig, CmdChannelServer, type CmdClientMessage, type CmdServerMessage, type ConfigReference, type ConfigReferenceType, ConfigResolver, Container, ControllerMetadataStore, CronJob, CronJobRepository, CrudRepository, CustomError, DeepSeekChatAdapter, DescriptionMetadataStore, EXPRESS_REQ, EXPRESS_RES, Entity, Env, type ErrorSeverity, ExpressProvider, GoogleChatAdapter, type GoogleChatAdapterV2Options, HtmlModule, HttpServerProvider, type IApiKeyData, type IApiKeyRepository, type IArrayValidationError, type IArrayValidationResult, type IBotMessageItem, type IBuiltQuery, type IChannelMessage, type IChannelMetadata, type IChatAdapter, type IChatAdapterDecoratorConfig, type IChatAdapterMetadata, type IChatAdapterNextItemsReq, type IChatAdapterNextItemsRes, type IChatAssociation, type IChatBot, type IChatBotMetadata, type IChatChannel, type IChatConnection, type IChatControllerMetadata, type IChatData, type IChatItem, type IChatItemData, type IChatItemType, type IChatMemory, type IChatMessage, type IChatMessageDocument, type IChatMessageFile, type IChatMessageImage, type IChatMessagesPrivateFile, type IChatMessagesPublicFile, type IChatRepository, type IChatType, type ICmdChannelEntry, type ICmdChannelHandlers, type ICmdChannelMessage, type ICmdReceivedMessage, type ICommandConfig, type ICommandHandler, type ICommandHandlerConfig, type IConstructor, type ICronConfig, type ICronHandler, type ICronJobData, type ICronJobRepository, type ICrudRepository, type ICustomErrorData, type IDescriptionMetadata, type IEndPointConfig, type IEndPointMetadata, type IEntityData, type IEnvType, type IErrorHandlersConfig, type IErrorMonitor, type IErrorMonitorContext, type IExtractChatMessageTextOptions, type IFunctionCall, type IFunctionCallItem, type IGenerateApiKeyReq, type IGenerateApiKeyRes, type IHandshakeMiddleware, type IHandshakeMiddlewareMetadata, type IHtmlModuleOptions, type IHumanMessageItem, type IJobData, type IJobRepository, type IJwtRefreshTokenData, type IJwtRefreshTokenRepository, type ILanguageModelUsage, type ILockKey, type ILocker, type ILockerKey, type IMemoryRepositoryAdapterOptions, type IMessageContext, type IMiddleware, type IMiddlewareMetadata, type IMindset, type IMindsetConfig, type IMindsetIdentity, type IMindsetLlm, type IMindsetMetadata, type IMindsetModelKind, type IMindsetModelRef, type IMindsetModels, type IMindsetModuleConfig, type IMindsetModuleMetadata, type IMindsetParameterSchema, type IMindsetTool, type IMindsetToolParameter, type IModelValidationError, type IModelValidationResult, type IModelValidatorsInfo, type IMoneyData, type IPersistentData, type IPgRepositoryConfig, type IProjectRunnerConfig, type IPropertyValidatorInfo, type IQueryAst, type IQueryCondition, type IQueryMethodMetadata, type IQueryOrderBy, type IReceivedMessage, type IRemoteApiKeyFetcher, type IRepositoryAdapter, type IRepositoryConfig, type IRepositoryRuntime, type IRestControllerConfig, type IRestControllerMetadata, type IScanProjectFilesOptions, type IScheduleAt, type IScheduleDelay, type ISendWhatsAppMessageReq, type ISendWhatsAppTemplateReq, type ISocketChannelConfig, type ISocketChannelMessage, type ISocketChannelReceivedMessage, type ISocketControllerConfig, type ISocketControllerMetadata, type ISocketEventConfig, type ISocketEventMetadata, type ISocketReceivedMessage, type IStorableData, type ITelegramChannelConfig, type ITelegramChannelMessage, type ITelegramReceivedMessage, type ITransactionAdapter, type IValidateArrayOptions, type IValidateArrayOptionsWithItemsValidators, type IValidateInputShape, type IValidateIsInOptions, type IValidateIsRecordOptions, type IValidateMaxOptions, type IValidateMinOptions, type IValidationError, type IValidationResult, type IValidator, type IValidatorMetadata, type IWasenderChannelConfig, type IWasenderChannelMessageListener, type IWasenderDeviceListMetadata, type IWasenderEvent, type IWasenderMessageContent, type IWasenderMessageContextInfo, type IWasenderMessageKey, type IWasenderMessageReceivedData, type IWasenderMessageReceivedEvent, type IWasenderQrUpdatedEvent, type IWasenderReceivedMessage, type IWhatsAppCloudContact, type IWhatsAppCloudMessage, type IWhatsAppCloudMessageMetadata, type IWhatsAppCloudTemplate, type IWhatsAppCloudTemplateComponent, type IWhatsAppCloudTemplateResponse, type IWhatsAppCloudWebhookPayload, type IWhatsAppSender, type IWhatsAppTemplateData, type IWhatsAppTemplateParameter, type IchatControllerConfig, InMemoryChatMemory, InMemoryChatRepository, InMemoryCronJobRepository, InMemoryJobRepository, InMemoryLockKey, InMemoryLocker, Job, JobRepository, JobRunner, Jwt, JwtAccessAndRefreshTokenDto, JwtConfig, JwtGuardMiddleware, JwtHandshakeGuardMiddleware, JwtRefreshToken, JwtRefreshTokenRepository, JwtSigner, JwtTokenDto, Lifecycle, Locker, Logger, MEMORY_ADAPTER_ID, Mapper, MemoryRepositoryAdapter, MemoryRepositoryExtension, Mindset, MindsetMetadataStore, MindsetOperator, Money, MoneyDto, OpenRouterChatAdapter, OpenaiChatAdapter, PG_ADAPTER_ID, Password, type PasswordHashOptions, Persistent, PgApiKeyRepository, PgChatMemory, PgChatRepository, PgCronJobRepository, PgCrudRepository, PgJobRepository, PgJsonRepositoryAdapter, PgJwtRefreshTokenRepository, PgLockKey, PgLocker, PgRepositoryBase, PgRepositoryBase as PgRepositoryExtension, PgTransactionAdapter, ProjectRunner, type QueryConnector, type QueryOperator, type QueryPrefix, Random, RemoteApiKeyRepository, RepositoryAdapterRegistry, RepositoryMetadataStore, type ResolvedConfig, RestControllerMetadataStore, RestRequest, SocketChannel, SocketChannelConfig, SocketChannelMessageFile, SocketChannelReceivedMessage, SocketControllerMetadataStore, SocketServerConfig, SocketServerProvider, Storable, TelegramChannel, TelegramChannelConfig, TransactionMetadataStore, UnionChatAdapter, ValidationMetadataStore, WabotChatAdapter, WasenderChannel, WasenderChannelConfig, WasenderReceiver, WasenderSender, WasenderWebhookController, WhatsAppApiSender, WhatsAppReceiverByCloudApi, WhatsAppSender, apiKeyGuard, apiKeyHandshakeGuard, bool, boolArr, buildQuerySql, chatAdapter, chatBot, chatController, chatItemTypeOptions, cmd, cmdChannelName, cmdChannelSocketPath, command, commandHandler, container, cronHandler, description, errorToPlainObject, evaluateQueryAst, extractChatMessageText, extractNumberFromWasenderMessageKey, getClientMap, getPgClient, handshakeMiddlewares, inject, injectable, isArray, isBoolean, isChatMessageEmpty, isDate, isIn, isModel, isNotEmpty, isNumber, isOptional, isPresent, isRecord, isRetryableError, isString, jwtGuard, jwtHandshakeGuard, markdownToTelegramHtml, max, memExtension, middleware, min, mindset, mindsetModule, modelInfo, num, numArr, obj, onDelete, onGet, onPost, onPut, onSocketEvent, parseQueryMethodName, pgExtension, pgStorage, query, queryExtension, readJsonFromFile, repository, resolveConfigReferences, restController, run, runChatAdapters, runChatControllers, runCmdClient, runCommandHandlers, runCronHandlers, runRestControllers, runSocketControllers, safeJsonParse, scanProjectFiles, scoped, setupErrorHandlers, singleton, socket, socketChannelName, socketController, stopCommandHandlers, stopCronHandlers, str, strArr, telegram, telegramChannelName, transaction, validateAndTransform, validateArray, validateIsBoolean, validateIsDate, validateIsIn, validateIsNotEmpty, validateIsNumber, validateIsPresent, validateIsRecord, validateIsString, validateMax, validateMin, validateModel, wasender, wasenderChannelName, withPgClient, withPgTransaction, writeJsonToFile };
package/dist/src/index.js CHANGED
@@ -177,6 +177,7 @@ export { telegram } from './addon/chat-controller/telegram/@telegram.js';
177
177
  export { TelegramChannelConfig } from './addon/chat-controller/telegram/TelegramChannelConfig.js';
178
178
  export { TelegramChannel } from './addon/chat-controller/telegram/TelegramChannel.js';
179
179
  export { telegramChannelName } from './addon/chat-controller/telegram/telegramChannelName.js';
180
+ export { markdownToTelegramHtml } from './addon/chat-controller/telegram/markdownToTelegramHtml.js';
180
181
  export { WhatsAppReceiverByCloudApi } from './addon/chat-controller/whatsapp/cloud-api/WhatsAppReceiverByCloudApi.js';
181
182
  export { WhatsAppApiSender } from './addon/chat-controller/whatsapp/cloud-api/WhatsAppApiSender.js';
182
183
  export { wasender } from './addon/chat-controller/whatsapp/wasender/@wasender.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wabot-dev/framework",
3
- "version": "0.9.17",
3
+ "version": "0.9.19",
4
4
  "description": "Framework for IA Chat Bots",
5
5
  "type": "module",
6
6
  "main": "dist/src/index.js",