summaryrefslogtreecommitdiffhomepage
path: root/packages/tool-youtube-transcript/src/tool.ts
diff options
context:
space:
mode:
authorAdam Malczewski <[email protected]>2026-06-21 15:08:51 +0900
committerAdam Malczewski <[email protected]>2026-06-21 15:08:51 +0900
commit64823e68e8c6c3bc199f9cb82d97321c830687c3 (patch)
tree9340fbaede62f86b0de9f8281d9415778adcda44 /packages/tool-youtube-transcript/src/tool.ts
parent4ccdfd34c55bee279ce5e190412afd19cfbb5238 (diff)
downloaddispatch-64823e68e8c6c3bc199f9cb82d97321c830687c3.tar.gz
dispatch-64823e68e8c6c3bc199f9cb82d97321c830687c3.zip
feat(tool-youtube-transcript): write full transcript to /tmp/dispatch on truncation
When the formatted transcript exceeds the 50K char output cap, the tool now writes the full output to /tmp/dispatch/{video_id}.txt and returns the truncated output with a notice pointing to the file path. The writeFile dep is injectable so tests verify without touching the filesystem.
Diffstat (limited to 'packages/tool-youtube-transcript/src/tool.ts')
-rw-r--r--packages/tool-youtube-transcript/src/tool.ts22
1 files changed, 22 insertions, 0 deletions
diff --git a/packages/tool-youtube-transcript/src/tool.ts b/packages/tool-youtube-transcript/src/tool.ts
index 189e42c..a47d693 100644
--- a/packages/tool-youtube-transcript/src/tool.ts
+++ b/packages/tool-youtube-transcript/src/tool.ts
@@ -7,6 +7,7 @@
* rather than thrown, so the model can react to the message.
*/
+import { mkdirSync, writeFileSync } from "node:fs";
import type { ToolContract, ToolExecuteContext, ToolResult } from "@dispatch/kernel";
import type { TranscriptClient } from "./client.js";
import {
@@ -19,10 +20,13 @@ import {
import { validateUrl } from "./validate.js";
const OUTPUT_CAP = 50_000;
+const FULL_OUTPUT_DIR = "/tmp/dispatch";
export interface YoutubeTranscriptToolDeps {
readonly client: TranscriptClient;
readonly outputCap?: number;
+ /** Injected file writer (defaults to real fs write). */
+ readonly writeFile?: (path: string, content: string) => void;
}
const DESCRIPTION =
@@ -41,6 +45,12 @@ const DESCRIPTION =
export function createYoutubeTranscriptTool(deps: YoutubeTranscriptToolDeps): ToolContract {
const client = deps.client;
const cap = deps.outputCap ?? OUTPUT_CAP;
+ const writeFile =
+ deps.writeFile ??
+ ((path, content) => {
+ mkdirSync(FULL_OUTPUT_DIR, { recursive: true });
+ writeFileSync(path, content, "utf-8");
+ });
return {
name: "youtube_transcript",
@@ -67,17 +77,29 @@ export function createYoutubeTranscriptTool(deps: YoutubeTranscriptToolDeps): To
try {
const data: TranscriptResponse = await client.getTranscript(url, ctx.signal);
let output: string;
+ let videoId: string | undefined;
// Check the single-literal discriminants ("completed"/"failed") first,
// so the final else narrows to QueuedResponse — whose `status` is itself
// a `"queued" | "processing"` union TS cannot negatively narrow.
if (data.status === "completed") {
output = formatCompleted(url, data);
+ videoId = data.video_id;
} else if (data.status === "failed") {
output = formatFailed(data);
} else {
output = formatQueued(url, data, Date.now);
}
span.end();
+
+ if (output.length > cap && videoId !== undefined) {
+ const filePath = `${FULL_OUTPUT_DIR}/${videoId}.txt`;
+ try {
+ writeFile(filePath, output);
+ return { content: truncateOutput(output, cap, filePath) };
+ } catch {
+ return { content: truncateOutput(output, cap) };
+ }
+ }
return { content: truncateOutput(output, cap) };
} catch (err: unknown) {
span.end({ err });