Detects Azure AI Foundry URLs (services.ai.azure.com and
openai.azure.com) and transforms them to include the proper
deployment path (/openai/deployments/<model-id>) required by
Azure's API. This fixes the 400 error when configuring OpenAI
models from Azure AI Foundry.
Fixesopenclaw/openclaw#17992
When a model API call hangs indefinitely (e.g. Anthropic quota exceeded
mid-call), the gateway acquires a session .jsonl.lock but the promise
never resolves, so the try/finally block never reaches release(). Since
the owning PID is the gateway itself, stale detection cannot help —
isPidAlive() always returns true.
This commit adds four layers of defense:
1. **In-process lock watchdog** (session-write-lock.ts)
- Track acquiredAt timestamp on each held lock
- 60-second interval timer checks all held locks
- Auto-releases any lock held longer than maxHoldMs (default 5 min)
- Catches the hung-API-call case that try/finally cannot
2. **Gateway startup cleanup** (server-startup.ts)
- On boot, scan all agent session directories for *.jsonl.lock files
- Remove locks with dead PIDs or older than staleMs (30 min)
- Log each cleaned lock for diagnostics
3. **openclaw doctor stale lock detection** (doctor-session-locks.ts)
- New health check scans for .jsonl.lock files
- Reports PID status and age of each lock found
- In --fix mode, removes stale locks automatically
4. **Transcript error entry on API failure** (attempt.ts)
- When promptError is set, write an error marker to the session
transcript before releasing the lock
- Preserves conversation history even on model API failures
Closes#18060
`models set` accepts any syntactically valid model ID without checking
the catalog, allowing typos to silently persist in config and fail at
runtime. It also unconditionally adds an empty `{}` entry to
`agents.defaults.models`, bypassing any provider routing constraints.
This commit:
- Validates the model ID against the catalog (skipped when catalog is
empty during initial setup)
- Warns when a new entry is added with empty config (no provider routing)
Closesopenclaw/openclaw#17183✍️ Author: Claude Code with @carrotRakko (AI-written, human-approved)
`openclaw doctor` audited gateway service runtime/path settings but did not
check whether the daemon's `OPENCLAW_GATEWAY_TOKEN` matched
`gateway.auth.token` in `openclaw.json`.
After re-pairing or token rotation, the config token and service env token can
drift. The daemon may keep running with a stale service token, leading to
unauthorized handshake failures for cron/tool clients.
Add a gateway service audit check for token drift and pass
`cfg.gateway.auth.token` into service audits so doctor treats config as the
source of truth when deciding whether to reinstall the service.
Key design decisions:
- Use `gateway.auth.token` from `openclaw.json` as the authority for service
token drift detection
- Only flag mismatch when an authoritative config token exists
- Keep fix in existing doctor service-repair flow (no separate migration step)
- Add focused tests for both audit mismatch behavior and doctor wiring
Fixes#18175
Addresses review feedback — channelName was declared but only
prefix was used for change messages.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When a channel is configured with dmPolicy="open" but without
allowFrom: ["*"], the gateway rejects the config and exits.
The error message suggests running "openclaw doctor --fix", but
the doctor had no repair logic for this case.
This adds a repair step that automatically adds "*" to allowFrom
(or creates it) when dmPolicy="open" is set without the required
wildcard. Handles both top-level and nested dm.allowFrom, as well
as per-account configs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>