@tractorscorch/clank 1.3.0 → 1.3.1
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/CHANGELOG.md +9 -0
- package/dist/index.js +47 -35
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,15 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/).
|
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
+
## [1.3.1] — 2026-03-23
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
- **STT not working** — local whisper.cpp was selected by default but not installed. Added Groq as the recommended free STT provider (whisper-large-v3-turbo).
|
|
13
|
+
- **STT provider priority:** Groq (free, fast) → OpenAI Whisper → local whisper.cpp
|
|
14
|
+
- **Setup wizard:** STT now offers Groq as option 1 (recommended), OpenAI as option 2, local as option 3
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
9
18
|
## [1.3.0] — 2026-03-23
|
|
10
19
|
|
|
11
20
|
### Added
|
package/dist/index.js
CHANGED
|
@@ -3931,11 +3931,9 @@ var init_tts = __esm({
|
|
|
3931
3931
|
constructor(config) {
|
|
3932
3932
|
this.config = config;
|
|
3933
3933
|
}
|
|
3934
|
-
/** Check if TTS is available */
|
|
3935
3934
|
isAvailable() {
|
|
3936
3935
|
return !!(this.config.integrations.elevenlabs?.enabled && this.config.integrations.elevenlabs?.apiKey);
|
|
3937
3936
|
}
|
|
3938
|
-
/** Convert text to speech */
|
|
3939
3937
|
async synthesize(text, opts) {
|
|
3940
3938
|
const elevenlabs = this.config.integrations.elevenlabs;
|
|
3941
3939
|
if (!elevenlabs?.enabled || !elevenlabs.apiKey) return null;
|
|
@@ -3953,29 +3951,21 @@ var init_tts = __esm({
|
|
|
3953
3951
|
body: JSON.stringify({
|
|
3954
3952
|
text,
|
|
3955
3953
|
model_id: model,
|
|
3956
|
-
voice_settings: {
|
|
3957
|
-
stability: 0.5,
|
|
3958
|
-
similarity_boost: 0.75
|
|
3959
|
-
}
|
|
3954
|
+
voice_settings: { stability: 0.5, similarity_boost: 0.75 }
|
|
3960
3955
|
})
|
|
3961
3956
|
}
|
|
3962
3957
|
);
|
|
3963
3958
|
if (!res.ok) {
|
|
3964
|
-
|
|
3965
|
-
console.error(`ElevenLabs TTS error ${res.status}: ${err}`);
|
|
3959
|
+
console.error(`ElevenLabs TTS error ${res.status}`);
|
|
3966
3960
|
return null;
|
|
3967
3961
|
}
|
|
3968
3962
|
const arrayBuffer = await res.arrayBuffer();
|
|
3969
|
-
return {
|
|
3970
|
-
audioBuffer: Buffer.from(arrayBuffer),
|
|
3971
|
-
format: "mp3"
|
|
3972
|
-
};
|
|
3963
|
+
return { audioBuffer: Buffer.from(arrayBuffer), format: "mp3" };
|
|
3973
3964
|
} catch (err) {
|
|
3974
3965
|
console.error(`TTS error: ${err instanceof Error ? err.message : err}`);
|
|
3975
3966
|
return null;
|
|
3976
3967
|
}
|
|
3977
3968
|
}
|
|
3978
|
-
/** List available voices from ElevenLabs */
|
|
3979
3969
|
async listVoices() {
|
|
3980
3970
|
const elevenlabs = this.config.integrations.elevenlabs;
|
|
3981
3971
|
if (!elevenlabs?.enabled || !elevenlabs.apiKey) return [];
|
|
@@ -3996,41 +3986,55 @@ var init_tts = __esm({
|
|
|
3996
3986
|
constructor(config) {
|
|
3997
3987
|
this.config = config;
|
|
3998
3988
|
}
|
|
3999
|
-
/** Check if STT is available */
|
|
4000
3989
|
isAvailable() {
|
|
4001
3990
|
const whisper = this.config.integrations.whisper;
|
|
4002
3991
|
if (whisper?.enabled) {
|
|
3992
|
+
if (whisper.provider === "groq" && whisper.apiKey) return true;
|
|
4003
3993
|
if (whisper.provider === "openai" && whisper.apiKey) return true;
|
|
4004
3994
|
if (whisper.provider === "local") return true;
|
|
4005
3995
|
}
|
|
4006
3996
|
if (this.config.models.providers.openai?.apiKey) return true;
|
|
3997
|
+
if (this.config.integrations.groq?.apiKey) return true;
|
|
4007
3998
|
return false;
|
|
4008
3999
|
}
|
|
4009
|
-
/** Transcribe audio to text */
|
|
4010
4000
|
async transcribe(audioBuffer, format = "ogg") {
|
|
4011
4001
|
const whisper = this.config.integrations.whisper;
|
|
4012
|
-
const
|
|
4013
|
-
if (
|
|
4014
|
-
|
|
4002
|
+
const groqKey = whisper?.provider === "groq" && whisper?.apiKey ? whisper.apiKey : this.config.integrations.groq?.apiKey;
|
|
4003
|
+
if (groqKey) {
|
|
4004
|
+
const result = await this.transcribeAPI(audioBuffer, format, groqKey, "https://api.groq.com/openai/v1/audio/transcriptions", "whisper-large-v3-turbo");
|
|
4005
|
+
if (result) return result;
|
|
4006
|
+
}
|
|
4007
|
+
const openaiKey = whisper?.provider === "openai" && whisper?.apiKey ? whisper.apiKey : this.config.models.providers.openai?.apiKey;
|
|
4008
|
+
if (openaiKey) {
|
|
4009
|
+
const result = await this.transcribeAPI(audioBuffer, format, openaiKey, "https://api.openai.com/v1/audio/transcriptions", "whisper-1");
|
|
4010
|
+
if (result) return result;
|
|
4011
|
+
}
|
|
4012
|
+
if (whisper?.provider === "local") {
|
|
4013
|
+
return this.transcribeLocal(audioBuffer, format);
|
|
4015
4014
|
}
|
|
4016
|
-
return
|
|
4015
|
+
return null;
|
|
4017
4016
|
}
|
|
4018
|
-
/** Transcribe via OpenAI
|
|
4019
|
-
async
|
|
4017
|
+
/** Transcribe via OpenAI-compatible API (works for both OpenAI and Groq) */
|
|
4018
|
+
async transcribeAPI(audioBuffer, format, apiKey, endpoint, model) {
|
|
4020
4019
|
try {
|
|
4021
4020
|
const blob = new Blob([new Uint8Array(audioBuffer)], { type: `audio/${format}` });
|
|
4022
4021
|
const formData = new FormData();
|
|
4023
4022
|
formData.append("file", blob, `audio.${format}`);
|
|
4024
|
-
formData.append("model",
|
|
4025
|
-
const res = await fetch(
|
|
4023
|
+
formData.append("model", model);
|
|
4024
|
+
const res = await fetch(endpoint, {
|
|
4026
4025
|
method: "POST",
|
|
4027
4026
|
headers: { "Authorization": `Bearer ${apiKey}` },
|
|
4028
4027
|
body: formData
|
|
4029
4028
|
});
|
|
4030
|
-
if (!res.ok)
|
|
4029
|
+
if (!res.ok) {
|
|
4030
|
+
const errText = await res.text().catch(() => "");
|
|
4031
|
+
console.error(`STT API error ${res.status}: ${errText.slice(0, 200)}`);
|
|
4032
|
+
return null;
|
|
4033
|
+
}
|
|
4031
4034
|
const data = await res.json();
|
|
4032
4035
|
return data.text ? { text: data.text, language: data.language } : null;
|
|
4033
|
-
} catch {
|
|
4036
|
+
} catch (err) {
|
|
4037
|
+
console.error(`STT error: ${err instanceof Error ? err.message : err}`);
|
|
4034
4038
|
return null;
|
|
4035
4039
|
}
|
|
4036
4040
|
}
|
|
@@ -5673,7 +5677,7 @@ var init_server = __esm({
|
|
|
5673
5677
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
5674
5678
|
res.end(JSON.stringify({
|
|
5675
5679
|
status: "ok",
|
|
5676
|
-
version: "1.3.
|
|
5680
|
+
version: "1.3.1",
|
|
5677
5681
|
uptime: process.uptime(),
|
|
5678
5682
|
clients: this.clients.size,
|
|
5679
5683
|
agents: this.engines.size
|
|
@@ -5781,7 +5785,7 @@ var init_server = __esm({
|
|
|
5781
5785
|
const hello = {
|
|
5782
5786
|
type: "hello",
|
|
5783
5787
|
protocol: PROTOCOL_VERSION,
|
|
5784
|
-
version: "1.3.
|
|
5788
|
+
version: "1.3.1",
|
|
5785
5789
|
agents: this.config.agents.list.map((a) => ({
|
|
5786
5790
|
id: a.id,
|
|
5787
5791
|
name: a.name || a.id,
|
|
@@ -6642,27 +6646,35 @@ async function runSetup(opts) {
|
|
|
6642
6646
|
console.log(green4(" ElevenLabs configured (TTS available)"));
|
|
6643
6647
|
}
|
|
6644
6648
|
}
|
|
6645
|
-
const addWhisper = await ask(rl, cyan2(" Set up speech-to-text (
|
|
6649
|
+
const addWhisper = await ask(rl, cyan2(" Set up speech-to-text (voice messages)? [y/N] "));
|
|
6646
6650
|
if (addWhisper.toLowerCase() === "y") {
|
|
6647
|
-
console.log(dim4(" 1.
|
|
6648
|
-
console.log(dim4(" 2.
|
|
6651
|
+
console.log(dim4(" 1. Groq (recommended \u2014 free, fast)"));
|
|
6652
|
+
console.log(dim4(" 2. OpenAI Whisper API (paid, uses OpenAI key)"));
|
|
6653
|
+
console.log(dim4(" 3. Local whisper.cpp (requires manual install)"));
|
|
6649
6654
|
const whisperChoice = await ask(rl, cyan2(" Choice [1]: "));
|
|
6650
|
-
if (whisperChoice === "
|
|
6655
|
+
if (whisperChoice === "3") {
|
|
6651
6656
|
config.integrations.whisper = { enabled: true, provider: "local" };
|
|
6652
6657
|
console.log(green4(" Local whisper.cpp configured"));
|
|
6653
6658
|
console.log(dim4(" Make sure whisper is installed and in PATH"));
|
|
6654
|
-
} else {
|
|
6659
|
+
} else if (whisperChoice === "2") {
|
|
6655
6660
|
const existingKey = config.models.providers.openai?.apiKey;
|
|
6656
6661
|
if (existingKey) {
|
|
6657
6662
|
config.integrations.whisper = { enabled: true, provider: "openai", apiKey: existingKey };
|
|
6658
6663
|
console.log(green4(" Whisper configured (using existing OpenAI key)"));
|
|
6659
6664
|
} else {
|
|
6660
|
-
const key = await ask(rl, cyan2(" OpenAI API key
|
|
6665
|
+
const key = await ask(rl, cyan2(" OpenAI API key: "));
|
|
6661
6666
|
if (key.trim()) {
|
|
6662
6667
|
config.integrations.whisper = { enabled: true, provider: "openai", apiKey: key.trim() };
|
|
6663
6668
|
console.log(green4(" Whisper configured"));
|
|
6664
6669
|
}
|
|
6665
6670
|
}
|
|
6671
|
+
} else {
|
|
6672
|
+
console.log(dim4(" Get a free API key at: https://console.groq.com/keys"));
|
|
6673
|
+
const key = await ask(rl, cyan2(" Groq API key: "));
|
|
6674
|
+
if (key.trim()) {
|
|
6675
|
+
config.integrations.whisper = { enabled: true, provider: "groq", apiKey: key.trim() };
|
|
6676
|
+
console.log(green4(" Groq Whisper configured (free, fast)"));
|
|
6677
|
+
}
|
|
6666
6678
|
}
|
|
6667
6679
|
}
|
|
6668
6680
|
if (isAdvanced) {
|
|
@@ -7138,7 +7150,7 @@ async function runTui(opts) {
|
|
|
7138
7150
|
ws.on("open", () => {
|
|
7139
7151
|
ws.send(JSON.stringify({
|
|
7140
7152
|
type: "connect",
|
|
7141
|
-
params: { auth: { token }, mode: "tui", version: "1.3.
|
|
7153
|
+
params: { auth: { token }, mode: "tui", version: "1.3.1" }
|
|
7142
7154
|
}));
|
|
7143
7155
|
});
|
|
7144
7156
|
ws.on("message", (data) => {
|
|
@@ -7567,7 +7579,7 @@ import { fileURLToPath as fileURLToPath5 } from "url";
|
|
|
7567
7579
|
import { dirname as dirname5, join as join18 } from "path";
|
|
7568
7580
|
var __filename3 = fileURLToPath5(import.meta.url);
|
|
7569
7581
|
var __dirname3 = dirname5(__filename3);
|
|
7570
|
-
var version = "1.3.
|
|
7582
|
+
var version = "1.3.1";
|
|
7571
7583
|
try {
|
|
7572
7584
|
const pkg = JSON.parse(readFileSync(join18(__dirname3, "..", "package.json"), "utf-8"));
|
|
7573
7585
|
version = pkg.version;
|