Skip to content

feat: add agent-runtime package with @AgentController decorator#411

Merged
jerryliang64 merged 2 commits intomasterfrom
feat/agent-runtime
Mar 15, 2026
Merged

feat: add agent-runtime package with @AgentController decorator#411
jerryliang64 merged 2 commits intomasterfrom
feat/agent-runtime

Conversation

@jerryliang64
Copy link
Contributor

@jerryliang64 jerryliang64 commented Mar 13, 2026

Summary

  • Add core/agent-runtime package: AgentRuntime engine with sync/async/stream execution modes, OSSAgentStore for OSS-backed persistent storage, HttpSSEWriter for Server-Sent Events
  • Add @AgentController decorator in core/controller-decorator: auto-generates 7 HTTP routes (threads CRUD, runs CRUD with stream/sync/async), smart defaults pattern where users only implement execRun + createStore
  • Add AgentControllerProto + AgentControllerObject in plugin/controller: custom EggObject lifecycle with AgentRuntime installation between postInject and init hooks
  • Add type definitions in core/types/agent-runtime: AgentStore, AgentRuntime, messages, errors
  • Add core/tegg/agent.ts facade for convenient re-exports

Migrated from eggjs/egg next branch (commits ee3c309a, 1a4fb20c, 3e4afccb), adapted for tegg independent repo conventions (mocha tests, tsc build, package name mappings, default exports).

Test plan

  • tsc --noEmit passes for core/agent-runtime, core/controller-decorator, plugin/controller
  • core/agent-runtime: 101 tests passing
  • core/controller-decorator: 73 tests passing (45 new AgentController tests)
  • plugin/controller: 82 tests passing (19 new AgentControllerProto tests)

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Agent runtime with sync/async/stream execution modes, thread and run lifecycle management, cancellation, and observability.
    • Real-time Server-Sent Events streaming for run progress and deltas.
    • HTTP AgentController support for exposing agent endpoints.
    • OSS-backed persistent store and improved message/usage formats and error types for agent workflows.
  • Tests
    • Comprehensive unit and integration tests covering runtime, storage, SSE, conversion, and state transitions.

…nd @AgentController decorator

Migrated from eggjs/egg next branch (commits ee3c309a, 1a4fb20c, 3e4afccb).

- core/types/agent-runtime: type definitions for AgentStore, AgentRuntime, messages, errors
- core/agent-runtime: AgentRuntime with sync/async/stream execution, OSSAgentStore, HttpSSEWriter
- core/controller-decorator: @AgentController decorator with smart defaults pattern, AgentInfoUtil
- core/runtime: export EggObjectUtil for plugin use
- plugin/controller: AgentControllerProto + AgentControllerObject lifecycle integration
- core/tegg: agent.ts facade re-exporting decorator, runtime classes and types

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 significantly enhances the Egg.js Tegg framework by integrating a new agent runtime system. It provides developers with a standardized and streamlined way to build agent-based applications, offering built-in support for thread and run management, persistent storage, and real-time event streaming. The introduction of the @AgentController decorator and custom object lifecycle management aims to reduce boilerplate and improve developer experience when creating intelligent agents.

Highlights

  • New Agent Runtime Package: Introduced the core/agent-runtime package, providing a robust AgentRuntime engine with synchronous, asynchronous, and streaming execution modes. It includes an OSSAgentStore for persistent storage and an HttpSSEWriter for Server-Sent Events.
  • AgentController Decorator: Added the @AgentController decorator in core/controller-decorator, which automatically generates 7 standard HTTP routes for managing threads (CRUD) and runs (CRUD with stream/sync/async). This simplifies agent controller development by providing smart defaults, requiring users to primarily implement execRun and createStore.
  • Custom EggObject Lifecycle for Agent Controllers: Implemented AgentControllerProto and AgentControllerObject in plugin/controller to manage a custom EggObject lifecycle. This ensures AgentRuntime installation occurs between the postInject and init hooks, making the runtime ready when the user's init() method is called.
  • Comprehensive Type Definitions and Re-exports: Added extensive type definitions within core/types/agent-runtime for AgentStore, AgentRuntime, messages, and errors. A facade core/tegg/agent.ts was also introduced for convenient re-exports of agent-related modules and types.
Changelog
  • core/agent-runtime/index.ts
    • Exported core agent runtime components and types.
  • core/agent-runtime/package.json
    • Defined new package metadata and dependencies for @eggjs/agent-runtime.
  • core/agent-runtime/src/AgentRuntime.ts
    • Added the core AgentRuntime class, managing thread and run lifecycles with sync, async, and stream execution.
  • core/agent-runtime/src/AgentStoreUtils.ts
    • Added utility functions for generating unique IDs and Unix timestamps.
  • core/agent-runtime/src/HttpSSEWriter.ts
    • Added an HttpSSEWriter class for handling Server-Sent Events over HTTP.
  • core/agent-runtime/src/MessageConverter.ts
    • Added MessageConverter utilities for handling agent stream messages and content blocks.
  • core/agent-runtime/src/OSSAgentStore.ts
    • Added OSSAgentStore, an implementation of AgentStore backed by an object storage client (OSS, S3).
  • core/agent-runtime/src/OSSObjectStorageClient.ts
    • Added OSSObjectStorageClient for interacting with Alibaba Cloud OSS, supporting put, get, and append operations.
  • core/agent-runtime/src/RunBuilder.ts
    • Added RunBuilder to encapsulate and manage agent run state transitions.
  • core/agent-runtime/src/SSEWriter.ts
    • Added an abstract interface SSEWriter for writing Server-Sent Events.
  • core/agent-runtime/test/AgentRuntime.test.ts
    • Added comprehensive tests for the AgentRuntime class, covering thread, run, and cancellation functionalities.
  • core/agent-runtime/test/HttpSSEWriter.test.ts
    • Added tests for the HttpSSEWriter to ensure correct SSE event formatting and connection handling.
  • core/agent-runtime/test/MessageConverter.test.ts
    • Added tests for MessageConverter to verify message and content block conversions.
  • core/agent-runtime/test/OSSAgentStore.test.ts
    • Added tests for OSSAgentStore, including thread and run operations, and prefix handling.
  • core/agent-runtime/test/OSSObjectStorageClient.test.ts
    • Added tests for OSSObjectStorageClient, verifying put, get, and append behaviors.
  • core/agent-runtime/test/RunBuilder.test.ts
    • Added tests for RunBuilder to validate run state transitions and snapshots.
  • core/agent-runtime/test/helpers.ts
    • Added helper classes MapStorageClient and MapStorageClientWithoutAppend for in-memory testing of storage clients.
  • core/agent-runtime/tsconfig.json
    • Added TypeScript configuration for the agent-runtime package.
  • core/agent-runtime/tsconfig.pub.json
    • Added TypeScript publish configuration for the agent-runtime package.
  • core/controller-decorator/index.ts
    • Exported new agent-related decorators and utilities.
  • core/controller-decorator/src/decorator/agent/AgentController.ts
    • Added the @AgentController decorator, which auto-generates HTTP routes for agent operations.
  • core/controller-decorator/src/decorator/agent/AgentHandler.ts
    • Added the AgentHandler interface, defining the contract for agent controller implementations.
  • core/controller-decorator/src/decorator/agent/index.ts
    • Exported agent controller decorators and interfaces.
  • core/controller-decorator/src/util/AgentInfoUtil.ts
    • Added AgentInfoUtil for managing metadata related to agent controllers.
  • core/controller-decorator/test/AgentController.test.ts
    • Added tests for the @AgentController decorator, verifying metadata and route generation.
  • core/controller-decorator/test/fixtures/AgentFooController.ts
    • Added a fixture AgentFooController to demonstrate the usage of @AgentController.
  • core/runtime/index.ts
    • Exported EggObjectUtil from the runtime module.
  • core/tegg/agent.ts
    • Added a facade for re-exporting agent-related modules and types for convenience.
  • core/tegg/package.json
    • Added @eggjs/agent-runtime as a dependency.
  • core/types/agent-runtime/AgentMessage.ts
    • Added type definitions for agent messages, content blocks, and input messages.
  • core/types/agent-runtime/AgentRuntime.ts
    • Added type definitions for agent runtime objects, SSE events, and stream messages.
  • core/types/agent-runtime/AgentStore.ts
    • Added type definitions for agent store records, run statuses, and the AgentStore interface.
  • core/types/agent-runtime/ObjectStorageClient.ts
    • Added an interface for abstract object storage client operations.
  • core/types/agent-runtime/errors.ts
    • Added custom error classes: AgentNotFoundError, AgentConflictError, and InvalidRunStateTransitionError.
  • core/types/agent-runtime/index.ts
    • Exported all agent-runtime type definitions.
  • core/types/controller-decorator/MetadataKey.ts
    • Added new metadata keys for agent controllers and their prototype implementation type.
  • core/types/index.ts
    • Re-exported agent-runtime types.
  • plugin/controller/app.ts
    • Registered AgentControllerProto and AgentControllerObject with the Egg.js application lifecycle.
  • plugin/controller/lib/AgentControllerObject.ts
    • Added AgentControllerObject for custom EggObject lifecycle management of agent controllers, including AgentRuntime installation.
  • plugin/controller/lib/AgentControllerProto.ts
    • Added AgentControllerProto to wrap standard EggPrototypes, providing a distinct identity for agent controllers.
  • plugin/controller/package.json
    • Added @eggjs/agent-runtime as a dependency.
  • plugin/controller/test/lib/AgentControllerProto.test.ts
    • Added tests for AgentControllerProto to verify its delegation and creation logic.
Activity
  • tsc --noEmit passed for core/agent-runtime, core/controller-decorator, and plugin/controller.
  • core/agent-runtime tests passed with 101 assertions.
  • core/controller-decorator tests passed with 73 assertions, including 45 new AgentController tests.
  • plugin/controller tests passed with 82 assertions, including 19 new AgentControllerProto tests.
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.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

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.

@coderabbitai
Copy link

coderabbitai bot commented Mar 13, 2026

📝 Walkthrough

Walkthrough

Adds a new agent-runtime package with AgentRuntime orchestration (sync/async/stream/run streaming), OSS-backed storage and object client, SSE streaming utilities, run/message utilities, controller decorator integration, types, tests, and Egg.js prototype/object glue to expose agent controllers.

Changes

Cohort / File(s) Summary
Agent Runtime Core
core/agent-runtime/src/AgentRuntime.ts, core/agent-runtime/index.ts, core/agent-runtime/package.json
New package and barrel; implements AgentRuntime with sync/async/streamRun, task tracking, cancellation, run lifecycle APIs, and public exports.
Storage Layer
core/agent-runtime/src/OSSAgentStore.ts, core/agent-runtime/src/OSSObjectStorageClient.ts
New OSS-backed AgentStore and ObjectStorageClient with JSONL message layout, append optimization/caching, get-concat-put fallback, run/thread CRUD and updates.
SSE & HTTP Writer
core/agent-runtime/src/SSEWriter.ts, core/agent-runtime/src/HttpSSEWriter.ts
SSEWriter interface and HttpSSEWriter implementation (lazy headers, close callbacks, formatted SSE writes).
Message & Run Utilities
core/agent-runtime/src/MessageConverter.ts, core/agent-runtime/src/RunBuilder.ts, core/agent-runtime/src/AgentStoreUtils.ts
Converters between stream payloads and MessageObjects, RunBuilder state machine for transitions/snapshots, and ID/timestamp helpers.
Types & Errors
core/types/agent-runtime/*, core/types/controller-decorator/MetadataKey.ts, core/types/index.ts
New comprehensive typing: messages, runs, store interface, object storage client, constants, and error classes; added metadata keys for agent controllers; updated types barrel export.
Controller Decorator
core/controller-decorator/src/decorator/agent/*, core/controller-decorator/index.ts, core/controller-decorator/src/util/AgentInfoUtil.ts
AgentController decorator, AgentHandler interface, AgentInfoUtil for marking/querying controllers, and barrel exports.
Egg.js Integration
plugin/controller/lib/AgentControllerProto.ts, plugin/controller/lib/AgentControllerObject.ts, plugin/controller/app.ts, plugin/controller/package.json
AgentPrototype wrapper and EggObject implementation that installs AgentRuntime delegations, integrates createStore(), and adapts streamRun to HTTP SSE; app registers prototype creator.
Tests & Helpers
core/agent-runtime/test/*, plugin/controller/test/*, core/controller-decorator/test/*, core/controller-decorator/test/fixtures/*, core/agent-runtime/test/helpers.ts
Extensive unit/integration tests for runtime, storage client, run builder, message converter, SSE writer, OSS store, proto/object wrappers, and helper in-memory storage clients.
Build Configs
core/agent-runtime/tsconfig.json, core/agent-runtime/tsconfig.pub.json
TypeScript project configs for the new package.
Public API Barrels
core/tegg/agent.ts, core/runtime/index.ts
New public re-exports consolidating agent controller/runtime types and EggObjectUtil exposure.

Sequence Diagram(s)

sequenceDiagram
    rect rgba(200,200,255,0.5)
    participant Client
    participant AgentRuntime
    participant Store as AgentStore
    participant Executor
    participant SSEWriter
    end

    Client->>AgentRuntime: streamRun(input, writer)
    activate AgentRuntime
    AgentRuntime->>Store: createThread()
    Store-->>AgentRuntime: thread
    AgentRuntime->>SSEWriter: writeEvent(ThreadRunCreated, run)
    AgentRuntime->>Executor: execRun(input)
    Executor-->>AgentRuntime: AsyncGenerator<AgentStreamMessage>
    AgentRuntime->>SSEWriter: writeEvent(ThreadRunInProgress, run)
    loop consume stream messages
        Executor-->>AgentRuntime: AgentStreamMessage
        AgentRuntime->>SSEWriter: writeEvent(ThreadMessageDelta, delta)
        AgentRuntime->>Store: updateRun(output/usage)
    end
    AgentRuntime->>SSEWriter: writeEvent(ThreadRunCompleted, run)
    AgentRuntime->>SSEWriter: writeEvent(Done)
    AgentRuntime->>SSEWriter: end()
    deactivate AgentRuntime
Loading
sequenceDiagram
    rect rgba(200,255,200,0.5)
    participant App as EggJs App
    participant Proto as AgentControllerProto
    participant Object as AgentControllerObject
    participant Store as AgentStore
    participant Runtime as AgentRuntime
    end

    App->>Proto: createProto()
    Proto-->>App: AgentControllerProto
    App->>Object: createObject(proto, lifecycleCtx)
    Object->>Object: postConstruct / inject / init
    Object->>Store: createStore()
    Store-->>Object: store instance
    Object->>Runtime: AgentRuntime.create(executor, store, logger)
    Runtime-->>Object: runtime instance
    Object->>Object: delegate sync/async/stream run methods
    Object-->>App: ready object
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Suggested reviewers

  • killagu
  • akitaSummer

Poem

🐰 I hopped a thread and found a run,
Streams of tokens, shining sun,
OSS shelves held every line,
SSE sparks the live design,
Hooray — agents race and have fun! 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically summarizes the main change: introducing an agent-runtime package with the @AgentController decorator, which are the primary focus of this comprehensive PR.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/agent-runtime
📝 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.

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 introduces a significant new feature: a comprehensive agent runtime and an associated @AgentController decorator. The changes are well-structured across several new packages and files, with a clear separation of concerns between the core runtime logic, the storage abstraction, the user-facing decorator, and the framework integration glue. The implementation appears robust, with thorough handling of asynchronous operations, state transitions, and error conditions. The addition of extensive tests is also a great plus.

My review includes a couple of suggestions for improving maintainability by reducing code duplication in AgentRuntime.ts and AgentControllerObject.ts. These are not critical issues but potential refinements for the long-term health of the codebase.

Copy link

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

Note

Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.

🟡 Minor comments (17)
core/agent-runtime/package.json-22-28 (1)

22-28: ⚠️ Potential issue | 🟡 Minor

Simplify files array to avoid referencing non-existent files.

The files array includes "index.js" and "index.d.ts" at the root level, but these files don't exist in the repository. The compiled output goes to the dist/ directory (as specified by main and types). This pattern is inconsistent with other core packages, which use "dist/**/*.js" and "dist/**/*.d.ts" or similar patterns.

Remove the non-existent root-level file references:

Suggested diff
  "files": [
-   "dist",
-   "index.js",
-   "index.d.ts"
+   "dist"
  ],
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@core/agent-runtime/package.json` around lines 22 - 28, The package.json
"files" array incorrectly lists root-level "index.js" and "index.d.ts" which
don't exist; update the "files" entry to only include the compiled output under
dist (e.g., replace or remove the root-level "index.js" and "index.d.ts" and use
patterns like "dist/**/*.js" and "dist/**/*.d.ts") so it matches the "main":
"dist/index.js" and "types": "dist/index.d.ts" settings and other core packages'
conventions.
core/types/agent-runtime/errors.ts-7-7 (1)

7-7: ⚠️ Potential issue | 🟡 Minor

Remove redundant type annotations to fix ESLint errors.

The pipeline is failing because TypeScript can trivially infer the number type from the numeric literals. Remove the explicit type annotations.

🔧 Proposed fix
 export class AgentNotFoundError extends Error {
-  status: number = 404;
+  status = 404;
 export class AgentConflictError extends Error {
-  status: number = 409;
+  status = 409;
 export class InvalidRunStateTransitionError extends Error {
-  status: number = 409;
+  status = 409;

Also applies to: 20-20, 33-33

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

In `@core/types/agent-runtime/errors.ts` at line 7, Remove the redundant explicit
type annotations on the numeric literal `status` properties in this errors file:
locate each `status: number = 404;` (and the two other similar `status: number =
...;` declarations) and change them to just `status = 404;` (or the appropriate
numeric literal) so TypeScript infers the type and ESLint errors are resolved.
core/agent-runtime/test/OSSAgentStore.test.ts-70-70 (1)

70-70: ⚠️ Potential issue | 🟡 Minor

Normalize the empty-array spacing in these fixtures.

CI is already failing with array-bracket-spacing on these annotations: [] literals, so this file will not lint cleanly until they match the repo's configured bracket style.

Also applies to: 78-78, 96-96, 106-106, 125-125, 147-147, 157-157, 232-232

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

In `@core/agent-runtime/test/OSSAgentStore.test.ts` at line 70, Update the
empty-array bracket spacing for the test fixtures so they match the repo's
array-bracket-spacing rule: replace each occurrence of "annotations: []" with
"annotations: [ ]" in OSSAgentStore.test.ts (affecting the fixtures around the
"content" objects noted at the comment and the other occurrences at the listed
lines) so all empty-array literals use the normalized "[ ]" spacing.
core/agent-runtime/test/HttpSSEWriter.test.ts-54-57 (1)

54-57: ⚠️ Potential issue | 🟡 Minor

Use dot notation for connection.

CI is already failing on this assertion. headers.connection satisfies the lint rule without changing the test behavior.

♻️ Proposed fix
-    assert.equal(res.writtenHead.headers['connection'], 'keep-alive');
+    assert.equal(res.writtenHead.headers.connection, 'keep-alive');
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@core/agent-runtime/test/HttpSSEWriter.test.ts` around lines 54 - 57, The
assertion uses bracket notation for the 'connection' header which violates the
lint rule; update the test to use dot notation by accessing
res.writtenHead.headers.connection instead of
res.writtenHead.headers['connection'] (leave the other header assertions as-is)
so the assertion still checks 'keep-alive' but conforms to linting.
plugin/controller/test/lib/AgentControllerProto.test.ts-33-33 (1)

33-33: ⚠️ Potential issue | 🟡 Minor

Fix ESLint arrow-parens error.

The pipeline is failing due to parentheses around single function argument.

🔧 Proposed fix
-      return qs.every((q) => q.attribute === 'valid');
+      return qs.every(q => q.attribute === 'valid');
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugin/controller/test/lib/AgentControllerProto.test.ts` at line 33, The
ESLint error is caused by unnecessary parentheses around the single arrow
function parameter in the expression using Array.prototype.every; update the
expression qs.every((q) => q.attribute === 'valid') to remove the parentheses so
it reads qs.every(q => q.attribute === 'valid') (modify the occurrence in
AgentControllerProto.test where the every callback is defined) and re-run
lint/tests.
plugin/controller/test/lib/AgentControllerProto.test.ts-142-142 (1)

142-142: ⚠️ Potential issue | 🟡 Minor

Fix ESLint array-bracket-spacing error.

🔧 Proposed fix
-      assert.deepStrictEqual(result, { constructed: true, args: ['a', 'b'] });
+      assert.deepStrictEqual(result, { constructed: true, args: [ 'a', 'b' ] });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugin/controller/test/lib/AgentControllerProto.test.ts` at line 142, The
test assertion in AgentControllerProto.test.ts is tripping the ESLint
array-bracket-spacing rule; update the expected array in the
assert.deepStrictEqual call so its bracket spacing matches the project's ESLint
config (for example change args: ['a', 'b'] to args: [ 'a', 'b' ]), i.e. edit
the assert.deepStrictEqual(result, { constructed: true, args: ... }) line to use
the correct spacing inside the array brackets.
core/controller-decorator/test/AgentController.test.ts-108-152 (1)

108-152: ⚠️ Potential issue | 🟡 Minor

Fix ESLint formatting errors flagged by CI.

Multiple lines have ESLint errors for array-bracket-spacing (spaces required after [ and before ]). The pipeline is failing due to these formatting issues.

🔧 Proposed fix for array-bracket-spacing
-      const methods = ['createThread', 'getThread', 'asyncRun', 'streamRun', 'syncRun', 'getRun', 'cancelRun'];
+      const methods = [ 'createThread', 'getThread', 'asyncRun', 'streamRun', 'syncRun', 'getRun', 'cancelRun' ];

Apply similar spacing fixes to lines 134, 147, 151, 152, 182, 187, 192, 197, 202, 207, and 210.

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

In `@core/controller-decorator/test/AgentController.test.ts` around lines 108 -
152, The test has ESLint array-bracket-spacing failures; update the array
literals (e.g., methods, routeMethods, and stubMethods args arrays such as
['createThread'], ['thread_1'], [{ input: { messages: [] } }], etc.) to include
a space after '[' and before ']' where required so they follow
"array-bracket-spacing": "always" (make them like [ 'createThread' ], [
'thread_1' ], [ { input: { messages: [] } } ]). Locate occurrences in the
AgentFooController test blocks (variables named methods, routeMethods,
stubMethods and the args arrays inside the stubMethods entries) and fix spacing
consistently across all listed arrays flagged by CI.
core/agent-runtime/test/OSSObjectStorageClient.test.ts-72-72 (1)

72-72: ⚠️ Potential issue | 🟡 Minor

Fix ESLint array-bracket-spacing error.

🔧 Proposed fix
-      const [key, body] = mockOSS.put.mock.calls[0];
+      const [ key, body ] = mockOSS.put.mock.calls[0];
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@core/agent-runtime/test/OSSObjectStorageClient.test.ts` at line 72, Add an
ESLint rule override for the failing line: prepend the destructuring of
mockOSS.put.mock.calls[0] with a single-line ESLint disable for
array-bracket-spacing (e.g. add "// eslint-disable-next-line
array-bracket-spacing") immediately above the line containing "const [key, body]
= mockOSS.put.mock.calls[0];" so the test compiles without changing semantics or
surrounding code; keep the existing variable names (key, body) and the mock call
reference.
core/controller-decorator/src/decorator/agent/AgentController.ts-30-43 (1)

30-43: ⚠️ Potential issue | 🟡 Minor

Fix unused parameter _arg flagged by ESLint.

The pipeline is failing because _arg is defined but never used. Since the underscore prefix convention isn't sufficient for this ESLint config, either use void or add a directive.

🔧 Proposed fix using void expression
   if (hasParam) {
-    fn = async function (_arg: unknown) {
+    fn = async function (arg: unknown) {
+      void arg; // Unused but required for function.length === 1
       throw new Error(`${methodName} not implemented`);
     };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@core/controller-decorator/src/decorator/agent/AgentController.ts` around
lines 30 - 43, The async stub created by createNotImplemented has an unused
parameter _arg which ESLint flags; update the branch that creates the
param-taking stub (inside createNotImplemented) to explicitly mark the parameter
as used (e.g., add a void usage like "void _arg;" as the first statement) so the
linter stops complaining while preserving the async signature, then keep calling
AgentInfoUtil.setNotImplemented(fn) and return fn unchanged.
core/controller-decorator/test/AgentController.test.ts-174-208 (1)

174-208: ⚠️ Potential issue | 🟡 Minor

Fix ESLint arrow-parens errors.

The arrow functions with single parameters should not have parentheses per the project's ESLint configuration.

🔧 Proposed fix for arrow-parens
-      const createThread = meta.methods.find((m) => m.name === 'createThread')!;
+      const createThread = meta.methods.find(m => m.name === 'createThread')!;

Apply similar fixes to lines 179, 189, 199, and 208.

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

In `@core/controller-decorator/test/AgentController.test.ts` around lines 174 -
208, ESLint is flagging unnecessary parentheses around single-parameter arrow
functions in the test; update the arrow callbacks used with meta.methods.find so
they use the concise form (e.g., change (m) => m.name === 'createThread' to m =>
m.name === 'createThread') for each occurrence referenced by the test
(createThread, getThread, asyncRun, streamRun, syncRun, getRun, cancelRun) and
any other single-parameter find callbacks mentioned in the comment.
core/agent-runtime/src/MessageConverter.ts-23-27 (1)

23-27: ⚠️ Potential issue | 🟡 Minor

Fix arrow-parens lint errors.

The pipeline is failing due to parentheses around single function arguments. The linter expects no parentheses for single arrow function parameters.

🔧 Proposed fix
     if (Array.isArray(content)) {
       return content
-        .filter((part) => part.type === ContentBlockType.Text)
-        .map((part) => ({ type: ContentBlockType.Text, text: { value: part.text, annotations: [] } }));
+        .filter(part => part.type === ContentBlockType.Text)
+        .map(part => ({ type: ContentBlockType.Text, text: { value: part.text, annotations: [] } }));
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@core/agent-runtime/src/MessageConverter.ts` around lines 23 - 27, The lint
failure is caused by unnecessary parentheses around single arrow function
parameters in the array handling inside MessageConverter; update the arrow
functions used in the filter and map (where ContentBlockType.Text and the
parameter name part are referenced) to use unparenthesized single-parameter
syntax (e.g., change (part) => ... to part => ...) so the linter rule for
arrow-parens is satisfied.
plugin/controller/lib/AgentControllerObject.ts-202-203 (1)

202-203: ⚠️ Potential issue | 🟡 Minor

Fix dot-notation lint error.

The pipeline suggests using dot notation instead of bracket notation.

🔧 Proposed fix
-    const streamRunFn = instance['streamRun'];
+    const streamRunFn = instance.streamRun;

Also apply to line 237:

-      instance['streamRun'] = async (input: CreateRunInput): Promise<void> => {
+      instance.streamRun = async (input: CreateRunInput): Promise<void> => {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugin/controller/lib/AgentControllerObject.ts` around lines 202 - 203,
Replace bracket-property access with dot notation: change uses of
instance['streamRun'] to instance.streamRun when assigning streamRunFn and
anywhere else (e.g., the second occurrence around the block at line ~237).
Update the checks that create streamRunIsStub to reference streamRunFn derived
from instance.streamRun and keep the existing type/function check using typeof
and AgentInfoUtil.isNotImplemented(streamRunFn).
plugin/controller/lib/AgentControllerObject.ts-101-122 (1)

101-122: ⚠️ Potential issue | 🟡 Minor

Fix arrow-parens lint error.

The pipeline is failing due to parentheses around the single function argument.

🔧 Proposed fix
       await Promise.all(
-        this.proto.injectObjects.map(async (injectObject) => {
+        this.proto.injectObjects.map(async injectObject => {
           const proto = injectObject.proto;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugin/controller/lib/AgentControllerObject.ts` around lines 101 - 122, The
lint failure is caused by parentheses around the single arrow parameter in the
map callback; update the Promise.all injection step in AgentControllerObject
(the this.proto.injectObjects.map callback) to use a parameter without
parentheses (change async (injectObject) => to async injectObject =>) so the
arrow-parens rule is satisfied while keeping the function body unchanged; ensure
no other logic in the callback (loadUnit lookup, initType check,
EggContainerFactory.getOrCreateEggObject call, and this.injectProperty calls) is
modified.
core/agent-runtime/test/AgentRuntime.test.ts-59-79 (1)

59-79: ⚠️ Potential issue | 🟡 Minor

Fix generator-star-spacing lint errors.

The pipeline is failing due to spacing around the * in generator functions. This affects multiple generator function definitions in this file.

🔧 Proposed fix for generator spacing
-function createSlowExecRun(chunks: AgentStreamMessage[], onYielded?: () => void): AgentExecutor['execRun'] {
-  return async function* (_input: CreateRunInput, signal?: AbortSignal): AsyncGenerator<AgentStreamMessage> {
+function createSlowExecRun(chunks: AgentStreamMessage[], onYielded?: () => void): AgentExecutor['execRun'] {
+  return async function*(_input: CreateRunInput, signal?: AbortSignal): AsyncGenerator<AgentStreamMessage> {

Apply similar spacing fixes to all generator functions in the file (lines 85, 106, 241, 365, 401).

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

In `@core/agent-runtime/test/AgentRuntime.test.ts` around lines 59 - 79, Fix the
generator-star-spacing lint errors by normalizing the spacing around the '*' for
all generator functions in this test file: update the inner generator in
createSlowExecRun (the "async function*" declaration returned) and the other
generator function definitions referenced in the review so they use the
project's ESLint style (no space before '*' and a single space after it, e.g.
"function* name()" or "async function* ()" as appropriate); apply the same
change to every generator declaration/expression in the file so the linter stops
failing.
core/agent-runtime/src/MessageConverter.ts-49-55 (1)

49-55: ⚠️ Potential issue | 🟡 Minor

Fix indentation lint errors.

The return type declaration has incorrect indentation per the pipeline failure.

🔧 Proposed fix
   static extractFromStreamMessages(
     messages: AgentStreamMessage[],
     runId?: string,
-  ): {
-    output: MessageObject[];
-    usage?: RunUsage;
-  } {
+  ): { output: MessageObject[]; usage?: RunUsage } {

Or keep multiline but with correct indentation:

   static extractFromStreamMessages(
     messages: AgentStreamMessage[],
     runId?: string,
-  ): {
-    output: MessageObject[];
-    usage?: RunUsage;
-  } {
+  ): {
+      output: MessageObject[];
+      usage?: RunUsage;
+    } {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@core/agent-runtime/src/MessageConverter.ts` around lines 49 - 55, The return
type annotation for MessageConverter.extractFromStreamMessages is mis-indented
causing lint failures; reformat the method signature so the multiline return
type aligns with the opening parenthesis or collapse it to a single line—ensure
the returned type block "{ output: MessageObject[]; usage?: RunUsage; }" is
indented to match the function parameters and surrounding style used in this
file (adjust the signature in the static extractFromStreamMessages declaration).
core/agent-runtime/src/MessageConverter.ts-110-128 (1)

110-128: ⚠️ Potential issue | 🟡 Minor

Fix arrow-parens lint errors in toInputMessageObjects.

🔧 Proposed fix
   static toInputMessageObjects(messages: CreateRunInput['input']['messages'], threadId?: string): MessageObject[] {
     return messages
       .filter(
-        (m): m is typeof m & { role: Exclude<typeof m.role, typeof MessageRole.System> } =>
+        m => m is typeof m & { role: Exclude<typeof m.role, typeof MessageRole.System> } =>
           m.role !== MessageRole.System,
       )
-      .map((m) => ({
+      .map(m => ({
         id: newMsgId(),
         object: AgentObjectType.ThreadMessage,
         createdAt: nowUnix(),
         threadId,
         role: m.role,
         status: MessageStatus.Completed,
         content:
           typeof m.content === 'string'
             ? [{ type: ContentBlockType.Text, text: { value: m.content, annotations: [] } }]
-            : m.content.map((p) => ({ type: ContentBlockType.Text, text: { value: p.text, annotations: [] } })),
+            : m.content.map(p => ({ type: ContentBlockType.Text, text: { value: p.text, annotations: [] } })),
       }));
   }

Note: The type guard syntax (m): m is ... may need to keep parentheses - verify with your ESLint config.

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

In `@core/agent-runtime/src/MessageConverter.ts` around lines 110 - 128, The lint
errors come from inconsistent arrow-parens in toInputMessageObjects; keep the
type-guard/filter signature as-is ((m): m is ... => ...) but remove unnecessary
parentheses for single-arg arrow callbacks elsewhere: change .map((m) => ... )
to .map(m => ... ) and change m.content.map((p) => ...) to m.content.map(p =>
... ), keeping all types and fields (newMsgId, AgentObjectType.ThreadMessage,
MessageStatus.Completed, ContentBlockType.Text, MessageRole.System) unchanged.
core/agent-runtime/src/OSSAgentStore.ts-110-114 (1)

110-114: ⚠️ Potential issue | 🟡 Minor

Fix array-bracket-spacing lint error.

The pipeline is failing due to spacing in the array destructuring.

🔧 Proposed fix
-    const [metaData, messagesData] = await Promise.all([
+    const [ metaData, messagesData ] = await Promise.all([

Note: Verify the exact spacing rule in your ESLint config - some configs require spaces inside brackets, others don't.

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

In `@core/agent-runtime/src/OSSAgentStore.ts` around lines 110 - 114, The array
destructuring in getThread is failing lint due to bracket spacing; update the
destructuring of [metaData, messagesData] in the getThread method to match your
ESLint bracket-spacing rule (either add spaces inside the brackets like [
metaData, messagesData ] or remove them to be [metaData, messagesData ]/
[metaData, messagesData] as per config), and ensure the same spacing style is
used consistently for the Promise.all call that references
this.threadMetaKey(threadId) and this.threadMessagesKey(threadId).
🧹 Nitpick comments (4)
plugin/controller/test/lib/AgentControllerProto.test.ts (1)

169-187: Test for unregistered creator relies on internal implementation details.

Accessing (EggPrototypeCreatorFactory as any).creatorMap.delete() is fragile and may break if the internal implementation changes. This is acceptable for ensuring complete test coverage, but consider adding a comment noting this is testing an edge case through internal access.

📝 Suggested comment
     it('should throw when default creator is not registered', () => {
-      // Temporarily remove the creator
+      // Temporarily remove the creator by accessing internal map (fragile but needed for edge case)
       const saved = EggPrototypeCreatorFactory.getPrototypeCreator(DEFAULT_PROTO_IMPL_TYPE);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugin/controller/test/lib/AgentControllerProto.test.ts` around lines 169 -
187, The test manipulates EggPrototypeCreatorFactory internals by calling
(EggPrototypeCreatorFactory as any).creatorMap.delete(DEFAULT_PROTO_IMPL_TYPE),
which is fragile; add an explanatory comment above that line stating this
internal access is intentional to simulate the edge case of an unregistered
creator for coverage, referencing EggPrototypeCreatorFactory, creatorMap,
DEFAULT_PROTO_IMPL_TYPE and AgentControllerProto.createProto so future
maintainers understand why the implementation detail is touched and should not
be refactored away without updating the test.
core/agent-runtime/test/OSSObjectStorageClient.test.ts (1)

8-45: The mockFn helper contains dead code that creates confusion.

The original fn function (lines 11-18) and its methods (lines 19-23) are defined but never used - only wrappedFn is returned. This duplicated logic is confusing and increases maintenance burden.

♻️ Proposed fix: Remove dead code
 function mockFn() {
   const calls: any[][] = [];
   let nextResults: Array<{ type: 'resolve' | 'reject'; value: any }> = [];
-  const fn = (...args: any[]) => {
-    calls.push(args);
-    const result = nextResults.shift();
-    if (result) {
-      return result.type === 'resolve' ? Promise.resolve(result.value) : Promise.reject(result.value);
-    }
-    return Promise.resolve({});
-  };
-  fn.mock = { calls };
-  fn.mockResolvedValue = (val: any) => { nextResults = []; fn.mockResolvedValueOnce(val); nextResults = nextResults.map(() => ({ type: 'resolve' as const, value: val })); (fn as any)._defaultResult = { type: 'resolve', value: val }; return fn; };
-  fn.mockResolvedValueOnce = (val: any) => { nextResults.push({ type: 'resolve', value: val }); return fn; };
-  fn.mockRejectedValue = (val: any) => { (fn as any)._defaultResult = { type: 'reject', value: val }; return fn; };
-  fn.mockRejectedValueOnce = (val: any) => { nextResults.push({ type: 'reject', value: val }); return fn; };
 
-  // Override fn to use default result when nextResults is empty
   const wrappedFn: any = (...args: any[]) => {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@core/agent-runtime/test/OSSObjectStorageClient.test.ts` around lines 8 - 45,
The test helper mockFn contains dead/duplicated code: the inner fn (and its
methods mockResolvedValue/mockRejectedValue/etc.) is created but never used;
only wrappedFn is returned. Remove the unused fn block and its associated mock.*
assignments, and keep the wrappedFn implementation and its mock methods (using
nextResults and _defaultResult) intact; ensure references to nextResults and the
mock.* API remain on wrappedFn so existing tests using mockFn.mock,
mockResolvedValue, mockResolvedValueOnce, mockRejectedValue, and
mockRejectedValueOnce continue to work.
core/agent-runtime/src/OSSObjectStorageClient.ts (1)

72-91: Append retry handles single position mismatch but may fail with highly concurrent writers.

The append logic retries once on PositionNotEqualToLength, which handles the common case of a stale cache. However, if multiple concurrent writers are appending to the same object, the retry could also encounter a position mismatch and throw. This is likely acceptable for the intended single-writer use case, but worth documenting.

Consider adding a brief comment noting this limitation, or implementing a bounded retry loop if concurrent writers are expected:

       if (isOSSError(err, 'PositionNotEqualToLength')) {
+        // Single retry handles cache staleness; concurrent multi-writer scenarios
+        // may still fail if the object grows between HEAD and retry.
         const head = await this.client.head(key);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@core/agent-runtime/src/OSSObjectStorageClient.ts` around lines 72 - 91, The
append method (OSSObjectStorageClient.append) currently retries once on
PositionNotEqualToLength using appendPositions and a head() lookup, but can
still fail under high concurrency if multiple writers race; update the
implementation to either (a) add a short comment above append noting this
single-retry limitation and that concurrent writers may still cause failures,
referencing append, appendPositions, isOSSError, client.append and client.head,
or (b) implement a bounded retry loop: on PositionNotEqualToLength re-read the
current position via client.head and retry append up to N times with
exponential/backoff before failing, updating appendPositions on each success and
propagating the last error if retries exhausted—choose one approach and apply it
consistently in append.
core/controller-decorator/src/decorator/agent/AgentController.ts (1)

114-116: Stack depth 5 is fragile and may break with transpiler/bundler changes.

The hardcoded stack depth assumes a specific call stack structure through decorator application. This could silently produce incorrect file paths if the transpiler (tsc, esbuild, swc) or decorator transform changes.

Consider documenting why depth 5 is needed and under which build conditions it was verified:

     // Set file path for prototype
-    // Stack depth 5: [0] getCalleeFromStack → [1] decorator fn → [2-4] reflect/oxc runtime → [5] user source
+    // Stack depth 5: [0] getCalleeFromStack → [1] decorator fn → [2-4] reflect/oxc runtime → [5] user source
+    // Verified with tsc + experimentalDecorators. May need adjustment for other transpilers.
     PrototypeUtil.setFilePath(constructor, StackUtil.getCalleeFromStack(false, 5));
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@core/controller-decorator/src/decorator/agent/AgentController.ts` around
lines 114 - 116, The use of a hardcoded stack depth (5) in
PrototypeUtil.setFilePath(constructor, StackUtil.getCalleeFromStack(false, 5))
is fragile; change the call to derive depth dynamically or make it configurable
and add a robust fallback so transpiler/bundler stack shape changes don't
produce wrong file paths. Update AgentController.ts to (a) add a configurable
constant or optional parameter for stack depth used by
StackUtil.getCalleeFromStack, (b) implement a detection loop or heuristic in
StackUtil to scan stack frames for the first user-source-like path and return
that index if found, and (c) keep a documented fallback value (previously 5) and
a comment explaining why that fallback was chosen and in which build
environments it was validated; reference PrototypeUtil.setFilePath,
StackUtil.getCalleeFromStack and the constructor to locate the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@core/agent-runtime/src/AgentRuntime.ts`:
- Around line 131-140: The current sequence calls
this.store.appendMessages(threadId, ...) then this.store.updateRun(run.id,
rb.complete(...)), which can leave messages persisted while run update fails;
create and use an atomic store method (e.g., Store.completeRunWithMessages or
completeRunTransaction) that takes run id, completed run payload
(rb.complete(...)), and the message objects and performs both writes inside a
single transaction/atomic operation; replace the separate calls in AgentRuntime
(the locations using appendMessages + updateRun) with this new aggregate method
to ensure consistency and avoid duplicated/advanced thread history on retry.
- Around line 409-420: The current cancelRun() does a freshRun = await
this.store.getRun(runId) then unconditionally calls this.store.updateRun(runId,
rb.cancel()), which still allows a lost-update if another worker terminalizes
the run between the read and the write; change the final write to a
conditional/compare-and-set update that only applies the cancel transition if
the run is still in the expected pre-cancel state or version: use the store's
conditional update API (e.g., an expectedStatus/expectedVersion/ETag parameter
or a compareAndSet-like method) when calling updateRun so the update fails if
freshRun has changed, and on failure re-read freshRun and return its terminal
snapshot (using RunBuilder.fromRecord(freshRun).snapshot()) rather than
overwriting it.
- Around line 97-105: The local AbortController branches (the immediate
signal.aborted check and the signal 'abort' listener, plus any direct abort
paths in destroy()) currently short-circuit without persisting cancellation
state; instead, funnel these through the existing store-backed cancellation
logic by invoking the same cancellation path used by cancelRun() (e.g., call the
cancelRun/runCancellation helper with the current run id or otherwise persist
"cancelling/cancelled" to the run store) whenever abortController.abort() would
be triggered; update the abort listener and the immediate-aborted branch in
syncRun(), and the destroy() abort path to call that shared cancellation
function so stored runs are moved out of in_progress consistently.
- Around line 243-261: The runningTasks registration (creation of
resolveTask/taskPromise and this.runningTasks.set(...)) must be moved inside the
existing try block that has the finally which resolves resolveTask so the map
entry cannot leak if writer.writeEvent or this.store.updateRun throws; update
the code around the sequence that creates
msgId/MessageConverter.createStreamMessage and calls writer.writeEvent and
this.store.updateRun so that resolveTask and taskPromise are initialized and
this.runningTasks.set(run.id, { promise: taskPromise, abortController }) occurs
after entering the try and before any calls that can throw (e.g.,
writer.writeEvent, this.store.updateRun), and ensure the finally still calls
resolveTask(); apply the same change to the second identical block around the
stream-run handling (the other place that creates resolveTask/taskPromise and
sets runningTasks).

In `@core/agent-runtime/src/HttpSSEWriter.ts`:
- Around line 7-10: The close signal can be missed if a consumer calls onClose()
after _closed has already been set because the callback is only stored in
closeCallbacks and never invoked; update HttpSSEWriter so that onClose(callback)
checks _closed and if true immediately invokes the callback (instead of just
pushing it), and ensure the code path that sets _closed (e.g., the internal
close/res-close handler that iterates closeCallbacks) always drains and clears
closeCallbacks after invoking them; add a regression test that closes the
response first and then registers an onClose callback to verify it is called
synchronously/once.

In `@core/types/agent-runtime/index.ts`:
- Around line 1-5: The barrel index.ts is re-exporting message-model symbols
multiple times; pick a single source (preferably AgentMessage) and remove
duplicate wildcard re-exports: either (A) remove the intermediate re-exports of
message types from AgentRuntime.ts and AgentStore.ts so index.ts can continue
exporting everything via export * from './AgentMessage', or (B) keep
AgentRuntime.ts and AgentStore.ts but change core/types/agent-runtime/index.ts
to explicit named exports for the message types (ContentBlockType,
InputContentPart, TextContentBlock, MessageContentBlock, InputMessage,
MessageObject) by importing them from './AgentMessage' and exporting those names
directly; update imports accordingly so message-model symbols are only sourced
from AgentMessage.

---

Minor comments:
In `@core/agent-runtime/package.json`:
- Around line 22-28: The package.json "files" array incorrectly lists root-level
"index.js" and "index.d.ts" which don't exist; update the "files" entry to only
include the compiled output under dist (e.g., replace or remove the root-level
"index.js" and "index.d.ts" and use patterns like "dist/**/*.js" and
"dist/**/*.d.ts") so it matches the "main": "dist/index.js" and "types":
"dist/index.d.ts" settings and other core packages' conventions.

In `@core/agent-runtime/src/MessageConverter.ts`:
- Around line 23-27: The lint failure is caused by unnecessary parentheses
around single arrow function parameters in the array handling inside
MessageConverter; update the arrow functions used in the filter and map (where
ContentBlockType.Text and the parameter name part are referenced) to use
unparenthesized single-parameter syntax (e.g., change (part) => ... to part =>
...) so the linter rule for arrow-parens is satisfied.
- Around line 49-55: The return type annotation for
MessageConverter.extractFromStreamMessages is mis-indented causing lint
failures; reformat the method signature so the multiline return type aligns with
the opening parenthesis or collapse it to a single line—ensure the returned type
block "{ output: MessageObject[]; usage?: RunUsage; }" is indented to match the
function parameters and surrounding style used in this file (adjust the
signature in the static extractFromStreamMessages declaration).
- Around line 110-128: The lint errors come from inconsistent arrow-parens in
toInputMessageObjects; keep the type-guard/filter signature as-is ((m): m is ...
=> ...) but remove unnecessary parentheses for single-arg arrow callbacks
elsewhere: change .map((m) => ... ) to .map(m => ... ) and change
m.content.map((p) => ...) to m.content.map(p => ... ), keeping all types and
fields (newMsgId, AgentObjectType.ThreadMessage, MessageStatus.Completed,
ContentBlockType.Text, MessageRole.System) unchanged.

In `@core/agent-runtime/src/OSSAgentStore.ts`:
- Around line 110-114: The array destructuring in getThread is failing lint due
to bracket spacing; update the destructuring of [metaData, messagesData] in the
getThread method to match your ESLint bracket-spacing rule (either add spaces
inside the brackets like [ metaData, messagesData ] or remove them to be
[metaData, messagesData ]/ [metaData, messagesData] as per config), and ensure
the same spacing style is used consistently for the Promise.all call that
references this.threadMetaKey(threadId) and this.threadMessagesKey(threadId).

In `@core/agent-runtime/test/AgentRuntime.test.ts`:
- Around line 59-79: Fix the generator-star-spacing lint errors by normalizing
the spacing around the '*' for all generator functions in this test file: update
the inner generator in createSlowExecRun (the "async function*" declaration
returned) and the other generator function definitions referenced in the review
so they use the project's ESLint style (no space before '*' and a single space
after it, e.g. "function* name()" or "async function* ()" as appropriate); apply
the same change to every generator declaration/expression in the file so the
linter stops failing.

In `@core/agent-runtime/test/HttpSSEWriter.test.ts`:
- Around line 54-57: The assertion uses bracket notation for the 'connection'
header which violates the lint rule; update the test to use dot notation by
accessing res.writtenHead.headers.connection instead of
res.writtenHead.headers['connection'] (leave the other header assertions as-is)
so the assertion still checks 'keep-alive' but conforms to linting.

In `@core/agent-runtime/test/OSSAgentStore.test.ts`:
- Line 70: Update the empty-array bracket spacing for the test fixtures so they
match the repo's array-bracket-spacing rule: replace each occurrence of
"annotations: []" with "annotations: [ ]" in OSSAgentStore.test.ts (affecting
the fixtures around the "content" objects noted at the comment and the other
occurrences at the listed lines) so all empty-array literals use the normalized
"[ ]" spacing.

In `@core/agent-runtime/test/OSSObjectStorageClient.test.ts`:
- Line 72: Add an ESLint rule override for the failing line: prepend the
destructuring of mockOSS.put.mock.calls[0] with a single-line ESLint disable for
array-bracket-spacing (e.g. add "// eslint-disable-next-line
array-bracket-spacing") immediately above the line containing "const [key, body]
= mockOSS.put.mock.calls[0];" so the test compiles without changing semantics or
surrounding code; keep the existing variable names (key, body) and the mock call
reference.

In `@core/controller-decorator/src/decorator/agent/AgentController.ts`:
- Around line 30-43: The async stub created by createNotImplemented has an
unused parameter _arg which ESLint flags; update the branch that creates the
param-taking stub (inside createNotImplemented) to explicitly mark the parameter
as used (e.g., add a void usage like "void _arg;" as the first statement) so the
linter stops complaining while preserving the async signature, then keep calling
AgentInfoUtil.setNotImplemented(fn) and return fn unchanged.

In `@core/controller-decorator/test/AgentController.test.ts`:
- Around line 108-152: The test has ESLint array-bracket-spacing failures;
update the array literals (e.g., methods, routeMethods, and stubMethods args
arrays such as ['createThread'], ['thread_1'], [{ input: { messages: [] } }],
etc.) to include a space after '[' and before ']' where required so they follow
"array-bracket-spacing": "always" (make them like [ 'createThread' ], [
'thread_1' ], [ { input: { messages: [] } } ]). Locate occurrences in the
AgentFooController test blocks (variables named methods, routeMethods,
stubMethods and the args arrays inside the stubMethods entries) and fix spacing
consistently across all listed arrays flagged by CI.
- Around line 174-208: ESLint is flagging unnecessary parentheses around
single-parameter arrow functions in the test; update the arrow callbacks used
with meta.methods.find so they use the concise form (e.g., change (m) => m.name
=== 'createThread' to m => m.name === 'createThread') for each occurrence
referenced by the test (createThread, getThread, asyncRun, streamRun, syncRun,
getRun, cancelRun) and any other single-parameter find callbacks mentioned in
the comment.

In `@core/types/agent-runtime/errors.ts`:
- Line 7: Remove the redundant explicit type annotations on the numeric literal
`status` properties in this errors file: locate each `status: number = 404;`
(and the two other similar `status: number = ...;` declarations) and change them
to just `status = 404;` (or the appropriate numeric literal) so TypeScript
infers the type and ESLint errors are resolved.

In `@plugin/controller/lib/AgentControllerObject.ts`:
- Around line 202-203: Replace bracket-property access with dot notation: change
uses of instance['streamRun'] to instance.streamRun when assigning streamRunFn
and anywhere else (e.g., the second occurrence around the block at line ~237).
Update the checks that create streamRunIsStub to reference streamRunFn derived
from instance.streamRun and keep the existing type/function check using typeof
and AgentInfoUtil.isNotImplemented(streamRunFn).
- Around line 101-122: The lint failure is caused by parentheses around the
single arrow parameter in the map callback; update the Promise.all injection
step in AgentControllerObject (the this.proto.injectObjects.map callback) to use
a parameter without parentheses (change async (injectObject) => to async
injectObject =>) so the arrow-parens rule is satisfied while keeping the
function body unchanged; ensure no other logic in the callback (loadUnit lookup,
initType check, EggContainerFactory.getOrCreateEggObject call, and
this.injectProperty calls) is modified.

In `@plugin/controller/test/lib/AgentControllerProto.test.ts`:
- Line 33: The ESLint error is caused by unnecessary parentheses around the
single arrow function parameter in the expression using Array.prototype.every;
update the expression qs.every((q) => q.attribute === 'valid') to remove the
parentheses so it reads qs.every(q => q.attribute === 'valid') (modify the
occurrence in AgentControllerProto.test where the every callback is defined) and
re-run lint/tests.
- Line 142: The test assertion in AgentControllerProto.test.ts is tripping the
ESLint array-bracket-spacing rule; update the expected array in the
assert.deepStrictEqual call so its bracket spacing matches the project's ESLint
config (for example change args: ['a', 'b'] to args: [ 'a', 'b' ]), i.e. edit
the assert.deepStrictEqual(result, { constructed: true, args: ... }) line to use
the correct spacing inside the array brackets.

---

Nitpick comments:
In `@core/agent-runtime/src/OSSObjectStorageClient.ts`:
- Around line 72-91: The append method (OSSObjectStorageClient.append) currently
retries once on PositionNotEqualToLength using appendPositions and a head()
lookup, but can still fail under high concurrency if multiple writers race;
update the implementation to either (a) add a short comment above append noting
this single-retry limitation and that concurrent writers may still cause
failures, referencing append, appendPositions, isOSSError, client.append and
client.head, or (b) implement a bounded retry loop: on PositionNotEqualToLength
re-read the current position via client.head and retry append up to N times with
exponential/backoff before failing, updating appendPositions on each success and
propagating the last error if retries exhausted—choose one approach and apply it
consistently in append.

In `@core/agent-runtime/test/OSSObjectStorageClient.test.ts`:
- Around line 8-45: The test helper mockFn contains dead/duplicated code: the
inner fn (and its methods mockResolvedValue/mockRejectedValue/etc.) is created
but never used; only wrappedFn is returned. Remove the unused fn block and its
associated mock.* assignments, and keep the wrappedFn implementation and its
mock methods (using nextResults and _defaultResult) intact; ensure references to
nextResults and the mock.* API remain on wrappedFn so existing tests using
mockFn.mock, mockResolvedValue, mockResolvedValueOnce, mockRejectedValue, and
mockRejectedValueOnce continue to work.

In `@core/controller-decorator/src/decorator/agent/AgentController.ts`:
- Around line 114-116: The use of a hardcoded stack depth (5) in
PrototypeUtil.setFilePath(constructor, StackUtil.getCalleeFromStack(false, 5))
is fragile; change the call to derive depth dynamically or make it configurable
and add a robust fallback so transpiler/bundler stack shape changes don't
produce wrong file paths. Update AgentController.ts to (a) add a configurable
constant or optional parameter for stack depth used by
StackUtil.getCalleeFromStack, (b) implement a detection loop or heuristic in
StackUtil to scan stack frames for the first user-source-like path and return
that index if found, and (c) keep a documented fallback value (previously 5) and
a comment explaining why that fallback was chosen and in which build
environments it was validated; reference PrototypeUtil.setFilePath,
StackUtil.getCalleeFromStack and the constructor to locate the change.

In `@plugin/controller/test/lib/AgentControllerProto.test.ts`:
- Around line 169-187: The test manipulates EggPrototypeCreatorFactory internals
by calling (EggPrototypeCreatorFactory as
any).creatorMap.delete(DEFAULT_PROTO_IMPL_TYPE), which is fragile; add an
explanatory comment above that line stating this internal access is intentional
to simulate the edge case of an unregistered creator for coverage, referencing
EggPrototypeCreatorFactory, creatorMap, DEFAULT_PROTO_IMPL_TYPE and
AgentControllerProto.createProto so future maintainers understand why the
implementation detail is touched and should not be refactored away without
updating the test.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 94b50553-9e2a-4775-b2d4-6eae46cc0187

📥 Commits

Reviewing files that changed from the base of the PR and between c146105 and 119d075.

📒 Files selected for processing (42)
  • core/agent-runtime/index.ts
  • core/agent-runtime/package.json
  • core/agent-runtime/src/AgentRuntime.ts
  • core/agent-runtime/src/AgentStoreUtils.ts
  • core/agent-runtime/src/HttpSSEWriter.ts
  • core/agent-runtime/src/MessageConverter.ts
  • core/agent-runtime/src/OSSAgentStore.ts
  • core/agent-runtime/src/OSSObjectStorageClient.ts
  • core/agent-runtime/src/RunBuilder.ts
  • core/agent-runtime/src/SSEWriter.ts
  • core/agent-runtime/test/AgentRuntime.test.ts
  • core/agent-runtime/test/HttpSSEWriter.test.ts
  • core/agent-runtime/test/MessageConverter.test.ts
  • core/agent-runtime/test/OSSAgentStore.test.ts
  • core/agent-runtime/test/OSSObjectStorageClient.test.ts
  • core/agent-runtime/test/RunBuilder.test.ts
  • core/agent-runtime/test/helpers.ts
  • core/agent-runtime/tsconfig.json
  • core/agent-runtime/tsconfig.pub.json
  • core/controller-decorator/index.ts
  • core/controller-decorator/src/decorator/agent/AgentController.ts
  • core/controller-decorator/src/decorator/agent/AgentHandler.ts
  • core/controller-decorator/src/decorator/agent/index.ts
  • core/controller-decorator/src/util/AgentInfoUtil.ts
  • core/controller-decorator/test/AgentController.test.ts
  • core/controller-decorator/test/fixtures/AgentFooController.ts
  • core/runtime/index.ts
  • core/tegg/agent.ts
  • core/tegg/package.json
  • core/types/agent-runtime/AgentMessage.ts
  • core/types/agent-runtime/AgentRuntime.ts
  • core/types/agent-runtime/AgentStore.ts
  • core/types/agent-runtime/ObjectStorageClient.ts
  • core/types/agent-runtime/errors.ts
  • core/types/agent-runtime/index.ts
  • core/types/controller-decorator/MetadataKey.ts
  • core/types/index.ts
  • plugin/controller/app.ts
  • plugin/controller/lib/AgentControllerObject.ts
  • plugin/controller/lib/AgentControllerProto.ts
  • plugin/controller/package.json
  • plugin/controller/test/lib/AgentControllerProto.test.ts

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

Fix formatting and code style issues flagged by eslint-config-egg/typescript:
- arrow-parens, array-bracket-spacing, indent, dot-notation, generator-star-spacing
- Remove unused destructured variables in OSSAgentStore
- Remove duplicate type re-exports in agent-runtime types
- Add eslint-disable for intentional unused parameter in AgentController stub

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link

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

🧹 Nitpick comments (6)
plugin/controller/test/lib/AgentControllerProto.test.ts (2)

169-186: The test relies on internal implementation details.

Directly accessing creatorMap is fragile and could break if EggPrototypeCreatorFactory's internals change. This is acceptable for now since the factory lacks an unregister API, but consider documenting this coupling.

📝 Add explanatory comment
 it('should throw when default creator is not registered', () => {
-  // Temporarily remove the creator
+  // Temporarily remove the creator by accessing internal state.
+  // The factory lacks an unregister API, so direct map access is necessary.
   const saved = EggPrototypeCreatorFactory.getPrototypeCreator(DEFAULT_PROTO_IMPL_TYPE);
   EggPrototypeCreatorFactory.registerPrototypeCreator(DEFAULT_PROTO_IMPL_TYPE, undefined as any);
-  // Force the map entry to be deleted so getPrototypeCreator returns undefined
   (EggPrototypeCreatorFactory as any).creatorMap.delete(DEFAULT_PROTO_IMPL_TYPE);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugin/controller/test/lib/AgentControllerProto.test.ts` around lines 169 -
186, The test directly manipulates the internal creatorMap of
EggPrototypeCreatorFactory (deleting the DEFAULT_PROTO_IMPL_TYPE entry) which is
fragile; update the test by adding an explanatory comment above that
manipulation explaining why we access creatorMap (no public unregister API
exists) and that this is an intentional coupling for the test to simulate an
unregistered default creator; reference EggPrototypeCreatorFactory, creatorMap,
DEFAULT_PROTO_IMPL_TYPE and AgentControllerProto.createProto in the comment so
future maintainers know the rationale and can replace the approach if an
unregister API is added.

71-74: Consider moving shared fixtures into beforeEach for test isolation.

Creating delegate and proto at the describe scope is fine here since all tests are read-only. However, using beforeEach would provide stronger isolation guarantees and prevent subtle bugs if future tests modify state.

♻️ Suggested refactor using beforeEach
 describe('getter delegation', () => {
-  const delegate = createMockDelegate();
-  const proto = new AgentControllerProto(delegate);
+  let delegate: EggPrototype;
+  let proto: AgentControllerProto;
+
+  beforeEach(() => {
+    delegate = createMockDelegate();
+    proto = new AgentControllerProto(delegate);
+  });

   it('should delegate id', () => {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugin/controller/test/lib/AgentControllerProto.test.ts` around lines 71 -
74, The test-suite creates shared fixtures at describe scope (delegate =
createMockDelegate(), proto = new AgentControllerProto(delegate)), which can
lead to shared-state leaks; change those to be initialized in a beforeEach hook
instead: declare delegate and proto as mutable (let) at the describe level, then
assign delegate = createMockDelegate() and proto = new
AgentControllerProto(delegate) inside beforeEach so each test gets a fresh
instance; update any test references accordingly to use the new let-scoped
variables.
core/controller-decorator/src/decorator/agent/AgentController.ts (1)

115-117: Stack depth may be fragile across runtime environments.

The hardcoded depth of 5 depends on the specific call stack structure. Consider adding a comment noting this may need adjustment if the decorator invocation path changes, or consider a more robust approach like searching for the first non-internal frame.

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

In `@core/controller-decorator/src/decorator/agent/AgentController.ts` around
lines 115 - 117, The hardcoded stack depth used when calling
StackUtil.getCalleeFromStack(false, 5) to set the prototype file path is
fragile; update the code around PrototypeUtil.setFilePath(constructor,
StackUtil.getCalleeFromStack(false, 5)) to use a more robust approach (e.g.,
change StackUtil.getCalleeFromStack to accept a sentinel/search mode or add a
new helper that scans the call stack for the first non-internal/user frame) or
at minimum add a clear comment documenting that the depth 5 is dependent on
runtime and may need adjustment; ensure you reference and update the
StackUtil.getCalleeFromStack call and PrototypeUtil.setFilePath usage so the
constructor gets a reliable file path across environments.
core/agent-runtime/test/AgentRuntime.test.ts (2)

399-411: Same generator-without-yield pattern for error testing.

Similar to line 240, the generator at line 400-402 throws immediately without yielding. This is intentional but could benefit from a clarifying comment.

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

In `@core/agent-runtime/test/AgentRuntime.test.ts` around lines 399 - 411, The
test assigns executor.execRun to an async generator that immediately throws (no
yields) to simulate an execution failure; add a brief clarifying comment above
the executor.execRun assignment in the 'should emit failed event when execRun
throws' test explaining that the immediate throw-without-yield is intentional
for error-path testing (reference executor.execRun, runtime.streamRun,
MockSSEWriter and the expectation of AgentSSEEvent.ThreadRunFailed and
AgentSSEEvent.Done) so future readers won't interpret it as a mistake.

239-262: Generator without yield is intentional but could be cleaner.

The static analyzer flags that the generator at lines 240-242 never yields. This is intentional for testing error paths, but using async function* syntax for a function that only throws is slightly misleading.

Consider using a non-generator async function if the executor interface allows, or add a comment explaining the intentional behavior:

📝 Suggested comment
+      // Intentionally throws without yielding to test error handling path
       executor.execRun = async function* (): AsyncGenerator<AgentStreamMessage> {
         throw new Error('exec failed');
       };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@core/agent-runtime/test/AgentRuntime.test.ts` around lines 239 - 262, The
test assigns executor.execRun to an async generator that immediately throws but
never yields (execRun) which is flagged by static analysis; either replace the
generator with a plain async function that throws if the executor interface
accepts a non-generator, or keep the current async function* and add a concise
comment above the executor.execRun assignment explaining "intentional generator
that throws immediately to exercise error path; no yields required" so readers
and linters understand this is deliberate (reference symbols: executor.execRun
and runtime.syncRun, and the surrounding test that manipulates store.updateRun).
core/agent-runtime/src/RunBuilder.ts (1)

49-52: Consider the empty string fallback for threadId.

When run.threadId is undefined, fromRecord uses an empty string. This could cause issues if downstream code (e.g., SSE events, API responses) expects a valid thread_ prefixed ID.

If runs without a threadId are intentionally supported, consider documenting this behavior. Otherwise, this may produce confusing API responses with threadId: "".

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

In `@core/agent-runtime/src/RunBuilder.ts` around lines 49 - 52, The fallback to
an empty string in RunBuilder.fromRecord causes downstream code to receive an
invalid/empty threadId; update RunBuilder.fromRecord to produce a valid thread
ID when run.threadId is missing (or explicitly document/support empty IDs). For
example, inside RunBuilder.fromRecord use a deterministic fallback such as a
generated/thread-prefixed value (e.g., `thread_${run.id}`) or call a helper that
ensures the `threadId` format before passing it to RunBuilder.create; reference
RunBuilder.fromRecord, RunBuilder.create and RunRecord.threadId and ensure the
chosen fallback preserves any expected `thread_` prefix so downstream SSE/API
consumers get a valid threadId.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@plugin/controller/lib/AgentControllerObject.ts`:
- Around line 219-224: Before calling AgentRuntime.create, ensure
AgentControllerObject.logger is set by validating AgentControllerObject.logger
(and/or that setLogger() has been called); if it's undefined, throw an explicit
error with a clear message indicating the plugin misconfiguration rather than
letting AgentRuntime.create/constructor fail later. Locate the block that
constructs runtime (AgentRuntime.create with executor: this._obj, store, logger:
AgentControllerObject.logger) and add a precondition check that raises a
descriptive exception explaining that a logger must be configured via
setLogger() before creating the AgentRuntime.

In `@plugin/controller/test/lib/AgentControllerProto.test.ts`:
- Around line 155-159: The teardown in the after() hook only restores a previous
creator when originalCreator is truthy, leaving the mock registered if there was
no prior creator; update the after() hook to fully clean up the mock for
DEFAULT_PROTO_IMPL_TYPE by either calling the factory's unregister/remove method
(e.g.,
EggPrototypeCreatorFactory.unregisterPrototypeCreator(DEFAULT_PROTO_IMPL_TYPE))
or, if no unregister exists, explicitly reset the entry by calling
EggPrototypeCreatorFactory.registerPrototypeCreator(DEFAULT_PROTO_IMPL_TYPE,
undefined) when originalCreator is falsy; keep restoring the originalCreator
when it exists.

---

Nitpick comments:
In `@core/agent-runtime/src/RunBuilder.ts`:
- Around line 49-52: The fallback to an empty string in RunBuilder.fromRecord
causes downstream code to receive an invalid/empty threadId; update
RunBuilder.fromRecord to produce a valid thread ID when run.threadId is missing
(or explicitly document/support empty IDs). For example, inside
RunBuilder.fromRecord use a deterministic fallback such as a
generated/thread-prefixed value (e.g., `thread_${run.id}`) or call a helper that
ensures the `threadId` format before passing it to RunBuilder.create; reference
RunBuilder.fromRecord, RunBuilder.create and RunRecord.threadId and ensure the
chosen fallback preserves any expected `thread_` prefix so downstream SSE/API
consumers get a valid threadId.

In `@core/agent-runtime/test/AgentRuntime.test.ts`:
- Around line 399-411: The test assigns executor.execRun to an async generator
that immediately throws (no yields) to simulate an execution failure; add a
brief clarifying comment above the executor.execRun assignment in the 'should
emit failed event when execRun throws' test explaining that the immediate
throw-without-yield is intentional for error-path testing (reference
executor.execRun, runtime.streamRun, MockSSEWriter and the expectation of
AgentSSEEvent.ThreadRunFailed and AgentSSEEvent.Done) so future readers won't
interpret it as a mistake.
- Around line 239-262: The test assigns executor.execRun to an async generator
that immediately throws but never yields (execRun) which is flagged by static
analysis; either replace the generator with a plain async function that throws
if the executor interface accepts a non-generator, or keep the current async
function* and add a concise comment above the executor.execRun assignment
explaining "intentional generator that throws immediately to exercise error
path; no yields required" so readers and linters understand this is deliberate
(reference symbols: executor.execRun and runtime.syncRun, and the surrounding
test that manipulates store.updateRun).

In `@core/controller-decorator/src/decorator/agent/AgentController.ts`:
- Around line 115-117: The hardcoded stack depth used when calling
StackUtil.getCalleeFromStack(false, 5) to set the prototype file path is
fragile; update the code around PrototypeUtil.setFilePath(constructor,
StackUtil.getCalleeFromStack(false, 5)) to use a more robust approach (e.g.,
change StackUtil.getCalleeFromStack to accept a sentinel/search mode or add a
new helper that scans the call stack for the first non-internal/user frame) or
at minimum add a clear comment documenting that the depth 5 is dependent on
runtime and may need adjustment; ensure you reference and update the
StackUtil.getCalleeFromStack call and PrototypeUtil.setFilePath usage so the
constructor gets a reliable file path across environments.

In `@plugin/controller/test/lib/AgentControllerProto.test.ts`:
- Around line 169-186: The test directly manipulates the internal creatorMap of
EggPrototypeCreatorFactory (deleting the DEFAULT_PROTO_IMPL_TYPE entry) which is
fragile; update the test by adding an explanatory comment above that
manipulation explaining why we access creatorMap (no public unregister API
exists) and that this is an intentional coupling for the test to simulate an
unregistered default creator; reference EggPrototypeCreatorFactory, creatorMap,
DEFAULT_PROTO_IMPL_TYPE and AgentControllerProto.createProto in the comment so
future maintainers know the rationale and can replace the approach if an
unregister API is added.
- Around line 71-74: The test-suite creates shared fixtures at describe scope
(delegate = createMockDelegate(), proto = new AgentControllerProto(delegate)),
which can lead to shared-state leaks; change those to be initialized in a
beforeEach hook instead: declare delegate and proto as mutable (let) at the
describe level, then assign delegate = createMockDelegate() and proto = new
AgentControllerProto(delegate) inside beforeEach so each test gets a fresh
instance; update any test references accordingly to use the new let-scoped
variables.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1aa51de9-36fc-424e-8f82-b2167239ee79

📥 Commits

Reviewing files that changed from the base of the PR and between 119d075 and 8187cb3.

📒 Files selected for processing (16)
  • core/agent-runtime/src/AgentRuntime.ts
  • core/agent-runtime/src/MessageConverter.ts
  • core/agent-runtime/src/OSSAgentStore.ts
  • core/agent-runtime/src/RunBuilder.ts
  • core/agent-runtime/test/AgentRuntime.test.ts
  • core/agent-runtime/test/HttpSSEWriter.test.ts
  • core/agent-runtime/test/OSSAgentStore.test.ts
  • core/agent-runtime/test/OSSObjectStorageClient.test.ts
  • core/agent-runtime/test/RunBuilder.test.ts
  • core/controller-decorator/src/decorator/agent/AgentController.ts
  • core/controller-decorator/test/AgentController.test.ts
  • core/types/agent-runtime/AgentRuntime.ts
  • core/types/agent-runtime/AgentStore.ts
  • core/types/agent-runtime/errors.ts
  • plugin/controller/lib/AgentControllerObject.ts
  • plugin/controller/test/lib/AgentControllerProto.test.ts
🚧 Files skipped from review as they are similar to previous changes (6)
  • core/agent-runtime/test/HttpSSEWriter.test.ts
  • core/agent-runtime/test/OSSObjectStorageClient.test.ts
  • core/types/agent-runtime/errors.ts
  • core/agent-runtime/src/MessageConverter.ts
  • core/agent-runtime/test/RunBuilder.test.ts
  • core/types/agent-runtime/AgentRuntime.ts

@jerryliang64 jerryliang64 merged commit d4d0006 into master Mar 15, 2026
12 checks passed
@jerryliang64 jerryliang64 deleted the feat/agent-runtime branch March 15, 2026 14:05
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