Skip to content

Commit 5dbc14f

Browse files
authored
prompt files: allow names to contain spaces (#278395)
allow names to contain spaces
1 parent 5f75522 commit 5dbc14f

File tree

4 files changed

+6
-60
lines changed

4 files changed

+6
-60
lines changed

src/vs/workbench/contrib/chat/common/promptSyntax/languageProviders/promptValidator.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import { ChatModeKind } from '../../constants.js';
1616
import { ILanguageModelChatMetadata, ILanguageModelsService } from '../../languageModels.js';
1717
import { ILanguageModelToolsService } from '../../languageModelToolsService.js';
1818
import { getPromptsTypeForLanguageId, PromptsType } from '../promptTypes.js';
19-
import { GithubPromptHeaderAttributes, IArrayValue, IHeaderAttribute, IStringValue, ParsedPromptFile, PROMPT_NAME_REGEXP, PromptHeaderAttributes, Target } from '../promptFileParser.js';
19+
import { GithubPromptHeaderAttributes, IArrayValue, IHeaderAttribute, IStringValue, ParsedPromptFile, PromptHeaderAttributes, Target } from '../promptFileParser.js';
2020
import { Disposable, DisposableStore, toDisposable } from '../../../../../../base/common/lifecycle.js';
2121
import { Delayer } from '../../../../../../base/common/async.js';
2222
import { ResourceMap } from '../../../../../../base/common/map.js';
@@ -197,9 +197,6 @@ export class PromptValidator {
197197
report(toMarker(localize('promptValidator.nameShouldNotBeEmpty', "The 'name' attribute must not be empty."), nameAttribute.value.range, MarkerSeverity.Error));
198198
return;
199199
}
200-
if (!PROMPT_NAME_REGEXP.test(nameAttribute.value.value)) {
201-
report(toMarker(localize('promptValidator.nameInvalidCharacters', "The 'name' attribute can only consist of letters, digits, underscores, hyphens, and periods."), nameAttribute.value.range, MarkerSeverity.Error));
202-
}
203200
}
204201

205202
private validateDescription(attributes: IHeaderAttribute[], report: (markers: IMarkerData) => void): void {

src/vs/workbench/contrib/chat/common/promptSyntax/promptFileParser.ts

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ import { URI } from '../../../../../base/common/uri.js';
1010
import { parse, YamlNode, YamlParseError, Position as YamlPosition } from '../../../../../base/common/yaml.js';
1111
import { Range } from '../../../../../editor/common/core/range.js';
1212

13-
export const PROMPT_NAME_REGEXP = /^[\p{L}\d_\-\.]+$/u;
14-
1513
export class PromptFileParser {
1614
constructor() {
1715
}
@@ -162,11 +160,7 @@ export class PromptHeader {
162160
}
163161

164162
public get name(): string | undefined {
165-
const name = this.getStringAttribute(PromptHeaderAttributes.name);
166-
if (name && PROMPT_NAME_REGEXP.test(name)) {
167-
return name;
168-
}
169-
return undefined;
163+
return this.getStringAttribute(PromptHeaderAttributes.name);
170164
}
171165

172166
public get description(): string | undefined {

src/vs/workbench/contrib/chat/common/promptSyntax/service/promptsServiceImpl.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,8 +246,10 @@ export class PromptsService extends Disposable implements IPromptsService {
246246
}
247247

248248
private asChatPromptSlashCommand(parsedPromptFile: ParsedPromptFile, promptPath: IPromptPath): IChatPromptSlashCommand {
249+
let name = parsedPromptFile?.header?.name ?? promptPath.name ?? getCleanPromptName(promptPath.uri);
250+
name = name.replace(/[^\p{L}\d_\-\.]+/gu, '-'); // replace spaces with dashes
249251
return {
250-
name: parsedPromptFile?.header?.name ?? promptPath.name ?? getCleanPromptName(promptPath.uri),
252+
name: name,
251253
description: parsedPromptFile?.header?.description ?? promptPath.description,
252254
argumentHint: parsedPromptFile?.header?.argumentHint,
253255
parsedPromptFile,

src/vs/workbench/contrib/chat/test/browser/promptSytntax/promptValidator.test.ts

Lines changed: 1 addition & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -472,27 +472,11 @@ suite('PromptValidator', () => {
472472
assert.strictEqual(markers[0].message, `The 'name' attribute must be a string.`);
473473
}
474474

475-
// Invalid characters in name
476-
{
477-
const content = [
478-
'---',
479-
'name: "My@Agent!"',
480-
'description: "Test agent"',
481-
'target: vscode',
482-
'---',
483-
'Body',
484-
].join('\n');
485-
const markers = await validate(content, PromptsType.agent);
486-
assert.strictEqual(markers.length, 1);
487-
assert.strictEqual(markers[0].severity, MarkerSeverity.Error);
488-
assert.strictEqual(markers[0].message, `The 'name' attribute can only consist of letters, digits, underscores, hyphens, and periods.`);
489-
}
490-
491475
// Valid name with allowed characters
492476
{
493477
const content = [
494478
'---',
495-
'name: "My_Agent-2.0"',
479+
'name: "My_Agent-2.0 with spaces"',
496480
'description: "Test agent"',
497481
'target: vscode',
498482
'---',
@@ -632,22 +616,6 @@ suite('PromptValidator', () => {
632616
assert.strictEqual(markers[0].severity, MarkerSeverity.Error);
633617
assert.strictEqual(markers[0].message, `The 'name' attribute must not be empty.`);
634618
}
635-
636-
// Invalid characters in name
637-
{
638-
const content = [
639-
'---',
640-
'name: "My Instructions#"',
641-
'description: "Test instructions"',
642-
'applyTo: "**/*.ts"',
643-
'---',
644-
'Body',
645-
].join('\n');
646-
const markers = await validate(content, PromptsType.instructions);
647-
assert.strictEqual(markers.length, 1);
648-
assert.strictEqual(markers[0].severity, MarkerSeverity.Error);
649-
assert.strictEqual(markers[0].message, `The 'name' attribute can only consist of letters, digits, underscores, hyphens, and periods.`);
650-
}
651619
});
652620
});
653621

@@ -786,21 +754,6 @@ suite('PromptValidator', () => {
786754
assert.strictEqual(markers[0].severity, MarkerSeverity.Error);
787755
assert.strictEqual(markers[0].message, `The 'name' attribute must not be empty.`);
788756
}
789-
790-
// Invalid characters in name
791-
{
792-
const content = [
793-
'---',
794-
'name: "My Prompt!"',
795-
'description: "Test prompt"',
796-
'---',
797-
'Body',
798-
].join('\n');
799-
const markers = await validate(content, PromptsType.prompt);
800-
assert.strictEqual(markers.length, 1);
801-
assert.strictEqual(markers[0].severity, MarkerSeverity.Error);
802-
assert.strictEqual(markers[0].message, `The 'name' attribute can only consist of letters, digits, underscores, hyphens, and periods.`);
803-
}
804757
});
805758
});
806759

0 commit comments

Comments
 (0)