Skip to content

[pull] main from danny-avila:main#118

Merged
pull[bot] merged 4 commits into
innFactory:mainfrom
danny-avila:main
Jun 19, 2026
Merged

[pull] main from danny-avila:main#118
pull[bot] merged 4 commits into
innFactory:mainfrom
danny-avila:main

Conversation

@pull

@pull pull Bot commented Jun 19, 2026

Copy link
Copy Markdown

See Commits and Changes for more details.


Created by pull[bot] (v2.0.0-alpha.4)

Can you help keep this open source service alive? 💖 Please sponsor : )

)

The extended 1h prompt-cache TTL is Anthropic-only on Bedrock. Non-Claude
models reject it — Nova returns `ValidationException: Extended TTL prompt
caching is only supported for Anthropic models` (verified live) — so the new
1h default broke Nova's message/system caching, which worked at 5m before.

Add `resolveBedrockPromptCacheTtl(ttl, model)`: Claude (and the omitted-model
default) keep the 1h default / configured ttl; non-Claude models clamp to 5m
even when 1h is explicitly set. Wire it into the three Bedrock cachePoint TTL
sites (index.ts tool, Graph.ts message tail, AgentContext summary). So Nova
now caches system/messages at 5m instead of erroring.
…l calls (#254)

* test: cover custom OpenAI-compatible vLLM reasoning + qwen3_coder tool calls

Regression coverage for a generic custom endpoint (provider openai,
default reasoningKey, non-standard model name) that streams reasoning in
the modern vLLM `reasoning` field (reasoning_content null throughout) and
streams tool_calls with fragmented arguments (qwen3_coder).

Locks in that delta.reasoning surfaces as think content and that the
fragmented streamed tool call accumulates into a structured call.
Mirrors the wire captures in LibreChat discussion #13849.

* test: address Codex review on vLLM regression spec

- Use a non-OpenAI baseURL so the model exercises the custom-endpoint
  (final-signal) path instead of the official-OpenAI sequential-seal path
  that an unset baseURL selects (isOfficialOpenAIBaseURL returns true).
- Drive the qwen3_coder tool call through the full Run.processStream graph
  path: assert the streamed fragments are dispatched into a TOOL_CALLS run
  step and the get_weather tool executes with the assembled args, rather
  than asserting only on local AIMessageChunk concatenation.
- Replace Record<string, unknown> converter inputs with typed OpenAI
  completion chunk/delta shapes (AGENTS.md: limit unknown/Record).

* test: assert streamed tool-call deltas assemble args (Codex round 2)

The TOOL_CALLS ON_RUN_STEP can be produced from the final assembled
AIMessage (handleToolCalls) even if the streamed-delta path regresses, so
asserting only on the step name would miss a streaming-UI regression.
Capture ON_RUN_STEP_DELTA (handleToolCallChunks) and assert the fragmented
qwen3_coder argument chunks assemble to {"location": "Berlin"}.
…255)

* fix(cloudflare): client-side timeout on native sandbox file-IO RPCs

PR #252 bounded the three `sandbox.exec()` sites with `withClientTimeout`, but
the native-DO FILE-IO RPCs were left unwrapped. `createCloudflareWorkspaceFS`'s
`readFile`/`writeFile`/`stat`/`readdir`/`mkdir`/`unlink`/`open` call
`sandbox.readFile()`/`writeFile()`/`listFiles()`/`mkdir()`/`deleteFile()`
directly — the same uncancellable native Durable Object transport (no `signal`,
no reliably-enforced timeout). So a stalled/cold container hangs the host await
on a single file read until the run-level abort, burning the whole budget on one
tool call — the exact failure exec() had before #252.

Observed live: an issue-triage `read_file` stalled ~552s before the wall-clock
budget killed the run (the in-batch `execute_bash` was bounded at ~130s by #252;
the parallel `read_file` was not). The v24 "read_file over bash" guidance had
ironically moved traffic from the now-bounded exec path onto the still-unbounded
FS path.

Wrap every native FS RPC in `createCloudflareWorkspaceFS` (and the `listFiles`
inside `findChildInfo`) with the same `withClientTimeout` backstop, using a new
`clientFsTimeoutMs(timeoutMs) = timeoutMs + 5000` (file IO has no in-sandbox
`timeout(1)` layer to honor, so a single headroom margin suffices). A normal,
byte-capped read completes well within it; a stalled container can't outlast it.

Tests: stalled `readFile` and stalled `listFiles` reject with a client-side
timeout; a fast read resolves and leaves no dangling backstop timer. Cloudflare
suite 28/28, typecheck + lint clean.

* fix(cloudflare): address Codex review on FS-RPC client timeout

P1 — distinguish FS timeouts from "file not found". The backstop now throws a
`WorkspaceClientTimeoutError` (code WORKSPACE_CLIENT_TIMEOUT) instead of a plain
Error, and the two ENOENT-only fallbacks rethrow it: the write_file pre-read in
LocalCodingTools (was treating a stalled read as "file absent" -> overwrite) and
FileCheckpointer.stat (was snapshotting a stalled stat as "absent" -> deletes the
file on rewind). A stalled read can no longer masquerade as a missing file.

P2 — keep the backstop active through the streamed-read drain. The race now wraps
readFile + normalizeReadFileContent together (readFile/open/stat-fallback), so a
sandbox.readFile that resolves to { content: ReadableStream } can't stall mid-drain
after the timer cleared.

P2 — bound execute_code temp-dir setup. executeCloudflareCode's pre-exec
ctx.sandbox.mkdir / writeFile were unbounded, so a native-DO stall there hung the
host before reaching the (already-bounded) exec path.

Not addressed here (documented limitation): a timed-out *mutating* FS RPC abandons
the host await but cannot cancel the native DO RPC, so a late write may still land
— the same uncancellable-transport property #252 accepted for exec(). Poisoning the
run on a mutating timeout is a larger behavior change left out of this focused
backstop.

Tests: distinguishable-error assertion on the readFile stall; streamed-read drain
stall; execute_code mkdir-setup stall; FileCheckpointer rethrows a stat timeout
instead of recording absent. Suites green (CloudflareSandboxExecution 30/30,
FileCheckpointer + local-tool suites 306 passed), tsc + eslint clean.

* fix(cloudflare): surface FS-RPC timeouts from generic swallow sites

Round-2 Codex follow-on to the distinguishable WorkspaceClientTimeoutError: now
that a stalled FS RPC throws a typed error, every generic catch that absorbs FS
failures as benign must rethrow the timeout — otherwise a stalled container
yields WRONG results (corrupted search, doubled latency) instead of failing.

- engine stat(): a directory-probe listFiles timeout now rethrows instead of
  falling through to the readFile branch (which waited through a SECOND backstop,
  ~2x the timeout, before surfacing).
- grep_search/glob_search Node fallback walker (LocalCodingTools): readdir
  timeout rethrows instead of skipping the directory (which silently corrupted
  results to "no matches").
- grep_search Node fallback scanner: both the per-file stat AND readFile timeouts
  rethrow instead of skipping the file (which could report "no matches" even when
  the stalled-unreadable file contained the match). The outer fallback catch
  already rethrows non-FallbackGrepError, so these surface as a real failure.

Test: engine stat probe timeout rethrows and does NOT fall through to readFile.
CloudflareSandboxExecution 31/31; local-tool + checkpointer suites 275 passed;
tsc + eslint clean.

* fix: surface FS-RPC timeouts from remaining probe & rollback swallow sites

Round-3 Codex follow-on — completes the sweep of generic catches that absorb a
WorkspaceFS error as benign. Now that a stalled native-DO RPC throws the typed
WorkspaceClientTimeoutError, the remaining swallow sites must rethrow it so a
stalled container fails loudly instead of producing wrong results / false success:

Probes (wrong-result):
- CompileCheckTool.pathExists: a stat timeout no longer returns false (which picks
  a weaker/wrong toolchain after waiting through the backstop).
- CompileCheckTool package.json / pyproject.toml reads: timeout no longer
  substitutes '' (which silently misses typescript/mypy detection).
- syntaxCheck jsonCheck read: a stalled read no longer returns ok:true (passing the
  syntax gate without actually reading the file).
- syntaxCheck runPostEditSyntaxCheck: a checker timeout no longer collapses to null
  (which would let the write through without a real syntax gate).

Rollback (false-success / data integrity):
- revertStrictWrite: a timed-out revert no longer lets the caller claim "reverted
  to pre-write state" while the rejected bytes remain on disk.
- FileCheckpointerImpl.rewind: a timed-out restore write or delete no longer counts
  the path as restored — rewind surfaces the timeout instead of silently leaving
  the workspace half-restored.

Non-timeout failures keep their existing benign behavior everywhere. Test: rewind
rethrows a restore-write timeout instead of claiming success. All affected suites
green (FileCheckpointer/Cloudflare/local-tool 181 + 127 passed); tsc + eslint clean.

* fix: handle second-order effects of surfacing FS-RPC timeouts

Round-4 Codex follow-on — two consequences of making the new client-timeout
surface (rather than swallow sites):

- execute_code temp-dir leak: the client-bounded mkdir/writeFile setup ran
  BEFORE the try/finally, so a setup timeout exited without cleanup, orphaning
  .lc-exec/<uuid> (the uncancellable write can still land late on a cold
  container). Moved setup inside the try so the existing detached cleanup runs.

- strict-mode revert bypassed: runPostEditSyntaxCheck now rethrows a stalled
  validation read, but that escaped write_file/edit_file before their strict
  rollback block, leaving the just-written bytes on disk while the call failed.
  Wrapped maybeRunSyntaxCheck so a validation-read timeout routes through
  revertStrictWrite (in strict mode) before surfacing — best-effort, since the
  revert may itself time out on the same stalled container.

Tests: execute_code still issues `rm -rf` cleanup when setup writeFile stalls;
write_file reverts (unlinks the new file) when the strict validation read times
out. Affected suites 183 passed; tsc + eslint clean.
@pull pull Bot locked and limited conversation to collaborators Jun 19, 2026
@pull pull Bot added the ⤵️ pull label Jun 19, 2026
@pull pull Bot merged commit 7fa672f into innFactory:main Jun 19, 2026
1 check passed
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant