Skip to content

test(supervisor): cover restart backoff timing - #1

Closed
vernonstinebaker wants to merge 87 commits into
mainfrom
test/supervisor-backoff-semantics
Closed

test(supervisor): cover restart backoff timing#1
vernonstinebaker wants to merge 87 commits into
mainfrom
test/supervisor-backoff-semantics

Conversation

@vernonstinebaker

Copy link
Copy Markdown
Owner

Summary

  • add supervisor tests that verify restarting instances do not respawn before the configured backoff window elapses
  • cover the capped backoff path to confirm later restart attempts still advance state and update restart timing

Validation

  • zig build test -Dembed-ui=false -Dbuild-ui=false --summary all

vernonstinebaker and others added 30 commits May 4, 2026 17:41
Custom providers (those with a base_url) now bypass the nullclaw probe on
create and update. The probe is designed for known providers and can
misclassify valid HTTP 200 responses from arbitrary OpenAI-compatible
endpoints (e.g. when the endpoint returns an empty completion body).

Standard providers (no base_url) continue to use the nullclaw probe as
before. The re-validate endpoint returns a clear message for custom
providers explaining that /models-based validation is coming in a follow-up.

Removes the skip_validation workaround that was auto-retried on the
frontend — the fix is now in the backend dispatch logic.

Adds base_url and provider_name fields to the provider CRUD API, state,
and UI (add form, edit form, card display, wizard step, config editor).
Adds 'OpenAI Compatible (custom endpoint)' to the provider picker.

Validation:
- zig build test -Dbuild-ui=false --summary all: all tests pass, 0 leaks
- Manual test against local llmserverplus (http://127.0.0.1:5801/v1):
  custom provider saves without probe, update skips re-probe,
  re-validate returns expected not-available message

Notes:
- Credential validation for custom endpoints via /models endpoint
  is tracked separately (PR 2)
- GET /api/providers/probe-models?base_url=...&api_key=... fetches
  available model IDs from any OpenAI-compatible /models endpoint
- handleCreate, handleUpdate, handleValidate now probe custom providers
  via /models instead of silently skipping; create/update are non-blocking
  (always save, record validation result); validate returns live status
- Frontend: Fetch Models button in add/edit forms for custom providers;
  clickable model chips populate the model field
- 9 new backend tests (buildModelsUrl, parseModelIdsJson, isProbeModelsPath,
  handleProbeModels, handleValidate behaviour, handleCreate timestamp)
…base_url

- Replace all real provider names/URLs/ports in test blocks with generic
  values (custom-llm, https://example.com/v1, sk-test-key, port 19999)
- Fix State.load() silently dropping base_url on round-trip: the struct
  literal in the saved_providers loop was missing .base_url = owned_base_url
- Remove dangling orphan load-block left by a partial test edit
- UI, syncProviderToInstances, and /models probe changes from prior work
  included in this commit (were already staged but uncommitted)
- Add ui/src/lib/providers.ts as shared source of truth for provider
  constants (PROVIDER_OPTIONS, OPENAI_COMPATIBLE_VALUE, LOCAL_PROVIDERS,
  KNOWN_PROVIDER_VALUES, mergeWithManifestOptions)
- providers/+page.svelte and ProviderList.svelte now import from the
  shared module; openai-compatible always visible in wizard dropdown
- orchestrator: extractCustomProvider strips custom provider fields
  before --from-json call so the binary sees no unknown provider name;
  patchProviderIntoConfig injects credentials into generated config
  after binary writes it (models.providers.<name>)
…in --from-json payload

The wizard sends both a top-level provider field and a providers array;
clearing them to empty string still caused 'UNKNOWN PROVIDER' because
nullclaw validates the name in both locations.

Fix: replace custom provider entries with 'openai' (a known valid name)
so the binary generates a valid base config, then patchProviderIntoConfig
writes the real credentials into models.providers.<custom-name>
afterwards. Also adds debug prints to confirm the detection path fires.
…m provider install

- Add `model` field to CustomProvider; extract from wizard answers before stripping
- patchProviderIntoConfig now sets agents.defaults.model.primary to <provider>/<model>
- Remove the injected `openai` placeholder key from models.providers after binary runs
… install

Custom providers backed by a local LLM may expose models whose vision
probe never returns an error response — instead it hangs indefinitely,
which blocks the nullclaw gateway HTTP handler during startup and causes
the nullhub supervisor health-check to time out after 30 s.

patchProviderIntoConfig now appends the installed model to
agent.vision_disabled_models whenever a base_url is present, so the
probe is skipped and the instance passes its first health check.
downloader.download() was called unconditionally on every install, even
when the binary was already present in ~/.nullhub/bin/. This made every
reinstall (e.g. updating provider config on an existing instance) pay
the full network round-trip cost.

Add the same existence check that stageLocalBinary already uses: open
the target path; if it succeeds the binary is cached and the download
is skipped entirely.
- ensureModelOptions now calls api.probeProviderModels(base_url, api_key)
  instead of api.getWizardModels for openai-compatible providers; the
  wizard list-models path calls nullclaw --list-models which does not
  support arbitrary base_url endpoints
- modelKey now includes base_url so different custom endpoints with the
  same api_key get separate cache entries
- server.zig: log the actual error when State.load() fails before
  falling back to empty state, preventing silent data loss
- WizardRenderer: openai-compatible providers (with base_url) are now
  validated via probeProviderModels HTTP probe instead of the nullclaw
  binary; nullclaw does not recognise the 'openai-compatible' provider
  name so it always returned live_ok=false, blocking the NEXT button
- WizardRenderer: import OPENAI_COMPATIBLE_VALUE from providers.ts
- Instance page: suppress provider health hint/warn while instance is
  not running (status != 'running') — stale 'instance_not_running'
  result from boot probe no longer shows as a provider error
- Instance page: re-fetch provider health automatically when the
  instance transitions from any state to 'running'
nullclaw-dev-local panics with 'programmer bug caused syscall error: AGAIN'
when a2a.enabled is false.  The --from-json generator always emits
enabled:false for fresh installs, so patchProviderIntoConfig now flips it
to true while preserving all other a2a fields (url, name, version, etc.).

Two tests cover the fix: one for the false→true mutation, one to confirm
an already-true value is left unchanged.

Also corrects the vision_disabled_models comment: the field is used at
inference time to strip image markers, not to suppress the startup probe.
OpenAI-compatible checks were timing out before healthy providers could respond through the probe path, which misreported working configs as failed.
…atible-providers

feat(providers): add OpenAI-compatible provider support with base_url
DonPrus and others added 28 commits May 6, 2026 14:36
…on-proxy

test(orchestration): cover proxy status and method handling
…ailures

test(installer): roll back persisted state on start failure
…ndaries

test(service): tighten systemctl status parsing
…lease-compat

fix(ui): install chat modules from released archives
…imported-standalone

fix(instances): report imported standalone live status
…refresh

# Conflicts:
#	src/api/instances.zig
…nary-refresh

fix(instances): refresh staged dev-local binaries
Preserve short-read semantics in the Zig 0.16 compat stream on Windows and keep the integration smoke on the real std.http.Client path.

Also keeps backend CI bounded with a timeout so a socket regression fails visibly instead of hanging indefinitely.
…-http-smoke

test(integration): add structured HTTP smoke harness
…e-load

fix(runtime): load persisted runtime state safely
…te-guard

fix(ui): avoid resetting instance page on same route
@vernonstinebaker

Copy link
Copy Markdown
Owner Author

Opened by mistake while preparing the upstream PR. Tracking the real review at nullclaw#60.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants