feat: Unified module storage, polyglot dispatch, app-layer services, WASM hook registration - #45
Merged
Merged
Conversation
Design for making Rust the single source of truth for module storage across non-Python transports. Five components: 1. Arc<HookRegistry> in Coordinator for shared ownership 2. Fix Node bindings to share real Arc instances 3. Complete gRPC transport symmetry (4 missing load functions) 4. Decouple LoadedModule from wasm feature gate 5. Documentation via docstrings, not prose examples Establishes Python-from-Rust-host pattern via gRPC adapters. Preserves 100% Python backward compatibility.
- Add `let _ =` before 39 unused .register() return values in tests (hooks.rs: 31, grpc_server.rs: 4, session.rs: 3, coordinator.rs: 1) - Auto-fix 2 `variable does not need to be mutable` warnings in bindings/python/src/lib.rs via `cargo fix --lib -p amplifier-core-py`
Approved design for wiring WASM and gRPC module loading into the Python host's session init path. Key decisions: - Deduplicate session.py/session_init.py (~200 lines removed) - Absorb transport dispatch into loader.py after source resolution - Delete loader_dispatch.py (wrong abstraction boundary) - Extend load_and_mount_wasm() for all 6 module types - Rust resolve_module() as single source of truth for transport detection
Add 4 tests verifying AmplifierSession.initialize() delegates to _session_init.initialize_session(). Tests intentionally fail with AttributeError because session.py does not yet import initialize_session - this is the RED phase of TDD.
RED test: test_wasm_dispatch_returns_mount_function verifies that loader.load() can dispatch to WASM transport and return a callable mount function. Currently fails with TypeError because loader.load() does not yet accept a coordinator parameter and has no WASM dispatch branch. Task-3 of unified-module-storage implementation plan.
The code quality reviewer suggested extracting the string literal "echo-tool" (repeated 6 times) to a module-level constant MODULE_ID for clarity. No behavioral change.
- Add coordinator parameter to load() for polyglot dispatch - Insert transport dispatch block before Python validation: routes to WASM or gRPC loaders when Rust engine resolves non-Python transport - Add _make_wasm_mount() and _make_grpc_mount() helper methods - Pass coordinator=coordinator at all 5 loader.load() call sites in _session_init.py (orchestrator, context, providers, tools, hooks) - Update test mocks in test_multi_instance.py to accept new parameter 🤖 Generated with Amplifier Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
- Deleted python/amplifier_core/loader_dispatch.py: functions (_detect_transport, _read_module_meta, load_module) are now absorbed into loader.load() - Deleted bindings/python/tests/test_loader_dispatch.py: tested internal implementation details of loader_dispatch.py - Deleted bindings/python/tests/test_dispatch_integration.py: tested internal implementation details of loader_dispatch.py - Rewrote python/tests/test_loader_dispatch_wasm.py: new test exercises WASM mounting through loader.load() dispatch path instead of old loader_dispatch.load_module() - Updated tests/validate_rust_kernel.py: replaced loader_dispatch import check with loader.ModuleLoader import check All transport and module dispatch logic is now unified through loader.load(), reducing code duplication and improving test maintainability. 🤖 Generated with Amplifier Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
- Add get-subscriptions function to hook-handler interface in WIT - Add event-subscription record type to WIT - Add EventSubscription struct to guest SDK types.rs - Add get_subscriptions method to HookHandler trait - Update export_hook! macro to export get_subscriptions WASM function - Update test implementations to include get_subscriptions method All 94 guest SDK tests pass with new functionality.
…for old modules - Add WasmHookBridge::subscriptions_from_result() (pub(crate)) to classify errors: 'not found' → debug log + wildcard, other → warn log + wildcard. Mirrors the GrpcHookBridge pattern for UNIMPLEMENTED fallback. - Change WasmHookBridge::get_subscriptions() from WasmResult<Vec<...>> to Vec<...> (infallible), applying graceful fallback internally so callers never need to handle a missing-export error. - Add get_subscriptions() default method to HookHandler trait (returns wildcard), overridden by WasmHookBridge to call the WASM export. This allows Arc<dyn HookHandler> callers to query subscriptions without downcasting. - Replace hardcoded wildcard vec in bindings/python/src/lib.rs mount path with hook.get_subscriptions(&config), so modules with the export use their declared subscriptions; old modules fall back to wildcard. - Add future-bidirectional-path comment to wit/amplifier-modules.wit near get-subscriptions describing the register-hook host import approach. - Fix pre-existing rustfmt issue in grpc_hook.rs (long parameter line).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Three design phases implemented, enabling non-Python hosts to provide app-layer services and making WASM/gRPC modules loadable from bundle config:
Phase 1: Unified Module Storage & Arc Sharing (design: 2026-03-09)
Arc<HookRegistry>in Coordinator — enables shared ownership for binding layersArc<Coordinator>andArc<HookRegistry>(deleted disconnected-copy factory methods)load_grpc_provider,load_grpc_hook,load_grpc_context,load_grpc_approvalLoadedModuleandresolve_module()available without--features wasmunused_must_usein test code suppressedPhase 2: Session Init Polyglot Dispatch (design: 2026-03-09)
session.py:initialize()delegates to_session_init.initialize_session(), eliminating ~200 lines of duplicationloader.py— Rustresolve_module()detects transport after source resolution, branches to WASM/gRPC/Pythonloader_dispatch.pydeleted (131 lines) — was at wrong abstraction boundary, duplicated Rust logicPyWasm*wrappers — Provider, Hook, Context, Orchestrator, Approval for all 6 WASM module types@pytest.mark.slowfor ARM64)Phase 3: App-Layer Services & Review Fixes (design: 2026-03-10)
ApprovalProviderwired to Coordinator — Rust trait field +PyApprovalProviderBridgewrapping PythonApprovalSystemDisplayServicetrait added — new Rust trait + Coordinator field +PyDisplayServiceBridgeget-subscriptions— new WIT export lets hooks self-describe event subscriptions; host registers at mount time (fixes silent hook drop bug)GetSubscriptionsRPC added to HookService protowarning(wasdebug)PyWasmOrchestratordocumentation improved with mount warnings_safe_exception_strdeduplicatedDesign docs
docs/plans/2026-03-09-unified-module-storage-design.mddocs/plans/2026-03-09-session-init-polyglot-dispatch-design.mddocs/plans/2026-03-10-app-layer-services-design.mdPython backward compatibility
Zero breaking changes. All existing Python APIs preserved unchanged. 514 Python tests pass (up from 495 at session start).
Test counts
🤖 Generated with Amplifier
Co-Authored-By: Amplifier 240397093+microsoft-amplifier@users.noreply.github.com