File size: 5,679 Bytes
f778c12 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 | import path from "node:path";
import type { Command } from "commander";
import { resolveAgentDir } from "../../agents/agent-scope.js";
import { inspectLocalAudioSelection } from "../../media-understanding/local-audio.js";
import { buildMediaUnderstandingRegistry } from "../../media-understanding/provider-registry.js";
import { transcribeAudioFile } from "../../media-understanding/runtime.js";
import { defaultRuntime } from "../../runtime.js";
import { getProviderEnvVars } from "../../secrets/provider-env-vars.js";
import { runCommandWithRuntime } from "../cli-utils.js";
import { getModelsCommandSecretTargetIds } from "../command-secret-targets.js";
import { prepareLocalCapabilityAccountSecrets } from "./local-account-secrets.js";
import { isMissingMediaUnderstandingProvider } from "./media-understanding-result.js";
import type { CapabilityEnvelope } from "./metadata.js";
import { emitJsonOrText, formatEnvelopeForText, providerSummaryText } from "./output.js";
import {
providerHasGenericConfig,
registerLocalProvidersCommand,
requireProviderModelOverride,
resolveCapabilityAgentOption,
resolveCapabilityProviderAgentId,
resolveLocalCapabilityRuntimeConfig,
} from "./shared.js";
async function runAudioTranscribe(params: {
file: string;
language?: string;
model?: string;
prompt?: string;
agent?: string;
}) {
const cfg = await resolveLocalCapabilityRuntimeConfig({
commandName: "infer audio transcribe",
targetIds: getModelsCommandSecretTargetIds(),
});
const agentId = resolveCapabilityProviderAgentId(cfg, params.agent, "infer audio transcribe");
await prepareLocalCapabilityAccountSecrets({ cfg, agentId });
const result = await transcribeAudioFile({
agentDir: resolveAgentDir(cfg, agentId),
activeModel: requireProviderModelOverride(params.model),
filePath: path.resolve(params.file),
cfg,
agentId,
language: params.language,
prompt: params.prompt,
});
if (!result.text) {
if (isMissingMediaUnderstandingProvider(result)) {
throw new Error(
"No audio transcription provider is configured or ready. Configure an audio-capable tools.media.models entry, or pass --model <provider/model> after configuring that provider's auth/API key.",
);
}
throw new Error(`No transcript returned for audio: ${path.resolve(params.file)}`);
}
return {
ok: true,
capability: "audio.transcribe",
transport: "local" as const,
provider: result.provider,
model: result.model,
attempts: [],
outputs: [{ path: path.resolve(params.file), text: result.text, kind: "audio.transcription" }],
} satisfies CapabilityEnvelope;
}
export function registerAudioCapabilityCommands(capability: Command): void {
const audio = capability
.command("audio")
.description("Audio transcription")
.option("--agent <id>", "Agent whose model and auth state should be used");
audio
.command("transcribe")
.description("Transcribe one audio file")
.requiredOption("--file <path>", "Audio file")
.option("--agent <id>", "Agent whose model and auth state should be used")
.option("--language <code>", "Language hint")
.option("--prompt <text>", "Prompt hint")
.option("--model <provider/model>", "Model override")
.option("--json", "Output JSON", false)
.action(async (opts, command) => {
await runCommandWithRuntime(defaultRuntime, async () => {
const result = await runAudioTranscribe({
file: String(opts.file),
agent: resolveCapabilityAgentOption(command, opts.agent),
language: opts.language as string | undefined,
model: opts.model as string | undefined,
prompt: opts.prompt as string | undefined,
});
emitJsonOrText(defaultRuntime, Boolean(opts.json), result, formatEnvelopeForText);
});
});
registerLocalProvidersCommand(
audio,
"List audio transcription providers",
async (cfg, agentId) => {
const remoteProviders = [...buildMediaUnderstandingRegistry(undefined, cfg).values()]
.filter((provider) => provider.capabilities?.includes("audio"))
.map((provider) => ({
available: true,
configured: providerHasGenericConfig({
cfg,
providerId: provider.id,
agentId,
envVars: getProviderEnvVars(provider.id, {
config: cfg,
includeUntrustedWorkspacePlugins: false,
}),
}),
selected: false,
id: provider.id,
capabilities: provider.capabilities,
defaultModels: provider.defaultModels,
}));
const localSelection = await inspectLocalAudioSelection();
const localProviders = localSelection.candidates
.filter((candidate) => candidate.available)
.map((candidate) =>
Object.assign(
{
available: candidate.available,
configured: candidate.ready,
selected: false,
localFallbackSelected: candidate.selected,
id: `local/${candidate.id}`,
transport: "local-cli",
command: candidate.command,
observedBackend: candidate.observedBackend ?? "unknown",
evidence: candidate.evidence,
},
candidate.capableBackend ? { capableBackend: candidate.capableBackend } : {},
candidate.requestedBackend ? { requestedBackend: candidate.requestedBackend } : {},
candidate.reason ? { reason: candidate.reason } : {},
),
);
return [...remoteProviders, ...localProviders];
},
providerSummaryText,
);
}
|