[release] v0.106.1 - #5532
Open
github-actions[bot] wants to merge 199 commits into
Open
Conversation
…playground and closes the Advanced drawer The production webpack build stubbed out react-syntax-highlighter's dynamic import of refractor/all via an IgnorePlugin. When the agent chat markdown renderer (AgentChatSlice/assets/markdown.tsx, PrismAsync) highlighted a fenced code block, that ignored chunk threw "Cannot find module 'refractor/all'", tripping the Layout error boundary and remounting the playground subtree, which unmounted the open Advanced drawer. refractor@5 is installed and resolves every subpath rsh imports (all 297 languages plus /all and /core), so the ignore was stale and purely harmful. Remove it so the chunk loads. Claude-Session: https://claude.ai/code/session_01Hyn9365BLPXDmNZShrQkmH
Bumps [esbuild](https://github.com/evanw/esbuild) from 0.23.1 to 0.28.1. - [Release notes](https://github.com/evanw/esbuild/releases) - [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG-2024.md) - [Commits](evanw/esbuild@v0.23.1...v0.28.1) --- updated-dependencies: - dependency-name: esbuild dependency-version: 0.28.1 dependency-type: direct:development ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [@opentelemetry/core](https://github.com/open-telemetry/opentelemetry-js) from 2.0.1 to 2.8.0. - [Release notes](https://github.com/open-telemetry/opentelemetry-js/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-js/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-js@v2.0.1...v2.8.0) --- updated-dependencies: - dependency-name: "@opentelemetry/core" dependency-version: 2.8.0 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [axios](https://github.com/axios/axios) from 1.16.0 to 1.18.0. - [Release notes](https://github.com/axios/axios/releases) - [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md) - [Commits](axios/axios@v1.16.0...v1.18.0) --- updated-dependencies: - dependency-name: axios dependency-version: 1.18.0 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com>
…ages/agenta-shared/axios-1.18.0
The playwright suites are owned and type-checked by the tests workspace, which holds the @playwright/test dependency; tests/manual scripts import state modules that no longer exist.
- Restore Parameter, CorrectAnswer and _EvaluationScenario to lib/Types.ts (removed by cleanup while consumers remained) - Re-export MetricColumnDefinition from the EvalRunDetails table barrel - TooltipButtonProps was renamed EnhancedButtonProps; statusMap moved to @agenta/entity-ui/variant - Synthesize full Parameter objects in UseApiContent
- useRunMetricData: type selection as the unwrapped value, not the atom - Webhook builders: narrow WebhookFormValues union before field access - filtersAtom: accept updater functions in the write signature - Organization settings: drop stale react-query v4 useErrorBoundary and migrate setQueriesData to the v5 filters shape - evaluations/utils: surface variantId from invocation metadata - PreviewTableRow: add index signature required by InfiniteTableRowBase
Mirrors the vetted WP-4e-2a in-place fixes from fe-chore/move-evals-to-packages (adapted to OSS import paths) plus new fixes for the component layer: - restore PreviewTestCase to lib/Types; re-export MetricProcessor/MetricScope - add "input" to EvaluationColumnKind (backend mapping emits it) and type the visibility-label column extension in buildPreviewColumns - recharts v3 API drift in EvaluatorMetricsChart (TooltipContentProps, tuple radius, MetricStripEntry contextual typing) - widen evaluationType to EvaluationRunKind; type query atoms as nullable - latent runtime bugs typed as-is per WP-4e-2a convention (applyAggregatesToRaw, metricProcessor ReferenceErrors, dead metric-group branches) - flagged, not fixed
…ant id - createPaginatedEntityStore: refreshAtom/actions.refresh accept an optional value or updater (bare set() still bumps the counter) - clears the 'Expected 0 arguments' cluster across testset modals and other consumers - EnvironmentStatus: variant.id optional; the component already guards it
…ing layers; oss tsc 347->105 Parallel per-area pass, behavior-preserving throughout (latent runtime bugs are typed as-is with NOTE comments per the WP-4e-2a convention, not silently fixed): - TraceSpanNode OSS<->entities dual-type: aligned at every crossing with documented boundary casts (16 errors -> 0); annotations field added to the OSS node (drawer stores attach it at runtime) - SharedDrawers: broken SessionDrawerButton imports repaired, JSON-schema access typed, null-safety in SelectEvaluators/AnnotateDrawer, drawer payload/ref/label types aligned with runtime - observability: extended-column types for custom antd props, TraceRow/ SessionRow InfiniteTableRowBase conformance, traceTabsAtom updater support, ag-attributes selector typing at the producer - playground/url-state: removed drifted local duplicates of package types, eagerAtom->atom where deps are sync, modal/store prop alignment - onboarding/testsets/org: updater-widened widget UI atom, tour placement vocabulary fix, OnboardingLoader next/dynamic compat, org provider API types matched to the backend wire shape (settings/flags dicts) - EvalRunDetails remainder: WP-4e-2a-vetted atom fixes adapted, recharts v3 formatter/content signatures, stale import paths repointed Flagged for triage (typed as-is): AddToTestsetDrawer trace draft discard/ update call missing molecule actions; orphaned SessionDrawerButton
…atterns; oss tsc 105->82 - InfiniteVirtualTable: canonical ExtendedColumnType exported from the barrel (three local extended-column copies repointed as aliases); pure read fn for columnHiddenKeys (write path reconciles versions); memo generic preservation; onRow/getRowProps/rowSelection.fixed aligned with antd 6 - antd v6 PopoverStylesType 'body' drops typed as-is (2 sites, existing pattern) - React 19: JSX.Element -> ReactElement in RequireWorkflowKind - AgentaNodeDTO: trace_id/span_id added (backend SpanDTO sends them) - Org.default_workspace: list endpoint strips it - both lookups are latent dead code, typed as-is with comments - FiltersPreview: operatorLabel is a display string, not the operator union
Adds a mic button to the agent-chat composer that dictates speech to text via the browser Web Speech API. Words stream into the Lexical editor live as you speak (interim + finalized), and the result is fully editable before sending. Transcribes to plain text, so it is independent of any model/audio capability — the model receives words, not audio. The mic is hidden where SpeechRecognition is unavailable (e.g. Firefox), and shows a clear state while recording plus a mic-permission-denied message. New: hooks/useVoiceInput.ts (typed SpeechRecognition wrapper), components/VoiceInputButton.tsx (composer-prefix mic).
Adds a second voice mode alongside voice-to-text. 'Voice message' records mic audio via MediaRecorder and drops the clip into the composer attachment tray (addFiles), same path as a picked/dropped file; 'Voice to text' transcribes as before. A mode toggle (persisted) switches between them, and only browser-supported modes are offered. The recorded audio rides the normal attachment flow, so nothing here depends on the wire-contract or model work — it produces an audio File up to the send boundary. audio/* is now an accepted attachment type. New: hooks/useAudioRecorder.ts (MediaRecorder → File, elapsed timer, permission/error, cleanup).
Fleshes out the voice-message flow into a proper state machine instead of the tap/tap minimum:
- Recording takeover (RecordingBar) covers the composer while capturing: live timer, input-level meter (Web Audio), and distinct Discard (cancel) vs Stop & attach (keep) exits. Esc discards.
- Permission-pending ('Waiting for microphone…') and a persistent, dismissible denied/error strip above the composer — no more hover-only tooltip.
- Hard 5-min cap with a countdown near the limit; sub-0.7s / empty takes are discarded, not attached.
- Recorded clips play back in the tray (AudioChip: play/pause + elapsed) before sending.
The recorder is owned by AgentConversation so the takeover can cover the whole input; the mic just starts it. audio/* accepted; the clip still rides the normal attachment path.
Recording a voice message is the primary action; voice-to-text is the alternative. Also orders the mode menu primary-first. Falls back to dictation only where MediaRecorder is unavailable.
The waiting state read as an error and was mis-laid-out: - Actions now right-align (ml-auto). Previously the discard button sat jammed against the label, because the waiting state has no flex-1 meter to push it over. - Red border only once actually capturing. Red reads as 'live'; waiting on the mic is neutral, so it now uses the normal border with a softly pulsing dot instead of an inert grey one. - Copy is actionable rather than passive: 'Allow microphone access to start recording' (vs 'Waiting for microphone...'), and the buttons say 'Cancel' / 'Delete recording' / 'Attach to message'. - Overlay geometry: mb-3 moved from the input to the wrapper so the bar covers the composer box exactly (inset-0) — the input no longer peeks out below. - role=status + aria-live so the state change is announced.
…th motion Every voice surface popped in/out with no transition. Now they animate on the slice's existing idioms rather than bespoke ones: - Mic permission/error notice -> new MicPermissionNotice using RevealCollapse (the shared composer-chrome enter/leave, same as ConnectModelBanner and the HITL dock), with the message latched in a ref so the text survives the collapse instead of vanishing mid-animation. - Recording takeover -> AnimatePresence cross-fade + slight rise/fall on SESSION_SPRING, the same physics the session rail and tag bar use. - Within the bar, the waiting -> capturing swap is a wait-mode cross-fade (labels never overlap); the attach button springs in; the '30s left' warning fades; and the border, dot and timer colours ease via transition-colors instead of snapping.
…e it up Corner artefact on transition: the bar was rounded-xl over a rounded-lg composer, so the input's corners poked out from under it mid-cross-fade. The bar now mirrors the composer's box exactly — rounded-lg, --ag-composer-border, --ag-colorBgContainer, --ag-surface-chat-shadow — so the transition reads as the input changing state rather than a second card on top. Sizing: the content was set against 12px defaults and read as too small inside the taller editor. Label and timer to text-sm, status dot 10->12px, action icons 16->18px, level bars taller and wider, and roomier gap/padding.
…on, and drop the takeover flash Two problems behind the sluggish, flashy recording transitions. Perf: useAudioRecorder is owned by AgentConversation (so the takeover can cover the composer), but it held the input level in React state and wrote it every animation frame — re-rendering a ~2400-line component 60x a second. Level and elapsed now live in a ref that RecordingBar samples itself, so only that small component repaints. AgentConversation re-renders on status/error only. Flash: an instantly-resolved permission request (already granted, or already denied) faded the takeover in and straight back out before the denied banner expanded — three animations for one click. The takeover now appears immediately when recording, but only after a 350ms grace period while a request is still pending, so instant resolutions never render it.
The recorder was mixing an rAF meter loop, a 200ms polling interval, and a second rAF in the UI. Split on the property that actually matters — rAF pauses in a background tab, timers do not: - rAF drives everything painted (input level + the derived clock). Pausing while hidden is correct: nothing is on screen, and it stops burning battery on an invisible meter. - A single setTimeout enforces the max-duration cap, because that must still fire when the tab is backgrounded and rAF is parked. It replaces a 200ms poll: one deadline, not 1500 wakeups over a 5-minute take. - Elapsed is derived from a start timestamp instead of accumulated by a ticker, so it cannot drift and survives a paused loop. Also quantises the readout to what is visible — N discrete bars and a 1Hz clock — so the 60Hz loop only triggers a render when a bar lights or the second rolls over, rather than on every frame.
Cancel (and Esc) did nothing in the waiting state: it called stop() on recRef, but no MediaRecorder exists until getUserMedia resolves, so it was a no-op on null and the bar just sat there. Cancel now branches — stop the recorder when there is one, otherwise tear down and return to idle immediately. The browser's permission prompt can only be dismissed by the person, so the pending request is neutralised instead: if it later resolves, the stream's tracks are stopped at once rather than starting a recording that was backed out of, and if it rejects, no denied banner is shown for a request the person already abandoned.
A page cannot dismiss a permission prompt — getUserMedia takes no AbortSignal and there is no API to close it — so our waiting takeover offered a cancel that could not cancel, and covered the composer while the browser owned the interaction. The takeover is now capture-only. Awaiting permission is shown on the mic itself: it pulses, is disabled (a second press only queues another request), and its tooltip points at the browser's prompt. Backing out is the prompt's own job; if it later resolves the stream is still dropped rather than starting a recording nobody asked for. RecordingBar loses its requesting branch entirely. Also splits denied from dismissed: Chrome rejects identically for both, so the permission store is consulted and we no longer tell someone to change browser settings when they merely dismissed the prompt and could just try again.
The seven threshold bars were a level meter — they showed loudness, not the take. Replaced with a rolling waveform: each slice is the FFT magnitude of one moment (voice band only, the top of the spectrum is mostly hiss), appended on the right so the recording scrolls leftward as it is spoken, older slices receding. It shows the shape of what was actually said. Drawn on a canvas from the animation frame, which also removes it from React entirely: the previous meter had to quantise its level into discrete lit-bar counts purely to avoid repainting its parent at frame rate. Now the only React state left in the bar is the clock, at 1Hz. Splits the concerns too — the hook owns the audio graph and exposes the analyser; the view owns sampling and drawing.
A recording attaches like any other file, so the attachment guardrails could reject it after the fact — you record, hit attach, and the take is gone. - At the file limit the mic is now disabled for voice-message mode (as the paperclip already was), rather than letting someone record a take that can only be rejected. Dictation is unaffected: it writes into the editor, not the tray. - Pins the recorder to 64kbps. The default bitrate is unspecified, and a full-length take at a high one lands near the per-file size cap — the same silent-destruction path, just at the end of a five-minute recording. 64kbps is ample for voice (~2.4MB at the cap).
… tray A sent voice message rendered as an inert file card — you could record and send one but never hear it back. Audio parts now render an inline player in the transcript. Extracts the tray's bespoke player into a shared AudioPlayer used by both surfaces, so a voice message behaves the same before and after sending, and adds a progress bar. Also resolves the duration properly: a MediaRecorder webm reports an infinite duration until it has been seeked to the end, so the player nudges it there once and reads the real value back (guarded, so the seek never surfaces as a wild current-time reading). Previously every recording showed no duration at all.
…a take is in flight Two remaining voice gaps. Dictation errors (a denied mic, a recognition failure) only ever appeared in the mic's tooltip — the same hover-only trap the recording path already moved away from. They now feed the shared MicPermissionNotice, so both voice modes report failures the same visible way. Only the error is lifted; the transcript stays inside the button because it changes far too often to re-render the conversation with. A file dropped or pasted mid-recording could also take the last tray slot, so the take was rejected — and destroyed — on attach. Drops and pastes are ignored while capturing (the composer is covered by the recording bar anyway). Guarded at the entry points rather than in addFiles, because the recorder's own completion calls that directly and must always get through.
…light The bar was red four times over — border, dot, waveform, and the near-limit timer — so it read as an error state, and the one thing that should escalate had nothing left to escalate with. - Border moves to brand. An error border is the form-validation signal; nothing about recording is invalid. - Waveform moves to a brand tint: a single horizontal gradient across the strip, faint at the old end and near-full at the newest, so age reads as depth rather than needing a second colour. Replaces the per-bar globalAlpha ramp — one gradient built per resize, so it is also less work per frame. - Red now means exactly one thing: the record light (and the genuine near-limit warning).
AGENTA_SESSIONS_RECONSTRUCT, AGENTA_RECORDS_DURABLE, and
NEXT_PUBLIC_SESSIONS_LAST_MESSAGE_ONLY now read as enabled unless set to the
literal "false". Absent and empty both mean on, because the compose files pass
the vars through as ${VAR:-}, which materializes an empty string that overrides
env_file values.
The web-identity JWT was hardcoded to 15 minutes, so SeaweedFS capped every mount credential at 900s regardless of the requested 3600s. Mint the token with the requested lifetime (capped at the 12h session ceiling), clamp DurationSeconds into each backend's valid range, make the TTL configurable via AGENTA_MOUNTS_CREDENTIALS_TTL_SECONDS, and raise instead of returning never-expiring credentials when an STS response carries no usable Expiration. Claude-Session: https://claude.ai/code/session_01BKPLpy1rUTBj5XktkP5eKY
…y die The session pool re-armed its expiry bookkeeping from each dispatch's fresh sign, which never reaches the running geesefs daemons, so active conversations reused mounts whose credentials had died (EACCES on every path, issue #5516). Record the expiry of the credentials actually installed at mount time, park from that installed lease, and evict to a cold rebuild when the lease cannot cover a worst-case turn plus clock skew. Claude-Session: https://claude.ai/code/session_01BKPLpy1rUTBj5XktkP5eKY
…egrading A null capability map has two causes: a schema with no x-ag-harness-ref (the pre-catalog controls are correct), or a catalog the browser could not reach. The drawer rendered both identically, so a failed request looked like a stale frontend build and gave the user nothing to act on. Track the query's error state and, when the schema did ask for the catalog, show a retry notice above the basic controls.
…ctivity Local turn-settle bump used Date.now() directly, which could overwrite a newer server heartbeat under clock skew and briefly sink the session in history. Use Math.max, matching the reconciler. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Rebuilt on top of current release/v0.106.1 instead of merging the stale dependabot branch forward (it predated several since-merged changes: the axios alignment fix, the native-tsc-trial scripts, and a version bump, all of which the stale branch's diff would have reverted). Aligns oss and the repo-wide pnpm.overrides floor with ee, which was already bumped to 15.5.21 in an earlier, narrower dependabot PR. Includes the lockfile regen that bump was missing (agenta-playground-ui's floating peer range doesn't auto-follow a floor bump; tightened to >=15.5.21 so pnpm can't keep resolving 15.5.18 there). Security-relevant: 15.5.21 fixes several CVEs — DoS in Server Actions, a Middleware/Turbopack single-locale proxy bypass, SSRF via rewrite destination hostnames, SSRF in Server Actions on custom servers, and response-body cache confusion. Verified: tsc --noEmit clean for both oss and ee, pnpm why next shows a single resolved version workspace-wide, and `pnpm build-oss` completes successfully. Not fixed here: `pnpm build-ee` still fails on a pre-existing, unrelated webpack error (react-syntax-highlighter's PrismAsync pulling in refractor's ESM-only per-language subpaths) — confirmed present identically before and after this bump, so it needs its own fix. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
[fix] Sort playground chat sessions by last message [AGE-4016]
…dled-file editors Uploading a skill package with a folded YAML description showed the literal ">-" in the Description field, and edits made just before switching bundled files were dropped by the shared editor's 300 ms debounce. - Parse SKILL.md frontmatter with js-yaml; accept name/description only as strings, and fall back to the body alone on invalid YAML. - Key the bundled-file editor by selected index and disable its debounce so a file switch cannot cancel a pending edit or leak undo history. - Cover the parser table in unit tests and the full upload flow in a new Playwright acceptance spec with an in-memory zip fixture. Claude-Session: https://claude.ai/code/session_017pBNyrqbAFZhWG9WTQ9siv
[fix] Tell the user when the model catalog fails to load
…lity [5541] fix(frontend): Fix skill description parsing and bundled file editing
The agenta_cloud EE Docker build was failing: "Module not found: ESM packages (refractor/x) need to be imported" from react-syntax-highlighter's PrismAsync, for every one of refractor's ~300 per-language subpaths. EE recompiles oss's source directly (../oss/src/... in its own webpack context) rather than consuming a built @agenta/oss package, so it needs every package that source imports resolvable from its own dependency tree. react-syntax-highlighter was declared only in oss/package.json, so ee/node_modules/react-syntax-highlighter never existed — oss had its own symlink into the pnpm store, ee had none. Without it, Next's build-time module classification for this package (bundle vs. external, ESM handling) diverged between the two apps even though they share identical next.config.ts, next version, and webpack setup, and oss's own build of the exact same route/component chain succeeded throughout. Fix: declare react-syntax-highlighter directly in ee/package.json, matching oss's version. Ruled out first: a next 15.5.18 vs 15.5.21 version mismatch (aligning versions either direction did not change the failure) and adding react-syntax-highlighter to transpilePackages (made things worse — broke oss's previously-working build too). Verified the actual fix with a fully clean rebuild (no turbo/next cache): `pnpm build-ee` completes successfully end to end (8/8 tasks), and tsc --noEmit stays clean for both apps. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…-5516 [AGE-4000] fix(runner): rebuild agent mounts before STS credentials expire
…/archive endpoints Adds a unit regression test pinning the epoch-ms/seconds mtime bug in stream_mounts_archive, plus acceptance coverage for the shallow (depth=1) listing and the download-all archive endpoint (/mounts/files/export) — the two gaps called out in #5416. _rollup_recent_entries already had coverage from #5411, so this PR doesn't touch it. Closes #5416
Clean up FakeMountStorage._mtimes on delete_keys so a recreated key can't inherit a stale timestamp. Assert the zip member's converted date_time explicitly, verified against the real stream_zip output, so a regression that ignores mtime and falls back to datetime.now() would still fail this test.
…ests [5416] test(api): Regression and acceptance tests for mounts file/archive endpoints
feat: turn the session-storage rework on by default
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.
New version v0.106.1 in