Skip to content

feat: add AgentController support to standalone Runner#5837

Open
jerryliang64 wants to merge 1 commit intonextfrom
feat/add-agent-controller-standalone
Open

feat: add AgentController support to standalone Runner#5837
jerryliang64 wants to merge 1 commit intonextfrom
feat/add-agent-controller-standalone

Conversation

@jerryliang64
Copy link
Contributor

@jerryliang64 jerryliang64 commented Mar 19, 2026

Summary

  • Register AgentControllerProto.createProto via EggPrototypeCreatorFactory in standalone Runner's initLoaderInstance()
  • Register AgentControllerObject.createObject via EggObjectFactory for object instantiation
  • Set logger for AgentControllerObject using the Runner's available logger
  • Add @eggjs/controller-plugin as a dependency of @eggjs/standalone

The standalone Runner bypasses egg plugin lifecycle (app.ts), so @AgentController decorator support requires manual registration of the prototype creator and object factory method — mirroring what @eggjs/controller-plugin/app.ts does in the plugin boot hook.

Test plan

  • Verify standalone Runner can resolve and instantiate classes decorated with @AgentController
  • Confirm existing standalone tests still pass

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • Chores

    • Added controller plugin dependency to the standalone package
  • Refactor

    • Enhanced runner initialization with controller integration support

The standalone Runner bypasses egg plugin lifecycle, so
AgentControllerProto/Object registration needs to be done
manually, similar to how it's done in the controller plugin's app.ts.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@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 introduces support for the @AgentController decorator within the standalone Runner environment. Since the standalone Runner bypasses the standard Egg plugin lifecycle, the necessary prototype creator and object factory methods for AgentController are now manually registered, mirroring the setup typically handled by the @eggjs/controller-plugin in a full Egg application. This change ensures that classes decorated with @AgentController can be properly resolved and instantiated in standalone contexts.

Highlights

  • Dependency Addition: Added @eggjs/controller-plugin as a dependency to @eggjs/standalone.
  • Prototype Creator Registration: Registered AgentControllerProto.createProto with EggPrototypeCreatorFactory in the standalone Runner.
  • Object Factory Registration: Registered AgentControllerObject.createObject with EggObjectFactory for AgentController object instantiation.
  • Logger Configuration: Configured the logger for AgentControllerObject using the Runner's available logger.
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.

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.

@cloudflare-workers-and-pages
Copy link

Deploying egg with  Cloudflare Pages  Cloudflare Pages

Latest commit: 6281827
Status:🚫  Build failed.

View logs

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 19, 2026

📝 Walkthrough

Walkthrough

The pull request extends the standalone tegg runner by adding the AgentController plugin as a dependency and integrating AgentController prototype creation, object instantiation, and logging into the runner's initialization sequence.

Changes

Cohort / File(s) Summary
Package Dependencies
tegg/standalone/standalone/package.json
Added @eggjs/controller-plugin as a workspace dependency.
Runner Initialization
tegg/standalone/standalone/src/Runner.ts
Registered AgentController integration points during initLoaderInstance: prototype creator mapping for AGENT_CONTROLLER_PROTO, egg object creation method for AgentControllerProto, and logger configuration via AgentControllerObject.setLogger().

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • akitaSummer

Poem

🐰 A plugin hops into the runner's embrace,
AgentController finds its rightful place,
Proto and object dance in harmony,
Bootstrap songs play wild and free! 🎵

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: add AgentController support to standalone Runner' directly and accurately describes the main change in the pull request, which adds AgentController support by registering proto/object creation in the standalone Runner.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ 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 feat/add-agent-controller-standalone
📝 Coding Plan
  • Generate coding plan for human review comments

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.

Tip

You can get early access to new features in CodeRabbit.

Enable the early_access setting to enable early access features such as new models, tools, and more.

@cloudflare-workers-and-pages
Copy link

Deploying egg-v3 with  Cloudflare Pages  Cloudflare Pages

Latest commit: 6281827
Status:🚫  Build failed.

View logs

Copy link
Contributor

@killagu killagu left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
tegg/standalone/standalone/src/Runner.ts (1)

310-353: ⚠️ Potential issue | 🟠 Major

Add cleanup for factory registrations in destroy() method.

The initLoaderInstance() method registers creators with EggPrototypeCreatorFactory (line 256) and object creation methods with EggObjectFactory (line 260), but these static factory registrations are never unregistered in destroy(). Since these factories maintain static Maps without clear/unregister methods, repeated Runner instantiation (particularly in test scenarios) will accumulate stale registrations.

The pattern should be consistent with how other lifecycle hooks are already cleaned up (DAL, AOP hooks at lines 325-347). Consider adding an unregisterPrototypeCreator() method to EggPrototypeCreatorFactory and corresponding cleanup for EggObjectFactory.eggObjectCreateMap to properly release these registrations.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tegg/standalone/standalone/src/Runner.ts` around lines 310 - 353, The
destroy() method fails to unregister static registrations made in
initLoaderInstance(): remove prototype creators and object creators registered
with EggPrototypeCreatorFactory and EggObjectFactory to avoid accumulating stale
entries; add methods such as
EggPrototypeCreatorFactory.unregisterPrototypeCreator(name) (or a clear entry
API) and an EggObjectFactory.unregisterEggObjectCreator(key) to remove the
specific entries the initLoaderInstance() added, and call them from
Runner.destroy() (matching the symbols initLoaderInstance, destroy,
EggPrototypeCreatorFactory, EggObjectFactory, and eggObjectCreateMap) so
repeated Runner instantiation does not leak static factory registrations.
🧹 Nitpick comments (2)
tegg/standalone/standalone/src/Runner.ts (2)

53-55: Add .js extension to ESM imports.

Per coding guidelines, all imports should use .js extensions for ESM files. Additionally, importing from internal lib/ paths creates coupling to implementation details—consider whether the controller plugin should export these from its main entry point instead.

♻️ Proposed fix
-import { AgentControllerObject } from '@eggjs/controller-plugin/lib/AgentControllerObject';
-import { AgentControllerProto } from '@eggjs/controller-plugin/lib/AgentControllerProto';
+import { AgentControllerObject } from '@eggjs/controller-plugin/lib/AgentControllerObject.js';
+import { AgentControllerProto } from '@eggjs/controller-plugin/lib/AgentControllerProto.js';

As per coding guidelines: "All imports should use .js extensions for ESM files"

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tegg/standalone/standalone/src/Runner.ts` around lines 53 - 55, The imports
in Runner.ts use internal lib paths without .js extensions—replace the two
imports of AgentControllerObject and AgentControllerProto to import them from
the package's public entry with a .js extension (or ask the controller plugin to
re-export these symbols) so ESM resolution and guidelines are satisfied; locate
the lines importing AgentControllerObject and AgentControllerProto and change
them to import the same exported symbols from the module's main entry point with
a trailing .js extension (or update the plugin to export
AgentControllerObject/AgentControllerProto) to remove the internal lib/
coupling.

256-259: Use the shared constant instead of a hardcoded string.

The controller plugin (tegg/plugin/controller/src/app.ts) imports and uses AGENT_CONTROLLER_PROTO_IMPL_TYPE from @eggjs/tegg-types. Using the same constant here ensures consistency and prevents subtle bugs if the value changes.

♻️ Proposed fix

Add the import:

import { AGENT_CONTROLLER_PROTO_IMPL_TYPE } from '@eggjs/tegg-types';

Then update the registration:

 EggPrototypeCreatorFactory.registerPrototypeCreator(
-  'AGENT_CONTROLLER_PROTO',
+  AGENT_CONTROLLER_PROTO_IMPL_TYPE,
   AgentControllerProto.createProto,
 );
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tegg/standalone/standalone/src/Runner.ts` around lines 256 - 259, Replace the
hardcoded registration key 'AGENT_CONTROLLER_PROTO' with the shared constant by
importing AGENT_CONTROLLER_PROTO_IMPL_TYPE from '@eggjs/tegg-types' and using it
in the call to EggPrototypeCreatorFactory.registerPrototypeCreator (which
currently passes AgentControllerProto.createProto); update the import list to
include AGENT_CONTROLLER_PROTO_IMPL_TYPE and change the first argument of
registerPrototypeCreator to that constant to ensure consistency with the
controller plugin.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tegg/standalone/standalone/src/Runner.ts`:
- Line 264: Replace the unsafe cast by ensuring the logger passed to
AgentControllerObject.setLogger has the correct EggLogger shape: import
EggLogger from the egg package and either (a) assert/convert the existing logger
variable (typed Logger from `@eggjs/tegg`) to EggLogger after mapping or wrapping
it with an adapter function that implements EggLogger methods, or (b) add a
small type-guard that verifies the logger implements the EggLogger interface and
choose a proper fallback (avoid using raw console); then call
AgentControllerObject.setLogger(with the adapted/typed EggLogger) instead of
using `as any`.

---

Outside diff comments:
In `@tegg/standalone/standalone/src/Runner.ts`:
- Around line 310-353: The destroy() method fails to unregister static
registrations made in initLoaderInstance(): remove prototype creators and object
creators registered with EggPrototypeCreatorFactory and EggObjectFactory to
avoid accumulating stale entries; add methods such as
EggPrototypeCreatorFactory.unregisterPrototypeCreator(name) (or a clear entry
API) and an EggObjectFactory.unregisterEggObjectCreator(key) to remove the
specific entries the initLoaderInstance() added, and call them from
Runner.destroy() (matching the symbols initLoaderInstance, destroy,
EggPrototypeCreatorFactory, EggObjectFactory, and eggObjectCreateMap) so
repeated Runner instantiation does not leak static factory registrations.

---

Nitpick comments:
In `@tegg/standalone/standalone/src/Runner.ts`:
- Around line 53-55: The imports in Runner.ts use internal lib paths without .js
extensions—replace the two imports of AgentControllerObject and
AgentControllerProto to import them from the package's public entry with a .js
extension (or ask the controller plugin to re-export these symbols) so ESM
resolution and guidelines are satisfied; locate the lines importing
AgentControllerObject and AgentControllerProto and change them to import the
same exported symbols from the module's main entry point with a trailing .js
extension (or update the plugin to export
AgentControllerObject/AgentControllerProto) to remove the internal lib/
coupling.
- Around line 256-259: Replace the hardcoded registration key
'AGENT_CONTROLLER_PROTO' with the shared constant by importing
AGENT_CONTROLLER_PROTO_IMPL_TYPE from '@eggjs/tegg-types' and using it in the
call to EggPrototypeCreatorFactory.registerPrototypeCreator (which currently
passes AgentControllerProto.createProto); update the import list to include
AGENT_CONTROLLER_PROTO_IMPL_TYPE and change the first argument of
registerPrototypeCreator to that constant to ensure consistency with the
controller plugin.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4dae786d-ddaf-4621-bcb0-859c6aba0b8b

📥 Commits

Reviewing files that changed from the base of the PR and between 1980cf1 and 6281827.

📒 Files selected for processing (2)
  • tegg/standalone/standalone/package.json
  • tegg/standalone/standalone/src/Runner.ts

AgentControllerProto,
AgentControllerObject.createObject,
);
AgentControllerObject.setLogger(logger as any);
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🌐 Web query:

What is the EggLogger interface in egg.js framework?

💡 Result:

The EggLogger interface in the Egg.js framework refers to the Logger class provided by the egg-logger module, which is the core logging system for Egg.js applications. It is not a formal TypeScript "interface" but the primary Logger class and its extensions used throughout Egg.js (e.g., app.logger, ctx.logger). Key aspects from official sources: - Logger is the base class from egg-logger that supports multiple Transports (e.g., file, console, custom). - Common methods: debug(msg), info(msg), warn(msg), error(err), supports printf-style formatting (%s, %j, %d). - Additional methods: set(name, transport), disable(name), enable(name), duplicate(target, options), redirect(level, logger). - Levels: NONE, DEBUG, INFO, WARN, ERROR. - Egg.js provides specialized loggers: appLogger (app-web.log), coreLogger (egg-web.log), errorLogger (common-error.log), agentLogger (egg-agent.log). - Custom loggers via config.customLogger. - Accessed as app.logger, ctx.logger, this.logger in controllers/services. Usage example: const Logger = require('egg-logger').Logger; const logger = new Logger; logger.set('console', new require('egg-logger').ConsoleTransport({ level: 'INFO' })); logger.info('Hello %s', 'world'); Egg.js loggers are instances of or wrap this Logger for enterprise features like multi-process safety, log rotation, and JSON output.

Citations:


🏁 Script executed:

# First, let's examine the Runner.ts file around line 264
fd -t f "Runner.ts" | xargs wc -l | head -20

Repository: eggjs/egg

Length of output: 172


🏁 Script executed:

# Get the specific file path
find . -name "Runner.ts" -path "*/tegg/standalone/*" -type f

Repository: eggjs/egg

Length of output: 95


🏁 Script executed:

# Read the Runner.ts file to understand the context
fd -t f "Runner.ts" -path "*/tegg/standalone/*" | head -1 | xargs cat -n | sed -n '240,280p'

Repository: eggjs/egg

Length of output: 221


🏁 Script executed:

# Find AgentControllerObject and its setLogger method
rg "AgentControllerObject" -A 20 -B 5 | head -50

Repository: eggjs/egg

Length of output: 3863


🏁 Script executed:

# Search for AgentControllerObject class definition and setLogger method
fd -t f "\.ts$" -path "*/tegg/*" | xargs rg "setLogger" -B 3 -A 3

Repository: eggjs/egg

Length of output: 1702


🏁 Script executed:

# Read the Runner.ts constructor to find the logger type definition
cat -n tegg/standalone/standalone/src/Runner.ts | sed -n '230,270p'

Repository: eggjs/egg

Length of output: 2184


🏁 Script executed:

# Find the imports and logger type in Runner.ts
cat -n tegg/standalone/standalone/src/Runner.ts | sed -n '1,50p'

Repository: eggjs/egg

Length of output: 1547


🏁 Script executed:

# Read AgentControllerObject.ts to find EggLogger import
cat -n tegg/plugin/controller/src/lib/AgentControllerObject.ts | sed -n '1,50p'

Repository: eggjs/egg

Length of output: 2161


🏁 Script executed:

# Check for Logger and EggLogger type definitions
rg "type Logger|interface Logger|class Logger" -B 2 -A 5 | head -80

Repository: eggjs/egg

Length of output: 5588


Remove the as any cast—use a compatible logger type or adjust the signature.

AgentControllerObject.setLogger() expects EggLogger from the egg package, but the logger variable is typed as Logger from @eggjs/tegg. The fallback to console further complicates this, since console is not compatible with EggLogger. The as any cast violates the no-any guideline and masks a real type mismatch.

Consider:

  1. Importing EggLogger and ensuring type compatibility before calling setLogger()
  2. Adding a type guard or adapter function to validate logger compatibility
  3. Adjusting setLogger() to accept a more general logger interface
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tegg/standalone/standalone/src/Runner.ts` at line 264, Replace the unsafe
cast by ensuring the logger passed to AgentControllerObject.setLogger has the
correct EggLogger shape: import EggLogger from the egg package and either (a)
assert/convert the existing logger variable (typed Logger from `@eggjs/tegg`) to
EggLogger after mapping or wrapping it with an adapter function that implements
EggLogger methods, or (b) add a small type-guard that verifies the logger
implements the EggLogger interface and choose a proper fallback (avoid using raw
console); then call AgentControllerObject.setLogger(with the adapted/typed
EggLogger) instead of using `as any`.

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 adds support for @AgentController in the standalone Runner by manually registering necessary components from @eggjs/controller-plugin. The changes are logical and follow the description. I have a few suggestions to improve maintainability and robustness by avoiding direct imports from internal lib directories, removing an as any type assertion, and replacing a magic string with a constant if one is available.

Comment on lines +53 to +54
import { AgentControllerObject } from '@eggjs/controller-plugin/lib/AgentControllerObject';
import { AgentControllerProto } from '@eggjs/controller-plugin/lib/AgentControllerProto';
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

Importing directly from the lib directory of @eggjs/controller-plugin is generally discouraged as it relies on internal implementation details that can change without notice, leading to potential breakages. It would be better to import these from the package's public API if they are exposed, for example: import { AgentControllerObject, AgentControllerProto } from '@eggjs/controller-plugin';. If they are not exported, it might be worth considering exposing them from the plugin package to create a stable API contract.


// AgentController support
EggPrototypeCreatorFactory.registerPrototypeCreator(
'AGENT_CONTROLLER_PROTO',
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

Using a magic string like 'AGENT_CONTROLLER_PROTO' is brittle. If this string is defined as a constant within the @eggjs/controller-plugin package (e.g., on AgentControllerProto itself as a static property), it would be safer to import and use that constant instead. This would prevent potential issues if the value changes in the source package.

AgentControllerProto,
AgentControllerObject.createObject,
);
AgentControllerObject.setLogger(logger as any);
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 use of as any here bypasses type safety. It suggests a type mismatch between the logger object (of type Logger from @eggjs/tegg) and the logger expected by AgentControllerObject.setLogger. Please investigate the type incompatibility and resolve it. If the logger types are structurally compatible but differ by name, you could use a more specific type assertion to the expected type instead of any, or create a simple adapter. Using any can hide bugs and makes the code harder to maintain.

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