osborn 0.8.29 → 0.8.30

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.
@@ -0,0 +1,41 @@
1
+ # Learned Behaviors
2
+
3
+ Auto-extracted from voice sessions via PreCompact.
4
+ Last updated: 2026-05-01 | Session: unknown...
5
+
6
+ USER CORRECTIONS:
7
+ - First write attempt for interruption timer was DENIED because it replaced existing LiveKit code instead of adding on top — always ADD fallbacks, never replace existing mechanisms; user said "you're basically deleting what we have"
8
+ - User denied permission dialog for file edit because they wanted to verify the approach first before committing — ask "should I build this?" before delegating write tasks on significant changes
9
+ - When proposing solution approach, verify against LiveKit SDK source AND docs before implementing — user asked "can you verify that we're doing it the right way in terms of live kits"
10
+
11
+ USER PREFERENCES:
12
+ - Voice transcription: "MPM"=npm, "mobile publish"=npm publish, "live gate"=LiveKit, "left kit"=LiveKit, "basketball man"=bash command, "Osborne"=osborn — interpret flexibly
13
+ - Sprite is the publish path for npm going forward (not Mac), set up with automation token
14
+ - Prefers additive code changes: keep existing mechanisms as primary, add new approaches as fallback tiers
15
+ - Wants to understand the "why" before approving implementation — explain the mechanism, not just the solution
16
+ - Wants confirmation before committing to solutions when uncertain: "before we commit to doing this"
17
+
18
+ DOMAIN KNOWLEDGE:
19
+ - `osborn --version` has no version flag — it starts a new LiveKit-connected instance; use `npm list -g osborn` or `npm list -g osborn --json` for version
20
+ - npm automation token (not web login token) required for headless publish — web login token still requires 2FA for publish
21
+ - `playbackPosition` is 0 because interrupt often fires before TTS audio frames start flowing (`pushedDuration = 0`); also race condition between `addDoneCallback` and `waitForPlayoutTask`
22
+ - `skipTTSQueue: true` does NOT bypass audio frame tracking — `ttsTask` code path is identical
23
+ - `EVENT_PLAYBACK_STARTED` ('playbackStarted') is public, fires on first audio frame, accessible via `audioOutput.on()`
24
+ - OpenAI TTS-1 rate: ~14 chars/second confirmed from community benchmarks
25
+ - `check-version` in sandbox/route.ts was incorrectly using `osborn --version` (starts instance); fixed to `npm list -g osborn --json`
26
+ - execInSprite works any time the Sprite container is running, independent of osborn agent health
27
+ - `checkVersion()` already existed in dashboard/page.tsx (lines 325-338); `installedVersion` and `latestVersion` state already existed
28
+ - Dashboard handleRestart/handleUpdate were not reading API response bodies — server returns rich data but client discarded it
29
+ - Railway auto-deploys from GitHub main branch push
30
+
31
+ EFFECTIVE PATTERNS:
32
+ - Layered fallback approach: preserve existing SDK mechanisms, add custom approach only as fallback — explicit user preference confirmed
33
+ - Taking checkpoint before significant changes gives confidence to experiment
34
+ - Reading API response bodies and surfacing errors/success messages is a simple fix for "silent" operations
35
+
36
+ ANTI-PATTERNS:
37
+ - Running `osborn --version` on the Sprite created stray processes connected to LiveKit room — never run the osborn binary to check version
38
+ - Replacing existing LiveKit code with custom implementation instead of adding on top — user explicitly denied and corrected this
39
+ - Delegating write task without confirming approach with user first on novel/uncertain changes
40
+ - Not reading the API response body after `await fetch()` — silent failure mode
41
+ </summary>
package/dist/index.js CHANGED
@@ -1112,7 +1112,7 @@ async function main() {
1112
1112
  // Wall-clock timer: capture when audio actually starts playing (first frame)
1113
1113
  // Used as fallback if LiveKit's playbackPosition is 0 (race condition)
1114
1114
  let playbackStartedAt = null;
1115
- const audioOutputRef = currentSession?._activity?.agentSession?.output?.audio;
1115
+ const audioOutputRef = currentSession?.output?.audio;
1116
1116
  if (audioOutputRef && typeof audioOutputRef.on === 'function') {
1117
1117
  const onPlaybackStarted = () => {
1118
1118
  playbackStartedAt = Date.now();
@@ -1124,7 +1124,7 @@ async function main() {
1124
1124
  handle.addDoneCallback((sh) => {
1125
1125
  if (sh.interrupted) {
1126
1126
  console.log(`🔇 [${sayId}] session.say INTERRUPTED`);
1127
- const audioOutput = currentSession?._activity?.agentSession?.output?.audio;
1127
+ const audioOutput = currentSession?.output?.audio;
1128
1128
  const sdkTranscript = audioOutput?.lastPlaybackEvent?.synchronizedTranscript;
1129
1129
  const sdkPlaybackSec = audioOutput?.lastPlaybackEvent?.playbackPosition ?? 0;
1130
1130
  let spokenText;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "osborn",
3
- "version": "0.8.29",
3
+ "version": "0.8.30",
4
4
  "description": "Voice AI coding assistant - local agent that connects to Osborn frontend",
5
5
  "type": "module",
6
6
  "bin": {