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
56 changes: 6 additions & 50 deletions .github/workflows/pr-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,11 @@ permissions:
contents: read

jobs:
# Deliberately not a dependency of native-arm64. These finish in about a minute; making the
# macOS job wait for them added that minute to every run's critical path and gated the suite
# that actually covers the shipping app behind the one that does not.
shared-tests:
name: Shared JavaScript and Rust tests
name: Shared JavaScript tests
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803
Expand All @@ -28,25 +31,13 @@ jobs:
with:
node-version: 24.19.0
cache: npm
- uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c
with:
toolchain: 1.98.0
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6
with:
workspaces: './src-tauri -> target'
- name: Install test dependencies
run: |
npm ci --ignore-scripts --no-audit --no-fund
sudo apt-get update
sudo apt-get install -y libwebkit2gtk-4.1-dev libssl-dev
run: npm ci --ignore-scripts --no-audit --no-fund
- name: JavaScript tests
run: npm test
- name: Rust tests
run: cargo test --locked --lib --manifest-path src-tauri/Cargo.toml

native-arm64:
name: Native tests and unsigned universal package
needs: shared-tests
runs-on: macos-26
env:
DEVELOPER_DIR: /Applications/Xcode_26.6.app/Contents/Developer
Expand Down Expand Up @@ -110,36 +101,6 @@ jobs:
cp "$codex" native/Vendor/test-tools/codex
cp "$claude" native/Vendor/test-tools/claude
chmod 755 native/Vendor/test-tools/codex native/Vendor/test-tools/claude
# Fail quickly on the large-reader regression, then still run both complete suites.
# Its separate result bundle is never included in the full-suite membership counts.
- name: Preflight the twelve-thousand-message reader
shell: bash
run: |
set -euo pipefail
result="$RUNNER_TEMP/CCBuddyLongTranscriptPreflight.xcresult"
summary="$RUNNER_TEMP/CCBuddyLongTranscriptPreflight-summary.json"
tests="$RUNNER_TEMP/CCBuddyLongTranscriptPreflight-tests.json"
test ! -e "$result"
xcodebuild test \
-project native/CCBuddy.xcodeproj \
-scheme CCBuddy \
-configuration Debug \
-destination 'platform=macOS,arch=arm64' \
-only-testing:CCBuddyUITests/NativeSearchExperienceUITests/testTwelveThousandMessageTranscriptCanFindItsTailAndReturnToSmallSession \
-parallel-testing-enabled NO \
-maximum-parallel-testing-workers 1 \
-resultBundlePath "$result" \
ARCHS=arm64 ONLY_ACTIVE_ARCH=YES CODE_SIGN_IDENTITY=- \
ENABLE_HARDENED_RUNTIME=NO \
CCBUD_PRODUCT_BUNDLE_IDENTIFIER="dev.ccbud.gateway.preflight.${GITHUB_RUN_ID}.${GITHUB_RUN_ATTEMPT}"
xcrun xcresulttool get test-results summary --path "$result" --compact > "$summary"
xcrun xcresulttool get test-results tests --path "$result" --compact > "$tests"
jq -e '.result == "Passed" and .totalTestCount == 1 and .passedTests == 1
and .failedTests == 0 and .skippedTests == 0 and .expectedFailures == 0' "$summary"
jq -e '[.. | objects | select(.nodeType == "Test Case")] as $cases
| ($cases | length) == 1
and $cases[0].nodeIdentifier == "NativeSearchExperienceUITests/testTwelveThousandMessageTranscriptCanFindItsTailAndReturnToSmallSession()"
and $cases[0].result == "Passed"' "$tests"
- name: Run native unit tests with all real E2Es
shell: bash
env:
Expand Down Expand Up @@ -242,7 +203,7 @@ jobs:
set -euo pipefail
evidence="$RUNNER_TEMP/ccbud-test-evidence"
mkdir -p "$evidence"
for suite in CCBuddyLongTranscriptPreflight CCBuddyTests CCBuddyUITests; do
for suite in CCBuddyTests CCBuddyUITests; do
result="$RUNNER_TEMP/$suite.xcresult"
if [[ -d "$result" ]]; then
xcrun xcresulttool get test-results summary --path "$result" \
Expand All @@ -251,11 +212,6 @@ jobs:
--compact > "$evidence/$suite-tests.json"
fi
done
if [[ -d "$RUNNER_TEMP/CCBuddyLongTranscriptPreflight.xcresult" ]]; then
xcrun xcresulttool export attachments \
--path "$RUNNER_TEMP/CCBuddyLongTranscriptPreflight.xcresult" \
--output-path "$evidence/preflight-attachments"
fi
if [[ -d "$RUNNER_TEMP/CCBuddyUITests.xcresult" ]]; then
xcrun xcresulttool export attachments \
--path "$RUNNER_TEMP/CCBuddyUITests.xcresult" \
Expand Down
30 changes: 3 additions & 27 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -121,30 +121,15 @@ jobs:
RELEASE_COMMIT: ${{ needs.prepare.outputs.commit }}
RELEASE_SOURCE_SHA: ${{ needs.prepare.outputs.source_sha }}
run: node scripts/prepare-main-release.js --verify "$RELEASE_COMMIT"
- uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c
with:
toolchain: 1.98.0
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6
with:
workspaces: './src-tauri -> target'
- name: Verify synchronized release version
run: node scripts/release-version.js check "${{ steps.tag.outputs.version }}"
- name: Run legacy updater validator suites
- name: Validate the published updater manifest
shell: bash
run: |
set -euo pipefail
node native/Scripts/tests/verify-legacy-tauri-manifest.test.js
node --test native/Scripts/tests/generate-latest-json.test.js
bash native/Scripts/tests/verify-legacy-tauri-update-contract.test.sh
run: node --test native/Scripts/tests/generate-latest-json.test.js
- name: Install shared test dependencies
run: |
npm ci --ignore-scripts --no-audit --no-fund
sudo apt-get update
sudo apt-get install -y libwebkit2gtk-4.1-dev libssl-dev
run: npm ci --ignore-scripts --no-audit --no-fund
- name: JavaScript tests
run: npm test
- name: Rust tests
run: cargo test --locked --lib --manifest-path src-tauri/Cargo.toml

native-test:
name: Native tests and unsigned packaged checks
Expand Down Expand Up @@ -498,15 +483,6 @@ jobs:

cleanup_credentials
trap - EXIT INT TERM HUP
- name: Validate the legacy Tauri 1.3.9 updater input contract
shell: bash
run: |
set -euo pipefail
native/Scripts/verify-legacy-tauri-update-contract.sh \
"$RUNNER_TEMP/ccbud-native/artifacts/CC.Buddy_universal.app.tar.gz" \
"$RUNNER_TEMP/ccbud-native/artifacts/CC.Buddy_universal.app.tar.gz.sig" \
"$RUNNER_TEMP/ccbud-native/artifacts/latest.json" \
"${{ needs.verify.outputs.version }}" "${{ github.repository }}"
- name: Upload immutable release inputs
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f
with:
Expand Down
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,12 @@ The redesign follows a macOS 27 design direction using available macOS 26 APIs b

## Included: local API gateway

As a companion feature, the gateway accepts **Anthropic Messages**, **OpenAI Chat Completions**, and **OpenAI Responses** on both client and provider sides, passing through matching protocols or translating between them. It configures **Claude Code and Codex** with one click; other compatible clients can use the local endpoint manually. Around seventy provider presets ship built in, alongside custom and plugin-backed providers, with switching and model mapping.
As a companion feature, the gateway accepts **Anthropic Messages**, **OpenAI Chat Completions**, and **OpenAI Responses** from clients, whichever of those three you configure as upstreams.

- **Configure all three** and every client is handed to the upstream that already speaks its protocol, untouched.
- **Configure one or two** and a client speaking a protocol you did have still passes through, while one speaking a protocol you do not is converted for you.

Either way, if an upstream fails the rest of your queue takes over in order. It configures **Claude Code and Codex** with one click; other compatible clients can use the local endpoint manually. Around seventy provider presets ship built in, alongside custom and plugin-backed providers, with switching and model mapping. A provider that publishes `/v1/models` or `/models` can fill in its own model bindings from the editor; one that does not leaves the control disabled rather than failing.

The gateway binds to `127.0.0.1`; inference requests still go to the provider you select.

Expand Down
7 changes: 6 additions & 1 deletion README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,12 @@ CLI 会话记录 ──▶ CC Buddy ──▶ 浏览 · 搜索 · 追踪 · 导

## 附带能力:本地 API 网关

作为附带能力,网关的客户端和上游均支持 **Anthropic Messages、OpenAI Chat Completions 和 OpenAI Responses**:协议相同则直通,不同则相互转换。它能一键配置 **Claude Code 和 Codex**;其他兼容客户端可手动使用本地端点。内置约七十个服务商预设,也支持自定义与插件服务,均可切换并映射模型。
作为附带能力,网关始终接受客户端发来的 **Anthropic Messages、OpenAI Chat Completions 和 OpenAI Responses**,而上游由你在这三种协议中自行选配。

- **三种都配**:每个客户端都会被交给协议相同的那个上游,原样直通,不做任何转换。
- **只配一种或两种**:协议已配置的客户端照样直通;协议未配置的客户端由网关完成协议转换后再发出。

两种情况下,若某个上游失败,队列中的其余上游都会按顺序接管。它能一键配置 **Claude Code 和 Codex**;其他兼容客户端可手动使用本地端点。内置约七十个服务商预设,也支持自定义与插件服务,均可切换并映射模型。若服务商提供 `/v1/models` 或 `/models`,可在编辑器中一键拉取并自动建立模型绑定;没有该接口时按钮会置灰而不是报错。

网关只监听 `127.0.0.1`;推理请求仍会发送给所选服务商。

Expand Down
Loading