@adonis-agora/agent 0.62.0 → 0.63.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/CHANGELOG.md +29 -0
- package/dist/providers/agent_provider.d.ts.map +1 -1
- package/dist/providers/agent_provider.js +1 -12
- package/dist/providers/agent_provider.js.map +1 -1
- package/dist/src/action-proposal-service.d.ts +3 -2
- package/dist/src/action-proposal-service.d.ts.map +1 -1
- package/dist/src/action-proposal-service.js +1 -0
- package/dist/src/action-proposal-service.js.map +1 -1
- package/dist/src/actor-resolver.d.ts +12 -4
- package/dist/src/actor-resolver.d.ts.map +1 -1
- package/dist/src/actor-resolver.js +24 -7
- package/dist/src/actor-resolver.js.map +1 -1
- package/dist/src/ag-ui/adapter.d.ts.map +1 -1
- package/dist/src/ag-ui/adapter.js +32 -6
- package/dist/src/ag-ui/adapter.js.map +1 -1
- package/dist/src/ag-ui/core/encoder.d.ts +2 -1
- package/dist/src/ag-ui/core/encoder.d.ts.map +1 -1
- package/dist/src/ag-ui/core/encoder.js +16 -5
- package/dist/src/ag-ui/core/encoder.js.map +1 -1
- package/dist/src/ag-ui/core/index.d.ts +2 -2
- package/dist/src/ag-ui/core/index.d.ts.map +1 -1
- package/dist/src/ag-ui/core/index.js +2 -2
- package/dist/src/ag-ui/core/index.js.map +1 -1
- package/dist/src/ag-ui/core/input.d.ts +21 -3
- package/dist/src/ag-ui/core/input.d.ts.map +1 -1
- package/dist/src/ag-ui/core/input.js +24 -6
- package/dist/src/ag-ui/core/input.js.map +1 -1
- package/dist/src/ag-ui/core/stream.d.ts +24 -2
- package/dist/src/ag-ui/core/stream.d.ts.map +1 -1
- package/dist/src/ag-ui/core/stream.js +25 -3
- package/dist/src/ag-ui/core/stream.js.map +1 -1
- package/dist/src/ag-ui/core/types.d.ts +2 -2
- package/dist/src/ag-ui/core/types.d.ts.map +1 -1
- package/dist/src/ag-ui/core/types.js +2 -2
- package/dist/src/ag-ui/core/types.js.map +1 -1
- package/dist/src/ag-ui/frames.d.ts +5 -1
- package/dist/src/ag-ui/frames.d.ts.map +1 -1
- package/dist/src/ag-ui/frames.js +13 -3
- package/dist/src/ag-ui/frames.js.map +1 -1
- package/dist/src/ag-ui/index.d.ts +1 -1
- package/dist/src/ag-ui/index.d.ts.map +1 -1
- package/dist/src/ag-ui/index.js +1 -1
- package/dist/src/ag-ui/index.js.map +1 -1
- package/dist/src/agent-service.d.ts +36 -3
- package/dist/src/agent-service.d.ts.map +1 -1
- package/dist/src/agent-service.js +65 -1
- package/dist/src/agent-service.js.map +1 -1
- package/dist/src/attachment-limits.d.ts +10 -0
- package/dist/src/attachment-limits.d.ts.map +1 -0
- package/dist/src/attachment-limits.js +13 -0
- package/dist/src/attachment-limits.js.map +1 -0
- package/dist/src/channels/adapters/evolution_api.d.ts +49 -0
- package/dist/src/channels/adapters/evolution_api.d.ts.map +1 -0
- package/dist/src/channels/adapters/evolution_api.js +241 -0
- package/dist/src/channels/adapters/evolution_api.js.map +1 -0
- package/dist/src/channels/adapters/telegram.d.ts +34 -0
- package/dist/src/channels/adapters/telegram.d.ts.map +1 -0
- package/dist/src/channels/adapters/telegram.js +196 -0
- package/dist/src/channels/adapters/telegram.js.map +1 -0
- package/dist/src/channels/adapters/whatsapp_cloud.d.ts +31 -0
- package/dist/src/channels/adapters/whatsapp_cloud.d.ts.map +1 -0
- package/dist/src/channels/adapters/whatsapp_cloud.js +177 -0
- package/dist/src/channels/adapters/whatsapp_cloud.js.map +1 -0
- package/dist/src/channels/handler.d.ts +167 -0
- package/dist/src/channels/handler.d.ts.map +1 -0
- package/dist/src/channels/handler.js +569 -0
- package/dist/src/channels/handler.js.map +1 -0
- package/dist/src/channels/http.d.ts +45 -0
- package/dist/src/channels/http.d.ts.map +1 -0
- package/dist/src/channels/http.js +147 -0
- package/dist/src/channels/http.js.map +1 -0
- package/dist/src/channels/index.d.ts +16 -0
- package/dist/src/channels/index.d.ts.map +1 -0
- package/dist/src/channels/index.js +15 -0
- package/dist/src/channels/index.js.map +1 -0
- package/dist/src/channels/markdown.d.ts +12 -0
- package/dist/src/channels/markdown.d.ts.map +1 -0
- package/dist/src/channels/markdown.js +120 -0
- package/dist/src/channels/markdown.js.map +1 -0
- package/dist/src/channels/questions.d.ts +43 -0
- package/dist/src/channels/questions.d.ts.map +1 -0
- package/dist/src/channels/questions.js +90 -0
- package/dist/src/channels/questions.js.map +1 -0
- package/dist/src/channels/split.d.ts +8 -0
- package/dist/src/channels/split.d.ts.map +1 -0
- package/dist/src/channels/split.js +45 -0
- package/dist/src/channels/split.js.map +1 -0
- package/dist/src/channels/store.d.ts +78 -0
- package/dist/src/channels/store.d.ts.map +1 -0
- package/dist/src/channels/store.js +151 -0
- package/dist/src/channels/store.js.map +1 -0
- package/dist/src/channels/types.d.ts +138 -0
- package/dist/src/channels/types.d.ts.map +1 -0
- package/dist/src/channels/types.js +7 -0
- package/dist/src/channels/types.js.map +1 -0
- package/dist/src/genui/builtins.d.ts.map +1 -1
- package/dist/src/genui/builtins.js +65 -6
- package/dist/src/genui/builtins.js.map +1 -1
- package/dist/src/genui/catalog.d.ts +11 -2
- package/dist/src/genui/catalog.d.ts.map +1 -1
- package/dist/src/genui/catalog.js +8 -0
- package/dist/src/genui/catalog.js.map +1 -1
- package/dist/src/genui/text.d.ts +4 -3
- package/dist/src/genui/text.d.ts.map +1 -1
- package/dist/src/genui/text.js +25 -24
- package/dist/src/genui/text.js.map +1 -1
- package/dist/src/genui/tools.d.ts +2 -1
- package/dist/src/genui/tools.d.ts.map +1 -1
- package/dist/src/genui/tools.js +6 -7
- package/dist/src/genui/tools.js.map +1 -1
- package/dist/src/index.d.ts +3 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +3 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/opencode/turns.d.ts +4 -2
- package/dist/src/opencode/turns.d.ts.map +1 -1
- package/dist/src/opencode/turns.js.map +1 -1
- package/dist/src/react/core/ag-ui-backend.d.ts +38 -14
- package/dist/src/react/core/ag-ui-backend.d.ts.map +1 -1
- package/dist/src/react/core/ag-ui-backend.js +182 -17
- package/dist/src/react/core/ag-ui-backend.js.map +1 -1
- package/dist/src/react/core/agent-chat-transport.d.ts.map +1 -1
- package/dist/src/react/core/agent-chat-transport.js +22 -1
- package/dist/src/react/core/agent-chat-transport.js.map +1 -1
- package/dist/src/react/core/backend.d.ts +11 -0
- package/dist/src/react/core/backend.d.ts.map +1 -1
- package/dist/src/react/core/backend.js.map +1 -1
- package/dist/src/react/core/index.d.ts +1 -1
- package/dist/src/react/core/index.d.ts.map +1 -1
- package/dist/src/react/core/index.js.map +1 -1
- package/dist/src/stores/lucid-schema.d.ts +24 -6
- package/dist/src/stores/lucid-schema.d.ts.map +1 -1
- package/dist/src/stores/lucid-schema.js +47 -6
- package/dist/src/stores/lucid-schema.js.map +1 -1
- package/dist/src/stores/lucid.d.ts +2 -0
- package/dist/src/stores/lucid.d.ts.map +1 -1
- package/dist/src/stores/lucid.js +4 -0
- package/dist/src/stores/lucid.js.map +1 -1
- package/package.json +6 -1
- package/skills/agent-setup/SKILL.md +39 -3
- package/skills/agent-tools/SKILL.md +3 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../../src/channels/http.ts"],"names":[],"mappings":"AAEA,wGAAwG;AACxG,qBAAa,oBAAqB,SAAQ,KAAK;IAE3C,QAAQ,CAAC,OAAO,EAAE,MAAM;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAFhC,YACW,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,GAAG,IAAI,EAC9B,OAAO,EAAE,MAAM,EAIhB;IAED;;;OAGG;IACH,IAAI,QAAQ,IAAI,OAAO,CAEtB;CACF;AAED,kFAAkF;AAClF,qBAAa,yBAA0B,SAAQ,KAAK;IACtC,QAAQ,CAAC,QAAQ,EAAE,MAAM;IAArC,YAAqB,QAAQ,EAAE,MAAM,EAGpC;CACF;AAED;;;GAGG;AACH,wBAAsB,UAAU,CAC9B,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,YAAY,EACrB,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAAC,CA+C5D;AAED,0EAA0E;AAC1E,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAOrE;AAED,wGAAwG;AACxG,wBAAgB,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAOzD;AAED,gGAAgG;AAChG,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAIxF;AAED,6FAA6F;AAC7F,MAAM,MAAM,YAAY,GAAG,OAAO,KAAK,CAAC;AAExC;;;;GAIG;AACH,wBAAsB,QAAQ,CAC5B,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,YAAY,EACrB,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,IAAI,EAAE,OAAO,EACb,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,OAAO,CAAC,CA8BlB;AAED,mDAAmD;AACnD,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAIxE;AAED,gGAAgG;AAChG,wBAAgB,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAI1E;AAED,6CAA6C;AAC7C,wBAAgB,GAAG,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAEtD"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { createHash, timingSafeEqual } from 'node:crypto';
|
|
2
|
+
/** A provider refused (or could not be reached for) a delivery. `status` is its HTTP status, if any. */
|
|
3
|
+
export class ChannelDeliveryError extends Error {
|
|
4
|
+
channel;
|
|
5
|
+
status;
|
|
6
|
+
constructor(channel, status, message) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.channel = channel;
|
|
9
|
+
this.status = status;
|
|
10
|
+
this.name = 'ChannelDeliveryError';
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* The provider answered and said no (400, 403, 404, 422): the message was certainly not delivered,
|
|
14
|
+
* so sending something else in its place cannot duplicate it.
|
|
15
|
+
*/
|
|
16
|
+
get definite() {
|
|
17
|
+
return this.status !== null && [400, 403, 404, 422].includes(this.status);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/** A file was larger than the attachment limit; it was not (fully) downloaded. */
|
|
21
|
+
export class ChannelMediaTooLargeError extends Error {
|
|
22
|
+
maxBytes;
|
|
23
|
+
constructor(maxBytes) {
|
|
24
|
+
super(`the file exceeds the ${maxBytes}-byte limit`);
|
|
25
|
+
this.maxBytes = maxBytes;
|
|
26
|
+
this.name = 'ChannelMediaTooLargeError';
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* GET a file, refusing one past `maxBytes` — by its `content-length` before reading, and by what
|
|
31
|
+
* actually arrives while reading. Throws a {@link ChannelDeliveryError} on a non-2xx.
|
|
32
|
+
*/
|
|
33
|
+
export async function fetchBytes(channel, fetcher, url, headers, timeoutMs, maxBytes) {
|
|
34
|
+
let response;
|
|
35
|
+
try {
|
|
36
|
+
response = await fetcher(url, {
|
|
37
|
+
method: 'GET',
|
|
38
|
+
headers,
|
|
39
|
+
signal: AbortSignal.timeout(timeoutMs),
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
throw new ChannelDeliveryError(channel, null, `${channel}: download failed (${error instanceof Error ? error.name : 'network error'})`);
|
|
44
|
+
}
|
|
45
|
+
if (!response.ok) {
|
|
46
|
+
await response.body?.cancel().catch(() => { });
|
|
47
|
+
throw new ChannelDeliveryError(channel, response.status, `${channel}: the provider refused the download (HTTP ${response.status})`);
|
|
48
|
+
}
|
|
49
|
+
const declared = Number(response.headers.get('content-length'));
|
|
50
|
+
if (Number.isFinite(declared) && declared > maxBytes) {
|
|
51
|
+
await response.body?.cancel().catch(() => { });
|
|
52
|
+
throw new ChannelMediaTooLargeError(maxBytes);
|
|
53
|
+
}
|
|
54
|
+
const chunks = [];
|
|
55
|
+
let size = 0;
|
|
56
|
+
if (response.body) {
|
|
57
|
+
const reader = response.body.getReader();
|
|
58
|
+
for (;;) {
|
|
59
|
+
const { done, value } = await reader.read();
|
|
60
|
+
if (done)
|
|
61
|
+
break;
|
|
62
|
+
size += value.byteLength;
|
|
63
|
+
if (size > maxBytes) {
|
|
64
|
+
await reader.cancel().catch(() => { });
|
|
65
|
+
throw new ChannelMediaTooLargeError(maxBytes);
|
|
66
|
+
}
|
|
67
|
+
chunks.push(value);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
data: Buffer.concat(chunks),
|
|
72
|
+
contentType: response.headers.get('content-type')?.split(';')[0]?.trim() || undefined,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
/** Bytes of a base64 string, refusing past `maxBytes` before decoding. */
|
|
76
|
+
export function decodeBase64(base64, maxBytes) {
|
|
77
|
+
const body = base64.replace(/^data:[^,]*,/, '');
|
|
78
|
+
if (Math.floor((body.length * 3) / 4) - 2 > maxBytes)
|
|
79
|
+
throw new ChannelMediaTooLargeError(maxBytes);
|
|
80
|
+
const data = Buffer.from(body, 'base64');
|
|
81
|
+
if (data.byteLength > maxBytes)
|
|
82
|
+
throw new ChannelMediaTooLargeError(maxBytes);
|
|
83
|
+
return data;
|
|
84
|
+
}
|
|
85
|
+
/** A positive number out of a webhook field that may be a number, a numeric string or a Long object. */
|
|
86
|
+
export function sizeOf(value) {
|
|
87
|
+
const raw = typeof value === 'object' && value !== null && 'low' in value
|
|
88
|
+
? value.low
|
|
89
|
+
: value;
|
|
90
|
+
const size = typeof raw === 'string' ? Number(raw) : raw;
|
|
91
|
+
return typeof size === 'number' && Number.isFinite(size) && size > 0 ? size : undefined;
|
|
92
|
+
}
|
|
93
|
+
/** Compare two secrets in constant time (over their hashes, so lengths leak nothing either). */
|
|
94
|
+
export function safeEqual(supplied, expected) {
|
|
95
|
+
if (typeof supplied !== 'string' || expected.length === 0)
|
|
96
|
+
return false;
|
|
97
|
+
const digest = (value) => createHash('sha256').update(value).digest();
|
|
98
|
+
return timingSafeEqual(digest(supplied), digest(expected)) && supplied === expected;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* POST a JSON body. Resolves with the parsed JSON answer (`null` when it is not JSON); throws a
|
|
102
|
+
* {@link ChannelDeliveryError} on a non-2xx or a network failure. The provider's error body is never
|
|
103
|
+
* put in the error — it can echo the message text or credentials.
|
|
104
|
+
*/
|
|
105
|
+
export async function postJson(channel, fetcher, url, headers, body, timeoutMs) {
|
|
106
|
+
let response;
|
|
107
|
+
try {
|
|
108
|
+
response = await fetcher(url, {
|
|
109
|
+
method: 'POST',
|
|
110
|
+
headers: { 'content-type': 'application/json', ...headers },
|
|
111
|
+
body: JSON.stringify(body),
|
|
112
|
+
signal: AbortSignal.timeout(timeoutMs),
|
|
113
|
+
redirect: 'error',
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
throw new ChannelDeliveryError(channel, null, `${channel}: delivery failed (${error instanceof Error ? error.name : 'network error'})`);
|
|
118
|
+
}
|
|
119
|
+
const text = await response.text().catch(() => '');
|
|
120
|
+
if (!response.ok) {
|
|
121
|
+
throw new ChannelDeliveryError(channel, response.status, `${channel}: the provider refused the message (HTTP ${response.status})`);
|
|
122
|
+
}
|
|
123
|
+
try {
|
|
124
|
+
return text === '' ? null : JSON.parse(text);
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/** A query-string parameter of a request's url. */
|
|
131
|
+
export function queryParam(url, name) {
|
|
132
|
+
const query = url.indexOf('?');
|
|
133
|
+
if (query === -1)
|
|
134
|
+
return undefined;
|
|
135
|
+
return new URLSearchParams(url.slice(query + 1)).get(name) ?? undefined;
|
|
136
|
+
}
|
|
137
|
+
/** `value` when it is a plain object, else `undefined` — for reading untyped webhook bodies. */
|
|
138
|
+
export function record(value) {
|
|
139
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value)
|
|
140
|
+
? value
|
|
141
|
+
: undefined;
|
|
142
|
+
}
|
|
143
|
+
/** `value` when it is a non-empty string. */
|
|
144
|
+
export function str(value) {
|
|
145
|
+
return typeof value === 'string' && value.length > 0 ? value : undefined;
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=http.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../../../src/channels/http.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@adonis-agora/agent/channels` — the agent on text channels (WhatsApp, Telegram, …): one webhook
|
|
3
|
+
* route per channel that verifies, deduplicates, acknowledges at once and answers in the background,
|
|
4
|
+
* with the channel's markdown, length limit and reply buttons. See `docs/channels.mdx`.
|
|
5
|
+
*/
|
|
6
|
+
export { type EvolutionApiOptions, evolutionApi } from './adapters/evolution_api.js';
|
|
7
|
+
export { type TelegramOptions, telegram } from './adapters/telegram.js';
|
|
8
|
+
export { type WhatsappCloudOptions, whatsappCloud } from './adapters/whatsapp_cloud.js';
|
|
9
|
+
export { type ChannelAddress, type ChannelHandleOptions, type ChannelMediaRefusal, type ChannelProposal, type ChannelRouteHandler, type ChannelTexts, type ChannelTextsOverrides, type ChannelTurnService, channels, DEFAULT_CHANNEL_TEXTS, handleChannel, proposalButtonIds, relayChannelOutcome, } from './handler.js';
|
|
10
|
+
export { ChannelDeliveryError, type ChannelFetch, ChannelMediaTooLargeError } from './http.js';
|
|
11
|
+
export { escapeTelegramMarkdown, toChannelMarkdown, unescapeTelegramMarkdown, } from './markdown.js';
|
|
12
|
+
export { type ChannelAnswer, type ChannelQuestionTexts, DEFAULT_CHANNEL_QUESTION_TEXTS, formatChannelQuestion, parseChannelAnswer, } from './questions.js';
|
|
13
|
+
export { splitMessage } from './split.js';
|
|
14
|
+
export { type ChannelStore, type ChannelStoreRedis, InMemoryChannelStore, type LucidChannelStoreDatabase, type LucidChannelStoreOptions, lucidChannelStore, redisChannelStore, } from './store.js';
|
|
15
|
+
export type { ChannelAdapter, ChannelButton, ChannelCapabilities, ChannelChallengeResponse, ChannelMarkdown, ChannelMediaFile, ChannelRequest, InboundMedia, InboundMessage, OutboundMessage, } from './types.js';
|
|
16
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/channels/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,KAAK,mBAAmB,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AACrF,OAAO,EAAE,KAAK,eAAe,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACxE,OAAO,EAAE,KAAK,oBAAoB,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AACxF,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,YAAY,EACjB,KAAK,qBAAqB,EAC1B,KAAK,kBAAkB,EACvB,QAAQ,EACR,qBAAqB,EACrB,aAAa,EACb,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,oBAAoB,EAAE,KAAK,YAAY,EAAE,yBAAyB,EAAE,MAAM,WAAW,CAAC;AAC/F,OAAO,EACL,sBAAsB,EACtB,iBAAiB,EACjB,wBAAwB,GACzB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,oBAAoB,EACzB,8BAA8B,EAC9B,qBAAqB,EACrB,kBAAkB,GACnB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,iBAAiB,EACtB,oBAAoB,EACpB,KAAK,yBAAyB,EAC9B,KAAK,wBAAwB,EAC7B,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,cAAc,EACd,aAAa,EACb,mBAAmB,EACnB,wBAAwB,EACxB,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,YAAY,EACZ,cAAc,EACd,eAAe,GAChB,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@adonis-agora/agent/channels` — the agent on text channels (WhatsApp, Telegram, …): one webhook
|
|
3
|
+
* route per channel that verifies, deduplicates, acknowledges at once and answers in the background,
|
|
4
|
+
* with the channel's markdown, length limit and reply buttons. See `docs/channels.mdx`.
|
|
5
|
+
*/
|
|
6
|
+
export { evolutionApi } from './adapters/evolution_api.js';
|
|
7
|
+
export { telegram } from './adapters/telegram.js';
|
|
8
|
+
export { whatsappCloud } from './adapters/whatsapp_cloud.js';
|
|
9
|
+
export { channels, DEFAULT_CHANNEL_TEXTS, handleChannel, proposalButtonIds, relayChannelOutcome, } from './handler.js';
|
|
10
|
+
export { ChannelDeliveryError, ChannelMediaTooLargeError } from './http.js';
|
|
11
|
+
export { escapeTelegramMarkdown, toChannelMarkdown, unescapeTelegramMarkdown, } from './markdown.js';
|
|
12
|
+
export { DEFAULT_CHANNEL_QUESTION_TEXTS, formatChannelQuestion, parseChannelAnswer, } from './questions.js';
|
|
13
|
+
export { splitMessage } from './split.js';
|
|
14
|
+
export { InMemoryChannelStore, lucidChannelStore, redisChannelStore, } from './store.js';
|
|
15
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/channels/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAA4B,YAAY,EAAE,MAAM,6BAA6B,CAAC;AACrF,OAAO,EAAwB,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACxE,OAAO,EAA6B,aAAa,EAAE,MAAM,8BAA8B,CAAC;AACxF,OAAO,EASL,QAAQ,EACR,qBAAqB,EACrB,aAAa,EACb,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,oBAAoB,EAAqB,yBAAyB,EAAE,MAAM,WAAW,CAAC;AAC/F,OAAO,EACL,sBAAsB,EACtB,iBAAiB,EACjB,wBAAwB,GACzB,MAAM,eAAe,CAAC;AACvB,OAAO,EAGL,8BAA8B,EAC9B,qBAAqB,EACrB,kBAAkB,GACnB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAGL,oBAAoB,EAGpB,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ChannelMarkdown } from './types.js';
|
|
2
|
+
/** Escape text for Telegram's MarkdownV2 — every character it reserves gets a backslash. */
|
|
3
|
+
export declare function escapeTelegramMarkdown(value: string): string;
|
|
4
|
+
/** Undo {@link escapeTelegramMarkdown}: what a message reads as plain text when MarkdownV2 is refused. */
|
|
5
|
+
export declare function unescapeTelegramMarkdown(value: string): string;
|
|
6
|
+
/**
|
|
7
|
+
* Convert a turn's markdown to what `markdown` renders: WhatsApp's `*bold*` `_italic_` `~strike~`,
|
|
8
|
+
* Telegram's MarkdownV2 (every reserved character escaped), or plain text. Links become
|
|
9
|
+
* `label (url)` where the channel has no link syntax; headings become bold lines.
|
|
10
|
+
*/
|
|
11
|
+
export declare function toChannelMarkdown(text: string, markdown: ChannelMarkdown): string;
|
|
12
|
+
//# sourceMappingURL=markdown.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../../src/channels/markdown.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAuBlD,4FAA4F;AAC5F,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE5D;AAED,0GAA0G;AAC1G,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE9D;AAuFD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,GAAG,MAAM,CAiBjF"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
const TELEGRAM_SPECIAL = /[_*[\]()~`>#+\-=|{}.!\\]/g;
|
|
2
|
+
/** Escape text for Telegram's MarkdownV2 — every character it reserves gets a backslash. */
|
|
3
|
+
export function escapeTelegramMarkdown(value) {
|
|
4
|
+
return value.replace(TELEGRAM_SPECIAL, '\\$&');
|
|
5
|
+
}
|
|
6
|
+
/** Undo {@link escapeTelegramMarkdown}: what a message reads as plain text when MarkdownV2 is refused. */
|
|
7
|
+
export function unescapeTelegramMarkdown(value) {
|
|
8
|
+
return value.replace(/\\([_*[\]()~`>#+\-=|{}.!\\])/g, '$1');
|
|
9
|
+
}
|
|
10
|
+
const linkText = (label, url) => label === '' || label === url ? url : `${label} (${url})`;
|
|
11
|
+
const DIALECTS = {
|
|
12
|
+
whatsapp: {
|
|
13
|
+
text: (value) => value,
|
|
14
|
+
bold: (inner) => `*${inner}*`,
|
|
15
|
+
italic: (inner) => `_${inner}_`,
|
|
16
|
+
strike: (inner) => `~${inner}~`,
|
|
17
|
+
code: (value) => `\`${value}\``,
|
|
18
|
+
pre: (_language, value) => `\`\`\`${value}\`\`\``,
|
|
19
|
+
link: linkText,
|
|
20
|
+
heading: (inner) => `*${inner}*`,
|
|
21
|
+
bullet: '- ',
|
|
22
|
+
quote: (inner) => `> ${inner}`,
|
|
23
|
+
},
|
|
24
|
+
telegram: {
|
|
25
|
+
text: escapeTelegramMarkdown,
|
|
26
|
+
bold: (inner) => `*${inner}*`,
|
|
27
|
+
italic: (inner) => `_${inner}_`,
|
|
28
|
+
strike: (inner) => `~${inner}~`,
|
|
29
|
+
code: (value) => `\`${value.replace(/[`\\]/g, '\\$&')}\``,
|
|
30
|
+
pre: (language, value) => `\`\`\`${language}\n${value.replace(/[`\\]/g, '\\$&')}\`\`\``,
|
|
31
|
+
link: (label, url) => `[${escapeTelegramMarkdown(label === '' ? url : label)}](${url.replace(/[)\\]/g, '\\$&')})`,
|
|
32
|
+
heading: (inner) => `*${inner}*`,
|
|
33
|
+
bullet: '• ',
|
|
34
|
+
quote: (inner) => `>${inner}`,
|
|
35
|
+
},
|
|
36
|
+
none: {
|
|
37
|
+
text: (value) => value,
|
|
38
|
+
bold: (inner) => inner,
|
|
39
|
+
italic: (inner) => inner,
|
|
40
|
+
strike: (inner) => inner,
|
|
41
|
+
code: (value) => value,
|
|
42
|
+
pre: (_language, value) => value,
|
|
43
|
+
link: linkText,
|
|
44
|
+
heading: (inner) => inner,
|
|
45
|
+
bullet: '- ',
|
|
46
|
+
quote: (inner) => `> ${inner}`,
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Inline tokens, earliest first: code, image/link, `**bold**`, `__bold__`, `~~strike~~`, then the
|
|
51
|
+
* single-character forms. A single marker must hug its text (`*a*`, not `* a *`) and must not sit
|
|
52
|
+
* inside a word, so `snake_case` and `2*3*4` stay as written.
|
|
53
|
+
*/
|
|
54
|
+
const INLINE = /`([^`\n]+)`|!?\[([^\]\n]*)\]\(([^)\s]+)(?:\s+"[^"]*")?\)|\*\*(?!\s)(.+?)(?<!\s)\*\*|__(?!\s)(.+?)(?<!\s)__|~~(?!\s)(.+?)(?<!\s)~~|(?<![\w*\\])\*(?![\s*])([^*\n]+?)(?<![\s\\])\*(?![\w*])|(?<![\w_\\])_(?![\s_])([^_\n]+?)(?<![\s\\])_(?![\w_])|(?<![\w~\\])~(?![\s~])([^~\n]+?)(?<![\s\\])~(?![\w~])/g;
|
|
55
|
+
function inline(source, dialect) {
|
|
56
|
+
let out = '';
|
|
57
|
+
let last = 0;
|
|
58
|
+
for (const match of source.matchAll(INLINE)) {
|
|
59
|
+
const index = match.index ?? 0;
|
|
60
|
+
out += dialect.text(source.slice(last, index));
|
|
61
|
+
last = index + match[0].length;
|
|
62
|
+
const [, code, label, url, bold, underscoreBold, strike, starBold, italic, tildeStrike] = match;
|
|
63
|
+
if (code !== undefined)
|
|
64
|
+
out += dialect.code(code);
|
|
65
|
+
else if (url !== undefined)
|
|
66
|
+
out += dialect.link(label ?? '', url);
|
|
67
|
+
else if (bold !== undefined)
|
|
68
|
+
out += dialect.bold(inline(bold, dialect));
|
|
69
|
+
else if (underscoreBold !== undefined)
|
|
70
|
+
out += dialect.bold(inline(underscoreBold, dialect));
|
|
71
|
+
else if (strike !== undefined)
|
|
72
|
+
out += dialect.strike(inline(strike, dialect));
|
|
73
|
+
else if (starBold !== undefined)
|
|
74
|
+
out += dialect.bold(inline(starBold, dialect));
|
|
75
|
+
else if (italic !== undefined)
|
|
76
|
+
out += dialect.italic(inline(italic, dialect));
|
|
77
|
+
else if (tildeStrike !== undefined)
|
|
78
|
+
out += dialect.strike(inline(tildeStrike, dialect));
|
|
79
|
+
}
|
|
80
|
+
return out + dialect.text(source.slice(last));
|
|
81
|
+
}
|
|
82
|
+
function line(source, dialect) {
|
|
83
|
+
const heading = /^\s{0,3}#{1,6}\s+(.*?)(?:\s+#+)?\s*$/.exec(source);
|
|
84
|
+
if (heading) {
|
|
85
|
+
// A heading is bold already; markers inside it would nest bold in bold.
|
|
86
|
+
return dialect.heading(inline((heading[1] ?? '').replace(/\*\*|__/g, ''), dialect));
|
|
87
|
+
}
|
|
88
|
+
if (/^\s{0,3}([-*_])(\s*\1){2,}\s*$/.test(source))
|
|
89
|
+
return '';
|
|
90
|
+
const bullet = /^(\s*)[-*+]\s+(.*)$/.exec(source);
|
|
91
|
+
if (bullet)
|
|
92
|
+
return `${bullet[1] ?? ''}${dialect.bullet}${inline(bullet[2] ?? '', dialect)}`;
|
|
93
|
+
const quote = /^\s{0,3}>\s?(.*)$/.exec(source);
|
|
94
|
+
if (quote)
|
|
95
|
+
return dialect.quote(inline(quote[1] ?? '', dialect));
|
|
96
|
+
return inline(source, dialect);
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Convert a turn's markdown to what `markdown` renders: WhatsApp's `*bold*` `_italic_` `~strike~`,
|
|
100
|
+
* Telegram's MarkdownV2 (every reserved character escaped), or plain text. Links become
|
|
101
|
+
* `label (url)` where the channel has no link syntax; headings become bold lines.
|
|
102
|
+
*/
|
|
103
|
+
export function toChannelMarkdown(text, markdown) {
|
|
104
|
+
const dialect = DIALECTS[markdown];
|
|
105
|
+
const fence = /```([\w+-]*)[^\S\n]*\n?([\s\S]*?)\n?```/g;
|
|
106
|
+
let out = '';
|
|
107
|
+
let last = 0;
|
|
108
|
+
const prose = (source) => source
|
|
109
|
+
.split('\n')
|
|
110
|
+
.map((row) => line(row, dialect))
|
|
111
|
+
.join('\n');
|
|
112
|
+
for (const match of text.matchAll(fence)) {
|
|
113
|
+
const index = match.index ?? 0;
|
|
114
|
+
out += prose(text.slice(last, index));
|
|
115
|
+
out += dialect.pre(match[1] ?? '', match[2] ?? '');
|
|
116
|
+
last = index + match[0].length;
|
|
117
|
+
}
|
|
118
|
+
return out + prose(text.slice(last));
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=markdown.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown.js","sourceRoot":"","sources":["../../../src/channels/markdown.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { ElicitationQuestion } from '../elicitation.js';
|
|
2
|
+
/** How a text channel words a question. English defaults; override any (`texts.questions`). */
|
|
3
|
+
export interface ChannelQuestionTexts {
|
|
4
|
+
/** Above the first question of a set with more than one: `(1/3)`. */
|
|
5
|
+
counter(index: number, total: number): string;
|
|
6
|
+
/** Under single-choice options. */
|
|
7
|
+
pickOne: string;
|
|
8
|
+
/** Under multiple-choice options. */
|
|
9
|
+
pickMany: string;
|
|
10
|
+
/** Under options a typed answer may replace. */
|
|
11
|
+
orWrite: string;
|
|
12
|
+
/** The word that keeps a question's pre-picked answers (or leaves it unanswered). */
|
|
13
|
+
skipWord: string;
|
|
14
|
+
/** How to keep the pre-picked answers, shown when a question has some. */
|
|
15
|
+
keep(skipWord: string, labels: string): string;
|
|
16
|
+
/** The answer could not be read; the question follows. */
|
|
17
|
+
invalid(problem: string): string;
|
|
18
|
+
}
|
|
19
|
+
export declare const DEFAULT_CHANNEL_QUESTION_TEXTS: ChannelQuestionTexts;
|
|
20
|
+
/** One question as a text message: its prompt, numbered options, and how to answer. */
|
|
21
|
+
export declare function formatChannelQuestion(question: ElicitationQuestion, position: {
|
|
22
|
+
index: number;
|
|
23
|
+
total: number;
|
|
24
|
+
preamble?: string;
|
|
25
|
+
}, texts?: ChannelQuestionTexts): string;
|
|
26
|
+
export type ChannelAnswer = {
|
|
27
|
+
status: 'answer';
|
|
28
|
+
values: string[];
|
|
29
|
+
}
|
|
30
|
+
/** Keep the question's defaults: its id is left out of the reply. */
|
|
31
|
+
| {
|
|
32
|
+
status: 'skip';
|
|
33
|
+
} | {
|
|
34
|
+
status: 'invalid';
|
|
35
|
+
problem: string;
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Read a chat message as the answer to `question`: an option's number or label (several, separated
|
|
39
|
+
* by commas, for a multiple choice), a typed value for a typed question or one that allows free
|
|
40
|
+
* text, or the skip word. Checked against the question's own rules.
|
|
41
|
+
*/
|
|
42
|
+
export declare function parseChannelAnswer(question: ElicitationQuestion, text: string, skipWord?: string): ChannelAnswer;
|
|
43
|
+
//# sourceMappingURL=questions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"questions.d.ts","sourceRoot":"","sources":["../../../src/channels/questions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAQ7D,+FAA+F;AAC/F,MAAM,WAAW,oBAAoB;IACnC,qEAAqE;IACrE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IAC9C,mCAAmC;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,qCAAqC;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,gDAAgD;IAChD,OAAO,EAAE,MAAM,CAAC;IAChB,qFAAqF;IACrF,QAAQ,EAAE,MAAM,CAAC;IACjB,0EAA0E;IAC1E,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;IAC/C,0DAA0D;IAC1D,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;CAClC;AAED,eAAO,MAAM,8BAA8B,EAAE,oBAQ5C,CAAC;AAKF,uFAAuF;AACvF,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,mBAAmB,EAC7B,QAAQ,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,EAC7D,KAAK,GAAE,oBAAqD,GAC3D,MAAM,CAoBR;AAED,MAAM,MAAM,aAAa,GACrB;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE;AACxC,qEAAqE;GACnE;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,GAClB;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAI3C;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,mBAAmB,EAC7B,IAAI,EAAE,MAAM,EACZ,QAAQ,GAAE,MAAgD,GACzD,aAAa,CAqCf"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { isTypedQuestion, questionOptions, validateElicitationAnswer, validateElicitationValue, } from '../elicitation-input.js';
|
|
2
|
+
export const DEFAULT_CHANNEL_QUESTION_TEXTS = {
|
|
3
|
+
counter: (index, total) => `(${index + 1}/${total})`,
|
|
4
|
+
pickOne: 'Reply with the number of your choice.',
|
|
5
|
+
pickMany: 'Reply with one or more numbers, separated by commas.',
|
|
6
|
+
orWrite: 'Or write your own answer.',
|
|
7
|
+
skipWord: 'skip',
|
|
8
|
+
keep: (skipWord, labels) => `Reply *${skipWord}* to keep: ${labels}.`,
|
|
9
|
+
invalid: (problem) => `I could not read that answer (${problem}).`,
|
|
10
|
+
};
|
|
11
|
+
const labelOf = (question, value) => questionOptions(question).find((option) => option.value === value)?.label ?? value;
|
|
12
|
+
/** One question as a text message: its prompt, numbered options, and how to answer. */
|
|
13
|
+
export function formatChannelQuestion(question, position, texts = DEFAULT_CHANNEL_QUESTION_TEXTS) {
|
|
14
|
+
const lines = [];
|
|
15
|
+
if (position.index === 0 && position.preamble)
|
|
16
|
+
lines.push(position.preamble, '');
|
|
17
|
+
const counter = position.total > 1 ? `${texts.counter(position.index, position.total)} ` : '';
|
|
18
|
+
lines.push(`*${counter}${question.prompt}*`);
|
|
19
|
+
if (question.description)
|
|
20
|
+
lines.push(question.description);
|
|
21
|
+
const options = isTypedQuestion(question) ? [] : questionOptions(question);
|
|
22
|
+
if (options.length > 0) {
|
|
23
|
+
lines.push('');
|
|
24
|
+
for (const [index, option] of options.entries())
|
|
25
|
+
lines.push(`${index + 1}. ${option.label}`);
|
|
26
|
+
lines.push('', question.multiple === true ? texts.pickMany : texts.pickOne);
|
|
27
|
+
if (question.allowFreeText === true)
|
|
28
|
+
lines.push(texts.orWrite);
|
|
29
|
+
}
|
|
30
|
+
const defaults = question.defaults ?? [];
|
|
31
|
+
if (defaults.length > 0) {
|
|
32
|
+
lines.push(texts.keep(texts.skipWord, defaults.map((value) => labelOf(question, value)).join(', ')));
|
|
33
|
+
}
|
|
34
|
+
return lines.join('\n');
|
|
35
|
+
}
|
|
36
|
+
const fold = (value) => value.trim().toLowerCase();
|
|
37
|
+
/**
|
|
38
|
+
* Read a chat message as the answer to `question`: an option's number or label (several, separated
|
|
39
|
+
* by commas, for a multiple choice), a typed value for a typed question or one that allows free
|
|
40
|
+
* text, or the skip word. Checked against the question's own rules.
|
|
41
|
+
*/
|
|
42
|
+
export function parseChannelAnswer(question, text, skipWord = DEFAULT_CHANNEL_QUESTION_TEXTS.skipWord) {
|
|
43
|
+
const answer = text.trim();
|
|
44
|
+
if (fold(answer) === fold(skipWord))
|
|
45
|
+
return { status: 'skip' };
|
|
46
|
+
if (answer === '')
|
|
47
|
+
return { status: 'invalid', problem: 'empty answer' };
|
|
48
|
+
let values;
|
|
49
|
+
if (isTypedQuestion(question)) {
|
|
50
|
+
values = [answer];
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
const options = questionOptions(question);
|
|
54
|
+
const pick = (token) => {
|
|
55
|
+
const bare = token.trim().replace(/[.)]$/, '');
|
|
56
|
+
if (/^\d+$/.test(bare)) {
|
|
57
|
+
const option = options[Number(bare) - 1];
|
|
58
|
+
if (option)
|
|
59
|
+
return option.value;
|
|
60
|
+
}
|
|
61
|
+
const match = options.find((option) => fold(option.label) === fold(token) || fold(option.value) === fold(token));
|
|
62
|
+
return match?.value ?? null;
|
|
63
|
+
};
|
|
64
|
+
const whole = pick(answer);
|
|
65
|
+
if (whole !== null)
|
|
66
|
+
values = [whole];
|
|
67
|
+
else if (question.multiple === true) {
|
|
68
|
+
const tokens = answer.split(/\s*[,;]\s*|\s+/).filter((token) => token !== '');
|
|
69
|
+
const picked = tokens.map(pick);
|
|
70
|
+
if (picked.every((value) => value !== null))
|
|
71
|
+
values = [...new Set(picked)];
|
|
72
|
+
else if (question.allowFreeText === true)
|
|
73
|
+
values = [answer];
|
|
74
|
+
else
|
|
75
|
+
return { status: 'invalid', problem: 'not one of the options' };
|
|
76
|
+
}
|
|
77
|
+
else if (question.allowFreeText === true || options.length === 0)
|
|
78
|
+
values = [answer];
|
|
79
|
+
else
|
|
80
|
+
return { status: 'invalid', problem: 'not one of the options' };
|
|
81
|
+
}
|
|
82
|
+
for (const value of values) {
|
|
83
|
+
const problem = validateElicitationValue(question, value);
|
|
84
|
+
if (problem !== null)
|
|
85
|
+
return { status: 'invalid', problem };
|
|
86
|
+
}
|
|
87
|
+
const problem = validateElicitationAnswer(question, values);
|
|
88
|
+
return problem === null ? { status: 'answer', values } : { status: 'invalid', problem };
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=questions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"questions.js","sourceRoot":"","sources":["../../../src/channels/questions.ts"],"names":[],"mappings":"AACA,OAAO,EACL,eAAe,EACf,eAAe,EACf,yBAAyB,EACzB,wBAAwB,GACzB,MAAM,yBAAyB,CAAC;AAoBjC,MAAM,CAAC,MAAM,8BAA8B,GAAyB;IAClE,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,GAAG;IACpD,OAAO,EAAE,uCAAuC;IAChD,QAAQ,EAAE,sDAAsD;IAChE,OAAO,EAAE,2BAA2B;IACpC,QAAQ,EAAE,MAAM;IAChB,IAAI,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,CAAC,UAAU,QAAQ,cAAc,MAAM,GAAG;IACrE,OAAO,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,iCAAiC,OAAO,IAAI;CACnE,CAAC;AAEF,MAAM,OAAO,GAAG,CAAC,QAA6B,EAAE,KAAa,EAAE,EAAE,CAC/D,eAAe,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,KAAK,KAAK,CAAC,EAAE,KAAK,IAAI,KAAK,CAAC;AAErF,uFAAuF;AACvF,MAAM,UAAU,qBAAqB,CACnC,QAA6B,EAC7B,QAA6D,EAC7D,KAAK,GAAyB,8BAA8B;IAE5D,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,QAAQ,CAAC,KAAK,KAAK,CAAC,IAAI,QAAQ,CAAC,QAAQ;QAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IACjF,MAAM,OAAO,GAAG,QAAQ,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IAC9F,KAAK,CAAC,IAAI,CAAC,IAAI,OAAO,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;IAC7C,IAAI,QAAQ,CAAC,WAAW;QAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IAC3D,MAAM,OAAO,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;IAC3E,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE;YAAE,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,GAAG,CAAC,KAAK,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;QAC7F,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC5E,IAAI,QAAQ,CAAC,aAAa,KAAK,IAAI;YAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACjE,CAAC;IACD,MAAM,QAAQ,GAAG,QAAQ,CAAC,QAAQ,IAAI,EAAE,CAAC;IACzC,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,KAAK,CAAC,IAAI,CACR,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CACzF,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAQD,MAAM,IAAI,GAAG,CAAC,KAAa,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AAE3D;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAChC,QAA6B,EAC7B,IAAY,EACZ,QAAQ,GAAW,8BAA8B,CAAC,QAAQ;IAE1D,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAC3B,IAAI,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,QAAQ,CAAC;QAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IAC/D,IAAI,MAAM,KAAK,EAAE;QAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC;IACzE,IAAI,MAAgB,CAAC;IACrB,IAAI,eAAe,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC9B,MAAM,GAAG,CAAC,MAAM,CAAC,CAAC;IACpB,CAAC;SAAM,CAAC;QACN,MAAM,OAAO,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;QAC1C,MAAM,IAAI,GAAG,CAAC,KAAa,EAAiB,EAAE;YAC5C,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YAC/C,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBACvB,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;gBACzC,IAAI,MAAM;oBAAE,OAAO,MAAM,CAAC,KAAK,CAAC;YAClC,CAAC;YACD,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CACxB,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,CACrF,CAAC;YACF,OAAO,KAAK,EAAE,KAAK,IAAI,IAAI,CAAC;QAC9B,CAAC,CAAC;QACF,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;QAC3B,IAAI,KAAK,KAAK,IAAI;YAAE,MAAM,GAAG,CAAC,KAAK,CAAC,CAAC;aAChC,IAAI,QAAQ,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;YACpC,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,EAAE,CAAC,CAAC;YAC9E,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAChC,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,EAAmB,EAAE,CAAC,KAAK,KAAK,IAAI,CAAC;gBAAE,MAAM,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;iBACvF,IAAI,QAAQ,CAAC,aAAa,KAAK,IAAI;gBAAE,MAAM,GAAG,CAAC,MAAM,CAAC,CAAC;;gBACvD,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,wBAAwB,EAAE,CAAC;QACvE,CAAC;aAAM,IAAI,QAAQ,CAAC,aAAa,KAAK,IAAI,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,MAAM,GAAG,CAAC,MAAM,CAAC,CAAC;;YACjF,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,wBAAwB,EAAE,CAAC;IACvE,CAAC;IACD,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,OAAO,GAAG,wBAAwB,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QAC1D,IAAI,OAAO,KAAK,IAAI;YAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC;IAC9D,CAAC;IACD,MAAM,OAAO,GAAG,yBAAyB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC5D,OAAO,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC;AAC1F,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Split `text` into messages of at most `maxLength` characters, cutting where a reader would: at a
|
|
3
|
+
* paragraph break, else a line break, else the end of a sentence, else a space — and only when
|
|
4
|
+
* none of those falls past the first third of the window, mid-word. Whitespace at the cut is dropped;
|
|
5
|
+
* empty pieces are never returned.
|
|
6
|
+
*/
|
|
7
|
+
export declare function splitMessage(text: string, maxLength: number): string[];
|
|
8
|
+
//# sourceMappingURL=split.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"split.d.ts","sourceRoot":"","sources":["../../../src/channels/split.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,CAqBtE"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Split `text` into messages of at most `maxLength` characters, cutting where a reader would: at a
|
|
3
|
+
* paragraph break, else a line break, else the end of a sentence, else a space — and only when
|
|
4
|
+
* none of those falls past the first third of the window, mid-word. Whitespace at the cut is dropped;
|
|
5
|
+
* empty pieces are never returned.
|
|
6
|
+
*/
|
|
7
|
+
export function splitMessage(text, maxLength) {
|
|
8
|
+
if (!Number.isInteger(maxLength) || maxLength < 1) {
|
|
9
|
+
throw new RangeError('maxLength must be a positive integer');
|
|
10
|
+
}
|
|
11
|
+
const pieces = [];
|
|
12
|
+
let rest = text.trim();
|
|
13
|
+
while (rest.length > maxLength) {
|
|
14
|
+
const window = rest.slice(0, maxLength + 1);
|
|
15
|
+
const floor = Math.floor(maxLength / 3);
|
|
16
|
+
const cut = lastBreak(window, /\n\s*\n/g, floor) ??
|
|
17
|
+
lastBreak(window, /\n/g, floor) ??
|
|
18
|
+
lastBreak(window, /[.!?…](?=\s)/g, floor, true) ??
|
|
19
|
+
lastBreak(window, /\s/g, floor) ??
|
|
20
|
+
maxLength;
|
|
21
|
+
const piece = rest.slice(0, cut).trimEnd();
|
|
22
|
+
if (piece.length > 0)
|
|
23
|
+
pieces.push(piece);
|
|
24
|
+
rest = rest.slice(cut).trimStart();
|
|
25
|
+
}
|
|
26
|
+
if (rest.length > 0)
|
|
27
|
+
pieces.push(rest);
|
|
28
|
+
return pieces;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Where the last match of `pattern` in `window` lets the text be cut, if that is past `floor`:
|
|
32
|
+
* before the match, or after it (`keep` — a sentence keeps its full stop). `null` when there is none.
|
|
33
|
+
*/
|
|
34
|
+
function lastBreak(window, pattern, floor, keep = false) {
|
|
35
|
+
let found = null;
|
|
36
|
+
for (const match of window.matchAll(pattern)) {
|
|
37
|
+
const index = match.index ?? 0;
|
|
38
|
+
const at = keep ? index + match[0].length : index;
|
|
39
|
+
// A cut must leave the piece within the limit (the window is one character longer).
|
|
40
|
+
if (at > floor && at <= window.length - 1)
|
|
41
|
+
found = at;
|
|
42
|
+
}
|
|
43
|
+
return found;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=split.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"split.js","sourceRoot":"","sources":["../../../src/channels/split.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,IAAY,EAAE,SAAiB;IAC1D,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;QAClD,MAAM,IAAI,UAAU,CAAC,sCAAsC,CAAC,CAAC;IAC/D,CAAC;IACD,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IACvB,OAAO,IAAI,CAAC,MAAM,GAAG,SAAS,EAAE,CAAC;QAC/B,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,GAAG,CAAC,CAAC,CAAC;QAC5C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC;QACxC,MAAM,GAAG,GACP,SAAS,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,CAAC;YACpC,SAAS,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC;YAC/B,SAAS,CAAC,MAAM,EAAE,eAAe,EAAE,KAAK,EAAE,IAAI,CAAC;YAC/C,SAAS,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC;YAC/B,SAAS,CAAC;QACZ,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC;QAC3C,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;YAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACzC,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,CAAC;IACrC,CAAC;IACD,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;QAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACvC,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;GAGG;AACH,SAAS,SAAS,CAAC,MAAc,EAAE,OAAe,EAAE,KAAa,EAAE,IAAI,GAAG,KAAK;IAC7E,IAAI,KAAK,GAAkB,IAAI,CAAC;IAChC,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QAC7C,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,IAAI,CAAC,CAAC;QAC/B,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC;QAClD,oFAAoF;QACpF,IAAI,EAAE,GAAG,KAAK,IAAI,EAAE,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;YAAE,KAAK,GAAG,EAAE,CAAC;IACxD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
|