From ac21f404535aa2adc7465b4f0596f6bab8a8be11 Mon Sep 17 00:00:00 2001 From: claude-code-best Date: Sat, 20 Jun 2026 16:35:44 +0800 Subject: [PATCH] fix(artifact): scanner type narrowing and url regex - Use double assertion (`as unknown as Record`) 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 --- .../artifacts/__tests__/scanner.test.ts | 38 +++++++++++++++++++ src/commands/artifacts/scanner.ts | 6 +-- 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/src/commands/artifacts/__tests__/scanner.test.ts b/src/commands/artifacts/__tests__/scanner.test.ts index b695f9083..8d6272483 100644 --- a/src/commands/artifacts/__tests__/scanner.test.ts +++ b/src/commands/artifacts/__tests__/scanner.test.ts @@ -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 }), diff --git a/src/commands/artifacts/scanner.ts b/src/commands/artifacts/scanner.ts index 911e57d41..e6ea68d32 100644 --- a/src/commands/artifacts/scanner.ts +++ b/src/commands/artifacts/scanner.ts @@ -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 + const b = block as unknown as Record 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 + const b = block as unknown as Record 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 }