Skip to content

Expose adaptive context APIs for Swift LLM#512

Open
shubhamsinnh wants to merge 3 commits into
RunanywhereAI:mainfrom
shubhamsinnh:issue-500-adaptive-context
Open

Expose adaptive context APIs for Swift LLM#512
shubhamsinnh wants to merge 3 commits into
RunanywhereAI:mainfrom
shubhamsinnh:issue-500-adaptive-context

Conversation

@shubhamsinnh

@shubhamsinnh shubhamsinnh commented Jun 22, 2026

Copy link
Copy Markdown

Description

Exposes adaptive-context LLM operations through the component and lifecycle-owned C ABI, then adds matching Swift public APIs so callers can reuse the model loaded through the existing RunAnywhere.loadModel flow.

Changes include:

  • component wrappers for inject, append, generate-from-context, and clear
  • lifecycle-owned C ABI helpers for the Swift/public path
  • Swift RunAnywhere.injectSystemPrompt, appendContext, generateFromContext, and clearContext
  • matching vendored headers and Apple symbol exports
  • review fixes preserving component default options and native backend error details

The public Swift path remains lifecycle-owned, avoiding a second model/service handle and its associated memory cost.

Fixes #500

Type of Change

  • Bug fix
  • New feature
  • Documentation update
  • Refactoring

Testing

  • Lint passes locally
  • Added/updated tests for changes

Validation performed:

  • git diff --check
  • focused declaration/definition/export symbol audit for all eight new C symbols
  • verified llama.cpp and MetalRT generate-from-context paths continue from existing context/cache
  • fork CI run: https://github.com/shubhamsinnh/runanywhere-sdks/actions/runs/28582734898
    • swift-spm: passed
    • ios-device: passed
    • macos-debug: passed
    • Linux, Android, WASM, and validation lanes: passed
  • macos-release failed before this PR's code while compiling committed generated protobuf headers against Homebrew protobuf 35.1; macos-debug passed in the same matrix
  • freshness audit against current main:
    • lifecycle/public adaptive-context symbols remain absent from main
    • underlying service operations remain present
    • synthetic three-way merge reports no conflicts
    • GitHub reports the PR mergeable

Platform-Specific Testing (check all that apply)

Swift SDK / iOS Sample:

  • Tested on iPhone (Simulator or Device)
  • Tested on iPad / Tablet
  • Tested on Mac (macOS target)

Kotlin SDK / Android Sample:

  • Tested on Android Phone (Emulator or Device)
  • Tested on Android Tablet

Flutter SDK / Flutter Sample:

  • Tested on iOS
  • Tested on Android

React Native SDK / React Native Sample:

  • Tested on iOS
  • Tested on Android

Playground:

  • Tested on target platform
  • Verified no regressions in existing Playground projects

Web SDK / Web Sample:

  • Tested in Chrome (Desktop)
  • Tested in Firefox
  • Tested in Safari
  • WASM backends load (LlamaCpp + ONNX)
  • OPFS storage persistence verified (survives page refresh)
  • Settings persistence verified (localStorage)

Labels

SDKs:

  • Swift SDK
  • Kotlin SDK
  • Flutter SDK
  • React Native SDK
  • Web SDK
  • Commons

Sample Apps:

  • iOS Sample
  • Android Sample
  • Flutter Sample
  • React Native Sample
  • Web Sample

Checklist

  • Code follows project style guidelines
  • Self-review completed
  • Documentation updated (public APIs and C ABI contracts include documentation)

Screenshots

Not applicable; this PR adds SDK APIs without changing UI.

Summary by CodeRabbit

  • New Features
    • Added an adaptive-context workflow for LLM text generation: inject a system prompt, append additional context incrementally, generate using the accumulated context, and clear the adaptive context.
    • Exposed the new workflow through the SDK’s public APIs and Swift helpers, including lifecycle-managed calls and protobuf-based request/response support.
  • Bug Fixes
    • Improved resilience when no LLM service is ready by returning consistent “not supported/not available” results for context operations instead of failing unexpectedly.

@coderabbitai

coderabbitai Bot commented Jun 22, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

No new commits to review since the last review.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f4164852-414c-4ab0-a857-136b9f5dc87e

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds adaptive context APIs across the C, C++, and Swift layers, including new component wrappers, lifecycle/proto entry points, exported symbols, Swift bridge methods, and public RunAnywhere static helpers.

Changes

LLM Adaptive Context API

Layer / File(s) Summary
C API contracts
sdk/runanywhere-commons/include/rac/features/llm/rac_llm_component.h, sdk/runanywhere-commons/include/rac/features/llm/rac_llm_service.h, sdk/runanywhere-swift/Sources/RunAnywhere/CRACommons/include/rac_llm_component.h, sdk/runanywhere-swift/Sources/RunAnywhere/CRACommons/include/rac_llm_service.h
Declares component-level adaptive context functions and lifecycle/proto adaptive context functions in both header trees.
C++ component and proto implementation
sdk/runanywhere-commons/src/features/llm/llm_module.cpp
Adds component wrappers plus lifecycle/proto entry points for adaptive context handling, including request parsing and protobuf result serialization.
Symbol exports
sdk/runanywhere-commons/exports/RACommons.exports
Adds the new adaptive context symbols to the exported symbols list.
Swift bridge
sdk/runanywhere-swift/Sources/RunAnywhere/Foundation/Bridge/Extensions/CppBridge+LLM.swift
Adds the native ABI wrapper, CppBridge.LLM methods, and shared native status validation.
Public RunAnywhere API
sdk/runanywhere-swift/Sources/RunAnywhere/Public/Extensions/LLM/RunAnywhere+TextGeneration.swift
Exposes four static RunAnywhere methods that forward to the bridge after initialization and service readiness checks.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

Suggested labels: ios-sdk

Suggested reviewers: shubhammalhotra28

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 52.17% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately summarizes the main change: exposing adaptive context APIs for Swift LLM.
Description check ✅ Passed The description matches the template well and includes change summary, type, testing, labels, checklist, and screenshots.
Linked Issues check ✅ Passed The PR implements the component-layer adaptive-context wrappers requested by issue #500 and exposes them to Swift as intended.
Out of Scope Changes check ✅ Passed The changes stay focused on adaptive-context C ABI, Swift bridging, headers, and exports needed for the requested feature.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix is ON, but it could not run because the branch was deleted or merged before autofix could start.

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 369d02c. Configure here.

Comment thread sdk/runanywhere-commons/src/features/llm/llm_module.cpp Outdated
@shubhamsinnh

Copy link
Copy Markdown
Author

Could a maintainer please approve the GitHub Actions run for this fork PR when you get a chance? I’m contributing from a Windows environment, so I can’t run the macOS/iOS Swift checks locally. I’ve included the local static checks I was able to run in the PR description.

@shubhamsinnh shubhamsinnh marked this pull request as ready for review June 27, 2026 17:28

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@sdk/runanywhere-swift/Sources/RunAnywhere/Foundation/Bridge/Extensions/CppBridge`+LLM.swift:
- Around line 145-152: The error handling in throwIfFailed currently converts
all non-success statuses into a generic SDKException and drops the native
backend detail. Update CppBridge+LLM.throwIfFailed to include
rac_error_message(status) in the thrown message, especially when status is
RAC_ERROR_NOT_SUPPORTED or RAC_ERROR_FEATURE_NOT_AVAILABLE, so callers can
distinguish unsupported-backend failures from other processing errors.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 357d08be-b462-415a-9b02-74bd7babe36e

📥 Commits

Reviewing files that changed from the base of the PR and between c272a1f and 369d02c.

📒 Files selected for processing (8)
  • sdk/runanywhere-commons/exports/RACommons.exports
  • sdk/runanywhere-commons/include/rac/features/llm/rac_llm_component.h
  • sdk/runanywhere-commons/include/rac/features/llm/rac_llm_service.h
  • sdk/runanywhere-commons/src/features/llm/llm_module.cpp
  • sdk/runanywhere-swift/Sources/RunAnywhere/CRACommons/include/rac_llm_component.h
  • sdk/runanywhere-swift/Sources/RunAnywhere/CRACommons/include/rac_llm_service.h
  • sdk/runanywhere-swift/Sources/RunAnywhere/Foundation/Bridge/Extensions/CppBridge+LLM.swift
  • sdk/runanywhere-swift/Sources/RunAnywhere/Public/Extensions/LLM/RunAnywhere+TextGeneration.swift

@shubhamsinnh

Copy link
Copy Markdown
Author

Validation update after addressing the review feedback:

The only failed lane was macos-release. Its log fails while compiling committed generated protobuf headers against Homebrew protobuf 35.1 (incompatible version of Protobuf C++ headers/runtime), before reaching the adaptive-context changes. macos-debug passed in the same matrix, so this appears to be baseline/toolchain drift unrelated to this PR.

Copy link
Copy Markdown
Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown
✅ Action performed

Full review finished.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
sdk/runanywhere-commons/src/features/llm/llm_module.cpp (1)

2153-2194: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider consolidating the near-identical lifecycle wrapper boilerplate.

rac_llm_inject_system_prompt_lifecycle, rac_llm_append_context_lifecycle, and rac_llm_clear_context_lifecycle all repeat the same shape: validate → #if !RAC_HAVE_PROTOBUF guard → acquire_lifecycle_llm → ternary dispatch on a vtable op → release_lifecycle_llm → return. A small helper (e.g., templated on the vtable member pointer, or a lambda-based wrapper) would collapse these into a few lines and reduce future copy/paste risk when more adaptive-context ops are added.

As per coding guidelines, "Focus on SIMPLICITY and follow Clean SOLID principles when writing code with emphasis on reusability, clean architecture style, and clear separation of concerns" for sdk/runanywhere-commons/**/*.{cpp,h,hpp,c}.

♻️ Illustrative consolidation sketch
+namespace {
+template <typename Op, typename... Args>
+rac_result_t call_lifecycle_op(Op op, Args&&... args) {
+#if !defined(RAC_HAVE_PROTOBUF)
+    return RAC_ERROR_FEATURE_NOT_AVAILABLE;
+#else
+    rac::llm::LifecycleLlmRef ref;
+    rac_result_t rc = rac::llm::acquire_lifecycle_llm(&ref);
+    if (rc != RAC_SUCCESS) return rc;
+    rc = (ref.ops && (ref.ops->*op)) ? (ref.ops->*op)(ref.impl, std::forward<Args>(args)...)
+                                     : RAC_ERROR_NOT_SUPPORTED;
+    rac::llm::release_lifecycle_llm(&ref);
+    return rc;
+#endif
+}
+}  // namespace
+
 rac_result_t rac_llm_inject_system_prompt_lifecycle(const char* prompt) {
-    if (!prompt) {
-        return RAC_ERROR_INVALID_ARGUMENT;
-    }
-#if !defined(RAC_HAVE_PROTOBUF)
-    return RAC_ERROR_FEATURE_NOT_AVAILABLE;
-#else
-    rac::llm::LifecycleLlmRef ref;
-    rac_result_t rc = rac::llm::acquire_lifecycle_llm(&ref);
-    if (rc != RAC_SUCCESS) {
-        return rc;
-    }
-
-    rc = (ref.ops && ref.ops->inject_system_prompt)
-             ? ref.ops->inject_system_prompt(ref.impl, prompt)
-             : RAC_ERROR_NOT_SUPPORTED;
-    rac::llm::release_lifecycle_llm(&ref);
-    return rc;
-#endif
+    if (!prompt) return RAC_ERROR_INVALID_ARGUMENT;
+    return call_lifecycle_op(&rac_llm_ops_t::inject_system_prompt, prompt);
 }

Also applies to: 2282-2298

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@sdk/runanywhere-commons/src/features/llm/llm_module.cpp` around lines 2153 -
2194, The lifecycle adaptive-context wrappers are duplicating the same
validate/acquire/dispatch/release pattern across
rac_llm_inject_system_prompt_lifecycle, rac_llm_append_context_lifecycle, and
rac_llm_clear_context_lifecycle. Refactor this into a small shared helper inside
llm_module.cpp, ideally one that takes the relevant vtable op (or a lambda) and
handles the RAC_HAVE_PROTOBUF guard, rac::llm::acquire_lifecycle_llm, null-op
fallback to RAC_ERROR_NOT_SUPPORTED, and rac::llm::release_lifecycle_llm
consistently. Keep the individual public wrappers as thin calls into that helper
so future adaptive-context lifecycle ops can be added without copy/paste.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@sdk/runanywhere-commons/src/features/llm/llm_module.cpp`:
- Around line 2153-2194: The lifecycle adaptive-context wrappers are duplicating
the same validate/acquire/dispatch/release pattern across
rac_llm_inject_system_prompt_lifecycle, rac_llm_append_context_lifecycle, and
rac_llm_clear_context_lifecycle. Refactor this into a small shared helper inside
llm_module.cpp, ideally one that takes the relevant vtable op (or a lambda) and
handles the RAC_HAVE_PROTOBUF guard, rac::llm::acquire_lifecycle_llm, null-op
fallback to RAC_ERROR_NOT_SUPPORTED, and rac::llm::release_lifecycle_llm
consistently. Keep the individual public wrappers as thin calls into that helper
so future adaptive-context lifecycle ops can be added without copy/paste.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: bac05259-0d09-4190-97f8-fdea89942a8a

📥 Commits

Reviewing files that changed from the base of the PR and between c272a1f and ad51147.

📒 Files selected for processing (8)
  • sdk/runanywhere-commons/exports/RACommons.exports
  • sdk/runanywhere-commons/include/rac/features/llm/rac_llm_component.h
  • sdk/runanywhere-commons/include/rac/features/llm/rac_llm_service.h
  • sdk/runanywhere-commons/src/features/llm/llm_module.cpp
  • sdk/runanywhere-swift/Sources/RunAnywhere/CRACommons/include/rac_llm_component.h
  • sdk/runanywhere-swift/Sources/RunAnywhere/CRACommons/include/rac_llm_service.h
  • sdk/runanywhere-swift/Sources/RunAnywhere/Foundation/Bridge/Extensions/CppBridge+LLM.swift
  • sdk/runanywhere-swift/Sources/RunAnywhere/Public/Extensions/LLM/RunAnywhere+TextGeneration.swift

Copy link
Copy Markdown
Author

@coderabbitai The full review still reports 52.17% docstring coverage after commit ad51147 documented the eight new C++ adaptive-context definitions and the Swift native-status helper. Please identify the exact functions you still count as undocumented so we can address only concrete gaps.

@coderabbitai

coderabbitai Bot commented Jul 3, 2026

Copy link
Copy Markdown
🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail
REPO="RunanywhereAI/runanywhere-sdks"
PR=512

# Get PR head ref info
gh pr view $PR --repo $REPO --json headRefName,headRepositoryOwner,headRepository -q '.'

# Fetch the branch to inspect files
gh pr diff $PR --repo $REPO > /tmp/pr512.diff
wc -l /tmp/pr512.diff

Length of output: 699


🏁 Script executed:

#!/bin/bash
set -euo pipefail
# Check for doc comments preceding the new functions in the diff
grep -n "rac_llm_component_inject_system_prompt\|rac_llm_component_append_context\|rac_llm_component_generate_from_context\|rac_llm_component_clear_context\|rac_llm_inject_system_prompt_lifecycle\|rac_llm_append_context_lifecycle\|rac_llm_generate_from_context_proto\|rac_llm_clear_context_lifecycle\|injectSystemPrompt\|appendContext\|generateFromContext\|clearContext\|throwIfFailed" -B5 /tmp/pr512.diff | head -400

Length of output: 869


🏁 Script executed:

#!/bin/bash
set -euo pipefail
REPO="RunanywhereAI/runanywhere-sdks"
PR=512

gh pr diff $PR --repo $REPO > /tmp/pr512.diff
wc -l /tmp/pr512.diff
echo "---- llm_module.cpp new functions context ----"
grep -n "^+.*rac_llm_component_inject_system_prompt\|^+.*rac_llm_component_append_context\|^+.*rac_llm_component_generate_from_context\|^+.*rac_llm_component_clear_context\|^+.*rac_llm_inject_system_prompt_lifecycle\|^+.*rac_llm_append_context_lifecycle\|^+.*rac_llm_generate_from_context_proto\|^+.*rac_llm_clear_context_lifecycle" /tmp/pr512.diff

echo "---- Swift new methods context ----"
grep -n "^+.*func injectSystemPrompt\|^+.*func appendContext\|^+.*func generateFromContext\|^+.*func clearContext\|^+.*func throwIfFailed" /tmp/pr512.diff

Length of output: 4206


🏁 Script executed:

#!/bin/bash
set -euo pipefail
# Inspect doc comments directly above each function definition in the diff
sed -n '160,260p' /tmp/pr512.diff
echo "======="
sed -n '380,430p' /tmp/pr512.diff
echo "======="
sed -n '555,650p' /tmp/pr512.diff

Length of output: 10603


🏁 Script executed:

#!/bin/bash
set -euo pipefail
sed -n '260,310p' /tmp/pr512.diff
echo "===RunAnywhere+TextGeneration rest==="
sed -n '640,690p' /tmp/pr512.diff

Length of output: 4058


All eight new C++ adaptive-context definitions and the four Swift native-status/public methods I can see in this diff do carry doc comments (/** ... */ or ///), so I can't reproduce an undocumented gap among the new functions listed in the PR summary from this diff alone. That 52.17% figure is most likely a repo-wide docstring-coverage metric (e.g., from a tool configured against the whole codebase or the whole file), not a per-PR-diff score — so it can include long-standing pre-existing functions in the same files (e.g., rac_llm_component.h, rac_llm_service.h, llm_module.cpp) that were never documented, unrelated to this PR's adaptive-context additions.

A few things worth verifying on your end:

  1. Check the specific review comment/report from the docstring-coverage check for the exact file(s) and line numbers it flags — that will list the precise "undocumented" symbols. If the tool is a repo-level scan rather than diff-scoped, it will surface pre-existing gaps rather than anything from your new code.
  2. Confirm which files the 52.17% is computed over — if it's the whole llm_module.cpp/rac_llm_component.h/rac_llm_service.h, older/unrelated functions in those files could be dragging the percentage down even though your eight new functions and the Swift helper are documented.

If you can point me to the exact CodeRabbit review comment/report containing that 52.17% figure (or its comment ID/permalink), I can cross-reference it directly against the current diff and give you a concrete list of symbols it's still counting as undocumented, rather than guessing at the source of the metric.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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.

feat(LLM): expose adaptive-context APIs through component layer wrappers

1 participant