Skip to content

fix: align generated function grouping contract#13

Merged
rohitg00 merged 1 commit into
mainfrom
align-generated-engine-functions
May 14, 2026
Merged

fix: align generated function grouping contract#13
rohitg00 merged 1 commit into
mainfrom
align-generated-engine-functions

Conversation

@rohitg00

@rohitg00 rohitg00 commented May 14, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • rename the worker implementation to generated bridge/function terminology
  • send the private engine grouping hint as metadata.iii.generatedWorker so converted OpenAPI/MCP sources appear as normal engine-runtime worker groups
  • update README and research note to remove hidden-worker and Context7-specific wording
  • add worker tests for the generated grouping response and private metadata hint

Validation

  • cargo fmt
  • cargo test
  • cargo clippy --all-targets --all-features -- -D warnings

Paired Engine PR

Summary by CodeRabbit

Release Notes

  • New Features

    • Converted OpenAPI specs and MCP servers now produce ordinary, triggerable iii functions without starting separate worker processes.
    • Generated functions integrate seamlessly into the engine with updated metadata identification.
  • Documentation

    • Updated guides with examples for converting OpenAPI and MCP sources to functions.
  • Refactor

    • Internal function generation model updated to improve engine registration and invocation behavior.

Review Change Stack

@coderabbitai

coderabbitai Bot commented May 14, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

This PR refactors spec-to-worker from a "virtual" worker model to a "generated" worker model. The system now converts OpenAPI specs and MCP servers into ordinary iii functions registered via an HTTP bridge, without starting separate worker processes. New public types define the conversion contract; registration flow routes through generated discovery helpers; the bridge server stores and invokes generated HTTP functions; and tests/docs validate the updated behavior.

Changes

Virtual-to-Generated Worker Refactor

Layer / File(s) Summary
Generated Type Contracts
src/lib.rs
Introduces GeneratedFunctionRegistration, GeneratedWorkerManifest, and GeneratedInvocation types. Updates SpecToWorkerConversion struct to include registered_functions, manifest, and notes fields reflecting generated registration model and HTTP-bridge invocation.
Conversion Flow and Generated Registration
src/lib.rs
Conversion entry point convert_spec_to_worker_for_iii routes OpenAPI/MCP sources through register_openapi_generated_worker / register_mcp_generated_worker into consolidated register_generated_worker, which registers iii functions backed by HTTP bridge and builds the generated manifest.
OpenAPI Generated Discovery
src/lib.rs
Helper openapi_generated_functions produces Vec<GeneratedHttpFunction> and maps OpenAPI operations to generated HTTP functions with correct invocation variant selection.
MCP Generated Discovery and Named Tools
src/lib.rs
MCP discovery helper mcp_discovered_generated_functions produces Vec<GeneratedHttpFunction> for tools; mcp_named_generated_functions provides named-tool mapping. Invocation and metadata mapping updated to GeneratedInvocation variants.
Bridge Server Storage and Invocation
src/lib.rs
Bridge function registry stores GeneratedHttpFunction instances with GENERATED_BRIDGE storage. Request handler dispatches via invoke_generated_http_function supporting Plain HTTP and MCP tool/list/call variants.
HTTP Request and Response Helpers
src/lib.rs
HTTP invocation including invoke_plain_generated_http_function, request building via generated_function_url / generated_function_body, and response parsing via parse_generated_http_response.
Generated Metadata Exposure
src/lib.rs
Metadata function updated to emit iii.generatedWorker instead of iii.virtualWorker.
Integration Tests
tests/rust_core.rs
Tests for OpenAPI and MCP conversion validate manifest shape, worker_name, namespace, and notes confirming engine-backed HTTP invocation without worker process startup.
Unit Tests
src/lib.rs
Unit tests for generated function URL/body helpers and metadata validation with generated worker fields.

Documentation Updates

Layer / File(s) Summary
README Overview and Product Contract
README.md
Rewrites spec-to-worker description as conversion system to ordinary iii functions via spec-to-worker::convert. Adds Product Contract specifying discovery/registration behavior and HTTP invocation path without generated worker process.
README Examples and Visibility
README.md
Updates OpenAPI and MCP example payloads and outputs. Adds "Convert MCP Stdio" and "Convert MCP HTTP" sections with generated function IDs and example iii trigger calls. Reorganizes "Verify Visibility" to show expected engine::functions::list and engine::workers::list shapes.
README Function ID Normalization and Developer Commands
README.md
Extends Function ID normalization examples. Replaces "Real Checks Run On This Branch" with "Developer Commands" block and updates release-status line.
Research Note Specification Updates
docs/research-note.md
Redefines spec-to-worker goal as iii-worker-style conversion to ordinary functions. Reworks Product Rule, Engine Rule, and Scope Now sections with explicit requirements for public spec-to-worker::convert API, engine HTTP registration, and public metadata stripping of private routing fields.

🎯 4 (Complex) | ⏱️ ~60 minutes

A rabbit hops through types so new,
From virtual dreams to generated true,
The bridge now shines with HTTP light,
Converting specs into functions bright! 🐰✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 22.22% 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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix: align generated function grouping contract' accurately describes the main change: aligning how generated functions are grouped and their contract, replacing 'virtual-worker' terminology with 'generated' and updating the worker grouping behavior.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch align-generated-engine-functions

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 and usage tips.

@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: 2

🧹 Nitpick comments (2)
tests/rust_core.rs (1)

132-139: ⚡ Quick win

Consider extracting duplicate note assertions into a helper function.

The same note assertion pattern appears in both the OpenAPI test (lines 132-139) and the new MCP test (lines 285-292). Extracting this into a helper function would improve maintainability and reduce duplication.

♻️ Proposed helper function

Add this helper at module level:

fn assert_conversion_notes_describe_engine_grouping(
    converted: &spec_to_worker::SpecToWorkerConversion,
) {
    assert!(converted
        .notes
        .iter()
        .any(|note| note.contains("normal iii functions backed by engine HTTP invocation")));
    assert!(converted
        .notes
        .iter()
        .any(|note| note.contains("engine-runtime worker group; no worker process is started")));
}

Then replace both assertion blocks with:

-    assert!(converted
-        .notes
-        .iter()
-        .any(|note| note.contains("normal iii functions backed by engine HTTP invocation")));
-    assert!(converted
-        .notes
-        .iter()
-        .any(|note| note.contains("engine-runtime worker group; no worker process is started")));
+    assert_conversion_notes_describe_engine_grouping(&converted);

Also applies to: 285-292

🤖 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 `@tests/rust_core.rs` around lines 132 - 139, Extract the duplicated note
assertions into a module-level helper named
assert_conversion_notes_describe_engine_grouping that accepts
&spec_to_worker::SpecToWorkerConversion (the same type as converted) and
performs both assert! checks for the two note substrings; add that function to
the test module and replace the two duplicate assertion blocks in the OpenAPI
and MCP tests (where they call converted.notes.iter().any(...)) with a single
call to assert_conversion_notes_describe_engine_grouping(&converted).
src/lib.rs (1)

332-403: 💤 Low value

Consider dropping the mode parameter or promoting it to a constant.

Both call sites pass the literal "http_invocation" (lines 316 and 329), and the same string is duplicated inside this function as schema: "spec-to-worker.http-invocation.v1" (line 378) and inside spec_to_worker_metadata at line 569. The mode argument is effectively dead today and the literal is repeated in three places.

♻️ Suggested cleanup
+const HTTP_INVOCATION_MODE: &str = "http_invocation";
+const GENERATED_WORKER_SCHEMA: &str = "spec-to-worker.http-invocation.v1";
@@
-fn register_generated_worker(
-    iii: &iii_sdk::III,
-    spec: &SpecSource,
-    generated_functions: Vec<GeneratedHttpFunction>,
-    mode: &str,
-) -> Result<SpecToWorkerConversion> {
+fn register_generated_worker(
+    iii: &iii_sdk::III,
+    spec: &SpecSource,
+    generated_functions: Vec<GeneratedHttpFunction>,
+) -> Result<SpecToWorkerConversion> {
@@
-    let manifest = GeneratedWorkerManifest {
-        schema: "spec-to-worker.http-invocation.v1".into(),
+    let manifest = GeneratedWorkerManifest {
+        schema: GENERATED_WORKER_SCHEMA.into(),
@@
-        mode: mode.into(),
+        mode: HTTP_INVOCATION_MODE.into(),

Then update the two callers (and spec_to_worker_metadata) to use HTTP_INVOCATION_MODE. Keep mode as a parameter only if a non-HTTP mode is planned in the near term.

🤖 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 `@src/lib.rs` around lines 332 - 403, The mode parameter is unused and
duplicated as a literal; remove it or promote it to a constant: add a constant
HTTP_INVOCATION_MODE (or similar) and replace all literal "http_invocation" call
sites and uses (e.g., callers of register_generated_worker and
spec_to_worker_metadata) to use that constant; update register_generated_worker
signature to drop the mode parameter (or accept the new constant if you must
keep the param), remove the duplicated literal occurrences inside
register_generated_worker (and rely on the constant where needed), and adjust
both callers and spec_to_worker_metadata to reference HTTP_INVOCATION_MODE so
the string is centralized.
🤖 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 `@README.md`:
- Line 277: Update the user-facing product name in the README table entry:
replace the lowercase token `github mcp` with `GitHub mcp` so the row reading
"`github mcp` + `search_repos` | `github_mcp::search_repos`" becomes "`GitHub
mcp` + `search_repos` | `github_mcp::search_repos`", preserving the
`search_repos` and `github_mcp::search_repos` identifiers.

In `@tests/rust_core.rs`:
- Around line 281-284: The test indexes converted.manifest.functions without
ensuring it has elements; add a bounds check before accessing it (e.g., assert
that converted.manifest.functions is not empty or
assert_eq!(converted.manifest.functions.len(), expected) ) and then perform the
existing assertion on converted.manifest.functions[0].function_id to avoid a
potential panic in the test.

---

Nitpick comments:
In `@src/lib.rs`:
- Around line 332-403: The mode parameter is unused and duplicated as a literal;
remove it or promote it to a constant: add a constant HTTP_INVOCATION_MODE (or
similar) and replace all literal "http_invocation" call sites and uses (e.g.,
callers of register_generated_worker and spec_to_worker_metadata) to use that
constant; update register_generated_worker signature to drop the mode parameter
(or accept the new constant if you must keep the param), remove the duplicated
literal occurrences inside register_generated_worker (and rely on the constant
where needed), and adjust both callers and spec_to_worker_metadata to reference
HTTP_INVOCATION_MODE so the string is centralized.

In `@tests/rust_core.rs`:
- Around line 132-139: Extract the duplicated note assertions into a
module-level helper named assert_conversion_notes_describe_engine_grouping that
accepts &spec_to_worker::SpecToWorkerConversion (the same type as converted) and
performs both assert! checks for the two note substrings; add that function to
the test module and replace the two duplicate assertion blocks in the OpenAPI
and MCP tests (where they call converted.notes.iter().any(...)) with a single
call to assert_conversion_notes_describe_engine_grouping(&converted).
🪄 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 Plus

Run ID: a92eca4c-b6ac-4d62-96d9-3f839340645d

📥 Commits

Reviewing files that changed from the base of the PR and between 40b44d4 and 192651d.

📒 Files selected for processing (4)
  • README.md
  • docs/research-note.md
  • src/lib.rs
  • tests/rust_core.rs

Comment thread README.md
| `xkcd live` + `get /{comicId}/info.0.json` | `xkcd_live::get_comicid_info_0_json` |
| `context7 stdio` + `query-docs` | `context7_stdio::query_docs` |
| `docs mcp` + `search-docs` | `docs_mcp::search_docs` |
| `github mcp` + `search_repos` | `github_mcp::search_repos` |

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Capitalize product name consistently (“GitHub”).

At Line 277, use GitHub mcp instead of github mcp to match official naming in user-facing docs.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~277-~277: The official name of this software platform is spelled with a capital “H”.
Context: ...rch-docs|docs_mcp::search_docs| |github mcp+search_repos|github_mcp::se...

(GITHUB)


[uncategorized] ~277-~277: The official name of this software platform is spelled with a capital “H”.
Context: ...cs| |github mcp+search_repos|github_mcp::search_repos` | If a duplicate ID...

(GITHUB)

🤖 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 `@README.md` at line 277, Update the user-facing product name in the README
table entry: replace the lowercase token `github mcp` with `GitHub mcp` so the
row reading "`github mcp` + `search_repos` | `github_mcp::search_repos`" becomes
"`GitHub mcp` + `search_repos` | `github_mcp::search_repos`", preserving the
`search_repos` and `github_mcp::search_repos` identifiers.

Comment thread tests/rust_core.rs
Comment on lines +281 to +284
assert_eq!(
converted.manifest.functions[0].function_id,
"docs_mcp::search_docs"
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add bounds check before indexing manifest.functions.

Direct array indexing without verifying the array is non-empty can panic if manifest.functions is empty. While the test expects successful conversion with at least one function, adding a guard improves test robustness.

✅ Proposed fix to add bounds check
+    assert!(!converted.manifest.functions.is_empty(), "Expected at least one function in manifest");
     assert_eq!(
         converted.manifest.functions[0].function_id,
         "docs_mcp::search_docs"
     );
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
assert_eq!(
converted.manifest.functions[0].function_id,
"docs_mcp::search_docs"
);
assert!(!converted.manifest.functions.is_empty(), "Expected at least one function in manifest");
assert_eq!(
converted.manifest.functions[0].function_id,
"docs_mcp::search_docs"
);
🤖 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 `@tests/rust_core.rs` around lines 281 - 284, The test indexes
converted.manifest.functions without ensuring it has elements; add a bounds
check before accessing it (e.g., assert that converted.manifest.functions is not
empty or assert_eq!(converted.manifest.functions.len(), expected) ) and then
perform the existing assertion on converted.manifest.functions[0].function_id to
avoid a potential panic in the test.

@rohitg00 rohitg00 merged commit cffa995 into main May 14, 2026
1 check passed
@rohitg00 rohitg00 deleted the align-generated-engine-functions branch May 14, 2026 17:29
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.

1 participant