Skip to content

Conversation

@jog1t
Copy link
Contributor

@jog1t jog1t commented Oct 30, 2025

TL;DR

Refactored actor worker context to support inspector mode and standardized HTTP header usage.

What changed?

  • Added a new useConnectionDetails() hook in actor-worker-context.tsx that returns different connection details based on the application type
  • Updated ActorWorkerContextProvider to use the new hook instead of directly accessing the data provider
  • Replaced hardcoded header strings in rivetkit with imported constants from driver-helpers/mod
  • Added HEADER_ACTOR_QUERY to the list of allowed CORS headers

How to test?

  1. Run the application in both normal and inspector modes
  2. Verify that actor workers connect properly in both modes
  3. Confirm that cross-origin requests with the Rivet headers are properly handled

Why make this change?

This change improves the codebase by:

  1. Adding proper support for inspector mode in the actor worker context
  2. Reducing duplication by using constants for header names
  3. Ensuring consistent header handling across the application
  4. Preventing potential bugs from mismatched header names

@vercel
Copy link

vercel bot commented Oct 30, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
rivet-inspector Ready Ready Preview Comment Nov 10, 2025 4:35pm
3 Skipped Deployments
Project Deployment Preview Comments Updated (UTC)
rivet-cloud Ignored Ignored Nov 10, 2025 4:35pm
rivet-site Ignored Ignored Preview Nov 10, 2025 4:35pm
rivetkit-serverless Skipped Skipped Nov 10, 2025 4:35pm

@jog1t jog1t requested a review from NathanFlurry October 30, 2025 01:25
@jog1t jog1t marked this pull request as ready for review October 30, 2025 01:25
Copy link
Contributor Author

jog1t commented Oct 30, 2025


How to use the Graphite Merge Queue

Add the label merge-queue to this PR to add it to the merge queue.

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has enabled the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

This stack of pull requests is managed by Graphite. Learn more about stacking.

@claude
Copy link

claude bot commented Oct 30, 2025

PR Review

Summary

This PR refactors actor worker context to support inspector mode and standardizes HTTP header usage by replacing hardcoded strings with constants. Overall, the changes are solid and improve maintainability.

✅ Strengths

  1. Good use of constants: Replacing hardcoded header strings ("x-rivet-actor", "x-rivet-target") with imported constants (HEADER_RIVET_ACTOR, HEADER_RIVET_TARGET) reduces duplication and prevents typos.

  2. Proper separation of concerns: The new useConnectionDetails() hook cleanly separates inspector mode from normal mode logic.

  3. Consistent pattern matching: Using ts-pattern's match API consistently with the existing useInspectorToken hook.

  4. CORS security improvement: Adding HEADER_ACTOR_QUERY to the allowed headers list ensures proper CORS handling for this header.

🔍 Issues & Suggestions

1. Code Style: Missing semicolon (Minor)

Location: frontend/src/components/actors/worker/actor-worker-context.tsx:55

The useConnectionDetails function is missing a semicolon at the end:

const useConnectionDetails = () => {
	return match(__APP_TYPE__)
		.with("inspector", () => {
			return {namespace: "", engineToken: ""};
		})
		.otherwise(() => {
			const provider = useEngineCompatDataProvider();
			return {namespace: provider.engineNamespace, engineToken: provider.engineToken};
		});
}  // Missing semicolon here

Recommendation: Add semicolon for consistency with the rest of the codebase.

2. Code Style: Inconsistent spacing (Minor)

Location: frontend/src/components/actors/worker/actor-worker-context.tsx:67

There's a trailing whitespace after the destructuring assignment:

const {engineToken, namespace} = useConnectionDetails();
	  // Extra blank line here
const {

Recommendation: Remove the trailing whitespace for consistency.

3. Code Style: Object property spacing (Minor)

Location: frontend/src/components/actors/worker/actor-worker-context.tsx:49,53

Missing spaces after colons in object literals:

return {namespace: "", engineToken: ""};  // Should be { namespace: "", engineToken: "" }
return {namespace: provider.engineNamespace, engineToken: provider.engineToken};

Recommendation: Add spaces after colons to match TypeScript/JavaScript conventions.

4. Potential Runtime Issue: Hook call order (Medium)

Location: frontend/src/components/actors/worker/actor-worker-context.tsx:52

The useConnectionDetails hook conditionally calls useEngineCompatDataProvider() only in the otherwise branch. This violates React's Rules of Hooks (hooks must be called in the same order on every render).

In inspector mode, useEngineCompatDataProvider() won't be called, but in normal mode it will. If __APP_TYPE__ could ever change at runtime, this would cause issues. While __APP_TYPE__ is likely a build-time constant, this pattern is still fragile.

Recommendation: Consider restructuring to call hooks unconditionally:

const useConnectionDetails = () => {
	const provider = match(__APP_TYPE__)
		.with("inspector", () => null)
		.otherwise(() => useEngineCompatDataProvider());
	
	return match(__APP_TYPE__)
		.with("inspector", () => ({ namespace: "", engineToken: "" }))
		.otherwise(() => ({
			namespace: provider?.engineNamespace ?? "",
			engineToken: provider?.engineToken ?? ""
		}));
}

However, this still has issues. A better approach might be:

const useConnectionDetails = () => {
	if (__APP_TYPE__ === "inspector") {
		return { namespace: "", engineToken: "" };
	}
	
	const provider = useEngineCompatDataProvider();
	return {
		namespace: provider.engineNamespace,
		engineToken: provider.engineToken
	};
}

Since __APP_TYPE__ is a compile-time constant, the dead code should be eliminated during bundling, avoiding the hook order issue.

5. Missing Test Coverage (Medium)

No test files were found for these components. Given that this PR changes critical connection logic for both normal and inspector modes, tests would be valuable.

Recommendation: Consider adding tests to verify:

  • Inspector mode returns empty strings for namespace and engineToken
  • Normal mode correctly retrieves values from the data provider
  • The connection details are properly passed to the ActorWorkerContainer

📊 Performance Considerations

No performance concerns. The refactoring maintains the same runtime behavior with minimal overhead.

🔒 Security Considerations

No security issues identified. The changes improve security by:

  • Properly declaring HEADER_ACTOR_QUERY in CORS allowed headers
  • Using constants reduces the risk of header name mismatches

📝 Best Practices

The PR follows repository conventions well:

  • ✅ Uses existing patterns (ts-pattern, hooks)
  • ✅ Proper import organization
  • ✅ Consistent with existing code style (mostly)

Final Verdict

Approve with minor suggestions. The core logic is sound and achieves the stated goals. The main concern is the conditional hook call, but if __APP_TYPE__ is truly a build-time constant (which it appears to be), this should be fine. The style issues are minor and could be fixed in a follow-up or left as-is.


🤖 Generated with Claude Code

@pkg-pr-new
Copy link

pkg-pr-new bot commented Oct 30, 2025

More templates

@rivetkit/actor

pnpm add https://pkg.pr.new/rivet-dev/rivet/@rivetkit/actor@3289

@rivetkit/cloudflare-workers

pnpm add https://pkg.pr.new/rivet-dev/rivet/@rivetkit/cloudflare-workers@3289

@rivetkit/core

pnpm add https://pkg.pr.new/rivet-dev/rivet/@rivetkit/core@3289

@rivetkit/db

pnpm add https://pkg.pr.new/rivet-dev/rivet/@rivetkit/db@3289

@rivetkit/framework-base

pnpm add https://pkg.pr.new/rivet-dev/rivet/@rivetkit/framework-base@3289

@rivetkit/next-js

pnpm add https://pkg.pr.new/rivet-dev/rivet/@rivetkit/next-js@3289

@rivetkit/react

pnpm add https://pkg.pr.new/rivet-dev/rivet/@rivetkit/react@3289

rivetkit

pnpm add https://pkg.pr.new/rivet-dev/rivet/rivetkit@3289

@rivetkit/sql-loader

pnpm add https://pkg.pr.new/rivet-dev/rivet/@rivetkit/sql-loader@3289

@rivetkit/engine-runner

pnpm add https://pkg.pr.new/rivet-dev/rivet/@rivetkit/engine-runner@3289

@rivetkit/engine-runner-protocol

pnpm add https://pkg.pr.new/rivet-dev/rivet/@rivetkit/engine-runner-protocol@3289

commit: bba545b

@graphite-app
Copy link
Contributor

graphite-app bot commented Oct 30, 2025

Graphite Automations

"Test" took an action on this PR • (10/30/25)

1 assignee was added to this PR based on Kacper Wojciechowski's automation.

@claude
Copy link

claude bot commented Nov 4, 2025

Code Review

Thanks for this refactor @jog1t! This PR improves the inspector mode support and standardizes header usage. Overall the changes look good, but I have some observations and suggestions:

Strengths

  1. Good refactoring: Replacing hardcoded header strings with constants from driver-helpers/mod is a solid improvement that reduces duplication and prevents typos.

  2. Inspector mode support: The new useConnectionDetails() hook properly handles the inspector mode case by returning empty strings for namespace and engineToken.

  3. Complete CORS header list: Adding HEADER_ACTOR_QUERY to the allowed CORS headers completes the set, ensuring all three custom Rivet headers are properly handled.

🔍 Observations & Suggestions

1. Missing semicolon (frontend/src/components/actors/worker/actor-worker-context.tsx:55)

There's a missing semicolon after the useConnectionDetails function definition:

const useConnectionDetails = () => {
	return match(__APP_TYPE__)
		.with("inspector", () => {
			return {namespace: "", engineToken: ""};
		})
		.otherwise(() => {
			const provider = useEngineCompatDataProvider();
			return {namespace: provider.engineNamespace, engineToken: provider.engineToken};
		});
}  // ← Missing semicolon here

Should be:

};

2. Trailing whitespace (frontend/src/components/actors/worker/actor-worker-context.tsx:67)

Line 67 has trailing whitespace after useConnectionDetails();:

const {engineToken, namespace} = useConnectionDetails();
	  // ← Trailing whitespace here

3. Consider edge case handling

The inspector mode returns empty strings for namespace and engineToken. While this works, consider if there are any edge cases where consuming code might not handle empty strings gracefully. A quick review of how these values are used in the container.init() call (line 102-112) would be valuable.

4. Unused variable (frontend/src/components/actors/worker/actor-worker-context.tsx:65)

After the refactor, dataProvider is assigned but never used:

const dataProvider = useDataProvider();  // ← Not used anywhere
const {engineToken, namespace} = useConnectionDetails();

This appears to be leftover from the refactoring. Should this line be removed, or is dataProvider needed for some side effect?

5. Test coverage

No test files exist for this component. Consider adding tests to verify:

  • Inspector mode returns empty connection details
  • Non-inspector mode returns proper namespace and engineToken
  • The actor worker initializes correctly in both modes

6. Consistency check across codebase

Good news: I checked and there are no other places in the TypeScript codebase using hardcoded "x-rivet-actor" or "x-rivet-target" strings (outside of the constant definitions). However, there are still hardcoded strings in:

  • Rust codebases (which is expected, as they have their own constant definitions)
  • Test files and scripts (acceptable for test fixtures)

🎯 Required Changes

  1. Fix missing semicolon on line 55
  2. Remove trailing whitespace on line 67
  3. Remove or justify the unused dataProvider variable on line 65

💡 Recommended Changes

  1. Add unit tests for the new useConnectionDetails hook
  2. Verify edge case handling of empty strings in inspector mode

📝 Additional Notes

The change is well-aligned with the PR description and solves the stated problem. The code follows the existing patterns in the codebase (using ts-pattern for conditional logic based on __APP_TYPE__).

Once the required changes are addressed, this will be ready to merge!

@graphite-app
Copy link
Contributor

graphite-app bot commented Nov 7, 2025

Merge activity

  • Nov 7, 4:35 AM UTC: This pull request can not be added to the Graphite merge queue. Please try rebasing and resubmitting to merge when ready.
  • Nov 7, 4:35 AM UTC: Graphite disabled "merge when ready" on this PR due to: a merge conflict with the target branch; resolve the conflict and try again..

@jog1t jog1t force-pushed the 10-30-fix_inspector_allow_executing_rpcs_in_inspector branch from 775bd91 to d6de769 Compare November 10, 2025 16:33
@vercel vercel bot temporarily deployed to Preview – rivetkit-serverless November 10, 2025 16:33 Inactive
@jog1t jog1t merged commit e7a7fa7 into main Nov 10, 2025
13 of 14 checks passed
@jog1t jog1t deleted the 10-30-fix_inspector_allow_executing_rpcs_in_inspector branch November 10, 2025 16:34
@claude
Copy link

claude bot commented Nov 10, 2025

Code Review for PR #3289

Summary

This PR refactors the actor worker context to support inspector mode by introducing a new useConnectionDetails() hook. The change is well-structured and follows existing patterns in the codebase.

Positive Observations ✅

  1. Consistent Pattern Usage: The new useConnectionDetails() hook follows the same pattern as useInspectorToken() above it, using match(__APP_TYPE__) with .with("inspector") and .otherwise() branches.

  2. Code Organization: The refactoring improves separation of concerns by extracting connection detail logic into a dedicated hook.

  3. Inspector Mode Support: Properly handles inspector mode by returning empty strings for namespace and engineToken, which aligns with inspector's direct connection model.

  4. Maintains Existing Behavior: For non-inspector modes (cloud/engine), the hook still uses useEngineCompatDataProvider() to get the same connection details as before.

Issues and Concerns 🔴

1. Hook Call Order Violation (Critical)

Location: actor-worker-context.tsx:46-55

const useConnectionDetails = () => {
	return match(__APP_TYPE__)
		.with("inspector", () => {
			return {namespace: "", engineToken: ""};
		})
		.otherwise(() => {
			const provider = useEngineCompatDataProvider(); // ❌ Conditional hook call
			return {namespace: provider.engineNamespace, engineToken: provider.engineToken};
		});
}

Problem: This violates React's Rules of Hooks. The useEngineCompatDataProvider() hook is only called conditionally (inside .otherwise()), which means it won't be called in inspector mode. While this works at runtime due to __APP_TYPE__ being a compile-time constant, it's still technically incorrect and could confuse linters.

Solution: Call the hook unconditionally at the top level:

const useConnectionDetails = () => {
	const isInspector = __APP_TYPE__ === "inspector";
	const provider = isInspector ? null : useEngineCompatDataProvider();
	
	return match(__APP_TYPE__)
		.with("inspector", () => {
			return {namespace: "", engineToken: ""};
		})
		.otherwise(() => {
			return {namespace: provider!.engineNamespace, engineToken: provider!.engineToken};
		});
}

Or more simply:

const useConnectionDetails = () => {
	if (__APP_TYPE__ === "inspector") {
		return {namespace: "", engineToken: ""};
	}
	const provider = useEngineCompatDataProvider();
	return {namespace: provider.engineNamespace, engineToken: provider.engineToken};
}

2. Missing Formatting (Minor)

Location: actor-worker-context.tsx:67

const {engineToken, namespace} = useConnectionDetails();
// Missing blank line here
const {

Issue: There's a trailing blank line on line 67 that should be removed according to standard formatting practices.

3. Unused Import (Minor)

Location: actor-worker-context.tsx:65

The change updates line 65 to use useDataProvider() instead of useEngineCompatDataProvider(), but I don't see dataProvider being used anywhere after this change. Previously dataProvider was used to access engineToken and namespace, but now those come from useConnectionDetails().

Question: Is const dataProvider = useDataProvider() still needed on line 65, or should it be removed?

Recommendations 📋

  1. Fix the hook call order to comply with React's Rules of Hooks (see issue [SVC-2555] Set up issue templates #1 above)
  2. Remove the trailing blank line on line 67
  3. Verify if useDataProvider() is still needed on line 65, or if it can be removed
  4. Add tests: Consider adding tests for inspector mode to ensure connection details are properly handled
  5. Consider adding comments: A brief comment explaining why inspector mode uses empty strings would be helpful for future maintainers

Additional Notes

  • The PR description mentions changes to rivetkit headers and CORS configuration, but these changes are not visible in the diff. Were those changes in a different file or commit?
  • The PR title says "allow executing rpcs in inspector" but the diff only shows connection detail changes. Can you clarify how this enables RPC execution?

Approval Status

⚠️ Requesting Changes - Please address the hook call order violation before merging.


🤖 Generated with Claude Code

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.

3 participants