mohdel 0.111.0 → 0.112.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/js/client/call_transcription.js +85 -0
- package/js/client/index.js +2 -0
- package/js/session/driver.js +11 -0
- package/package.json +2 -2
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Send a TranscriptionEnvelope to thin-gate's `POST /v1/transcription`.
|
|
3
|
+
*
|
|
4
|
+
* Transcription is one-shot: single JSON response body, no streaming,
|
|
5
|
+
* no cooldown/rate-limit. `audio.fileUri` must be a `file://` or
|
|
6
|
+
* `data:` URI — `file://` requires that the gate's sessions share a
|
|
7
|
+
* filesystem with the caller; `data:` carries the bytes inline subject
|
|
8
|
+
* to the gate's body-size cap.
|
|
9
|
+
*
|
|
10
|
+
* @module client/call_transcription
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { requestUnix } from './transport.js'
|
|
14
|
+
import { MohdelTypedError } from '#core'
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @param {import('#core/transcription.js').TranscriptionEnvelope} envelope
|
|
18
|
+
* @param {object} options
|
|
19
|
+
* @param {string} options.socketPath
|
|
20
|
+
* @param {AbortSignal} [options.signal]
|
|
21
|
+
* @param {string} [options.path] HTTP path; defaults to '/v1/transcription'
|
|
22
|
+
* @returns {Promise<import('#core/transcription.js').TranscriptionResult>}
|
|
23
|
+
*/
|
|
24
|
+
export async function callTranscription (envelope, { socketPath, signal, path = '/v1/transcription' }) {
|
|
25
|
+
const res = await requestUnix({
|
|
26
|
+
socketPath,
|
|
27
|
+
path,
|
|
28
|
+
method: 'POST',
|
|
29
|
+
body: envelope,
|
|
30
|
+
signal
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
const body = await readAll(res)
|
|
34
|
+
|
|
35
|
+
if (res.statusCode !== 200) {
|
|
36
|
+
throw MohdelTypedError.fromJSON(parseErrorBody(body, res.statusCode ?? 0))
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
let parsed
|
|
40
|
+
try {
|
|
41
|
+
parsed = JSON.parse(body)
|
|
42
|
+
} catch (e) {
|
|
43
|
+
throw new MohdelTypedError(
|
|
44
|
+
'thin-gate returned non-JSON transcription response',
|
|
45
|
+
{ type: 'PROTOCOL_INVALID_EVENT', retryable: false }
|
|
46
|
+
)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (!parsed || typeof parsed !== 'object' || parsed.status !== 'completed' || typeof parsed.text !== 'string') {
|
|
50
|
+
throw new MohdelTypedError(
|
|
51
|
+
'thin-gate returned malformed TranscriptionResult',
|
|
52
|
+
{ type: 'PROTOCOL_INVALID_EVENT', retryable: false }
|
|
53
|
+
)
|
|
54
|
+
}
|
|
55
|
+
return parsed
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* @param {AsyncIterable<Buffer|string>} stream
|
|
60
|
+
* @returns {Promise<string>}
|
|
61
|
+
*/
|
|
62
|
+
async function readAll (stream) {
|
|
63
|
+
let s = ''
|
|
64
|
+
for await (const c of stream) s += typeof c === 'string' ? c : c.toString('utf8')
|
|
65
|
+
return s
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* @param {string} body
|
|
70
|
+
* @param {number} status
|
|
71
|
+
* @returns {import('#core/errors.js').TypedError}
|
|
72
|
+
*/
|
|
73
|
+
function parseErrorBody (body, status) {
|
|
74
|
+
try {
|
|
75
|
+
const parsed = JSON.parse(body)
|
|
76
|
+
if (parsed && typeof parsed === 'object' && typeof parsed.type === 'string') {
|
|
77
|
+
return parsed
|
|
78
|
+
}
|
|
79
|
+
} catch {}
|
|
80
|
+
return {
|
|
81
|
+
type: 'PROTOCOL_HTTP_ERROR',
|
|
82
|
+
message: `thin-gate returned HTTP ${status}`,
|
|
83
|
+
retryable: status >= 500
|
|
84
|
+
}
|
|
85
|
+
}
|
package/js/client/index.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* Public surface (0.90):
|
|
5
5
|
* - call(envelope, { socketPath, signal }): AsyncGenerator<Event>
|
|
6
6
|
* - callImage(envelope, { socketPath, signal }): Promise<ImageResult>
|
|
7
|
+
* - callTranscription(envelope, { socketPath, signal }): Promise<TranscriptionResult>
|
|
7
8
|
*
|
|
8
9
|
* No provider SDKs are imported transitively. This module can be
|
|
9
10
|
* consumed by callers that must not pull openai-node, anthropic-sdk,
|
|
@@ -14,3 +15,4 @@
|
|
|
14
15
|
|
|
15
16
|
export { call } from './call.js'
|
|
16
17
|
export { callImage } from './call_image.js'
|
|
18
|
+
export { callTranscription } from './call_transcription.js'
|
package/js/session/driver.js
CHANGED
|
@@ -16,6 +16,7 @@ import readline from 'node:readline'
|
|
|
16
16
|
|
|
17
17
|
import { run } from './run.js'
|
|
18
18
|
import { runImage } from './run_image.js'
|
|
19
|
+
import { runTranscription } from './run_transcription.js'
|
|
19
20
|
import { setCatalog } from './adapters/_catalog.js'
|
|
20
21
|
|
|
21
22
|
// Bounded memory for pre-dequeue cancels. Hostile/buggy supervisors
|
|
@@ -148,6 +149,16 @@ export async function drive (stdin, stdout) {
|
|
|
148
149
|
} else {
|
|
149
150
|
stdout.write(JSON.stringify({ type: 'error', error: out.error }) + '\n')
|
|
150
151
|
}
|
|
152
|
+
} else if (envelope.op === 'transcription') {
|
|
153
|
+
// Same one-shot contract as the image path; shape matches
|
|
154
|
+
// `js/core/transcription.js` after the tag strip.
|
|
155
|
+
const { op: _op, ...trEnv } = envelope
|
|
156
|
+
const out = await runTranscription(trEnv)
|
|
157
|
+
if (out.ok) {
|
|
158
|
+
stdout.write(JSON.stringify({ type: 'transcription_done', result: out.result }) + '\n')
|
|
159
|
+
} else {
|
|
160
|
+
stdout.write(JSON.stringify({ type: 'error', error: out.error }) + '\n')
|
|
161
|
+
}
|
|
151
162
|
} else {
|
|
152
163
|
for await (const ev of run(envelope, { signal: controller.signal })) {
|
|
153
164
|
stdout.write(JSON.stringify(ev) + '\n')
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mohdel",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.112.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Christophe Le Bars",
|
|
@@ -87,7 +87,7 @@
|
|
|
87
87
|
"@opentelemetry/exporter-trace-otlp-grpc": "^0.218.0",
|
|
88
88
|
"@opentelemetry/sdk-node": "^0.218.0",
|
|
89
89
|
"chalk": "^5.4.0",
|
|
90
|
-
"mohdel-thin-gate-linux-x64-gnu": "0.
|
|
90
|
+
"mohdel-thin-gate-linux-x64-gnu": "0.112.0"
|
|
91
91
|
},
|
|
92
92
|
"dependencies": {
|
|
93
93
|
"@anthropic-ai/sdk": "^0.104.1",
|