Loading workspace insights... Statistics interval
7 days30 daysLatest CI Pipeline Executions
1deaa299 fix(sandbox): make file-diff failures observable and correct (#914) (#917)
* fix(sandbox): make file-diff failures observable and correct (#914)
Follow-up to #892. The sandbox file-diff subsystem was built on a
"never throws, fall back to ''/empty, don't log" contract, so a
git/exec/fs failure silently became empty/wrong data.
- diff(): synthesize an add-patch for any file git isn't tracking
(a created file AND every later edit), keyed on tracked-ness at the
baseline rather than event.type; a tracked file identical to the
baseline still diffs empty, and a transient git-show probe failure no
longer fabricates a bogus add-patch. Synthesized patches follow git's
add-file shape (diff --git header, new file mode, no-newline marker).
- git-ignored files are withheld from the diff feed (the event still
fires; diff() returns '') so a .env/secret is never surfaced.
- exec-poll watcher no longer fabricates phantom create/delete storms:
a failed poll preserves the previous snapshot, a failed/partial initial
poll seeds without diffing (re-baselining on the first complete poll),
and a partial (permission-denied) poll is merged, not diffed.
- watcher watches the definition workspace.root (was defaulting to
/workspace, diverging from enrichment); native watch re-seeds if its
initial listing fails; teardown always destroys even if stop() rejects.
- every swallowed git/exec/fs failure now logs (real anomalies under
errors/warn, expected-empty under the sandbox debug category).
* docs(sandbox): document file-diff observability behavior
Cover the git-ignored-file withholding, the untracked-file synthesized
diff, and that swallowed failures now log; align the middleware SKILL
hook-error claim with the actual errors category.
* ci: apply automated fixes
* fix(sandbox): escalate persistent find-poll throws to warn
A steady-state `find` poll throw was logged only under `sandbox` (off by
default). A *persistent* mid-run exec failure (seam wedged, `find` gone)
then leaves the watcher silently dead for the rest of the run with no
signal at default verbosity — the silent-degradation class this change
set out to eliminate.
Distinguish teardown (`controller.signal.aborted` → quiet `sandbox`) from a
genuine failure, and escalate to `warn` after 3 consecutive non-teardown
throws so a wedged watcher is observable while a single transient blip
stays quiet. Honors the observability doc's "real anomalies → errors
category (on by default)" contract on the one path that hid one.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Tom Beckenham <34339192+tombeckenham@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> 1deaa299 fix(sandbox): make file-diff failures observable and correct (#914) (#917)
* fix(sandbox): make file-diff failures observable and correct (#914)
Follow-up to #892. The sandbox file-diff subsystem was built on a
"never throws, fall back to ''/empty, don't log" contract, so a
git/exec/fs failure silently became empty/wrong data.
- diff(): synthesize an add-patch for any file git isn't tracking
(a created file AND every later edit), keyed on tracked-ness at the
baseline rather than event.type; a tracked file identical to the
baseline still diffs empty, and a transient git-show probe failure no
longer fabricates a bogus add-patch. Synthesized patches follow git's
add-file shape (diff --git header, new file mode, no-newline marker).
- git-ignored files are withheld from the diff feed (the event still
fires; diff() returns '') so a .env/secret is never surfaced.
- exec-poll watcher no longer fabricates phantom create/delete storms:
a failed poll preserves the previous snapshot, a failed/partial initial
poll seeds without diffing (re-baselining on the first complete poll),
and a partial (permission-denied) poll is merged, not diffed.
- watcher watches the definition workspace.root (was defaulting to
/workspace, diverging from enrichment); native watch re-seeds if its
initial listing fails; teardown always destroys even if stop() rejects.
- every swallowed git/exec/fs failure now logs (real anomalies under
errors/warn, expected-empty under the sandbox debug category).
* docs(sandbox): document file-diff observability behavior
Cover the git-ignored-file withholding, the untracked-file synthesized
diff, and that swallowed failures now log; align the middleware SKILL
hook-error claim with the actual errors category.
* ci: apply automated fixes
* fix(sandbox): escalate persistent find-poll throws to warn
A steady-state `find` poll throw was logged only under `sandbox` (off by
default). A *persistent* mid-run exec failure (seam wedged, `find` gone)
then leaves the watcher silently dead for the rest of the run with no
signal at default verbosity — the silent-degradation class this change
set out to eliminate.
Distinguish teardown (`controller.signal.aborted` → quiet `sandbox`) from a
genuine failure, and escalate to `warn` after 3 consecutive non-teardown
throws so a wedged watcher is observable while a single transient blip
stays quiet. Honors the observability doc's "real anomalies → errors
category (on by default)" contract on the one path that hid one.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Tom Beckenham <34339192+tombeckenham@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> de5fbb52 feat(ai-gemini): Gemini Omni Flash video generation via the Interactions API (#886)
* feat(ai-gemini): support Gemini Omni Flash video generation via the Interactions API
Add gemini-omni-flash-preview to the Gemini video adapter. Omni only
serves the Interactions API (generateContent rejects it with 400), so
the adapter now routes by model: Veo models keep the
:predictLongRunning operations flow, while Omni creates a background
interaction with response_modalities: ['video'], polls it by id, and
returns the inline base64 MP4 as a data: URL (Files-API URI delivery
passes through). Usage maps from output_tokens_by_modality, size maps
onto response_format.aspect_ratio, and
modelOptions.previous_interaction_id chains conversational video edits.
- model-meta: GEMINI_OMNI_FLASH_PREVIEW ($0.10/sec video+audio output)
+ GEMINI_INTERACTIONS_VIDEO_MODELS
- provider options: GeminiOmniVideoProviderOptions derived from the
SDK's CreateModelInteractionParamsNonStreaming; per-model input
modalities (Omni accepts image+video parts) and fixed 10s duration
- @google/genai floor bumped to ^2.10.0 for the interactions surface
- 17 new unit tests; new interactions-video E2E feature backed by a
dedicated aimock mount (native interactions text handling untouched)
- docs/media/video-generation.md + media-generation skill updates
Verified live against the Gemini API: background job completed in ~45s
and returned a valid MP4 with video-modality usage; the SDK's typed
interactions.create works with Step-list input, so no raw REST
fallback is needed.
Closes #871
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(examples): Gemini Omni Flash with all inputs in ts-react-media
Add gemini-omni-flash-preview (text-to-video + image-to-video) to the
ts-react-media example, exercising every Omni input: text prompts, a
start image, an attached reference/edit video clip (Omni-only — never
sent to other providers), and conversational editing that chains a new
prompt onto a completed generation via previous_interaction_id.
Also fixes a latent core type bug this surfaced: generateVideo /
getVideoJobStatus constrained adapters as VideoAdapter<string, any,
any, any>, leaving the duration generic at its Record<string, number>
default — any adapter with a narrowed per-model duration union (Omni's
10, Veo's 4|6|8) failed assignability under strict function-type
contravariance. All video-activity constraints now span all six
VideoAdapter generics.
Verified live: Omni edit chaining (previous_interaction_id) against the
real Gemini API returned an edited 10s MP4; example dev server boots
and type-checks.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(ai-gemini): support Omni Flash 3-10s clip durations
The issue's live verification concluded Omni clips were a fixed 10
seconds, but response_format.duration is a real request field — just
undocumented. Verified against the live API: it takes a "<seconds>s"
string, accepts any value in the 3-10s range including fractional
seconds (a 3s request returns a 3.008s MP4 per ffprobe), rejects
out-of-range values with explicit minimum/maximum errors, and defaults
to 10s when omitted.
Omni's duration is now typed number with availableDurations() =
{ kind: 'range', min: 3, max: 10, unit: 'seconds' } and snapDuration
clamping into it; the adapter maps the generateVideo duration option
onto response_format.duration.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(ai-gemini): address PR review findings for Omni Flash video
- Reject out-of-range Omni durations at job creation with a clear local
error instead of silently passing them to the live API
- Map requires_action interactions to a failed status so polling can't
spin until timeout (reachable via previous_interaction_id chaining)
- Surface failed job statuses in the ts-react-media example instead of
polling forever on a pending spinner
- Add a compile-time regression test guarding the generateVideo
VideoAdapter generic-arity fix, plus unit tests for duration
rejection, fractional pass-through, and requires_action mapping
- Fix stale doc/comment claims: Veo 2/3 model lists, "fixed 10s" clips,
"clamped" duration wording, and content-block ordering (images, then
videos, then text)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(examples): Omni Studio conversational session view in ts-react-media
Add a chat-style session tab built around Gemini Omni Flash's
conversational editing:
- Timeline of turns where each completed clip auto-becomes the
continue-from target; "Continue from here" branches the session from
any earlier clip via previous_interaction_id
- Multi-reference image tray (Omni supports ~6), single reference clip
slot labeled with the 3s API limit, and a prompt-steered audio
direction field
- Per-turn duration slider (3-10s) doubling as a $0.10/s cost estimate,
aspect toggle, and task-mode pin mapped to
generation_config.video_config.task
- Duration is locked and omitted for edit-shaped requests (continuing a
clip, task=edit, or attached clip without a reference pin) — Omni
rejects durations that don't match the source clip's length
- Failed turns get an "Edit & retry" button that restores the prompt,
attachments, and settings to the composer and removes the dead turn
createVideoJobFn gains omniOptions (duration / aspectRatio / task) to
carry the new controls.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com> de5fbb52 feat(ai-gemini): Gemini Omni Flash video generation via the Interactions API (#886)
* feat(ai-gemini): support Gemini Omni Flash video generation via the Interactions API
Add gemini-omni-flash-preview to the Gemini video adapter. Omni only
serves the Interactions API (generateContent rejects it with 400), so
the adapter now routes by model: Veo models keep the
:predictLongRunning operations flow, while Omni creates a background
interaction with response_modalities: ['video'], polls it by id, and
returns the inline base64 MP4 as a data: URL (Files-API URI delivery
passes through). Usage maps from output_tokens_by_modality, size maps
onto response_format.aspect_ratio, and
modelOptions.previous_interaction_id chains conversational video edits.
- model-meta: GEMINI_OMNI_FLASH_PREVIEW ($0.10/sec video+audio output)
+ GEMINI_INTERACTIONS_VIDEO_MODELS
- provider options: GeminiOmniVideoProviderOptions derived from the
SDK's CreateModelInteractionParamsNonStreaming; per-model input
modalities (Omni accepts image+video parts) and fixed 10s duration
- @google/genai floor bumped to ^2.10.0 for the interactions surface
- 17 new unit tests; new interactions-video E2E feature backed by a
dedicated aimock mount (native interactions text handling untouched)
- docs/media/video-generation.md + media-generation skill updates
Verified live against the Gemini API: background job completed in ~45s
and returned a valid MP4 with video-modality usage; the SDK's typed
interactions.create works with Step-list input, so no raw REST
fallback is needed.
Closes #871
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(examples): Gemini Omni Flash with all inputs in ts-react-media
Add gemini-omni-flash-preview (text-to-video + image-to-video) to the
ts-react-media example, exercising every Omni input: text prompts, a
start image, an attached reference/edit video clip (Omni-only — never
sent to other providers), and conversational editing that chains a new
prompt onto a completed generation via previous_interaction_id.
Also fixes a latent core type bug this surfaced: generateVideo /
getVideoJobStatus constrained adapters as VideoAdapter<string, any,
any, any>, leaving the duration generic at its Record<string, number>
default — any adapter with a narrowed per-model duration union (Omni's
10, Veo's 4|6|8) failed assignability under strict function-type
contravariance. All video-activity constraints now span all six
VideoAdapter generics.
Verified live: Omni edit chaining (previous_interaction_id) against the
real Gemini API returned an edited 10s MP4; example dev server boots
and type-checks.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(ai-gemini): support Omni Flash 3-10s clip durations
The issue's live verification concluded Omni clips were a fixed 10
seconds, but response_format.duration is a real request field — just
undocumented. Verified against the live API: it takes a "<seconds>s"
string, accepts any value in the 3-10s range including fractional
seconds (a 3s request returns a 3.008s MP4 per ffprobe), rejects
out-of-range values with explicit minimum/maximum errors, and defaults
to 10s when omitted.
Omni's duration is now typed number with availableDurations() =
{ kind: 'range', min: 3, max: 10, unit: 'seconds' } and snapDuration
clamping into it; the adapter maps the generateVideo duration option
onto response_format.duration.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(ai-gemini): address PR review findings for Omni Flash video
- Reject out-of-range Omni durations at job creation with a clear local
error instead of silently passing them to the live API
- Map requires_action interactions to a failed status so polling can't
spin until timeout (reachable via previous_interaction_id chaining)
- Surface failed job statuses in the ts-react-media example instead of
polling forever on a pending spinner
- Add a compile-time regression test guarding the generateVideo
VideoAdapter generic-arity fix, plus unit tests for duration
rejection, fractional pass-through, and requires_action mapping
- Fix stale doc/comment claims: Veo 2/3 model lists, "fixed 10s" clips,
"clamped" duration wording, and content-block ordering (images, then
videos, then text)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(examples): Omni Studio conversational session view in ts-react-media
Add a chat-style session tab built around Gemini Omni Flash's
conversational editing:
- Timeline of turns where each completed clip auto-becomes the
continue-from target; "Continue from here" branches the session from
any earlier clip via previous_interaction_id
- Multi-reference image tray (Omni supports ~6), single reference clip
slot labeled with the 3s API limit, and a prompt-steered audio
direction field
- Per-turn duration slider (3-10s) doubling as a $0.10/s cost estimate,
aspect toggle, and task-mode pin mapped to
generation_config.video_config.task
- Duration is locked and omitted for edit-shaped requests (continuing a
clip, task=edit, or attached clip without a reference pin) — Omni
rejects durations that don't match the source clip's length
- Failed turns get an "Edit & retry" button that restores the prompt,
attachments, and settings to the composer and removes the dead turn
createVideoJobFn gains omniOptions (duration / aspectRatio / task) to
carry the new controls.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com> 26650859 Feat(ai-gemini): Gemini Realtime Adapter (#405)
* Added gemini ephemeral realtime token
* added initial realtime adapter
* ci: apply automated fixes
* Added gemini adapter, refactored realtime client
* Added gemini live option to example
* Fixed refactoring of realtime client
* Bug fixes, added go_away event, more gemini live provider config options
* refactored event emitter and media handling in gemini adapter
* added go_away & usage event handlers in ai-client
* bug fixes
* refactor: Gemini realtime adapter, Gemini realtime client and audio capture & playback, add support for dynamic token updates and session resumption
* renamed providerOptions to modelOptions
* minor changes
* fixed liveConnectConstraints in geminiRealtimeToken overriding GeminiLiveClient setup message
* fixed message handling and bugs
* consolidated all session updates under updateSession method in the realtime client, added more config
* removed old model
* updated changeset
* fix(ai-gemini): address review findings on the realtime adapter
Correctness / error surfacing:
- token.ts: compute token expiry inside generateToken() so a reused adapter no
longer mints tokens with a fixed (eventually past) expiry.
- client.ts: surface an error instead of silently dropping messages when the
socket isn't open; route JSON parse failures to onError instead of swallowing
them; stop the WebSocket close handler from overwriting a surfaced error with
a benign "idle"; detach socket handlers on disconnect so deliberate reconnects
don't emit a spurious idle/disconnect.
- adapter.ts: emit input transcripts with the real `finished` flag instead of
always-final; tear down socket + audio graph if mic/worklet setup fails
(e.g. denied mic) rather than leaking; route playback errors to onError.
- utils.ts: clean up mic/AudioContext on failed start()/init(); drop the empty
resume() catch; revoke worklet blob URLs.
Types / correctness:
- Fix tool double-conversion: build FunctionDeclarations once from the correct
source (Zod tools vs serialized configs) and use genai v2's responseJsonSchema
(the old outputJsonSchema was silently dropped). Removes the `as any` casts and
the dead functionsMap.
- event-emitter: replace Set<RealtimeEventHandler<any>> with a never-param store
(contravariance) — no `any`, no non-null assertions.
- ai-client updateSession: replace the `(this.options as any)` loop with explicit
typed field assignment.
- Flesh out GeminiRealtimeProviderOptions to match what's consumed (googleGrounding,
proactiveAudio) and export it so it's a usable, non-dead type.
- Rename the isSetupCompelete typo to isSetupComplete.
Cleanup:
- Remove leftover debug console.logs (incl. the full-setup-JSON dump); decode
audio base64 once instead of twice.
Tests:
- Add focused tests for parseResponseMessages (server-message -> event mapping)
and per-call token expiry.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* ci: apply automated fixes
* fix(ai-client): include tool outputSchema in applySessionConfig
Mirror the outputSchema through the session-update tool mapping the same way
inputSchema is handled, so tool output schemas reach providers (e.g. Gemini's
responseJsonSchema) on mid-session updateSession(), not just at connect.
Addresses a CodeRabbit review comment on PR #405.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* docs(realtime): use updateSession instead of removed setVADMode
This PR replaced the useRealtimeChat `vadMode`/`setVADMode` return values with
a generic `updateSession`. Update the realtime-chat doc snippet to destructure
`updateSession` and switch VAD at runtime via `updateSession({ vadMode })`, so
the (non-ignored) snippet type-checks again under kiira.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Tom Beckenham <34339192+tombeckenham@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> 26650859 Feat(ai-gemini): Gemini Realtime Adapter (#405)
* Added gemini ephemeral realtime token
* added initial realtime adapter
* ci: apply automated fixes
* Added gemini adapter, refactored realtime client
* Added gemini live option to example
* Fixed refactoring of realtime client
* Bug fixes, added go_away event, more gemini live provider config options
* refactored event emitter and media handling in gemini adapter
* added go_away & usage event handlers in ai-client
* bug fixes
* refactor: Gemini realtime adapter, Gemini realtime client and audio capture & playback, add support for dynamic token updates and session resumption
* renamed providerOptions to modelOptions
* minor changes
* fixed liveConnectConstraints in geminiRealtimeToken overriding GeminiLiveClient setup message
* fixed message handling and bugs
* consolidated all session updates under updateSession method in the realtime client, added more config
* removed old model
* updated changeset
* fix(ai-gemini): address review findings on the realtime adapter
Correctness / error surfacing:
- token.ts: compute token expiry inside generateToken() so a reused adapter no
longer mints tokens with a fixed (eventually past) expiry.
- client.ts: surface an error instead of silently dropping messages when the
socket isn't open; route JSON parse failures to onError instead of swallowing
them; stop the WebSocket close handler from overwriting a surfaced error with
a benign "idle"; detach socket handlers on disconnect so deliberate reconnects
don't emit a spurious idle/disconnect.
- adapter.ts: emit input transcripts with the real `finished` flag instead of
always-final; tear down socket + audio graph if mic/worklet setup fails
(e.g. denied mic) rather than leaking; route playback errors to onError.
- utils.ts: clean up mic/AudioContext on failed start()/init(); drop the empty
resume() catch; revoke worklet blob URLs.
Types / correctness:
- Fix tool double-conversion: build FunctionDeclarations once from the correct
source (Zod tools vs serialized configs) and use genai v2's responseJsonSchema
(the old outputJsonSchema was silently dropped). Removes the `as any` casts and
the dead functionsMap.
- event-emitter: replace Set<RealtimeEventHandler<any>> with a never-param store
(contravariance) — no `any`, no non-null assertions.
- ai-client updateSession: replace the `(this.options as any)` loop with explicit
typed field assignment.
- Flesh out GeminiRealtimeProviderOptions to match what's consumed (googleGrounding,
proactiveAudio) and export it so it's a usable, non-dead type.
- Rename the isSetupCompelete typo to isSetupComplete.
Cleanup:
- Remove leftover debug console.logs (incl. the full-setup-JSON dump); decode
audio base64 once instead of twice.
Tests:
- Add focused tests for parseResponseMessages (server-message -> event mapping)
and per-call token expiry.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* ci: apply automated fixes
* fix(ai-client): include tool outputSchema in applySessionConfig
Mirror the outputSchema through the session-update tool mapping the same way
inputSchema is handled, so tool output schemas reach providers (e.g. Gemini's
responseJsonSchema) on mid-session updateSession(), not just at connect.
Addresses a CodeRabbit review comment on PR #405.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* docs(realtime): use updateSession instead of removed setVADMode
This PR replaced the useRealtimeChat `vadMode`/`setVADMode` return values with
a generic `updateSession`. Update the realtime-chat doc snippet to destructure
`updateSession` and switch VAD at runtime via `updateSession({ vadMode })`, so
the (non-ignored) snippet type-checks again under kiira.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Tom Beckenham <34339192+tombeckenham@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> 26650859 Feat(ai-gemini): Gemini Realtime Adapter (#405)
* Added gemini ephemeral realtime token
* added initial realtime adapter
* ci: apply automated fixes
* Added gemini adapter, refactored realtime client
* Added gemini live option to example
* Fixed refactoring of realtime client
* Bug fixes, added go_away event, more gemini live provider config options
* refactored event emitter and media handling in gemini adapter
* added go_away & usage event handlers in ai-client
* bug fixes
* refactor: Gemini realtime adapter, Gemini realtime client and audio capture & playback, add support for dynamic token updates and session resumption
* renamed providerOptions to modelOptions
* minor changes
* fixed liveConnectConstraints in geminiRealtimeToken overriding GeminiLiveClient setup message
* fixed message handling and bugs
* consolidated all session updates under updateSession method in the realtime client, added more config
* removed old model
* updated changeset
* fix(ai-gemini): address review findings on the realtime adapter
Correctness / error surfacing:
- token.ts: compute token expiry inside generateToken() so a reused adapter no
longer mints tokens with a fixed (eventually past) expiry.
- client.ts: surface an error instead of silently dropping messages when the
socket isn't open; route JSON parse failures to onError instead of swallowing
them; stop the WebSocket close handler from overwriting a surfaced error with
a benign "idle"; detach socket handlers on disconnect so deliberate reconnects
don't emit a spurious idle/disconnect.
- adapter.ts: emit input transcripts with the real `finished` flag instead of
always-final; tear down socket + audio graph if mic/worklet setup fails
(e.g. denied mic) rather than leaking; route playback errors to onError.
- utils.ts: clean up mic/AudioContext on failed start()/init(); drop the empty
resume() catch; revoke worklet blob URLs.
Types / correctness:
- Fix tool double-conversion: build FunctionDeclarations once from the correct
source (Zod tools vs serialized configs) and use genai v2's responseJsonSchema
(the old outputJsonSchema was silently dropped). Removes the `as any` casts and
the dead functionsMap.
- event-emitter: replace Set<RealtimeEventHandler<any>> with a never-param store
(contravariance) — no `any`, no non-null assertions.
- ai-client updateSession: replace the `(this.options as any)` loop with explicit
typed field assignment.
- Flesh out GeminiRealtimeProviderOptions to match what's consumed (googleGrounding,
proactiveAudio) and export it so it's a usable, non-dead type.
- Rename the isSetupCompelete typo to isSetupComplete.
Cleanup:
- Remove leftover debug console.logs (incl. the full-setup-JSON dump); decode
audio base64 once instead of twice.
Tests:
- Add focused tests for parseResponseMessages (server-message -> event mapping)
and per-call token expiry.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* ci: apply automated fixes
* fix(ai-client): include tool outputSchema in applySessionConfig
Mirror the outputSchema through the session-update tool mapping the same way
inputSchema is handled, so tool output schemas reach providers (e.g. Gemini's
responseJsonSchema) on mid-session updateSession(), not just at connect.
Addresses a CodeRabbit review comment on PR #405.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* docs(realtime): use updateSession instead of removed setVADMode
This PR replaced the useRealtimeChat `vadMode`/`setVADMode` return values with
a generic `updateSession`. Update the realtime-chat doc snippet to destructure
`updateSession` and switch VAD at runtime via `updateSession({ vadMode })`, so
the (non-ignored) snippet type-checks again under kiira.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Tom Beckenham <34339192+tombeckenham@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>