Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
13 changes: 0 additions & 13 deletions .github/workflows/build-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,19 +32,6 @@ jobs:
- name: Check native Go CLI
run: scripts/check-go-cli.sh

- name: Build native Go CLI
run: scripts/build-go-cli.sh

- name: Verify checked-in native Go CLI binaries
run: |
git diff --exit-code -- \
Packages/src/GoCli~/dist/darwin-arm64/uloop-core \
Packages/src/GoCli~/dist/darwin-amd64/uloop-core \
Packages/src/GoCli~/dist/windows-amd64/uloop-core.exe \
Packages/src/GoCli~/dist/darwin-arm64/uloop-dispatcher \
Packages/src/GoCli~/dist/darwin-amd64/uloop-dispatcher \
Packages/src/GoCli~/dist/windows-amd64/uloop-dispatcher.exe

- name: Package native Go CLI installers
run: scripts/package-go-cli.sh

Expand Down
3 changes: 0 additions & 3 deletions .github/workflows/native-cli-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,6 @@ jobs:
- name: Check native CLI
run: scripts/check-go-cli.sh

- name: Build native CLI binaries
run: scripts/build-go-cli.sh

- name: Package native CLI release assets
run: scripts/package-go-cli.sh

Expand Down
5 changes: 5 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ Comments in the code, commit messages, PR titles, and PR descriptions must all b
Do not directly edit skill files under the project-root `.agents/` or `.claude/` directories.
These files are generated copies. Update the source skill definitions instead, then regenerate the copies through the normal workflow.

## Native Go CLI Validation

When changing files under `Packages/src/GoCli~` or any checked-in native CLI binary under `Packages/src/GoCli~/dist`, run `scripts/check-go-cli.sh` before opening or updating a pull request.
This script is the local equivalent of the Go CLI CI validation: it runs formatting checks, vet, lint, tests, rebuilds the checked-in native binaries, and fails if the rebuilt binaries differ from the committed files.

## Unity Freeze Prevention

Do not add or keep Unity EditMode tests that can freeze the Editor.
Expand Down
Binary file modified Packages/src/GoCli~/dist/darwin-amd64/uloop-core
Binary file not shown.
Binary file modified Packages/src/GoCli~/dist/darwin-amd64/uloop-dispatcher
Binary file not shown.
Binary file modified Packages/src/GoCli~/dist/darwin-arm64/uloop-core
Binary file not shown.
Binary file modified Packages/src/GoCli~/dist/darwin-arm64/uloop-dispatcher
Binary file not shown.
Binary file modified Packages/src/GoCli~/dist/windows-amd64/uloop-core.exe
Binary file not shown.
Binary file modified Packages/src/GoCli~/dist/windows-amd64/uloop-dispatcher.exe
Binary file not shown.
66 changes: 66 additions & 0 deletions Packages/src/GoCli~/internal/cli/argument_error.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package cli

import "fmt"

type argumentError struct {
message string
option string
received string
expectedType string
command string
nextActions []string
}

func (err *argumentError) Error() string {
return err.message
}

func (err *argumentError) toCLIError(context errorContext) cliError {
command := firstNonEmpty(err.command, context.command)
details := map[string]any{}
if err.option != "" {
details["option"] = err.option
}
if err.received != "" {
details["received"] = err.received
}
if err.expectedType != "" {
details["expectedType"] = err.expectedType
}

nextActions := err.nextActions
if len(nextActions) == 0 {
nextActions = []string{"Correct the command arguments and retry."}
}

return cliError{
ErrorCode: errorCodeInvalidArgument,
Phase: errorPhaseArgumentParsing,
Message: err.message,
Retryable: false,
SafeToRetry: false,
ProjectRoot: context.projectRoot,
Command: command,
NextActions: nextActions,
Details: details,
}
}

func missingValueArgumentError(option string) *argumentError {
return &argumentError{
message: fmt.Sprintf("%s requires a value", option),
option: option,
expectedType: "string",
nextActions: []string{fmt.Sprintf("Pass a value after `%s` or use `%s=<value>`.", option, option)},
}
}

func invalidValueArgumentError(option string, received string, expectedType string) *argumentError {
return &argumentError{
message: fmt.Sprintf("Invalid %s value for %s: %s", expectedType, option, received),
option: option,
received: received,
expectedType: expectedType,
nextActions: []string{fmt.Sprintf("Pass a valid %s value for `%s`.", expectedType, option)},
}
}
41 changes: 33 additions & 8 deletions Packages/src/GoCli~/internal/cli/completion.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,12 @@ func tryHandleCompletionRequest(args []string, cache toolsCache, stdout io.Write

if args[0] == listOptionsFlag {
if len(args) < 2 {
writeLine(stderr, "--list-options requires a command name")
writeErrorEnvelope(stderr, (&argumentError{
message: "--list-options requires a command name",
option: listOptionsFlag,
command: completionCommand,
nextActions: []string{"Pass the command name after `--list-options`."},
}).toCLIError(errorContext{command: completionCommand}))
return true, 1
}
printOptionsForCommand(args[1], cache, stdout)
Expand All @@ -64,7 +69,7 @@ func tryHandleCompletionRequest(args []string, cache toolsCache, stdout io.Write

request, err := parseCompletionRequest(args[1:])
if err != nil {
writeLine(stderr, err.Error())
writeClassifiedError(stderr, err, errorContext{command: completionCommand})
return true, 1
}

Expand All @@ -73,7 +78,15 @@ func tryHandleCompletionRequest(args []string, cache toolsCache, stdout io.Write
shellName = detectShell()
}
if shellName == "" {
writeLine(stderr, "Could not detect shell. Use --shell bash, --shell zsh, --shell powershell, or --shell pwsh.")
writeErrorEnvelope(stderr, cliError{
ErrorCode: errorCodeInvalidArgument,
Phase: errorPhaseArgumentParsing,
Message: "Could not detect shell.",
Retryable: false,
SafeToRetry: false,
Command: completionCommand,
NextActions: []string{"Pass `--shell bash`, `--shell zsh`, `--shell powershell`, or `--shell pwsh`."},
})
return true, 1
}

Expand All @@ -85,11 +98,11 @@ func tryHandleCompletionRequest(args []string, cache toolsCache, stdout io.Write

configPath, err := getShellConfigPath(shellName)
if err != nil {
writeLine(stderr, err.Error())
writeClassifiedError(stderr, err, errorContext{command: completionCommand})
return true, 1
}
if err := installCompletionScript(configPath, shellName, script); err != nil {
writeLine(stderr, err.Error())
writeClassifiedError(stderr, err, errorContext{command: completionCommand})
return true, 1
}

Expand Down Expand Up @@ -127,7 +140,7 @@ func parseCompletionRequest(args []string) (completionRequest, error) {

if arg == shellFlag {
if index+1 >= len(args) {
return completionRequest{}, fmt.Errorf("%s requires a value", shellFlag)
return completionRequest{}, missingValueArgumentError(shellFlag)
}
normalized, err := normalizeShell(args[index+1])
if err != nil {
Expand All @@ -138,7 +151,12 @@ func parseCompletionRequest(args []string) (completionRequest, error) {
continue
}

return completionRequest{}, fmt.Errorf("unknown completion option: %s", arg)
return completionRequest{}, &argumentError{
message: "Unknown completion option: " + arg,
option: arg,
command: completionCommand,
nextActions: []string{"Run `uloop completion --help` to inspect supported completion options."},
}
}
return request, nil
}
Expand All @@ -151,7 +169,14 @@ func normalizeShell(value string) (string, error) {
if normalized == "powershell-core" {
return "pwsh", nil
}
return "", fmt.Errorf("unknown shell: %s. Supported: bash, zsh, powershell, pwsh", value)
return "", &argumentError{
message: "Unknown shell: " + value,
option: shellFlag,
received: value,
expectedType: "bash|zsh|powershell|pwsh",
command: completionCommand,
nextActions: []string{"Use one of: bash, zsh, powershell, pwsh."},
}
}

func printCommandNames(cache toolsCache, stdout io.Writer) {
Expand Down
Loading