Skip to content

fix: PKCE removal, driver defaults, MiniMax stubs#4

Closed
AlexZander85 wants to merge 83 commits into
mainfrom
fix/driver-defaults-pkce
Closed

fix: PKCE removal, driver defaults, MiniMax stubs#4
AlexZander85 wants to merge 83 commits into
mainfrom
fix/driver-defaults-pkce

Conversation

@AlexZander85
Copy link
Copy Markdown
Owner

Summary

  • Remove unused generate_pkce / generate_state functions and their tests from oauth_providers.rs
  • Add 6 provider_defaults tests (codex, gemini, qwen, minimax, copilot, vertex-ai)
  • Add 2 shell-wrapper regression tests in subprocess_sandbox.rs
  • Clean MiniMax OAuth: replace dead Ok branches with minimal stub implementations + TODO comments (Rust requires exhaustive match)
  • Fix copilot driver: key_required=false, vertex-ai default port 8600

Changed files

  • crates/openfang-runtime/src/oauth_providers.rs - PKCE removal, doc comment cleanup
  • crates/openfang-runtime/src/drivers/mod.rs - copilot key_required, vertex-ai defaults, 6 provider_defaults tests
  • crates/openfang-runtime/src/subprocess_sandbox.rs - 2 shell-wrapper tests
  • crates/openfang-api/src/routes.rs - MiniMax stub implementations

Test plan

  • cargo build --workspace --lib - compiles clean
  • cargo test -p openfang-api -p openfang-runtime -p openfang-types - all 910+ tests pass
  • cargo clippy --workspace --all-targets -- -D warnings - zero warnings

Part of RightNow-AI#1030 OAuth providers review split (PR 2 of 3)

nldhuyen0047 and others added 30 commits March 30, 2026 17:00
- Add NOVITA_BASE_URL constant to model_catalog.rs
- Register novita provider in provider_defaults() with OpenAI-compatible endpoint
- Add novita to known_providers() list
- Add novita to detect_available_provider() auto-detection probe
- Document NOVITA_API_KEY in .env.example

Novita AI uses an OpenAI-compatible API at https://api.novita.ai/openai/v1
Default model: moonshotai/kimi-k2.5
…creation

- test_provider_defaults_novita: verify base_url, api_key_env, key_required
- test_provider_defaults_novita_ai_alias: verify "novita-ai" alias resolves
- test_novita_provider_with_env_key: driver creation succeeds with env key
- test_novita_provider_no_key_errors: driver creation fails without key

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
GHCR defaults new packages to private, so docker pull
ghcr.io/rightnow-ai/openfang:... returned 401 for unauthenticated
users despite the repo being public.

Two changes to the docker job in release.yml:

1. Add OCI labels to the build — links the package to the repo so
   GHCR associates it correctly, and is standard practice for
   container images.

2. After each push, call the GitHub Packages API (PATCH
   /orgs/RightNow-AI/packages/container/openfang) to set visibility
   to public. The workflow already holds packages: write, which is
   the required scope. This runs on every release tag so visibility
   cannot regress if the package is ever reset.

Fixes RightNow-AI#961
Since v0.5.4, native-tls uses features = ["vendored"], which compiles OpenSSL from source via openssl-sys. This requires perl for the OpenSSL Configure script, but perl was missing from the flake's buildInputs.

Mirrors the Dockerfile fix in RightNow-AI#952. Fixes RightNow-AI#894.
Built-in templates and the spawn wizard both hardcoded
provider = "groq" / model = "llama-3.3-70b-versatile" in the
manifest TOML sent to the API. The kernel's default_model overlay
only activates when provider/model are empty or "default", so
hardcoded values bypassed the user's configured default entirely.

Fixes RightNow-AI#967
When an LLM produces text alongside tool_use blocks (e.g., a chat
message followed by memory_store calls), the text was lost if the
final EndTurn iteration returned empty text. The empty-response guard
would activate and return "[Task completed — the agent executed tools
but did not produce a text summary.]" even though the agent DID
produce text in an earlier iteration.

This is a common pattern when agents are instructed to respond to
users AND persist state via memory_store in the same turn.

Fix: accumulate text content from all ToolUse iterations. When the
final EndTurn has empty text, use accumulated text as fallback before
triggering the empty-response guard.

Applied to both sync and streaming agent loop paths.
… entry

- Move Overview to first navigation item for better UX
- Consolidate `Chat` into `Agents` section
- Increase chevron and section title font sizes for improved readability
- Adjust section title padding for better visual spacing

Signed-off-by: 诺墨 <normal@normalcoder.com>
…ontrast

- Add `--text-on-accent` CSS variable (white) for text on accent backgrounds
- Replace hardcoded `var(--bg-primary)` with `--text-on-accent` across components
- Update dark theme surface, border, and text color tokens for better contrast
- Adjust dark mode surface colors (`#1F1D1C` → `#242221`) for improved depth
- Refine border and text-muted colors for better visual hierarchy

Signed-off-by: 诺墨 <normal@normalcoder.com>
…wser loading issues.

Signed-off-by: 诺墨 <normal@normalcoder.com>
…nt rendering

- Replace `&times;` close icons with SVG X icons across all modals and panels
- Replace `&#10003;` checkmarks with SVG check icons in setup checklist, step indicators, and success states
- Replace `&bull;` and `&middot;` separators with small SVG dot icons for better visual consistency
- Improve icon sizing, alignment, and stroke properties for crisp rendering

Signed-off-by: 诺墨 <normal@normalcoder.com>
- Add complete i18n framework with en.json and ru.json locale files
- Add i18n.js with language loading, detection, and fallback logic
- Localize chat.js: slash commands, Toast messages, welcome message
- Localize agents.js: personality presets, profile descriptions
- Localize wizard.js: step labels, channel options, suggestions, profiles
- Localize skills.js: 18 skill categories, uninstall confirm
- Localize sessions.js: delete session/key confirm dialogs

Provides full Russian translation for OpenFang UI as first non-English locale.
## Headline feature
- Multi-instance Hands via optional instance_name (customer ask + RightNow-AI#878).
  Web UI, CLI (--name / -n), API, kernel, registry all threaded. Two
  clip-youtube + clip-tiktok instances now coexist. Backward compatible
  when instance_name is omitted.

## Critical bug fixes
- RightNow-AI#919 [SECURITY] rm bypass closed. process_start tool now validates against
  exec_policy allowlist and rejects shell metacharacters in both command
  and args. Added 5 regression tests.
- RightNow-AI#1013 session_repair phase ordering — dedup now runs BEFORE synthetic
  result insertion, fixing Moonshot's non-unique tool_call_id format
  (function_name:index). Added regression test.
- RightNow-AI#1003 global [[fallback_providers]] now actually used at runtime.
  resolve_driver wraps primary in FallbackDriver with global fallback
  chain. Network errors escalate to fallback instead of infinite retry.
- RightNow-AI#937 Discord gateway heartbeat. Spawns interval task, tracks sequence,
  handles ACKs, detects zombie connections, force-closes on missing ACK.
  Credits @hello-world-bfree (PR RightNow-AI#938) for the diagnosis.
- RightNow-AI#935 System prompt leak in Web UI. get_agent_session now filters
  Role::System by default (?include_system=true for debug). Defense in
  depth client-side filter too.
- RightNow-AI#984 Custom hands persistence. install_from_path copies to
  ~/.openfang/hands/. Kernel loads them on startup.
- RightNow-AI#884 Workspace version bump 0.5.5 -> 0.5.7. Binaries now correctly
  report --version as 0.5.7 instead of stale 0.5.5.

## Cleanup
- rmcp 1.3 builder API adopted (credits @jefflower PR RightNow-AI#986) for
  StreamableHttpClientTransportConfig. Drops unused Arc import.

## Stats
- 22 files changed, all workspace tests passing (1800+)
- Live-tested with daemon: v0.5.7 reported, multi-instance hands
  verified end-to-end, Groq round-trip PONG confirmed
The Copilot LLM driver was broken - it expected users to provide a
GITHUB_TOKEN env var, but no standard token type (PAT, gh CLI token)
works with the Copilot token exchange endpoint.

Changes:
- Full rewrite of copilot.rs with OAuth device flow using Copilot's
  client ID (Iv1.b507a08c87ecfe98)
- Three-layer token chain: ghu_ (8h) -> Copilot API token (30min),
  with automatic caching and refresh
- Dynamic model fetching from Copilot API on daemon startup and on
  model_not_supported error
- Init wizard: TUI auth screen with device code display, live model
  picker after authentication
- set-key command: interactive device flow for github-copilot provider
- Doctor: detects Copilot auth via persisted token file
- Removed static Copilot model entries (now fetched dynamically)
- Simplified driver instantiation (no env vars needed)

Tested end-to-end with Copilot Enterprise: auth, token exchange,
43 models fetched, completions working with claude-opus-4.6-1m.

Closes RightNow-AI#1014

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Bug: in activate_hand(), kill_agent() is called on the existing agent
BEFORE the new agent is spawned. kill_agent() invokes
cron_scheduler.remove_agent_jobs() which deletes all cron jobs from memory
AND persists [] to cron_jobs.json. The reassign_agent_jobs() call further
down was meant to migrate jobs from old to new (per RightNow-AI#461), but it always
runs as a no-op because the jobs are already gone — the order of
operations defeats the fix.

Symptom: every daemon restart silently destroys cron jobs for hand-style
agents. cron_jobs.json is rewritten as []. /api/cron/jobs returns empty.
No error message.

Fix: snapshot the cron jobs into a local Vec BEFORE kill_agent (same
pattern as saved_triggers above), then re-add them under the new agent_id
AFTER spawn_agent_with_parent. Runtime state (next_run, last_run) is
reset so jobs get a fresh start. The existing reassign_agent_jobs()
block is kept as a defensive safety net but is now redundant in the
common path.

Verified with cargo check -p openfang-kernel --lib (clean compile, no
warnings).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…pilot proxy

The Copilot API proxy rejects conversations ending with an empty
assistant message as unsupported 'assistant message prefill' when
proxying Claude and Gemini models. GPT models are unaffected.

Strips trailing empty assistant messages (no content, no tool calls)
before sending the request. Applied in both complete() and stream()
paths.

Also reverts unused fixup_request method from copilot.rs since the
fix belongs in the OpenAI driver layer.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…stant

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The Copilot API proxy can sometimes deliver streaming tool call chunks
without a function name, resulting in empty-name tool calls stored in
conversation history. When replayed to the API, these cause
'tool call must have a tool call ID and function name' errors.

Skip malformed tool calls (empty ID or name) during streaming response
finalization and log a warning.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
jaberjaber23 and others added 29 commits April 10, 2026 19:13
…xt-response

fix: capture text from intermediate tool_use iterations
Fix: Safe char boundary handling for UTF-8 string slicing
…default-model

fix: new agents default to configured model instead of hardcoded groq
…s-style

fix(comms): align task and send modals to center
…free-response

fix: crypto provider, silent failure debug, Discord free_response_channels
fix(analytics): correct bar style attribute binding
fix(comms): OpenFangAPI.baseUrl is undefined
fix(chat): prevent duplicate message keys on first chat welcome message
fix(nix): add perl to buildInputs for openssl-sys vendored build
Bumps [lettre](https://github.com/lettre/lettre) from 0.11.19 to 0.11.20.
- [Release notes](https://github.com/lettre/lettre/releases)
- [Changelog](https://github.com/lettre/lettre/blob/master/CHANGELOG.md)
- [Commits](lettre/lettre@v0.11.19...v0.11.20)

---
updated-dependencies:
- dependency-name: lettre
  dependency-version: 0.11.20
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [prost](https://github.com/tokio-rs/prost) from 0.13.5 to 0.14.3.
- [Release notes](https://github.com/tokio-rs/prost/releases)
- [Changelog](https://github.com/tokio-rs/prost/blob/master/CHANGELOG.md)
- [Commits](tokio-rs/prost@v0.13.5...v0.14.3)

---
updated-dependencies:
- dependency-name: prost
  dependency-version: 0.14.3
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [cron](https://github.com/zslayton/cron) from 0.15.0 to 0.16.0.
- [Release notes](https://github.com/zslayton/cron/releases)
- [Commits](https://github.com/zslayton/cron/commits)

---
updated-dependencies:
- dependency-name: cron
  dependency-version: 0.16.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Add armv7-unknown-linux-gnueabihf target
…vice-flow

fix: rewrite Copilot driver with OAuth device flow authentication
…-i18n-translation

feat(i18n): add Russian localization and i18n framework
…cron-0.16.0

chore(deps): bump cron from 0.15.0 to 0.16.0
…ge-visibility

Set GHCR package visibility to public on every release
fix: Fix panic due to UTF-8 character boundary errors
…m-provider-support-with-token-auth

feat: Add AWS Bedrock LLM provider support with token auth
Refactor UI navigation and improve visual consistency with SVGs
- Replace SystemTime-based pseudo-random with OsRng
- generate_pkce() now uses rand::rngs::OsRng.fill_bytes()
- generate_state() now uses OsRng (128-bit entropy)
- Fix MiniMax stub with clearer error messages
- Add tests for uniqueness (CSPRNG verification)

Addresses security audit findings:
- CRITICAL: Weak PKCE code verifier generation
- CRITICAL: Weak state parameter generation
…docs

- OAuth /start endpoints now cost 100 tokens (prevents device code spam)
- OAuth /poll endpoints cost 1 token (normal polling)
- Clarified Qwen is file-based token import, not true OAuth flow
- Added rate limiter tests for OAuth endpoints
- Updated module docs to explain Qwen and MiniMax limitations
- Resolve merge conflicts in drivers/mod.rs, mcp.rs, index_body.html
- Add oauth_provider field to ProviderDefaults struct
- Fix clippy: &PathBuf -> &Path, unnecessary_cast, redundant_closure,
  collapsible_if, manual_contains, dead_code warnings
- Add missing novita/novita-ai provider defaults entry
- Fix huggingface env var: HF_API_KEY -> HF_TOKEN (match upstream)
- Remove orphaned i18n routes (not in this PR scope)
- Fix unused variable warnings in OAuth route handlers
- Apply cargo fmt
- Replace MiniMax dead-code Ok branches with minimal stub implementations + TODO comments
- Add State(_state) to minimax_oauth_poll for future token persistence
- Remove unused PKCE generate_pkce/generate_state functions and their tests
- Clean up doc comments (remove redundant blank lines, update module description)
- Fix copilot provider_defaults: key_required=false (uses OAuth, not API key)
- Add vertex-ai provider_defaults (GOOGLE_APPLICATION_CREDENTIALS)
- Add 4 OAuth provider_defaults tests (codex, gemini, qwen, minimax)
- Add copilot + vertex-ai provider_defaults tests
- Add 2 shell-wrapper regression tests in subprocess_sandbox
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.