osborn 0.8.17 → 0.8.18

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.
Files changed (2) hide show
  1. package/dist/index.js +28 -0
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -491,6 +491,11 @@ async function main() {
491
491
  let userState = 'listening'; // Track user speech state for queue safety
492
492
  let currentVoiceMode = voiceMode; // Track active voice mode for data handlers
493
493
  let currentProvider = realtimeConfig.provider; // Track active realtime provider
494
+ // Authenticated Supabase userId from participant metadata. Used to scope
495
+ // workspace artifact uploads to the owner's prefix in Supabase Storage.
496
+ // Empty string = anonymous / unauthenticated; uploads fall back to a
497
+ // session-only path (no user prefix).
498
+ let currentUserId = '';
494
499
  // Track the active resume session ID across scopes (ParticipantConnected + DataReceived)
495
500
  // Updated by resume_session, session_selected, continue_session, switch_session handlers
496
501
  let currentResumeSessionId;
@@ -1776,6 +1781,15 @@ async function main() {
1776
1781
  try {
1777
1782
  const metadata = JSON.parse(participant.metadata || '{}');
1778
1783
  console.log(`📋 Participant metadata:`, metadata);
1784
+ // userId from authenticated Supabase session — used to scope Supabase
1785
+ // Storage uploads so each user's workspace artifacts live under their
1786
+ // own prefix. Falls through to '' (anonymous) if not authenticated.
1787
+ if (typeof metadata.userId === 'string' && metadata.userId.length > 0) {
1788
+ currentUserId = metadata.userId;
1789
+ }
1790
+ else {
1791
+ currentUserId = '';
1792
+ }
1779
1793
  if (metadata.voiceArch === 'realtime' || metadata.voiceArch === 'direct' || metadata.voiceArch === 'pipeline') {
1780
1794
  sessionVoiceMode = metadata.voiceArch;
1781
1795
  console.log(`🎙️ Using voice mode from frontend: ${sessionVoiceMode}`);
@@ -2733,6 +2747,20 @@ async function main() {
2733
2747
  const form = new FormData();
2734
2748
  form.append('file', new Blob([buf], { type: mimeType }), fileName);
2735
2749
  form.append('folder', 'artifacts');
2750
+ // Pass userId + sessionId so /api/upload can place the file
2751
+ // under `{userId}/{sessionId}/...` in Supabase Storage for
2752
+ // easy ownership queries and future RLS policies. Both are
2753
+ // optional — route falls back to `artifacts/...` if missing.
2754
+ if (currentUserId)
2755
+ form.append('userId', currentUserId);
2756
+ // Prefer the live resume session id (updated by session
2757
+ // switches), fall back to whatever SDK session id the LLM
2758
+ // reports, fall back to empty.
2759
+ const uploadSessionId = currentResumeSessionId
2760
+ || currentLLM?.sessionId
2761
+ || '';
2762
+ if (uploadSessionId)
2763
+ form.append('sessionId', uploadSessionId);
2736
2764
  const r = await fetch(`${FRONTEND_URL.replace(/\/$/, '')}/api/upload`, {
2737
2765
  method: 'POST', body: form,
2738
2766
  signal: AbortSignal.timeout(15_000),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "osborn",
3
- "version": "0.8.17",
3
+ "version": "0.8.18",
4
4
  "description": "Voice AI coding assistant - local agent that connects to Osborn frontend",
5
5
  "type": "module",
6
6
  "bin": {