mirror of
https://github.com/codewhale-hq/Codewhale.git
synced 2026-11-12 15:54:18 -10:00
Compare commits
1
Commits
ci/cw-8149
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8aa7707d04 |
No files matched your search
@@ -11,7 +11,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- **Non-ASCII file names:** `/diff`, the `@git` and `@diff` mentions and the Runtime API workspace diff now show paths with Chinese, emoji and other non-ASCII characters as written instead of as quoted octal escapes, and the turn context no longer lists the workspace root as an empty "Active paths" entry. Thanks [@luochen211](https://github.com/luochen211) (PR 7317).
|
||||
- **Session names after a crash, and keep-forever snapshot retention:** a session name saved right after a crash that cut off the previous session-index line is no longer lost, because the new entry now starts on its own line; and a very large `[snapshots] max_age_days` (such as `9223372036854775807` for "keep forever") no longer wraps around and deletes every undo snapshot at session start. Thanks [@luochen211](https://github.com/luochen211) (PR 7316).
|
||||
- **Blank environment variables:** exporting a variable empty (for example `CODEWHALE_MODEL=` from a compose `${VAR:-}` template) no longer hides its legacy alias. `DEEPSEEK_MODEL`, `DEEPSEEK_BASE_URL`, `KIMI_BASE_URL`, `DEEPSEEK_FORCE_HTTP1`, `DEEPSEEK_STREAM_OPEN_TIMEOUT_SECS` and the other provider alias variables now apply as they do when the primary is unset. Thanks [@luochen211](https://github.com/luochen211) (PR 7315).
|
||||
- **Qwen Code as an external agent:** Codewhale now finds an installed Qwen Code CLI (`qwen`, 0.6.1 or newer) and can run it as a session over ACP with `qwen --acp`. `GET /v1/agents/external` lists it, an older install is reported as needing `npm i -g @qwen-code/qwen-code@latest`, and sign-in stays inside Qwen Code (`/auth`). Thanks [@MannXo](https://github.com/MannXo) (PR 7293).
|
||||
- **MCP and language servers that send requests mid-call:** a tool call no longer fails with "neither a result nor an error" when an MCP server sends a `ping` or other request that reuses the call's id while the call is running, and a language server's `workspace/configuration` or similar request no longer ends a pending LSP request. Codewhale now answers `ping`, answers other server requests with "Method not found" (it never advertised them), keeps waiting for the real reply, and a refused answer over Streamable HTTP no longer drops the connection to legacy SSE. Thanks [@luochen211](https://github.com/luochen211) (PR 7319).
|
||||
- **Qwen Code as an external agent:** Codewhale now finds an installed Qwen Code CLI (`qwen`, 0.6.1 or newer) and can run it as a session over ACP with `qwen --acp`. `GET /v1/agents/external` lists it, an older install is reported as needing `npm i -g @qwen-code/qwen-code@latest`, and sign-in stays inside Qwen Code (`/auth`). Thanks [@MannXo](https://github.com/MannXo) (#7293).
|
||||
- **README and contributor credit:** the repository front page now opens the way the website does: the line "The model can be anyone's. The agent should be yours.", one sentence on what Codewhale is, the install command and one picture, with reference detail moved into the linked guides; the 18 translated READMEs follow the same structure and say they are machine-drafted. The contributor wall and the website now count the same 433 people (407 GitHub accounts and the commit authors whose email is not linked to an account), where the website had counted accounts only. `DEPENDENCY_SECURITY.md` moved into `docs/dependency-maintenance.md`, and `.github/SUPPORT.md` says where to ask for help.
|
||||
|
||||
@@ -11,7 +11,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- **Non-ASCII file names:** `/diff`, the `@git` and `@diff` mentions and the Runtime API workspace diff now show paths with Chinese, emoji and other non-ASCII characters as written instead of as quoted octal escapes, and the turn context no longer lists the workspace root as an empty "Active paths" entry. Thanks [@luochen211](https://github.com/luochen211) (PR 7317).
|
||||
- **Session names after a crash, and keep-forever snapshot retention:** a session name saved right after a crash that cut off the previous session-index line is no longer lost, because the new entry now starts on its own line; and a very large `[snapshots] max_age_days` (such as `9223372036854775807` for "keep forever") no longer wraps around and deletes every undo snapshot at session start. Thanks [@luochen211](https://github.com/luochen211) (PR 7316).
|
||||
- **Blank environment variables:** exporting a variable empty (for example `CODEWHALE_MODEL=` from a compose `${VAR:-}` template) no longer hides its legacy alias. `DEEPSEEK_MODEL`, `DEEPSEEK_BASE_URL`, `KIMI_BASE_URL`, `DEEPSEEK_FORCE_HTTP1`, `DEEPSEEK_STREAM_OPEN_TIMEOUT_SECS` and the other provider alias variables now apply as they do when the primary is unset. Thanks [@luochen211](https://github.com/luochen211) (PR 7315).
|
||||
- **Qwen Code as an external agent:** Codewhale now finds an installed Qwen Code CLI (`qwen`, 0.6.1 or newer) and can run it as a session over ACP with `qwen --acp`. `GET /v1/agents/external` lists it, an older install is reported as needing `npm i -g @qwen-code/qwen-code@latest`, and sign-in stays inside Qwen Code (`/auth`). Thanks [@MannXo](https://github.com/MannXo) (PR 7293).
|
||||
- **MCP and language servers that send requests mid-call:** a tool call no longer fails with "neither a result nor an error" when an MCP server sends a `ping` or other request that reuses the call's id while the call is running, and a language server's `workspace/configuration` or similar request no longer ends a pending LSP request. Codewhale now answers `ping`, answers other server requests with "Method not found" (it never advertised them), keeps waiting for the real reply, and a refused answer over Streamable HTTP no longer drops the connection to legacy SSE. Thanks [@luochen211](https://github.com/luochen211) (PR 7319).
|
||||
- **Qwen Code as an external agent:** Codewhale now finds an installed Qwen Code CLI (`qwen`, 0.6.1 or newer) and can run it as a session over ACP with `qwen --acp`. `GET /v1/agents/external` lists it, an older install is reported as needing `npm i -g @qwen-code/qwen-code@latest`, and sign-in stays inside Qwen Code (`/auth`). Thanks [@MannXo](https://github.com/MannXo) (#7293).
|
||||
- **README and contributor credit:** the repository front page now opens the way the website does: the line "The model can be anyone's. The agent should be yours.", one sentence on what Codewhale is, the install command and one picture, with reference detail moved into the linked guides; the 18 translated READMEs follow the same structure and say they are machine-drafted. The contributor wall and the website now count the same 433 people (407 GitHub accounts and the commit authors whose email is not linked to an account), where the website had counted accounts only. `DEPENDENCY_SECURITY.md` moved into `docs/dependency-maintenance.md`, and `.github/SUPPORT.md` says where to ask for help.
|
||||
|
||||
@@ -119,22 +119,8 @@ impl ProviderOffer {
|
||||
}
|
||||
|
||||
pub(crate) fn render(&self, locale: Locale, area: Rect, buf: &mut Buffer) -> Rect {
|
||||
self.render_if(crate::tui::orca_offer::available(locale), locale, area, buf)
|
||||
}
|
||||
|
||||
fn render_if(&self, available: bool, locale: Locale, area: Rect, buf: &mut Buffer) -> Rect {
|
||||
self.clear();
|
||||
if area.height < 4 || area.width < 20 || !available {
|
||||
return area;
|
||||
}
|
||||
let disclosure = wrap_to_width(
|
||||
&tr(locale, MessageId::OrcaRouterOfferDisclosure),
|
||||
usize::from(area.width),
|
||||
);
|
||||
let rows = u16::try_from(disclosure.len())
|
||||
.unwrap_or(u16::MAX)
|
||||
.saturating_add(1);
|
||||
if rows > area.height.saturating_sub(3) {
|
||||
if area.height < 4 || area.width < 20 || !crate::tui::orca_offer::available(locale) {
|
||||
return area;
|
||||
}
|
||||
let chord = crate::tui::shell_key_routing::display_chord(
|
||||
@@ -157,51 +143,10 @@ impl ProviderOffer {
|
||||
Style::default().fg(palette::WHALE_ACTION).underlined()
|
||||
})
|
||||
.render(row, buf);
|
||||
for (index, line) in disclosure.into_iter().enumerate() {
|
||||
let y = area.y + 1 + u16::try_from(index).unwrap_or(0);
|
||||
Paragraph::new(line)
|
||||
.style(Style::default().fg(palette::TEXT_MUTED))
|
||||
.render(Rect::new(area.x, y, area.width, 1), buf);
|
||||
}
|
||||
Rect::new(area.x, area.y + rows, area.width, area.height - rows)
|
||||
Rect::new(area.x, area.y + 1, area.width, area.height - 1)
|
||||
}
|
||||
}
|
||||
|
||||
fn wrap_to_width(text: &str, width: usize) -> Vec<String> {
|
||||
use unicode_width::UnicodeWidthChar;
|
||||
let width = width.max(1);
|
||||
let mut lines = Vec::new();
|
||||
let mut line = String::new();
|
||||
let mut line_width = 0;
|
||||
let mut last_space: Option<usize> = None;
|
||||
for ch in text.chars() {
|
||||
let w = ch.width().unwrap_or(0);
|
||||
if line_width + w > width {
|
||||
if let Some(at) = last_space {
|
||||
let rest = line.split_off(at);
|
||||
lines.push(line.trim_end().to_owned());
|
||||
line = rest.trim_start().to_owned();
|
||||
} else {
|
||||
lines.push(std::mem::take(&mut line));
|
||||
}
|
||||
line_width = unicode_width::UnicodeWidthStr::width(line.as_str());
|
||||
last_space = None;
|
||||
}
|
||||
if ch == ' ' {
|
||||
if line.is_empty() {
|
||||
continue;
|
||||
}
|
||||
last_space = Some(line.len());
|
||||
}
|
||||
line.push(ch);
|
||||
line_width += w;
|
||||
}
|
||||
if !line.is_empty() {
|
||||
lines.push(line);
|
||||
}
|
||||
lines
|
||||
}
|
||||
|
||||
const DS4_PROVIDER_ID: &str = "ds4";
|
||||
const LM_STUDIO_PROVIDER_ID: &str = "lm_studio";
|
||||
/// Rows a PageUp/PageDown travels in the provider lists. Both views are
|
||||
@@ -5945,66 +5890,6 @@ mod tests {
|
||||
.join("\n")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn featured_offer_row_is_followed_by_its_disclosure_in_every_locale_and_width() {
|
||||
for locale in Locale::shipped_complete() {
|
||||
let disclosure = tr(*locale, MessageId::OrcaRouterOfferDisclosure).into_owned();
|
||||
let label = tr(*locale, MessageId::OrcaRouterOfferRecommended).into_owned();
|
||||
for width in [100u16, 56, 48, 30] {
|
||||
let area = Rect::new(0, 0, width, 24);
|
||||
let mut buf = Buffer::empty(area);
|
||||
let offer = ProviderOffer::default();
|
||||
let rest = offer.render_if(true, *locale, area, &mut buf);
|
||||
let lines: Vec<String> = (0..24)
|
||||
.map(|y| {
|
||||
(0..width)
|
||||
.map(|x| buf[(x, y)].symbol())
|
||||
.collect::<String>()
|
||||
.trim_end()
|
||||
.to_owned()
|
||||
})
|
||||
.collect();
|
||||
assert!(
|
||||
lines[0].starts_with(&label),
|
||||
"{} {width}: {:?}",
|
||||
locale.tag(),
|
||||
lines[0]
|
||||
);
|
||||
let shown = lines[1..usize::from(rest.y)].concat();
|
||||
let squash = |text: &str| text.split_whitespace().collect::<String>();
|
||||
assert_eq!(
|
||||
squash(&shown),
|
||||
squash(&disclosure),
|
||||
"{} {width}",
|
||||
locale.tag()
|
||||
);
|
||||
assert!(
|
||||
lines[usize::from(rest.y)..].iter().all(String::is_empty),
|
||||
"{} {width}: list area overprinted",
|
||||
locale.tag()
|
||||
);
|
||||
for line in &lines {
|
||||
assert!(
|
||||
codewhale_tui_kit::ui_text::text_display_width(line) <= usize::from(width)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn featured_offer_shows_neither_row_nor_disclosure_when_unavailable() {
|
||||
let area = Rect::new(0, 0, 100, 24);
|
||||
let mut buf = Buffer::empty(area);
|
||||
let offer = ProviderOffer::default();
|
||||
assert_eq!(offer.render(Locale::ZhHans, area, &mut buf), area);
|
||||
assert_eq!(offer.render_if(false, Locale::En, area, &mut buf), area);
|
||||
assert!(
|
||||
(0..24).all(|y| (0..100).all(|x| buf[(x, y)].symbol() == " ")),
|
||||
"nothing may be drawn"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn failed_live_catalog_refresh_names_the_working_fallback() {
|
||||
assert_eq!(
|
||||
|
||||
@@ -35,7 +35,6 @@ export const RELEASE_CONTRIBUTORS: string[] = [
|
||||
"@luochen211",
|
||||
"@gannp",
|
||||
"@Felixkw12",
|
||||
"@MannXo",
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -43,7 +42,7 @@ export const RELEASE_CONTRIBUTORS: string[] = [
|
||||
* one. scripts/check-contributor-credit.py requires them here now; the release
|
||||
* cut moves them into RELEASE_CONTRIBUTORS with that release's changelog block.
|
||||
*/
|
||||
export const UNRELEASED_CONTRIBUTORS: string[] = ["@luochen211", "@Lstarsky0", "@SamhandsomeLee", "@gaord"];
|
||||
export const UNRELEASED_CONTRIBUTORS: string[] = ["@luochen211", "@Lstarsky0", "@SamhandsomeLee", "@gaord", "@MannXo"];
|
||||
|
||||
/**
|
||||
* Contributors who helped with reports, reproductions, and verification.
|
||||
|
||||
Reference in new issue
Block a user