Repository navigation
Fix #5: Workers AI streamed tool calls, Node.js module stubs for named imports; p11f queue hand-over timing - #9
Merged
Conversation
…named imports Two defects in #5: - env.AI.run(…, { stream: true, tools }) passed each OpenAI chunk on by itself, so a tool call streamed in fragments (a name, then pieces of the arguments' JSON, keyed by index) came out as several half calls, with empty names and unparsed fragments. The stream now gathers the fragments by index and sends the whole calls once, before [DONE], as { response: "", tool_calls: [{ name, arguments }] }. - The stubs for Node.js modules without a browser polyfill were CommonJS whose members were made on first read; esbuild copies a CommonJS module's own properties once, so named imports (`import { spawn } from "node:child_process"`) were undefined, and only `mod.member` threw as meant. The stub is now an ES module exporting a throwing function for every export the module has on the bundling Node.js (classes extend them), with a default export that answers any member (Object.prototype's names included) the same way. Tests (p14): streamed tool-call fragments become the whole calls; a bundle importing node:child_process and node:readline gets throwing named, namespace and default members, and extends a stubbed class at load. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SXJQA3LbggJHi5qZBpUKe8
"Queues: a delayed message sent on cellb is delivered by celld" failed now and then in CI (#5, #7). celld wakes cells from its wake index by minute (wake/entries/<UTC minute>/…): a message due in a later minute than celld started in is woken at its next scan, up to a minute on, and the test polled for 20 s. Reproduced every time by sending at :54 of a minute (delivered 59 s after celld started); cellb writes the same entry celld writes for its own delayed messages. The test now polls for up to 80 s (timeout 150 s). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SXJQA3LbggJHi5qZBpUKe8
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two defects in #5, found reviewing it after it went up, and the cause of the queue test that kept failing in CI. Neither defect affects Flue's path (its provider reads the raw response, and only the default import of the stubbed modules), which is why #5's tests passed.
1. Streamed tool calls came out in pieces
env.AI.run(model, { messages, tools, stream: true })passed each OpenAI chunk on by itself. OpenAI-compatible servers stream a tool call in fragments: the name first, then pieces of the arguments' JSON, all keyed byindex. So a caller got several half calls, with empty names and unparsed fragments.The stream now gathers the fragments by
indexand sends the whole calls once, beforedata: [DONE]:2. Named imports from a stubbed Node.js module were
undefinedThe stub for a module without a browser polyfill (
node:child_process,node:readline, …) was CommonJS, and it created its members only when they were read. esbuild imports a CommonJS module by copying its own properties once, so it found none.import { spawn } from "node:child_process"gaveundefined, and onlymod.memberthrew as intended.The stub is now an ES module:
Object.prototype's names.3. The flaky "Queues: a delayed message sent on cellb is delivered by celld"
This test failed on #5 and #7, in
e2e/p11f-celld-one-bucket.test.ts.wake/entries/<minute>/…). A message falling due in a later minute than the one celld started in is woken at celld's next scan, up to a minute later. The test polled for 20 s.Tests
test/p14-workers-ai.test.ts:node:child_processandnode:readlinegets named, namespace and default members that throw, and extends a stubbed class at load (it failed before:f is not a function).main(48f6222) merged in:tscpass;🤖 Generated with Claude Code
https://claude.ai/code/session_01SXJQA3LbggJHi5qZBpUKe8