Skip to content

Release 0.3.1 - #68

Merged
omgate234 merged 8 commits into
mainfrom
release
Sep 2, 2026
Merged

Release 0.3.1#68
omgate234 merged 8 commits into
mainfrom
release

Conversation

@omgate234

Copy link
Copy Markdown
Collaborator

Pull Request

Description:
Fixes four regressions in the Search v2 surface, all found while exercising search()ShotgetEmbedCode() end to end. Three come from the server sending shapes the SDK's types did not allow (length: null, absent title, explicit null stream keys); the fourth is an ask() signature that could not accept the options object its own docs implied. Behaviour is aligned with videodb-python in each case.

No version bump: 0.3.1 is still unpublished (npm latest is 0.3.0), so these entries fold into the existing [0.3.1] CHANGELOG section rather than opening a [0.3.2].

Changes:

  • ask() accepts an options object — Video.ask() / Collection.ask() now take AskOptions (topK, mode, includeSources) as the second argument. Previously that parameter was topK: number, so an options object was serialised straight into top_k and mode / includeSources were dropped without error. The positional form still works; AskOptions is exported from @/types/search
  • getEmbedCode({ autoGenerate: true }) works on search shots — generateStream() returned early when streamUrl alone was set, so shots from search never fetched playerUrl and getEmbedCode() threw despite auto-generation. It now skips the request only when both URLs are known, and sends length: null for shots with no video length instead of letting JSON.stringify coerce NaN
  • videoLength is no longer NaNparseFloat(result.length) produced NaN when Search v2 sent length: null; values now pass through a finite-number coercion returning undefined for null/empty/non-numeric input
  • streamUrl is no longer dropped from serialised shots — doc.streamLink ?? doc.streamUrl fell through a real null onto a key the server never emits, leaving undefined so JSON.stringify() omitted the field. Now uses || and normalises absent streams to null
  • Types widened to match the wire — videoLength / videoTitle optional and streamUrl / playerUrl nullable on Shot and ShotBase; SearchResponse allows length: string | number | null and title: string | null
  • CHANGELOG entries added under the unreleased [0.3.1]

Related Issues:

  • None filed on this repo; raised through internal triage.

Testing:

  • npx tsc --noEmit — passes (exit 0). This carries real signal here, since the ShotBase / SearchResponse widenings are the fix for three of the four bugs
  • npx jest — passes, but only exercises the pre-existing test/index.spec.ts placeholder; it covers none of this
  • Manual verification still required against a live collection, because every one of these depends on server response shapes that cannot be reproduced offline:
    1. video.ask('...', { topK: 5, includeSources: true }) → confirm the request body carries top_k: 5 and include_sources: true, and that the positional form ask('...', 5, 'default', true) still produces the same body
    2. collection.search(...) on an indexed video → take a returned Shot, call getEmbedCode({ autoGenerate: true }), confirm it returns an iframe rather than throwing player_url not available
    3. On the same shot, confirm videoLength is undefined (never NaN) and that JSON.stringify(shot) still contains a streamUrl key — null when there is no stream
  • Re-test scope: any caller of Video.ask / Collection.ask, and anything consuming Shot.videoLength / videoTitle / streamUrl / playerUrl, since those four are now optional or nullable

Checklist:

  • Code follows project coding standards
  • Tests have been added or updated — no; see note below
  • Code Review
  • Manual test after merge
  • All checks passed

On tests: this branch adds none. The repo has no HTTP-mocking harness, and the four bugs are all about real server response shapes, so a spec would mostly assert the fixtures it declares. Landing a proper mocked-transport suite is worth doing as its own change rather than smuggling a half-harness in here.

Compatibility: no breaking changes at the call site. ask() keeps its positional form. The Shot field widenings are type-level and will surface in downstream TypeScript that assumed videoLength: number or non-null streamUrl — which is the point, since the server was already sending those values.

ENG-1524  ask() took topK positionally, so an options object serialised
          into top_k and includeSources was silently dropped. Both
          Video.ask and Collection.ask now accept AskOptions, with the
          positional form still working.

ENG-1516  playStream() built a player URL and never opened it. Added
          utils/openBrowser (with a browser-field counterpart) so every
          .play() launches the browser like videodb-python does.
          VIDEODB_NO_BROWSER opts out for CI.

ENG-1522  generateStream() short-circuited on streamUrl alone, so search
          shots never fetched playerUrl and getEmbedCode() threw despite
          autoGenerate: true. Skip the request only when both are known.
          Needs the same one-line change in videodb-python shot.py:88.

ENG-1518  parseFloat(null) produced NaN for videoLength. Coerce through a
          finite-number helper and type videoLength/videoTitle optional.

ENG-1512  doc.streamLink ?? doc.streamUrl fell through a real null onto a
          key the server never emits, so JSON.stringify dropped streamUrl.
          Use || and normalise absent streams to null, matching Python.

Adds test/regressions.spec.ts covering all of the above plus ENG-1517's
scene_id casing, and a jest moduleNameMapper for the @/* alias.
ask() took topK positionally, so an options object serialised into top_k
and includeSources was silently dropped. Video.ask and Collection.ask now
accept AskOptions, with the positional form still working.

generateStream() short-circuited on streamUrl alone, so search shots never
fetched playerUrl and getEmbedCode() threw despite autoGenerate: true. Skip
the request only when both are already known.

parseFloat(null) produced NaN for videoLength. Coerce through a
finite-number helper and type videoLength/videoTitle as optional.

doc.streamLink ?? doc.streamUrl fell through a real null onto a key the
server never emits, so JSON.stringify dropped streamUrl. Use || and
normalise absent streams to null, matching videodb-python.

Folded into the unreleased 0.3.1 CHANGELOG entry; 0.3.0 is npm latest.
fix: search, ask, and stream metadata regressions
@omgate234
omgate234 merged commit 6d01a88 into main Sep 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant