Skip to content

Commit 89d8085

Browse files
authored
feat: add create template for support agent (#467)
1 parent a0b5565 commit 89d8085

File tree

4 files changed

+54
-136
lines changed

4 files changed

+54
-136
lines changed

cmd/project/create_template.go

Lines changed: 18 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import (
2121
"time"
2222

2323
"github.com/slackapi/slack-cli/internal/api"
24-
"github.com/slackapi/slack-cli/internal/experiment"
2524
"github.com/slackapi/slack-cli/internal/iostreams"
2625
"github.com/slackapi/slack-cli/internal/pkg/create"
2726
"github.com/slackapi/slack-cli/internal/shared"
@@ -32,53 +31,9 @@ import (
3231
)
3332

3433
// getSelectionOptions returns the app template options for a given category.
35-
func getSelectionOptions(clients *shared.ClientFactory, categoryID string) []promptObject {
36-
if clients.Config.WithExperimentOn(experiment.Templates) {
37-
templatePromptObjects := map[string]([]promptObject){
38-
"slack-cli#getting-started": {
39-
{
40-
Title: fmt.Sprintf("Bolt for JavaScript %s", style.Secondary("Node.js")),
41-
Repository: "slack-samples/bolt-js-starter-template",
42-
},
43-
{
44-
Title: fmt.Sprintf("Bolt for Python %s", style.Secondary("Python")),
45-
Repository: "slack-samples/bolt-python-starter-template",
46-
},
47-
},
48-
"slack-cli#ai-apps": {
49-
{
50-
Title: fmt.Sprintf("Support Agent %s", style.Secondary("Resolve IT support cases")),
51-
Repository: "slack-cli#ai-apps/support-agent",
52-
},
53-
{
54-
Title: fmt.Sprintf("Custom Agent %s", style.Secondary("Start from scratch")),
55-
Repository: "slack-cli#ai-apps/custom-agent",
56-
},
57-
},
58-
"slack-cli#automation-apps": {
59-
{
60-
Title: fmt.Sprintf("Bolt for JavaScript %s", style.Secondary("Node.js")),
61-
Repository: "slack-samples/bolt-js-custom-function-template",
62-
},
63-
{
64-
Title: fmt.Sprintf("Bolt for Python %s", style.Secondary("Python")),
65-
Repository: "slack-samples/bolt-python-custom-function-template",
66-
},
67-
{
68-
Title: fmt.Sprintf("Deno Slack SDK %s", style.Secondary("Deno")),
69-
Repository: "slack-samples/deno-starter-template",
70-
},
71-
},
72-
}
73-
return templatePromptObjects[categoryID]
74-
}
75-
76-
if strings.TrimSpace(categoryID) == "" {
77-
categoryID = "slack-cli#getting-started"
78-
}
79-
34+
func getSelectionOptions(categoryID string) []promptObject {
8035
templatePromptObjects := map[string]([]promptObject){
81-
"slack-cli#getting-started": []promptObject{
36+
"slack-cli#getting-started": {
8237
{
8338
Title: fmt.Sprintf("Bolt for JavaScript %s", style.Secondary("Node.js")),
8439
Repository: "slack-samples/bolt-js-starter-template",
@@ -88,6 +43,16 @@ func getSelectionOptions(clients *shared.ClientFactory, categoryID string) []pro
8843
Repository: "slack-samples/bolt-python-starter-template",
8944
},
9045
},
46+
"slack-cli#ai-apps": {
47+
{
48+
Title: fmt.Sprintf("Support Agent %s", style.Secondary("Resolve IT support cases")),
49+
Repository: "slack-cli#ai-apps/support-agent",
50+
},
51+
{
52+
Title: fmt.Sprintf("Custom Agent %s", style.Secondary("Start from scratch")),
53+
Repository: "slack-cli#ai-apps/custom-agent",
54+
},
55+
},
9156
"slack-cli#automation-apps": {
9257
{
9358
Title: fmt.Sprintf("Bolt for JavaScript %s", style.Secondary("Node.js")),
@@ -102,18 +67,7 @@ func getSelectionOptions(clients *shared.ClientFactory, categoryID string) []pro
10267
Repository: "slack-samples/deno-starter-template",
10368
},
10469
},
105-
"slack-cli#ai-apps": {
106-
{
107-
Title: fmt.Sprintf("Bolt for JavaScript %s", style.Secondary("Node.js")),
108-
Repository: "slack-samples/bolt-js-assistant-template",
109-
},
110-
{
111-
Title: fmt.Sprintf("Bolt for Python %s", style.Secondary("Python")),
112-
Repository: "slack-samples/bolt-python-assistant-template",
113-
},
114-
},
11570
}
116-
11771
return templatePromptObjects[categoryID]
11872
}
11973

@@ -243,14 +197,10 @@ func promptTemplateSelection(cmd *cobra.Command, clients *shared.ClientFactory,
243197

244198
// Prompt for the example template
245199
prompt := "Select a language:"
246-
if clients.Config.WithExperimentOn(experiment.Templates) {
247-
if categoryID == "slack-cli#ai-apps" {
248-
prompt = "Select a template:"
249-
} else {
250-
prompt = "Select a language:"
251-
}
200+
if categoryID == "slack-cli#ai-apps" {
201+
prompt = "Select a template:"
252202
}
253-
options := getSelectionOptions(clients, categoryID)
203+
options := getSelectionOptions(categoryID)
254204
titles := make([]string, len(options))
255205
for i, m := range options {
256206
titles[i] = m.Title
@@ -348,28 +298,18 @@ func listTemplates(ctx context.Context, clients *shared.ClientFactory, categoryS
348298
}
349299

350300
var categories []categoryInfo
351-
if categoryShortcut == "agent" && clients.Config.WithExperimentOn(experiment.Templates) {
301+
if categoryShortcut == "agent" {
352302
categories = []categoryInfo{
353303
{id: "slack-cli#ai-apps/support-agent", name: "Support agent"},
354304
{id: "slack-cli#ai-apps/custom-agent", name: "Custom agent"},
355305
}
356-
} else if categoryShortcut == "agent" {
357-
categories = []categoryInfo{
358-
{id: "slack-cli#ai-apps", name: "AI Agent apps"},
359-
}
360-
} else if clients.Config.WithExperimentOn(experiment.Templates) {
306+
} else {
361307
categories = []categoryInfo{
362308
{id: "slack-cli#getting-started", name: "Getting started"},
363309
{id: "slack-cli#ai-apps/support-agent", name: "Support agent"},
364310
{id: "slack-cli#ai-apps/custom-agent", name: "Custom agent"},
365311
{id: "slack-cli#automation-apps", name: "Automation apps"},
366312
}
367-
} else {
368-
categories = []categoryInfo{
369-
{id: "slack-cli#getting-started", name: "Getting started"},
370-
{id: "slack-cli#ai-apps", name: "AI Agent apps"},
371-
{id: "slack-cli#automation-apps", name: "Automation apps"},
372-
}
373313
}
374314

375315
for _, category := range categories {
@@ -383,7 +323,7 @@ func listTemplates(ctx context.Context, clients *shared.ClientFactory, categoryS
383323
secondary = append(secondary, repo)
384324
}
385325
} else {
386-
for _, tmpl := range getSelectionOptions(clients, category.id) {
326+
for _, tmpl := range getSelectionOptions(category.id) {
387327
secondary = append(secondary, tmpl.Repository)
388328
}
389329
}

cmd/project/create_test.go

Lines changed: 36 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,15 @@ func TestCreateCommand(t *testing.T) {
120120
CmdArgs: []string{"agent"},
121121
Setup: func(t *testing.T, ctx context.Context, cm *shared.ClientsMock, cf *shared.ClientFactory) {
122122
cm.IO.On("IsTTY").Return(true)
123-
// Should skip category prompt and go directly to language selection
123+
// Should skip category prompt and go directly to template selection
124+
cm.IO.On("SelectPrompt", mock.Anything, "Select a template:", mock.Anything, mock.Anything).
125+
Return(
126+
iostreams.SelectPromptResponse{
127+
Prompt: true,
128+
Index: 1, // Select Custom Agent
129+
},
130+
nil,
131+
)
124132
cm.IO.On("SelectPrompt", mock.Anything, "Select a language:", mock.Anything, mock.Anything).
125133
Return(
126134
iostreams.SelectPromptResponse{
@@ -151,7 +159,15 @@ func TestCreateCommand(t *testing.T) {
151159
"creates an agent app with app name using agent argument": {
152160
CmdArgs: []string{"agent", "my-agent-app"},
153161
Setup: func(t *testing.T, ctx context.Context, cm *shared.ClientsMock, cf *shared.ClientFactory) {
154-
// Should skip category prompt and go directly to language selection
162+
// Should skip category prompt and go directly to template selection
163+
cm.IO.On("SelectPrompt", mock.Anything, "Select a template:", mock.Anything, mock.Anything).
164+
Return(
165+
iostreams.SelectPromptResponse{
166+
Prompt: true,
167+
Index: 1, // Select Custom Agent
168+
},
169+
nil,
170+
)
155171
cm.IO.On("SelectPrompt", mock.Anything, "Select a language:", mock.Anything, mock.Anything).
156172
Return(
157173
iostreams.SelectPromptResponse{
@@ -178,12 +194,9 @@ func TestCreateCommand(t *testing.T) {
178194
cm.IO.AssertNotCalled(t, "InputPrompt", mock.Anything, "Name your app:", mock.Anything)
179195
},
180196
},
181-
"creates a pydantic ai agent app with templates experiment": {
197+
"creates a pydantic ai agent app": {
182198
CmdArgs: []string{"my-pydantic-app"},
183199
Setup: func(t *testing.T, ctx context.Context, cm *shared.ClientsMock, cf *shared.ClientFactory) {
184-
cm.AddDefaultMocks()
185-
cm.Config.ExperimentsFlag = append(cm.Config.ExperimentsFlag, "templates")
186-
cm.Config.LoadExperiments(ctx, cm.IO.PrintDebug)
187200
cm.IO.On("SelectPrompt", mock.Anything, "Select an app:", mock.Anything, mock.Anything).
188201
Return(iostreams.SelectPromptResponse{Prompt: true, Index: 1}, nil)
189202
cm.IO.On("SelectPrompt", mock.Anything, "Select a template:", mock.Anything, mock.Anything).
@@ -283,6 +296,14 @@ func TestCreateCommand(t *testing.T) {
283296
CmdArgs: []string{"agent", "--name", "my-custom-name"},
284297
Setup: func(t *testing.T, ctx context.Context, cm *shared.ClientsMock, cf *shared.ClientFactory) {
285298
// Should skip category prompt due to agent shortcut
299+
cm.IO.On("SelectPrompt", mock.Anything, "Select a template:", mock.Anything, mock.Anything).
300+
Return(
301+
iostreams.SelectPromptResponse{
302+
Prompt: true,
303+
Index: 1, // Select Custom Agent
304+
},
305+
nil,
306+
)
286307
cm.IO.On("SelectPrompt", mock.Anything, "Select a language:", mock.Anything, mock.Anything).
287308
Return(
288309
iostreams.SelectPromptResponse{
@@ -346,6 +367,14 @@ func TestCreateCommand(t *testing.T) {
346367
CmdArgs: []string{"agent", "my-project", "--name", "my-name"},
347368
Setup: func(t *testing.T, ctx context.Context, cm *shared.ClientsMock, cf *shared.ClientFactory) {
348369
// Should skip category prompt due to agent shortcut
370+
cm.IO.On("SelectPrompt", mock.Anything, "Select a template:", mock.Anything, mock.Anything).
371+
Return(
372+
iostreams.SelectPromptResponse{
373+
Prompt: true,
374+
Index: 1, // Select Custom Agent
375+
},
376+
nil,
377+
)
349378
cm.IO.On("SelectPrompt", mock.Anything, "Select a language:", mock.Anything, mock.Anything).
350379
Return(
351380
iostreams.SelectPromptResponse{
@@ -567,49 +596,6 @@ func TestCreateCommand(t *testing.T) {
567596
createClientMock = new(CreateClientMock)
568597
CreateFunc = createClientMock.Create
569598
},
570-
ExpectedOutputs: []string{
571-
"Getting started",
572-
"AI Agent apps",
573-
"Automation apps",
574-
"slack-samples/bolt-js-starter-template",
575-
"slack-samples/bolt-python-starter-template",
576-
"slack-samples/bolt-js-assistant-template",
577-
"slack-samples/bolt-python-assistant-template",
578-
"slack-samples/bolt-js-custom-function-template",
579-
"slack-samples/bolt-python-custom-function-template",
580-
"slack-samples/deno-starter-template",
581-
},
582-
ExpectedAsserts: func(t *testing.T, ctx context.Context, cm *shared.ClientsMock) {
583-
createClientMock.AssertNotCalled(t, "Create", mock.Anything, mock.Anything, mock.Anything)
584-
},
585-
},
586-
"lists agent templates with agent --list flag": {
587-
CmdArgs: []string{"agent", "--list"},
588-
Setup: func(t *testing.T, ctx context.Context, cm *shared.ClientsMock, cf *shared.ClientFactory) {
589-
createClientMock = new(CreateClientMock)
590-
CreateFunc = createClientMock.Create
591-
},
592-
ExpectedOutputs: []string{
593-
"AI Agent apps",
594-
"slack-samples/bolt-js-assistant-template",
595-
"slack-samples/bolt-python-assistant-template",
596-
},
597-
ExpectedAsserts: func(t *testing.T, ctx context.Context, cm *shared.ClientsMock) {
598-
createClientMock.AssertNotCalled(t, "Create", mock.Anything, mock.Anything, mock.Anything)
599-
output := cm.GetCombinedOutput()
600-
assert.NotContains(t, output, "Getting started")
601-
assert.NotContains(t, output, "Automation apps")
602-
},
603-
},
604-
"lists all templates with --list flag and templates experiment": {
605-
CmdArgs: []string{"--list"},
606-
Setup: func(t *testing.T, ctx context.Context, cm *shared.ClientsMock, cf *shared.ClientFactory) {
607-
cm.AddDefaultMocks()
608-
cm.Config.ExperimentsFlag = append(cm.Config.ExperimentsFlag, "templates")
609-
cm.Config.LoadExperiments(ctx, cm.IO.PrintDebug)
610-
createClientMock = new(CreateClientMock)
611-
CreateFunc = createClientMock.Create
612-
},
613599
ExpectedOutputs: []string{
614600
"Getting started",
615601
"slack-samples/bolt-js-starter-template",
@@ -630,12 +616,9 @@ func TestCreateCommand(t *testing.T) {
630616
createClientMock.AssertNotCalled(t, "Create", mock.Anything, mock.Anything, mock.Anything)
631617
},
632618
},
633-
"lists agent templates with agent --list flag and templates experiment": {
619+
"lists agent templates with agent --list flag": {
634620
CmdArgs: []string{"agent", "--list"},
635621
Setup: func(t *testing.T, ctx context.Context, cm *shared.ClientsMock, cf *shared.ClientFactory) {
636-
cm.AddDefaultMocks()
637-
cm.Config.ExperimentsFlag = append(cm.Config.ExperimentsFlag, "templates")
638-
cm.Config.LoadExperiments(ctx, cm.IO.PrintDebug)
639622
createClientMock = new(CreateClientMock)
640623
CreateFunc = createClientMock.Create
641624
},

docs/reference/experiments.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ The following is a list of currently available experiments. We'll remove experim
88

99
- `lipgloss`: shows pretty styles.
1010
- `sandboxes`: enables users who have joined the Slack Developer Program to manage their sandboxes ([PR#379](https://github.com/slackapi/slack-cli/pull/379)).
11-
- `templates`: brings more agent templates to the `create` command.
1211

1312
## Experiments changelog
1413

internal/experiment/experiment.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,6 @@ const (
3838

3939
// Sandboxes experiment lets users who have joined the Slack Developer Program use the CLI to manage their sandboxes.
4040
Sandboxes Experiment = "sandboxes"
41-
42-
// Templates experiment brings more agent templates to the create command.
43-
Templates Experiment = "templates"
4441
)
4542

4643
// AllExperiments is a list of all available experiments that can be enabled
@@ -49,7 +46,6 @@ var AllExperiments = []Experiment{
4946
Lipgloss,
5047
Placeholder,
5148
Sandboxes,
52-
Templates,
5349
}
5450

5551
// EnabledExperiments is a list of experiments that are permanently enabled

0 commit comments

Comments
 (0)