mirror of
https://github.com/0xMassi/webclaw.git
synced 2026-07-24 07:31:01 +02:00
Merge pull request #93 from 0xMassi/release/0.6.16
release: 0.6.16 — Atlas Cloud opt-in provider + `--urls-file` single-row fix
This commit is contained in:
commit
50a17d27e5
6 changed files with 29 additions and 16 deletions
|
|
@ -3,10 +3,14 @@
|
||||||
All notable changes to webclaw are documented here.
|
All notable changes to webclaw are documented here.
|
||||||
Format follows [Keep a Changelog](https://keepachangelog.com/).
|
Format follows [Keep a Changelog](https://keepachangelog.com/).
|
||||||
|
|
||||||
## [Unreleased]
|
## [0.6.16] - 2026-07-22
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
- **`@webclaw/mcp` — zero-install MCP launcher.** `npx -y @webclaw/mcp` downloads the prebuilt `webclaw-mcp` binary once, verifies it against the release `SHA256SUMS`, caches it, and runs it as an MCP stdio server. This is now the canonical way to add webclaw to an MCP client (`{"command": "npx", "args": ["-y", "@webclaw/mcp"]}`) — no Rust build — and it makes the server introspectable in MCP registries (Glama, Smithery, the MCP registry). `create-webclaw` stays as the auto-detect installer.
|
- **`@webclaw/mcp` — zero-install MCP launcher.** `npx -y @webclaw/mcp` downloads the prebuilt `webclaw-mcp` binary once, verifies it against the release `SHA256SUMS`, caches it, and runs it as an MCP stdio server. This is now the canonical way to add webclaw to an MCP client (`{"command": "npx", "args": ["-y", "@webclaw/mcp"]}`) — no Rust build — and it makes the server introspectable in MCP registries (Glama, Smithery, the MCP registry). `create-webclaw` stays as the auto-detect installer.
|
||||||
|
- **Atlas Cloud provider in the LLM chain (opt-in).** Set `ATLASCLOUD_API_KEY` to add [Atlas Cloud](https://atlascloud.ai) as a provider for the LLM features (extraction, summarization). It's added at the end of the chain — Ollama → OpenAI → Gemini → Anthropic → Atlas Cloud — so it only runs when you configure it and never preempts an already-configured provider. Override the model with `ATLASCLOUD_MODEL` (default `qwen/qwen3.5-flash`) and the endpoint with `ATLASCLOUD_BASE_URL`.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- **`--urls-file` with a single URL now works.** A file containing exactly one URL (with no positional URL on the command line) was rejected with *"no input provided"*: it fell between the batch path, which skips single-entry files, and the single-URL path, which only reads positional arguments. A lone file URL is now treated exactly like `webclaw <url>`, so it works with stdout, `--output-dir`, `--brand`, `--diff-with`, `--crawl`, `--watch`, and the LLM paths.
|
||||||
|
|
||||||
## [0.6.15] - 2026-07-18
|
## [0.6.15] - 2026-07-18
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ Three binaries: `webclaw` (CLI), `webclaw-mcp` (MCP server), `webclaw-server` (R
|
||||||
- `url_security.rs` — SSRF guards + SSRF-safe redirect policy
|
- `url_security.rs` — SSRF guards + SSRF-safe redirect policy
|
||||||
|
|
||||||
### LLM Modules (`webclaw-llm`)
|
### LLM Modules (`webclaw-llm`)
|
||||||
- Provider chain (`chain.rs`): Ollama (local-first, always added; availability checked at call time) -> OpenAI -> Gemini -> Anthropic. Gemini sits ahead of Anthropic so Google Cloud credits are preferred; Anthropic is the last-resort fallback. Each provider lives in `providers/` (`ollama.rs`, `openai.rs`, `gemini.rs`, `anthropic.rs`).
|
- Provider chain (`chain.rs`): Ollama (local-first, always added; availability checked at call time) -> OpenAI -> Gemini -> Anthropic -> Atlas Cloud. Gemini sits ahead of Anthropic so Google Cloud credits are preferred; Anthropic is the last-resort fallback. Atlas Cloud is opt-in and added last — only when `ATLASCLOUD_API_KEY` is set — so it never preempts an already-configured provider (`ATLASCLOUD_MODEL` / `ATLASCLOUD_BASE_URL` override its model/endpoint). Each provider lives in `providers/` (`ollama.rs`, `openai.rs`, `gemini.rs`, `anthropic.rs`, `atlascloud.rs`).
|
||||||
- JSON schema extraction, prompt-based extraction, summarization
|
- JSON schema extraction, prompt-based extraction, summarization
|
||||||
|
|
||||||
### PDF Modules (`webclaw-pdf`)
|
### PDF Modules (`webclaw-pdf`)
|
||||||
|
|
|
||||||
14
Cargo.lock
generated
14
Cargo.lock
generated
|
|
@ -3221,7 +3221,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "webclaw-cli"
|
name = "webclaw-cli"
|
||||||
version = "0.6.15"
|
version = "0.6.16"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"dotenvy",
|
"dotenvy",
|
||||||
|
|
@ -3242,7 +3242,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "webclaw-core"
|
name = "webclaw-core"
|
||||||
version = "0.6.15"
|
version = "0.6.16"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ego-tree",
|
"ego-tree",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
|
|
@ -3260,7 +3260,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "webclaw-fetch"
|
name = "webclaw-fetch"
|
||||||
version = "0.6.15"
|
version = "0.6.16"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"bytes",
|
"bytes",
|
||||||
|
|
@ -3288,7 +3288,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "webclaw-llm"
|
name = "webclaw-llm"
|
||||||
version = "0.6.15"
|
version = "0.6.16"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
|
|
@ -3301,7 +3301,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "webclaw-mcp"
|
name = "webclaw-mcp"
|
||||||
version = "0.6.15"
|
version = "0.6.16"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dirs",
|
"dirs",
|
||||||
"dotenvy",
|
"dotenvy",
|
||||||
|
|
@ -3321,7 +3321,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "webclaw-pdf"
|
name = "webclaw-pdf"
|
||||||
version = "0.6.15"
|
version = "0.6.16"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"pdf-extract",
|
"pdf-extract",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
|
|
@ -3330,7 +3330,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "webclaw-server"
|
name = "webclaw-server"
|
||||||
version = "0.6.15"
|
version = "0.6.16"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"axum",
|
"axum",
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ resolver = "2"
|
||||||
members = ["crates/*"]
|
members = ["crates/*"]
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
version = "0.6.15"
|
version = "0.6.16"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
license = "AGPL-3.0"
|
license = "AGPL-3.0"
|
||||||
repository = "https://github.com/0xMassi/webclaw"
|
repository = "https://github.com/0xMassi/webclaw"
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/// Provider chain — tries providers in order until one succeeds.
|
/// Provider chain — tries providers in order until one succeeds.
|
||||||
/// Default order: Ollama (local, free) -> OpenAI -> Gemini -> Anthropic.
|
/// Default order: Ollama (local, free) -> OpenAI -> Gemini -> Anthropic -> Atlas Cloud (opt-in).
|
||||||
/// Only includes providers that are actually configured/available.
|
/// Only includes providers that are actually configured/available.
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use tracing::{debug, warn};
|
use tracing::{debug, warn};
|
||||||
|
|
@ -7,8 +7,8 @@ use tracing::{debug, warn};
|
||||||
use crate::error::LlmError;
|
use crate::error::LlmError;
|
||||||
use crate::provider::{CompletionRequest, LlmProvider};
|
use crate::provider::{CompletionRequest, LlmProvider};
|
||||||
use crate::providers::{
|
use crate::providers::{
|
||||||
anthropic::AnthropicProvider, gemini::GeminiProvider, ollama::OllamaProvider,
|
anthropic::AnthropicProvider, atlascloud::AtlasCloudProvider, gemini::GeminiProvider,
|
||||||
openai::OpenAiProvider,
|
ollama::OllamaProvider, openai::OpenAiProvider,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct ProviderChain {
|
pub struct ProviderChain {
|
||||||
|
|
@ -16,11 +16,13 @@ pub struct ProviderChain {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ProviderChain {
|
impl ProviderChain {
|
||||||
/// Build the default chain: Ollama -> OpenAI -> Gemini -> Anthropic.
|
/// Build the default chain: Ollama -> OpenAI -> Gemini -> Anthropic -> Atlas Cloud.
|
||||||
/// Ollama is always added (availability checked at call time).
|
/// Ollama is always added (availability checked at call time).
|
||||||
/// Cloud providers are only added if their API keys are configured.
|
/// Cloud providers are only added if their API keys are configured.
|
||||||
/// Gemini sits ahead of Anthropic so Google Cloud credits are preferred,
|
/// Gemini sits ahead of Anthropic so Google Cloud credits are preferred,
|
||||||
/// with Anthropic as the last-resort fallback.
|
/// with Anthropic as the last-resort fallback. Atlas Cloud is opt-in and
|
||||||
|
/// added last (only when `ATLASCLOUD_API_KEY` is set), so it never preempts
|
||||||
|
/// an already-configured provider.
|
||||||
pub async fn default() -> Self {
|
pub async fn default() -> Self {
|
||||||
let mut providers: Vec<Box<dyn LlmProvider>> = Vec::new();
|
let mut providers: Vec<Box<dyn LlmProvider>> = Vec::new();
|
||||||
|
|
||||||
|
|
@ -47,6 +49,11 @@ impl ProviderChain {
|
||||||
providers.push(Box::new(anthropic));
|
providers.push(Box::new(anthropic));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(atlas) = AtlasCloudProvider::new(None, None, None) {
|
||||||
|
debug!("atlascloud configured, adding to chain");
|
||||||
|
providers.push(Box::new(atlas));
|
||||||
|
}
|
||||||
|
|
||||||
Self { providers }
|
Self { providers }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,9 @@ impl AtlasCloudProvider {
|
||||||
let base_url = base_url
|
let base_url = base_url
|
||||||
.or_else(|| std::env::var("ATLASCLOUD_BASE_URL").ok())
|
.or_else(|| std::env::var("ATLASCLOUD_BASE_URL").ok())
|
||||||
.unwrap_or_else(|| "https://api.atlascloud.ai/v1".into());
|
.unwrap_or_else(|| "https://api.atlascloud.ai/v1".into());
|
||||||
let model = model.unwrap_or_else(|| "qwen/qwen3.5-flash".into());
|
let model = model
|
||||||
|
.or_else(|| std::env::var("ATLASCLOUD_MODEL").ok())
|
||||||
|
.unwrap_or_else(|| "qwen/qwen3.5-flash".into());
|
||||||
let inner = OpenAiProvider::new(Some(key), Some(base_url), Some(model))?;
|
let inner = OpenAiProvider::new(Some(key), Some(base_url), Some(model))?;
|
||||||
Some(Self { inner })
|
Some(Self { inner })
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue