agent-messenger 2.6.2 → 2.7.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.
Files changed (39) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/dist/package.json +1 -1
  3. package/dist/src/platforms/webex/client.d.ts +3 -0
  4. package/dist/src/platforms/webex/client.d.ts.map +1 -1
  5. package/dist/src/platforms/webex/client.js +22 -8
  6. package/dist/src/platforms/webex/client.js.map +1 -1
  7. package/dist/src/platforms/webex/commands/snapshot.d.ts +0 -3
  8. package/dist/src/platforms/webex/commands/snapshot.d.ts.map +1 -1
  9. package/dist/src/platforms/webex/commands/snapshot.js +9 -47
  10. package/dist/src/platforms/webex/commands/snapshot.js.map +1 -1
  11. package/dist/src/platforms/webex/markdown-to-html.d.ts +3 -0
  12. package/dist/src/platforms/webex/markdown-to-html.d.ts.map +1 -0
  13. package/dist/src/platforms/webex/markdown-to-html.js +161 -0
  14. package/dist/src/platforms/webex/markdown-to-html.js.map +1 -0
  15. package/docs/content/docs/cli/webex.mdx +3 -11
  16. package/package.json +1 -1
  17. package/skills/agent-channeltalk/SKILL.md +1 -1
  18. package/skills/agent-channeltalkbot/SKILL.md +1 -1
  19. package/skills/agent-discord/SKILL.md +1 -1
  20. package/skills/agent-discordbot/SKILL.md +1 -1
  21. package/skills/agent-instagram/SKILL.md +1 -1
  22. package/skills/agent-kakaotalk/SKILL.md +1 -1
  23. package/skills/agent-line/SKILL.md +1 -1
  24. package/skills/agent-slack/SKILL.md +1 -1
  25. package/skills/agent-slackbot/SKILL.md +1 -1
  26. package/skills/agent-teams/SKILL.md +1 -1
  27. package/skills/agent-telegram/SKILL.md +1 -1
  28. package/skills/agent-webex/SKILL.md +6 -14
  29. package/skills/agent-webex/references/common-patterns.md +3 -32
  30. package/skills/agent-wechatbot/SKILL.md +1 -1
  31. package/skills/agent-whatsapp/SKILL.md +1 -1
  32. package/skills/agent-whatsappbot/SKILL.md +1 -1
  33. package/src/platforms/webex/client.test.ts +35 -0
  34. package/src/platforms/webex/client.ts +26 -9
  35. package/src/platforms/webex/commands/snapshot.test.ts +13 -41
  36. package/src/platforms/webex/commands/snapshot.ts +10 -61
  37. package/src/platforms/webex/markdown-to-html.test.ts +153 -0
  38. package/src/platforms/webex/markdown-to-html.ts +194 -0
  39. package/src/platforms/wechatbot/cli.ts +0 -0
@@ -0,0 +1,194 @@
1
+ const BLOCK_PLACEHOLDER_PREFIX = '\u0000BLOCK'
2
+ const INLINE_PLACEHOLDER_PREFIX = '\u0000INLINE'
3
+
4
+ export function markdownToHtml(markdown: string): string {
5
+ if (markdown.length === 0) {
6
+ return ''
7
+ }
8
+
9
+ const normalized = markdown.replace(/\r\n?/g, '\n')
10
+ if (normalized.trim().length === 0) {
11
+ return normalized
12
+ }
13
+
14
+ const { text, blocks } = extractCodeBlocks(normalized)
15
+ const lines = text.split('\n')
16
+ const output: string[] = []
17
+ let paragraph: string[] = []
18
+
19
+ const flushParagraph = () => {
20
+ if (paragraph.length === 0) {
21
+ return
22
+ }
23
+
24
+ output.push(processInline(paragraph.join('\n')).replace(/\n/g, '<br/>'))
25
+ paragraph = []
26
+ }
27
+
28
+ for (let index = 0; index < lines.length; ) {
29
+ const line = lines[index]
30
+ const trimmed = line.trim()
31
+
32
+ if (trimmed.length === 0) {
33
+ flushParagraph()
34
+ index++
35
+ continue
36
+ }
37
+
38
+ if (isBlockPlaceholder(trimmed)) {
39
+ flushParagraph()
40
+ output.push(trimmed)
41
+ index++
42
+ continue
43
+ }
44
+
45
+ const headingMatch = line.match(/^(#{1,6})\s+(.*)$/)
46
+ if (headingMatch) {
47
+ flushParagraph()
48
+ output.push(`<h${headingMatch[1].length}>${processInline(headingMatch[2])}</h${headingMatch[1].length}>`)
49
+ index++
50
+ continue
51
+ }
52
+
53
+ if (/^---$/.test(trimmed)) {
54
+ flushParagraph()
55
+ output.push('<hr>')
56
+ index++
57
+ continue
58
+ }
59
+
60
+ if (/^>\s?/.test(line)) {
61
+ flushParagraph()
62
+ const quoteLines: string[] = []
63
+ while (index < lines.length && /^>\s?/.test(lines[index])) {
64
+ quoteLines.push(lines[index].replace(/^>\s?/, ''))
65
+ index++
66
+ }
67
+ output.push(`<blockquote>${processInline(quoteLines.join('\n')).replace(/\n/g, '<br/>')}</blockquote>`)
68
+ continue
69
+ }
70
+
71
+ if (/^-\s+/.test(line)) {
72
+ flushParagraph()
73
+ const items: string[] = []
74
+ while (index < lines.length && /^-\s+/.test(lines[index])) {
75
+ items.push(`<li>${processInline(lines[index].replace(/^-\s+/, ''))}</li>`)
76
+ index++
77
+ }
78
+ output.push(`<ul>${items.join('')}</ul>`)
79
+ continue
80
+ }
81
+
82
+ if (/^\d+\.\s+/.test(line)) {
83
+ flushParagraph()
84
+ const items: string[] = []
85
+ while (index < lines.length && /^\d+\.\s+/.test(lines[index])) {
86
+ items.push(`<li>${processInline(lines[index].replace(/^\d+\.\s+/, ''))}</li>`)
87
+ index++
88
+ }
89
+ output.push(`<ol>${items.join('')}</ol>`)
90
+ continue
91
+ }
92
+
93
+ paragraph.push(line)
94
+ index++
95
+ }
96
+
97
+ flushParagraph()
98
+
99
+ return restorePlaceholders(output.join('<br/><br/>'), blocks)
100
+ }
101
+
102
+ export function stripMarkdown(markdown: string): string {
103
+ return markdown
104
+ .replace(/\r\n?/g, '\n')
105
+ .replace(/```([a-zA-Z0-9_-]+)?\n?([\s\S]*?)```/g, (_, _language: string | undefined, code: string) => {
106
+ return code.replace(/\n$/, '')
107
+ })
108
+ .replace(/^---$/gm, '')
109
+ .replace(/^(#{1,6})\s+/gm, '')
110
+ .replace(/^>\s?/gm, '')
111
+ .replace(/^-\s+/gm, '')
112
+ .replace(/^\d+\.\s+/gm, '')
113
+ .replace(/\[([^\]]+)\]\(([^)\n]+)\)/g, '$1')
114
+ .replace(/`([^`\n]+)`/g, '$1')
115
+ .replace(/\*\*\*([^*\n]+)\*\*\*/g, '$1')
116
+ .replace(/\*\*([^*\n]+)\*\*/g, '$1')
117
+ .replace(/(^|[^\w])_([^_\n]+)_(?=[^\w]|$)/g, '$1$2')
118
+ }
119
+
120
+ function processInline(markdown: string): string {
121
+ const placeholders: string[] = []
122
+ let text = markdown
123
+
124
+ text = text.replace(/`([^`\n]+)`/g, (_, code: string) => {
125
+ return createInlinePlaceholder(placeholders, `<code>${escapeHtml(code)}</code>`)
126
+ })
127
+
128
+ text = text.replace(/\[([^\]]+)\]\(([^)\n]+)\)/g, (_, label: string, url: string) => {
129
+ if (!isSafeUrl(url)) {
130
+ return processInline(label)
131
+ }
132
+ return createInlinePlaceholder(
133
+ placeholders,
134
+ `<a href="${escapeHtml(url)}">${processInline(label)}</a>`,
135
+ )
136
+ })
137
+
138
+ text = escapeHtml(text)
139
+ text = text.replace(/\*\*\*([^*\n]+)\*\*\*/g, '<strong><em>$1</em></strong>')
140
+ text = text.replace(/\*\*([^*\n]+)\*\*/g, '<strong>$1</strong>')
141
+ text = text.replace(/(^|[^\w])_([^_\n]+)_(?=[^\w]|$)/g, '$1<em>$2</em>')
142
+
143
+ return restorePlaceholders(text, placeholders)
144
+ }
145
+
146
+ function extractCodeBlocks(markdown: string): { text: string; blocks: string[] } {
147
+ const blocks: string[] = []
148
+ const text = markdown.replace(/```([a-zA-Z0-9_-]+)?\n([\s\S]*?)\n```/g, (_, language: string | undefined, code: string) => {
149
+ const className = language ? ` class="language-${escapeHtml(language)}"` : ''
150
+ return createBlockPlaceholder(blocks, `<pre><code${className}>${escapeHtml(code)}</code></pre>`)
151
+ })
152
+
153
+ return { text, blocks }
154
+ }
155
+
156
+ function createBlockPlaceholder(blocks: string[], html: string): string {
157
+ const token = `${BLOCK_PLACEHOLDER_PREFIX}${blocks.length}\u0000`
158
+ blocks.push(html)
159
+ return token
160
+ }
161
+
162
+ function createInlinePlaceholder(placeholders: string[], html: string): string {
163
+ const token = `${INLINE_PLACEHOLDER_PREFIX}${placeholders.length}\u0000`
164
+ placeholders.push(html)
165
+ return token
166
+ }
167
+
168
+ function isBlockPlaceholder(value: string): boolean {
169
+ return new RegExp(`^${BLOCK_PLACEHOLDER_PREFIX}\\d+\\u0000$`).test(value)
170
+ }
171
+
172
+ function restorePlaceholders(text: string, values: string[]): string {
173
+ let restored = text
174
+ for (const [index, value] of values.entries()) {
175
+ restored = restored.replaceAll(`${BLOCK_PLACEHOLDER_PREFIX}${index}\u0000`, value)
176
+ restored = restored.replaceAll(`${INLINE_PLACEHOLDER_PREFIX}${index}\u0000`, value)
177
+ }
178
+ return restored
179
+ }
180
+
181
+ const SAFE_URL_PATTERN = /^(https?:|mailto:|\/|#)/i
182
+
183
+ function isSafeUrl(url: string): boolean {
184
+ return SAFE_URL_PATTERN.test(url.trim())
185
+ }
186
+
187
+ function escapeHtml(value: string): string {
188
+ return value
189
+ .replaceAll('&', '&amp;')
190
+ .replaceAll('<', '&lt;')
191
+ .replaceAll('>', '&gt;')
192
+ .replaceAll('"', '&quot;')
193
+ .replaceAll("'", '&#39;')
194
+ }
File without changes