fix(core): Allow Unicode characters in execution metadata keys (#30486)

Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
José Braulio González Valido 2026-05-21 11:48:14 +01:00 committed by GitHub
parent cdf9b4ffb0
commit 41a273e1e4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 61 additions and 2 deletions

View File

@ -173,4 +173,63 @@ describe('Execution Metadata functions', () => {
test1: longValue.slice(0, 512),
});
});
// GHC-8254: AI Agent node with Chinese name fails with "Custom date key can only contain characters A-Za-z0-9_"
describe('Unicode support in keys (GHC-8254)', () => {
test('should allow Chinese characters in keys', () => {
const { metadata, executionData } = createExecutionDataWithMetadata();
// Simulates AI Agent node named "测试" generating key "response_测试"
const chineseKey = 'response_测试';
expect(() => setWorkflowExecutionMetadata(executionData, chineseKey, 'value1')).not.toThrow();
expect(metadata).toHaveProperty(chineseKey, 'value1');
});
test('should allow other Unicode characters (Japanese, Korean)', () => {
const { metadata, executionData } = createExecutionDataWithMetadata();
// Japanese
const japaneseKey = 'response_テスト';
expect(() =>
setWorkflowExecutionMetadata(executionData, japaneseKey, 'value1'),
).not.toThrow();
// Korean
const koreanKey = 'response_테스트';
expect(() => setWorkflowExecutionMetadata(executionData, koreanKey, 'value2')).not.toThrow();
expect(metadata).toHaveProperty(japaneseKey, 'value1');
expect(metadata).toHaveProperty(koreanKey, 'value2');
});
test('should allow Unicode combining marks (Devanagari)', () => {
const { metadata, executionData } = createExecutionDataWithMetadata();
// `lodash/snakeCase('नमस्ते')` preserves combining marks (e.g. U+094D virama,
// U+0947 vowel sign) which fall under \p{M}, not \p{L}.
const devanagariKey = 'response_नमस्ते';
expect(() =>
setWorkflowExecutionMetadata(executionData, devanagariKey, 'value1'),
).not.toThrow();
expect(metadata).toHaveProperty(devanagariKey, 'value1');
});
test('should still reject special characters that could cause issues', () => {
const { metadata, executionData } = createExecutionDataWithMetadata();
// Control characters should still be rejected
expect(() => setWorkflowExecutionMetadata(executionData, 'test\x00key', 'value')).toThrow(
InvalidExecutionMetadataError,
);
// Newlines should be rejected
expect(() => setWorkflowExecutionMetadata(executionData, 'test\nkey', 'value')).toThrow(
InvalidExecutionMetadataError,
);
expect(metadata).toEqual({});
});
});
});

View File

@ -23,11 +23,11 @@ export function setWorkflowExecutionMetadata(
if (typeof key !== 'string') {
throw new InvalidExecutionMetadataError('key', key);
}
if (key.replace(/[A-Za-z0-9_]/g, '').length !== 0) {
if (key.replace(/[\p{L}\p{N}\p{M}_]/gu, '').length !== 0) {
throw new InvalidExecutionMetadataError(
'key',
key,
`Custom date key can only contain characters "A-Za-z0-9_" (key "${key}")`,
`Custom data key can only contain letters, numbers, and underscores (key "${key}")`,
);
}
if (typeof value !== 'string' && typeof value !== 'number' && typeof value !== 'bigint') {