// SPDX-License-Identifier: AGPL-3.0-only // Copyright 2026-present the Unsloth AI Inc. team. All rights reserved. See /studio/LICENSE.AGPL-3.0 import assert from "node:assert/strict"; import { readFileSync } from "node:fs"; import test from "node:test"; import { fileURLToPath } from "node:url"; import ts from "typescript"; import { buildArtifactSourceKey, createArtifactId, createChatArtifact, hashArtifactCode, } from "../src/features/chat/artifacts/types.ts"; // The shipped helper the component keys on, not a copy of it. const sourceKey = buildArtifactSourceKey; const toolInput = (code: string) => ({ code, source: "tool" as const, threadId: "thread-1", sourceMessageId: "msg-1", sourceToolCallId: "call_0", }); const fenceInput = (code: string) => ({ code, source: "fence" as const, threadId: "thread-1", sourceMessageId: "msg-1", }); test("tool artifact IDs are stable across code changes, so the ID alone is not enough", () => { const first = createArtifactId(toolInput("
first
")); const second = createArtifactId(toolInput("second
")); assert.equal(first, second); }); test("the source key changes when a tool artifact's code changes", () => { const first = createChatArtifact(toolInput("first
")); const second = createChatArtifact(toolInput("second
")); assert.notEqual(sourceKey(first), sourceKey(second)); }); test("the source key changes when switching between fence artifacts", () => { const first = createChatArtifact(fenceInput("alpha
")); const second = createChatArtifact(fenceInput("bravo
")); assert.notEqual(sourceKey(first), sourceKey(second)); }); test("the source key is stable for an unchanged artifact, so no needless remount", () => { const code = "same
"; assert.equal( sourceKey(createChatArtifact(toolInput(code))), sourceKey(createChatArtifact(toolInput(code))), ); }); // Equal line count, the shape where Streamdown's comparator sees no change. test("the source key changes for two canvases with the same shape", () => { const first = createChatArtifact( toolInput("\n\nab
"), hashArtifactCode("ba
")); assert.notEqual(hashArtifactCode(""), hashArtifactCode(" ")); }); const KEYED_BY_HELPER = /^\{buildArtifactSourceKey\(\s*artifact\s*\)\}$/; const SURFACE_PATH = fileURLToPath( new URL( "../src/features/chat/artifacts/artifact-surface.tsx", import.meta.url, ), ); /** The opening tag of `node`, for both `