Skip to content

fix: improve local WASM fallback installs and soften Ollama model listing#1167

Open
JZKK720 wants to merge 11 commits intonearai:stagingfrom
JZKK720:setup-env.test-improvements
Open

fix: improve local WASM fallback installs and soften Ollama model listing#1167
JZKK720 wants to merge 11 commits intonearai:stagingfrom
JZKK720:setup-env.test-improvements

Conversation

@JZKK720
Copy link
Contributor

@JZKK720 JZKK720 commented Mar 14, 2026

Summary

  • Fix local WASM extension/channel installs when release artifacts are missing by allowing source-build fallback to work from the Docker app container.
  • Make tarball extraction accept crate-named bundle entries in addition to extension-id names, which fixes installs for bundles like telegram_tool.wasm and similar variants.
  • Soften Ollama model discovery so list_models() falls back to the configured model when /api/tags is unavailable or malformed instead of failing callers.
  • Add Docker networking guidance for host-based local model providers and align the WhatsApp channel lockfile with its crate version.

Change Type

  • Bug fix
  • New feature
  • Refactor
  • Documentation
  • CI/Infrastructure
  • Security
  • Dependencies

Linked Issue

None

Validation

  • cargo fmt
  • cargo clippy --all --benches --tests --examples --all-features
  • Relevant tests pass: cargo test list_models_falls_back_to_configured_model_on_request_failure --lib
  • Manual testing:
    • Rebuilt and restarted the local Docker stack
    • Verified Telegram bot connectivity after network/VPN recovery
    • Verified local gateway installs succeed for web-search, telegram-mtproto, whatsapp, and discord

Security Impact

Low. This change does not expand secret scope or sandbox permissions. It keeps extension fallback local to mounted source/build directories and changes Ollama model listing to best-effort behavior against the already configured Ollama base URL.

Database Impact

None

Blast Radius

Touches the local Docker development path, gateway extension install flow, registry tarball extraction, and Ollama-backed model listing. If this regresses, likely symptoms are failed local extension installs, missing capability extraction from bundles, or incomplete model lists for Ollama-backed providers.

Rollback Plan

Revert the branch commits that introduced this behavior:

  • b57f62b (fix: soften Ollama model listing fallback)
  • 2fa27a6 (Fix local WASM extension fallback installs)
  • 2e3ca8d (docs: update .env.example with Docker networking guidance)

If rollback is needed quickly, reverting those three commits restores the pre-change runtime and docs behavior without requiring schema or data rollback.


Review track: C

JZKK720 added 4 commits March 12, 2026 14:27
- Add host.docker.internal patterns for Database (PostgreSQL), Ollama, and LM Studio
- Improve configuration hints for users running local LLM providers on host machine while using Docker containers
- Benefit: Cross-platform guide for accessing host services from Docker without code changes
- No functional changes, documentation/configuration only
Copilot AI review requested due to automatic review settings March 14, 2026 11:18
@github-actions github-actions bot added scope: llm LLM integration scope: extensions Extension management size: L 200-499 changed lines risk: medium Business logic, config, or moderate-risk modules contributor: regular 2-5 merged PRs labels Mar 14, 2026
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request primarily enhances the robustness of local development and extension management. It addresses issues with WASM extension installations, making them more resilient to missing artifacts and flexible in handling different naming conventions within tarball bundles. Additionally, it improves the reliability of Ollama model discovery by implementing a fallback mechanism, and provides clearer Docker networking instructions for local model providers. These changes collectively aim to streamline the development workflow and prevent common setup pitfalls.

Highlights

  • WASM Extension Installation Improvements: Fixed local WASM extension/channel installs to allow source-build fallback from Docker containers when release artifacts are missing. Tarball extraction now accepts crate-named bundle entries, resolving issues with bundles like telegram_tool.wasm.
  • Softened Ollama Model Discovery: Modified Ollama model discovery to gracefully fall back to the configured model when the /api/tags endpoint is unavailable or malformed, preventing failures in callers.
  • Docker Networking Guidance: Added guidance to the .env.example file for configuring Docker networking to access host-based local model providers (Ollama, LM Studio) using host.docker.internal.
  • Docker Compose Configuration: Introduced an app service to docker-compose.yml for the main application, including port mappings, environment variables, and volume mounts for extensions and source code, facilitating local development.
  • WhatsApp Channel Lockfile Update: Updated the Cargo.lock file for the WhatsApp channel to align its crate version with the latest changes.
Changelog
  • .env.example
    • Added comments providing Docker networking guidance for DATABASE_URL, OLLAMA_BASE_URL, and LLM_BASE_URL to use host.docker.internal.
  • channels-src/whatsapp/Cargo.lock
    • Updated the whatsapp-channel package version from 0.1.0 to 0.2.0.
  • docker-compose.yml
    • Modified the postgres service port binding to expose 5432 directly.
    • Added a new app service definition, configuring it to use the ironclaw:latest image, depend on postgres, map ports 3231:3000 and 8281:8080, load environment variables from .env, override DATABASE_URL for Docker's internal DNS, and mount local source directories as volumes.
  • src/extensions/manager.rs
    • Modified install_wasm_channel_from_url to accept an additional archive_crate_name parameter.
    • Updated install_wasm_tool_from_url_with_caps and install_wasm_channel_from_url to pass archive_crate_name when installing extensions from registry entries.
    • Adjusted download_and_install_wasm to accept archive_crate_name and pass it to extract_wasm_tar_gz.
    • Modified extract_wasm_tar_gz to accept archive_crate_name and use archive_filename_candidates for more flexible WASM and capabilities file matching within tarballs.
    • Added new helper functions archive_filename_candidates and preferred_archive_crate_name to generate potential filenames for WASM and capability files within archives.
    • Included new test cases for extract_wasm_tar_gz to verify acceptance of crate-named bundles.
  • src/llm/mod.rs
    • Modified create_ollama_from_registry to pass the config.base_url to the RigAdapter using with_ollama_base_url.
  • src/llm/rig_adapter.rs
    • Added an ollama_base_url field to RigAdapter to store the Ollama base URL for model listing.
    • Initialized ollama_base_url to None in the RigAdapter constructor.
    • Introduced with_ollama_base_url method to set the Ollama base URL.
    • Implemented ollama_model_list_fallback method to return the configured model name if no models are discovered.
    • Overrode the list_models method to fetch models from Ollama's /api/tags endpoint, with robust error handling and fallback to the configured model on request failure, non-success status, or malformed JSON.
    • Added a new test test_list_models_falls_back_to_configured_model_on_request_failure to validate the fallback behavior.
  • src/registry/installer.rs
    • Modified extract_tar_gz to accept archive_crate_name and archive_caps_name parameters, and updated its call site in install_wasm_extension.
    • Updated extract_tar_gz to use archive_filename_candidates and archive_capability_candidates for matching WASM and capabilities files within tarballs, allowing for more flexible naming.
    • Adjusted error messages in extract_tar_gz to list all candidate filenames when a WASM file is not found.
    • Added new helper functions archive_filename_candidates and archive_capability_candidates to generate potential filenames for WASM and capability files.
    • Included new test cases for extract_tar_gz to verify acceptance of crate-named entries.
Activity
  • The pull request description includes a detailed summary, change type, validation steps, security impact analysis, blast radius assessment, and a rollback plan.
  • No human comments or reviews have been posted on this pull request yet.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces several valuable fixes and improvements. The softening of Ollama model discovery with a fallback mechanism is well-implemented and robust. The changes to support crate-named WASM bundles and improve local installation fallbacks are also solid additions that enhance the developer experience. The documentation updates for Docker networking are clear and helpful.

My review includes a couple of suggestions to refactor the duplicated archive_filename_candidates helper function in both src/extensions/manager.rs and src/registry/installer.rs. Using a HashSet instead of a Vec for deduplication would be more idiomatic and slightly more efficient. Overall, this is a great set of changes.

Comment on lines +4179 to +4201
fn archive_filename_candidates(
extension_name: &str,
archive_crate_name: Option<&str>,
suffix: &str,
) -> Vec<String> {
let mut candidates = Vec::new();

for base in [Some(extension_name), archive_crate_name] {
if let Some(base) = base {
let raw = format!("{}{}", base, suffix);
if !candidates.contains(&raw) {
candidates.push(raw);
}

let snake = format!("{}{}", base.replace('-', "_"), suffix);
if !candidates.contains(&snake) {
candidates.push(snake);
}
}
}

candidates
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The implementation of archive_filename_candidates can be made more efficient and idiomatic. Using a Vec with repeated contains() checks for deduplication is less performant than using a HashSet. For a small number of items, the performance difference is negligible, but using a HashSet is cleaner and considered a best practice for managing unique collections.

fn archive_filename_candidates(
    extension_name: &str,
    archive_crate_name: Option<&str>,
    suffix: &str,
) -> Vec<String> {
    use std::collections::HashSet;
    let mut candidates: HashSet<String> = HashSet::new();

    for base in [Some(extension_name), archive_crate_name].into_iter().flatten() {
        candidates.insert(format!("{}{}", base, suffix));
        candidates.insert(format!("{}{}", base.replace('-', "_"), suffix));
    }

    candidates.into_iter().collect()
}

Comment on lines +754 to +776
fn archive_filename_candidates(
extension_name: &str,
archive_crate_name: Option<&str>,
suffix: &str,
) -> Vec<String> {
let mut candidates = Vec::new();

for base in [Some(extension_name), archive_crate_name] {
if let Some(base) = base {
let raw = format!("{}{}", base, suffix);
if !candidates.contains(&raw) {
candidates.push(raw);
}

let snake = format!("{}{}", base.replace('-', "_"), suffix);
if !candidates.contains(&snake) {
candidates.push(snake);
}
}
}

candidates
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

This function is a duplicate of archive_filename_candidates in src/extensions/manager.rs and has the same opportunity for improvement. Using a Vec with repeated contains() checks for deduplication can be replaced with a more efficient and idiomatic HashSet.

Additionally, since this logic is now duplicated in two modules, it might be worth considering extracting it into a shared utility function in a follow-up PR to improve maintainability.

fn archive_filename_candidates(
    extension_name: &str,
    archive_crate_name: Option<&str>,
    suffix: &str,
) -> Vec<String> {
    use std::collections::HashSet;
    let mut candidates: HashSet<String> = HashSet::new();

    for base in [Some(extension_name), archive_crate_name].into_iter().flatten() {
        candidates.insert(format!("{}{}", base, suffix));
        candidates.insert(format!("{}{}", base.replace('-', "_"), suffix));
    }

    candidates.into_iter().collect()
}

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR improves local development ergonomics for WASM extension/channel installs (especially when release artifacts are missing) and makes Ollama model discovery more resilient by falling back to the configured model when tag listing fails.

Changes:

  • Expand tar.gz extraction to accept crate-named (and snake_case) bundle entries for both registry installs and runtime extension installs.
  • Add Ollama /api/tags model listing with best-effort fallback behavior in the rig-based LLM adapter, wiring it up for the Ollama provider.
  • Update local Docker/dev guidance and configs (compose app service, env example hints) and align the WhatsApp channel lockfile version.

Reviewed changes

Copilot reviewed 6 out of 7 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/registry/installer.rs Accept multiple filename candidates when extracting tar.gz artifacts; adds tests for crate-named bundles.
src/extensions/manager.rs Pass preferred crate name into tar extraction; accept crate-named bundle entries; adds test coverage.
src/llm/rig_adapter.rs Implement list_models() for Ollama with fallback-to-configured-model behavior; add test.
src/llm/mod.rs Wire Ollama base URL into RigAdapter so list_models() can query /api/tags.
docker-compose.yml Add app service and change Postgres port publishing behavior.
channels-src/whatsapp/Cargo.lock Update lockfile package version to match crate version.
.env.example Add Docker networking guidance for host-based local model providers.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

image: pgvector/pgvector:pg16
ports:
- "127.0.0.1:5432:5432"
- "5432:5432"
Comment on lines +2 to 3
# For Docker: use host.docker.internal instead of localhost to access services on the host machine
DATABASE_URL=postgres://localhost/ironclaw
Comment on lines +4184 to +4199
let mut candidates = Vec::new();

for base in [Some(extension_name), archive_crate_name] {
if let Some(base) = base {
let raw = format!("{}{}", base, suffix);
if !candidates.contains(&raw) {
candidates.push(raw);
}

let snake = format!("{}{}", base.replace('-', "_"), suffix);
if !candidates.contains(&snake) {
candidates.push(snake);
}
}
}

@JZKK720
Copy link
Contributor Author

JZKK720 commented Mar 14, 2026

Follow-up after the rustfmt-only push (84ab91a): the remaining failing policy checks appear to be false positives.

  1. Regression Test Check
    This PR does add regression tests in changed Rust files, including new #[test] / #[tokio::test] additions for the tarball extraction and Ollama fallback work. The workflow log still reports no test changes, even though the diff contains those new test attributes and test bodies. That suggests the check is missing tests that live inside existing src/**/*.rs unit-test modules rather than a real absence of regression coverage.

  2. No panics in production code
    This job is flagging unwrap / expect / assert! lines that are inside mod tests blocks in src/**/*.rs, not production code paths. The failing log excerpts are all test-only lines from the newly added regression tests. So this looks like the grep-based policy is scanning added Rust lines broadly and not excluding test bodies accurately enough.

Formatting is now green after 84ab91a, so the two blockers left on this PR are these policy-check false positives rather than formatting or an obvious functional regression.

If maintainers want an immediate unblock for the regression policy specifically, the workflow itself suggests the skip-regression-check label. For the panic check, this looks like a workflow-pattern issue rather than a code issue.

Copilot AI review requested due to automatic review settings March 14, 2026 12:27
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR improves local development and installation resilience by expanding WASM bundle extraction name matching, adding a Docker “app” service to support local source-build fallbacks, and making Ollama model discovery best-effort (falling back to the configured model when listing fails).

Changes:

  • Extend tar.gz extraction to accept multiple archive entry naming conventions (extension-id, crate name, snake_case) for both WASM and capabilities files.
  • Add an Ollama-aware list_models() implementation that falls back to the configured model on request/parse failures.
  • Update local Docker/dev configuration (compose + .env.example) and align WhatsApp channel lockfile version.

Reviewed changes

Copilot reviewed 7 out of 8 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/registry/installer.rs Expands tar.gz extraction to accept crate-named/variant bundle entries; adds test coverage.
src/extensions/manager.rs Mirrors bundle entry candidate logic for gateway installs; passes through preferred crate name; adds tests.
src/llm/rig_adapter.rs Adds Ollama model listing via /api/tags with fallback behavior and a regression test.
src/llm/mod.rs Wires Ollama base URL into RigAdapter for model listing.
docker-compose.yml Publishes Postgres broadly and adds an app service with mounted sources for local installs.
channels-src/telegram/src/lib.rs Refines slash-command emission behavior for Submission parsing and /start payload handling; updates tests.
channels-src/whatsapp/Cargo.lock Aligns lockfile package version with crate version.
.env.example Adds Docker networking guidance for host-based local model providers.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

image: pgvector/pgvector:pg16
ports:
- "127.0.0.1:5432:5432"
- "5432:5432"
Comment on lines +33 to +35
- ./extensions/ironclaw-home:/home/ironclaw/.ironclaw
- ./tools-src:/app/tools-src:ro
- ./channels-src:/app/channels-src:ro
Comment on lines +2 to 3
# For Docker: use host.docker.internal instead of localhost to access services on the host machine
DATABASE_URL=postgres://localhost/ironclaw
Comment on lines +619 to +625
tracing::warn!(
model = %self.model_name,
base_url,
%status,
body,
"Ollama /api/tags returned an error; falling back to configured model"
);
let expected = format!("/start@{}", bot);
command.eq_ignore_ascii_case(&expected)
} else {
command.len() > "/start@".len() && command[..7].eq_ignore_ascii_case("/start@")
@github-actions github-actions bot added scope: channel/wasm WASM channel runtime size: XL 500+ changed lines and removed size: L 200-499 changed lines labels Mar 14, 2026
Copilot AI review requested due to automatic review settings March 14, 2026 14:05
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR improves local development and install robustness by enhancing WASM bundle extraction/fallback behavior, adding a safer Ollama model-listing fallback, and extending Docker/dev configuration to better support host-based services and channel runtime overrides.

Changes:

  • Make WASM tarball extraction accept multiple filename candidates (extension id, crate name, snake_case variants) for both registry installs and URL installs.
  • Add Ollama list_models() best-effort behavior that falls back to the configured model when /api/tags is unavailable or malformed.
  • Add local dev ergonomics: Docker compose app service + networking guidance, Telegram polling override config, and bundled capabilities fallback when an installed channel is missing its sidecar.

Reviewed changes

Copilot reviewed 12 out of 13 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/registry/installer.rs Expands tar.gz extraction to match multiple wasm/capabilities entry names; adds tests for crate-named entries.
src/extensions/manager.rs Updates URL installer extraction logic to support crate-named tarball entries; threads crate-name hint through install path; adds tests.
src/llm/rig_adapter.rs Adds optional Ollama base URL and implements list_models() with HTTP fetch + fallback behavior and a regression test.
src/llm/mod.rs Wires Ollama provider creation to set the base URL used for model listing.
src/config/channels.rs Introduces TELEGRAM_POLLING_ENABLED config flag and tests.
src/config/mod.rs Extends Config::for_testing() to populate the new channels config field.
src/channels/wasm/setup.rs Injects polling_enabled into the Telegram WASM channel config when the override is enabled.
src/channels/wasm/loader.rs Adds capability-sidecar resolution fallback to bundled capabilities when installed sidecar is missing; adds tests.
src/channels/wasm/bundled.rs Exposes a helper to locate bundled channel capabilities sidecar; adds a test.
channels-src/telegram/src/lib.rs Refines Telegram command parsing/emission logic, especially for /start and slash commands with arguments; updates tests.
docker-compose.yml Adds an app service for local Docker dev; adjusts Postgres port publishing.
.env.example Adds Docker networking guidance and documents TELEGRAM_POLLING_ENABLED.
channels-src/whatsapp/Cargo.lock Aligns the lockfile package version with the crate version.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines +566 to +580
let previous = std::env::var_os("IRONCLAW_CHANNELS_SRC");
unsafe {
std::env::set_var("IRONCLAW_CHANNELS_SRC", bundled_root.path());
}

let resolved = super::resolve_capabilities_path("telegram", &installed_wasm);

match previous {
Some(value) => unsafe {
std::env::set_var("IRONCLAW_CHANNELS_SRC", value);
},
None => unsafe {
std::env::remove_var("IRONCLAW_CHANNELS_SRC");
},
}
Comment on lines +751 to +773
fn archive_filename_candidates(
extension_name: &str,
archive_crate_name: Option<&str>,
suffix: &str,
) -> Vec<String> {
let mut candidates = Vec::new();

for base in [Some(extension_name), archive_crate_name] {
if let Some(base) = base {
let raw = format!("{}{}", base, suffix);
if !candidates.contains(&raw) {
candidates.push(raw);
}

let snake = format!("{}{}", base.replace('-', "_"), suffix);
if !candidates.contains(&snake) {
candidates.push(snake);
}
}
}

candidates
}
image: pgvector/pgvector:pg16
ports:
- "127.0.0.1:5432:5432"
- "5432:5432"
retries: 5

app:
image: ironclaw:latest
Comment on lines +618 to +623
let body = response.text().await.unwrap_or_default();
tracing::warn!(
model = %self.model_name,
base_url,
%status,
body,
@G7CNF
Copy link
Contributor

G7CNF commented Mar 14, 2026

Prepared a fix branch for this PR’s failing checks, since I can’t push to nearai/ironclaw directly.

Branch: G7CNF:codex/pr-1167-fix

Commits to cherry-pick onto setup-env.test-improvements:

  • 77e3e0c fix(clippy): flatten optional archive filename bases
  • 22fa6bd test(ci): annotate test-only panic macros for no-panics gate

What these address:

  • Clippy manual_flatten in archive_filename_candidates (src/extensions/manager.rs, src/registry/installer.rs)
  • No panics in production code matcher false positives on test-only assertions/unwrap/expect lines by adding inline // safety: suppressions

Local verification on that branch:

  • cargo clippy --all --benches --tests --examples -- -D warnings
  • no-panics workflow grep logic (run locally against origin/staging...HEAD) ✅

@G7CNF
Copy link
Contributor

G7CNF commented Mar 14, 2026

Prepared a fix branch for this PR’s failing checks, since I can’t push to directly.

Branch:

Commits to cherry-pick onto :

  • fix(clippy): flatten optional archive filename bases
  • test(ci): annotate test-only panic macros for no-panics gate

What these address:

  • Clippy in (, )
  • matcher false positives on test-only assertions/unwrap/expect lines by adding inline suppressions

Local verification on that branch:

  • no-panics workflow grep logic (run locally against ) ✅

@github-actions github-actions bot added the scope: ci CI/CD workflows label Mar 14, 2026
Copilot AI review requested due to automatic review settings March 14, 2026 16:47
@github-actions github-actions bot added the scope: dependencies Dependency updates label Mar 14, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR improves local development and install robustness for WASM extensions/channels, and makes Ollama model discovery best-effort to avoid failing callers when model listing is unavailable.

Changes:

  • Extend tar.gz extraction to accept multiple filename candidates (extension name, crate name, snake_case) for .wasm and capabilities sidecars.
  • Add Ollama model listing via /api/tags with fallback to the configured model when the endpoint fails or returns unusable data.
  • Add Telegram channel runtime overrides/config and loader-side capabilities fallbacks; update local Docker/dev guidance and introduce a CI script to detect panic-style calls in production Rust diffs.

Reviewed changes

Copilot reviewed 14 out of 16 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/registry/installer.rs Accept crate-/snake-named entries when extracting registry tar.gz bundles; adds tests.
src/extensions/manager.rs Extend URL install tar.gz extraction to accept crate-/snake-named bundle entries; adds tests/helpers.
src/llm/rig_adapter.rs Add optional Ollama base URL and implement list_models() with fallback behavior + test.
src/llm/mod.rs Wire Ollama base URL into the RigAdapter so listing is enabled for Ollama providers.
src/config/mod.rs Add telegram_polling_enabled default in test config.
src/config/channels.rs Add TELEGRAM_POLLING_ENABLED env/config support + unit test coverage.
src/channels/wasm/setup.rs Inject Telegram polling_enabled runtime config override into the WASM channel.
src/channels/wasm/loader.rs Fall back to bundled capabilities sidecar when an installed channel is missing its local sidecar; adds tests.
src/channels/wasm/bundled.rs Add helper to locate bundled channel capabilities sidecar; adds test.
channels-src/telegram/src/lib.rs Adjust emitted agent content handling for slash commands and /start@bot forms; expands tests.
channels-src/whatsapp/Cargo.lock Align WhatsApp channel lockfile crate version.
docker-compose.yml Add an app service and update Postgres port binding for local Docker stack.
.env.example Add Docker networking guidance (host access via host.docker.internal) and Telegram polling flag.
scripts/check_no_panics.py New diff-aware checker used by CI to block new unwrap/expect/assert in production Rust code.
.github/workflows/code_style.yml Switch “no panics” job to use scripts/check_no_panics.py.
Cargo.lock Update workspace lockfile dependency resolutions.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

let expected = format!("/start@{}", bot);
command.eq_ignore_ascii_case(&expected)
} else {
command.len() > "/start@".len() && command[..7].eq_ignore_ascii_case("/start@")
Comment on lines +619 to +623
tracing::warn!(
model = %self.model_name,
base_url,
%status,
body,
image: pgvector/pgvector:pg16
ports:
- "127.0.0.1:5432:5432"
- "5432:5432"
Comment on lines 1 to 3
# Database Configuration
# For Docker: use host.docker.internal instead of localhost to access services on the host machine
DATABASE_URL=postgres://localhost/ironclaw
self.assertFalse(contexts[5])
self.assertFalse(contexts[6])

def test_named_tests_module_without_cfg_is_ignored(self) -> None:
Copy link
Collaborator

@zmanian zmanian left a comment

Choose a reason for hiding this comment

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

Review: Local WASM fallback installs and Ollama model listing

The WASM archive filename resolution logic is useful (handling crate_name vs extension_name mismatches), but there's a security issue and scope concerns.

Blocking

1. Security: PostgreSQL exposed to all interfaces

In `docker-compose.yml`, the postgres port binding changed from:
```yaml

  • "127.0.0.1:5432:5432"
    ```
    to:
    ```yaml
  • "5432:5432"
    ```

This exposes the database to all network interfaces instead of localhost-only. On any machine with a public IP, this makes the database accessible from the internet with default credentials (`ironclaw:ironclaw`). Please revert to the localhost binding.

2. Scope too broad

This PR bundles 4+ distinct changes across 10 commits:

  • Docker compose app service addition
  • .env.example Docker networking docs
  • WASM archive filename candidate logic
  • Ollama model listing changes
  • Registry installer modifications

These should be separate PRs for reviewability. At minimum, the docker-compose security change should not be bundled with WASM install logic.

Non-blocking

  • The `archive_filename_candidates()` function is well-designed -- handles hyphenated vs snake_case name mismatches
  • The `preferred_archive_crate_name()` fallback chain (source -> fallback_source) is a reasonable approach

Title check: partially accurate -- title mentions WASM fallback and Ollama but doesn't mention docker-compose changes or .env.example docs.

Copy link
Collaborator

@zmanian zmanian left a comment

Choose a reason for hiding this comment

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

Review: REQUEST CHANGES

Previous blocking feedback remains unresolved (no commits since March 14th).

Still blocking from prior review

1. PostgreSQL exposed on all interfaces
docker-compose.yml still has "5432:5432" with default credentials (ironclaw:ironclaw). Must revert to "127.0.0.1:5432:5432".

2. Scope too broad
PR bundles 6+ distinct changes: WASM archive resolution, Ollama model listing, Telegram slash command parsing, Docker compose app service, CI script replacement, bundled channel capabilities fallback, dependency update.

New issues found

3. Duplicated archive_filename_candidates() -- identical function in both extensions/manager.rs and registry/installer.rs. Flagged by multiple reviewers across multiple rounds, never addressed. Extract to a shared module.

4. Untrusted response body logged in full -- list_models() reads entire Ollama response with .unwrap_or_default() and logs at warn level. Should truncate before logging (use truncate_for_preview or similar).

5. is_start_command_token() with None bot_username accepts /start@AnyBot in group chats -- could react to commands intended for other bots. Should only match bare /start when bot_username is None.

6. Test uses unsafe { std::env::set_var } without synchronization -- resolve_capabilities_path_falls_back_to_bundled_sidecar in loader.rs can race with parallel tests.

What's good

  • archive_filename_candidates() design is sound -- handles the hyphen/underscore mismatch correctly
  • Ollama list_models() fallback strategy is well-structured with appropriate logging
  • Good test coverage for archive extraction, Ollama fallback, and Telegram commands
  • check_no_panics.py is a meaningful improvement over inline shell

Recommendation

Split into at minimum 3 PRs:

  1. WASM archive resolution + Ollama model listing
  2. Telegram channel improvements
  3. Docker/CI infrastructure

CI is green. The individual changes are mostly good -- they just need to be separated and the blockers addressed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

contributor: regular 2-5 merged PRs risk: medium Business logic, config, or moderate-risk modules scope: channel/wasm WASM channel runtime scope: ci CI/CD workflows scope: dependencies Dependency updates scope: extensions Extension management scope: llm LLM integration size: XL 500+ changed lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants