Move the active-hours helpers (resolveActiveHoursTimezone,
parseActiveHoursTime, resolveMinutesInTimeZone, isWithinActiveHours)
into heartbeat-active-hours.ts to reduce heartbeat-runner.ts below
the 1030-line CI threshold after the model-override addition.
The heartbeat runner correctly merges per-agent heartbeat config
(agents.list[].heartbeat.model) with global defaults, but never
passed the resolved model through to getReplyFromConfig. The reply
layer only read cfg.agents.defaults.heartbeat.model, ignoring
per-agent overrides entirely.
Add heartbeatModelOverride to GetReplyOptions so the heartbeat
runner can forward the merged model. The reply layer now prefers
the explicit override, falling back to the global default for
backward compatibility.
Closes#14087
* fix(cli): exit with non-zero code when configure/agents-add wizards are cancelled
Follow-up to the onboard cancel fix. The configure wizard and
agents add wizard also caught WizardCancelledError and exited with
code 0, which signals success to callers. Change to exit(1) for
consistency — user cancellation is not a successful completion.
This ensures scripts that chain these commands with set -e will
correctly stop when the user cancels.
* fix(cli): make wizard cancellations exit non-zero (#14156) (thanks @0xRaini)
---------
Co-authored-by: Rain <rain@Rains-MBA-M4.local>
Co-authored-by: Sebastian <19554889+sebslight@users.noreply.github.com>
When creating a Discord thread without a messageId (standalone thread),
the Discord API defaults to type 12 (private). Most users expect public.
- Default standalone non-forum threads to ChannelType.PublicThread (11)
- Add optional type field to DiscordThreadCreate for explicit control
Closes#14147
When creating a Discord thread without a messageId, the API defaults
to type 12 (private thread) which is unexpected. This adds an explicit
type: PublicThread (11) for standalone thread creation in non-forum
channels, matching user expectations.
Closes#14147
The xAI /v1/responses API returns content in a structured format with
typed output blocks (type: 'message') containing typed content blocks
(type: 'output_text') and url_citation annotations. The previous code
only checked output[0].content[0].text without filtering by type,
which could miss content in responses with multiple output entries.
Changes:
- Update GrokSearchResponse type to include annotations on content blocks
- Filter output blocks by type='message' and content by type='output_text'
- Extract url_citation annotations as fallback citations when top-level
citations array is empty
- Deduplicate annotation-derived citation URLs
- Update tests for the new structured return type
Closes#13520
* feat: add LiteLLM provider types, env var, credentials, and auth choice
Add litellm-api-key auth choice, LITELLM_API_KEY env var mapping,
setLitellmApiKey() credential storage, and LITELLM_DEFAULT_MODEL_REF.
* feat: add LiteLLM onboarding handler and provider config
Add applyLitellmProviderConfig which properly registers
models.providers.litellm with baseUrl, api type, and model definitions.
This fixes the critical bug from PR #6488 where the provider entry was
never created, causing model resolution to fail at runtime.
* docs: add LiteLLM provider documentation
Add setup guide covering onboarding, manual config, virtual keys,
model routing, and usage tracking. Link from provider index.
* docs: add LiteLLM to sidebar navigation in docs.json
Add providers/litellm to both English and Chinese provider page lists
so the docs page appears in the sidebar navigation.
* test: add LiteLLM non-interactive onboarding test
Wire up litellmApiKey flag inference and auth-choice handler for the
non-interactive onboarding path, and add an integration test covering
profile, model default, and credential storage.
* fix: register --litellm-api-key CLI flag and add preferred provider mapping
Wire up the missing Commander CLI option, action handler mapping, and
help text for --litellm-api-key. Add litellm-api-key to the preferred
provider map for consistency with other providers.
* fix: remove zh-CN sidebar entry for litellm (no localized page yet)
* style: format buildLitellmModelDefinition return type
* fix(onboarding): harden LiteLLM provider setup (#12823)
* refactor(onboarding): keep auth-choice provider dispatcher under size limit
---------
Co-authored-by: Peter Steinberger <steipete@gmail.com>
- Remove specific machine type (CX22) and pricing
- Hetzner pricing and server types change frequently
- Keep focus on technical approach rather than costs
- Add Infrastructure as Code section to Hetzner installation docs
- Links to community-maintained Terraform repositories
- Provides alternative for users preferring IaC workflows
- Includes cost estimate and feature overview
Related: Discussion #12532
* fix: enforce embedding model token limit to prevent 8192 overflow
- Replace EMBEDDING_APPROX_CHARS_PER_TOKEN=1 with UTF-8 byte length
estimation (safe upper bound for tokenizer output)
- Add EMBEDDING_MODEL_MAX_TOKENS=8192 hard cap
- Add splitChunkToTokenLimit() that binary-searches for the largest
safe split point, with surrogate pair handling
- Add enforceChunkTokenLimit() wrapper called in indexFile() after
chunkMarkdown(), before any embedding API call
- Fixes: session files with large JSONL entries could produce chunks
exceeding text-embedding-3-small's 8192 token limit
Tests: 2 new colocated tests in manager.embedding-token-limit.test.ts
- Verifies oversized ASCII chunks are split to <=8192 bytes each
- Verifies multibyte (emoji) content batching respects byte limits
* fix: make embedding token limit provider-aware
- Add optional maxInputTokens to EmbeddingProvider interface
- Each provider (openai, gemini, voyage) reports its own limit
- Known-limits map as fallback: openai 8192, gemini 2048, voyage 32K
- Resolution: provider field > known map > default 8192
- Backward compatible: local/llama uses fallback
* fix: enforce embedding input size limits (#13455) (thanks @rodrigouroz)
---------
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
* Heartbeat: inject cron-style current time into prompts
* Tests: fix type for web heartbeat timestamp test
* Infra: inline heartbeat current-time injection
* fix(pairing): show actual code in approval command instead of placeholder
The pairing reply shown to new users included the approval command with
a literal '<code>' placeholder. Users had to manually copy the code
from one line and substitute it into the command.
Now shows the ready-to-copy command with the real pairing code:
Before: openclaw pairing approve telegram <code>
After: openclaw pairing approve telegram abc123
Fixed in both the shared pairing message builder and the Telegram
inline pairing reply.
* test(pairing): update test to expect actual code instead of placeholder
---------
Co-authored-by: Echo Ito <echoito@MacBook-Air.local>
xAI's /v1/responses endpoint does not support the 'include' parameter,
returning 400 'Argument not supported: include'. Inline citations are
returned automatically when available — no explicit request needed.
Closes#12910
Co-authored-by: Luna AI <luna@coredirection.ai>