1 Commits

Author SHA1 Message Date
dependabot[bot]
065eaeaa4e chore(deps): bump tonic from 0.13.1 to 0.14.2 in /llmx-rs
Bumps [tonic](https://github.com/hyperium/tonic) from 0.13.1 to 0.14.2.
- [Release notes](https://github.com/hyperium/tonic/releases)
- [Changelog](https://github.com/hyperium/tonic/blob/master/CHANGELOG.md)
- [Commits](https://github.com/hyperium/tonic/compare/v0.13.1...v0.14.2)

---
updated-dependencies:
- dependency-name: tonic
  dependency-version: 0.14.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-12 19:46:57 +00:00
14 changed files with 110 additions and 76 deletions

View File

@@ -27,6 +27,34 @@
"path": "llmx.exe" "path": "llmx.exe"
} }
} }
},
"llmx-responses-api-proxy": {
"platforms": {
"macos-aarch64": {
"regex": "^llmx-responses-api-proxy-aarch64-apple-darwin\\.zst$",
"path": "llmx-responses-api-proxy"
},
"macos-x86_64": {
"regex": "^llmx-responses-api-proxy-x86_64-apple-darwin\\.zst$",
"path": "llmx-responses-api-proxy"
},
"linux-x86_64": {
"regex": "^llmx-responses-api-proxy-x86_64-unknown-linux-musl\\.zst$",
"path": "llmx-responses-api-proxy"
},
"linux-aarch64": {
"regex": "^llmx-responses-api-proxy-aarch64-unknown-linux-musl\\.zst$",
"path": "llmx-responses-api-proxy"
},
"windows-x86_64": {
"regex": "^llmx-responses-api-proxy-x86_64-pc-windows-msvc\\.exe\\.zst$",
"path": "llmx-responses-api-proxy.exe"
},
"windows-aarch64": {
"regex": "^llmx-responses-api-proxy-aarch64-pc-windows-msvc\\.exe\\.zst$",
"path": "llmx-responses-api-proxy.exe"
}
}
} }
} }
} }

BIN
.github/llmx-cli-login.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 MiB

BIN
.github/llmx-cli-permissions.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 408 KiB

BIN
.github/llmx-cli-splash.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 MiB

View File

@@ -445,19 +445,7 @@ jobs:
run: | run: |
./scripts/stage_npm_packages.py \ ./scripts/stage_npm_packages.py \
--release-version "${{ steps.release_name.outputs.name }}" \ --release-version "${{ steps.release_name.outputs.name }}" \
--package llmx --package @valknar/llmx
# Delete any existing release to avoid conflicts with dotslash manifest file
- name: Delete existing release if present
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
if gh release view "${{ github.ref_name }}" --repo "${{ github.repository }}" >/dev/null 2>&1; then
echo "Deleting existing release ${{ github.ref_name }}"
gh release delete "${{ github.ref_name }}" --repo "${{ github.repository }}" --yes
else
echo "No existing release found for ${{ github.ref_name }}"
fi
- name: Create GitHub Release - name: Create GitHub Release
uses: softprops/action-gh-release@v2 uses: softprops/action-gh-release@v2
@@ -476,7 +464,9 @@ jobs:
tag: ${{ github.ref_name }} tag: ${{ github.ref_name }}
config: .github/dotslash-config.json config: .github/dotslash-config.json
# Publish to npm using authentication token # Publish to npm using OIDC authentication.
# July 31, 2025: https://github.blog/changelog/2025-07-31-npm-trusted-publishing-with-oidc-is-generally-available/
# npm docs: https://docs.npmjs.com/trusted-publishers
publish-npm: publish-npm:
# Publish to npm for stable releases and alpha pre-releases with numeric suffixes. # Publish to npm for stable releases and alpha pre-releases with numeric suffixes.
if: ${{ needs.release.outputs.should_publish_npm == 'true' }} if: ${{ needs.release.outputs.should_publish_npm == 'true' }}
@@ -484,6 +474,7 @@ jobs:
needs: release needs: release
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions: permissions:
id-token: write # Required for OIDC
contents: read contents: read
steps: steps:
@@ -492,6 +483,11 @@ jobs:
with: with:
node-version: 22 node-version: 22
registry-url: "https://registry.npmjs.org" registry-url: "https://registry.npmjs.org"
scope: "@valknar"
# Trusted publishing requires npm CLI version 11.5.1 or later.
- name: Update npm
run: npm install -g npm@latest
- name: Download npm tarballs from release - name: Download npm tarballs from release
env: env:
@@ -503,18 +499,15 @@ jobs:
mkdir -p dist/npm mkdir -p dist/npm
gh release download "$tag" \ gh release download "$tag" \
--repo "${GITHUB_REPOSITORY}" \ --repo "${GITHUB_REPOSITORY}" \
--pattern "llmx-npm-${version}.tgz" \ --pattern "valknar-llmx-npm-${version}.tgz" \
--dir dist/npm --dir dist/npm
# No NODE_AUTH_TOKEN needed because we use OIDC.
- name: Publish to npm - name: Publish to npm
env: env:
VERSION: ${{ needs.release.outputs.version }} VERSION: ${{ needs.release.outputs.version }}
NPM_TAG: ${{ needs.release.outputs.npm_tag }} NPM_TAG: ${{ needs.release.outputs.npm_tag }}
run: | run: |
# Write auth token to the .npmrc file that setup-node created
echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" >> ${NPM_CONFIG_USERCONFIG}
set -euo pipefail set -euo pipefail
tag_args=() tag_args=()
if [[ -n "${NPM_TAG}" ]]; then if [[ -n "${NPM_TAG}" ]]; then
@@ -522,7 +515,7 @@ jobs:
fi fi
tarballs=( tarballs=(
"llmx-npm-${VERSION}.tgz" "valknar-llmx-npm-${VERSION}.tgz"
) )
for tarball in "${tarballs[@]}"; do for tarball in "${tarballs[@]}"; do

View File

@@ -1,9 +1,13 @@
<p align="center"><code>npm i -g @valknarthing/llmx</code></p> <p align="center"><code>npm i -g @valknar/llmx</code><br />or <code>brew install --cask llmx</code></p>
<p align="center"><strong>LLMX CLI</strong> is a coding agent powered by LiteLLM that runs locally on your computer. <p align="center"><strong>LLMX CLI</strong> is a coding agent powered by LiteLLM that runs locally on your computer.
</br> </br>
</br>This project is a community fork with enhanced support for multiple LLM providers via LiteLLM. </br>This project is a community fork with enhanced support for multiple LLM providers via LiteLLM.
</br>Original project: <a href="https://github.com/openai/codex">github.com/openai/codex</a></p> </br>Original project: <a href="https://github.com/openai/llmx">github.com/openai/llmx</a></p>
<p align="center">
<img src="./.github/llmx-cli-splash.png" alt="LLMX CLI splash" width="80%" />
</p>
--- ---
@@ -11,10 +15,16 @@
### Installing and running LLMX CLI ### Installing and running LLMX CLI
Install globally with npm: Install globally with your preferred package manager. If you use npm:
```shell ```shell
npm install -g @valknarthing/llmx npm install -g @valknar/llmx
```
Alternatively, if you use Homebrew:
```shell
brew install --cask llmx
``` ```
Then simply run `llmx` to get started: Then simply run `llmx` to get started:
@@ -23,8 +33,10 @@ Then simply run `llmx` to get started:
llmx llmx
``` ```
If you're running into upgrade issues with Homebrew, see the [FAQ entry on brew upgrade llmx](./docs/faq.md#brew-upgrade-llmx-isnt-upgrading-me).
<details> <details>
<summary>You can also go to the <a href="https://github.com/valknarthing/llmx/releases/latest">latest GitHub Release</a> and download the appropriate binary for your platform.</summary> <summary>You can also go to the <a href="https://github.com/valknar/llmx/releases/latest">latest GitHub Release</a> and download the appropriate binary for your platform.</summary>
Each GitHub Release contains many executables, but in practice, you likely want one of these: Each GitHub Release contains many executables, but in practice, you likely want one of these:
@@ -84,7 +96,7 @@ LLMX CLI supports a rich set of configuration options, with preferences stored i
- [Auth methods](./docs/authentication.md#forcing-a-specific-auth-method-advanced) - [Auth methods](./docs/authentication.md#forcing-a-specific-auth-method-advanced)
- [Login on a "Headless" machine](./docs/authentication.md#connecting-on-a-headless-machine) - [Login on a "Headless" machine](./docs/authentication.md#connecting-on-a-headless-machine)
- **Automating LLMX** - **Automating LLMX**
- [GitHub Action](https://github.com/valknarthing/llmx-action) - [GitHub Action](https://github.com/valknar/llmx-action)
- [TypeScript SDK](./sdk/typescript/README.md) - [TypeScript SDK](./sdk/typescript/README.md)
- [Non-interactive mode (`llmx exec`)](./docs/exec.md) - [Non-interactive mode (`llmx exec`)](./docs/exec.md)
- [**Advanced**](./docs/advanced.md) - [**Advanced**](./docs/advanced.md)

View File

@@ -1,5 +1,5 @@
{ {
"name": "@valknarthing/llmx", "name": "@valknar/llmx",
"version": "0.1.0", "version": "0.1.0",
"license": "Apache-2.0", "license": "Apache-2.0",
"description": "LLMX CLI - Multi-provider coding agent powered by LiteLLM", "description": "LLMX CLI - Multi-provider coding agent powered by LiteLLM",
@@ -16,7 +16,7 @@
], ],
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git+https://github.com/valknarthing/llmx.git", "url": "git+https://github.com/valknar/llmx.git",
"directory": "llmx-cli" "directory": "llmx-cli"
} }
} }

View File

@@ -33,7 +33,7 @@ def parse_args() -> argparse.Namespace:
"--package", "--package",
choices=("llmx", "llmx-responses-api-proxy", "llmx-sdk"), choices=("llmx", "llmx-responses-api-proxy", "llmx-sdk"),
default="llmx", default="llmx",
help="Which npm package to stage (default: llmx).", help="Which npm package to stage (default: codex).",
) )
parser.add_argument( parser.add_argument(
"--version", "--version",

54
llmx-rs/Cargo.lock generated
View File

@@ -2227,7 +2227,7 @@ dependencies = [
"libc", "libc",
"percent-encoding", "percent-encoding",
"pin-project-lite", "pin-project-lite",
"socket2 0.6.0", "socket2",
"system-configuration", "system-configuration",
"tokio", "tokio",
"tower-service", "tower-service",
@@ -3330,7 +3330,7 @@ dependencies = [
"serde_json", "serde_json",
"strum_macros 0.27.2", "strum_macros 0.27.2",
"tokio", "tokio",
"tonic", "tonic 0.14.2",
"tracing", "tracing",
] ]
@@ -4222,7 +4222,7 @@ dependencies = [
"serde_json", "serde_json",
"thiserror 2.0.17", "thiserror 2.0.17",
"tokio", "tokio",
"tonic", "tonic 0.13.1",
"tracing", "tracing",
] ]
@@ -4238,7 +4238,7 @@ dependencies = [
"opentelemetry_sdk", "opentelemetry_sdk",
"prost", "prost",
"serde", "serde",
"tonic", "tonic 0.13.1",
] ]
[[package]] [[package]]
@@ -4710,7 +4710,7 @@ dependencies = [
"quinn-udp", "quinn-udp",
"rustc-hash 2.1.1", "rustc-hash 2.1.1",
"rustls", "rustls",
"socket2 0.6.0", "socket2",
"thiserror 2.0.17", "thiserror 2.0.17",
"tokio", "tokio",
"tracing", "tracing",
@@ -4747,7 +4747,7 @@ dependencies = [
"cfg_aliases 0.2.1", "cfg_aliases 0.2.1",
"libc", "libc",
"once_cell", "once_cell",
"socket2 0.6.0", "socket2",
"tracing", "tracing",
"windows-sys 0.60.2", "windows-sys 0.60.2",
] ]
@@ -5819,16 +5819,6 @@ version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c" checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c"
[[package]]
name = "socket2"
version = "0.5.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678"
dependencies = [
"libc",
"windows-sys 0.52.0",
]
[[package]] [[package]]
name = "socket2" name = "socket2"
version = "0.6.0" version = "0.6.0"
@@ -6374,7 +6364,7 @@ dependencies = [
"pin-project-lite", "pin-project-lite",
"signal-hook-registry", "signal-hook-registry",
"slab", "slab",
"socket2 0.6.0", "socket2",
"tokio-macros", "tokio-macros",
"windows-sys 0.59.0", "windows-sys 0.59.0",
] ]
@@ -6505,6 +6495,32 @@ name = "tonic"
version = "0.13.1" version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e581ba15a835f4d9ea06c55ab1bd4dce26fc53752c69a04aac00703bfb49ba9" checksum = "7e581ba15a835f4d9ea06c55ab1bd4dce26fc53752c69a04aac00703bfb49ba9"
dependencies = [
"async-trait",
"base64",
"bytes",
"http",
"http-body",
"http-body-util",
"hyper",
"hyper-timeout",
"hyper-util",
"percent-encoding",
"pin-project",
"prost",
"tokio",
"tokio-stream",
"tower",
"tower-layer",
"tower-service",
"tracing",
]
[[package]]
name = "tonic"
version = "0.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb7613188ce9f7df5bfe185db26c5814347d110db17920415cf2fbcad85e7203"
dependencies = [ dependencies = [
"async-trait", "async-trait",
"axum", "axum",
@@ -6519,8 +6535,8 @@ dependencies = [
"hyper-util", "hyper-util",
"percent-encoding", "percent-encoding",
"pin-project", "pin-project",
"prost", "socket2",
"socket2 0.5.10", "sync_wrapper",
"tokio", "tokio",
"tokio-stream", "tokio-stream",
"tower", "tower",

View File

@@ -190,7 +190,7 @@ tokio-test = "0.4"
tokio-util = "0.7.16" tokio-util = "0.7.16"
toml = "0.9.5" toml = "0.9.5"
toml_edit = "0.23.4" toml_edit = "0.23.4"
tonic = "0.13.1" tonic = "0.14.2"
tracing = "0.1.41" tracing = "0.1.41"
tracing-appender = "0.2.3" tracing-appender = "0.2.3"
tracing-subscriber = "0.3.20" tracing-subscriber = "0.3.20"

View File

@@ -2,6 +2,7 @@ use anyhow::Result;
use app_test_support::McpProcess; use app_test_support::McpProcess;
use app_test_support::to_response; use app_test_support::to_response;
use llmx_app_server_protocol::CancelLoginChatGptParams; use llmx_app_server_protocol::CancelLoginChatGptParams;
use llmx_app_server_protocol::CancelLoginChatGptResponse;
use llmx_app_server_protocol::GetAuthStatusParams; use llmx_app_server_protocol::GetAuthStatusParams;
use llmx_app_server_protocol::GetAuthStatusResponse; use llmx_app_server_protocol::GetAuthStatusResponse;
use llmx_app_server_protocol::JSONRPCError; use llmx_app_server_protocol::JSONRPCError;
@@ -109,35 +110,21 @@ async fn login_and_cancel_chatgpt() -> Result<()> {
login_id: login.login_id, login_id: login.login_id,
}) })
.await?; .await?;
let cancel_resp: JSONRPCResponse = timeout(
// The cancel might succeed or fail with "login id not found" if the login DEFAULT_READ_TIMEOUT,
// completed/cancelled already due to a race condition. Either outcome is acceptable.
// Use a timeout and allow either success or error response.
let cancel_result = timeout(
Duration::from_secs(5),
mcp.read_stream_until_response_message(RequestId::Integer(cancel_id)), mcp.read_stream_until_response_message(RequestId::Integer(cancel_id)),
) )
.await; .await??;
let _ok: CancelLoginChatGptResponse = to_response(cancel_resp)?;
match cancel_result {
Ok(Ok(_)) => {
// Successfully cancelled
eprintln!("cancel succeeded");
}
Ok(Err(_)) | Err(_) => {
// Cancel failed or timed out - acceptable in race condition
eprintln!("cancel failed or timed out (expected in race condition)");
}
}
// Optionally observe the completion notification; do not fail if it races. // Optionally observe the completion notification; do not fail if it races.
let maybe_note = timeout( let maybe_note = timeout(
Duration::from_secs(2), Duration::from_secs(2),
mcp.read_stream_until_notification_message("loginChatGptComplete"), mcp.read_stream_until_notification_message("llmx/event/login_chat_gpt_complete"),
) )
.await; .await;
if maybe_note.is_err() { if maybe_note.is_err() {
eprintln!("warning: did not observe loginChatGptComplete notification after cancel"); eprintln!("warning: did not observe login_chat_gpt_complete notification after cancel");
} }
Ok(()) Ok(())
} }

View File

@@ -1,5 +1,5 @@
{ {
"name": "@valknarthing/llmx-responses-api-proxy", "name": "@valknar/llmx-responses-api-proxy",
"version": "0.1.0", "version": "0.1.0",
"license": "Apache-2.0", "license": "Apache-2.0",
"bin": { "bin": {
@@ -15,7 +15,7 @@
], ],
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git+https://github.com/valknarthing/llmx.git", "url": "git+https://github.com/valknar/llmx.git",
"directory": "llmx-rs/responses-api-proxy/npm" "directory": "llmx-rs/responses-api-proxy/npm"
} }
} }

View File

@@ -148,9 +148,7 @@ def main() -> int:
print(f"should `git checkout {resolved_head_sha}`") print(f"should `git checkout {resolved_head_sha}`")
for package in packages: for package in packages:
# Sanitize package name for use in filesystem path (replace / with -) staging_dir = Path(tempfile.mkdtemp(prefix=f"npm-stage-{package}-", dir=runner_temp))
safe_package_name = package.replace("/", "-").replace("@", "")
staging_dir = Path(tempfile.mkdtemp(prefix=f"npm-stage-{safe_package_name}-", dir=runner_temp))
pack_output = output_dir / f"{package}-npm-{args.release_version}.tgz" pack_output = output_dir / f"{package}-npm-{args.release_version}.tgz"
cmd = [ cmd = [

View File

@@ -1,10 +1,10 @@
{ {
"name": "@valknarthing/llmx-sdk", "name": "@valknar/llmx-sdk",
"version": "0.1.0", "version": "0.1.0",
"description": "TypeScript SDK for LLMX - Multi-provider coding agent", "description": "TypeScript SDK for LLMX - Multi-provider coding agent",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git+https://github.com/valknarthing/llmx.git", "url": "git+https://github.com/valknar/llmx.git",
"directory": "sdk/typescript" "directory": "sdk/typescript"
}, },
"keywords": [ "keywords": [