diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index a93bec32f..6a92a112f 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -59,10 +59,13 @@ jobs:
if [ -n "${{ github.event.inputs.version }}" ]; then
VERSION="${{ github.event.inputs.version }}"
# Validate version format matches dist-tag
- # TEMPORARY: skips validation for "latest" so prerelease versions
- # can be published under that tag. To ship stable 1.0.0, revert the
- # commit that introduced this temporary change.
- if [ "${{ github.event.inputs.dist-tag }}" != "latest" ]; then
+ if [ "${{ github.event.inputs.dist-tag }}" = "latest" ]; then
+ if [[ "$VERSION" == *-* ]]; then
+ echo "❌ Error: Version '$VERSION' has a prerelease suffix but dist-tag is 'latest'" >> $GITHUB_STEP_SUMMARY
+ echo "Use a version without suffix (e.g., '1.0.0') for latest releases"
+ exit 1
+ fi
+ else
if [[ "$VERSION" != *-* ]]; then
echo "❌ Error: Version '$VERSION' has no prerelease suffix but dist-tag is '${{ github.event.inputs.dist-tag }}'" >> $GITHUB_STEP_SUMMARY
echo "Use a version with suffix (e.g., '1.0.0-preview.0') for prerelease/unstable"
@@ -231,11 +234,21 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6.0.2
- # TEMPORARY: both "latest" and "prerelease" create GitHub pre-releases
- # since "latest" publishes beta versions. To ship stable 1.0.0, revert
- # the commit that introduced this temporary change.
- name: Create GitHub Release
- if: github.event.inputs.dist-tag == 'latest' || github.event.inputs.dist-tag == 'prerelease'
+ if: github.event.inputs.dist-tag == 'latest'
+ run: |
+ NOTES_FLAG=""
+ if git rev-parse "v${{ needs.version.outputs.current }}" >/dev/null 2>&1; then
+ NOTES_FLAG="--notes-start-tag v${{ needs.version.outputs.current }}"
+ fi
+ gh release create "v${{ needs.version.outputs.version }}" \
+ --title "v${{ needs.version.outputs.version }}" \
+ --generate-notes $NOTES_FLAG \
+ --target ${{ github.sha }}
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ - name: Create GitHub Pre-Release
+ if: github.event.inputs.dist-tag == 'prerelease'
run: |
NOTES_FLAG=""
if git rev-parse "v${{ needs.version.outputs.current-prerelease }}" >/dev/null 2>&1; then
diff --git a/docs/auth/byok.md b/docs/auth/byok.md
index 504602fd3..6f2d20633 100644
--- a/docs/auth/byok.md
+++ b/docs/auth/byok.md
@@ -409,7 +409,7 @@ func main() {
Name: "My Custom Model",
Capabilities: copilot.ModelCapabilities{
Supports: copilot.ModelSupports{Vision: false, ReasoningEffort: false},
- Limits: copilot.ModelLimits{MaxContextWindowTokens: 128000},
+ Limits: copilot.ModelLimits{MaxContextWindowTokens: copilot.Int(128000)},
},
},
}, nil
@@ -478,7 +478,7 @@ When using BYOK, be aware of these limitations:
### Identity limitations
-BYOK authentication uses **static credentials only**.
+BYOK authentication uses **static credentials only**.
You must use an API key or static bearer token that you manage yourself.
diff --git a/docs/features/mcp.md b/docs/features/mcp.md
index e974532b0..6f715bd2e 100644
--- a/docs/features/mcp.md
+++ b/docs/features/mcp.md
@@ -120,7 +120,7 @@ func main() {
"my-local-server": copilot.MCPStdioServerConfig{
Command: "node",
Args: []string{"./mcp-server.js"},
- Tools: &[]string{"*"},
+ Tools: []string{"*"},
},
},
})
diff --git a/go/README.md b/go/README.md
index 92e7cad0f..0ceaabb73 100644
--- a/go/README.md
+++ b/go/README.md
@@ -810,11 +810,10 @@ name, ok, err := ui.Input(ctx, "Enter the release name", &copilot.UIInputOptions
})
// Full custom elicitation with a schema
-result, err := ui.Elicitation(ctx, "Configure deployment", rpc.RequestedSchema{
- Type: rpc.RequestedSchemaTypeObject,
- Properties: map[string]rpc.Property{
- "target": {Type: rpc.PropertyTypeString, Enum: []string{"staging", "production"}},
- "force": {Type: rpc.PropertyTypeBoolean},
+result, err := ui.Elicitation(ctx, "Configure deployment", copilot.ElicitationSchema{
+ Properties: map[string]any{
+ "target": map[string]any{"type": "string", "enum": []string{"staging", "production"}},
+ "force": map[string]any{"type": "boolean"},
},
Required: []string{"target"},
})
@@ -839,7 +838,7 @@ session, err := client.CreateSession(ctx, &copilot.SessionConfig{
// Return the user's response
return copilot.ElicitationResult{
- Action: "accept",
+ Action: copilot.ElicitationActionAccept,
Content: map[string]any{"confirmed": true},
}, nil
},
diff --git a/go/client_test.go b/go/client_test.go
index 6236a95ab..d5ba47da8 100644
--- a/go/client_test.go
+++ b/go/client_test.go
@@ -867,7 +867,7 @@ func TestListModelsWithCustomHandler(t *testing.T) {
Name: "My Custom Model",
Capabilities: ModelCapabilities{
Supports: ModelSupports{Vision: false, ReasoningEffort: false},
- Limits: ModelLimits{MaxContextWindowTokens: 128000},
+ Limits: ModelLimits{MaxContextWindowTokens: Int(128000)},
},
},
}
@@ -899,7 +899,7 @@ func TestListModelsHandlerCachesResults(t *testing.T) {
Name: "Cached Model",
Capabilities: ModelCapabilities{
Supports: ModelSupports{Vision: false, ReasoningEffort: false},
- Limits: ModelLimits{MaxContextWindowTokens: 128000},
+ Limits: ModelLimits{MaxContextWindowTokens: Int(128000)},
},
},
}
diff --git a/go/internal/e2e/commands_and_elicitation_e2e_test.go b/go/internal/e2e/commands_and_elicitation_e2e_test.go
index 45d54dde9..8d2d40f2f 100644
--- a/go/internal/e2e/commands_and_elicitation_e2e_test.go
+++ b/go/internal/e2e/commands_and_elicitation_e2e_test.go
@@ -437,7 +437,7 @@ func TestUIElicitationCallbackE2E(t *testing.T) {
session, err := client.CreateSession(t.Context(), &copilot.SessionConfig{
OnPermissionRequest: copilot.PermissionHandler.ApproveAll,
OnElicitationRequest: func(ctx copilot.ElicitationContext) (copilot.ElicitationResult, error) {
- return copilot.ElicitationResult{Action: "accept", Content: map[string]any{}}, nil
+ return copilot.ElicitationResult{Action: copilot.ElicitationActionAccept, Content: map[string]any{}}, nil
},
})
if err != nil {
@@ -481,7 +481,7 @@ func TestUIElicitationCallbackE2E(t *testing.T) {
t.Errorf("Expected RequestedSchema to contain 'confirmed' property")
}
return copilot.ElicitationResult{
- Action: "accept",
+ Action: copilot.ElicitationActionAccept,
Content: map[string]any{"confirmed": true},
}, nil
},
@@ -505,7 +505,7 @@ func TestUIElicitationCallbackE2E(t *testing.T) {
session, err := client.CreateSession(t.Context(), &copilot.SessionConfig{
OnPermissionRequest: copilot.PermissionHandler.ApproveAll,
OnElicitationRequest: func(ec copilot.ElicitationContext) (copilot.ElicitationResult, error) {
- return copilot.ElicitationResult{Action: "decline"}, nil
+ return copilot.ElicitationResult{Action: copilot.ElicitationActionDecline}, nil
},
})
if err != nil {
@@ -534,7 +534,7 @@ func TestUIElicitationCallbackE2E(t *testing.T) {
t.Errorf("Expected RequestedSchema to contain 'selection' property")
}
return copilot.ElicitationResult{
- Action: "accept",
+ Action: copilot.ElicitationActionAccept,
Content: map[string]any{"selection": "beta"},
}, nil
},
@@ -568,7 +568,7 @@ func TestUIElicitationCallbackE2E(t *testing.T) {
t.Errorf("Expected RequestedSchema to contain 'value' property")
}
return copilot.ElicitationResult{
- Action: "accept",
+ Action: copilot.ElicitationActionAccept,
Content: map[string]any{"value": "typed value"},
}, nil
},
@@ -601,9 +601,9 @@ func TestUIElicitationCallbackE2E(t *testing.T) {
ctx.ConfigureForTest(t)
responses := []copilot.ElicitationResult{
- {Action: "accept", Content: map[string]any{"name": "Mona"}},
- {Action: "decline"},
- {Action: "cancel"},
+ {Action: copilot.ElicitationActionAccept, Content: map[string]any{"name": "Mona"}},
+ {Action: copilot.ElicitationActionDecline},
+ {Action: copilot.ElicitationActionCancel},
}
var idx int
@@ -625,9 +625,8 @@ func TestUIElicitationCallbackE2E(t *testing.T) {
t.Fatalf("CreateSession failed: %v", err)
}
- schema := rpc.UIElicitationSchema{
- Type: rpc.UIElicitationSchemaTypeObject,
- Properties: map[string]rpc.UIElicitationSchemaProperty{
+ schema := copilot.ElicitationSchema{
+ Properties: map[string]any{
"name": &rpc.UIElicitationSchemaPropertyString{},
},
Required: []string{"name"},
@@ -637,10 +636,10 @@ func TestUIElicitationCallbackE2E(t *testing.T) {
if err != nil {
t.Fatalf("Elicitation accept call failed: %v", err)
}
- if accept.Action != "accept" {
+ if accept.Action != copilot.ElicitationActionAccept {
t.Errorf("Expected accept.Action='accept', got %q", accept.Action)
}
- if accept.Content == nil || fmt.Sprintf("%v", accept.Content["name"]) != "Mona" {
+ if accept.Content == nil || accept.Content["name"] != "Mona" {
t.Errorf("Expected accept.Content[name]='Mona', got %v", accept.Content)
}
@@ -648,7 +647,7 @@ func TestUIElicitationCallbackE2E(t *testing.T) {
if err != nil {
t.Fatalf("Elicitation decline call failed: %v", err)
}
- if decline.Action != "decline" {
+ if decline.Action != copilot.ElicitationActionDecline {
t.Errorf("Expected decline.Action='decline', got %q", decline.Action)
}
@@ -656,7 +655,7 @@ func TestUIElicitationCallbackE2E(t *testing.T) {
if err != nil {
t.Fatalf("Elicitation cancel call failed: %v", err)
}
- if cancel.Action != "cancel" {
+ if cancel.Action != copilot.ElicitationActionCancel {
t.Errorf("Expected cancel.Action='cancel', got %q", cancel.Action)
}
})
@@ -681,7 +680,7 @@ func TestUIElicitationCallbackE2E(t *testing.T) {
session, err := client.CreateSession(t.Context(), &copilot.SessionConfig{
OnPermissionRequest: copilot.PermissionHandler.ApproveAll,
OnElicitationRequest: func(ec copilot.ElicitationContext) (copilot.ElicitationResult, error) {
- return copilot.ElicitationResult{Action: "accept", Content: map[string]any{}}, nil
+ return copilot.ElicitationResult{Action: copilot.ElicitationActionAccept, Content: map[string]any{}}, nil
},
})
if err != nil {
@@ -694,29 +693,14 @@ func TestUIElicitationCallbackE2E(t *testing.T) {
})
}
-// schemaHasProperty reports whether the elicitation schema map has a top-level
-// property with the given name. RequestedSchema["properties"] is typically a
-// map[string]rpc.UIElicitationSchemaProperty, but we accept any map[string]X.
-func schemaHasProperty(schema map[string]any, name string) bool {
+// schemaHasProperty reports whether the elicitation schema has a top-level
+// property with the given name.
+func schemaHasProperty(schema *copilot.ElicitationSchema, name string) bool {
if schema == nil {
return false
}
- props, ok := schema["properties"]
- if !ok || props == nil {
- return false
- }
- switch p := props.(type) {
- case map[string]any:
- _, found := p[name]
- return found
- case map[string]rpc.UIElicitationSchemaProperty:
- _, found := p[name]
- return found
- default:
- // Fallback: marshal/unmarshal via reflection-friendly route.
- // For test diagnostic purposes we treat unknown shapes as not found.
- return false
- }
+ _, found := schema.Properties[name]
+ return found
}
func TestUIElicitationMultiClientE2E(t *testing.T) {
@@ -776,7 +760,7 @@ func TestUIElicitationMultiClientE2E(t *testing.T) {
OnPermissionRequest: copilot.PermissionHandler.ApproveAll,
SuppressResumeEvent: true,
OnElicitationRequest: func(ctx copilot.ElicitationContext) (copilot.ElicitationResult, error) {
- return copilot.ElicitationResult{Action: "accept", Content: map[string]any{}}, nil
+ return copilot.ElicitationResult{Action: copilot.ElicitationActionAccept, Content: map[string]any{}}, nil
},
})
if err != nil {
@@ -836,7 +820,7 @@ func TestUIElicitationMultiClientE2E(t *testing.T) {
OnPermissionRequest: copilot.PermissionHandler.ApproveAll,
SuppressResumeEvent: true,
OnElicitationRequest: func(ctx copilot.ElicitationContext) (copilot.ElicitationResult, error) {
- return copilot.ElicitationResult{Action: "accept", Content: map[string]any{}}, nil
+ return copilot.ElicitationResult{Action: copilot.ElicitationActionAccept, Content: map[string]any{}}, nil
},
})
if err != nil {
diff --git a/go/internal/e2e/mcp_and_agents_e2e_test.go b/go/internal/e2e/mcp_and_agents_e2e_test.go
index dd2ff228b..e4bd34e26 100644
--- a/go/internal/e2e/mcp_and_agents_e2e_test.go
+++ b/go/internal/e2e/mcp_and_agents_e2e_test.go
@@ -59,7 +59,7 @@ func TestMCPServersE2E(t *testing.T) {
mcpServers := map[string]copilot.MCPServerConfig{
"test-server": copilot.MCPStdioServerConfig{
Command: "git",
- Tools: &[]string{"*"},
+ Tools: []string{"*"},
},
}
@@ -125,7 +125,7 @@ func TestMCPServersE2E(t *testing.T) {
"env-echo": copilot.MCPStdioServerConfig{
Command: "node",
Args: []string{mcpServerPath},
- Tools: &[]string{"*"},
+ Tools: []string{"*"},
Env: map[string]string{"TEST_SECRET": "hunter2"},
WorkingDirectory: mcpServerDir,
},
diff --git a/go/internal/e2e/mcp_server_helpers_test.go b/go/internal/e2e/mcp_server_helpers_test.go
index 54c75e08c..1860067ed 100644
--- a/go/internal/e2e/mcp_server_helpers_test.go
+++ b/go/internal/e2e/mcp_server_helpers_test.go
@@ -23,7 +23,7 @@ func testMCPServers(t *testing.T, serverNames ...string) map[string]copilot.MCPS
mcpServers[serverName] = copilot.MCPStdioServerConfig{
Command: "node",
Args: []string{mcpServerPath},
- Tools: &[]string{"*"},
+ Tools: []string{"*"},
WorkingDirectory: mcpServerDir,
}
}
diff --git a/go/internal/e2e/pre_mcp_tool_call_hook_e2e_test.go b/go/internal/e2e/pre_mcp_tool_call_hook_e2e_test.go
index 6dfb5b1b7..184727092 100644
--- a/go/internal/e2e/pre_mcp_tool_call_hook_e2e_test.go
+++ b/go/internal/e2e/pre_mcp_tool_call_hook_e2e_test.go
@@ -19,13 +19,12 @@ func TestPreMCPToolCallHookE2E(t *testing.T) {
metaEchoServer := filepath.Join(testHarnessDir, "test-mcp-meta-echo-server.mjs")
metaEchoConfig := func() map[string]copilot.MCPServerConfig {
- tools := []string{"*"}
return map[string]copilot.MCPServerConfig{
"meta-echo": copilot.MCPStdioServerConfig{
Command: "node",
Args: []string{metaEchoServer},
WorkingDirectory: testHarnessDir,
- Tools: &tools,
+ Tools: []string{"*"},
},
}
}
diff --git a/go/internal/e2e/rpc_tasks_and_handlers_e2e_test.go b/go/internal/e2e/rpc_tasks_and_handlers_e2e_test.go
index cbaa92f9e..60ae3f1fd 100644
--- a/go/internal/e2e/rpc_tasks_and_handlers_e2e_test.go
+++ b/go/internal/e2e/rpc_tasks_and_handlers_e2e_test.go
@@ -311,7 +311,7 @@ func TestRPCTasksAndHandlersE2E(t *testing.T) {
OnElicitationRequest: func(ctx copilot.ElicitationContext) (copilot.ElicitationResult, error) {
handlerContext <- ctx
return copilot.ElicitationResult{
- Action: "accept",
+ Action: copilot.ElicitationActionAccept,
Content: map[string]any{
"answer": "from handler",
"confirmed": true,
@@ -347,7 +347,7 @@ func TestRPCTasksAndHandlersE2E(t *testing.T) {
if ctx.SessionID != session.SessionID || ctx.Message != "Need details" {
t.Fatalf("Unexpected elicitation context: %+v", ctx)
}
- if _, ok := ctx.RequestedSchema["properties"]; !ok {
+ if ctx.RequestedSchema == nil || ctx.RequestedSchema.Properties == nil {
t.Fatalf("Expected requested schema to include properties, got %+v", ctx.RequestedSchema)
}
if response.Action != rpc.UIElicitationResponseActionAccept {
diff --git a/go/rpc/zrpc.go b/go/rpc/zrpc.go
index 730d0f9fb..d6ae99b6c 100644
--- a/go/rpc/zrpc.go
+++ b/go/rpc/zrpc.go
@@ -2204,14 +2204,14 @@ type MCPServer struct {
// Set to `true` to use defaults, or provide an object with additional auth or OIDC settings.
type MCPServerAuthConfig interface {
- mCPServerAuthConfig()
+ mcpServerAuthConfig()
}
type MCPServerAuthConfigBoolean bool
-func (MCPServerAuthConfigBoolean) mCPServerAuthConfig() {}
+func (MCPServerAuthConfigBoolean) mcpServerAuthConfig() {}
-func (MCPServerAuthConfigRedirectPort) mCPServerAuthConfig() {}
+func (MCPServerAuthConfigRedirectPort) mcpServerAuthConfig() {}
// Authentication settings with optional redirect port configuration.
type MCPServerAuthConfigRedirectPort struct {
@@ -2221,14 +2221,14 @@ type MCPServerAuthConfigRedirectPort struct {
// MCP server configuration (stdio process or remote HTTP/SSE)
type MCPServerConfig interface {
- mCPServerConfig()
+ mcpServerConfig()
}
type RawMCPServerConfigData struct {
Raw json.RawMessage
}
-func (RawMCPServerConfigData) mCPServerConfig() {}
+func (RawMCPServerConfigData) mcpServerConfig() {}
// Remote MCP server configuration accessed over HTTP or SSE.
type MCPServerConfigHTTP struct {
@@ -2260,7 +2260,7 @@ type MCPServerConfigHTTP struct {
URL string `json:"url"`
}
-func (MCPServerConfigHTTP) mCPServerConfig() {}
+func (MCPServerConfigHTTP) mcpServerConfig() {}
// Stdio MCP server configuration launched as a child process.
type MCPServerConfigStdio struct {
@@ -2288,7 +2288,7 @@ type MCPServerConfigStdio struct {
Tools []string `json:"tools,omitzero"`
}
-func (MCPServerConfigStdio) mCPServerConfig() {}
+func (MCPServerConfigStdio) mcpServerConfig() {}
// MCP servers configured for the session, with their connection status.
// Experimental: MCPServerList is part of an experimental API and may change or be removed.
@@ -6115,24 +6115,24 @@ type UIElicitationArrayEnumFieldItems struct {
// Experimental: UIElicitationFieldValue is part of an experimental API and may change or be
// removed.
type UIElicitationFieldValue interface {
- uIElicitationFieldValue()
+ uiElicitationFieldValue()
}
type UIElicitationBooleanValue bool
-func (UIElicitationBooleanValue) uIElicitationFieldValue() {}
+func (UIElicitationBooleanValue) uiElicitationFieldValue() {}
type UIElicitationNumberValue float64
-func (UIElicitationNumberValue) uIElicitationFieldValue() {}
+func (UIElicitationNumberValue) uiElicitationFieldValue() {}
type UIElicitationStringArrayValue []string
-func (UIElicitationStringArrayValue) uIElicitationFieldValue() {}
+func (UIElicitationStringArrayValue) uiElicitationFieldValue() {}
type UIElicitationStringValue string
-func (UIElicitationStringValue) uIElicitationFieldValue() {}
+func (UIElicitationStringValue) uiElicitationFieldValue() {}
// Prompt message and JSON schema describing the form fields to elicit from the user.
// Experimental: UIElicitationRequest is part of an experimental API and may change or be
@@ -6185,7 +6185,7 @@ type UIElicitationSchema struct {
// Experimental: UIElicitationSchemaProperty is part of an experimental API and may change
// or be removed.
type UIElicitationSchemaProperty interface {
- uIElicitationSchemaProperty()
+ uiElicitationSchemaProperty()
Type() UIElicitationSchemaPropertyType
}
@@ -6194,7 +6194,7 @@ type RawUIElicitationSchemaPropertyData struct {
Raw json.RawMessage
}
-func (RawUIElicitationSchemaPropertyData) uIElicitationSchemaProperty() {}
+func (RawUIElicitationSchemaPropertyData) uiElicitationSchemaProperty() {}
func (r RawUIElicitationSchemaPropertyData) Type() UIElicitationSchemaPropertyType {
return r.Discriminator
}
@@ -6217,7 +6217,7 @@ type UIElicitationArrayAnyOfField struct {
Title *string `json:"title,omitempty"`
}
-func (UIElicitationArrayAnyOfField) uIElicitationSchemaProperty() {}
+func (UIElicitationArrayAnyOfField) uiElicitationSchemaProperty() {}
func (UIElicitationArrayAnyOfField) Type() UIElicitationSchemaPropertyType {
return UIElicitationSchemaPropertyTypeArray
}
@@ -6240,7 +6240,7 @@ type UIElicitationArrayEnumField struct {
Title *string `json:"title,omitempty"`
}
-func (UIElicitationArrayEnumField) uIElicitationSchemaProperty() {}
+func (UIElicitationArrayEnumField) uiElicitationSchemaProperty() {}
func (UIElicitationArrayEnumField) Type() UIElicitationSchemaPropertyType {
return UIElicitationSchemaPropertyTypeArray
}
@@ -6257,7 +6257,7 @@ type UIElicitationSchemaPropertyBoolean struct {
Title *string `json:"title,omitempty"`
}
-func (UIElicitationSchemaPropertyBoolean) uIElicitationSchemaProperty() {}
+func (UIElicitationSchemaPropertyBoolean) uiElicitationSchemaProperty() {}
func (UIElicitationSchemaPropertyBoolean) Type() UIElicitationSchemaPropertyType {
return UIElicitationSchemaPropertyTypeBoolean
}
@@ -6279,7 +6279,7 @@ type UIElicitationSchemaPropertyNumber struct {
Discriminator UIElicitationSchemaPropertyNumberType `json:"type,omitempty"`
}
-func (UIElicitationSchemaPropertyNumber) uIElicitationSchemaProperty() {}
+func (UIElicitationSchemaPropertyNumber) uiElicitationSchemaProperty() {}
func (r UIElicitationSchemaPropertyNumber) Type() UIElicitationSchemaPropertyType {
if r.Discriminator == "" {
return UIElicitationSchemaPropertyTypeNumber
@@ -6305,7 +6305,7 @@ type UIElicitationSchemaPropertyString struct {
Title *string `json:"title,omitempty"`
}
-func (UIElicitationSchemaPropertyString) uIElicitationSchemaProperty() {}
+func (UIElicitationSchemaPropertyString) uiElicitationSchemaProperty() {}
func (UIElicitationSchemaPropertyString) Type() UIElicitationSchemaPropertyType {
return UIElicitationSchemaPropertyTypeString
}
@@ -6326,7 +6326,7 @@ type UIElicitationStringEnumField struct {
Title *string `json:"title,omitempty"`
}
-func (UIElicitationStringEnumField) uIElicitationSchemaProperty() {}
+func (UIElicitationStringEnumField) uiElicitationSchemaProperty() {}
func (UIElicitationStringEnumField) Type() UIElicitationSchemaPropertyType {
return UIElicitationSchemaPropertyTypeString
}
@@ -6345,7 +6345,7 @@ type UIElicitationStringOneOfField struct {
Title *string `json:"title,omitempty"`
}
-func (UIElicitationStringOneOfField) uIElicitationSchemaProperty() {}
+func (UIElicitationStringOneOfField) uiElicitationSchemaProperty() {}
func (UIElicitationStringOneOfField) Type() UIElicitationSchemaPropertyType {
return UIElicitationSchemaPropertyTypeString
}
diff --git a/go/session.go b/go/session.go
index fadf338b7..3e37a3483 100644
--- a/go/session.go
+++ b/go/session.go
@@ -867,25 +867,28 @@ func (s *Session) handleElicitationRequest(elicitCtx ElicitationContext, request
return
}
- rpcContent := make(map[string]rpc.UIElicitationFieldValue)
- for k, v := range result.Content {
- contentValue, err := toRPCContent(v)
- if err != nil {
- s.RPC.UI.HandlePendingElicitation(ctx, &rpc.UIHandlePendingElicitationRequest{
- RequestID: requestID,
- Result: rpc.UIElicitationResponse{
- Action: rpc.UIElicitationResponseActionCancel,
- },
- })
- return
+ var rpcContent map[string]rpc.UIElicitationFieldValue
+ if result.Content != nil {
+ rpcContent = make(map[string]rpc.UIElicitationFieldValue, len(result.Content))
+ for k, v := range result.Content {
+ contentValue, err := toRPCContent(v)
+ if err != nil {
+ s.RPC.UI.HandlePendingElicitation(ctx, &rpc.UIHandlePendingElicitationRequest{
+ RequestID: requestID,
+ Result: rpc.UIElicitationResponse{
+ Action: rpc.UIElicitationResponseActionCancel,
+ },
+ })
+ return
+ }
+ rpcContent[k] = contentValue
}
- rpcContent[k] = contentValue
}
s.RPC.UI.HandlePendingElicitation(ctx, &rpc.UIHandlePendingElicitationRequest{
RequestID: requestID,
Result: rpc.UIElicitationResponse{
- Action: rpc.UIElicitationResponseAction(result.Action),
+ Action: result.Action,
Content: rpcContent,
},
})
@@ -983,13 +986,17 @@ func (s *Session) assertElicitation() error {
}
// Elicitation shows a generic elicitation dialog with a custom schema.
-func (ui *SessionUI) Elicitation(ctx context.Context, message string, requestedSchema rpc.UIElicitationSchema) (*ElicitationResult, error) {
+func (ui *SessionUI) Elicitation(ctx context.Context, message string, requestedSchema ElicitationSchema) (*ElicitationResult, error) {
if err := ui.session.assertElicitation(); err != nil {
return nil, err
}
+ rpcSchema, err := toRPCUIElicitationSchema(requestedSchema)
+ if err != nil {
+ return nil, err
+ }
rpcResult, err := ui.session.RPC.UI.Elicitation(ctx, &rpc.UIElicitationRequest{
Message: message,
- RequestedSchema: requestedSchema,
+ RequestedSchema: rpcSchema,
})
if err != nil {
return nil, err
@@ -997,6 +1004,60 @@ func (ui *SessionUI) Elicitation(ctx context.Context, message string, requestedS
return fromRPCElicitationResult(rpcResult), nil
}
+func toRPCUIElicitationSchema(schema ElicitationSchema) (rpc.UIElicitationSchema, error) {
+ var properties map[string]rpc.UIElicitationSchemaProperty
+ if schema.Properties != nil {
+ properties = make(map[string]rpc.UIElicitationSchemaProperty, len(schema.Properties))
+ for name, property := range schema.Properties {
+ rpcProperty, err := toRPCUIElicitationSchemaProperty(name, property)
+ if err != nil {
+ return rpc.UIElicitationSchema{}, err
+ }
+ properties[name] = rpcProperty
+ }
+ }
+
+ return rpc.UIElicitationSchema{
+ Properties: properties,
+ Required: append([]string(nil), schema.Required...),
+ Type: rpc.UIElicitationSchemaTypeObject,
+ }, nil
+}
+
+func toRPCUIElicitationSchemaProperty(name string, property any) (rpc.UIElicitationSchemaProperty, error) {
+ if property == nil {
+ return nil, fmt.Errorf("elicitation schema property %q is nil", name)
+ }
+ if rpcProperty, ok := property.(rpc.UIElicitationSchemaProperty); ok {
+ return rpcProperty, nil
+ }
+
+ data, err := json.Marshal(property)
+ if err != nil {
+ return nil, fmt.Errorf("marshal elicitation schema property %q: %w", name, err)
+ }
+ wrapperData, err := json.Marshal(struct {
+ Properties map[string]json.RawMessage `json:"properties"`
+ Type rpc.UIElicitationSchemaType `json:"type"`
+ }{
+ Properties: map[string]json.RawMessage{name: data},
+ Type: rpc.UIElicitationSchemaTypeObject,
+ })
+ if err != nil {
+ return nil, fmt.Errorf("marshal elicitation schema wrapper for property %q: %w", name, err)
+ }
+
+ var rpcSchema rpc.UIElicitationSchema
+ if err := json.Unmarshal(wrapperData, &rpcSchema); err != nil {
+ return nil, fmt.Errorf("decode elicitation schema property %q: %w", name, err)
+ }
+ rpcProperty, ok := rpcSchema.Properties[name]
+ if !ok {
+ return nil, fmt.Errorf("decode elicitation schema property %q: property missing after conversion", name)
+ }
+ return rpcProperty, nil
+}
+
// Confirm shows a confirmation dialog and returns the user's boolean answer.
// Returns false if the user declines or cancels.
func (ui *SessionUI) Confirm(ctx context.Context, message string) (bool, error) {
@@ -1111,17 +1172,20 @@ func fromRPCElicitationResult(r *rpc.UIElicitationResponse) *ElicitationResult {
if r == nil {
return nil
}
- content := make(map[string]any)
- for k, v := range r.Content {
- content[k] = fromRPCContent(v)
+ var content map[string]ElicitationFieldValue
+ if r.Content != nil {
+ content = make(map[string]ElicitationFieldValue, len(r.Content))
+ for k, v := range r.Content {
+ content[k] = fromRPCContent(v)
+ }
}
return &ElicitationResult{
- Action: string(r.Action),
+ Action: r.Action,
Content: content,
}
}
-func fromRPCContent(value rpc.UIElicitationFieldValue) any {
+func fromRPCContent(value rpc.UIElicitationFieldValue) ElicitationFieldValue {
switch v := value.(type) {
case nil:
return nil
@@ -1137,6 +1201,16 @@ func fromRPCContent(value rpc.UIElicitationFieldValue) any {
return nil
}
+func fromRPCElicitationRequestedSchema(schema *rpc.ElicitationRequestedSchema) *ElicitationSchema {
+ if schema == nil {
+ return nil
+ }
+ return &ElicitationSchema{
+ Properties: schema.Properties,
+ Required: schema.Required,
+ }
+}
+
// dispatchEvent enqueues an event for delivery to user handlers and fires
// broadcast handlers concurrently.
//
@@ -1225,35 +1299,13 @@ func (s *Session) handleBroadcastEvent(event SessionEvent) {
if handler == nil {
return
}
- var requestedSchema map[string]any
- if d.RequestedSchema != nil {
- requestedSchema = map[string]any{
- "type": string(d.RequestedSchema.Type),
- "properties": d.RequestedSchema.Properties,
- }
- if len(d.RequestedSchema.Required) > 0 {
- requestedSchema["required"] = d.RequestedSchema.Required
- }
- }
- mode := ""
- if d.Mode != nil {
- mode = string(*d.Mode)
- }
- elicitationSource := ""
- if d.ElicitationSource != nil {
- elicitationSource = *d.ElicitationSource
- }
- url := ""
- if d.URL != nil {
- url = *d.URL
- }
s.handleElicitationRequest(ElicitationContext{
SessionID: s.SessionID,
Message: d.Message,
- RequestedSchema: requestedSchema,
- Mode: mode,
- ElicitationSource: elicitationSource,
- URL: url,
+ RequestedSchema: fromRPCElicitationRequestedSchema(d.RequestedSchema),
+ Mode: d.Mode,
+ ElicitationSource: d.ElicitationSource,
+ URL: d.URL,
}, d.RequestID)
case *CapabilitiesChangedData:
diff --git a/go/session_test.go b/go/session_test.go
index 9e95e9a50..85bca1a05 100644
--- a/go/session_test.go
+++ b/go/session_test.go
@@ -718,7 +718,7 @@ func TestSession_ElicitationHandler(t *testing.T) {
}
session.registerElicitationHandler(func(ctx ElicitationContext) (ElicitationResult, error) {
- return ElicitationResult{Action: "accept"}, nil
+ return ElicitationResult{Action: ElicitationActionAccept}, nil
})
if session.getElicitationHandler() == nil {
@@ -756,7 +756,7 @@ func TestSession_ElicitationHandler(t *testing.T) {
session.registerElicitationHandler(func(ctx ElicitationContext) (ElicitationResult, error) {
return ElicitationResult{
- Action: "accept",
+ Action: ElicitationActionAccept,
Content: map[string]any{"color": "blue"},
}, nil
})
@@ -768,7 +768,7 @@ func TestSession_ElicitationHandler(t *testing.T) {
if err != nil {
t.Fatalf("Expected no error, got %v", err)
}
- if result.Action != "accept" {
+ if result.Action != ElicitationActionAccept {
t.Errorf("Expected action 'accept', got %q", result.Action)
}
if result.Content["color"] != "blue" {
@@ -883,6 +883,16 @@ func TestSession_HookForwardCompatibility(t *testing.T) {
}
func TestSession_ElicitationRequestSchema(t *testing.T) {
+ t.Run("nil content values are allowed", func(t *testing.T) {
+ value, err := toRPCContent(nil)
+ if err != nil {
+ t.Fatalf("Expected nil content to be accepted, got %v", err)
+ }
+ if value != nil {
+ t.Fatalf("Expected nil RPC content, got %T", value)
+ }
+ })
+
t.Run("elicitation.requested passes full schema to handler", func(t *testing.T) {
// Verify the schema extraction logic from handleBroadcastEvent
// preserves type, properties, and required.
@@ -892,28 +902,20 @@ func TestSession_ElicitationRequestSchema(t *testing.T) {
}
required := []string{"name", "age"}
- // Replicate the schema extraction logic from handleBroadcastEvent
- requestedSchema := map[string]any{
- "type": "object",
- "properties": properties,
- }
- if len(required) > 0 {
- requestedSchema["required"] = required
+ requestedSchema := ElicitationSchema{
+ Properties: properties,
+ Required: required,
}
- if requestedSchema["type"] != "object" {
- t.Errorf("Expected schema type 'object', got %v", requestedSchema["type"])
- }
- props, ok := requestedSchema["properties"].(map[string]any)
- if !ok || props == nil {
+ props := requestedSchema.Properties
+ if props == nil {
t.Fatal("Expected schema properties map")
}
if len(props) != 2 {
t.Errorf("Expected 2 properties, got %d", len(props))
}
- req, ok := requestedSchema["required"].([]string)
- if !ok || len(req) != 2 {
- t.Errorf("Expected required [name, age], got %v", requestedSchema["required"])
+ if len(requestedSchema.Required) != 2 {
+ t.Errorf("Expected required [name, age], got %v", requestedSchema.Required)
}
})
@@ -922,18 +924,44 @@ func TestSession_ElicitationRequestSchema(t *testing.T) {
"optional_field": map[string]any{"type": "string"},
}
- requestedSchema := map[string]any{
- "type": "object",
- "properties": properties,
+ requestedSchema := ElicitationSchema{
+ Properties: properties,
}
- // Simulate: if len(schema.Required) > 0 { ... } — with empty required
- var required []string
- if len(required) > 0 {
- requestedSchema["required"] = required
+
+ if requestedSchema.Required != nil {
+ t.Error("Expected Required to be nil when omitted")
}
+ })
- if _, exists := requestedSchema["required"]; exists {
- t.Error("Expected no 'required' key when Required is empty")
+ t.Run("schema conversion adds object type", func(t *testing.T) {
+ requestedSchema := ElicitationSchema{
+ Properties: map[string]any{
+ "name": map[string]any{"type": "string"},
+ },
+ }
+
+ rpcSchema, err := toRPCUIElicitationSchema(requestedSchema)
+ if err != nil {
+ t.Fatalf("toRPCUIElicitationSchema failed: %v", err)
+ }
+ if rpcSchema.Type != rpc.UIElicitationSchemaTypeObject {
+ t.Errorf("Expected RPC schema type object, got %q", rpcSchema.Type)
+ }
+ if _, ok := rpcSchema.Properties["name"].(*rpc.UIElicitationSchemaPropertyString); !ok {
+ t.Fatalf("Expected name property to decode as string schema, got %T", rpcSchema.Properties["name"])
+ }
+ })
+
+ t.Run("schema conversion preserves typed properties", func(t *testing.T) {
+ property := &rpc.UIElicitationSchemaPropertyString{}
+ rpcSchema, err := toRPCUIElicitationSchema(ElicitationSchema{
+ Properties: map[string]any{"name": property},
+ })
+ if err != nil {
+ t.Fatalf("toRPCUIElicitationSchema failed: %v", err)
+ }
+ if rpcSchema.Properties["name"] != property {
+ t.Fatalf("Expected typed property to be preserved, got %T", rpcSchema.Properties["name"])
}
})
}
diff --git a/go/types.go b/go/types.go
index a944a452b..7ffd454a3 100644
--- a/go/types.go
+++ b/go/types.go
@@ -743,19 +743,15 @@ type MCPServerConfig interface {
//
// The Tools field controls which tools from the server are exposed:
// - nil (omitted from the wire): all tools (CLI default)
-// - &[]string{"*"}: explicit "all tools"
-// - &[]string{}: no tools
-// - &[]string{"foo","bar"}: only those tools
-//
-// The pointer-to-slice form is required so that a nil pointer (omitted from
-// the wire) is distinguishable from a non-nil pointer to an empty slice
-// (sent as `"tools": []`).
+// - []string{"*"}: explicit "all tools"
+// - []string{}: no tools
+// - []string{"foo","bar"}: only those tools
type MCPStdioServerConfig struct {
- Tools *[]string `json:"tools,omitempty"`
+ Tools []string `json:"tools,omitzero"`
Timeout int `json:"timeout,omitempty"`
Command string `json:"command"`
- Args []string `json:"args,omitempty"`
- Env map[string]string `json:"env,omitempty"`
+ Args []string `json:"args,omitzero"`
+ Env map[string]string `json:"env,omitzero"`
WorkingDirectory string `json:"cwd,omitempty"`
}
@@ -777,10 +773,10 @@ func (c MCPStdioServerConfig) MarshalJSON() ([]byte, error) {
//
// See [MCPStdioServerConfig] for the semantics of the Tools field.
type MCPHTTPServerConfig struct {
- Tools *[]string `json:"tools,omitempty"`
+ Tools []string `json:"tools,omitzero"`
Timeout int `json:"timeout,omitempty"`
URL string `json:"url"`
- Headers map[string]string `json:"headers,omitempty"`
+ Headers map[string]string `json:"headers,omitzero"`
}
func (MCPHTTPServerConfig) mcpServerConfig() {}
@@ -1197,12 +1193,34 @@ type UICapabilities struct {
MCPApps bool `json:"mcpApps,omitempty"`
}
+// ElicitationAction is the user response to an elicitation request.
+type ElicitationAction = rpc.UIElicitationResponseAction
+
+// Elicitation action values.
+const (
+ ElicitationActionAccept ElicitationAction = rpc.UIElicitationResponseActionAccept
+ ElicitationActionCancel ElicitationAction = rpc.UIElicitationResponseActionCancel
+ ElicitationActionDecline ElicitationAction = rpc.UIElicitationResponseActionDecline
+)
+
+// ElicitationFieldValue is a primitive value submitted for an elicitation form field.
+// Supported values are string, numeric types, bool, []string, and []any containing strings.
+type ElicitationFieldValue = any
+
// ElicitationResult is the user's response to an elicitation dialog.
type ElicitationResult struct {
- // Action is the user response: "accept" (submitted), "decline" (rejected), or "cancel" (dismissed).
- Action string `json:"action"`
- // Content holds form values submitted by the user (present when Action is "accept").
- Content map[string]any `json:"content,omitzero"`
+ // Action is the user response: accept, decline, or cancel.
+ Action ElicitationAction `json:"action"`
+ // Content holds form values submitted by the user when Action is accept.
+ Content map[string]ElicitationFieldValue `json:"content,omitzero"`
+}
+
+// ElicitationSchema describes the form fields for an elicitation request.
+type ElicitationSchema struct {
+ // Properties contains form field definitions keyed by field name.
+ Properties map[string]any `json:"properties"`
+ // Required lists field names that must be submitted.
+ Required []string `json:"required,omitzero"`
}
// ElicitationContext describes an elicitation request from the server,
@@ -1214,13 +1232,13 @@ type ElicitationContext struct {
// Message describes what information is needed from the user.
Message string
// RequestedSchema is a JSON Schema describing the form fields (form mode only).
- RequestedSchema map[string]any
+ RequestedSchema *ElicitationSchema
// Mode is "form" for structured input, "url" for browser redirect.
- Mode string
+ Mode *ElicitationRequestedMode
// ElicitationSource is the source that initiated the request (e.g. MCP server name).
- ElicitationSource string
+ ElicitationSource *string
// URL to open in the user's browser (url mode only).
- URL string
+ URL *string
}
// ElicitationHandler handles elicitation requests from the server (e.g. from MCP tools).
@@ -1548,7 +1566,7 @@ type ModelVisionLimits struct {
// ModelLimits contains model limits
type ModelLimits struct {
MaxPromptTokens *int `json:"max_prompt_tokens,omitempty"`
- MaxContextWindowTokens int `json:"max_context_window_tokens"`
+ MaxContextWindowTokens *int `json:"max_context_window_tokens,omitempty"`
Vision *ModelVisionLimits `json:"vision,omitempty"`
}
diff --git a/go/types_test.go b/go/types_test.go
index 4f536c53b..f4132fa3d 100644
--- a/go/types_test.go
+++ b/go/types_test.go
@@ -326,7 +326,7 @@ func TestCanvasDeclaration_JSONOmitsNilInputSchema(t *testing.T) {
func TestElicitationResult_JSONIncludesEmptyContent(t *testing.T) {
result := ElicitationResult{
- Action: "accept",
+ Action: ElicitationActionAccept,
Content: map[string]any{},
}
@@ -354,7 +354,7 @@ func TestElicitationResult_JSONIncludesEmptyContent(t *testing.T) {
}
func TestElicitationResult_JSONOmitsNilContent(t *testing.T) {
- result := ElicitationResult{Action: "cancel"}
+ result := ElicitationResult{Action: ElicitationActionCancel}
data, err := json.Marshal(result)
if err != nil {
diff --git a/java/README.md b/java/README.md
index 44f9b65e4..6cddbc67f 100644
--- a/java/README.md
+++ b/java/README.md
@@ -30,14 +30,14 @@ Replace `${copilot.sdk.version}` with the latest release from Maven Central.
com.github
copilot-sdk-java
- 1.0.0-beta-12-java.1
+ 1.0.0
```
### Gradle
```groovy
-implementation 'com.github:copilot-sdk-java:1.0.0-beta-12-java.1'
+implementation 'com.github:copilot-sdk-java:1.0.0'
```
#### Snapshot Builds
@@ -56,7 +56,7 @@ Snapshot builds of the next development version are published to Maven Central S
com.github
copilot-sdk-java
- 1.0.0-beta-12-java.2-SNAPSHOT
+ 1.0.1-SNAPSHOT
```
@@ -65,7 +65,7 @@ Snapshot builds of the next development version are published to Maven Central S
Replace `${copilot.sdk.version}` with the latest release from Maven Central.
```groovy
-implementation 'com.github:copilot-sdk-java:1.0.0-beta-12-java.1-SNAPSHOT'
+implementation 'com.github:copilot-sdk-java:1.0.0-SNAPSHOT'
```
## Quick Start
diff --git a/java/jbang-example.java b/java/jbang-example.java
index 47abce64e..856eb727c 100644
--- a/java/jbang-example.java
+++ b/java/jbang-example.java
@@ -1,5 +1,5 @@
///usr/bin/env jbang "$0" "$@" ; exit $?
-//DEPS com.github:copilot-sdk-java:1.0.0-beta-12-java.1
+//DEPS com.github:copilot-sdk-java:1.0.0
import com.github.copilot.CopilotClient;
import com.github.copilot.generated.AssistantMessageEvent;
import com.github.copilot.generated.SessionUsageInfoEvent;
diff --git a/java/pom.xml b/java/pom.xml
index f26f7ecaf..198368d0e 100644
--- a/java/pom.xml
+++ b/java/pom.xml
@@ -7,7 +7,7 @@
com.github
copilot-sdk-java
- 1.0.0-beta-12-java.1
+ 1.0.0
jar
GitHub Copilot SDK :: Java
@@ -33,7 +33,7 @@
scm:git:https://github.com/github/copilot-sdk.git
scm:git:https://github.com/github/copilot-sdk.git
https://github.com/github/copilot-sdk
- java/v1.0.0-beta-12-java.1
+ java/v1.0.0
diff --git a/nodejs/scripts/calculate-version.js b/nodejs/scripts/calculate-version.js
index ac5722d43..c90ff1a37 100644
--- a/nodejs/scripts/calculate-version.js
+++ b/nodejs/scripts/calculate-version.js
@@ -43,13 +43,10 @@ export function calculateVersion(command, { latest, prerelease, unstable }) {
}
}
- // TEMPORARY: "latest" uses prerelease increments so we publish beta versions
- // under the "latest" dist-tag. To ship stable 1.0.0, revert the commit that
- // introduced this temporary change.
- const increment = "prerelease";
+ const increment = command === "latest" ? "patch" : "prerelease";
const isIncrementingExistingPrerelease = semver.prerelease(higherVersion) !== null;
const prereleaseIdentifier =
- command === "prerelease" || command === "latest"
+ command === "prerelease"
? isIncrementingExistingPrerelease
? undefined
: "preview"
diff --git a/nodejs/test/get-version.test.ts b/nodejs/test/get-version.test.ts
index 23d2486ec..5dea84cf2 100644
--- a/nodejs/test/get-version.test.ts
+++ b/nodejs/test/get-version.test.ts
@@ -2,15 +2,13 @@ import { describe, expect, it } from "vitest";
import { calculateVersion } from "../scripts/calculate-version.js";
describe("get-version", () => {
- // TEMPORARY: these two tests reflect beta-as-latest behavior. To ship
- // stable 1.0.0, revert the commit that introduced this temporary change.
- it("increments latest versions as prerelease (temporary beta behavior)", () => {
- expect(calculateVersion("latest", { latest: "1.0.1" })).toBe("1.0.2-preview.0");
+ it("increments stable latest versions by patch", () => {
+ expect(calculateVersion("latest", { latest: "1.0.1" })).toBe("1.0.2");
});
- it("continues beta prerelease for latest releases (temporary beta behavior)", () => {
+ it("promotes a higher prerelease to stable for latest releases", () => {
expect(calculateVersion("latest", { latest: "0.3.0", prerelease: "1.0.0-beta.1" })).toBe(
- "1.0.0-beta.2"
+ "1.0.0"
);
});
diff --git a/scripts/codegen/go.ts b/scripts/codegen/go.ts
index 69556d094..82aac2a0b 100644
--- a/scripts/codegen/go.ts
+++ b/scripts/codegen/go.ts
@@ -115,6 +115,20 @@ function toGoFieldName(jsonName: string): string {
.join("");
}
+function toGoUnexportedIdentifier(name: string): string {
+ const leadingSpecialCases = [
+ ...Array.from(goIdentifierCasingOverrides.values()),
+ ...Array.from(goInitialisms, (initialism) => initialism.toUpperCase()),
+ ].sort((left, right) => right.length - left.length);
+
+ const leadingSpecialCase = leadingSpecialCases.find((specialCase) => name.startsWith(specialCase));
+ if (leadingSpecialCase) {
+ return leadingSpecialCase.toLowerCase() + name.slice(leadingSpecialCase.length);
+ }
+
+ return name.charAt(0).toLowerCase() + name.slice(1);
+}
+
function goRefTypeName(ref: string, definitions?: DefinitionCollections, currentPackage?: string): string {
const externalRef = parseExternalSchemaRef(ref);
if (externalRef) {
@@ -1754,7 +1768,7 @@ function emitGoFlatDiscriminatedUnion(
const unmarshalFuncName = goUnexportedFunctionName("unmarshal", typeName);
const rawDataName = `Raw${typeName}${ctx.discriminatedUnionRawVariantSuffix ?? "Data"}`;
const hasRawVariant = discriminator.valueKind === "string";
- const markerName = `${typeName.charAt(0).toLowerCase()}${typeName.slice(1)}`;
+ const markerName = toGoUnexportedIdentifier(typeName);
ctx.discriminatedUnions.set(typeName, { typeName, unmarshalFuncName });
const lines: string[] = [];
@@ -1952,7 +1966,7 @@ function emitGoRequiredFieldDiscriminatedUnion(
const unionVariants = [...discriminator.variants].sort((left, right) => compareGoTypeNames(left.typeName, right.typeName));
const unmarshalFuncName = goUnexportedFunctionName("unmarshal", typeName);
const rawDataName = `Raw${typeName}${ctx.discriminatedUnionRawVariantSuffix ?? "Data"}`;
- const markerName = `${typeName.charAt(0).toLowerCase()}${typeName.slice(1)}`;
+ const markerName = toGoUnexportedIdentifier(typeName);
ctx.discriminatedUnions.set(typeName, { typeName, unmarshalFuncName });
const lines: string[] = [];
@@ -2515,7 +2529,7 @@ function emitGoPrimitiveUnionInterface(typeName: string, schema: JSONSchema7, ct
ctx.generatedNames.add(typeName);
const unmarshalFuncName = goUnexportedFunctionName("unmarshal", typeName);
- const markerName = `${typeName.charAt(0).toLowerCase()}${typeName.slice(1)}`;
+ const markerName = toGoUnexportedIdentifier(typeName);
ctx.discriminatedUnions.set(typeName, { typeName, unmarshalFuncName });
const lines: string[] = [];
@@ -2671,7 +2685,7 @@ function emitGoUntaggedUnionInterface(typeName: string, schema: JSONSchema7, ctx
ctx.generatedNames.add(typeName);
const unmarshalFuncName = goUnexportedFunctionName("unmarshal", typeName);
- const markerName = `${typeName.charAt(0).toLowerCase()}${typeName.slice(1)}`;
+ const markerName = toGoUnexportedIdentifier(typeName);
ctx.discriminatedUnions.set(typeName, { typeName, unmarshalFuncName });
const lines: string[] = [];