osborn 0.8.34 → 0.8.35
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/index.js +32 -6
- package/dist/meeting-output.html +32 -0
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -11,7 +11,13 @@ import { setMaxListeners } from 'node:events';
|
|
|
11
11
|
setMaxListeners(50);
|
|
12
12
|
import { createServer } from 'http';
|
|
13
13
|
import { existsSync, readdirSync, readFileSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
14
|
-
import { join } from 'node:path';
|
|
14
|
+
import { dirname, join } from 'node:path';
|
|
15
|
+
import { fileURLToPath } from 'node:url';
|
|
16
|
+
// Resolve __dirname for this ESM module so we can find sibling files (e.g.
|
|
17
|
+
// meeting-output.html) relative to the compiled JS location, NOT process.cwd().
|
|
18
|
+
// In production cwd is the user's workspace; the static file lives next to dist/index.js.
|
|
19
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
20
|
+
const __dirname = dirname(__filename);
|
|
15
21
|
import { createPatch } from 'diff';
|
|
16
22
|
import { loadConfig, getMcpServers, getEnabledMcpServerNames, getVoiceMode, getRealtimeConfig, getDirectConfig, listAllClaudeSessions, getMostRecentSessionId, sessionExists, getSessionSummary, getConversationHistory, ensureSessionWorkspace, getSessionWorkspace, getMcpServerStatusList, buildMcpServersForKeys, listWorkspaceArtifacts } from './config.js';
|
|
17
23
|
import { createSTT, createTTS, createRealtimeModelFromConfig, DIRECT_MODE_STT, DIRECT_MODE_TTS } from './voice-io.js';
|
|
@@ -200,15 +206,35 @@ function startApiServer(workingDir, port) {
|
|
|
200
206
|
});
|
|
201
207
|
return;
|
|
202
208
|
}
|
|
203
|
-
// GET /meeting-output — Output Media webpage for Recall.ai bot audio
|
|
209
|
+
// GET /meeting-output — Output Media webpage for Recall.ai bot audio.
|
|
210
|
+
//
|
|
211
|
+
// The file lives next to this compiled JS (copied by the build script from
|
|
212
|
+
// src/ to dist/). Resolve via __dirname rather than process.cwd() — in
|
|
213
|
+
// production cwd is the user's workspace, NOT the osborn package directory.
|
|
204
214
|
if (req.method === 'GET' && url.pathname === '/meeting-output') {
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
215
|
+
// Try the package-relative path first (post-build location), then fall
|
|
216
|
+
// back to source path for `tsx src/index.ts` dev runs.
|
|
217
|
+
const candidates = [
|
|
218
|
+
join(__dirname, 'meeting-output.html'), // dist/ (production)
|
|
219
|
+
join(__dirname, '..', 'src', 'meeting-output.html'), // dev: dist/ → src/
|
|
220
|
+
join(__dirname, '..', 'meeting-output.html'), // tsx run from src/
|
|
221
|
+
];
|
|
222
|
+
let html = null;
|
|
223
|
+
let foundPath = null;
|
|
224
|
+
for (const p of candidates) {
|
|
225
|
+
try {
|
|
226
|
+
html = readFileSync(p, 'utf-8');
|
|
227
|
+
foundPath = p;
|
|
228
|
+
break;
|
|
229
|
+
}
|
|
230
|
+
catch { }
|
|
231
|
+
}
|
|
232
|
+
if (html) {
|
|
208
233
|
res.writeHead(200, { 'Content-Type': 'text/html' });
|
|
209
234
|
res.end(html);
|
|
210
235
|
}
|
|
211
|
-
|
|
236
|
+
else {
|
|
237
|
+
console.warn(`[meeting-output] not found in any of: ${candidates.join(', ')}`);
|
|
212
238
|
res.writeHead(404, { 'Content-Type': 'text/plain' });
|
|
213
239
|
res.end('meeting-output.html not found');
|
|
214
240
|
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head><title>Osborn Meeting Output</title></head>
|
|
4
|
+
<body>
|
|
5
|
+
<script>
|
|
6
|
+
const botId = new URLSearchParams(window.location.search).get('bot_id') || 'unknown'
|
|
7
|
+
|
|
8
|
+
function connect() {
|
|
9
|
+
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'
|
|
10
|
+
const ws = new WebSocket(`${protocol}//${window.location.host}/meeting-audio?bot_id=${botId}`)
|
|
11
|
+
|
|
12
|
+
ws.onmessage = async (event) => {
|
|
13
|
+
try {
|
|
14
|
+
const audioCtx = new (window.AudioContext || window.webkitAudioContext)()
|
|
15
|
+
const arrayBuffer = await event.data.arrayBuffer()
|
|
16
|
+
const audioBuffer = await audioCtx.decodeAudioData(arrayBuffer)
|
|
17
|
+
const source = audioCtx.createBufferSource()
|
|
18
|
+
source.buffer = audioBuffer
|
|
19
|
+
source.connect(audioCtx.destination)
|
|
20
|
+
source.start()
|
|
21
|
+
} catch (e) {
|
|
22
|
+
console.error('Audio playback error:', e)
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
ws.onclose = () => setTimeout(connect, 1000)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
connect()
|
|
30
|
+
</script>
|
|
31
|
+
</body>
|
|
32
|
+
</html>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "osborn",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.35",
|
|
4
4
|
"description": "Voice AI coding assistant - local agent that connects to Osborn frontend",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"dev:logged": "tsx scripts/dev-logged.ts",
|
|
12
12
|
"review": "tsx scripts/review.ts",
|
|
13
13
|
"start": "tsx src/index.ts",
|
|
14
|
-
"build": "tsc && rm -rf dist/prompts && cp -r src/prompts dist/prompts",
|
|
14
|
+
"build": "tsc && rm -rf dist/prompts && cp -r src/prompts dist/prompts && cp src/meeting-output.html dist/",
|
|
15
15
|
"room": "tsx src/index.ts --room",
|
|
16
16
|
"prepublishOnly": "npm run build"
|
|
17
17
|
},
|