diff --git a/CHANGELOG.md b/CHANGELOG.md index e1a167a..a132284 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## [4.41.7] + +- Add `summarization` to the speech understanding feature requests and responses (`SummarizationRequest`, `SummarizationResponse`): `summary_type`, `headline_length`, `approximate_chapters` and `effort`. The feature was already accepted by the API but missing from the SDK types, so setting it failed to type check + ## [4.41.6] - Add `rewrite_mode` to `DictationConfig` — the model tier that runs the dictation rewrite: `"fast"` (the server default) or `"smart"`, which follows detailed formatting instructions more reliably at higher latency. Unset, it is not sent. The `DictationRewriteMode` type is exported from the package root diff --git a/package.json b/package.json index 944ab0a..7670770 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "assemblyai", - "version": "4.41.6", + "version": "4.41.7", "description": "The AssemblyAI JavaScript SDK provides an easy-to-use interface for interacting with the AssemblyAI API, which supports async and real-time transcription.", "engines": { "node": ">=18" diff --git a/src/types/openapi.generated.ts b/src/types/openapi.generated.ts index 307d64f..c7f0b66 100644 --- a/src/types/openapi.generated.ts +++ b/src/types/openapi.generated.ts @@ -1120,6 +1120,37 @@ export type CustomFormattingRequest = { effort?: SpeechUnderstandingEffort; }; +/** + * Summarization type for speech understanding + */ +export type SummarizationType = "bullets" | "paragraph"; + +/** + * Summarization configuration for speech understanding + */ +export type SummarizationRequest = { + /** + * The format of the summary + */ + summary_type: SummarizationType; + /** + * Target word count for each chapter headline (5-15) + * + * @defaultValue 10 + */ + headline_length?: number; + /** + * Override: Approximate number of chapters to split the transcript into + */ + approximate_chapters?: number; + /** + * How much effort to spend on this task + * + * @defaultValue "low" + */ + effort?: SpeechUnderstandingEffort; +}; + /** * Speech understanding feature requests grouped together */ @@ -1136,6 +1167,10 @@ export type SpeechUnderstandingFeatureRequests = { * Custom formatting configuration */ custom_formatting?: CustomFormattingRequest; + /** + * Summarization configuration + */ + summarization?: SummarizationRequest; }; /** @@ -1194,6 +1229,58 @@ export type CustomFormattingResponse = { status: string; }; +/** + * A summarized section of the transcript + */ +export type SummarizationSection = { + /** + * Start of the section, in milliseconds + */ + start: number; + /** + * End of the section, in milliseconds + */ + end: number; + /** + * Section summary, when summary_type is 'paragraph' + */ + text?: string; + /** + * Section summary, when summary_type is 'bullets' + */ + bullets?: string[]; + /** + * Short headline describing the section + */ + headline?: string; +}; + +/** + * Summarization response containing the chapter summaries + */ +export type SummarizationResponse = { + /** + * Status of the summarization feature + */ + status: string; + /** + * Per-section summaries + */ + summary?: SummarizationSection[]; + /** + * Single summary covering the whole transcript + */ + block_summary?: string; + /** + * The summary type that was used + */ + summary_type?: SummarizationType; + /** + * The effort level that was used + */ + effort?: SpeechUnderstandingEffort; +}; + /** * Speech understanding feature responses grouped together */ @@ -1210,6 +1297,10 @@ export type SpeechUnderstandingFeatureResponses = { * Custom formatting results */ custom_formatting?: CustomFormattingResponse; + /** + * Summarization results + */ + summarization?: SummarizationResponse; }; /** diff --git a/tests/unit/speech-understanding-summarization.test.ts b/tests/unit/speech-understanding-summarization.test.ts new file mode 100644 index 0000000..9949276 --- /dev/null +++ b/tests/unit/speech-understanding-summarization.test.ts @@ -0,0 +1,52 @@ +import fetchMock from "jest-fetch-mock"; +import { SummarizationRequest, SummarizationResponse } from "../../src"; +import { createClient, requestMatches } from "./utils"; + +fetchMock.enableMocks(); + +const assembly = createClient(); +const transcriptId = "transcript_123"; +const remoteAudioURL = "https://assembly.ai/espn.m4a"; + +beforeEach(() => { + jest.clearAllMocks(); + fetchMock.resetMocks(); + fetchMock.doMock(); +}); + +describe("speech understanding summarization", () => { + it("should submit every summarization option", async () => { + const summarization: SummarizationRequest = { + summary_type: "bullets", + headline_length: 8, + approximate_chapters: 4, + effort: "medium", + }; + fetchMock.doMockOnceIf( + requestMatches({ url: "/v2/transcript", method: "POST" }), + JSON.stringify({ id: transcriptId, status: "queued" }), + ); + + await assembly.transcripts.submit({ + audio_url: remoteAudioURL, + speech_understanding: { request: { summarization } }, + }); + + const body = JSON.parse(fetchMock.mock.calls[0][1]?.body as string); + expect(body.speech_understanding.request.summarization).toEqual( + summarization, + ); + }); + + it("should type the summarization response", () => { + const response: SummarizationResponse = { + status: "success", + summary_type: "paragraph", + effort: "low", + block_summary: "A summary.", + summary: [{ start: 0, end: 1000, text: "A summary.", headline: "Intro" }], + }; + + expect(response.summary?.[0].headline).toBe("Intro"); + }); +});