Commit Graph

36434 Commits

Author SHA1 Message Date
Mason Huang
5ff247b99e test: prefer auto-cleaning temp dir helper (#93209)
Summary:
- The branch adds `useAutoCleanupTempDirTracker()`, broadens the temp-dir warning reporter to flag new manual helper imports/usages, updates docs, and migrates two script tests to the new helper.
- PR surface: Tests +301, Docs +1, Other +248. Total +550 across 8 files.
- Reproducibility: not applicable. this is test/tooling cleanup, and the changed behavior is exercised through helper/reporter tests and CI evidence rather than a user reproduction path.

Automerge notes:
- PR branch already contained follow-up commit before automerge: test: harden temp dir helper guard
- PR branch already contained follow-up commit before automerge: test: clarify auto cleanup temp dir helper name
- PR branch already contained follow-up commit before automerge: test: cover existing mkdtemp temp dir forms
- PR branch already contained follow-up commit before automerge: test: read staged temp helper source from index

Validation:
- ClawSweeper review passed for head 1fdd7d2a9a.
- Required merge gates passed before the squash merge.

Prepared head SHA: 1fdd7d2a9a
Review: https://github.com/openclaw/openclaw/pull/93209#issuecomment-4705653665

Co-authored-by: Mason Huang <masonxhuang@tencent.com>
Approved-by: hxy91819
2026-07-02 02:46:28 +00:00
Josh Avant
0cdce79221 docs: update mobile app release messaging (#98843) 2026-07-01 21:11:56 -05:00
joshavant
080481fec9 Require explicit iOS release versions 2026-07-01 20:24:38 -05:00
qingminlong
40e02a418c fix(wizard): reject loose gateway port input (#98689)
* fix(wizard): reject loose gateway port input

* fix(wizard): reuse shared gateway port parser
2026-07-01 18:06:21 -07:00
Vincent Koc
1cbcff7c89 test(gateway): isolate live release agent state 2026-07-01 18:02:09 -07:00
Vincent Koc
c0511692d8 test(plugins): repair prerelease validation fixtures 2026-07-01 18:02:09 -07:00
Harjoth Khara
c49714f7b6 fix(agents): don't inject A2A turns into isolated-cron sessions_send (#92257) (#92283)
* fix(agents): don't inject A2A turns into isolated-cron sessions_send (#92257)

Fire-and-forget sessions_send (timeoutSeconds === 0) with announce
delivery runs the A2A ping-pong loop. For a cross-session send
(requester != target) the loop's first iteration feeds the target
agent's reply back into the requester session as a new turn. For a
normal requester that roundtrip is intended, but for an *isolated cron*
requester it injects reply context into the isolated run and causes an
agent feedback loop.

Narrow the fix to isolated-cron requesters only (detected by a session
key containing ":cron:" or channel "cron" -- the same signal used by
src/agents/subagent-registry.ts and set in
src/cron/isolated-agent/run.ts), NOT by timeoutSeconds. Gating on
timeoutSeconds was too broad: it disabled the intended ping-pong for
normal cross-session fire-and-forget sends.

Two hunks in src/agents/tools/sessions-send-tool.ts, both reusing one
`isIsolatedCronRequester` gate:

1. Force maxPingPongTurns to 0 in the runSessionsSendA2AFlow invocation
   only for an isolated-cron requester. The a2a flow's ping-pong guard
   (`maxPingPongTurns > 0`) then skips the requester-injection loop and
   proceeds straight to the announce step in the TARGET session,
   preserving fire-and-forget announce delivery. Normal requesters keep
   the configured turn count.

2. Read baselineReply for fire-and-forget sends when same-session (prior
   behavior) OR isolated-cron. Without a baseline fingerprint, a2a.ts
   would treat pre-existing assistant text in the target session (e.g.
   an unrelated concurrent cron's output) as "the reply" and
   misattribute it. The normal cross-session fire leg's history-call
   count is unchanged from origin/main. Read failures are tolerated so a
   snapshot error never blocks accepting the send.

Tests (sessions.test.ts): an isolated-cron cross-session fire-and-forget
forwards maxPingPongTurns: 0; a normal-requester regression guard
(discord:group:req / channel discord) forwards the configured turn count
(not 0), proving the normal ping-pong is preserved. a2a flow tests
(sessions-send-tool.a2a.test.ts): with turns=0 + requester!=target the
requester is never stepped but the target is still announced, and a
baseline-matching reply is neither injected nor announced.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(agents): gate isolated-cron A2A on canonical cron-run classifier (#92257)

Address Codex [P2] review: replace the raw `:cron:` substring detector with
the canonical isCronRunSessionKey so a non-canonical cron-like requester key
(e.g. agent:main:slack:cron:job:run:uuid) keeps its intended cross-session
ping-pong. Keep the requesterChannel === "cron" arm (isolated cron runs set
that channel in src/cron/isolated-agent/run.ts). Add a regression covering the
non-canonical key.

* refactor(agents): drop dead cron-channel A2A arm, gate on canonical key only (#92257)

The requesterChannel === "cron" arm was unreachable: agentChannel is always a
DeliverableMessageChannel from resolveGatewayMessageChannel(messageProvider),
never the literal "cron". The channel: "cron" in src/cron/isolated-agent/run.ts
labels diagnostics events/lifecycle, not the tool channel. Gate on
isCronRunSessionKey alone and fix the misleading comment.

Tests drove the dead arm via agentChannel/requesterChannel "cron" plus a
non-canonical key (agent:main:cron:run:abc, which isCronRunSessionKey rejects).
Switch them to a canonical cron-run key (agent:main:cron:job:run:abc) and a
normal delivery channel so they exercise the real production gate.

* fix(agents): align cron A2A fallback baselines

* chore: prepare branch refresh

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-07-01 17:34:26 -07:00
Masato Hoshino
8e28e88387 fix(gateway): distinguish reachable gateway from failed status probe (#98183)
* fix(gateway): distinguish reachable gateway from failed status probe

* fix(status): gate owns-port RPC recovery guidance on no stale gateway PIDs

inspectGatewayRestart can set health.healthy from bare reachability after
ownership attribution failed, while still returning a non-empty
staleGatewayPids. Printing owns-port recovery guidance in that case
contradicted the dedicated stale-PID diagnostic below it. Require
staleGatewayPids to be empty before treating healthy as owns-port proof.
2026-07-01 17:04:31 -07:00
Peter Steinberger
17482a4026 fix(ci): restore docs and test type checks (#98792) 2026-07-02 00:36:52 +01:00
Gio Della-Libera
cdaafe198c doctor: expose channel plugin blocker findings (#97496) 2026-07-01 16:31:52 -07:00
Ayaan Zaidi
f8769559ae fix(telegram): honor long flood-wait retry_after on outbound sends 2026-07-01 16:22:34 -07:00
anagnorisis2peripeteia
6df7db9f9e feat(cli): add attach launcher (#96454)
* feat(cli): openclaw attach — launch Claude Code bound to a gateway session with scoped MCP tools
* fix(cli): use token-only MCP config for attach

---------

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-07-01 15:52:39 -07:00
Kevin Lin
d9b5afad18 fix(codex): rename destructive approval mode to ask (#98501)
* fix(codex): rename destructive approval mode to ask

* fix(codex): keep ask reviewer app-scoped

* test: fix current-main CI regressions
2026-07-01 15:14:55 -07:00
Josh Avant
eb417fa206 fix: diagnose Windows LAN Gateway firewall blocks (#98666)
* Diagnose Windows LAN Gateway firewall blocks

* Fix Windows firewall diagnostic lint

* fix: gate gateway firewall diagnostics to local targets

* fix: keep firewall inspection off critical flows
2026-07-01 16:24:16 -05:00
Darren2030
e79865569c fix(install): preserve SecretRef service env values (#96065)
* fix(install): manage config-secretref env refs via OPENCLAW_SERVICE_MANAGED_ENV_KEYS
* fix(install): preserve config secret refs in launchd env
* fix(install): preserve secretref env render sources

---------

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-07-01 14:04:33 -07:00
Ayaan Zaidi
bc7f9a36ec fix(cron): detach session-targeted cron runs (#98755)
* fix(cron): detach session-targeted runs
* fix(tasks): cancel stale childless cron rows

---------

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-07-01 14:04:25 -07:00
Ayaan Zaidi
44e88f550b fix(telegram): keep media retry policy local 2026-07-01 13:05:42 -07:00
luoyanglang
f9d7afda10 fix(telegram): narrow durable inbound media retry to transient + abort (#98076)
Review on #98102: the durable-retry classifier treated every MediaFetchError
`fetch_failed` as retryable, but `fetch_failed` also covers permanent failures
(SSRF/guard denials, local Bot API path/read errors). On spooled replay those
would requeue forever with the user-facing warning suppressed.

Move the policy to its owner: add `isDurablyRetryableMediaFetchError` to
`src/media/fetch.ts`, defined as `shouldRetryMediaFetch` (the canonical in-loop
transient policy) plus shutdown/abort `fetch_failed`. A restart-window abort is
the primary inbound-media loss vector and is recoverable on replay, whereas
in-loop retry mid-shutdown is futile; permanent `fetch_failed`, other 4xx, and
size limits stay non-retryable so they cannot loop in the spool.

Telegram reuses the shared helper instead of a local classifier
(`isAbortError`/`isTransientNetworkError` live in core; the classification must
not drift). Adds permanent-`fetch_failed` regression coverage at the unit and
behavioral level. Media-group partial delivery (#55216) unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 13:05:42 -07:00
fsdwen
44cb3f7b98 fix(agents): prevent duplicate subagent announce sends
Fixes the subagent announce prompt-lock race by treating lock-change failures with visible-send evidence as terminal, while keeping pre-send failures retryable.

Scoped proof:
- node scripts/run-vitest.mjs src/agents/subagent-announce-delivery.test.ts src/agents/subagent-announce.test.ts src/agents/subagent-registry-lifecycle.test.ts
- node scripts/run-tsgo.mjs -p tsconfig.core.json
- node scripts/run-tsgo.mjs -p test/tsconfig/tsconfig.core.test.agents.json
- oxfmt --check on touched agent files
- git diff --check
- .agents/skills/autoreview/scripts/autoreview --mode local

Thanks @fsdwen!
2026-07-01 12:55:15 -07:00
Peter Steinberger
ab2f6f5642 feat: prepare scoped conversation capability profiles (#98536)
* feat(agents): prepare scoped conversation capability profiles

* fix: satisfy scoped profile lint

* test: update compaction harness agent-scope mock
2026-07-01 20:28:58 +01:00
Mark
5db7c3797d Fix Telegram plugin callback routing (#97174)
* fix telegram plugin callback routing

* Add Telegram callback proof coverage

* Fix proof script lint

* Fix Telegram proof CI regressions

* test: fix telegram callback proof CI regressions

* fix: retire registry-owned callbacks

* fix: retire registry-owned callbacks

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-01 19:49:54 +01:00
Omar Shahine
d0b30e0deb fix(imessage): shed emoji anywhere in poll-vote echo match (#98691)
* fix(imessage): shed emoji anywhere in poll-vote echo match

iMessage native poll options carry a trailing emoji ("Lobster 🦞 ") while the
agent echoes its vote with a leading one ("🦞 Lobster.") under message_tool_only
reply mode. normalizePollEchoText stripped only a leading emoji prefix, so
"lobster 🦞" never matched "lobster" and the redundant text leaked past the
poll_vote_echo guard (shipped in #98421).

Shed emoji anywhere across every class: pictographic, regional-indicator flags
(🇺🇸), subdivision-flag tag chars, ZWJ, skin-tone, and keycap sequences cleared
as a unit (so "1️⃣" -> "" not "1", while a plain "1"/"#"/"*" survives). Internal
punctuation stays so C#/C++/Node.js remain distinct; emoji-only labels normalize
to empty and the guard's existing empty-option check fails open. Re-exports
normalizePollEchoText with a focused unit test across every emoji class plus a
message-tool integration test for the emoji-suffixed-option case.

* fix(imessage): make poll-echo emoji regex lint-safe

ClawSweeper/CI check-lint flagged no-misleading-character-class: combining
marks (VS16, U+20E3), ZWJ, and skin-tone modifiers are misleading inside a
single character class. Rewrite the emoji strip as an alternation using
property escapes (\p{Regional_Indicator}, \p{Emoji_Modifier}) plus standalone
atoms so the same normalization behavior passes lint. Behavior unchanged;
poll-echo unit + integration tests still green.

* fix(imessage): preserve poll option emoji identity

---------

Co-authored-by: Omar Shahine <10343873+omarshahine@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-01 19:49:43 +01:00
Ayaan Zaidi
53fe2e4bc3 refactor(auth): simplify codex login follow-up 2026-07-01 11:16:49 -07:00
Josh Lehman
26a756ee84 fix: preserve plugin login command precedence 2026-07-01 11:16:49 -07:00
Josh Lehman
bde0e4541e refactor: share codex login flow helpers 2026-07-01 11:16:49 -07:00
Eva
236626fffd Avoid object stringification in login surface checks 2026-07-01 11:16:49 -07:00
Eva
af8a4540ed Address Codex login review feedback 2026-07-01 11:16:49 -07:00
Eva
918612513f Use nondeprecated provider auth SDK path 2026-07-01 11:16:49 -07:00
Eva
72653b600c Narrow Codex login SDK export 2026-07-01 11:16:49 -07:00
Eva
48974b5765 Add shared Codex login command surfaces 2026-07-01 11:16:49 -07:00
Eva
77edfe7414 Add Telegram Codex login pairing 2026-07-01 11:16:49 -07:00
Cameron Beeley
68bfa42b9b feat(cron): on-exit cron schedule kind — fire a job when a watched command exits
Adds an `on-exit` cron schedule kind: a job fires once when a watched command/process
exits, via gateway ProcessSupervisor exit watchers. Covers CLI (`--on-exit`/`--on-exit-cwd`),
tool/protocol schema, RPC list-filter, Control UI + macOS read-only display, SQLite
round-trip, and origin-aware wake routing. Restart-safe one-shot (persists completion
before firing); platform-aware shell; bounded watched-command execution.

Squashed from 22 iterative commits for a clean rebase onto current main.
2026-07-01 10:47:01 -07:00
Eva
8d9a7ab2ca fix(reply): steer active non-streaming runs 2026-07-01 10:34:20 -07:00
Eva
bfc4e1dcb5 fix(telegram): restore active-run steering 2026-07-01 10:34:20 -07:00
Ayaan Zaidi
4895a00b94 fix(usage): tidy compact footer defaults 2026-07-01 09:59:37 -07:00
Peter Lindsey
2205bf9d24 test(usage): update default footer expectations 2026-07-01 09:59:37 -07:00
Peter Lindsey
f2b54d18d8 feat(usage): make built-in default footer Telegram-friendly
The built-in default footer (added in #92657) only defined a `discord`
surface. Telegram and every other surface fall through to `output.default`,
which was authored for a wide terminal: space-separated badges, a leading
space-less join onto the message body, and ↕️ token + 🗄 cache% segments.

On a narrow Telegram screen this wrapped at arbitrary spaces (often mid-meter
or between 📚 and its bar) and welded onto the end of the message text.

Make `default` read well on a phone:
- Leading \n so the footer sits on its own line below the body.
- Tight badges (no separators between model/flags/reasoning/fast).
- NBSP before "|" and 💰; 📚 glued hard to the meter so it can't wrap there.
- Single regular space after "|" as the only sanctioned wrap point.
- Drop ↕️ tokens and 🗄 cache% from the default — noise for most users
  (still available to anyone via a custom messages.usageTemplate).

Discord surface trimmed to match for consistency (keeps its -# dim header).
2026-07-01 09:59:37 -07:00
Peter Steinberger
db97bc1e4f test: isolate message tool unit plugin loading (#98701)
Co-authored-by: Peter Steinberger <58493+steipete@users.noreply.github.com>
2026-07-01 17:35:29 +01:00
Ayaan Zaidi
a5e11c0083 fix(plugin-sdk): honor suppressReply across native commands 2026-07-01 09:09:45 -07:00
Alexander Chen
d616206c58 fix(types): remove unused PluginCommandSuppressReply export 2026-07-01 09:09:45 -07:00
alexuser
20fcd4a39c fix(telegram): suppress fallback reply when plugin command returns suppressReply: true
Adds  to the  type so plugin
commands that handle their own transport delivery (e.g. via Telegram Bot API
directly with retry logic, IPv4 forcing, etc.) can signal the channel adapter
to skip the fallback reply.

When a plugin command handler returns , the Telegram
native command dispatcher now:
1. Cleans up any progress placeholder
2. Returns early without sending the "No response generated. Please try again." fallback

Includes detailed JSDoc for the new  flag explaining its use
for plugin commands that deliver their own responses via channel-native APIs.

Fixes #80756
2026-07-01 09:09:45 -07:00
Wynne668
d9d6108086 fix(agents): preserve UTF-16 tool summary truncation (#98644) 2026-07-01 08:56:40 -07:00
lizeyu
8c54704b77 fix(embedded-agent-runner): pump async streamFn through pumpStreamWithRecovery for mid-stream error recovery (#95430)
* fix(embedded-agent-runner): pump async streamFn through pumpStreamWithRecovery for mid-stream error recovery

When wrapEmbeddedAgentStreamFn returns an async function (e.g. when
authStorage or resolvedApiKey is present), the stream is a Promise that
resolves to AssistantMessageEventStreamLike. The old Promise branch in
wrapAnthropicStreamWithRecovery only handled Promise rejections via
.catch(), missing {type:"error"} events that arrive after the Promise
resolves — such as Anthropic thinking-signature replay rejections.

Now the Promise branch:
  - Awaits the resolved stream and runs pumpStreamWithRecovery on it,
    so mid-stream error events trigger thinking-signature recovery.
  - Handles Promise rejection via .then(onFulfilled, onRejected) with
    the same retryStreamWithoutThinking path used by the sync branch.
  - Returns a unified AssistantMessageEventStream (outer) identical to
    the non-Promise branch pattern.

Tests updated to match the new return type (outer stream + .result()
instead of a bare Promise).

Fixes #95429

* fix(anthropic): remove orphaned wrapRetryStreamWithRecoveryNotification

Function is dead code — the Promise-handling was inlined into
pumpStreamWithRecovery, leaving only a recursive self-call
with no external entry point.

* fix(embedded-agent-runner): add Promise-resolved-stream regression test

* fix: use createTestStreamErrorMessage for type-correct stream error in Promise-resolved test

* test(agents): cover async thinking stream recovery

---------

Co-authored-by: lzyyzznl <lzyyzznl@users.noreply.github.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-07-01 08:56:30 -07:00
Yuval Dinodia
a5a8d992ae fix(claude-cli): return updatedInput in can_use_tool allow response (#98665)
Claude Code >= 2.1.156 tightened its PermissionResult schema so an
approved can_use_tool control_response allow branch must carry an
updatedInput record. The Claude live-session bridge answered with the
deprecated { behavior: "allow" } shape and no updatedInput, so the CLI
rejected every approval-gated native tool call (Bash, WebFetch, and
AskUserQuestion among them) with a ZodError before the tool ran.

Echo the tool input back unchanged as updatedInput on the allow branch,
matching the shape the Claude Code 2.1 binary expects. The deny branch
and all other behavior are unchanged.

Fixes #95171.
2026-07-01 08:11:38 -07:00
Super Zheng
0666423237 fix: media tools skip env-key provider plugins when auto-selecting models (#98623)
hasProviderAuthForTool/hasAuthForProvider now thread cfg and workspaceDir into resolveEnvApiKey, so provider plugins that authenticate via environment variables and are only discoverable with config are detected during image/video model auto-selection instead of being dropped as unconfigured.
2026-07-01 08:11:13 -07:00
RichChen01
808e8f09ba fix(cron): persist startup catch-up deferral ids in service state to prevent read-RPC clobber (#94022)
* fix(cron): persist startup catch-up deferral ids in service state to prevent read-RPC clobber

The startup overflow catch-up deferral (#93810) set deferred job
nextRunAtMs to a staggered slot, but the exemption was stored as a
local skipFutureRepairJobIds set threaded only into start()'s
maintenance recompute pass. Every other caller of
recomputeNextRunsForMaintenance — ensureLoadedForRead (list/status),
finalizeCompletedResults, empty-due tick, manual run preflight, and
releaseUnclaimedDueJobReservations — called maintenance recompute
without the skip set, causing shouldRepairFutureCronNextRunAtMs to
advance the deferred staggered slot to the job's natural next run,
dropping the missed run for a full period.

Fix: Move the exemption into CronServiceState as
pendingCatchupDeferralJobIds, populated by applyStartupCatchupOutcomes
where deferrals are assigned. recomputeNextRunsForMaintenance now
always checks this state-level set instead of a local parameter, and
clears each id once its staggered slot is reached (now >= nextRunAtMs).
This gives one canonical exemption path that covers all recompute
callers.

The now-redundant skipFutureRepairJobIds parameter is removed.

Fixes #93935

Co-Authored-By: Claude <noreply@anthropic.com>

* fix(clownfish): address review for repair-94022-fresh-plan-20260618 (1)

* fix(cron): preserve agentTurn exempt + add stale-deferral cleanup + runtime proof

Address ClawSweeper review by:
1. Keeping the existing agentTurn deferred-slot exemption unchanged
   (shouldRepairFutureCronNextRunAtMs still returns false for agentTurn
   jobs with nextRunAtMs before the natural schedule).
2. Adding cleanup of stale pendingCatchupDeferralJobIds markers for
   jobs that no longer exist or are disabled.
3. Adding regression tests for pending startup catch-up deferral
   preservation and stale marker cleanup.
4. Adding standalone CLI runtime proof script demonstrating the fix.

Co-Authored-By: Claude <noreply@anthropic.com>

* fix: add pendingCatchupDeferralJobIds to test-harness + remove unused import

- Add pendingCatchupDeferralJobIds to createMockCronStateForJobs to fix TS2741.
- Remove unused loadCronStore import from runtime proof script.

Co-Authored-By: Claude <noreply@anthropic.com>

* fix(cron): tighten startup catch-up deferral handling

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: openclaw-clownfish[bot] <280122609+openclaw-clownfish[bot]@users.noreply.github.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-07-01 08:04:31 -07:00
Onur Solmaz
530d576cc6 fix(agents): time out local streams without first event (#98525)
* fix(agents): time out streams without first event

* fix(agents): propagate first-event stream timeout

* fix(agents): abort streams on first-event timeout

* fix(agents): time out chatgpt websocket streams

* fix(agents): clamp first event stream timeouts

* fix(agents): keep first event timeout internal

* fix(agents): classify first event stream stalls as timeouts

* fix(agents): preserve provider first-event timeouts

* fix(agents): satisfy first-event timeout lint

* fix(agents): classify first-event stalls as idle timeouts

* test(tooling): include transcript store helper route
2026-07-01 23:01:46 +08:00
Fede Kamelhar
f35fbc898c fix(gateway): cap agentRunCache to prevent unbounded growth under run fan-out (#77973)
* fix(gateway): cap agentRunCache to prevent unbounded growth under run fan-out

Time-based prune only reclaims entries past the 10-minute TTL window; a burst
of run fan-out can add far more entries than the window reclaims, so the cache
could grow without bound between prunes. Add a FIFO entry cap (5000) enforced
on insert, mirroring the existing Discord REST entity-cache bound.

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

* test(gateway): preserve waited run snapshots under cache cap

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-07-01 07:48:58 -07:00
Peter Steinberger
909be7bcbc fix: validate message timeout before secret resolution (#98652)
Co-authored-by: Peter Steinberger <58493+steipete@users.noreply.github.com>
2026-07-01 15:35:58 +01:00
huangjianxiong
8abd5d4071 fix(tlon): bound error response body reads to prevent OOM (#98496)
* fix(tlon): bound error response body reads to prevent OOM

Replace bare response.text() on non-ok paths with readResponseTextLimited
capped at 16 KiB so a hostile or misconfigured Urbit ship cannot force the
gateway to buffer an arbitrary-size error body into process memory.

Affected paths:
- pokeUrbitChannel (channel-ops.ts)
- channel.runtime.ts poke path
- sendSubscription (sse-client.ts)

* fix(tlon): fix lint issues in error-body-boundary test

- Remove unused beforeEach import
- Wrap if/else bodies in braces (curly)
- Use block body for Promise executors (no-promise-executor-return)

* fix(types): resolve pre-existing TS test type errors

- Fix TS2493 tuple type errors in server-cron-notifications and
  server-cron tests by adding explicit type annotations on mock.calls
- Fix TS2322 in anthropic.test.ts by adding as const to resource
  content block type

* chore: trigger CI
2026-07-01 06:57:21 -07:00