always transcribe in the source language, and let tasks call the API
Three changes that Transcribe Audio needs. Whisper's translate mode only ever outputs English, so it cannot honour "translate into <language>" for anything else — it answered Portuguese audio with a rough English rendering instead of a transcript. The translate decision is gone and transcription is always faithful to the detected language; spokenLanguages now only breaks ties on clips Whisper is unsure about. Script tasks get OFFICER_API_URL / OFFICER_API_HOST / OFFICER_AUTH_TOKEN so they can call Officer's own endpoints rather than reimplementing server-side work. Requests go to 127.0.0.1 so nothing depends on DNS or the proxy, but origin validation matches Host against PUBLIC_URL, hence the separate host variable. `inline` accepts "ask", which offers both affordances in the runner — Run here streams into the modal, Run as job queues it. Useful when the same task can take a second or an hour depending on whether it was pointed at a file or a library. Existing true/false values behave exactly as before. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
5f7d574dec
commit
06aac5478f
+26
-18
@@ -869,8 +869,11 @@ const ScriptRunner = ({
|
||||
const client = useClient();
|
||||
const navigate = useNavigate();
|
||||
const files = useFilesAPI('home');
|
||||
// Inline tasks (quick/interactive) run ephemerally in this modal; everything else becomes a job.
|
||||
const [inline, setInline] = useState(false);
|
||||
// How this task runs: false = job, true = ephemerally in this modal, 'ask' = the task leaves the
|
||||
// choice to the user and both affordances are offered.
|
||||
const [inlineMode, setInlineMode] = useState<boolean | 'ask'>(false);
|
||||
const alwaysInline = inlineMode === true;
|
||||
const canChooseRunMode = inlineMode === 'ask';
|
||||
// Is a job already running? (drives the Run vs Queue affordance).
|
||||
const [jobRunning, setJobRunning] = useState(false);
|
||||
// After a job is created, show a confirmation (View / Close) rather than navigating away.
|
||||
@@ -901,13 +904,13 @@ const ScriptRunner = ({
|
||||
useEffect(() => {
|
||||
client
|
||||
.get<{
|
||||
inline?: boolean;
|
||||
inline?: boolean | 'ask';
|
||||
inputs?: Record<string, TaskInputDef>;
|
||||
config?: { folderKeepAll?: boolean; perGroupTracks?: boolean; perGroupAllFiles?: boolean };
|
||||
}>(`/tasks/${taskDirName}`)
|
||||
.then((task) => {
|
||||
const defs: Record<string, TaskInputDef> = task.inputs ?? {};
|
||||
setInline(task.inline === true);
|
||||
setInlineMode(task.inline === 'ask' ? 'ask' : task.inline === true);
|
||||
setFolderKeepAll(task.config?.folderKeepAll === true);
|
||||
setPerGroupTracks(task.config?.perGroupTracks === true);
|
||||
setPerGroupAllFiles(task.config?.perGroupAllFiles === true);
|
||||
@@ -1036,12 +1039,12 @@ const ScriptRunner = ({
|
||||
|
||||
// Non-inline tasks become jobs — check if one is already running so we can offer Queue.
|
||||
useEffect(() => {
|
||||
if (inline) return;
|
||||
if (alwaysInline) return;
|
||||
client
|
||||
.get<Array<unknown>>('/jobs?live=1')
|
||||
.then((live) => setJobRunning(live.length > 0))
|
||||
.catch(() => {});
|
||||
}, [inline]);
|
||||
}, [alwaysInline]);
|
||||
|
||||
// Which per-group pickers this task declares, and whether the current selection is real work.
|
||||
const has = pickerKinds(inputDefs);
|
||||
@@ -1166,20 +1169,24 @@ const ScriptRunner = ({
|
||||
const noWork = perGroupTracks && entryType === 'directory' && !perGroupHasWork;
|
||||
const base =
|
||||
'flex items-center gap-2 px-6 py-2.5 rounded-lg font-medium text-sm transition-colors disabled:opacity-50 disabled:cursor-not-allowed cursor-pointer';
|
||||
if (inline) {
|
||||
return (
|
||||
<button
|
||||
onClick={runInline}
|
||||
disabled={!runner.isConnected || !inputDefs || probing || noWork}
|
||||
className={`${base} bg-duck-teal text-white hover:bg-duck-teal/90`}
|
||||
>
|
||||
<Play className="h-4 w-4" /> Run
|
||||
</button>
|
||||
);
|
||||
}
|
||||
const jobDisabled = !inputDefs || probing || noWork;
|
||||
const runHere = (
|
||||
<button
|
||||
onClick={runInline}
|
||||
disabled={!runner.isConnected || jobDisabled}
|
||||
className={`${base} ${
|
||||
canChooseRunMode
|
||||
? 'bg-duck-dark/10 dark:bg-foreground/10 text-duck-dark dark:text-foreground hover:bg-duck-dark/15 dark:hover:bg-foreground/15'
|
||||
: 'bg-duck-teal text-white hover:bg-duck-teal/90'
|
||||
}`}
|
||||
>
|
||||
<Play className="h-4 w-4" /> {canChooseRunMode ? 'Run here' : 'Run'}
|
||||
</button>
|
||||
);
|
||||
if (alwaysInline) return runHere;
|
||||
return (
|
||||
<>
|
||||
{canChooseRunMode && runHere}
|
||||
{jobRunning && (
|
||||
<button
|
||||
onClick={() => submitJob('queue')}
|
||||
@@ -1194,7 +1201,8 @@ const ScriptRunner = ({
|
||||
disabled={jobDisabled}
|
||||
className={`${base} text-white ${jobRunning ? 'bg-red-500 hover:bg-red-500/90' : 'bg-duck-teal hover:bg-duck-teal/90'}`}
|
||||
>
|
||||
<Play className="h-4 w-4" /> {jobRunning ? 'Run now' : 'Run'}
|
||||
<Play className="h-4 w-4" />{' '}
|
||||
{canChooseRunMode ? (jobRunning ? 'Run now as job' : 'Run as job') : jobRunning ? 'Run now' : 'Run'}
|
||||
</button>
|
||||
</>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user