arisa 3.1.8 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
function mimeMatches(pattern, mimeType = "") {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
if (
|
|
2
|
+
const normalizedMimeType = mimeType.split(";")[0].trim().toLowerCase();
|
|
3
|
+
const normalizedPattern = pattern?.trim().toLowerCase();
|
|
4
|
+
if (!normalizedPattern || !normalizedMimeType) return false;
|
|
5
|
+
if (normalizedPattern === normalizedMimeType) return true;
|
|
6
|
+
if (normalizedPattern.endsWith("/*")) return normalizedMimeType.startsWith(`${normalizedPattern.slice(0, -2)}/`);
|
|
5
7
|
return false;
|
|
6
8
|
}
|
|
7
9
|
|
|
@@ -20,8 +22,9 @@ function looksLikeAudioTranscriptionTool(tool) {
|
|
|
20
22
|
}
|
|
21
23
|
|
|
22
24
|
export function shouldNormalizeArtifactToText(artifact, desiredMimeType = "text/plain") {
|
|
25
|
+
const mimeType = artifact?.mimeType?.split(";")[0].trim().toLowerCase();
|
|
23
26
|
return desiredMimeType === "text/plain"
|
|
24
|
-
&& (
|
|
27
|
+
&& (mimeType?.startsWith("audio/") || mimeType?.startsWith("video/"));
|
|
25
28
|
}
|
|
26
29
|
|
|
27
30
|
export function selectPipeTool({ toolRegistry, artifact, desiredMimeType }) {
|
|
@@ -6,6 +6,28 @@ async function downloadToBuffer(ctx, fileId) {
|
|
|
6
6
|
return Buffer.from(await response.arrayBuffer());
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
+
function mimeTypeFromAudioFileName(fileName = "") {
|
|
10
|
+
const extension = fileName.toLowerCase().split(".").pop();
|
|
11
|
+
return {
|
|
12
|
+
flac: "audio/flac",
|
|
13
|
+
m4a: "audio/mp4",
|
|
14
|
+
mp3: "audio/mpeg",
|
|
15
|
+
mp4: "audio/mp4",
|
|
16
|
+
mpeg: "audio/mpeg",
|
|
17
|
+
mpga: "audio/mpga",
|
|
18
|
+
ogg: "audio/ogg",
|
|
19
|
+
opus: "audio/ogg",
|
|
20
|
+
wav: "audio/wav",
|
|
21
|
+
webm: "audio/webm"
|
|
22
|
+
}[extension] || "";
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function normalizeDocumentMimeType(document) {
|
|
26
|
+
const mimeType = document.mime_type || "";
|
|
27
|
+
if (mimeType && mimeType !== "application/octet-stream") return mimeType;
|
|
28
|
+
return mimeTypeFromAudioFileName(document.file_name) || mimeType || "application/octet-stream";
|
|
29
|
+
}
|
|
30
|
+
|
|
9
31
|
function incomingCaptionMetadata(ctx) {
|
|
10
32
|
return ctx.message?.caption ? { caption: ctx.message.caption } : {};
|
|
11
33
|
}
|
|
@@ -33,6 +55,26 @@ export async function captureIncomingArtifact(ctx, artifactStore) {
|
|
|
33
55
|
});
|
|
34
56
|
}
|
|
35
57
|
|
|
58
|
+
if (ctx.message?.audio) {
|
|
59
|
+
const audio = ctx.message.audio;
|
|
60
|
+
const fileName = audio.file_name || `${chatId}-${ctx.msg.message_id}`;
|
|
61
|
+
const content = await downloadToBuffer(ctx, audio.file_id);
|
|
62
|
+
return store.createGeneratedFile({
|
|
63
|
+
fileName,
|
|
64
|
+
content,
|
|
65
|
+
kind: "audio",
|
|
66
|
+
mimeType: audio.mime_type || "audio/mpeg",
|
|
67
|
+
source: baseSource,
|
|
68
|
+
metadata: {
|
|
69
|
+
duration: audio.duration,
|
|
70
|
+
performer: audio.performer,
|
|
71
|
+
title: audio.title,
|
|
72
|
+
fileSize: audio.file_size,
|
|
73
|
+
...incomingCaptionMetadata(ctx)
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
36
78
|
if (ctx.message?.video) {
|
|
37
79
|
const video = ctx.message.video;
|
|
38
80
|
const fileName = video.file_name || `${chatId}-${ctx.msg.message_id}.mp4`;
|
|
@@ -54,13 +96,15 @@ export async function captureIncomingArtifact(ctx, artifactStore) {
|
|
|
54
96
|
}
|
|
55
97
|
|
|
56
98
|
if (ctx.message?.document) {
|
|
57
|
-
const
|
|
58
|
-
const
|
|
99
|
+
const document = ctx.message.document;
|
|
100
|
+
const fileName = document.file_name || `${chatId}-${ctx.msg.message_id}`;
|
|
101
|
+
const mimeType = normalizeDocumentMimeType(document);
|
|
102
|
+
const content = await downloadToBuffer(ctx, document.file_id);
|
|
59
103
|
return store.createGeneratedFile({
|
|
60
104
|
fileName,
|
|
61
105
|
content,
|
|
62
|
-
kind: "document",
|
|
63
|
-
mimeType
|
|
106
|
+
kind: mimeType.startsWith("audio/") ? "audio" : "document",
|
|
107
|
+
mimeType,
|
|
64
108
|
source: baseSource,
|
|
65
109
|
metadata: incomingCaptionMetadata(ctx)
|
|
66
110
|
});
|
|
@@ -8,8 +8,55 @@ import { getToolConfigPath } from "../../src/runtime/paths.js";
|
|
|
8
8
|
const toolName = "openai-transcribe";
|
|
9
9
|
const config = await loadToolConfig(toolName, defaults);
|
|
10
10
|
|
|
11
|
+
const supportedUploadExtensions = new Set([
|
|
12
|
+
".flac",
|
|
13
|
+
".m4a",
|
|
14
|
+
".mp3",
|
|
15
|
+
".mp4",
|
|
16
|
+
".mpeg",
|
|
17
|
+
".mpga",
|
|
18
|
+
".ogg",
|
|
19
|
+
".wav",
|
|
20
|
+
".webm"
|
|
21
|
+
]);
|
|
22
|
+
|
|
23
|
+
const mimeUploadExtensions = new Map([
|
|
24
|
+
["audio/aac", ".m4a"],
|
|
25
|
+
["audio/flac", ".flac"],
|
|
26
|
+
["audio/m4a", ".m4a"],
|
|
27
|
+
["audio/mp3", ".mp3"],
|
|
28
|
+
["audio/mp4", ".m4a"],
|
|
29
|
+
["audio/mpeg", ".mp3"],
|
|
30
|
+
["audio/mpga", ".mpga"],
|
|
31
|
+
["audio/ogg", ".ogg"],
|
|
32
|
+
["audio/opus", ".ogg"],
|
|
33
|
+
["audio/wav", ".wav"],
|
|
34
|
+
["audio/wave", ".wav"],
|
|
35
|
+
["audio/webm", ".webm"],
|
|
36
|
+
["audio/x-m4a", ".m4a"],
|
|
37
|
+
["audio/x-wav", ".wav"],
|
|
38
|
+
["video/mp4", ".mp4"],
|
|
39
|
+
["video/webm", ".webm"]
|
|
40
|
+
]);
|
|
41
|
+
|
|
42
|
+
function baseMimeType(mimeType = "") {
|
|
43
|
+
return mimeType.split(";")[0].trim().toLowerCase();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function uploadFileNameForArtifact(artifact) {
|
|
47
|
+
const currentName = path.basename(artifact.path);
|
|
48
|
+
const currentExtension = path.extname(currentName).toLowerCase();
|
|
49
|
+
if (supportedUploadExtensions.has(currentExtension)) return currentName;
|
|
50
|
+
|
|
51
|
+
const extension = mimeUploadExtensions.get(baseMimeType(artifact.mimeType));
|
|
52
|
+
if (!extension) return currentName;
|
|
53
|
+
|
|
54
|
+
const parsed = path.parse(currentName);
|
|
55
|
+
return `${parsed.name || "audio"}${extension}`;
|
|
56
|
+
}
|
|
57
|
+
|
|
11
58
|
function printHelp() {
|
|
12
|
-
console.log(`openai-transcribe\n\nUsage:\n node index.js --help\n node index.js run --request-file <json>\n\nExpected input:\n {\n "artifact": { "path": "/abs/media.ogg", "mimeType": "audio/ogg" },\n "args": {}\n }\n\nConfig at ${getToolConfigPath(toolName)}:\n OPENAI_API_KEY\n MODEL\n`);
|
|
59
|
+
console.log(`openai-transcribe\n\nUsage:\n node index.js --help\n node index.js run --request-file <json>\n\nExpected input:\n {\n "artifact": { "path": "/abs/media.ogg", "mimeType": "audio/ogg" },\n "args": {}\n }\n\nSupported upload formats include flac, mp3, mp4, mpeg, mpga, m4a, ogg, wav, and webm.\n\nConfig at ${getToolConfigPath(toolName)}:\n OPENAI_API_KEY\n MODEL\n`);
|
|
13
60
|
}
|
|
14
61
|
|
|
15
62
|
async function run(requestFile) {
|
|
@@ -32,7 +79,7 @@ async function run(requestFile) {
|
|
|
32
79
|
await stat(artifact.path);
|
|
33
80
|
const form = new FormData();
|
|
34
81
|
const data = await readFile(artifact.path);
|
|
35
|
-
form.append("file", new Blob([data]
|
|
82
|
+
form.append("file", new Blob([data], { type: baseMimeType(artifact.mimeType) || "application/octet-stream" }), uploadFileNameForArtifact(artifact));
|
|
36
83
|
form.append("model", config.MODEL);
|
|
37
84
|
|
|
38
85
|
const response = await fetch("https://api.openai.com/v1/audio/transcriptions", {
|
|
@@ -2,7 +2,24 @@
|
|
|
2
2
|
"name": "openai-transcribe",
|
|
3
3
|
"description": "Transcribe audio files and video audio tracks with OpenAI audio transcription API.",
|
|
4
4
|
"entry": "index.js",
|
|
5
|
-
"input": [
|
|
5
|
+
"input": [
|
|
6
|
+
"audio/aac",
|
|
7
|
+
"audio/flac",
|
|
8
|
+
"audio/m4a",
|
|
9
|
+
"audio/mp3",
|
|
10
|
+
"audio/mp4",
|
|
11
|
+
"audio/mpeg",
|
|
12
|
+
"audio/mpga",
|
|
13
|
+
"audio/ogg",
|
|
14
|
+
"audio/opus",
|
|
15
|
+
"audio/wav",
|
|
16
|
+
"audio/wave",
|
|
17
|
+
"audio/webm",
|
|
18
|
+
"audio/x-m4a",
|
|
19
|
+
"audio/x-wav",
|
|
20
|
+
"video/mp4",
|
|
21
|
+
"video/webm"
|
|
22
|
+
],
|
|
6
23
|
"output": ["text/plain"],
|
|
7
24
|
"configSchema": {
|
|
8
25
|
"OPENAI_API_KEY": {
|