-
Notifications
You must be signed in to change notification settings - Fork 153
Add support for prompt and agent files in Kitfile generation #1034
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -66,6 +66,13 @@ var datasetSuffixes = []string{ | |||||||||
| ".tar", ".zip", ".parquet", ".csv", | ||||||||||
| } | ||||||||||
|
|
||||||||||
| // Files that are considered prompt or agent files based on their names | ||||||||||
| var promptFilePatterns = []string{ | ||||||||||
| "AGENTS.md", | ||||||||||
| "SKILL.md", | ||||||||||
| "CLAUDE.md", | ||||||||||
| } | ||||||||||
|
|
||||||||||
| // Generate a basic Kitfile by looking at the contents of a directory. Parameter | ||||||||||
| // packageOpt can be used to define metadata for the Kitfile (i.e. the package | ||||||||||
| // section), which is left empty if the parameter is nil. | ||||||||||
|
|
@@ -270,6 +277,19 @@ func addDirToKitfile(kitfile *artifact.KitFile, dir DirectoryListing) (modelFile | |||||||||
| } | ||||||||||
|
|
||||||||||
| func determineFileType(filename string) fileType { | ||||||||||
| // Check for exact agent and prompt file matches | ||||||||||
| baseName := strings.ToLower(filepath.Base(filename)) | ||||||||||
| for _, pattern := range promptFilePatterns { | ||||||||||
| if baseName == strings.ToLower(pattern) { | ||||||||||
|
Comment on lines
+282
to
+283
|
||||||||||
| for _, pattern := range promptFilePatterns { | |
| if baseName == strings.ToLower(pattern) { | |
| for _, pattern := range promptFilePatternsLower { | |
| if baseName == pattern { |
Copilot
AI
Dec 4, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The substring check strings.Contains(baseName, ".prompt") may match unintended files. For example, files like "system.prompts.md" or "my.prompter.config" would also be matched because they contain ".prompt" as a substring. Consider using a more specific pattern, such as checking if the basename ends with ".prompt" or contains ".prompt." (with a trailing dot), or use strings.HasPrefix after splitting on dots to ensure ".prompt" is a complete segment.
| // Check for .prompt pattern (substring match) | |
| if strings.Contains(baseName, ".prompt") { | |
| // Check for .prompt as a complete segment or suffix | |
| if strings.HasSuffix(baseName, ".prompt") || strings.Contains(baseName, ".prompt.") { |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,133 @@ | ||
| // Copyright 2024 The KitOps Authors. | ||
| // | ||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||
| // you may not use this file except in compliance with the License. | ||
| // You may obtain a copy of the License at | ||
| // | ||
| // http://www.apache.org/licenses/LICENSE-2.0 | ||
| // | ||
| // Unless required by applicable law or agreed to in writing, software | ||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| // See the License for the specific language governing permissions and | ||
| // limitations under the License. | ||
| // | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| package generate | ||
|
|
||
| import ( | ||
| "testing" | ||
| ) | ||
gorkem marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| func TestDetermineFileType(t *testing.T) { | ||
| tests := []struct { | ||
| name string | ||
| filename string | ||
| expectedType fileType | ||
| }{ | ||
| // Prompt files - should be recognized as code | ||
| { | ||
| name: "prompt file without extension", | ||
| filename: "system.prompt", | ||
| expectedType: fileTypeCode, | ||
| }, | ||
| { | ||
| name: "prompt file with .md extension", | ||
| filename: "chain.prompt.md", | ||
| expectedType: fileTypeCode, | ||
| }, | ||
| { | ||
| name: "prompt file with .yaml extension", | ||
| filename: "my.prompt.yaml", | ||
| expectedType: fileTypeCode, | ||
| }, | ||
| { | ||
| name: "prompt file with .txt extension", | ||
| filename: "instruction.prompt.txt", | ||
| expectedType: fileTypeCode, | ||
| }, | ||
| { | ||
| name: "prompt file in subdirectory", | ||
| filename: "prompts/user.prompt", | ||
| expectedType: fileTypeCode, | ||
| }, | ||
| // Agent files - should be recognized as code | ||
| { | ||
| name: "AGENTS.md file", | ||
| filename: "AGENTS.md", | ||
| expectedType: fileTypeCode, | ||
| }, | ||
| { | ||
| name: "agents.md lowercase", | ||
| filename: "agents.md", | ||
| expectedType: fileTypeCode, | ||
| }, | ||
| { | ||
| name: "SKILL.md file", | ||
| filename: "SKILL.md", | ||
| expectedType: fileTypeCode, | ||
| }, | ||
| { | ||
| name: "skill.md lowercase", | ||
| filename: "skill.md", | ||
| expectedType: fileTypeCode, | ||
| }, | ||
| { | ||
| name: "AGENTS.md in subdirectory", | ||
| filename: "docs/AGENTS.md", | ||
| expectedType: fileTypeCode, | ||
| }, | ||
gorkem marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| // Edge cases - should NOT be recognized as prompt/code | ||
| { | ||
| name: "prompt without dot prefix (no leading dot)", | ||
| filename: "prompt.txt", | ||
| expectedType: fileTypeMetadata, // .txt is in metadataSuffixes, doesn't match .prompt pattern | ||
| }, | ||
| { | ||
| name: "prompt with underscore", | ||
| filename: "my_prompt.md", | ||
| expectedType: fileTypeDocs, // .md suffix takes precedence | ||
gorkem marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| }, | ||
| { | ||
| name: "file containing prompt in name", | ||
| filename: "prompter.py", | ||
| expectedType: fileTypeUnknown, | ||
| }, | ||
| // Regular files - should use existing logic | ||
| { | ||
| name: "model file .gguf", | ||
| filename: "model.gguf", | ||
| expectedType: fileTypeModel, | ||
| }, | ||
| { | ||
| name: "dataset file .csv", | ||
| filename: "data.csv", | ||
| expectedType: fileTypeDataset, | ||
| }, | ||
| { | ||
| name: "docs file .md", | ||
| filename: "README.md", | ||
| expectedType: fileTypeDocs, | ||
| }, | ||
| { | ||
| name: "metadata file .json", | ||
| filename: "config.json", | ||
| expectedType: fileTypeMetadata, | ||
| }, | ||
| { | ||
| name: "unknown file .sh", | ||
| filename: "script.sh", | ||
| expectedType: fileTypeUnknown, | ||
| }, | ||
| } | ||
|
|
||
| for _, tt := range tests { | ||
| t.Run(tt.name, func(t *testing.T) { | ||
| result := determineFileType(tt.filename) | ||
| if result != tt.expectedType { | ||
| t.Errorf("determineFileType(%q) = %v, want %v", tt.filename, result, tt.expectedType) | ||
| } | ||
| }) | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The variable name
promptFilePatternsis misleading since it contains agent-related files (AGENTS.md, SKILL.md, CLAUDE.md) that aren't necessarily prompt files. Consider renaming to something more inclusive likeagentAndPromptFilePatternsorcodeFilePatternsto better reflect its purpose of identifying files that should be treated as code.