Commit Graph
1443 Commits
Author SHA1 Message Date
can1357 e689351597 fix(coding-agent): resolved OAuth token expiry flow in AuthStorage
- Centralized OAuth access lifecycle in `AuthStorage`, returning identity metadata and new access-result types.
- Added 60-second skew and strict expiry checks, returning undefined/throws for stale or expired OAuth credentials.
- Removed provider-local token refresh flows from Gemini, Gemini CLI, Antigravity, Kimi, and related OAuth helpers.
- Migrated web-search providers from `AgentStorage` to `AuthStorage` session-aware lookup with `authStorage`/`sessionId`/`signal` flow.
- Replaced `findAnthropicAuth`/DB auth lookup with `buildAnthropicAuthConfig` and explicit base-url override/env fallback ordering.
2026-05-26 03:59:13 +02:00
can1357 cfabeeb17c feat(web): added Codex and Gemini web search providers with shared AgentStorage flow
- Added OpenAI Codex and Gemini web search provider options with updated setup/auth descriptions.
- Updated Codex OAuth flow to refresh near-expiry tokens during web_search and persist the refreshed credentials.
- Plumbed AgentStorage through search orchestrator, scrapers, and fetch paths so providers share session credentials.
- Refactored web provider and credential helpers to accept caller-provided AgentStorage and resolve keys synchronously.
2026-05-25 21:21:13 +02:00
Can BölükandGitHub d201442a16 Merge pull request #1372 from can1357/farm/e4c67c73/fix-subagent-session-start-busy
fix(agent): prevent subagent session_start busy race
2026-05-25 21:59:38 +03:00
Can BölükandGitHub 8b4525e869 Merge branch 'main' into farm/70c1e455/bash 2026-05-25 21:56:06 +03:00
roboomp 23300d0348 fix(bash): quarantined stalled shell sessions
Quarantined persistent session keys only while the native cancellation promise remains unsettled, so healthy cleanup restores persistent mode and stalled cleanup cannot accumulate live shell instances.

Added coverage for both stalled and settled native cleanup paths.

Fixes #1347
2026-05-25 18:48:20 +00:00
roboomp 1217091557 fix(agent): prevented subagent session_start busy race
Queued extension-delivered user messages when deliverAs is set and waited for session_start extension message sends before prompting subagents.

Fixes #1343
2026-05-25 18:48:06 +00:00
Can BölükandGitHub 47dab57559 Merge branch 'main' into farm/5c2ff3c3/report-finding-tool-agent-output-schema- 2026-05-25 21:42:35 +03:00
roboomp 8e5c7c9bf1 fix(bash): kept persistent shells after cancel
Stopped marking persistent bash sessions as permanently broken when the JavaScript abort or timeout race wins.

Stopped the Rust descendant kill-wave helper once no cancellation targets remain so later commands are not swept into old cancels.

Fixes #1347
2026-05-25 18:40:22 +00:00
can1357 a7af3900bd feat(coding-agent/task): added parent-aware labels to nested live task snapshots
- Updated nested task-rendering tests to use parent-qualified IDs for completed child task results.
- Updated in-flight nested snapshot expectations to verify parent-aware `Parent>Subtask` labeling.
- Documented the live nested task rendering behavior in the package changelog.
2026-05-25 20:27:22 +02:00
can1357 a5275b17ce feat(coding-agent): added hashline inline |TEXT matching for BOF/EOF
- Added inline `|TEXT` payload parsing for `"/"` before/after inserts, including BOF/EOF usage.
- Fixed inline anchor handling by resolving matching `|TEXT` bodies and handling whitespace-containing payloads.
- Added parser tests for `applyDiff` and `parseHashline` covering whitespace, matching, and non-matching inline `|TEXT`.
- Added nested live task fixtures and snapshot tests for ordered in-flight and completed child rendering.
- Documented hashline inline `|TEXT` behavior updates in CHANGELOG.
2026-05-25 20:24:44 +02:00
roboomp 14c7ddf7d0 fix(bash): returned on stalled cancellation
Raced bash execution against the JavaScript abort signal and timeout so the tool returns even when native shell cleanup does not settle.

Added regression coverage for native cleanup stalls on ESC abort and timeout.

Fixes #1347
2026-05-25 18:03:09 +00:00
roboomp 6e9cf81544 style: bun run fix 2026-05-25 18:01:45 +00:00
roboomp 6b14cf1f55 fix(coding-agent): coerced report_finding string priority to number for reviewer schema
The report_finding tool's priority is exposed as a string enum
("P0"-"P3") for ergonomics, but the reviewer agent and every
custom review agent declare priority as `type: number` in their
JTD output schema. The cast at executor.ts:1473 lied about the
runtime shape, so the auto-injected `findings[].priority` flowed
through as strings and every yield with at least one finding was
rejected with `findings.0.priority: expected number, received string`,
forcing the run into the schema_violation exit path.

Added `toReviewFinding(details)` in tools/review.ts that maps the
priority enum to its numeric ordinal via the existing PRIORITY_INFO
table and use it at the boundary in executor.ts. Render paths still
see the original `ReportFindingDetails` shape (string priority)
through normalizeReportFindings, so display formatting is unaffected.

Fixes #1350
2026-05-25 18:01:38 +00:00
Can BölükandGitHub a40864c5b2 Merge branch 'main' into farm/ccf5d9fd/csharp-lsp-plugin-doesn-t-work-with-omp- 2026-05-25 20:37:30 +03:00
roboomp 24b249219e fix(lsp): supported config-only marketplace servers
Loaded marketplace lspServers metadata from Claude plugin caches and embedded it for OMP marketplace installs so config-only plugins register without package code.

Fixes #1352
2026-05-25 17:34:32 +00:00
Can BölükandGitHub 29d0e3a470 Merge branch 'main' into farm/b4be9197/task-explore-agent-fails-with-schema-vio 2026-05-25 20:27:22 +03:00
roboomp ef68db17f5 fix(coding-agent/tools): stopped re-walking JTD-converted JSON Schema for nested JTD detection
The JTD-to-JSON-Schema converter post-processed convertSchema's
output with normalizeMixedSchemaNode, which walked back into the
emitted JSON Schema looking for nested JTD forms. Inside a
properties block, user-defined property names whose keys happened
to collide with JTD keywords ('ref', 'elements', 'values',
'optionalProperties', 'discriminator') were misclassified as JTD
forms and re-rewritten - corrupting properties like { ref: { type:
'string' } } into { $ref: '#/$defs/[object Object]' } and breaking
the built-in explore agent's output validator with
schema_violation: files.0.ref: must not be present.

convertSchema is already fully recursive and emits pure JSON Schema,
so the post-walk is both unnecessary and unsafe. Drop it.

Fixes #1345
2026-05-25 17:21:53 +00:00
can1357 079d18a82b fix(model-registry): fixed tp- token-plan baseUrl lost during discovery merge
- Extracted `mergeDiscoveredModel` so discovered baseUrl takes priority over bundled entry, fixing 401s on Xiaomi tp- token-plan streams.
- User providerOverride.baseUrl still wins over both discovered and bundled values.
- Added regression tests covering all merge priority paths.
2026-05-25 14:06:13 +02:00
can1357 d6acef8b76 perf(status-line): replaced index-based token cache with message sidecar cache
- Added Symbol-keyed sidecar on each AgentMessage to memoize estimateTokens, with a cheap content fingerprint to detect in-place mutations.
- Fixed stale cache on same-length replaceMessages, post-hoc error attachment, and branch rebuild edge cases.
- Fixed usage fetch error backoff: stamped fetchedAt on failure so the 5-min TTL also gates retries during outages.
- Extracted computeNonMessageBreakdown as shared helper to prevent drift between status-line and context panel token counts.
2026-05-25 14:06:05 +02:00
can1357 8e3e4fd5f0 fix(slash-commands): captured mode state before handler call for history
- Fixed /plan and /goal history preservation by snapshotting enabled state before handlePlanModeCommand/handleGoalModeCommand executes.
- Previous check read state after the call, missing cases where the handler itself toggled the mode off (e.g., confirmed exit).
- Added tests covering confirm-exit, cancel-exit, and first-activation paths.
2026-05-25 14:05:55 +02:00
can1357 81cec1c38b fix(clipboard): hardened WSL PowerShell fallback for headless environments
- Raised PowerShell timeout to 8s and swallowed reap errors to prevent unhandled throws on WSL interop.
- Fixed fallback logic so arboard is skipped when no display server is present on headless WSL.
- Added test coverage for the headless WSL short-circuit path.
2026-05-25 14:05:48 +02:00
can1357 79f6bf4f76 fix(session-manager): added orphaned backup recovery after EPERM rename
- Added `recoverOrphanedBackups` to promote `.jsonl..bak` files back to their primary path when the primary is missing, preventing data loss after a mid-rename crash.
- Changed backup filename from dot-prefixed to plain `..bak` so the shared `*.bak` glob can find it on both real and in-memory storage backends.
- Surfaced the original EPERM as the error `cause` and included both original and retry messages when rollback also fails.
2026-05-25 14:05:41 +02:00
can1357 975c836015 fix(image-resize): deferred OMP_NO_WEBP evaluation to call time
- Replaced baked module-load value with per-call `isWebPExcluded()` so runtime env changes take effect.
- Only `"1"` and `"true"` (case-insensitive) enable exclusion; empty string and `"0"` are treated as disabled.
- Fast path now bypassed for WebP sources when exclusion is active.
- Explicit error surfaced when decode fails and WebP exclusion cannot be honored.
2026-05-25 14:05:31 +02:00
can1357 e5bc511392 edit(hashline): leniently parse anchors with trailing |TEXT body and read/search decoration
Anchors are formatted by read/search as LINE+HASH|TEXT, and lines may be
prefixed with marker decoration (*, >, +, -). The parser previously required
a bare LINE+HASH and rejected verbatim copy-pasted anchors with:

  line N: expected a full anchor such as "119sr", ...; got "364sp|".

Loosen LID_CAPTURE_RE to allow optional leading decoration and an optional
trailing |... body on each anchor (including each side of a range).
2026-05-25 13:36:44 +02:00
can1357 3801b4ee32 fix(coding-agent): added configurable retry delay cap and surfaced rate-limit failure state
- Added `retry.maxDelayMs` to the settings schema and interfaces, with a default cap for provider backoff delays.
- Updated session auto-retry logic to fail fast when a requested wait exceeds the cap without fallback, emitting terminal auto-retry failure state.
- Propagated retry state and failure data into task progress and rendering so children show retry/wait details and reminder prompts stop after terminal errors.
2026-05-25 12:37:32 +02:00
roboompandcan1357 294f0067d0 fix(tui): refreshed model tabs by provider id
Separated model selector provider tab labels from provider ids so human-readable labels like Ollama Cloud refresh and filter the underlying ollama-cloud models.

Fixes #1153
2026-05-25 12:25:12 +02:00
roboompandcan1357 a2032850e5 fix(legacy-pi-compat): fall back to peer deps when resolveSync fails in binary mode
In a compiled binary, Bun.resolveSync(spec, import.meta.dir) throws
'Cannot find module' because import.meta.dir is inside /$bunfs/root
and the virtual FS exposes no node_modules tree at runtime.

Previously this throw propagated through rewriteLegacyPiImports ->
rewriteLegacyPiImportsForRuntime -> mirrorLegacyPiFile ->
loadLegacyPiModule -> loadExtension, which swallowed it as 'Failed to
load extension' and silently dropped any plugin whose files imported
@mariozechner/pi-ai (or any @mariozechner/pi-* whose bundled
counterpart isn't reachable via resolveSync in the binary).

Fix: wrap the resolution call in rewriteLegacyPiImports in a try/catch
and return the original match on failure. rewriteBareImportsForLegacyExtension
runs immediately afterwards in every call path and already resolves bare
specifiers against the importer's real filesystem directory, so it picks
up @mariozechner/pi-ai from the plugin's installed peer deps instead.

Apply the same fallback to resolveLegacyPiSpecifier (the Bun plugin
shim's onResolve handler) for tool/hook files loaded directly via Bun's
import system rather than through loadLegacyPiModule.

Fixes #1215
2026-05-25 12:22:57 +02:00
can1357 8e74996513 chore: adjust tests 2026-05-25 12:22:43 +02:00
Can BölükandGitHub 1084a854f8 Merge pull request #1296 from can1357/farm/93902d04/goal-set-rejects-active-goals-but-clears
fix(cli): allow /goal set to replace active goals
2026-05-25 13:20:46 +03:00
Can BölükandGitHub e4165a41e6 Merge branch 'main' into farm/bfe680ee/ctx-ui-notify-during-session-start-is-cl 2026-05-25 13:20:04 +03:00
Can BölükandGitHub acd64750e4 Merge pull request #1335 from TommyC81/feature/autoload-skills
feat: add autoloadSkills frontmatter field for agent definitions
2026-05-25 13:19:06 +03:00
Leo Kimandcan1357 4eb2919674 fix(coding-agent): incremental per-message token cache for status-line context% (avoid 1.1s freeze on long sessions)
Root cause (verified on user's environment):

- User commit `296641213` swapped status-line's context% computation from cheap `calculatePromptTokens(lastAssistantMessage.usage)` to `computeContextBreakdown(session)`, which walks EVERY message and runs native `countTokens` (~0.5 ms per message).

- The 2-second TTL cache helps for steady-state idle but every cache MISS is a full sweep.

- `updateEditorTopBorder()` is invoked on EVERY agent event (event-controller.ts:163 — `agent_start`, `delta`, `agent_end`, `tool_*`). Each delta during streaming can trigger a cache miss.

- User session has 2,312 messages → each full sweep is ~1,120 ms blocking.

- During streaming the UI freezes for ~1.1 s every ~2 s, producing the user-visible 'jittery rendering' ("버벅거림") and 'status bar disappearing' symptoms.

Fix:

`StatusLineComponent.getCachedContextBreakdown()` (renamed from `#getCachedContextBreakdown` so unit tests can exercise it directly) now uses an incremental per-message token cache that exploits the append-only nature of `session.messages`:

  1. Message tokens (the dominant cost): cached per-index. New messages are tokenized as they arrive; previously-cached messages are reused. The LAST message is always recomputed because its content may still be growing during streaming. Compaction (messages.length shrinks) resets the cache.

  2. Non-message tokens (system prompt + tools + skills): cached separately, invalidated only when a cheap inputs-identity fingerprint changes (model swap, skill toggle, tool registration). These rarely change during a session.

Required exposing three helpers from `modes/utils/context-usage.ts` (`estimateSkillsTokens`, `estimateToolSchemaTokens`, `computeNonMessageTokens`) so the status-line cache can call them directly.

Performance (2,300-message synthetic session, measured on user's M-series Mac):

  - COLD warm-up call: ~75 ms (one-time, runs at OMP startup before any streaming)

  - WARM refresh, no new message: ~0.04 ms (20 calls = 0.7 ms total)

  - WARM refresh, 1 new message: ~0.02 ms

vs. prior implementation:

  - Per cache-miss call: ~1,120 ms blocking

  - 28,000× speedup on warm-state refresh

`computeContextBreakdown` itself is untouched — `/context` slash command continues to use it, and its output matches the status-line context% for the same session state (parity preserved).

Tests: 6 new cases in `packages/coding-agent/test/status-line-context-cache.test.ts` covering cold/warm/append/compaction/non-message-invalidation/zero-messages and a perf smoke test asserting 20 warm refreshes on a 200-message session complete in <100 ms.

Full suite: 3,199 tests, 26 pre-existing failures (status-line accent / log_experiment timing-flaky / skills / github tool / workspace-tree / tool path — all unrelated and baseline-confirmed). Lint: 1 pre-existing import-order issue in `event-controller-plan-ready.test.ts` unchanged.
2026-05-25 12:11:15 +02:00
Leo Kimandcan1357 b373c54cd7 fix(coding-agent): guard sendCompletionNotification on aborted/error stopReason
Bug: Ctrl+C on the ask tool selector threw ToolAbortError, the turn
ended with stopReason === "aborted", and handleBackgroundEvent fired
sendCompletionNotification() unconditionally — producing a misleading
"Task complete" desktop toast for a turn that never actually completed.

Fix mirrors the stopReason filter already used by
#currentContextTokens, #handleMessageEnd, and the retry / TTSR /
compaction skip paths across agent-session.ts: check the most recent
assistant message via session.getLastAssistantMessage() and return
early when stopReason is "aborted" or "error".

Test coverage (event-controller-abort-guard.test.ts, 6 cases):
- aborted   -> 0 sendNotification calls
- error     -> 0 calls
- stop      -> 1 call (normal completion)
- no last assistant message -> proceeds (defensive)
- isBackgrounded=false (foreground) -> still 0
- completion.notify=off -> still 0

Matching guard applied to the standalone desktop-notify extension
(~/.omp/agent/extensions/desktop-notify/index.ts) which is currently
the live producer of completion toasts after Phase 1 of
seed_0ca7e1143ac1.
2026-05-25 12:08:36 +02:00
Can BölükandGitHub ffdb2fdd6b Merge branch 'main' into feat/no-webp-llama-cpp 2026-05-25 13:00:46 +03:00
Can BölükandGitHub 98603c669b Merge branch 'main' into farm/7f8acce1/loop-mode-can-auto-submit-again-before-t 2026-05-25 12:58:57 +03:00
roboomp 84eb837b00 fix(session): handled eperm during session rewrite
Replaced overwrite-style session rewrites with an EPERM fallback that moves the old session file aside before retrying and restores it if the retry fails.

Added regression coverage for active-session rewrite recovery so the session remains writable after the fallback.

Fixes #1337
2026-05-24 18:00:42 +00:00
Tommy Carlsson 5b35cd626b feat: add autoloadSkills frontmatter field for agent definitions
Adds optional autoloadSkills field to agent frontmatter that automatically loads listed skills when a sub-agent is spawned. Uses the same buildSkillPromptMessage + sendCustomMessage mechanism as interactive skill loading, queued via sendCustomMessage({ triggerTurn: false }) before the first session.prompt(task). No extra agent turns, no new injection path. Skills stay in listing for sub-resource access. Compaction behavior matches manual loading. Unknown skill names silently skipped.

Lore-id: f85fdbdc
Constraint: autoload must use buildSkillPromptMessage + sendCustomMessage, never modify systemPrompt or use contextFiles
Constraint: triggerTurn must be false to avoid extra agent turns
Rejected: append to systemPrompt | agent cannot distinguish skill content from own instructions
Rejected: contextFiles injection | agent sees opaque file blob, cannot discover sub-resources
Rejected: promptCustomMessage per skill | N extra agent turns with model inference
Directive: autoload skill names are resolved against parent session skill list at spawn time in task/index.ts
Tested: TypeScript compiles clean with tsc --noEmit
Tested: parseAgentFields parses array and CSV string frontmatter
Tested: parseAgentFields returns undefined for absent and empty fields
Not-tested: bun test cannot run locally due to missing pi_natives native addon (requires Rust toolchain)
Confidence: high
Scope-risk: moderate
Reversibility: clean
2026-05-24 19:35:40 +04:00
roboomp a916ae512e fix(coding-agent): preserved startup extension notifications
Keep chat notifications emitted during session_start visible after the initial transcript render rebuilds the chat container. Add regression coverage for preserving startup notifications during initial render.

Fixes #1316
2026-05-23 19:59:55 +00:00
Chris Danis 72544278f1 feat: add OMP_NO_WEBP env var to exclude WebP from image resize
Gated WebP encoding behind OMP_NO_WEBP environment variable so that local
llama.cpp vision models (which use the STB library that lacks WebP
decoding support) can accept browser snapshots without returning HTTP 400.

Upstream reference: cline/cline PR #9837
(https://github.com/cline/cline/pull/9837) implements a similar workaround
for the same llama.cpp STB WebP incompatibility.
2026-05-23 15:48:03 -04:00
roboomp 5573270e5e fix(loop-mode): block auto-submit while post-prompt background work is pending
When session.prompt() returns, idle-flush tasks for async-job result
deliveries are scheduled via #schedulePostPromptTask (1ms delay) and
added to #postPromptTasks immediately.  The 800ms loop timer could fire
in that window before isStreaming became true, causing the loop to
submit the next prompt while the delivery turn was still pending.  The
delivery then hit AgentBusyError and the job result was silently dropped.

Add AgentSession.hasPostPromptWork (= #postPromptTasks.size > 0) and
include it in #isLoopAutoSubmitBlocked() alongside isStreaming and
isCompacting.  Add a regression test that verifies the loop defers when
hasPostPromptWork is true and fires once it becomes false.

Fixes #1294
2026-05-22 13:41:17 +00:00
Can Bölük 3b072a10b9 Merge remote-tracking branch 'origin/farm/a46597ca/clipboard-image-paste-ctrl-v-silently-fa' 2026-05-22 22:40:03 +09:00
roboomp ccba77c5c7 fix(cli): allowed goal set to replace active goals
Allowed /goal set to replace the current active goal instead of rejecting and discarding the command input.

Added goal runtime and interactive-mode regression coverage for active replacements.

Fixes #1293
2026-05-22 13:23:06 +00:00
roboomp 00233b24fa style: bun run fix 2026-05-22 09:47:52 +00:00
roboomp 8f83cbd9a9 fix(clipboard): route image reads through powershell.exe on WSL
WSLg exposes WAYLAND_DISPLAY, so readImageFromClipboard() took the
native arboard path on WSL2. arboard::Clipboard::get_image() returns
ContentNotAvailable on WSLg because the Wayland clipboard does not
carry image payloads from the Windows clipboard, and that surfaced as
silent 'No image in clipboard' on Ctrl+V.

Detect WSL via WSL_DISTRO_NAME / WSL_INTEROP and read the image with a
PowerShell one-liner that emits base64-encoded PNG bytes from
[System.Windows.Forms.Clipboard]::GetImage(). Fall back to the native
bridge when PowerShell returns nothing, exits non-zero, or is missing,
so non-WSLg Wayland setups continue working unchanged.

Fixes #1280
2026-05-22 09:47:47 +00:00
can1357 6ca92dd08d test(coding-agent): increased bash abort test timeout and runtime
- Extended the abort scenario shell command from a 5-second sleep to 60 seconds.
- Raised the corresponding test timeout to 15,000 ms for the abort test case.
2026-05-22 18:06:50 +09:00
can1357andCan Bölük ebd2f77770 feat: implemented canonical § hashlines with ≔/""/" ops in hashline parser
- Changed hashline format to canonical `§` section headers and `"`/`"`/`≔` operations across grammar, parser, and docs.
- Reworked range and op parsing so single anchors are valid, legacy `-`/`-=` ops error, and empty `≔` payloads now delete ranges.
- Removed legacy `HL_EDIT_SEP`, `$HSEP$`, and `hsep` plumbing, adopting raw payload lines.
- Updated execution, input, renderer, and streaming flows to use `HL_FILE_PREFIX` and `HL_OP_CHARS` helpers.
- Updated session-stats parsing to `§`/`≔`/`"`/`"` format, patch envelopes, and bumped parser versions.
- Removed the hashline-separator benchmark script and its PI_HL_SEP job orchestration.
2026-05-22 17:46:53 +09:00
can1357andCan Bölük 2ebb55134e fix(coding-agent): adjusted reasoning-disable handling and title generation for reasoned models
- Updated OpenAI completions parameterization to honor `disableReasoning` on effort-based compatible models by sending the minimum supported effort.
- Expanded commit and title generation token budgets so reasoning models can return output after internal thinking while non-reasoning calls keep existing limits.
- Switched title generation to request a `set_title` tool call, added extraction from tool-call arguments, and updated tests for the new behavior.
2026-05-22 15:51:32 +09:00
can1357 4ada748c61 feat(modes): added ANSI-capable shimmer accents to loading messages
- Loading message rendering now derived session-specific accent colors and applied them to shimmer output when a session name was available.
- Shimmer palettes were updated to accept raw ANSI color values as well as theme color names during compilation.
- A unit test was added to confirm shimmer text rendered with a supplied ANSI crest color.
2026-05-22 15:40:58 +09:00
can1357 a13c9bf6fc feat(coding-agent): added SettingsList#setItems with clamped selection
- Added SettingsList#setItems to replace items and clamp selection to a valid index after updates.
- Updated SettingsSelector to rebuild active memory items on backend changes and skip refresh when appropriate.
- Switched MCP wizard and command spinners to theme frames with themed initial frame and 80ms updates.
- Reworked welcome intro animation for a 3-second eased sweep with optional shine blending.
- Added memory backend refresh tests and aligned package changelogs with the updated behavior.
2026-05-22 13:19:35 +09:00
can1357andCan Bölük 796f963da9 feat(coding-agent): added coding-agent follow-up queue with onBeforeYield
- Added optional `onBeforeYield` configuration and `setOnBeforeYield` in Agent, executed before follow-up checks.
- Added `YieldQueue` to `AgentSession`, with setup/teardown and streaming/idle flush via `setOnBeforeYield`.
- Replaced immediate async-result follow-up dispatch with queued batch entries, including stale-state suppression.
- Added MCP follow-up queueing in SDK, deduplicating updates by `serverName` and `uri`.
- Added changelog entries for `onBeforeYield`, async-result batching, MCP dedupe, and `display.shimmer` modes.
- Added yield queue unit tests for streaming emission, debounced idle batches, stale filtering, and error isolation.
2026-05-22 13:08:51 +09:00