@goodandready/dsh-messenger-gateway 0.3.21 → 0.3.22

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/lib/config.js CHANGED
@@ -1,104 +1,104 @@
1
- import z from '@deepseek-ai/schemastery'
2
-
3
- const HomeEntry = z.object({
4
- name: z.string().default('default'),
5
- chatId: z.union([z.number(), z.string()]),
6
- threadId: z.number().default(0),
7
- })
8
-
9
- export const PluginConfig = z.object({
10
- enabled: z.boolean().default(true),
11
- internalBaseURL: z.string().default('http://127.0.0.1:3080'),
12
- telegram: z.object({
13
- enabled: z.boolean().default(false),
14
- botToken: z.string().role('secret').default(''),
15
- allowedUserIds: z.array(z.number()).default([]),
16
- pollTimeoutSeconds: z.number().default(50),
17
- pollIntervalMs: z.number().default(500),
18
- commands: z.array(z.object({
19
- command: z.string(),
20
- description: z.string(),
21
- })).default([]),
22
- textFormat: z.union([z.const('html'), z.const('plain')]).default('html').description('html: Markdown→Telegram HTML; plain: unformatted plain text'),
23
- homeChatId: z.union([z.number(), z.string()]).default('').description('Legacy default home chatId'),
24
- homeThreadId: z.number().default(0),
25
- homes: z.array(HomeEntry).default([]).description('Named homes (forum topics / channels)'),
26
- pairingEnabled: z.boolean().default(true).description('Issue pairing codes to unknown users when allowlist is non-empty'),
27
- streaming: z.boolean().default(false).description('If true, edit one Telegram message while tokens arrive; default off'),
28
- streamEditIntervalMs: z.number().default(1200),
29
- progressEnabled: z.boolean().default(true),
30
- approvalsEnabled: z.boolean().default(true),
31
- groupsEnabled: z.boolean().default(true).description('Process group/supergroup messages'),
32
- groupRequireMention: z.boolean().default(true).description('In groups, only respond to @mention, reply-to-bot, or /commands'),
33
- reactionsEnabled: z.boolean().default(true).description('React with 👀 while processing a turn'),
34
- statusIndicator: z.boolean().default(false).description('Opt-in: set bot short description to Online/Offline (bots have no presence)'),
35
- statusOnline: z.string().default('Online'),
36
- statusOffline: z.string().default('Offline'),
37
- transport: z.union([z.const('poll'), z.const('webhook')]).default('poll'),
38
- webhookUrl: z.string().default(''),
39
- webhookSecret: z.string().role('secret').default(''),
40
- webhookPath: z.string().default('/dsh-messenger-gateway/telegram/webhook'),
41
- voiceMode: z.union([z.const('mirror'), z.const('always'), z.const('off')]).default('mirror')
42
- .description('mirror: TTS when inbound was voice; always/off override (per-user /voice wins)'),
43
- quickActions: z.boolean().default(false).description('Show quick actions keyboard in Telegram (/new, /stop, /voice, /status)'),
44
- artifactPreviews: z.boolean().default(true).description('Render diagrams and formatted tables as previews'),
45
- notifyBridge: z.object({
46
- enabled: z.boolean().default(false),
47
- events: z.array(z.string()).default(['task_done', 'error']),
48
- home: z.string().default('default'),
49
- excludeSessionPrefixes: z.array(z.string()).default(['msgw-']),
50
- }).default({ enabled: false }),
51
- alerts: z.object({
52
- enabled: z.boolean().default(false),
53
- chatId: z.union([z.number(), z.string()]).default(''),
54
- threadId: z.number().default(0),
55
- home: z.string().default(''),
56
- events: z.array(z.string()).default(['error', 'pairing']),
57
- }).default({ enabled: false }),
58
- forumMirror: z.object({
59
- enabled: z.boolean().default(false),
60
- chatId: z.union([z.number(), z.string()]).default(''),
61
- }).default({ enabled: false }),
62
- forumMirrorChatId: z.union([z.number(), z.string()]).default(''),
63
- forumMirrorEnabled: z.boolean().default(false),
64
- }),
65
- discord: z.object({
66
- enabled: z.boolean().default(false),
67
- botToken: z.string().role('secret').default(''),
68
- webhookUrl: z.string().default(''),
69
- }).default({ enabled: false }),
70
- slack: z.object({
71
- enabled: z.boolean().default(false),
72
- botToken: z.string().role('secret').default(''),
73
- webhookUrl: z.string().default(''),
74
- }).default({ enabled: false }),
75
- webhooks: z.object({
76
- enabled: z.boolean().default(true),
77
- secret: z.string().role('secret').default(''),
78
- }).default({ enabled: true }),
79
- media: z.object({
80
- cacheDir: z.string().default(''),
81
- maxDocBytes: z.number().default(20 * 1024 * 1024),
82
- maxTextInjectBytes: z.number().default(100 * 1024),
83
- maxImageBytes: z.number().default(20 * 1024 * 1024),
84
- }),
85
- tts: z.object({
86
- enabled: z.boolean().default(false),
87
- maxChars: z.number().default(4000),
88
- voiceSummary: z.boolean().default(false).description('Speak concise TL;DR summary while full text is sent to chat'),
89
- }),
90
- agent: z.object({
91
- provider: z.string().default(''),
92
- model: z.string().default(''),
93
- cwd: z.string().default(''),
94
- instructionPrefix: z.string().default(''),
95
- maxMessageLength: z.number().default(4000),
96
- idleTimeoutMs: z.number().default(3_600_000),
97
- turnTimeoutMs: z.number().default(600_000),
98
- photoOnlyMode: z.union([z.const('prompt'), z.const('run')]).default('prompt'),
99
- sessionScope: z.union([z.const('chat'), z.const('user')]).default('user')
100
- .description('In groups: user = per-user session; chat = shared session for the chat/topic'),
101
- }),
102
- })
103
-
104
- export const Config = PluginConfig
1
+ import z from '@deepseek-ai/schemastery'
2
+
3
+ const HomeEntry = z.object({
4
+ name: z.string().default('default'),
5
+ chatId: z.union([z.number(), z.string()]),
6
+ threadId: z.number().default(0),
7
+ })
8
+
9
+ export const PluginConfig = z.object({
10
+ enabled: z.boolean().default(true),
11
+ internalBaseURL: z.string().default('http://127.0.0.1:3080'),
12
+ telegram: z.object({
13
+ enabled: z.boolean().default(false),
14
+ botToken: z.string().role('secret').default(''),
15
+ allowedUserIds: z.array(z.number()).default([]),
16
+ pollTimeoutSeconds: z.number().default(50),
17
+ pollIntervalMs: z.number().default(500),
18
+ commands: z.array(z.object({
19
+ command: z.string(),
20
+ description: z.string(),
21
+ })).default([]),
22
+ textFormat: z.union([z.const('html'), z.const('plain')]).default('html').description('html: Markdown→Telegram HTML; plain: unformatted plain text'),
23
+ homeChatId: z.union([z.number(), z.string()]).default('').description('Legacy default home chatId'),
24
+ homeThreadId: z.number().default(0),
25
+ homes: z.array(HomeEntry).default([]).description('Named homes (forum topics / channels)'),
26
+ pairingEnabled: z.boolean().default(true).description('Issue pairing codes to unknown users when allowlist is non-empty'),
27
+ streaming: z.boolean().default(false).description('If true, edit one Telegram message while tokens arrive; default off'),
28
+ streamEditIntervalMs: z.number().default(1200),
29
+ progressEnabled: z.boolean().default(true),
30
+ approvalsEnabled: z.boolean().default(true),
31
+ groupsEnabled: z.boolean().default(true).description('Process group/supergroup messages'),
32
+ groupRequireMention: z.boolean().default(true).description('In groups, only respond to @mention, reply-to-bot, or /commands'),
33
+ reactionsEnabled: z.boolean().default(true).description('React with 👀 while processing a turn'),
34
+ statusIndicator: z.boolean().default(false).description('Opt-in: set bot short description to Online/Offline (bots have no presence)'),
35
+ statusOnline: z.string().default('Online'),
36
+ statusOffline: z.string().default('Offline'),
37
+ transport: z.union([z.const('poll'), z.const('webhook')]).default('poll'),
38
+ webhookUrl: z.string().default(''),
39
+ webhookSecret: z.string().role('secret').default(''),
40
+ webhookPath: z.string().default('/dsh-messenger-gateway/telegram/webhook'),
41
+ voiceMode: z.union([z.const('mirror'), z.const('always'), z.const('off')]).default('mirror')
42
+ .description('mirror: TTS when inbound was voice; always/off override (per-user /voice wins)'),
43
+ quickActions: z.boolean().default(false).description('Show quick actions keyboard in Telegram (/new, /stop, /voice, /status)'),
44
+ artifactPreviews: z.boolean().default(true).description('Render diagrams and formatted tables as previews'),
45
+ notifyBridge: z.object({
46
+ enabled: z.boolean().default(false),
47
+ events: z.array(z.string()).default(['task_done', 'error']),
48
+ home: z.string().default('default'),
49
+ excludeSessionPrefixes: z.array(z.string()).default(['msgw-']),
50
+ }).default({ enabled: false }),
51
+ alerts: z.object({
52
+ enabled: z.boolean().default(false),
53
+ chatId: z.union([z.number(), z.string()]).default(''),
54
+ threadId: z.number().default(0),
55
+ home: z.string().default(''),
56
+ events: z.array(z.string()).default(['error', 'pairing']),
57
+ }).default({ enabled: false }),
58
+ forumMirror: z.object({
59
+ enabled: z.boolean().default(false),
60
+ chatId: z.union([z.number(), z.string()]).default(''),
61
+ }).default({ enabled: false }),
62
+ forumMirrorChatId: z.union([z.number(), z.string()]).default(''),
63
+ forumMirrorEnabled: z.boolean().default(false),
64
+ }),
65
+ discord: z.object({
66
+ enabled: z.boolean().default(false),
67
+ botToken: z.string().role('secret').default(''),
68
+ webhookUrl: z.string().default(''),
69
+ }).default({ enabled: false }),
70
+ slack: z.object({
71
+ enabled: z.boolean().default(false),
72
+ botToken: z.string().role('secret').default(''),
73
+ webhookUrl: z.string().default(''),
74
+ }).default({ enabled: false }),
75
+ webhooks: z.object({
76
+ enabled: z.boolean().default(true),
77
+ secret: z.string().role('secret').default(''),
78
+ }).default({ enabled: true }),
79
+ media: z.object({
80
+ cacheDir: z.string().default(''),
81
+ maxDocBytes: z.number().default(20 * 1024 * 1024),
82
+ maxTextInjectBytes: z.number().default(100 * 1024),
83
+ maxImageBytes: z.number().default(20 * 1024 * 1024),
84
+ }),
85
+ tts: z.object({
86
+ enabled: z.boolean().default(false),
87
+ maxChars: z.number().default(4000),
88
+ voiceSummary: z.boolean().default(false).description('Speak concise TL;DR summary while full text is sent to chat'),
89
+ }),
90
+ agent: z.object({
91
+ provider: z.string().default(''),
92
+ model: z.string().default(''),
93
+ cwd: z.string().default(''),
94
+ instructionPrefix: z.string().default(''),
95
+ maxMessageLength: z.number().default(4000),
96
+ idleTimeoutMs: z.number().default(3_600_000),
97
+ turnTimeoutMs: z.number().default(600_000),
98
+ photoOnlyMode: z.union([z.const('prompt'), z.const('run')]).default('prompt'),
99
+ sessionScope: z.union([z.const('chat'), z.const('user')]).default('user')
100
+ .description('In groups: user = per-user session; chat = shared session for the chat/topic'),
101
+ }),
102
+ })
103
+
104
+ export const Config = PluginConfig
@@ -1,14 +1,14 @@
1
- /**
2
- * Normalize any content value to ContentBlock[].
3
- * DSH core (dsh-llm) calls content.some() without Array.isArray guard,
4
- * so we must ensure every message we create or copy has array content.
5
- * Refs: #51
6
- */
7
- export function ensureContentArray(content) {
8
- if (Array.isArray(content)) return content
9
- if (typeof content === 'string') {
10
- return content ? [{ type: 'text', text: content }] : [{ type: 'text', text: '(empty message)' }]
11
- }
12
- if (content && typeof content === 'object' && content.type) return [content]
13
- return [{ type: 'text', text: String(content ?? '(empty message)') }]
14
- }
1
+ /**
2
+ * Normalize any content value to ContentBlock[].
3
+ * DSH core (dsh-llm) calls content.some() without Array.isArray guard,
4
+ * so we must ensure every message we create or copy has array content.
5
+ * Refs: #51
6
+ */
7
+ export function ensureContentArray(content) {
8
+ if (Array.isArray(content)) return content
9
+ if (typeof content === 'string') {
10
+ return content ? [{ type: 'text', text: content }] : [{ type: 'text', text: '(empty message)' }]
11
+ }
12
+ if (content && typeof content === 'object' && content.type) return [content]
13
+ return [{ type: 'text', text: String(content ?? '(empty message)') }]
14
+ }