From 9e1ee4d48e2606f48f6c17a64829f2f99eafab6d Mon Sep 17 00:00:00 2001 From: Kayvan Sylvan Date: Mon, 19 Jan 2026 06:25:31 -0800 Subject: [PATCH 1/4] WIP: Phase 1 - Add Infermatic provider to ProviderMap Issue: #1033 Phase: 1 of 2 Status: Pending verification Co-Authored-By: Claude Opus 4.5 --- internal/plugins/ai/openai_compatible/providers_config.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/internal/plugins/ai/openai_compatible/providers_config.go b/internal/plugins/ai/openai_compatible/providers_config.go index c98e7907..751c5572 100644 --- a/internal/plugins/ai/openai_compatible/providers_config.go +++ b/internal/plugins/ai/openai_compatible/providers_config.go @@ -145,6 +145,11 @@ var ProviderMap = map[string]ProviderConfig{ ModelsURL: "https://models.github.ai/catalog", // FetchModelsDirectly will append /models ImplementsResponses: false, }, + "Infermatic": { + Name: "Infermatic", + BaseURL: "https://api.totalgpt.ai/v1", + ImplementsResponses: false, + }, "GrokAI": { Name: "GrokAI", BaseURL: "https://api.x.ai/v1", From 387610bcf87616f95ba42e2f3a4f6f6cb62c1d8e Mon Sep 17 00:00:00 2001 From: Kayvan Sylvan Date: Mon, 19 Jan 2026 06:38:38 -0800 Subject: [PATCH 2/4] Add Infermatic provider test case Adds test coverage for the Infermatic AI provider in TestCreateClient to verify the provider exists and creates a valid client. Part of #1033: Add Infermatic AI provider support Co-Authored-By: Claude Opus 4.5 --- .../plugins/ai/openai_compatible/providers_config_test.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/internal/plugins/ai/openai_compatible/providers_config_test.go b/internal/plugins/ai/openai_compatible/providers_config_test.go index 7de54c9d..9666c985 100644 --- a/internal/plugins/ai/openai_compatible/providers_config_test.go +++ b/internal/plugins/ai/openai_compatible/providers_config_test.go @@ -30,6 +30,11 @@ func TestCreateClient(t *testing.T) { provider: "Abacus", exists: true, }, + { + name: "Existing provider - Infermatic", + provider: "Infermatic", + exists: true, + }, { name: "Existing provider - MiniMax", provider: "MiniMax", From 7012acd12add4a967621f080a268c19a34600a1b Mon Sep 17 00:00:00 2001 From: Kayvan Sylvan Date: Mon, 19 Jan 2026 08:15:22 -0800 Subject: [PATCH 3/4] fix: replace go-git status API with native git CLI for worktree compatibility - Replace go-git status API with native `git status --porcelain` command - Fix worktree detection issues caused by go-git library bugs - Simplify `IsWorkingDirectoryClean` to use CLI output parsing - Simplify `GetStatusDetails` to return raw porcelain output - Use native `git rev-parse HEAD` to get commit hash after commit - Remove unused `os` and `filepath` imports from walker.go - Remove complex worktree file existence checking logic --- cmd/generate_changelog/internal/git/walker.go | 67 ++++++++----------- 1 file changed, 27 insertions(+), 40 deletions(-) diff --git a/cmd/generate_changelog/internal/git/walker.go b/cmd/generate_changelog/internal/git/walker.go index a8c03c8d..e7aaf50d 100644 --- a/cmd/generate_changelog/internal/git/walker.go +++ b/cmd/generate_changelog/internal/git/walker.go @@ -2,9 +2,7 @@ package git import ( "fmt" - "os" "os/exec" - "path/filepath" "regexp" "strconv" "strings" @@ -425,64 +423,49 @@ func (w *Walker) Repository() *git.Repository { } // IsWorkingDirectoryClean checks if the working directory has any uncommitted changes +// Uses native git CLI instead of go-git to properly handle worktree scenarios func (w *Walker) IsWorkingDirectoryClean() (bool, error) { worktree, err := w.repo.Worktree() if err != nil { return false, fmt.Errorf("failed to get worktree: %w", err) } - status, err := worktree.Status() + worktreePath := worktree.Filesystem.Root() + + // Use native git status --porcelain to avoid go-git worktree issues + // go-git's status API has known bugs with linked worktrees + cmd := exec.Command("git", "status", "--porcelain") + cmd.Dir = worktreePath + + output, err := cmd.Output() if err != nil { return false, fmt.Errorf("failed to get git status: %w", err) } - worktreePath := worktree.Filesystem.Root() - - // In worktrees, files staged in the main repo may appear in status but not exist in the worktree - // We need to check both the working directory status AND filesystem existence - for file, fileStatus := range status { - // Check if there are any changes in the working directory - if fileStatus.Worktree != git.Unmodified && fileStatus.Worktree != git.Untracked { - return false, nil - } - - // For staged files (Added, Modified in index), verify they exist in this worktree's filesystem - // This handles the worktree case where the main repo has staged files that don't exist here - if fileStatus.Staging != git.Unmodified && fileStatus.Staging != git.Untracked { - filePath := filepath.Join(worktreePath, file) - if _, err := os.Stat(filePath); os.IsNotExist(err) { - // File is staged but doesn't exist in this worktree - ignore it - continue - } - // File is staged AND exists in this worktree - not clean - return false, nil - } - } - - return true, nil + // If output is empty, working directory is clean + return len(strings.TrimSpace(string(output))) == 0, nil } // GetStatusDetails returns a detailed status of the working directory +// Uses native git CLI instead of go-git to properly handle worktree scenarios func (w *Walker) GetStatusDetails() (string, error) { worktree, err := w.repo.Worktree() if err != nil { return "", fmt.Errorf("failed to get worktree: %w", err) } - status, err := worktree.Status() + worktreePath := worktree.Filesystem.Root() + + // Use native git status --porcelain to avoid go-git worktree issues + cmd := exec.Command("git", "status", "--porcelain") + cmd.Dir = worktreePath + + output, err := cmd.Output() if err != nil { return "", fmt.Errorf("failed to get git status: %w", err) } - var details strings.Builder - for file, fileStatus := range status { - // Only include files with actual working directory changes - if fileStatus.Worktree != git.Unmodified && fileStatus.Worktree != git.Untracked { - details.WriteString(fmt.Sprintf(" %c%c %s\n", fileStatus.Staging, fileStatus.Worktree, file)) - } - } - - return details.String(), nil + return string(output), nil } // AddFile adds a file to the git index @@ -526,13 +509,17 @@ func (w *Walker) CommitChanges(message string) (plumbing.Hash, error) { return plumbing.ZeroHash, fmt.Errorf("failed to commit: %w (output: %s)", err, string(output)) } - // Get the commit hash from HEAD - ref, err := w.repo.Head() + // Get the commit hash from HEAD using native git to avoid go-git worktree issues + hashCmd := exec.Command("git", "rev-parse", "HEAD") + hashCmd.Dir = worktreePath + + hashOutput, err := hashCmd.Output() if err != nil { return plumbing.ZeroHash, fmt.Errorf("failed to get HEAD after commit: %w", err) } - return ref.Hash(), nil + hashStr := strings.TrimSpace(string(hashOutput)) + return plumbing.NewHash(hashStr), nil } // PushToRemote pushes the current branch to the remote repository From f4e7489d42548966b86b11894891c00d04156557 Mon Sep 17 00:00:00 2001 From: Kayvan Sylvan Date: Mon, 19 Jan 2026 08:16:05 -0800 Subject: [PATCH 4/4] chore: incoming 1944 changelog entry --- cmd/generate_changelog/incoming/1944.txt | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 cmd/generate_changelog/incoming/1944.txt diff --git a/cmd/generate_changelog/incoming/1944.txt b/cmd/generate_changelog/incoming/1944.txt new file mode 100644 index 00000000..c593238f --- /dev/null +++ b/cmd/generate_changelog/incoming/1944.txt @@ -0,0 +1,7 @@ +### PR [#1944](https://github.com/danielmiessler/Fabric/pull/1944) by [ksylvan](https://github.com/ksylvan): Add Infermatic AI Provider Support + +- Add Infermatic provider to ProviderMap as part of Phase 1 implementation for issue #1033 +- Add test coverage for the Infermatic AI provider in TestCreateClient to verify provider exists and creates valid client +- Replace go-git status API with native `git status --porcelain` command to fix worktree compatibility issues +- Simplify `IsWorkingDirectoryClean` and `GetStatusDetails` functions to use CLI output parsing instead of go-git library +- Use native `git rev-parse HEAD` to get commit hash after commit and remove unused imports from walker.go