fix: tighten model fallback + docs (#1762) (thanks @senoldogann)

This commit is contained in:
Peter Steinberger
2026-01-25 12:54:32 +00:00
parent f552055cef
commit d7f5818443
5 changed files with 19 additions and 8 deletions

View File

@@ -46,6 +46,7 @@ Docs: https://docs.clawd.bot
- Agents: auto-compact on context overflow prompt errors before failing. (#1627) Thanks @rodrigouroz.
- Agents: use the active auth profile for auto-compaction recovery.
- Models: default missing custom provider fields so minimal configs are accepted.
- Models/Heartbeat: normalize provider-less default model fallback and skip empty checklist items. (#1762) Thanks @senoldogann.
- Media understanding: skip image understanding when the primary model already supports vision. (#1747) Thanks @tyler6204.
- Gateway: skip Tailscale DNS probing when tailscale.mode is off. (#1671)
- Gateway: reduce log noise for late invokes + remote node probes; debounce skills refresh. (#1607) Thanks @petter-b.

View File

@@ -46,7 +46,7 @@ AI PRs are first-class citizens here. We just want transparency so reviewers kno
We are currently prioritizing:
- **Stability**: Fixing edge cases in channel connections (WhatsApp/Telegram).
- **UX**: Improving the onboarding wizard and error messages.
- **Skills**: Expanding the library of bundled skills and improving the Skill Creation developer experience.
- **Skills**: ClawdHub-first (no new core/bundled skills).
- **Performance**: Optimizing token usage and compaction logic.
Check the [GitHub Issues](https://github.com/clawdbot/clawdbot/issues) for "good first issue" labels!

View File

@@ -8,7 +8,7 @@ A skill is a directory containing a `SKILL.md` file (which provides instructions
## Step-by-Step: Your First Skill
### 1. Create the Directory
Skills live in your workspace, usually `~/clawd/skills/`. Create a new folder for your skill:
Skills live in your workspace at `<workspace>/skills` (default: `~/clawd/skills`). Create a new folder for your skill:
```bash
mkdir -p ~/clawd/skills/hello-world
```
@@ -23,18 +23,18 @@ description: A simple skill that says hello.
---
# Hello World Skill
When the user asks for a greeting, use the `echo` tool to say "Hello from your custom skill!".
When the user asks for a greeting, use the `exec` tool to run `echo "Hello from your custom skill!"`.
```
### 3. Add Tools (Optional)
You can define custom tools in the frontmatter or instruct the agent to use existing system tools (like `bash` or `browser`).
You can define custom tools in the frontmatter or instruct the agent to use existing system tools (like `exec` or `web`).
### 4. Refresh Clawdbot
Ask your agent to "refresh skills" or restart the gateway. Clawdbot will discover the new directory and index the `SKILL.md`.
If the skills watcher is enabled (default), changes are picked up automatically. Otherwise restart the gateway or start a new session to refresh the skills snapshot.
## Best Practices
- **Be Concise**: Instruct the model on *what* to do, not how to be an AI.
- **Safety First**: If your skill uses `bash`, ensure the prompts don't allow arbitrary command injection from untrusted user input.
- **Safety First**: If your skill uses `exec`, ensure the prompts don't allow arbitrary command injection from untrusted user input.
- **Test Locally**: Use `clawdbot agent --message "use my new skill"` to test.
## Shared Skills

View File

@@ -137,10 +137,11 @@ export function resolveConfiguredModelRef(params: {
if (aliasMatch) return aliasMatch.ref;
// Default to anthropic if no provider is specified, but warn as this is deprecated.
const normalized = normalizeProviderModelId("anthropic", trimmed);
console.warn(
`[clawdbot] Model "${trimmed}" specified without provider. Falling back to "anthropic/${trimmed}". Please use "anthropic/${trimmed}" in your config.`,
`[clawdbot] Model "${trimmed}" specified without provider. Falling back to "anthropic/${normalized}". Please use "anthropic/${normalized}" in your config.`,
);
return { provider: "anthropic", model: trimmed };
return { provider: "anthropic", model: normalized };
}
const resolved = resolveModelRefFromString({

View File

@@ -133,6 +133,15 @@ describe("isHeartbeatContentEffectivelyEmpty", () => {
expect(isHeartbeatContentEffectivelyEmpty("# HEARTBEAT.md\n\n")).toBe(true);
});
it("returns true for empty list items", () => {
expect(isHeartbeatContentEffectivelyEmpty("- ")).toBe(true);
expect(isHeartbeatContentEffectivelyEmpty("- [ ]")).toBe(true);
expect(isHeartbeatContentEffectivelyEmpty("- [x]")).toBe(true);
expect(isHeartbeatContentEffectivelyEmpty("* [ ]")).toBe(true);
expect(isHeartbeatContentEffectivelyEmpty("+ [ ]")).toBe(true);
expect(isHeartbeatContentEffectivelyEmpty("# HEARTBEAT.md\n- [ ]")).toBe(true);
});
it("returns true for comments only", () => {
expect(isHeartbeatContentEffectivelyEmpty("# Header\n# Another comment")).toBe(true);
expect(isHeartbeatContentEffectivelyEmpty("## Subheader\n### Another")).toBe(true);