Skip to content

[release] v0.106.1 - #5532

Open
github-actions[bot] wants to merge 199 commits into
mainfrom
release/v0.106.1
Open

[release] v0.106.1#5532
github-actions[bot] wants to merge 199 commits into
mainfrom
release/v0.106.1

Conversation

@github-actions

Copy link
Copy Markdown
Contributor

New version v0.106.1 in

  • web
    • web/oss
    • web/ee
  • services
  • api
  • sdks
    • sdks/python
  • clients
    • clients/python
    • clients/typescript
  • kubernetes
    • kubernetes/helm

mmabrouk and others added 30 commits July 14, 2026 23:09
…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>
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.
mmabrouk and others added 10 commits July 29, 2026 22:32
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]
mmabrouk and others added 2 commits July 30, 2026 10:49
…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
Yuvakunaal and others added 3 commits July 30, 2026 11:43
…/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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XL This PR changes 500-999 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants