Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .changeset/patch-goose-1-54.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions .github/workflows/shared/goose.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
engine:
id: goose
detection-engine: copilot
version: "1.53.0"
version: "1.54.0"
display-name: Goose
description: Goose CLI with headless execution and MCP support
experimental: true
Expand Down Expand Up @@ -70,6 +70,7 @@ engine:
const archive = join(installDir, "goose.tar.gz");
const checksums = {
"1.53.0": "deb2191a6b75acc0a20232fc5c52655ea2f9cc8fa2f5dffc8622e8d378a915dc",
"1.54.0": "ab396c95aebbd28b4d38c175234be8d4a3ea0c96e7ccb24c307e4618c9be57e1",
};
const fail = (result, action) => {
if (result.error) throw result.error;
Expand Down Expand Up @@ -184,7 +185,7 @@ Shared engine definition for the [Goose](https://github.com/aaif-goose/goose)
open-source AI agent. Import this file and set `engine: id: goose` to use it.

This is an unsupported repository sample, pinned to
[v1.53.0](https://github.com/aaif-goose/goose/releases/tag/v1.53.0).
[v1.54.0](https://github.com/aaif-goose/goose/releases/tag/v1.54.0).
The Linux x86-64 archive is SHA-256 verified before extraction; other versions
require a reviewed checksum or a verified binary supplied through `engine.command`.

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/smoke-goose.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ post-steps:
const binary = fs.lstatSync(path.join(process.env.GITHUB_WORKSPACE, "gh-aw"));
assert.ok(binary.isFile() && !binary.isSymbolicLink() && (binary.mode & 0o111) !== 0, "gh-aw build output is missing");
const log = fs.readFileSync("/tmp/gh-aw/agent-stdio.log", "utf8");
assert.ok(log.includes("[goose-harness] verified Goose 1.53.0"), "Pinned CLI verification is missing");
assert.ok(log.includes("[goose-harness] verified Goose 1.54.0"), "Pinned CLI verification is missing");
Comment thread
pelikhan marked this conversation as resolved.
assert.ok(!log.includes("Failed to start extension"), "A Goose MCP extension failed to connect");
const events = log.split("\n").filter(line => line.trim().startsWith("{")).map(line => JSON.parse(line));
assert.ok(events.some(event => event.type === "complete"), "Goose did not finish a structured run");
Expand Down
20 changes: 14 additions & 6 deletions pkg/workflow/goose_runtime_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
func TestGooseReleaseRuntime(t *testing.T) {
binary := os.Getenv("GH_AW_TEST_GOOSE_BINARY")
if binary == "" {
t.Skip("set GH_AW_TEST_GOOSE_BINARY to a verified Goose v1.53.0 binary")
t.Skip("set GH_AW_TEST_GOOSE_BINARY to a verified Goose v" + loadGooseSample(t).Version + " binary")
}
dir := t.TempDir()
var toolCalls, inferenceCalls atomic.Int32
Expand All @@ -38,21 +38,24 @@
prompt := filepath.Join(dir, "prompt.txt")
require.NoError(t, os.WriteFile(prompt, []byte("Call the probe echo tool once, then answer Done."), 0o600))
config := filepath.Join(dir, "mcp.json")
content, err := json.Marshal(map[string]any{"mcpServers": map[string]any{
servers := map[string]map[string]any{
"probe": map[string]any{"url": server.URL + "/mcp/probe", "headers": map[string]string{"Authorization": "Bearer test-only"}},
Comment thread
Copilot marked this conversation as resolved.
Outdated
}})
}
servers["probe"]["tools"] = []string{"echo"}
content, err := json.Marshal(map[string]any{"mcpServers": servers})
require.NoError(t, err)
require.NoError(t, os.WriteFile(config, content, 0o600))
ctx, cancel := context.WithTimeout(context.Background(), 45*time.Second)
defer cancel()
cmd := exec.CommandContext(ctx, "node", harness, binary)
cmd.Dir = dir
cmd.Env = append(os.Environ(), "GH_AW_ENGINE_VERSION=1.53.0",
"GH_AW_MCP_CONFIG="+config, "GH_AW_PROMPT="+prompt,
cmd.Env = []string{"PATH=" + os.Getenv("PATH"), "HOME=" + dir, "TMPDIR=" + dir,
"GH_AW_ENGINE_VERSION=" + loadGooseSample(t).Version,
"GH_AW_MCP_CONFIG=" + config, "GH_AW_PROMPT=" + prompt,
Comment thread
pelikhan marked this conversation as resolved.
"GOOSE_MODEL=copilot/test-model", "GOOSE_MODE=auto",
"GOOSE_DISABLE_SESSION_NAMING=true", "GH_AW_MAX_TURNS=3",
"OPENAI_API_KEY=test-only", "AWF_REFLECT_ENABLED=1",
"GH_AW_LLM_PROVIDER=github", "TEST_ENDPOINT="+server.URL)
"GH_AW_LLM_PROVIDER=github", "TEST_ENDPOINT=" + server.URL}
output, err := cmd.CombinedOutput()
require.NoError(t, err, "%s", output)
assert.NotContains(t, string(output), "Failed to start extension")
Expand Down Expand Up @@ -99,6 +102,10 @@
tools.Add(1)
return &mcp.CallToolResult{Content: []mcp.Content{&mcp.TextContent{Text: "probe passed"}}}, nil, nil
})
mcp.AddTool(server, &mcp.Tool{Name: "excluded", Description: "Tool excluded by the configured allowlist"}, func(_ context.Context, _ *mcp.CallToolRequest, _ struct{}) (*mcp.CallToolResult, any, error) {
t.Error("Goose called a tool outside the configured allowlist")
return nil, nil, fmt.Errorf("tool is not allowed")

Check failure on line 107 in pkg/workflow/goose_runtime_test.go

View workflow job for this annotation

GitHub Actions / lint-go-golangci (2)

error-format: fmt.Errorf can be replaced with errors.New (perfsprint)

Check failure on line 107 in pkg/workflow/goose_runtime_test.go

View workflow job for this annotation

GitHub Actions / lint-go-golangci (2)

error-format: fmt.Errorf can be replaced with errors.New (perfsprint)
Comment thread
pelikhan marked this conversation as resolved.
Outdated
Comment thread
pelikhan marked this conversation as resolved.
Outdated
})
handler := mcp.NewStreamableHTTPHandler(func(*http.Request) *mcp.Server { return server }, &mcp.StreamableHTTPOptions{JSONResponse: true, Stateless: true})
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/chat/completions" {
Expand Down Expand Up @@ -134,6 +141,7 @@
for _, tool := range request.Tools {
function := tool["function"].(map[string]any)
found = found || function["name"] == "probe__echo"
assert.NotEqual(t, "probe__excluded", function["name"], "upstream extension leases must preserve the configured tool allowlist")
Comment thread
pelikhan marked this conversation as resolved.
Outdated
}
assert.True(t, found, "authenticated MCP tool must be advertised on the first model turn")
message = map[string]any{"role": "assistant", "content": nil, "tool_calls": []any{
Expand Down
12 changes: 6 additions & 6 deletions pkg/workflow/goose_smoke_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func writeGooseSmokeFixtures(t *testing.T, dir string) {
"smoke-test-goose-123.txt": "Smoke test passed for Goose at test timestamp\n",
"web-fetch.json": `{"containsGitHub":true}`,
"gh-aw": "test build output",
"agent-stdio.log": `[goose-harness] verified Goose 1.53.0
"agent-stdio.log": `[goose-harness] verified Goose 1.54.0
{"type":"message","message":{"role":"assistant","content":[{"type":"toolRequest","id":"tool-1","toolCall":{"status":"success","value":{"name":"github__pull_request_read"}}}]}}
{"type":"message","message":{"role":"user","content":[{"type":"toolResponse","id":"tool-1","toolResult":{"status":"success","value":{"content":[]}}}]}}
{"type":"message","message":{"id":"text-1","role":"assistant","content":[{"type":"text","text":"Done."}]}}
Expand Down Expand Up @@ -75,12 +75,12 @@ func TestGooseSmokeCheckerRequiresOperationalEvidence(t *testing.T) {
{name: "missing build binary", file: "gh-aw", wantError: "ENOENT"},
{name: "missing unified session", file: "agent-session.jsonl", wantError: "ENOENT"},
{name: "legacy session events", file: "agent-session.jsonl", content: `{"type":"assistant","message":{"content":[{"type":"text","text":"Done."}]}}`, wantError: "Goose session contains non-canonical events"},
{name: "failed MCP", file: "agent-stdio.log", content: `[goose-harness] verified Goose 1.53.0
{name: "failed MCP", file: "agent-stdio.log", content: `[goose-harness] verified Goose 1.54.0
{"type":"message","message":{"content":[{"type":"toolRequest","id":"tool-1","toolCall":{"status":"success","value":{"name":"github__pull_request_read"}}},{"type":"toolResponse","id":"tool-1","toolResult":{"status":"success","value":{"isError":true,"content":[]}}}]}}
{"type":"complete"}
`, wantError: "No successful native GitHub MCP round-trip"},
{name: "missing completion", file: "agent-stdio.log", content: "[goose-harness] verified Goose 1.53.0\n", wantError: "Goose did not finish a structured run"},
{name: "disconnected extension", file: "agent-stdio.log", content: "[goose-harness] verified Goose 1.53.0\nFailed to start extension 'github'\n", wantError: "A Goose MCP extension failed to connect"},
{name: "missing completion", file: "agent-stdio.log", content: "[goose-harness] verified Goose 1.54.0\n", wantError: "Goose did not finish a structured run"},
{name: "disconnected extension", file: "agent-stdio.log", content: "[goose-harness] verified Goose 1.54.0\nFailed to start extension 'github'\n", wantError: "A Goose MCP extension failed to connect"},
} {
t.Run(test.name, func(t *testing.T) {
dir := t.TempDir()
Expand Down Expand Up @@ -139,12 +139,12 @@ func TestGooseSmokeRuntimeProbeTrimsNativeVersionOutput(t *testing.T) {
probe, _, ok = strings.Cut(probe, "\n JS\n")
require.True(t, ok)
dir := t.TempDir()
require.NoError(t, os.WriteFile(filepath.Join(dir, "goose"), []byte("#!/bin/sh\nprintf ' 1.53.0\\n'\n"), 0o700))
require.NoError(t, os.WriteFile(filepath.Join(dir, "goose"), []byte("#!/bin/sh\nprintf ' 1.54.0\\n'\n"), 0o700))
config := filepath.Join(dir, "config.json")
require.NoError(t, os.WriteFile(config, []byte(`{"extensions":{"github":{"type":"streamable_http","uri":"http://awmg-mcpg:8080/mcp/github","headers":{"Authorization":"Bearer test-only"}}}}`), 0o600))
cmd := exec.Command("node", "-e", probe)
cmd.Env = append(os.Environ(), "PATH="+dir+string(os.PathListSeparator)+os.Getenv("PATH"),
"GH_AW_ENGINE_VERSION=1.53.0", "GOOSE_PROVIDER=openai", "GOOSE_MODEL=gpt-5.4",
"GH_AW_ENGINE_VERSION=1.54.0", "GOOSE_PROVIDER=openai", "GOOSE_MODEL=gpt-5.4",
"OPENAI_HOST=http://test-proxy", "OPENAI_BASE_PATH=chat/completions",
"GH_AW_MAX_TURNS=30", "GOOSE_ADDITIONAL_CONFIG_FILES="+config)
output, err := cmd.CombinedOutput()
Expand Down
6 changes: 3 additions & 3 deletions pkg/workflow/goose_workflow_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func loadGooseSample(t *testing.T) *EngineDefinition {

func TestGooseSampleExecution(t *testing.T) {
def := loadGooseSample(t)
require.Equal(t, "1.53.0", def.Version)
require.Equal(t, "1.54.0", def.Version)
engine, err := NewBehaviorDefinedEngine(def)
require.NoError(t, err)
assert.True(t, engine.GetCapabilities().MCP)
Expand All @@ -42,7 +42,7 @@ func TestGooseSampleExecution(t *testing.T) {
EngineConfig: &EngineConfig{ID: "goose", Version: def.Version, MaxTurns: "30"},
}, "/tmp/gh-aw/agent-stdio.log")
execution := strings.Join(steps[len(steps)-1], "\n")
assert.Contains(t, execution, "GH_AW_ENGINE_VERSION: 1.53.0")
assert.Contains(t, execution, "GH_AW_ENGINE_VERSION: 1.54.0")
assert.Contains(t, execution, "GH_AW_MAX_TURNS: 30")
assert.Contains(t, execution, "GOOSE_MODEL: copilot/auto")
assert.Contains(t, execution, "GH_AW_LLM_PROVIDER: github")
Expand Down Expand Up @@ -115,7 +115,7 @@ exports.resolveOpenAICompatibleEndpointFromReflect = () => ({provider: "github",
binary := filepath.Join(dir, "test-goose")
fixture := `#!/usr/bin/env node
const fs = require("fs");
if (process.argv.includes("--version")) { console.log("1.53.0"); process.exit(0); }
if (process.argv.includes("--version")) { console.log("1.54.0"); process.exit(0); }
const configPath = process.env.GOOSE_ADDITIONAL_CONFIG_FILES;
fs.writeFileSync(process.env.TEST_OUTPUT, JSON.stringify({
args: process.argv.slice(2),
Expand Down
Loading