From f8de54368897b99fccbeb36e4177accfa1a218d6 Mon Sep 17 00:00:00 2001 From: Michael Brooks Date: Thu, 18 Jun 2026 18:00:43 -0700 Subject: [PATCH 1/2] feat: add agent_view manifest types Adds AgentView and AgentViewAction structs and an AgentView field on AppFeatures so manifests using the new agent_view property survive JSON/YAML round-trips through the CLI. Mirrors AssistantView and reuses the existing SuggestedPrompts type. --- internal/shared/types/app_manifest.go | 12 ++++ internal/shared/types/app_manifest_test.go | 82 ++++++++++++++++++++++ 2 files changed, 94 insertions(+) diff --git a/internal/shared/types/app_manifest.go b/internal/shared/types/app_manifest.go index a9864fc3..61755859 100644 --- a/internal/shared/types/app_manifest.go +++ b/internal/shared/types/app_manifest.go @@ -70,6 +70,7 @@ type DisplayInformation struct { type AppFeatures struct { AppHome ManifestAppHome `json:"app_home,omitempty" yaml:"app_home,flow,omitempty"` + AgentView *AgentView `json:"agent_view,omitempty" yaml:"agent_view,omitempty"` AssistantView *AssistantView `json:"assistant_view,omitempty" yaml:"assistant_view,omitempty"` BotUser BotUser `json:"bot_user,omitempty" yaml:"bot_user,flow,omitempty"` WorkflowSteps []WorkflowStep `json:"workflow_steps,omitempty" yaml:"workflow_steps,flow,omitempty"` @@ -95,6 +96,17 @@ type SuggestedPrompts struct { Message string `json:"message,omitempty" yaml:"message,omitempty"` } +type AgentView struct { + AgentDescription string `json:"agent_description,omitempty" yaml:"agent_description,omitempty"` + SuggestedPrompts []SuggestedPrompts `json:"suggested_prompts,omitempty" yaml:"suggested_prompts,flow,omitempty"` + Actions []AgentViewAction `json:"actions,omitempty" yaml:"actions,flow,omitempty"` +} + +type AgentViewAction struct { + Name string `json:"name,omitempty" yaml:"name,omitempty"` + Description string `json:"description,omitempty" yaml:"description,omitempty"` +} + type OAuthConfig struct { RedirectURLs []string `json:"redirect_urls,omitempty" yaml:"redirect_urls,flow,omitempty"` Scopes *ManifestScopes `json:"scopes,omitempty" yaml:"scopes,flow,omitempty"` diff --git a/internal/shared/types/app_manifest_test.go b/internal/shared/types/app_manifest_test.go index 174ff2d0..6d15193b 100644 --- a/internal/shared/types/app_manifest_test.go +++ b/internal/shared/types/app_manifest_test.go @@ -192,6 +192,40 @@ func Test_AppManifest_AppFeatures(t *testing.T) { }, want: `{"app_home":{},"assistant_view":{"assistant_description":"magic","suggested_prompts":[{"title":"visit the beach","message":"what is glass"}]},"bot_user":{"display_name":"einstein"}}`, }, + "includes agent view when provided": { + features: AppFeatures{ + AgentView: &AgentView{ + AgentDescription: "summarizes threads", + SuggestedPrompts: []SuggestedPrompts{ + { + Title: "summarize this thread", + Message: "please summarize the conversation", + }, + }, + Actions: []AgentViewAction{ + { + Name: "open_settings", + Description: "Open the agent settings panel.", + }, + }, + }, + BotUser: BotUser{ + DisplayName: "agent_smith", + }, + }, + want: `{"app_home":{},"agent_view":{"agent_description":"summarizes threads","suggested_prompts":[{"title":"summarize this thread","message":"please summarize the conversation"}],"actions":[{"name":"open_settings","description":"Open the agent settings panel."}]},"bot_user":{"display_name":"agent_smith"}}`, + }, + "omits agent view fields when empty": { + features: AppFeatures{ + AgentView: &AgentView{ + AgentDescription: "minimal", + }, + BotUser: BotUser{ + DisplayName: "agent_smith", + }, + }, + want: `{"app_home":{},"agent_view":{"agent_description":"minimal"},"bot_user":{"display_name":"agent_smith"}}`, + }, "includes search when provided": { features: AppFeatures{ BotUser: BotUser{ @@ -226,6 +260,54 @@ func Test_AppManifest_AppFeatures(t *testing.T) { } } +func Test_AppManifest_AgentView_RoundTrip(t *testing.T) { + original := AppManifest{ + DisplayInformation: DisplayInformation{Name: "agent_smith"}, + Features: &AppFeatures{ + AgentView: &AgentView{ + AgentDescription: "summarizes threads", + SuggestedPrompts: []SuggestedPrompts{ + {Title: "summarize", Message: "please summarize"}, + }, + Actions: []AgentViewAction{ + {Name: "open_settings", Description: "Open the agent settings panel."}, + }, + }, + }, + } + + t.Run("JSON round-trip preserves agent_view", func(t *testing.T) { + blob, err := json.Marshal(original) + require.NoError(t, err) + assert.Contains(t, string(blob), `"agent_view":{`) + + var got AppManifest + require.NoError(t, json.Unmarshal(blob, &got)) + assert.Equal(t, original.Features.AgentView, got.Features.AgentView) + }) + + t.Run("YAML round-trip preserves agent_view", func(t *testing.T) { + blob, err := yaml.Marshal(original) + require.NoError(t, err) + assert.Contains(t, string(blob), "agent_view:") + assert.Contains(t, string(blob), "agent_description: summarizes threads") + + var got AppManifest + require.NoError(t, yaml.Unmarshal(blob, &got)) + assert.Equal(t, original.Features.AgentView, got.Features.AgentView) + }) + + t.Run("nil agent_view is omitted from JSON", func(t *testing.T) { + manifest := AppManifest{ + DisplayInformation: DisplayInformation{Name: "no_agent"}, + Features: &AppFeatures{BotUser: BotUser{DisplayName: "no_agent"}}, + } + blob, err := json.Marshal(manifest) + require.NoError(t, err) + assert.NotContains(t, string(blob), "agent_view") + }) +} + func Test_AppManifest_AppSettings_SiwsLinks(t *testing.T) { expectedSiws := SiwsLinks{ InitiateURI: "an initiate uri", From 6014806859001e29c5560c862a51cd27bf9b88ef Mon Sep 17 00:00:00 2001 From: Michael Brooks Date: Thu, 18 Jun 2026 21:59:52 -0700 Subject: [PATCH 2/2] test: drop redundant agent_view round-trip test The agent_view JSON marshal cases live in Test_AppManifest_AppFeatures alongside other features. The standalone round-trip test had no precedent for sibling properties like assistant_view. --- internal/shared/types/app_manifest_test.go | 48 ---------------------- 1 file changed, 48 deletions(-) diff --git a/internal/shared/types/app_manifest_test.go b/internal/shared/types/app_manifest_test.go index 6d15193b..405be005 100644 --- a/internal/shared/types/app_manifest_test.go +++ b/internal/shared/types/app_manifest_test.go @@ -260,54 +260,6 @@ func Test_AppManifest_AppFeatures(t *testing.T) { } } -func Test_AppManifest_AgentView_RoundTrip(t *testing.T) { - original := AppManifest{ - DisplayInformation: DisplayInformation{Name: "agent_smith"}, - Features: &AppFeatures{ - AgentView: &AgentView{ - AgentDescription: "summarizes threads", - SuggestedPrompts: []SuggestedPrompts{ - {Title: "summarize", Message: "please summarize"}, - }, - Actions: []AgentViewAction{ - {Name: "open_settings", Description: "Open the agent settings panel."}, - }, - }, - }, - } - - t.Run("JSON round-trip preserves agent_view", func(t *testing.T) { - blob, err := json.Marshal(original) - require.NoError(t, err) - assert.Contains(t, string(blob), `"agent_view":{`) - - var got AppManifest - require.NoError(t, json.Unmarshal(blob, &got)) - assert.Equal(t, original.Features.AgentView, got.Features.AgentView) - }) - - t.Run("YAML round-trip preserves agent_view", func(t *testing.T) { - blob, err := yaml.Marshal(original) - require.NoError(t, err) - assert.Contains(t, string(blob), "agent_view:") - assert.Contains(t, string(blob), "agent_description: summarizes threads") - - var got AppManifest - require.NoError(t, yaml.Unmarshal(blob, &got)) - assert.Equal(t, original.Features.AgentView, got.Features.AgentView) - }) - - t.Run("nil agent_view is omitted from JSON", func(t *testing.T) { - manifest := AppManifest{ - DisplayInformation: DisplayInformation{Name: "no_agent"}, - Features: &AppFeatures{BotUser: BotUser{DisplayName: "no_agent"}}, - } - blob, err := json.Marshal(manifest) - require.NoError(t, err) - assert.NotContains(t, string(blob), "agent_view") - }) -} - func Test_AppManifest_AppSettings_SiwsLinks(t *testing.T) { expectedSiws := SiwsLinks{ InitiateURI: "an initiate uri",