Speech-to-text is now plugins/transcribe — sidecar, its own config, its own skill and a task for the file browser's context menu. The transcription logic moved BYTE FOR BYTE: 416 lines whose every decision has a reason attached, from the two-pass detect-then-transcribe to the 25 language priming prompts to timeout:false. Verified identical rather than assumed. Removed here: api/stt/, server-settings/stt.ts and its mount, POST /chat/stt, POST /file-browser/transcribe, the FileViewer handler behind the button hidden last release, the Settings screen, the dead useAudioRecording hook and the orphaned locale keys across all six locales. blobToWav stayed. It lived in the same file as the dead hook and is still used by DictateDialog — unrelated to STT, and deleting by file rather than by use is how that would have gone. No permission entry to remove: STT never had one, living under server-admin, chat and files. The registry count is unchanged and docs:check is green. The plugin ships a task that will not appear in the menu yet — the platform loads a plugin's skills, affordances and notifications from its own directory but not its tasks. That loader is the remaining piece of docs/plugin-capabilities.md and is deliberately not built here. 1426 pass, tsgo clean, 18 plugins discovered with none broken. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Officer-Session: 656f5c85-e49a-4f1f-b9f3-042a04b4d043
34 lines
1.4 KiB
TypeScript
34 lines
1.4 KiB
TypeScript
import { sign } from '@@/jwt';
|
|
import { PORT, OFFICER_API_URL } from '../../officer-url.mjs';
|
|
|
|
const { PUBLIC_URL } = process.env;
|
|
|
|
const PUBLIC_HOST = (() => {
|
|
try {
|
|
return PUBLIC_URL ? new URL(PUBLIC_URL).host : undefined;
|
|
} catch {
|
|
return undefined;
|
|
}
|
|
})();
|
|
|
|
type TaskApiUser = { id: number; email: string; username?: string | null };
|
|
|
|
// Environment that lets a script task call Officer's own API instead of reimplementing server-side
|
|
// work (transcription, for one — `plugins/transcribe/tasks/transcribe-audio-file/index.ts` uses exactly
|
|
// this to reach the transcribe plugin's own route rather than talking to Whisper itself).
|
|
//
|
|
// Requests go to 127.0.0.1 so a task never depends on DNS or the reverse proxy being up. Origin
|
|
// validation matches the Host header against PUBLIC_URL though, so a bare localhost request is
|
|
// rejected — hence OFFICER_API_HOST, which scripts must pass as an explicit Host header:
|
|
//
|
|
// curl -H "Authorization: Bearer $OFFICER_AUTH_TOKEN" -H "Host: $OFFICER_API_HOST" \
|
|
// "$OFFICER_API_URL/api/transcribe/transcribe"
|
|
export async function buildTaskApiEnv(user: TaskApiUser): Promise<Record<string, string>> {
|
|
const token = await sign({ id: user.id, email: user.email, username: user.username ?? '' }, '12h');
|
|
return {
|
|
OFFICER_API_URL,
|
|
OFFICER_API_HOST: PUBLIC_HOST ?? `127.0.0.1:${PORT}`,
|
|
OFFICER_AUTH_TOKEN: token,
|
|
};
|
|
}
|