Skip to content

Commit 0f22345

Browse files
committed
feat: introduce prompt library management
The following subcommands are included: - `list`: lists prompts - `get`: gets a prompt by ID - `create`: creates a prompt - `update`: updates a prompt - `delete`: deletes a prompt - `tags`: manages prompt tags (with subcommands: list, create, update, delete)
1 parent bc9fc81 commit 0f22345

14 files changed

Lines changed: 1947 additions & 0 deletions

cmd/src/prompts.go

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
package main
2+
3+
import (
4+
"flag"
5+
"fmt"
6+
)
7+
8+
var promptsCommands commander
9+
10+
func init() {
11+
usage := `'src prompts' is a tool that manages prompt library prompts and tags in a Sourcegraph instance.
12+
13+
Usage:
14+
15+
src prompts command [command options]
16+
17+
The commands are:
18+
19+
list lists prompts
20+
get get a prompt by ID
21+
create create a prompt
22+
update update a prompt
23+
delete delete a prompt
24+
export export prompts to a JSON file
25+
import import prompts from a JSON file
26+
tags manage prompt tags (use "src prompts tags [command] -h" for more info)
27+
28+
Use "src prompts [command] -h" for more information about a command.
29+
`
30+
31+
flagSet := flag.NewFlagSet("prompts", flag.ExitOnError)
32+
handler := func(args []string) error {
33+
promptsCommands.run(flagSet, "src prompts", usage, args)
34+
return nil
35+
}
36+
37+
// Register the command.
38+
commands = append(commands, &command{
39+
flagSet: flagSet,
40+
handler: handler,
41+
usageFunc: func() {
42+
fmt.Println(usage)
43+
},
44+
})
45+
}
46+
47+
const promptFragment = `
48+
fragment PromptFields on Prompt {
49+
id
50+
name
51+
description
52+
definition {
53+
text
54+
}
55+
draft
56+
visibility
57+
autoSubmit
58+
mode
59+
recommended
60+
tags(first: 100) {
61+
nodes {
62+
id
63+
name
64+
}
65+
}
66+
}
67+
`
68+
69+
const promptTagFragment = `
70+
fragment PromptTagFields on PromptTag {
71+
id
72+
name
73+
}
74+
`
75+
76+
type Prompt struct {
77+
ID string `json:"id"`
78+
Name string `json:"name"`
79+
Description string `json:"description"`
80+
Definition Definition `json:"definition"`
81+
Draft bool `json:"draft"`
82+
Visibility string `json:"visibility"`
83+
AutoSubmit bool `json:"autoSubmit"`
84+
Mode string `json:"mode"`
85+
Recommended bool `json:"recommended"`
86+
Tags PromptTags `json:"tags"`
87+
}
88+
89+
type Definition struct {
90+
Text string `json:"text"`
91+
}
92+
93+
type PromptTags struct {
94+
Nodes []PromptTag `json:"nodes"`
95+
}
96+
97+
type PromptTag struct {
98+
ID string `json:"id"`
99+
Name string `json:"name"`
100+
}

cmd/src/prompts_create.go

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"flag"
6+
"fmt"
7+
"strings"
8+
9+
"github.com/sourcegraph/sourcegraph/lib/errors"
10+
11+
"github.com/sourcegraph/src-cli/internal/api"
12+
)
13+
14+
func init() {
15+
usage := `
16+
Examples:
17+
18+
Create a prompt "Go Error Handling":
19+
20+
$ src prompts create -name="Go Error Handling" \
21+
-description="Best practices for Go error handling" \
22+
-content="When handling errors in Go..." \
23+
-owner=<owner-id>
24+
`
25+
26+
flagSet := flag.NewFlagSet("create", flag.ExitOnError)
27+
usageFunc := func() {
28+
fmt.Fprintf(flag.CommandLine.Output(), "Usage of 'src prompts %s':\n", flagSet.Name())
29+
flagSet.PrintDefaults()
30+
fmt.Println(usage)
31+
}
32+
var (
33+
nameFlag = flagSet.String("name", "", "The prompt name")
34+
descriptionFlag = flagSet.String("description", "", "Description of the prompt")
35+
contentFlag = flagSet.String("content", "", "The prompt template text content")
36+
ownerFlag = flagSet.String("owner", "", "The ID of the owner (user or organization)")
37+
tagsFlag = flagSet.String("tags", "", "Comma-separated list of tag IDs")
38+
draftFlag = flagSet.Bool("draft", false, "Whether the prompt is a draft")
39+
visibilityFlag = flagSet.String("visibility", "PUBLIC", "Visibility of the prompt (PUBLIC or SECRET)")
40+
autoSubmitFlag = flagSet.Bool("auto-submit", false, "Whether the prompt should be automatically executed in one click")
41+
modeFlag = flagSet.String("mode", "CHAT", "Mode to execute prompt (CHAT, EDIT, or INSERT)")
42+
recommendedFlag = flagSet.Bool("recommended", false, "Whether the prompt is recommended")
43+
apiFlags = api.NewFlags(flagSet)
44+
)
45+
46+
handler := func(args []string) error {
47+
if err := flagSet.Parse(args); err != nil {
48+
return err
49+
}
50+
51+
if *nameFlag == "" {
52+
return errors.New("provide a name for the prompt")
53+
}
54+
if *descriptionFlag == "" {
55+
return errors.New("provide a description for the prompt")
56+
}
57+
if *contentFlag == "" {
58+
return errors.New("provide content for the prompt")
59+
}
60+
if *ownerFlag == "" {
61+
return errors.New("provide an owner ID for the prompt")
62+
}
63+
64+
// Validate mode
65+
validModes := map[string]bool{"CHAT": true, "EDIT": true, "INSERT": true}
66+
mode := strings.ToUpper(*modeFlag)
67+
if !validModes[mode] {
68+
return errors.New("mode must be one of: CHAT, EDIT, or INSERT")
69+
}
70+
71+
// Validate visibility
72+
validVisibility := map[string]bool{"PUBLIC": true, "SECRET": true}
73+
visibility := strings.ToUpper(*visibilityFlag)
74+
if !validVisibility[visibility] {
75+
return errors.New("visibility must be either PUBLIC or SECRET")
76+
}
77+
78+
// Parse tags into array
79+
var tagIDs []string
80+
if *tagsFlag != "" {
81+
tagIDs = strings.Split(*tagsFlag, ",")
82+
}
83+
84+
client := cfg.apiClient(apiFlags, flagSet.Output())
85+
86+
query := `mutation CreatePrompt(
87+
$input: PromptInput!
88+
) {
89+
createPrompt(input: $input) {
90+
...PromptFields
91+
}
92+
}
93+
` + promptFragment
94+
95+
input := map[string]interface{}{
96+
"name": *nameFlag,
97+
"description": *descriptionFlag,
98+
"definitionText": *contentFlag,
99+
"owner": *ownerFlag,
100+
"draft": *draftFlag,
101+
"visibility": visibility,
102+
"autoSubmit": *autoSubmitFlag,
103+
"mode": mode,
104+
"recommended": *recommendedFlag,
105+
}
106+
107+
if len(tagIDs) > 0 {
108+
input["tags"] = tagIDs
109+
}
110+
111+
var result struct {
112+
CreatePrompt Prompt
113+
}
114+
if ok, err := client.NewRequest(query, map[string]interface{}{
115+
"input": input,
116+
}).Do(context.Background(), &result); err != nil || !ok {
117+
return err
118+
}
119+
120+
fmt.Printf("Prompt created: %s\n", result.CreatePrompt.ID)
121+
return nil
122+
}
123+
124+
// Register the command.
125+
promptsCommands = append(promptsCommands, &command{
126+
flagSet: flagSet,
127+
handler: handler,
128+
usageFunc: usageFunc,
129+
})
130+
}

cmd/src/prompts_delete.go

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"flag"
6+
"fmt"
7+
8+
"github.com/sourcegraph/sourcegraph/lib/errors"
9+
10+
"github.com/sourcegraph/src-cli/internal/api"
11+
)
12+
13+
func init() {
14+
usage := `
15+
Examples:
16+
17+
Delete a prompt by ID:
18+
19+
$ src prompts delete -id=<prompt-id>
20+
21+
`
22+
23+
flagSet := flag.NewFlagSet("delete", flag.ExitOnError)
24+
usageFunc := func() {
25+
fmt.Fprintf(flag.CommandLine.Output(), "Usage of 'src prompts %s':\n", flagSet.Name())
26+
flagSet.PrintDefaults()
27+
fmt.Println(usage)
28+
}
29+
var (
30+
idFlag = flagSet.String("id", "", "The ID of the prompt to delete")
31+
apiFlags = api.NewFlags(flagSet)
32+
)
33+
34+
handler := func(args []string) error {
35+
if err := flagSet.Parse(args); err != nil {
36+
return err
37+
}
38+
39+
if *idFlag == "" {
40+
return errors.New("provide the ID of the prompt to delete")
41+
}
42+
43+
client := cfg.apiClient(apiFlags, flagSet.Output())
44+
45+
query := `mutation DeletePrompt($id: ID!) {
46+
deletePrompt(id: $id) {
47+
alwaysNil
48+
}
49+
}
50+
`
51+
52+
var result struct {
53+
DeletePrompt struct {
54+
AlwaysNil interface{} `json:"alwaysNil"`
55+
}
56+
}
57+
58+
if ok, err := client.NewRequest(query, map[string]interface{}{
59+
"id": *idFlag,
60+
}).Do(context.Background(), &result); err != nil || !ok {
61+
return err
62+
}
63+
64+
fmt.Println("Prompt deleted successfully.")
65+
return nil
66+
}
67+
68+
// Register the command.
69+
promptsCommands = append(promptsCommands, &command{
70+
flagSet: flagSet,
71+
handler: handler,
72+
usageFunc: usageFunc,
73+
})
74+
}

0 commit comments

Comments
 (0)