git-commit-suggestion — Knowledge Base

Non-obvious facts about providers, the pipeline, and VSCode integration. Append new gotchas here as you discover them; do not delete entries unless the underlying behavior changed.

Auto-fallback chain

The default provider: "auto" walks AUTO_CHAIN = ["pollinations", "duckduckgo", "huggingface"] in orchestrator.ts, returning the first success. Every leg is keyless — auto mode is guaranteed not to prompt for credentials. Ordering rationale:

  1. pollinations first — pure-OpenAI schema, no handshake, GPT-4o-class. Lowest friction.
  2. duckduckgo second — needs a vqd handshake (extra round-trip) but otherwise reliable; supports multiple frontier models.
  3. huggingface third — works without a key but per-IP rate-limited heavily; default model is a 7B which is sometimes worse at JSON.

When all three legs fail, the orchestrator throws a single error that lists every leg's failure reason. The webview surfaces this verbatim — useful for debugging because typically only one or two legs go down at a time. Providers that require a key (mistral, openai, anthropic, groq) are never in the auto chain; the user must select them explicitly after pasting a key.

Provider quirks

Pollinations.ai

DuckDuckGo AI Chat

HuggingFace router

No bundled keys — BYOK only

The extension ships no API keys. Providers split into two categories:

Earlier in the project we shipped a hardcoded shared Mistral key as a convenience. That was reversed: shared keys get burned or violate ToS once the extension hits real usage.

Mistral free tier

Anthropic — different schema

Ollama (local)

Groq

g4f — unofficial reverse proxy

Risk acknowledged by the user. g4f-style endpoints scrape or proxy upstream provider sessions. Using them violates the upstream provider's Terms of Service, has no SLA, and historically some forks have shipped credential-stealing payloads. The extension gates this provider behind gitCommitSuggestion.enableUnofficialProviders and shows a modal warning before first use.

Provider fetches need a hard timeout — Node's fetch has none

Node's fetch() never times out on its own. If an upstream LB accepts the TCP connection then never sends a response (Pollinations does this occasionally when rate-limited; Cloudflare-fronted providers do it during incidents), await resp.text() hangs forever. The webview shows a spinning loader with no exit condition — exactly the bug 0.1.1 was supposed to kill, just via a different path. Always wrap provider calls in an AbortController tied to a setTimeout; the timeout-fired abort must be distinguishable from a user-initiated Stop so the chain can surface "Timed out after Ns" instead of treating it as a silent cancel.

HTTP error bodies — never inline raw response text

Every provider that does throw new ProviderError(this.id, `HTTP ${resp.status}: ${text.slice(0, 400)}`) is a footgun. When upstream load balancers (Cloudflare, nginx) return 502/503, the body is a full HTML page with <!DOCTYPE> + meta + inline CSS. The orchestrator aggregates these into "all auto-chain providers failed:\n…" and dumps the wall of HTML into the webview banner. Route every HTTP error body through summarizeErrorBody() in src/providers/base.ts — it preserves the first 400 chars of JSON bodies (where upstream API errors put their useful message) but tag-strips and 120-caps HTML/plain text.

Pipeline quirks

Locating the git repo root

Diff truncation

JSON parsing

SCM input box

VSCode integration quirks

Secrets vs settings

Activation events

F5 debug launch: preLaunchTask must not depend on PATH

The preLaunchTask npm: compile in .vscode/tasks.json uses type: "process" with absolute paths to node and tsc.js, NOT type: "shell". Earlier attempts with shell tasks failed intermittently with exit 127 ("command not found"), even after adding an env PATH override. Root cause on macOS: the task shell sources /etc/zshenv → path_helper and .zprofile, which can rebuild PATH in unpredictable order. When nvm is lazy-loaded in .zshrc (a common setup), node exists only as a shell function that a non-interactive task shell never triggers, so /usr/bin/env node inside the tsc shebang resolves to nothing. type: "process" bypasses all of that — VS Code execs the binary directly, no shell startup, no shebang resolution.

Do NOT put `when` on a view contribution

The view in views.scm must NOT have a "when" clause. Context keys like scmProvider == git apply to menu contributions only (menus.scm/title, menus.view/title). On view contributions, an unmatched when silently hides the entire view — symptom: "Commit Suggestions doesn't appear in my SCM sidebar". Earlier in this project the view was hidden by exactly this mistake for several commits.

Webview view (sidebar GUI)

Cross-view navigation (SCM ↔ Commit Suggestion)

Cancelling an in-flight LLM request (Stop button)

Repo layout principle

Layout mirrors index-crawl: