Skip to content

fix(google-adk-agents): Node workflow loading, OTel composition, and telemetry replay-safety tests - #2276

Merged
xumaple merged 19 commits into
maplexu/google-adk-agents-contribfrom
adk-telemetry-replay-safety
Aug 12, 2026
Merged

fix(google-adk-agents): Node workflow loading, OTel composition, and telemetry replay-safety tests#2276
xumaple merged 19 commits into
maplexu/google-adk-agents-contribfrom
adk-telemetry-replay-safety

Conversation

@DABH

@DABH DABH commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Stacked on #2120 (targets its branch). Fixes the Node CI failures on that PR and makes ADK telemetry work — replay-safely — with the OpenTelemetry plugin.

What

  • Fix workflow loading on Node (all 8 Node CI jobs were red): evaluate polyfills before @google/genai regardless of user import order, and shim node:async_hooks and node:net (the latter needed by @google/adk 1.5.0, which fresh installs resolve).
  • Un-stub @opentelemetry/sdk-trace-base/resources so composing OpenTelemetryPlugin works instead of failing every workflow task; pin @opentelemetry/api to a single bundle copy so ADK spans export regardless of module evaluation order.
  • Replay-safety regression tests: with the OTel plugin composed and the workflow cache disabled, ADK's agent-loop spans (invocation, invoke_agent, call_llm — carrying the gen_ai.* token attributes) export exactly once per real operation across replays (asserted on retry-free histories); plus an isolation test pinning that sandbox spans can't leak to process-global providers ungated.
  • README telemetry section: spans are dropped by default; the OTel plugin is the replay-safe export path; cautions on callDuringReplay sinks and at-least-once retries.

Sibling fixes for the same issue class: temporalio/sdk-go#2514, temporalio/sdk-python#1710.

Testing

Full contrib suite green (59 tests, incl. previously-crashing E2E files), plus a run under REUSE_V8_CONTEXT=false. For CI context: the base branch's own tip run has red integration jobs with this contrib's suite hanging until timeout — the exact failure this PR fixes.

DABH added 5 commits July 31, 2026 18:23
The workflow bundle crashed at load on Node (Bun masked both crashes by
exposing web globals):

- @google/genai's web build dereferences ReadableStream at module load,
  before user imports could evaluate the polyfill barrel. Prepend the
  load-polyfills module to workflowInterceptorModules so it evaluates per
  workflow, before the user's workflow module, regardless of import order.
- @google/adk's utils/client_labels.js runs new AsyncLocalStorage() from
  node:async_hooks at module load. Redirect async_hooks to a shim
  re-exporting the sandbox-injected AsyncLocalStorage global.
@opentelemetry/sdk-trace-base and @opentelemetry/resources were aliased to
empty modules for the whole workflow bundle, so composing this plugin with
@temporalio/interceptors-opentelemetry failed every workflow task with
'tracing.BasicTracerProvider is not a constructor' — disabling the SDK's
replay-gated workflow span path (the only egress for ADK's gcp.vertex.agent
spans) for all workflows on the worker. Both packages are pure JS and
load-safe in the sandbox; keep them real.
Run a two-turn agent workflow composed with OpenTelemetryPlugin and the
workflow cache disabled (every workflow task replays the whole history):
the workflow must complete and export exactly one gcp.vertex.agent span
per real operation — replays add none. Also pin that without the
OpenTelemetry plugin, sandbox spans never reach a process-global tracer
provider.
- Fix README default-case wording: it's the absent tracer provider, not an
  impossibility of running an OTel SDK in the sandbox, that drops ADK spans.
- Add README caution that workflow task retries (unlike replays) re-emit
  spans, so export is at-least-once.
- Pin in plugin unit tests that the pure-JS OTel packages stay unstubbed and
  that load-polyfills is prepended to workflowInterceptorModules.
- Document the converter-modules-evaluate-first gap in the bundler recipe.
@DABH
DABH requested review from a team as code owners August 1, 2026 00:02
DABH added 4 commits August 1, 2026 03:35
Un-stubbing @opentelemetry/sdk-trace-base exposed @opentelemetry/core's
browser build, which dereferences the performance global at module load.
ESM workflow files dodge that chain through harmony-import pruning, but
tsc-compiled CommonJS workflow files — including the published lib/
artifacts and converter modules importing @google/adk — evaluate it
eagerly, failing every workflow task with 'ReferenceError: performance
is not defined'. Install a deterministic performance shim (mapped onto
the sandbox-patched Date.now, mirroring interceptors-opentelemetry's
workflow runtime shim) in load-polyfills, and add E2E regression tests
for the compiled-CJS workflow layout and the documented converter-module
workaround.
@google/adk pins an exact @opentelemetry/api version, so the Workflow
bundle can contain two api copies. ADK's telemetry/tracing.js caches
trace.getTracer() at module load; when a user interceptor or converter
module evaluates @google/adk before the OTel interceptor factories
register the sandbox tracer provider, that tracer binds the other copy's
never-delegated provider and every ADK span is silently dropped while
the interceptor's own spans keep exporting. Rewrite all bundle requests
for @opentelemetry/api to ADK's own resolution in the sandbox-compat
webpack plugin, pin the rewrite with a unit contract test, and add an
E2E test that evaluates ADK from a user workflowModules entry and
asserts exact span counts.
Move the converter-module workaround into the README's telemetry
cautions (the PR description already pointed there), note the polyfill
loader now includes the performance shim, document the single
@opentelemetry/api copy pinning, and extend the google-adk-agents
changelog entry with the replay-safe span-export composition.
A workflow task retry re-executes its segment and legitimately re-emits
spans through the replay-gated sink, so exact-count assertions could
flake on slow runners; degrade to a lower bound when the history shows
WorkflowTaskTimedOut/Failed events. Also make the performance-shim
comment precise about the interceptor package's unconditional shim.
@DABH
DABH force-pushed the adk-telemetry-replay-safety branch from becf512 to c38dfd4 Compare August 1, 2026 09:02
DABH added 5 commits August 4, 2026 14:10
Replace the sandbox-compat plugin's beforeResolve rewrite of
@opentelemetry/api with an exact-match resolve.alias entry in the
webpackConfigHook — the same declarative surface the Worker bundler
itself uses — and assert the config shape in the unit test instead of
driving a fake compiler through the plugin's tap.

Also export an empty interceptors factory from the polyfill loader so
its workflowInterceptorModules entry satisfies the documented
interceptor-module contract rather than relying on the runtime
skipping modules without one, and point the recipe docs at the
initRuntime evaluation-order contract.
Array-form resolve.alias resolves first-match-first, so prepend the
@opentelemetry/api pin instead of appending it, matching the object
branch where the pin is spread last. Cover the array branch in the
config-shape test and note the ADK BaseTool contract at the external
_getDeclaration call site.
Object-form resolve.alias entries also match in key insertion order, so a
user prefix-form '@opentelemetry/api' key spread before the pin used to
capture the bare specifier in object form while losing to the unshifted
pin in array form. Place the pin key first in the object branch so both
forms agree: the pin wins the bare specifier over any user entry, and a
user prefix-form entry still applies to subpath imports.
Mirror packages/test so REUSE_V8_CONTEXT=false runs every worker (and the
replayer) in per-workflow-VM mode, giving the polyfill loader and telemetry
gating coverage in both sandbox modes.
ADK 1.5.0 added tools/load_web_page.js on the barrel path, which parses
its blocked-CIDR tables at module load, calling net.isIP in the
process. With net aliased to an empty module (like the other disallowed
builtins), isIP is undefined and every workflow task fails at bundle
load: on a fresh install resolving the ^1.4.0 peer range, the
documented quick-start hangs in workflow-task retry with no usable
diagnostic.

Redirect net/node:net to a deterministic shim implementing
isIP/isIPv4/isIPv6 with Node's own address grammar (the
lib/internal/net.js regexes): pure string parsing, frozen in the bundle
so classification cannot drift across replay, and no socket surface. A
parity test pins the classifiers to node:net's across the addresses ADK
parses at load plus classification corners, and the test workflows
module mirrors ADK's top-level pattern so every E2E bundle in the suite
fails loudly if the shim regresses.

The devDependency stays at ^1.4.0: the workspace's minimumReleaseAge
(two weeks) blocks resolving 1.5.0 until 2026-08-13. The full suite was
additionally verified against a local @google/adk@1.5.0 install.
@DABH
DABH requested a balanced review from Copilot August 11, 2026 06:15

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Fixes Google ADK workflow loading and OpenTelemetry composition while adding replay-safety regression coverage.

Changes:

  • Adds deterministic sandbox shims and polyfill preloading.
  • Pins a single OpenTelemetry API copy and restores tracing packages.
  • Adds telemetry, CommonJS, replay, and network-shim tests plus documentation.

Reviewed changes

Copilot reviewed 15 out of 16 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
CHANGELOG.md Notes replay-safe ADK telemetry support.
pnpm-lock.yaml Locks added OpenTelemetry dependencies.
contrib/google-adk-agents/package.json Adds telemetry test dependencies.
contrib/google-adk-agents/README.md Documents telemetry configuration and cautions.
src/plugin.ts Adds shims, API aliasing, and polyfill preloading.
src/load-polyfills.ts Adds interceptor contract and performance shim.
src/activities.ts Clarifies ADK tool declaration usage.
src/__tests__/helpers.ts Supports both V8 context modes.
src/__tests__/workflows.ts Adds telemetry and network test workflows.
src/__tests__/telemetry.test.ts Tests span export and isolation.
src/__tests__/replay.test.ts Applies configured V8 reuse mode.
src/__tests__/plugin.test.ts Tests bundler configuration contracts.
src/__tests__/net-shim.test.ts Tests network shim parity and loading.
src/__tests__/compiled-cjs.test.ts Tests compiled CommonJS workflows.
src/__tests__/adk-first-interceptor.ts Exercises early ADK evaluation.
src/__tests__/adk-converter.ts Exercises converter polyfill workaround.
Files not reviewed (1)
  • pnpm-lock.yaml: Generated file

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread contrib/google-adk-agents/src/__tests__/telemetry.test.ts
Comment thread contrib/google-adk-agents/README.md Outdated
DABH added 5 commits August 11, 2026 01:24
A workflow task retry re-executes live and legitimately re-emits spans,
but downgrading the regression assertion to a lower bound would also let
a genuine replay over-count pass. Re-run the scenario on a fresh workflow
until the history is retry-free and keep the assertion exact, and qualify
the README's exactly-once wording accordingly.
The base merge glued the expanded google-adk-agents changelog entry to
neighbors that main's 1.22.0 release had moved into the released section,
duplicating it; keep the single expanded entry under Unreleased. Also
restore the base's deliberate removal of the unused @temporalio/client
devDependency and replace two any-casts with the file's typed-filter
pattern.
The linux-arm/macos-arm integration jobs run the full suite in 19-21
minutes and have repeatedly hit the 20-minute job timeout while green
(GitHub reports the timeout as cancelled). Windows already gets 30
minutes for the same reason.
A fully green linux-x64 leg now finishes past the 20-minute mark (the
earlier under-20 runs early-exited on a test failure), so the per-platform
split no longer holds; use the windows budget everywhere.
@xumaple
xumaple merged commit f858d95 into maplexu/google-adk-agents-contrib Aug 12, 2026
83 of 90 checks passed
@xumaple
xumaple deleted the adk-telemetry-replay-safety branch August 12, 2026 17:40
xumaple added a commit that referenced this pull request Aug 14, 2026
…2120)

* contrib: add @temporalio/google-adk-agents (draft)

Initial preliminary draft of the Google ADK agent integration:
plugin, model/MCP/tool workflow-side proxies, worker-side activities,
test doubles, and E2E tests. Builds, typechecks, and passes the test
suite; cleanup (lint, ava migration, packaging metadata, docs) to follow.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* contrib(google-adk-agents): clean up draft — ava tests, lint, packaging, code fixes

Convert tests vitest→ava, add eslint override, extend tsconfig base +
references, fill package.json metadata, fix README/comment inaccuracies,
warn on streaming without streamingTopic + adaptive-heartbeat the streaming
activity, and register in CODEOWNERS + root README.

* contrib(google-adk-agents): trim public API and reuse SDK ActivityOptions

Rename TemporalLlm->TemporalModel and TemporalMcpToolset->TemporalMcpToolSet
(with their *Options) to match the Python contrib, and trim the public barrel
to the constructs users actually touch -- demoting the activity-boundary wire
types and the internal tool classes (TemporalMcpTool, ActivityTool) to
internal.

Replace the bespoke TemporalActivityOptions with the SDK's ActivityOptions,
nested as `activity?:` consistently across the model, MCP, and activity-tool
options. Reduce @experimental to the public entry points and conform the
package to the repo prettier config.

* contrib(google-adk-agents): align model boundary behavior with Python contrib

Raise a non-retryable GoogleAdkStreamingTopicRequired error when streaming is
requested without a streamingTopic, instead of silently falling back to a
non-streaming call. Default the model and tool Activity start-to-close timeout
to 1 minute, and derive the default Activity summary from the ADK
`adk_agent_name` label. Adds E2E coverage for the streaming-without-topic
failure and the agent-name summary default.

* contrib(google-adk-agents): fix error classification, heartbeat leak, tool-not-found

- readStatus now also reads err.response?.status, so wrapped HTTP errors are
  classified by their real status instead of defaulting to retryable.
- Nest the streaming Activity's finally block so stopHeartbeat() always runs
  even if the stream's async-dispose throws (was leaking the heartbeat timer).
- MCP tool-not-found is now non-retryable; a tool absent from the server won't
  appear on a retry.

* contrib(google-adk-agents): trim comments to essential rationale

Condense plugin.ts's webpack-sandbox shim documentation down to the non-obvious
WHY (why a data: URI shim rather than alias->false, the node: scheme strip, the
determinism guarantee), cutting restatement and enumeration. Remove two
code-restating one-line comments. No code changes.

* contrib(google-adk-agents): update README for renames and streaming behavior

Rename TemporalLlm->TemporalModel and TemporalMcpToolset->TemporalMcpToolSet in
the docs, note that streamingTopic is required for SSE streaming (requesting it
without a topic throws GoogleAdkStreamingTopicRequired), and reflect the nested
activity options shape.

* contrib(google-adk-agents): build as CommonJS so the published artifact is consumable

Drop "type": "module" and add require/default export conditions (mirroring the
openai-agents sibling) so the package is require()-able from CommonJS and its
compiled lib bundles into a Workflow without the strict-ESM errors — a
require() threw `No "exports" main defined`, and the lib failed to bundle on
`import { builtinModules } from 'node:module'`. The CJS emit root-fixes both.

Also: export an inert builtinModules=[] from the node:module shim and alias
ADK's dist/cjs Postgres subtree (@mikro-orm/postgresql, pg) to silence the
remaining webpack warnings. Adds a regression test that consumes the built lib
by package name (CJS require + a Workflow bundling the barrel) so these can't
regress — the existing suite bundled source and hid them.

* fixes

* remove slop comments

* Address PR review comments

- README: import TemporalModel/activityAsTool from the /workflow subpath
- README: fix TemporalMCPToolset / mockMCPToolset casing
- README: note tools run in-workflow, activityAsTool opts into an Activity
- README: drop the under-the-hood bundling section; retriable -> retryable
- CODEOWNERS: align the contrib owner column

* additional fixes

* Validate the published artifact with a unit assertion (match langsmith)

Replace the by-name workflow fixture and Worker bundling test with a
server-free unit test of the plugin's configureBundler/configureWorker
output, matching the other contrib packages. Removes the tsconfig
exclude the fixture required. Switch relative imports to extensionless
to match the repo convention.

* readme fixes

* changelog

* PR comments

* contrib(google-adk-agents): align package with main post-1.22.0

The 1.22.0 release and the CI-logging cleanup landed while this branch
was out of tree, so both skipped this package. Brings it back in line
and fixes accuracy defects the sweep surfaced.

Packaging: version 1.22.0 (was the only package in the repo still on
1.21.1); test script moved to the scripts/ava-ci.ts wrapper so results
reach the new ci-summary job; build.watch renamed to build:watch, which
is what `pnpm --recursive run build:watch` actually matches; ava.files
added so a bare ava run can't pick up helpers.js/workflows.js as tests;
engines.node raised to >= 20.3.0, the repo floor since 1.19.0.

Dependencies: polyfill floors raised to the versions actually tested
against, matching contrib/openai-agents. Dropped local typescript and
@temporalio/client, neither used. @types/node is deliberately kept
despite no sibling declaring it: @google/adk pulls mysql2, which has a
required @types/node peer, and this importer is its only provider —
removing it re-resolves the peer and churns the @google/adk snapshot key.

Also adds the package to tsconfig.prune.json so ts-prune walks its three
entry points, and exports MCPToolsetFactory from the root entry point —
it is the value type of GoogleAdkPluginOptions.mcpToolsets, so naming it
previously meant importing the workflow entry point into worker code.

Comment fixes: a claim that `await using` would SyntaxError on the Node
20 floor (tsconfig targets ES2022, so TypeScript downlevels it); the
wrong module named as importing load-polyfills; two "only X imports
this" absolutes contradicted by the tests; and two unconditional
API-key-safety claims narrowed to what the plugin itself guarantees —
toWireRequest strips only toolsDict and liveConnectConfig, so a caller's
config.httpOptions.headers does reach Workflow history.

* fix(google-adk-agents): Node workflow loading, OTel composition, and telemetry replay-safety tests (#2276)

* fix: load @google/adk workflow bundles on Node

The workflow bundle crashed at load on Node (Bun masked both crashes by
exposing web globals):

- @google/genai's web build dereferences ReadableStream at module load,
  before user imports could evaluate the polyfill barrel. Prepend the
  load-polyfills module to workflowInterceptorModules so it evaluates per
  workflow, before the user's workflow module, regardless of import order.
- @google/adk's utils/client_labels.js runs new AsyncLocalStorage() from
  node:async_hooks at module load. Redirect async_hooks to a shim
  re-exporting the sandbox-injected AsyncLocalStorage global.

* fix: stop stubbing pure-JS OpenTelemetry tracing packages bundle-wide

@opentelemetry/sdk-trace-base and @opentelemetry/resources were aliased to
empty modules for the whole workflow bundle, so composing this plugin with
@temporalio/interceptors-opentelemetry failed every workflow task with
'tracing.BasicTracerProvider is not a constructor' — disabling the SDK's
replay-gated workflow span path (the only egress for ADK's gcp.vertex.agent
spans) for all workflows on the worker. Both packages are pure JS and
load-safe in the sandbox; keep them real.

* test: pin ADK span replay-safety and OpenTelemetry plugin composition

Run a two-turn agent workflow composed with OpenTelemetryPlugin and the
workflow cache disabled (every workflow task replays the whole history):
the workflow must complete and export exactly one gcp.vertex.agent span
per real operation — replays add none. Also pin that without the
OpenTelemetry plugin, sandbox spans never reach a process-global tracer
provider.

* docs: document ADK telemetry behavior in the workflow sandbox

* address review: doc accuracy and bundler contract tests

- Fix README default-case wording: it's the absent tracer provider, not an
  impossibility of running an OTel SDK in the sandbox, that drops ADK spans.
- Add README caution that workflow task retries (unlike replays) re-emit
  spans, so export is at-least-once.
- Pin in plugin unit tests that the pure-JS OTel packages stay unstubbed and
  that load-polyfills is prepended to workflowInterceptorModules.
- Document the converter-modules-evaluate-first gap in the bundler recipe.

* fix: shim the performance global in the workflow polyfill loader

Un-stubbing @opentelemetry/sdk-trace-base exposed @opentelemetry/core's
browser build, which dereferences the performance global at module load.
ESM workflow files dodge that chain through harmony-import pruning, but
tsc-compiled CommonJS workflow files — including the published lib/
artifacts and converter modules importing @google/adk — evaluate it
eagerly, failing every workflow task with 'ReferenceError: performance
is not defined'. Install a deterministic performance shim (mapped onto
the sandbox-patched Date.now, mirroring interceptors-opentelemetry's
workflow runtime shim) in load-polyfills, and add E2E regression tests
for the compiled-CJS workflow layout and the documented converter-module
workaround.

* fix: pin @opentelemetry/api to the copy @google/adk resolves

@google/adk pins an exact @opentelemetry/api version, so the Workflow
bundle can contain two api copies. ADK's telemetry/tracing.js caches
trace.getTracer() at module load; when a user interceptor or converter
module evaluates @google/adk before the OTel interceptor factories
register the sandbox tracer provider, that tracer binds the other copy's
never-delegated provider and every ADK span is silently dropped while
the interceptor's own spans keep exporting. Rewrite all bundle requests
for @opentelemetry/api to ADK's own resolution in the sandbox-compat
webpack plugin, pin the rewrite with a unit contract test, and add an
E2E test that evaluates ADK from a user workflowModules entry and
asserts exact span counts.

* docs: cover telemetry ordering fixes in README and changelog

Move the converter-module workaround into the README's telemetry
cautions (the PR description already pointed there), note the polyfill
loader now includes the performance shim, document the single
@opentelemetry/api copy pinning, and extend the google-adk-agents
changelog entry with the replay-safe span-export composition.

* test: gate exact ADK span counts on a retry-free history

A workflow task retry re-executes its segment and legitimately re-emits
spans through the replay-gated sink, so exact-count assertions could
flake on slow runners; degrade to a lower bound when the history shows
WorkflowTaskTimedOut/Failed events. Also make the performance-shim
comment precise about the interceptor package's unconditional shim.

* refactor: pin the otel api copy via resolve.alias, not a resolve tap

Replace the sandbox-compat plugin's beforeResolve rewrite of
@opentelemetry/api with an exact-match resolve.alias entry in the
webpackConfigHook — the same declarative surface the Worker bundler
itself uses — and assert the config shape in the unit test instead of
driving a fake compiler through the plugin's tap.

Also export an empty interceptors factory from the polyfill loader so
its workflowInterceptorModules entry satisfies the documented
interceptor-module contract rather than relying on the runtime
skipping modules without one, and point the recipe docs at the
initRuntime evaluation-order contract.

* fix: give the api pin consistent precedence in array-form aliases

Array-form resolve.alias resolves first-match-first, so prepend the
@opentelemetry/api pin instead of appending it, matching the object
branch where the pin is spread last. Cover the array branch in the
config-shape test and note the ADK BaseTool contract at the external
_getDeclaration call site.

* fix: make the api pin win the bare specifier in both alias forms

Object-form resolve.alias entries also match in key insertion order, so a
user prefix-form '@opentelemetry/api' key spread before the pin used to
capture the bare specifier in object form while losing to the unshifted
pin in array form. Place the pin key first in the object branch so both
forms agree: the pin wins the bare specifier over any user entry, and a
user prefix-form entry still applies to subpath imports.

* test: honor REUSE_V8_CONTEXT in the contrib suite

Mirror packages/test so REUSE_V8_CONTEXT=false runs every worker (and the
replayer) in per-workflow-VM mode, giving the polyfill loader and telemetry
gating coverage in both sandbox modes.

* fix: shim node:net so @google/adk 1.5.0 bundles load

ADK 1.5.0 added tools/load_web_page.js on the barrel path, which parses
its blocked-CIDR tables at module load, calling net.isIP in the
process. With net aliased to an empty module (like the other disallowed
builtins), isIP is undefined and every workflow task fails at bundle
load: on a fresh install resolving the ^1.4.0 peer range, the
documented quick-start hangs in workflow-task retry with no usable
diagnostic.

Redirect net/node:net to a deterministic shim implementing
isIP/isIPv4/isIPv6 with Node's own address grammar (the
lib/internal/net.js regexes): pure string parsing, frozen in the bundle
so classification cannot drift across replay, and no socket surface. A
parity test pins the classifiers to node:net's across the addresses ADK
parses at load plus classification corners, and the test workflows
module mirrors ADK's top-level pattern so every E2E bundle in the suite
fails loudly if the shim regresses.

The devDependency stays at ^1.4.0: the workspace's minimumReleaseAge
(two weeks) blocks resolving 1.5.0 until 2026-08-13. The full suite was
additionally verified against a local @google/adk@1.5.0 install.

* test: always assert exact span counts on a retry-free history

A workflow task retry re-executes live and legitimately re-emits spans,
but downgrading the regression assertion to a lower bound would also let
a genuine replay over-count pass. Re-run the scenario on a fresh workflow
until the history is retry-free and keep the assertion exact, and qualify
the README's exactly-once wording accordingly.

* Fix changelog merge placement and drop unused client devDep

The base merge glued the expanded google-adk-agents changelog entry to
neighbors that main's 1.22.0 release had moved into the released section,
duplicating it; keep the single expanded entry under Unreleased. Also
restore the base's deliberate removal of the unused @temporalio/client
devDependency and replace two any-casts with the file's typed-filter
pattern.

* ci: give arm integration legs the same 30m budget as windows

The linux-arm/macos-arm integration jobs run the full suite in 19-21
minutes and have repeatedly hit the 20-minute job timeout while green
(GitHub reports the timeout as cancelled). Windows already gets 30
minutes for the same reason.

* ci: give all integration legs a 30-minute budget

A fully green linux-x64 leg now finishes past the 20-minute mark (the
earlier under-20 runs early-exited on a test failure), so the per-platform
split no longer holds; use the windows budget everywhere.

* perf(google-adk-agents): reuse the workflow bundle across test cases

withWorker passed workflowsPath to Worker.create, so every call site
rebuilt the ~9.7MB webpack bundle — 34 compiles per suite run for only 5
distinct bundles, which was most of the suite's runtime. Cache the bundle
on the plugin-resolved BundleOptions and pass workflowBundle instead:
34 compiles become 14, and the suite roughly halves.

That makes interceptors.workflowModules redundant, since configureBundler
already bakes those modules into the bundle, and it lets plugins and
activities take the types WorkerOptions itself uses, dropping both `as any`
casts along with one at a call site.

SlowLlm now honors the abortSignal it was already being handed, so the
worker stops draining for the 10s left over after a start-to-close timeout
has already been observed.

* fix(ci): strip the trailing CR from TAP lines on Windows

ava terminates each TAP write with os.EOL, and TEST_LINE has no `m` flag
while `.` excludes CR, so no `ok` line parsed on Windows: the
google-adk-agents suite reported 0 passed against 59 `ok` lines in its own
log, and packages/test reported 3 for roughly 957 tests. Only ava's exit
code was catching failures.

Strip the CR at the top of handleTapLine, which covers both the line-split
loop and the trailing-partial-line flush in finish().

* test(google-adk-agents): drop redundant tests, cover the model tool loop

The suite had grown tests that cost a worker boot to assert something a
cheaper test already proved. Cut the bundle-load probe in net-shim (every
one of the ~30 E2Es loads that module and calls isIP at module scope, and
the bundler runs without tree-shaking, so a regressed shim fails all of
them), usesCustomModelProvider (FakeLlm reaches LLMRegistry only in the
file's last test, so no earlier case can resolve fake-model except through
the plugin's modelProvider), and resolvesNamedToolsetFactory (its sibling
already proves the named factory resolved by getting the mock's tools
back). Collapse the four activity-summary E2Es into one workflow and one
history fetch covering the same four branches, and merge the MCP filter and
prefix cases into one workflow — with a third case for their interaction,
since the filter matches the post-prefix advertised name and that was
untested.

wrapsActivityAsTool called tool.runAsync directly from workflow code,
bypassing ADK entirely, so the plugin's central use case had no coverage at
any level. It is replaced by a test that drives a real LlmAgent and
InMemoryRunner: the model emits a functionCall, ADK dispatches it as an
Activity, and the result feeds back into a second turn. Asserting two
adk-invokeModel schedules around exactly one lookupOrder is what pins the
loop against stopping early or running the tool twice.

52 tests, down from 59, with the model tool loop and the filter/prefix
interaction newly covered.

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: David Hyde <DABH@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants