fix(artifact): scanner type narrowing and url regex

- Use double assertion (`as unknown as Record<string, unknown>`) at lines 30
  and 90 to fix TS2352 per project convention
- Tighten URL_REGEX to avoid capturing trailing punctuation (parens,
  quotes, commas) when URL is embedded in text
- Add test case for array-form tool_result content path

Co-Authored-By: glm-5.2 <zai-org@claude-code-best.win>
This commit is contained in:
claude-code-best
2026-06-20 16:35:44 +08:00
parent bdd023d0af
commit ac21f40453
2 changed files with 41 additions and 3 deletions

View File

@@ -99,6 +99,44 @@ describe('extractArtifacts', () => {
expect(result[0].url).toBeUndefined()
})
test('parses url/id/expires from array-form tool_result content', () => {
const messages: Message[] = [
assistantToolUse('tu1', { file_path: '/tmp/report.html', ttl: 7 }),
{
type: 'user',
uuid: crypto.randomUUID(),
message: {
role: 'user',
content: [
{
type: 'tool_result' as const,
tool_use_id: 'tu1',
content: [
{ type: 'text' as const, text: 'Artifact uploaded: ' },
{
type: 'text' as const,
text: 'https://x.test/7d/def.html (id: def, expires: 2026-06-27T10:00:00.000Z)',
},
],
},
],
},
},
]
const result = extractArtifacts(messages)
expect(result).toHaveLength(1)
expect(result[0]).toMatchObject({
filePath: '/tmp/report.html',
hash: 'def',
url: 'https://x.test/7d/def.html',
expiresAt: '2026-06-27T10:00:00.000Z',
basename: 'report.html',
isError: false,
})
})
test('orders newest first (last in conversation appears at top)', () => {
const messages: Message[] = [
assistantToolUse('tu1', { file_path: '/tmp/a.html', ttl: 7 }),

View File

@@ -12,7 +12,7 @@ export type ArtifactInfo = {
isError: boolean
}
const URL_REGEX = /https?:\/\/\S+\.html\b/
const URL_REGEX = /https?:\/\/[^\s)"',]+\.html\b/
const ID_REGEX = /\bid:\s*([A-Za-z0-9_-]+)/
const EXPIRES_REGEX = /\bexpires:\s*([0-9T:.Z+-]+)/
@@ -27,7 +27,7 @@ export function extractArtifacts(messages: Message[]): ArtifactInfo[] {
for (const block of content) {
if (typeof block !== 'object' || block === null) continue
if (!('type' in block)) continue
const b = block as Record<string, unknown>
const b = block as unknown as Record<string, unknown>
if (b.type !== 'tool_use') continue
if (b.name !== 'artifact') continue
@@ -87,7 +87,7 @@ function findToolResult(
for (const block of content) {
if (typeof block !== 'object' || block === null) continue
if (!('type' in block)) continue
const b = block as Record<string, unknown>
const b = block as unknown as Record<string, unknown>
if (b.type !== 'tool_result') continue
if (b.tool_use_id !== toolUseId) continue
return { content: b.content, is_error: b.is_error as boolean | undefined }