Skip to content

Add type support to react useAgent().call#269

Merged
threepointone merged 10 commits intocloudflare:mainfrom
ruifigueira:typed-agents-call
May 12, 2025
Merged

Add type support to react useAgent().call#269
threepointone merged 10 commits intocloudflare:mainfrom
ruifigueira:typed-agents-call

Conversation

@ruifigueira
Copy link
Copy Markdown
Contributor

@ruifigueira ruifigueira commented May 11, 2025

Proposal to add type support to react useAgent() RPC calls. It can infer argument tyoes and ensure we pass all required values.

Usage example:

// server.ts
class MyAgent extends Agent<typeof env, {}> {
  @callable()
  sayHello(name?: string): string {
    return `Hello, ${name ?? 'World'}!`;
  }
  
  @callable()
  async perform(task: string, p1?: number): Promise<void> {
    // do something
  }

  // not annotated with @callable()
  nonRpc(): void {
  }
}

// index.tsx
import type { MyAgent } from './server.ts';

// ...

const agent = useAgent<{}, MyAgent>({ agent: 'my-agent' });
// return type is promisified
agent.call('sayHello') satisfies Promise<string>;

// @ts-expect-error first argument is not a string
await agent.call('sayHello', [1]);

await agent.call('perform', ['some task', 1]);
await agent.call('perform', ['another task']);
// @ts-expect-error requires parameters
await agent.call('perform');

// we cannot exclude it because typescript doesn't have a way
// to exclude based on decorators
await agent.call('nonRpc');

Intellisense in vscode:

image

Unfortunately, I didn't find a way to restrict calls to methods decorated with @callable(), so it will also suggest non-RPC methods.
Nevertheless, I excluded the ones declared in the base Agent class to ensure intellisense is as clean as possible.

If there are public methods to exclude, it's always possible to exclude the non-RPC ones with Omit<MyAgent, 'noRpc'>:

image

@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented May 11, 2025

🦋 Changeset detected

Latest commit: ac80e64

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages
Name Type
agents Patch
hono-agents Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@ruifigueira ruifigueira force-pushed the typed-agents-call branch 2 times, most recently from c18c9ec to b0261ac Compare May 11, 2025 21:53
Copy link
Copy Markdown
Contributor

@threepointone threepointone left a comment

Choose a reason for hiding this comment

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

this is great, thanks so much! a couple of questions

ruifigueira and others added 5 commits May 12, 2025 15:26
It was failing in windows with the following error:

```
Error: Failed to load url C:/worker.ts (resolved id: C:/worker.ts). Does the file exist?
 ❯ loadAndTransform ../../../../node_modules/vite/dist/node/chunks/dep-DBxKXgDP.js:35725:17
```
@threepointone
Copy link
Copy Markdown
Contributor

I fixed some lint checks, and rebased on top of previous changes. There are a bunch of explicit anys, which I try to keep out of the codebase. If possible, could you replace them? If not possible, it's fine to skip the check with a //biome-ignore statement

You can run npm run check at the root to see whether it would pass checks btw

@ruifigueira
Copy link
Copy Markdown
Contributor Author

I had to ignore those errors for now. Maybe in the future we can improve type checking for RPC and restrict types to the ones that are JSON compatible.

@threepointone
Copy link
Copy Markdown
Contributor

there's still a type failure in rpc.tsx, which shows that it fails if you don't have an explicit type param passed, can we make it so that's still acceptable? a default <Agent, State> value?

@ruifigueira
Copy link
Copy Markdown
Contributor Author

ruifigueira commented May 12, 2025

It seems that switching the order of overload functions fixes it.

@threepointone
Copy link
Copy Markdown
Contributor

This is awesome, thanks for iterating on it. I'll do one final review and test it out tomorrow and land it. Great PR!

@threepointone threepointone merged commit 0ac89c6 into cloudflare:main May 12, 2025
1 check passed
@threepointone threepointone mentioned this pull request May 12, 2025
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.

2 participants