mirror of
https://github.com/agoramachina/claude-exporter.git
synced 2026-07-15 02:41:03 +00:00
Fix artifact extraction for create_file MCP tool (v1.10.15)
When Anthropic's `enabled_artifacts_attachments` conversation setting is false, Claude creates files via the skills-runner `create_file` MCP tool instead of the legacy `artifacts` tool. The display_content shape is identical (json_block with language / code / filename), only the tool_use.name differs. The v1.9.1 strict allowlist was rejecting it, silently dropping every artifact in those conversations. Allowlist now accepts both 'artifacts' and 'create_file'. Other skills tools that happen to share json_block display (view, list_directory, etc.) stay filtered out by name. Two regression tests added: - positive: create_file with markdown json_block extracts correctly - negative: view tool with similar json_block stays filtered Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
bec92d687f
commit
f125602d12
3 changed files with 75 additions and 6 deletions
|
|
@ -247,9 +247,17 @@ function extractArtifactsFromMessage(message) {
|
|||
// Check if message has content array (new format)
|
||||
if (message.content && Array.isArray(message.content)) {
|
||||
for (const content of message.content) {
|
||||
// NEW FORMAT: tool_use with display_content
|
||||
// Only the `artifacts` tool produces real artifacts — bash, web_search, repl, etc. are filtered out
|
||||
if (content.type === 'tool_use' && content.name === 'artifacts' && content.display_content) {
|
||||
// NEW FORMAT: tool_use with display_content.
|
||||
// Allowlist real file/artifact producers:
|
||||
// - `artifacts` — legacy artifacts tool (still used when
|
||||
// `enabled_artifacts_attachments` is true)
|
||||
// - `create_file` — skills-runner MCP tool that replaced artifacts
|
||||
// when `enabled_artifacts_attachments` is false. Same json_block
|
||||
// display_content shape (language / code / filename).
|
||||
// bash, web_search, repl, view, list_directory, etc. are filtered out.
|
||||
if (content.type === 'tool_use' &&
|
||||
(content.name === 'artifacts' || content.name === 'create_file') &&
|
||||
content.display_content) {
|
||||
const displayContent = content.display_content;
|
||||
|
||||
// Check for code_block format (newer artifact format)
|
||||
|
|
|
|||
|
|
@ -247,9 +247,17 @@ function extractArtifactsFromMessage(message) {
|
|||
// Check if message has content array (new format)
|
||||
if (message.content && Array.isArray(message.content)) {
|
||||
for (const content of message.content) {
|
||||
// NEW FORMAT: tool_use with display_content
|
||||
// Only the `artifacts` tool produces real artifacts — bash, web_search, repl, etc. are filtered out
|
||||
if (content.type === 'tool_use' && content.name === 'artifacts' && content.display_content) {
|
||||
// NEW FORMAT: tool_use with display_content.
|
||||
// Allowlist real file/artifact producers:
|
||||
// - `artifacts` — legacy artifacts tool (still used when
|
||||
// `enabled_artifacts_attachments` is true)
|
||||
// - `create_file` — skills-runner MCP tool that replaced artifacts
|
||||
// when `enabled_artifacts_attachments` is false. Same json_block
|
||||
// display_content shape (language / code / filename).
|
||||
// bash, web_search, repl, view, list_directory, etc. are filtered out.
|
||||
if (content.type === 'tool_use' &&
|
||||
(content.name === 'artifacts' || content.name === 'create_file') &&
|
||||
content.display_content) {
|
||||
const displayContent = content.display_content;
|
||||
|
||||
// Check for code_block format (newer artifact format)
|
||||
|
|
|
|||
|
|
@ -114,6 +114,59 @@ describe('extractArtifactsFromMessage — tool name filter', () => {
|
|||
};
|
||||
expect(extractArtifactsFromMessage(message)).toEqual([]);
|
||||
});
|
||||
|
||||
// Regression: when `enabled_artifacts_attachments` is false in conversation
|
||||
// settings, Claude uses the skills-runner `create_file` MCP tool instead of
|
||||
// the legacy `artifacts` tool. display_content shape is identical
|
||||
// (json_block with language / code / filename). The extractor must allowlist
|
||||
// both tool names.
|
||||
it('extracts a create_file tool_use (skills-runner replacement for artifacts)', () => {
|
||||
const message = {
|
||||
content: [
|
||||
{
|
||||
type: 'tool_use',
|
||||
name: 'create_file',
|
||||
input: {
|
||||
path: '/mnt/user-data/outputs/hello.md',
|
||||
file_text: '# Hello, world!\n',
|
||||
},
|
||||
display_content: {
|
||||
type: 'json_block',
|
||||
json_block: JSON.stringify({
|
||||
language: 'markdown',
|
||||
code: '# Hello, world!\n',
|
||||
filename: '/mnt/user-data/outputs/hello.md',
|
||||
}),
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
const artifacts = extractArtifactsFromMessage(message);
|
||||
expect(artifacts).toHaveLength(1);
|
||||
expect(artifacts[0].title).toBe('hello');
|
||||
expect(artifacts[0].language).toBe('markdown');
|
||||
expect(artifacts[0].content).toBe('# Hello, world!');
|
||||
});
|
||||
|
||||
it('still rejects other skills tools that share json_block display (e.g. view, list_directory)', () => {
|
||||
const message = {
|
||||
content: [
|
||||
{
|
||||
type: 'tool_use',
|
||||
name: 'view',
|
||||
display_content: {
|
||||
type: 'json_block',
|
||||
json_block: JSON.stringify({
|
||||
language: 'text',
|
||||
code: 'directory listing here',
|
||||
filename: '/mnt/skills/public',
|
||||
}),
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
expect(extractArtifactsFromMessage(message)).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('extractArtifactFiles — end-to-end', () => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue