Skip to content

Fix: export CODE_EXECUTION_RESPONSE_PROCESSOR from the @google/adk public API - #460

Open
AmaadMartin wants to merge 2 commits into
mainfrom
fix/export-code-execution-response-processor
Open

Fix: export CODE_EXECUTION_RESPONSE_PROCESSOR from the @google/adk public API#460
AmaadMartin wants to merge 2 commits into
mainfrom
fix/export-code-execution-response-processor

Conversation

@AmaadMartin

@AmaadMartin AmaadMartin commented Aug 1, 2026

Copy link
Copy Markdown
Owner

Please ensure you have read the contribution guide before creating a pull request.

Link to Issue or Description of Change

  1. Link to an existing issue (if applicable):
    N/A

  2. Or, if no issue exists, describe the change:

Problem: LlmAgent advertises a public responseProcessors?: BaseLlmResponseProcessor[] option (core/src/agents/llm_agent.ts:304), stores it (line 372), defaults it to [] (line 434), and iterates it during postprocess (line 910). Unlike requestProcessors, nothing is auto-installed into it, so an empty array means code-execution results are never turned into events.

The one implementation a user would put there — export const responseProcessor = new CodeExecutionResponseProcessor() in core/src/agents/processors/code_execution_request_processor.ts — is unreachable from the published package:

  • core/src/common.ts re-exports the sibling processors (CONTENT_REQUEST_PROCESSOR, INTERACTIONS_REQUEST_PROCESSOR) but had no entry for code_execution_request_processor.js, and core/src/index.ts only does export * from './common.js'.
  • core/package.json's exports map declares exactly one subpath, ".". There is no wildcard, so a consumer cannot deep-import the module either.

Net effect: a published consumer could not enable code-execution result handling at all. Both spellings fail:

import {responseProcessor} from '@google/adk';
// TS2305: Module '"@google/adk"' has no exported member 'responseProcessor'.

import {responseProcessor} from '@google/adk/agents/processors/code_execution_request_processor.js';
// TS2307: Cannot find module ... (exports map declares only ".")

The in-repo integration test hid the defect rather than exposing it. tests/integration/agents/agent_with_sandbox_executor_test.ts:9 used the deep specifier, which resolved only because vitest.config.ts aliases @google/adk to core/src. Under the alias it degrades to a plain relative path into the source tree, so the test passed while the shipped package was broken — a false-green.

Solution: Four edits, no behavioural change.

  1. core/src/agents/processors/code_execution_request_processor.ts — rename the singleton from the bare, ambiguous responseProcessor to CODE_EXECUTION_RESPONSE_PROCESSOR, mirroring CODE_EXECUTION_REQUEST_PROCESSOR declared in the same file and the repo's SCREAMING_SNAKE_CASE convention for processor singletons. Exporting responseProcessor verbatim would put an ambiguous bare noun into the top-level @google/adk namespace. The TSDoc block is kept and expanded, since the symbol is becoming public.
  2. core/src/common.ts — re-export CODE_EXECUTION_RESPONSE_PROCESSOR and CodeExecutionResponseProcessor in one statement, singleton first, matching the two sibling processor blocks exactly. Placed between the base_llm_processor.js and content_request_processor.js blocks so prettier-plugin-organize-imports ordering holds.
  3. core/src/index.tsno change. Its export * from './common.js' already propagates both symbols to the package root and to the TypeDoc entry point (typedoc.json uses ./core/src/index.ts as its sole entry point). A duplicate entry would create an export conflict and a TypeDoc warning.
  4. Tests retargeted at the package root (see Testing Plan).

Why rename rather than export the legacy name — this is technically a breaking change to a symbol nobody can consume, therefore effectively non-breaking: responseProcessor has never been reachable from @google/adk, neither via the root barrel nor via a subpath, so no published version ever exposed it under any spelling and no consumer's build can break. Renaming now, at the moment of first export, avoids being stuck with the awkward name. No deprecation alias is added, since that would ship two names for one object on day one.

Scope disciplineCODE_EXECUTION_REQUEST_PROCESSOR is deliberately not exported: LlmAgent installs it itself, so a consumer never needs to name it. core/package.json is not modified (adding a wildcard subpath would publish the entire internal module tree as public API). vitest.config.ts is not modified. No new dependency, no new file, no change to runPostProcessor or any code-execution logic.

Cross-language noteadk-python is not a reference here. There the equivalent class is private (_CodeExecutionResponseProcessor) and unexported, because Python's LlmAgent wires code execution through its flow rather than through a public responseProcessors option. adk-js intentionally diverges by exposing responseProcessors publicly; that divergence is exactly what creates the obligation to export the processor. Local convention wins over parity here because the divergence is in the observable public API by design.

Collision checkgh pr list --repo AmaadMartin/adk-js --state open --limit 300 reviewed; no open PR lands this change. Three PRs touch adjacent ground and are disclosed here:

Neither the naming nor the export was proposed by any of them.

Testing Plan

Please describe the tests that you ran to verify your changes. This is required for all PRs that are not small documentation or typo fixes.

Unit Tests:
[x] I have added or updated unit tests for my change.
[x] All unit tests pass locally.

One describe block appended to the existing core/test/agents/processors/code_execution_request_processor_test.ts (the five existing CodeExecutionResponseProcessor.runAsync cases are untouched and still pass). It imports CODE_EXECUTION_RESPONSE_PROCESSOR from '@google/adk' while keeping CodeExecutionResponseProcessor on the existing relative import, so the assertion compares the package-root symbol against the module symbol and fails if common.ts ever stops re-exporting it. toBeInstanceOf here is an identity assertion in a test, not runtime type detection in src/.

$ npx vitest run --project unit:core core/test/agents/processors/code_execution_request_processor_test.ts
 Test Files  1 passed (1)
      Tests  9 passed (9)

No new executable lines or branches are introduced (a rename plus a re-export), so new-line coverage is satisfied vacuously.

Integration tests:

$ npx vitest run --project integration tests/integration/agents/agent_with_sandbox_executor_test.ts
 Test Files  1 passed (1)
      Tests  1 passed (1)

CODE_EXECUTION_RESPONSE_PROCESSOR was also added to the ts_esm build_setup fixture. That is the only place in the repo that consumes @google/adk as a real installed package — its package.json declares "@google/adk": "file:../../../../core" and its build runs tsc with noEmitOnError, strict and preserveSymlinks, so type resolution goes through core/package.json's exports map into core/dist/types/index.d.ts, with no vitest alias in sight. Nothing else in the repo can catch an exports-map regression. Only ts_esm was modified; the other five fixtures are untouched (one fixture proves the path, each extra one costs another npm install in CI). The addition is behaviourally inert: the fixture agent has no codeExecutor, so runPostProcessor returns at its early-exit guard and the fixture's existing test-llm-model-response assertion is unaffected.

Mutation proof (each new/changed test proven able to fail). Mutation applied: revert only the core/src/common.ts hunk, keeping the rename.

  1. Unit test — AssertionError: expected undefined to be an instance of CodeExecutionResponseProcessor (Tests 1 failed | 8 passed (9)).
  2. Sandbox-executor integration test — AssertionError: expected 1 to be greater than or equal to 3 (Tests 1 failed (1)); with the processor gone the code block is never executed, so the execution-result event is never emitted.
  3. ts_esm consumer fixture, after npm run build --workspace=core:
    agent.ts:9:3 - error TS2305: Module '"@google/adk"' has no exported member 'CODE_EXECUTION_RESPONSE_PROCESSOR'.
    9   CODE_EXECUTION_RESPONSE_PROCESSOR,
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Found 1 error in agent.ts:9
    

The hunk was restored and all three re-verified green afterwards.

Independent confirmation of the defect and the fix. npm run ts:check is red on main in this checkout (281 errors, pre-existing; see the in-flight work in #370/#408/#414/#421). Diffing the error list before and after this change: no new error is introduced, the 12 pre-existing errors in the unit test file merely shift by one line, and exactly one error disappears —

- tests/integration/agents/agent_with_sandbox_executor_test.ts:9:33 - error TS2307:
  Cannot find module '@google/adk/agents/processors/code_execution_request_processor.js'
  or its corresponding type declarations.

That is the original defect, reported by tsc itself, and it is gone. Count: 281 -> 280.

Manual End-to-End (E2E) Tests:

The published-package surface, exercised outside the repo with no vitest alias and no test framework:

cd <adk-js>
npm install && npm run build
cd /tmp && mkdir adk-export-check && cd adk-export-check
npm init -y && npm pkg set type=module
npm install <adk-js>/core
node --input-type=module -e "import {CODE_EXECUTION_RESPONSE_PROCESSOR, CodeExecutionResponseProcessor} from '@google/adk'; console.assert(CODE_EXECUTION_RESPONSE_PROCESSOR instanceof CodeExecutionResponseProcessor); process.stdout.write('ok\n');"

Prints ok. Both built entry points were checked directly as well — core/dist/esm/index.js and core/dist/cjs/index.js each resolve the named export and the singleton is an instance of the exported class. Before the fix the same command fails with SyntaxError: The requested module '@google/adk' does not provide an export named 'CODE_EXECUTION_RESPONSE_PROCESSOR'.

Full gate, all run on the pushed commit:

Command Result
npm run build pass
npx vitest run --project unit:core core/test/agents/processors/code_execution_request_processor_test.ts 9 passed
npx vitest run --project integration tests/integration/agents/agent_with_sandbox_executor_test.ts 1 passed
npx vitest run --project integration tests/integration/build_setup/build_setup_test.ts not runnable in this sandbox — see below
npm run ts:check pre-existing red (281 on main); 280 with this change, no new errors
npm run lint clean
npm run format:check All matched files use Prettier code style!
npm run docs:check clean, zero TypeDoc warnings under --treatWarningsAsErrors

build_setup_test.ts performs a fresh npm install per fixture and fails in this sandbox with npm ERR! code E403 ... Forbidden - GET .../@a2a-js%2fsdk from the restricted registry proxy. This was verified to fail identically on a clean, unmodified tree, so it is an environment limitation, not a regression. To cover the gap the ts_esm fixture was type-checked directly against the built package instead — its two file: dependencies linked into node_modules/@google/, then tsc -p . with the fixture's own tsconfig.json (module: nodenext, noEmitOnError, strict, preserveSymlinks) — which resolves through core/package.json's exports map exactly as the CI fixture build does. It passes with the fix and fails with TS2305 without it, as quoted above. The scratch node_modules/dist were removed and are not in the diff.

npm run docs:check was the one most likely to surprise, since two new symbols enter the documented surface. Both already carry TSDoc, and every type in their public signatures (BaseLlmResponseProcessor, InvocationContext, LlmResponse, Event) was verified to be exported from common.ts already, so no export was added for them.

Postconditions verified by grep:

  • grep -rn "responseProcessor" --include="*.ts" . | grep -v node_modules — zero remaining imports of the old name; the only surviving hits are llm_agent.ts's unrelated responseProcessors option (plural) and the unit test's own local const responseProcessor.
  • grep -rn "from '@google/adk/" --include="*.ts" . | grep -v node_modulestests/integration is now free of deep imports. Three hits remain in core/test/sessions/vertex_ai_session_service_test.ts; those are explicitly out of scope for this task, are already owned by Fix: anchor the vitest workspace aliases so deep @google/adk/* specifiers fail at test time #380, and are unrelated to code execution.

Checklist

[x] I have read the CONTRIBUTING.md document.
[x] I have performed a self-review of my own code.
[x] I have commented my code, particularly in hard-to-understand areas.
[x] I have added tests that prove my fix is effective or that my feature works.
[x] New and existing unit tests pass locally with my changes.

CI note

The first validation run went green on ubuntu-latest but red on macos-latest, with windows-latest cancelled by the matrix's fail-fast (all of its own steps had already succeeded — 2681 tests passed, plus lint, format and docs). The single macOS failure was tests/integration/app_loader/app_loader_test.ts > AgentLoader discovery and loading integration > should discover apps vs agents across directories and standalone files, Error: Test timed out in 40000ms on a runner that spent 418s total with 380s of that in collection alone.

That test is unrelated to this change: it only scans tests/integration/app_loader/discovery, a different tree from the tests/integration/build_setup/ts_esm fixture touched here, and nothing in this diff affects agent discovery. Re-running the failed jobs with no code change turned all three matrix legs green, confirming a runner-slowness timeout flake rather than a regression.

Amaad Martin added 2 commits August 1, 2026 08:25
LlmAgent advertises a public responseProcessors option, but the only
processor that implements code-execution result handling was unreachable
from the published package: it was absent from common.ts / index.ts, and
core/package.json declares only the "." subpath, so a deep import is
rejected too. The advertised knob could not be used by a consumer of
npm install @google/adk.

Rename the singleton from the bare, ambiguous responseProcessor to
CODE_EXECUTION_RESPONSE_PROCESSOR, matching the repo's convention for
processor singletons (CONTENT_REQUEST_PROCESSOR,
INTERACTIONS_REQUEST_PROCESSOR), and re-export it with its class from
common.ts. index.ts already does 'export * from ./common.js', so both
symbols reach the package root and the TypeDoc entry point.
…umer

The sandbox-executor integration test deep-imported the processor, which
only resolved because vitest aliases @google/adk to core/src -- a
false-green that proved nothing about the shipped package. Retarget it at
the package root.

Add the symbol to the ts_esm build_setup fixture, the only place in the
repo that consumes @google/adk as an installed package (file:../core,
tsc --noEmitOnError through the exports map), so a regression in
core/package.json's exports map is caught too. The addition is inert: the
fixture agent has no codeExecutor, so runPostProcessor returns early.

Add one unit test asserting the package-root singleton is an instance of
the module's class.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant