Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
[package]
name = "wally"
# Must equal [product] version in versions.toml (scripts/ci/check-versions.py).
version = "0.8.15"
version = "0.8.16"
edition = "2021"
rust-version = "1.93"
license = "Apache-2.0"
Expand Down
6 changes: 3 additions & 3 deletions Formula/wally.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@
class Wally < Formula
desc "Run models on your machine or your RunAnywhere account"
homepage "https://github.com/RunanywhereAI/wally"
version "0.8.15"
version "0.8.16"
license "MIT"

# macOS arm64 ships the Swift MLX host
# (llama.cpp + ONNX + Sherpa + MLX). Linux is not in this cut.
on_macos do
on_arm do
url "https://github.com/RunanywhereAI/wally/releases/download/v0.8.15/wally-0.8.15-macos-arm64.tar.gz"
# Placeholder -- the v0.8.15 release has not published a wally-named asset
url "https://github.com/RunanywhereAI/wally/releases/download/v0.8.16/wally-0.8.16-macos-arm64.tar.gz"
# Placeholder -- the v0.8.16 release has not published a wally-named asset
# yet. scripts/release/update-tap.sh re-stamps this from the real release
# checksum; a stale value here fails brew install's own hash check
# rather than installing something unverified.
Expand Down
46 changes: 46 additions & 0 deletions src/account/console.rs
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,25 @@ pub struct CatalogPrice {
pub decisions_only: bool,
}

/// Chat models `GET /v1/models` omitted that this account is still entitled
/// to. The price catalog is per-account, so a gated id is here only when the
/// account holds the grant. Decision-only rows are not chat models.
pub fn gated_chat_ids(listed: &[String], prices: &[CatalogPrice]) -> Vec<String> {
Comment thread
cubic-dev-ai[bot] marked this conversation as resolved.
let mut ids = Vec::new();
for price in prices {
let id = price.id.as_str();
if price.decisions_only
|| id.is_empty()
|| listed.iter().any(|listed_id| listed_id == id)
|| ids.iter().any(|seen: &String| seen == id)
{
continue;
}
ids.push(price.id.clone());
}
ids
}
Comment thread
cubic-dev-ai[bot] marked this conversation as resolved.

#[derive(Debug, Clone, Default, PartialEq)]
pub struct DecisionsResult {
pub response: decisions::DecisionsResponse,
Expand Down Expand Up @@ -2267,6 +2286,33 @@ mod tests {
use std::collections::HashMap;
use std::time::Duration;

fn price(id: &str, decisions_only: bool) -> super::CatalogPrice {
super::CatalogPrice {
id: id.to_string(),
decisions_only,
..Default::default()
}
}

#[test]
fn gated_chat_ids_are_entitled_catalog_rows_missing_from_the_model_list() {
let listed = vec!["deepseek-v4.1-flash-1017".to_string()];
let prices = vec![
price("deepseek-v4.1-flash-1017", false),
price("deepseek-v4.1-flash-1017-uncensored", false),
price("deepseek-v4.1-flash-1017-uncensored", false),
price("eve", true),
price("", false),
];
assert_eq!(
super::gated_chat_ids(&listed, &prices),
vec!["deepseek-v4.1-flash-1017-uncensored".to_string()]
);
assert!(
super::gated_chat_ids(&listed, &[price("deepseek-v4.1-flash-1017", false)]).is_empty()
);
}

#[test]
fn console_tls_uses_the_platform_stack_and_trust_store() {
let tls = super::console_tls_config();
Expand Down
24 changes: 23 additions & 1 deletion src/account/model_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,11 +168,33 @@ pub fn refresh_model_cache_now(credentials: &Credentials) -> Result<(), bool> {
// Rate-limited or unreachable is a "try again", anything else a hard fail.
Comment thread
Siddhesh2377 marked this conversation as resolved.
return Err(result == super::IdentityResult::Unavailable);
}
let ids: Vec<String> = models
let mut ids: Vec<String> = models
.into_iter()
.filter(|model| !model.id.is_empty())
.map(|model| model.id)
.collect();
// Gated chat models are entitled on the price catalog and absent from
// /v1/models. Same 3s bound as `models list`, so a hung catalog cannot
// stall a launch for the transport's full timeout.
const CATALOG_TIMEOUT_MS: i32 = 3_000;
match console.fetch_catalog_within(
&credentials.console_url,
&credentials.access_token,
CATALOG_TIMEOUT_MS,
) {
(super::IdentityResult::Ok, prices, _) => {
ids.extend(super::gated_chat_ids(&ids, &prices));
}
// A failed catalog read must not drop grants the last good read
// cached. Ids that are not on the fresh public list are those grants.
_ => {
Comment thread
Siddhesh2377 marked this conversation as resolved.
for cached in cached_model_ids() {
Comment thread
Siddhesh2377 marked this conversation as resolved.
if !cached.is_empty() && !ids.iter().any(|id| id == &cached) {
ids.push(cached);
Comment thread
Siddhesh2377 marked this conversation as resolved.
}
}
}
}
// A failed write must not report success: the caller (and the launch
// path validating against the cache) would otherwise trust a catalog that
// was never actually persisted, and reject a valid model against the
Expand Down
3 changes: 1 addition & 2 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,12 +134,11 @@ pub fn configure_app(app: &mut App) {
"deepseek",
"prime-agent",
"command-code",
"shannon",
],
},
Section {
group: "Security tools",
names: &["deepsec", "vvah"],
names: &["shannon", "deepsec", "vvah"],
},
Section {
group: "Account",
Expand Down
10 changes: 5 additions & 5 deletions src/cli_formatter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1200,11 +1200,6 @@ mod tests {
"Open OpenCode with a local or cloud model",
"Coding tools",
),
leaf(
"shannon",
"Test your own apps with Shannon, an AI pentester",
"Coding tools",
),
leaf("hermes", "Open Hermes with a model", "Coding tools"),
leaf("openclaw", "Open OpenClaw with a model", "Coding tools"),
leaf(
Expand All @@ -1222,6 +1217,11 @@ mod tests {
"Open Command Code with a model",
"Coding tools",
),
leaf(
"shannon",
"Test your own apps with Shannon, an AI pentester",
"Security tools",
),
leaf(
"deepsec",
"Scan your own repos with DeepSec",
Expand Down
14 changes: 11 additions & 3 deletions src/commands/cmd_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,12 +254,20 @@ fn cloud_models() -> Result<CloudModels, String> {
decisions_only: false,
})
.collect();
// Decision-only models never appear above; the price catalog
// names them. A failed price lookup is not fatal: the rows just
// stay missing, exactly as before.
// The price catalog is this account's entitlements. Chat models
// it names that /v1/models left out are gated: shown only when
// this account holds the grant. Decision-only models never appear
// above. A failed price lookup is not fatal: those rows stay missing.
if let Ok(prices) = session.call(|client, url, token| {
client.fetch_catalog_within(url, token, CLOUD_LOOKUP_TIMEOUT_MS)
}) {
let listed: Vec<String> = rows.iter().map(|row| row.id.clone()).collect();
for id in crate::account::gated_chat_ids(&listed, &prices) {
rows.push(CloudRow {
id,
decisions_only: false,
});
}
for price in &prices {
if price.decisions_only
&& !price.id.is_empty()
Expand Down
15 changes: 7 additions & 8 deletions src/harness/catalog_models.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,15 +162,14 @@ pub fn account_models_with(
// (the same shape `primary_first` uses for a model it only knows by id).
// Decisions-only ids stay out: they are the one thing the catalogue names
// that is deliberately not a chat model.
for price in &prices {
if price.id.is_empty() || price.decisions_only || out.iter().any(|m| m.id == price.id) {
continue;
}
let listed: Vec<String> = out.iter().map(|model| model.id.clone()).collect();
for id in crate::account::gated_chat_ids(&listed, &prices) {
let price = prices.iter().find(|price| price.id == id);
out.push(CatalogModel {
id: price.id.clone(),
input_per_mtok: price.input_per_mtok,
output_per_mtok: price.output_per_mtok,
cached_input_per_mtok: price.cached_input_per_mtok,
id,
input_per_mtok: price.map(|price| price.input_per_mtok).unwrap_or(0),
output_per_mtok: price.map(|price| price.output_per_mtok).unwrap_or(0),
cached_input_per_mtok: price.map(|price| price.cached_input_per_mtok).unwrap_or(0),
..Default::default()
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ Coding tools:
codex Open Codex with a model
chatgpt Open ChatGPT's Codex with a model
opencode Open OpenCode with a local or cloud model
shannon Test your own apps with Shannon, an AI pentester
hermes Open Hermes with a model
openclaw Open OpenClaw with a model
deepseek Open DeepSeek Harness with a model
prime-agent Open Prime Agent with a model
command-code Open Command Code with a model

Security tools:
shannon Test your own apps with Shannon, an AI pentester
deepsec Scan your own repos with DeepSec
vvah Scan your own repos with VVAH

Expand Down
2 changes: 1 addition & 1 deletion tests/golden/expected/alt_help__-h.stdout
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ Coding tools:
codex Open Codex with a model
chatgpt Open ChatGPT's Codex with a model
opencode Open OpenCode with a local or cloud model
shannon Test your own apps with Shannon, an AI pentester
hermes Open Hermes with a model
openclaw Open OpenClaw with a model
deepseek Open DeepSeek Harness with a model
prime-agent Open Prime Agent with a model
command-code Open Command Code with a model

Security tools:
shannon Test your own apps with Shannon, an AI pentester
deepsec Scan your own repos with DeepSec
vvah Scan your own repos with VVAH

Expand Down
2 changes: 1 addition & 1 deletion tests/golden/expected/alt_help__help.stdout
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ Coding tools:
codex Open Codex with a model
chatgpt Open ChatGPT's Codex with a model
opencode Open OpenCode with a local or cloud model
shannon Test your own apps with Shannon, an AI pentester
hermes Open Hermes with a model
openclaw Open OpenClaw with a model
deepseek Open DeepSeek Harness with a model
prime-agent Open Prime Agent with a model
command-code Open Command Code with a model

Security tools:
shannon Test your own apps with Shannon, an AI pentester
deepsec Scan your own repos with DeepSec
vvah Scan your own repos with VVAH

Expand Down
2 changes: 1 addition & 1 deletion tests/golden/expected/alt_help__help__nope.stdout
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ Coding tools:
codex Open Codex with a model
chatgpt Open ChatGPT's Codex with a model
opencode Open OpenCode with a local or cloud model
shannon Test your own apps with Shannon, an AI pentester
hermes Open Hermes with a model
openclaw Open OpenClaw with a model
deepseek Open DeepSeek Harness with a model
prime-agent Open Prime Agent with a model
command-code Open Command Code with a model

Security tools:
shannon Test your own apps with Shannon, an AI pentester
deepsec Scan your own repos with DeepSec
vvah Scan your own repos with VVAH

Expand Down
2 changes: 1 addition & 1 deletion tests/golden/expected/help__ROOT.stdout
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ Coding tools:
codex Open Codex with a model
chatgpt Open ChatGPT's Codex with a model
opencode Open OpenCode with a local or cloud model
shannon Test your own apps with Shannon, an AI pentester
hermes Open Hermes with a model
openclaw Open OpenClaw with a model
deepseek Open DeepSeek Harness with a model
prime-agent Open Prime Agent with a model
command-code Open Command Code with a model

Security tools:
shannon Test your own apps with Shannon, an AI pentester
deepsec Scan your own repos with DeepSec
vvah Scan your own repos with VVAH

Expand Down
2 changes: 1 addition & 1 deletion tests/golden/expected/help__help.stdout
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ Coding tools:
codex Open Codex with a model
chatgpt Open ChatGPT's Codex with a model
opencode Open OpenCode with a local or cloud model
shannon Test your own apps with Shannon, an AI pentester
hermes Open Hermes with a model
openclaw Open OpenClaw with a model
deepseek Open DeepSeek Harness with a model
prime-agent Open Prime Agent with a model
command-code Open Command Code with a model

Security tools:
shannon Test your own apps with Shannon, an AI pentester
deepsec Scan your own repos with DeepSec
vvah Scan your own repos with VVAH

Expand Down
2 changes: 1 addition & 1 deletion tests/golden/expected/parse__--bogus.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@ Coding tools:
codex Open Codex with a model
chatgpt Open ChatGPT's Codex with a model
opencode Open OpenCode with a local or cloud model
shannon Test your own apps with Shannon, an AI pentester
hermes Open Hermes with a model
openclaw Open OpenClaw with a model
deepseek Open DeepSeek Harness with a model
prime-agent Open Prime Agent with a model
command-code Open Command Code with a model

Security tools:
shannon Test your own apps with Shannon, an AI pentester
deepsec Scan your own repos with DeepSec
vvah Scan your own repos with VVAH

Expand Down
2 changes: 1 addition & 1 deletion tests/golden/expected/parse__-U__--json.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@ Coding tools:
codex Open Codex with a model
chatgpt Open ChatGPT's Codex with a model
opencode Open OpenCode with a local or cloud model
shannon Test your own apps with Shannon, an AI pentester
hermes Open Hermes with a model
openclaw Open OpenClaw with a model
deepseek Open DeepSeek Harness with a model
prime-agent Open Prime Agent with a model
command-code Open Command Code with a model

Security tools:
shannon Test your own apps with Shannon, an AI pentester
deepsec Scan your own repos with DeepSec
vvah Scan your own repos with VVAH

Expand Down
2 changes: 1 addition & 1 deletion tests/golden/expected/parse__-u__-v.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@ Coding tools:
codex Open Codex with a model
chatgpt Open ChatGPT's Codex with a model
opencode Open OpenCode with a local or cloud model
shannon Test your own apps with Shannon, an AI pentester
hermes Open Hermes with a model
openclaw Open OpenClaw with a model
deepseek Open DeepSeek Harness with a model
prime-agent Open Prime Agent with a model
command-code Open Command Code with a model

Security tools:
shannon Test your own apps with Shannon, an AI pentester
deepsec Scan your own repos with DeepSec
vvah Scan your own repos with VVAH

Expand Down
2 changes: 1 addition & 1 deletion tests/golden/expected/parse__-z.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@ Coding tools:
codex Open Codex with a model
chatgpt Open ChatGPT's Codex with a model
opencode Open OpenCode with a local or cloud model
shannon Test your own apps with Shannon, an AI pentester
hermes Open Hermes with a model
openclaw Open OpenClaw with a model
deepseek Open DeepSeek Harness with a model
prime-agent Open Prime Agent with a model
command-code Open Command Code with a model

Security tools:
shannon Test your own apps with Shannon, an AI pentester
deepsec Scan your own repos with DeepSec
vvah Scan your own repos with VVAH

Expand Down
2 changes: 1 addition & 1 deletion tests/golden/expected/unknown__auth.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@ Coding tools:
codex Open Codex with a model
chatgpt Open ChatGPT's Codex with a model
opencode Open OpenCode with a local or cloud model
shannon Test your own apps with Shannon, an AI pentester
hermes Open Hermes with a model
openclaw Open OpenClaw with a model
deepseek Open DeepSeek Harness with a model
prime-agent Open Prime Agent with a model
command-code Open Command Code with a model

Security tools:
shannon Test your own apps with Shannon, an AI pentester
deepsec Scan your own repos with DeepSec
vvah Scan your own repos with VVAH

Expand Down
Loading
Loading