osborn 0.9.194 → 0.9.195
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/dist/config.d.ts +9 -3
- package/dist/config.js +79 -30
- package/dist/index.js +10 -14
- package/dist/pipeline-fastbrain.js +3 -1
- package/dist/voice-io.d.ts +0 -6
- package/dist/voice-io.js +0 -20
- package/package.json +1 -1
package/dist/config.d.ts
CHANGED
|
@@ -2,8 +2,8 @@ import type { McpServerConfig } from './claude-handler.js';
|
|
|
2
2
|
export type VoiceMode = 'pipeline';
|
|
3
3
|
export type EditMode = 'read-only' | 'edit';
|
|
4
4
|
export type AgentMode = 'plan' | 'execute' | 'research';
|
|
5
|
-
export type STTProvider = 'soniox' | 'deepgram' | 'groq-whisper' | 'openai-whisper';
|
|
6
|
-
export type TTSProvider = 'soniox' | 'openai' | 'deepgram';
|
|
5
|
+
export type STTProvider = 'soniox' | 'deepgram' | 'deepgram-flux' | 'groq-whisper' | 'openai-whisper';
|
|
6
|
+
export type TTSProvider = 'soniox' | 'openai' | 'deepgram' | 'groq-orpheus' | 'fishaudio' | 'rime';
|
|
7
7
|
export interface DirectConfig {
|
|
8
8
|
stt?: {
|
|
9
9
|
provider?: STTProvider;
|
|
@@ -16,11 +16,16 @@ export interface DirectConfig {
|
|
|
16
16
|
voice?: string;
|
|
17
17
|
};
|
|
18
18
|
}
|
|
19
|
+
export interface InferenceConfig {
|
|
20
|
+
fastBrainModel?: string;
|
|
21
|
+
fastBrainProvider?: 'openrouter';
|
|
22
|
+
}
|
|
19
23
|
export interface OsbornConfig {
|
|
20
24
|
workingDirectory?: string;
|
|
21
25
|
mcpServers?: Record<string, McpServerConfigYaml>;
|
|
22
26
|
voiceMode?: VoiceMode;
|
|
23
27
|
direct?: DirectConfig;
|
|
28
|
+
inference?: InferenceConfig;
|
|
24
29
|
}
|
|
25
30
|
interface McpServerConfigYaml {
|
|
26
31
|
enabled?: boolean;
|
|
@@ -76,7 +81,8 @@ export declare function getVoiceMode(_config: OsbornConfig): VoiceMode;
|
|
|
76
81
|
/**
|
|
77
82
|
* Get pipeline mode config with defaults merged
|
|
78
83
|
*/
|
|
79
|
-
export declare function getDirectConfig(
|
|
84
|
+
export declare function getDirectConfig(_config: OsbornConfig): Required<DirectConfig>;
|
|
85
|
+
export declare function getInferenceConfig(_config: OsbornConfig): Required<InferenceConfig>;
|
|
80
86
|
/**
|
|
81
87
|
* Save config to file
|
|
82
88
|
*/
|
package/dist/config.js
CHANGED
|
@@ -43,35 +43,74 @@ export const MCP_CATALOG = [
|
|
|
43
43
|
// (`/usr/local/nvm/.../osborn`) and gets persisted to ~/.osborn/config.yaml forever.
|
|
44
44
|
// Leaving it undefined lets the runtime self-heal in index.ts resolve it on every boot
|
|
45
45
|
// from OSBORN_CWD → process.cwd() at the actual time the agent starts.
|
|
46
|
+
// ============================================================
|
|
47
|
+
// PROVIDER DEFAULTS — Single source of truth for STT, TTS, and inference.
|
|
48
|
+
// To switch provider: change `provider` (and model/voice) here.
|
|
49
|
+
// All alternatives are listed as comments. Env vars override without redeploy:
|
|
50
|
+
// STT: OSBORN_STT_PROVIDER, OSBORN_STT_MODEL, OSBORN_STT_LANGUAGE
|
|
51
|
+
// TTS: OSBORN_TTS_PROVIDER, OSBORN_TTS_MODEL, OSBORN_TTS_VOICE
|
|
52
|
+
// Inference: OSBORN_FAST_BRAIN_MODEL
|
|
53
|
+
// These are admin-owned defaults — NOT written to config.yaml on disk.
|
|
54
|
+
// ============================================================
|
|
46
55
|
const DEFAULT_CONFIG = {
|
|
47
56
|
voiceMode: 'pipeline',
|
|
48
57
|
direct: {
|
|
49
58
|
stt: {
|
|
50
|
-
//
|
|
51
|
-
// custom vocabulary via context.terms. ~60% cheaper than nova-3 ($0.0017 vs $0.0043/min).
|
|
52
|
-
// Needs SONIOX_API_KEY.
|
|
59
|
+
// ── Active ─────────────────────────────────────────────────────────────
|
|
53
60
|
provider: 'soniox',
|
|
54
61
|
model: 'stt-rt-v4',
|
|
55
|
-
//
|
|
56
|
-
//
|
|
62
|
+
// Semantic endpointing — ML model holds on incomplete thoughts, commits on
|
|
63
|
+
// natural sentence ends. ~60% cheaper than nova-3 ($0.0017 vs $0.0043/min).
|
|
64
|
+
// Needs SONIOX_API_KEY. See voice-io.ts createSTT for tuning params.
|
|
65
|
+
//
|
|
66
|
+
// ── Alternatives ───────────────────────────────────────────────────────
|
|
67
|
+
// provider: 'deepgram', model: 'nova-3'
|
|
68
|
+
// Silence-based endpointing (550ms). Fast, reliable. $0.0043/min.
|
|
69
|
+
// provider: 'deepgram-flux', model: 'flux-general-en'
|
|
70
|
+
// ML turn detection (server-side). Flux V2 has 30s silent keepalive bug.
|
|
71
|
+
// provider: 'groq-whisper', model: 'whisper-large-v3-turbo'
|
|
72
|
+
// Batch STT via Groq (very fast). Requires VAD for turn detection.
|
|
73
|
+
// provider: 'openai-whisper', model: 'whisper-1'
|
|
74
|
+
// Batch STT via OpenAI. Requires VAD. $0.006/min.
|
|
57
75
|
},
|
|
58
76
|
tts: {
|
|
59
|
-
//
|
|
60
|
-
// clean abort on interruption. Estimated ~$4–16/M chars vs OpenAI tts-1-hd $30/M.
|
|
61
|
-
// Pricing: $0.70/hr of generated speech (preview). Needs SONIOX_API_KEY.
|
|
77
|
+
// ── Active ─────────────────────────────────────────────────────────────
|
|
62
78
|
provider: 'soniox',
|
|
63
79
|
model: 'tts-rt-v1',
|
|
64
80
|
voice: 'Victoria',
|
|
65
|
-
//
|
|
66
|
-
//
|
|
67
|
-
//
|
|
68
|
-
//
|
|
69
|
-
//
|
|
70
|
-
//
|
|
71
|
-
//
|
|
72
|
-
//
|
|
81
|
+
// WebSocket streaming — clean abort on interruption. Speed control 0.7–1.3x.
|
|
82
|
+
// Est. ~$4–16/M chars vs OpenAI $30/M. Victoria = en-GB female, refined.
|
|
83
|
+
// Also: Isla (en-GB, lively), Maya (en-US female). Needs SONIOX_API_KEY.
|
|
84
|
+
//
|
|
85
|
+
// ── Alternatives ───────────────────────────────────────────────────────
|
|
86
|
+
// provider: 'openai', model: 'tts-1-hd', voice: 'fable'
|
|
87
|
+
// $30/M chars, ~500ms TTFB, HTTP streaming. 6 voices: alloy echo fable onyx nova shimmer.
|
|
88
|
+
// provider: 'openai', model: 'tts-1', voice: 'fable'
|
|
89
|
+
// $15/M chars, slightly lower quality, same voices.
|
|
90
|
+
// provider: 'deepgram', model: 'aura-2-asteria-en'
|
|
91
|
+
// $15/M chars, ~100ms TTFB, WebSocket. Voices: asteria luna stella hera orion arcas perseus angus orpheus.
|
|
92
|
+
// provider: 'rime', model: 'mistv3', voice: 'cove'
|
|
93
|
+
// $30/M chars, 37ms TTFB, WebSocket (clean abort). Voices: aurora ember cove. Needs RIME_API_KEY.
|
|
94
|
+
// provider: 'fishaudio', model: 's2-pro', voice: '<voice-id>'
|
|
95
|
+
// $15/M chars, voice cloning, HTTP streaming. Needs FISH_AUDIO_API_KEY.
|
|
96
|
+
// provider: 'groq-orpheus', model: 'canopylabs/orpheus-v1-english', voice: 'autumn'
|
|
97
|
+
// $22/M chars, fast (Groq chips). Voices: autumn diana hannah austin daniel troy.
|
|
73
98
|
},
|
|
74
99
|
},
|
|
100
|
+
inference: {
|
|
101
|
+
// ── Active ───────────────────────────────────────────────────────────────
|
|
102
|
+
fastBrainModel: 'deepseek/deepseek-chat',
|
|
103
|
+
fastBrainProvider: 'openrouter',
|
|
104
|
+
// Parallel fast brain: answers greetings/follow-ups instantly while main agent
|
|
105
|
+
// processes. Uses OpenRouter (OPENROUTER_API_KEY). ~20ms TTFB on deepseek-chat.
|
|
106
|
+
//
|
|
107
|
+
// ── Alternatives ─────────────────────────────────────────────────────────
|
|
108
|
+
// fastBrainModel: 'deepseek/deepseek-reasoner' — slower, deeper CoT
|
|
109
|
+
// fastBrainModel: 'google/gemini-flash-1.5' — Google via OpenRouter
|
|
110
|
+
// fastBrainModel: 'openai/gpt-4o-mini' — OpenAI via OpenRouter
|
|
111
|
+
// fastBrainModel: 'meta-llama/llama-3.1-8b-instruct:free' — free tier via OpenRouter
|
|
112
|
+
// fastBrainModel: 'anthropic/claude-haiku-4-5-20251001' — Haiku via OpenRouter
|
|
113
|
+
},
|
|
75
114
|
mcpServers: {
|
|
76
115
|
// ─────────────────────────────────────────────────────────────────────────
|
|
77
116
|
// MCP Servers for Read-Only Plan Mode
|
|
@@ -139,10 +178,12 @@ export function loadConfig() {
|
|
|
139
178
|
mkdirSync(CONFIG_DIR, { recursive: true });
|
|
140
179
|
console.log(`📁 Created config directory: ${CONFIG_DIR}`);
|
|
141
180
|
}
|
|
142
|
-
// Create default config if it doesn't exist
|
|
181
|
+
// Create default config if it doesn't exist.
|
|
182
|
+
// Exclude `direct` (STT/TTS) and `inference` — admin-owned, not user config on disk.
|
|
183
|
+
// Writing them to disk causes the file to permanently override npm package updates.
|
|
143
184
|
if (!existsSync(CONFIG_FILE)) {
|
|
144
|
-
const
|
|
145
|
-
writeFileSync(CONFIG_FILE,
|
|
185
|
+
const { direct: _d, inference: _i, ...persistable } = DEFAULT_CONFIG;
|
|
186
|
+
writeFileSync(CONFIG_FILE, stringify(persistable), 'utf-8');
|
|
146
187
|
console.log(`📝 Created default config: ${CONFIG_FILE}`);
|
|
147
188
|
return DEFAULT_CONFIG;
|
|
148
189
|
}
|
|
@@ -207,25 +248,33 @@ export function getVoiceMode(_config) {
|
|
|
207
248
|
/**
|
|
208
249
|
* Get pipeline mode config with defaults merged
|
|
209
250
|
*/
|
|
210
|
-
export function getDirectConfig(
|
|
251
|
+
export function getDirectConfig(_config) {
|
|
211
252
|
const defaults = DEFAULT_CONFIG.direct;
|
|
212
|
-
|
|
213
|
-
//
|
|
214
|
-
//
|
|
215
|
-
//
|
|
253
|
+
// STT/TTS settings are admin-owned defaults — they live in DEFAULT_CONFIG only.
|
|
254
|
+
// config.yaml is intentionally NOT consulted here: writing provider settings
|
|
255
|
+
// to the volume creates a stale file that permanently overrides npm updates.
|
|
256
|
+
// To override without a redeploy, set OSBORN_STT_PROVIDER / OSBORN_TTS_PROVIDER
|
|
257
|
+
// / OSBORN_TTS_VOICE / OSBORN_STT_MODEL / OSBORN_TTS_MODEL on the machine.
|
|
216
258
|
return {
|
|
217
259
|
stt: {
|
|
218
|
-
provider: (process.env.OSBORN_STT_PROVIDER ||
|
|
219
|
-
model: process.env.OSBORN_STT_MODEL ||
|
|
220
|
-
language:
|
|
260
|
+
provider: (process.env.OSBORN_STT_PROVIDER || defaults.stt.provider),
|
|
261
|
+
model: process.env.OSBORN_STT_MODEL || defaults.stt.model,
|
|
262
|
+
language: process.env.OSBORN_STT_LANGUAGE || 'en',
|
|
221
263
|
},
|
|
222
264
|
tts: {
|
|
223
|
-
provider: (process.env.OSBORN_TTS_PROVIDER ||
|
|
224
|
-
model: process.env.OSBORN_TTS_MODEL ||
|
|
225
|
-
voice: process.env.OSBORN_TTS_VOICE ||
|
|
265
|
+
provider: (process.env.OSBORN_TTS_PROVIDER || defaults.tts.provider),
|
|
266
|
+
model: process.env.OSBORN_TTS_MODEL || defaults.tts.model,
|
|
267
|
+
voice: process.env.OSBORN_TTS_VOICE || defaults.tts.voice,
|
|
226
268
|
},
|
|
227
269
|
};
|
|
228
270
|
}
|
|
271
|
+
export function getInferenceConfig(_config) {
|
|
272
|
+
const defaults = DEFAULT_CONFIG.inference;
|
|
273
|
+
return {
|
|
274
|
+
fastBrainModel: process.env.OSBORN_FAST_BRAIN_MODEL || defaults.fastBrainModel,
|
|
275
|
+
fastBrainProvider: 'openrouter',
|
|
276
|
+
};
|
|
277
|
+
}
|
|
229
278
|
/**
|
|
230
279
|
* Save config to file
|
|
231
280
|
*/
|
package/dist/index.js
CHANGED
|
@@ -30,7 +30,7 @@ const __filename = fileURLToPath(import.meta.url);
|
|
|
30
30
|
const __dirname = dirname(__filename);
|
|
31
31
|
import { createPatch } from 'diff';
|
|
32
32
|
import { loadConfig, getMcpServers, getEnabledMcpServerNames, getVoiceMode, getDirectConfig, listSessions, listAllClaudeSessions, invalidateSessionListCache, getMostRecentSessionId, sessionExists, getSessionSummary, getConversationHistory, ensureSessionWorkspace, getMcpServerStatusList, buildMcpServersForKeys, listWorkspaceArtifacts } from './config.js';
|
|
33
|
-
import { createSTT, createTTS
|
|
33
|
+
import { createSTT, createTTS } from './voice-io.js';
|
|
34
34
|
import { createClaudeLLM, NAMED_AGENTS, applyTurbo } from './claude-llm.js';
|
|
35
35
|
import { clearPipelineFastBrainSession, prewarmBM25Index } from './pipeline-fastbrain.js';
|
|
36
36
|
import { getIndexPath, buildSummaryIndex } from './summary-index.js';
|
|
@@ -417,13 +417,11 @@ async function synthMp3(text) {
|
|
|
417
417
|
console.warn('⚠️ synthMp3: no OPENAI_API_KEY — meeting has no voice');
|
|
418
418
|
return null;
|
|
419
419
|
}
|
|
420
|
-
// Meeting
|
|
421
|
-
//
|
|
422
|
-
//
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
const model = DIRECT_MODE_TTS.provider === 'openai' ? (DIRECT_MODE_TTS.model || 'tts-1-hd') : 'tts-1-hd';
|
|
426
|
-
const voice = DIRECT_MODE_TTS.provider === 'openai' ? (DIRECT_MODE_TTS.voice || 'fable') : 'fable';
|
|
420
|
+
// Meeting audio is always OpenAI TTS (HTTP MP3 required for Recall output_audio).
|
|
421
|
+
// Reads OSBORN_TTS_* env vars — same source as getDirectConfig — so voice is
|
|
422
|
+
// consistent between the pipeline and meeting canvas when TTS provider is openai.
|
|
423
|
+
const model = process.env.OSBORN_TTS_PROVIDER === 'openai' ? (process.env.OSBORN_TTS_MODEL || 'tts-1-hd') : 'tts-1-hd';
|
|
424
|
+
const voice = process.env.OSBORN_TTS_PROVIDER === 'openai' ? (process.env.OSBORN_TTS_VOICE || 'fable') : 'fable';
|
|
427
425
|
try {
|
|
428
426
|
const r = await fetch('https://api.openai.com/v1/audio/speech', {
|
|
429
427
|
method: 'POST',
|
|
@@ -859,18 +857,16 @@ function startApiServer(workingDir, port) {
|
|
|
859
857
|
return;
|
|
860
858
|
}
|
|
861
859
|
const t0 = Date.now();
|
|
862
|
-
// Meeting
|
|
863
|
-
//
|
|
864
|
-
// sounded cheap/inconsistent. Consistency over the ~2-4s latency Deepgram
|
|
865
|
-
// saved. mp3 out (the canvas <audio> element plays it into the meeting).
|
|
860
|
+
// Meeting canvas TTS — always OpenAI HTTP (mp3 for <audio> element).
|
|
861
|
+
// Reads OSBORN_TTS_* env vars so voice stays in sync with pipeline when provider is openai.
|
|
866
862
|
const key = process.env.OPENAI_API_KEY;
|
|
867
863
|
if (!key) {
|
|
868
864
|
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
869
865
|
res.end(JSON.stringify({ error: 'no OPENAI_API_KEY' }));
|
|
870
866
|
return;
|
|
871
867
|
}
|
|
872
|
-
const model =
|
|
873
|
-
const voice = url.searchParams.get('voice') || (
|
|
868
|
+
const model = process.env.OSBORN_TTS_PROVIDER === 'openai' ? (process.env.OSBORN_TTS_MODEL || 'tts-1-hd') : 'tts-1-hd';
|
|
869
|
+
const voice = url.searchParams.get('voice') || (process.env.OSBORN_TTS_PROVIDER === 'openai' ? (process.env.OSBORN_TTS_VOICE || 'fable') : 'fable');
|
|
874
870
|
try {
|
|
875
871
|
const tts = await fetch('https://api.openai.com/v1/audio/speech', {
|
|
876
872
|
method: 'POST',
|
|
@@ -15,7 +15,9 @@
|
|
|
15
15
|
// ============================================================
|
|
16
16
|
// CONSTANTS
|
|
17
17
|
// ============================================================
|
|
18
|
-
|
|
18
|
+
// Model reads from env var (set by main process from getInferenceConfig) or DEFAULT_CONFIG default.
|
|
19
|
+
// To switch model: update DEFAULT_CONFIG.inference.fastBrainModel in config.ts, or set OSBORN_FAST_BRAIN_MODEL env var.
|
|
20
|
+
const OPENROUTER_MODEL = process.env.OSBORN_FAST_BRAIN_MODEL || 'deepseek/deepseek-chat';
|
|
19
21
|
const OPENROUTER_URL = 'https://openrouter.ai/api/v1/chat/completions';
|
|
20
22
|
const TIMEOUT_MS = 20_000;
|
|
21
23
|
const MAX_TOOL_ROUNDS = 4;
|
package/dist/voice-io.d.ts
CHANGED
|
@@ -42,9 +42,3 @@ export declare function createTTS(config: TTSConfig): any;
|
|
|
42
42
|
* - False triggers from ambient noise
|
|
43
43
|
*/
|
|
44
44
|
export declare function createVAD(): Promise<silero.VAD>;
|
|
45
|
-
/**
|
|
46
|
-
* Pipeline mode voice config — centralized here for easy provider swapping.
|
|
47
|
-
* To switch providers: comment out the active line, uncomment the alternative.
|
|
48
|
-
*/
|
|
49
|
-
export declare const DIRECT_MODE_STT: STTConfig;
|
|
50
|
-
export declare const DIRECT_MODE_TTS: TTSConfig;
|
package/dist/voice-io.js
CHANGED
|
@@ -154,23 +154,3 @@ export async function createVAD() {
|
|
|
154
154
|
activationThreshold: 0.85, // default — balanced for interruptions only
|
|
155
155
|
});
|
|
156
156
|
}
|
|
157
|
-
/**
|
|
158
|
-
* Pipeline mode voice config — centralized here for easy provider swapping.
|
|
159
|
-
* To switch providers: comment out the active line, uncomment the alternative.
|
|
160
|
-
*/
|
|
161
|
-
export const DIRECT_MODE_STT = {
|
|
162
|
-
// provider: 'groq-whisper', model: 'whisper-large-v3-turbo', // Batch — needs VAD
|
|
163
|
-
// provider: 'openai-whisper', model: 'whisper-1', // Batch — needs VAD
|
|
164
|
-
// provider: 'deepgram-flux', model: 'flux-general-en', language: 'en', // Streaming, ML-based turn detection — Flux V2 has silent keepalive timeout bug (~30s silence kills connection)
|
|
165
|
-
// provider: 'deepgram', model: 'nova-3', language: 'en', // Silence-based endpointing (550ms) — $0.0043/min
|
|
166
|
-
provider: 'soniox', model: 'stt-rt-v4', language: 'en', // Semantic endpointing, ~60% cheaper ($0.0017/min) — needs SONIOX_API_KEY
|
|
167
|
-
};
|
|
168
|
-
export const DIRECT_MODE_TTS = {
|
|
169
|
-
// provider: 'deepgram', model: 'aura-2-asteria-en', // WebSocket-based: handles TTS abort cleanly — but quality rejected (run-on sentences)
|
|
170
|
-
// provider: 'openai', model: 'tts-1', voice: 'fable', // HTTP streaming: throws APIUserAbortError on interrupt → unrecoverable session crash
|
|
171
|
-
// provider: 'openai', model: 'tts-1-hd', voice: 'fable', // $30/M chars, ~500ms TTFB — fallback if Soniox has issues
|
|
172
|
-
// provider: 'groq-orpheus', model: 'canopylabs/orpheus-v1-english', voice: 'autumn', // $22/M chars — voices: autumn, diana, hannah, austin, daniel, troy
|
|
173
|
-
// provider: 'fishaudio', model: 's2-pro', voice: '<voice-id>', // $15/M chars — blind test winner, HTTP streaming (test abort behavior)
|
|
174
|
-
// provider: 'rime', model: 'mistv3', voice: 'cove', // $30/M chars, 37ms TTFB — WebSocket (safe on interruption); voices: aurora, ember, cove
|
|
175
|
-
provider: 'soniox', model: 'tts-rt-v1', voice: 'Victoria', // WebSocket streaming, ~$4–16/M chars, British female — needs SONIOX_API_KEY
|
|
176
|
-
};
|