fix(web): exclude brackets from CJK autolink punctuation stripping (#486)

* fix(web): exclude brackets from CJK autolink punctuation stripping

Fullwidth brackets and parentheses (()【】「」etc.) can appear in
valid URL paths, so they should not be stripped. Narrow the regex to
only sentence-ending punctuation: comma, period, semicolon, colon,
exclamation, question mark.

via [HAPI](https://hapi.run)

Co-Authored-By: HAPI <noreply@hapi.run>

* fix(web): always show 'Agent launched' for internal metadata results

The tool state is set to 'completed' immediately when the result
arrives, so the state-based label was always showing 'Done' for
internal launch metadata. Remove the state check and always show
'Agent launched'.

via [HAPI](https://hapi.run)

Co-Authored-By: HAPI <noreply@hapi.run>

* fix(web): handle sentence-ending punctuation followed by closing brackets

The regex was missing cases like 。) where a sentence-ender is followed
by a closing bracket. Use a pattern that matches sentence-ending
punctuation optionally followed by trailing closing brackets/parens.
A bare closing bracket without a preceding sentence-ender is still
preserved as a valid URL character.

via [HAPI](https://hapi.run)

Co-Authored-By: HAPI <noreply@hapi.run>

---------

Co-authored-by: HAPI <noreply@hapi.run>
This commit is contained in:
Haoqing Wang
2026-04-17 11:37:06 +08:00
committed by GitHub
co-authored by HAPI
parent 9248b6825f
commit f408608db0
3 changed files with 24 additions and 6 deletions
@@ -536,8 +536,7 @@ const AgentResultView: ToolViewComponent = (props: ToolViewProps) => {
|| (text.startsWith('Async agent launched successfully.') && text.includes('agentId:'))
if (isInternalMeta) {
const label = state === 'completed' ? 'Done' : 'Agent launched'
return <div className="text-sm text-[var(--app-hint)]">{label}</div>
return <div className="text-sm text-[var(--app-hint)]">Agent launched</div>
}
return (
@@ -83,6 +83,25 @@ describe('remarkStripCjkAutolink', () => {
expect(tree.children[0].children.length).toBe(2)
})
it('does not strip fullwidth brackets/parens that may be part of the URL', () => {
const tree = makeAutolink('https://example.com/路径)')
transform(tree)
const link = tree.children[0].children[1]
expect(link.url).toBe('https://example.com/路径)')
expect(tree.children[0].children.length).toBe(2)
})
it('strips sentence-ending punctuation followed by closing bracket', () => {
const tree = makeAutolink('https://example.com/path。)')
transform(tree)
const paragraph = tree.children[0]
const link = paragraph.children[1]
expect(link.url).toBe('https://example.com/path')
expect(paragraph.children[2].value).toBe('。)')
})
it('does not modify explicit markdown links', () => {
// Explicit markdown link: [click here](https://example.com/path)
// The link text differs from the URL, so it's not an autolink
+4 -4
View File
@@ -10,10 +10,10 @@
* node.
*/
// Common CJK / fullwidth punctuation that should never be part of a URL.
// Includes: fullwidth comma/period/semicolon/colon/exclamation/question/parens,
// ideographic comma/period, CJK brackets, ideographic space, fullwidth full stop.
const TRAILING_CJK_PUNCT = /[,。、;:!?()【】「」『』《》〈〉\u3000\uFF0E]+$/
// CJK / fullwidth sentence-ending punctuation that should never be part of a
// URL, optionally followed by closing brackets/parens (which on their own are
// valid URL characters but should be stripped when they trail sentence-enders).
const TRAILING_CJK_PUNCT = /(?:[,。、;:!?\u3000\uFF0E]+[)】」』》〉]*)$/
interface MdastNode {
type: string