* feat(tencent): add bundled Tencent Cloud provider plugin (Tokenhub + Token Plan)
* fix(tencent): use provider-specific default model aliases
Both Tencent providers previously defaulted to the same alias "HY3 Preview",
which collides in buildModelAliasIndex (single alias map, keyed by normalized
alias). When both providers are onboarded, alias-based selection routed to
whichever provider was configured last.
Disambiguate the fallback aliases so resolution is deterministic regardless
of onboarding order:
- tencent-tokenhub -> "HY3 Preview (TokenHub)"
- tencent-token-plan -> "HY3 Preview (Token Plan)"
* docs(tencent): rename model to "Hy3 preview" and drop "HY3" family name
Align with the external-facing product name:
- model display name: "HY3 Preview" -> "Hy3 preview"
- family/umbrella references in docs and auth hints: "HY3" -> "Hy3 preview"
- internal cost constant: HY3_COST -> HY_COST
Model call id (hy3-preview) is unchanged.
* docs(tencent): use "Hy" as the family name in generic references
Keep specific model references as "Hy3 preview" (model catalog names,
onboarding aliases, Available-models docs entries), but switch
family/umbrella references to the plain "Hy" family name so future Hy
versions fit without doc churn:
- auth hints: "Hy via Tencent TokenHub Gateway" / "Hy via Token Plan"
- docs intro + Use-case table: "Tencent Hy models" / "call Hy via ..."
- models.ts pricing comment: "Hy pricing"
* feat(tencent): add tiered pricing for Hy3 preview model
---------
Co-authored-by: albertxyu <albertxyu@tencent.com>
* fix(memory/dreaming): surface blocked status in memory status when heartbeat disabled for main
Replace the hand-rolled heartbeat-rules logic in resolveDreamingBlockedReason
with the shared resolveHeartbeatSummaryForAgent helper, promoted from core to
the plugin-sdk via infra-runtime. Collapses the two disabled-reason branches
into a single message that points at a new Troubleshooting section in the
dreaming docs, so the silent-failure mode described in openclaw/openclaw#69843
becomes legible without the extension re-encoding heartbeat-enablement rules.
Refs openclaw/openclaw#69843, openclaw/openclaw#46046.
* refactor(memory/dreaming): share resolveDreamingBlockedReason across cli and /dreaming surfaces
- Move resolveDreamingBlockedReason from cli.runtime.ts into dreaming.ts as an exported helper and pin its heartbeat check to DEFAULT_AGENT_ID (now exported from plugin-sdk/routing) so the status-line check agrees with the cron's hardcoded sessionTarget even when the configured default agent is not main.
- Render the blocked reason from formatStatus in dreaming-command.ts directly under the enabled line, so /dreaming status, /dreaming on, /dreaming off, and bare /dreaming all flag that the cron is blocked instead of implying dreaming is healthy.
- Tighten the blocked-reason text to lead with user impact ('dreaming is enabled but will not run because heartbeat is disabled for main'), so operators immediately understand the config is toggled on but nothing is actually running.
- Tighten the dreaming Troubleshooting copy to name main explicitly and mention both surfaces.
- Add tests locking the new behavior across cli.test.ts (default-agent=ops still reports blocked for main) and dreaming-command.test.ts (/dreaming status ordering, /dreaming on surfacing, healthy-heartbeat omission).
Refs openclaw/openclaw#69843, openclaw/openclaw#46046.
* fix(memory/dreaming): check heartbeat for the resolved default agent, not the literal 'main'
sessionTarget: 'main' is a cron session-type enum variant meaning 'the default agent's main session', not an agent id (see src/cron/service/jobs.ts). buildManagedDreamingCronJob does not set agentId, and cron runtime resolves the missing agentId through resolveDefaultAgentId(cfg) before enqueuing or waking. The previous pin to DEFAULT_AGENT_ID could produce a false 'blocked' reading when a configured default agent is not 'main' and its heartbeat is fine, and could miss a real block when the default agent is not 'main' and that agent's heartbeat is actually off.
Switch resolveDreamingBlockedReason to resolveDefaultAgentId(cfg) and interpolate the resolved agent id into the message so the blocked line names the agent whose heartbeat is the blocker. Introduce a narrow local CRON_SESSION_TARGET_MAIN constant for the cron session-type enum variant (used by the sessionTarget type and value) so the remaining 'main' literal is semantically distinct from any agent id. Revert the DEFAULT_AGENT_ID export addition on plugin-sdk/routing; memory-core no longer needs it. Update the Troubleshooting doc wording and the cli test that was locking the wrong behaviour.
Refs openclaw/openclaw#69843, openclaw/openclaw#46046.
* fix(memory/dreaming): align blocked check with server-cron wake's defaults-only heartbeat
resolveDreamingBlockedReason was using resolveHeartbeatSummaryForAgent, which merges agents.defaults.heartbeat with agents.list[].heartbeat. The managed dreaming cron leaves job.agentId and job.sessionKey unset, so server-cron's wake wrapper cannot look up a per-agent entry and calls runHeartbeatOnce with agents.defaults.heartbeat only. Using the summary helper would disagree with the actual wake when the default agent overrides heartbeat.every differently from the defaults (either direction — false blocked when the override would run, or false healthy when defaults block).
Mirror the wake path explicitly: rule-1 enablement via isHeartbeatEnabledForAgent against the default agent, rule-3 interval via resolveHeartbeatIntervalMs with defaults-only heartbeat config. Comment points at server-cron so a future cleanup of that latent override-propagation gap sees the coupling.
Refs openclaw/openclaw#69843.
Link docs feature cards to their intended destination pages in the English docs surfaces.
- add hrefs to the feature cards in docs/concepts/features.md
- add hrefs to the key capability cards in docs/index.md
- preserve current main branch copy while landing the navigation fix