The quickstart tells users to run `npx tempest config` to switch to the local
provider, but there is no `config` subcommand — the CLI exposes `interactive`
(default), `setup`, `status`, `test`, and `models`. The "Change default
provider" flow lives in the default `interactive` command, so the correct
invocation is `npx tempest`.
Add a first-class `gemini` provider so operators can drive missions with a
direct GEMINI_API_KEY, instead of only reaching Gemini through OpenRouter.
Gemini is wired exactly like xAI: dispatched through OpenAIAdapter against
Google's OpenAI-compatible surface. The base URL is
https://generativelanguage.googleapis.com/v1beta/openai — the `/openai`
segment is required because OpenAIAdapter posts to `${baseUrl}/chat/completions`;
without it requests hit `/v1beta/chat/completions`, which Google does not serve.
Wires the provider through the type union, adapter factory, config
(interface, defaults, model catalog, key env map, getLLMConfig, fallback
chain, redaction, .env template), and adds regression tests pinning the
`/openai` base-URL segment.
Two issues blocked OpenAI-compatible servers that aren't Ollama-on-/v1:
1. LocalAdapter.isOpenAIWire matched only a literal /v1 path, so versioned
endpoints like Zhipu/z.ai's /api/paas/v4 silently fell through to Ollama's
native /api/chat wire format and failed. Match any /vN instead of literally /v1.
2. The `local` provider was treated as always-keyless, so servers that require
a bearer (Zhipu/z.ai, Together, ...) could never authenticate. Read an
optional key from TEMPEST_LOCAL_API_KEY (ZAI_API_KEY / ZHIPUAI_API_KEY as
aliases), wire it through getApiKey/hasApiKey so `tempest test` and the
mission engine accept a configured local provider, and document the options
in the env template.
The key is read from env in-memory and never persisted into the store, matching
the existing env-key hardening invariant (api-key-env-static).
Adds src/__tests__/local-openai-wire-static.test.ts pinning both fixes.
Verified end-to-end against z.ai's GLM models (glm-4.5-air / 4.6 / 5.2).
The opt-in code/supply-chain scanners (semgrep, gitleaks, trufflehog, trivy,
syft, grype, checkov) are subcommand-driven and non-networked, but had no
bespoke arg template — so adapterToCustomTool fell through to DEFAULT_TEMPLATE
and spawned `<binary> <target>`. For these that is a broken invocation:
`semgrep <host>` never runs a scan, and with no target it is `semgrep ''`.
semgrep in particular is advertised on the arsenal's headline tool list.
Add per-binary templates that mirror each tool's catalog commandHint and
operate on a filesystem PATH (default: the working dir "."):
semgrep → scan --config auto --json <path>
gitleaks → detect --source <path> --report-format json --redact --no-banner
trufflehog → filesystem <path> --json --no-update
trivy → fs --format json <path>
syft → dir:<path> -o cyclonedx-json
grype → dir:<path> -o json
checkov → -d <path> -o json
Subcommand + output flags are hardcoded (never taken from an LLM string),
matching the conservative pattern of the existing templates. The path is the
only tunable and is sanitised by scanPath(): a leading '-' (flag injection) or
an inherited http(s) mission target is rejected in favour of ".". Option-looking
targets are still refused up front by the factory's existing guard (no spawn).
Adds table-driven tests asserting the exact argv for each scanner, the "."
default, http(s)-target rejection, and the option-looking-path refusal.
Three new category loadouts, each = arsenal + an offline-scorable benchmark, opt-in and
honestly scoped (roster marks all 🚧; pacu/frida stay catalog_only, unit-tested non-mintable):
- cloud: aws/az/gcloud + scoutsuite/cloudfox/pmapper; cloud:bench IaC-misconfig detection
- mobile: apkleaks/mobsfscan/drozer/objection/class-dump; mobile:bench static ruleset
- binary/RE: ghidra/objdump/checksec/strings/readelf/gdb; binary:bench decompiled-sink detector
Mobile/binary benches are DETECTOR REGRESSION CHECKS (rules+fixtures co-authored — a pass is a
floor, not a detection rate). No new headline numbers; verify-claims 24/24.
tsc clean; 337 tests; lint 0 errors.
Model IDs confirmed against xAI's published list (docs.x.ai/docs/models, 2026-07-05):
grok-build-0.1 (coding, 256K) and grok-4.3 (general, 1M). Addresses PR review P2.
The honesty pass had the hero paragraph and the benchmarks 'flex' block
restating numbers/caveats already in the Benchmarks table. State each once:
the hero drops the inline CVE-Zero deep-dive (kept in the table) and points to
#benchmarks; the flex block trims to its thesis. No claim/number changes.