infinicode 2.8.71 → 2.8.73

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.
@@ -24,9 +24,10 @@
24
24
  export const DASHBOARD_HTML = `<!doctype html>
25
25
  <html lang="en">
26
26
  <head>
27
- <meta charset="utf-8">
28
- <meta name="viewport" content="width=device-width, initial-scale=1">
29
- <title>RoboPark Control</title>
27
+ <meta charset="utf-8">
28
+ <meta name="viewport" content="width=device-width, initial-scale=1">
29
+ <meta name="robopark-ui-build" content="voice-media-20260716-3">
30
+ <title>RoboPark Control</title>
30
31
  <style>
31
32
  /* ── premium tech glass theme ── dark is the committed default; light is a frosted toggle ── */
32
33
  :root{
@@ -896,7 +897,7 @@ button.act:disabled{opacity:0.5;cursor:default;}
896
897
  <div class="rp-call-device"><label>Camera</label><select id="rp-call-cam-device"><option value="">system default</option></select></div>
897
898
  <div class="rp-call-device"><label>Speaker output</label><select id="rp-call-speaker-device"><option value="">system default</option></select></div>
898
899
  <div class="rp-call-device-note" id="rp-call-device-note">Enable media access to reveal the actual microphone, camera, and speaker names available to this browser.</div>
899
- <div class="rp-call-device-actions"><button class="rp-btn primary" id="rp-call-refresh-devices">Enable &amp; scan</button><button class="rp-btn" id="rp-call-test-mic">Test microphone</button></div>
900
+ <div class="rp-call-device-actions"><button class="rp-btn primary" id="rp-call-refresh-devices">Enable media access</button><button class="rp-btn" id="rp-call-test-mic">Test microphone</button></div>
900
901
  </div>
901
902
  </aside>
902
903
  <main class="rp-call-stage">
@@ -1178,8 +1179,14 @@ button.act:disabled{opacity:0.5;cursor:default;}
1178
1179
 
1179
1180
  <script>
1180
1181
  (function(){
1181
- var TOKEN = new URLSearchParams(location.search).get('token') || '';
1182
- var QS = TOKEN ? ('?token=' + encodeURIComponent(TOKEN)) : '';
1182
+ var TOKEN = new URLSearchParams(location.search).get('token') || '';
1183
+ var QS = TOKEN ? ('?token=' + encodeURIComponent(TOKEN)) : '';
1184
+ var UI_BUILD=(document.querySelector('meta[name="robopark-ui-build"]')||{}).content||'unknown';
1185
+ fetch('/fed/ui-build'+QS,{cache:'no-store'}).then(function(r){return r.ok?r.json():null;}).then(function(info){
1186
+ if(!info||!info.build||info.build===UI_BUILD)return;
1187
+ var key='rp-ui-reload-'+info.build;if(sessionStorage.getItem(key))return;sessionStorage.setItem(key,'1');
1188
+ var url=new URL(location.href);url.searchParams.set('ui',info.build);location.replace(url.toString());
1189
+ }).catch(function(){});
1183
1190
  var selfId = null, selected = null, lastSeq = -1, everOk = false;
1184
1191
  var rpReadOnly = false, pmBusy = false;
1185
1192
  var lastSchedulerPollAt = 0; // updated by pollRobopark() on every successful /api/telemetry fetch
@@ -3031,10 +3038,22 @@ button.act:disabled{opacity:0.5;cursor:default;}
3031
3038
  if(LK.RoomEvent.ParticipantAttributesChanged)room.on(LK.RoomEvent.ParticipantAttributesChanged,function(changed,p){updateAgentFromParticipant(p);});
3032
3039
  room.on(LK.RoomEvent.ParticipantConnected,function(p){updateAgentFromParticipant(p);setVoiceEvent('Agent connected',p.name||p.identity||'ROBOVOICE worker');});
3033
3040
  room.on(LK.RoomEvent.Disconnected,function(){ if(!rpVoiceCall.ending) finishVoiceCall('connection_lost'); });
3034
- return room.connect(call.server_url,call.token).then(function(){var mic=$('rp-call-mic-device').value,opts=mic?{deviceId:mic}:undefined;setVoiceEvent('LiveKit connected','publishing '+(mic?'selected microphone':'system default microphone'));return room.localParticipant.setMicrophoneEnabled(true,opts);});
3035
- }).then(function(){
3036
- setVoiceCallStatus('secure channel connected','live');setVoiceAgentState('Listening','speak naturally');setVoiceEvent('Connected','waiting for ROBOVOICE agent');rpVoiceCall.startedAt=Date.now();rpVoiceCall.timer=setInterval(updateVoiceTimer,1000);updateVoiceTimer();
3041
+ return room.connect(call.server_url,call.token).then(function(){
3042
+ var mic=$('rp-call-mic-device').value,opts=mic?{deviceId:mic}:undefined;
3043
+ setVoiceEvent('LiveKit connected','publishing '+(mic?'selected microphone':'system default microphone'));
3044
+ return room.localParticipant.setMicrophoneEnabled(true,opts).then(function(){return true;}).catch(function(e){
3045
+ var message=e&&e.message||'Browser microphone could not be published';
3046
+ rpVoiceCall.muted=true;
3047
+ voiceDeviceMessage('Voice channel is connected, but the microphone is blocked: '+message+'. Allow access, then press RETRY MIC.','bad');
3048
+ setVoiceEvent('Microphone blocked',message);
3049
+ if(window.console)console.error('RoboPark microphone publish failed',e);
3050
+ return false;
3051
+ });
3052
+ });
3053
+ }).then(function(micActive){
3054
+ setVoiceCallStatus(micActive?'secure channel connected':'channel connected - microphone blocked',micActive?'live':'busy');setVoiceAgentState(micActive?'Listening':'Microphone required',micActive?'speak naturally':'allow browser microphone access, then retry');if(micActive)setVoiceEvent('Connected','waiting for ROBOVOICE agent');rpVoiceCall.startedAt=Date.now();rpVoiceCall.timer=setInterval(updateVoiceTimer,1000);updateVoiceTimer();
3037
3055
  $('rp-call-mute').disabled=false;$('rp-call-camera').disabled=false;$('rp-call-screen').disabled=false;$('rp-call-end').disabled=false;$('rp-call-message').disabled=false;$('rp-call-send').disabled=false;
3056
+ $('rp-call-mute').textContent=micActive?'MIC':'RETRY MIC';$('rp-call-mute').classList.toggle('on',!!micActive);
3038
3057
  return fetch('/robopark/api/sessions/'+encodeURIComponent(rpVoiceCall.session)+'/joined'+QS,{method:'POST',headers:{'X-RoboPark-Session-Token':rpVoiceCall.eventToken}}).catch(function(){});
3039
3058
  });
3040
3059
  }).catch(function(e){
@@ -3047,9 +3066,8 @@ button.act:disabled{opacity:0.5;cursor:default;}
3047
3066
  });
3048
3067
  }
3049
3068
  function toggleVoiceMute(){
3050
- if(!rpVoiceCall.room)return; rpVoiceCall.muted=!rpVoiceCall.muted;
3051
- rpVoiceCall.room.localParticipant.setMicrophoneEnabled(!rpVoiceCall.muted);
3052
- $('rp-call-mute').textContent=rpVoiceCall.muted?'MIC OFF':'MIC';$('rp-call-mute').classList.toggle('on',!rpVoiceCall.muted);setVoiceCallStatus(rpVoiceCall.muted?'microphone muted':'secure channel connected','live');
3069
+ if(!rpVoiceCall.room)return;var enable=rpVoiceCall.muted,mic=$('rp-call-mic-device').value,opts=enable&&mic?{deviceId:mic}:undefined,btn=$('rp-call-mute');btn.disabled=true;
3070
+ rpVoiceCall.room.localParticipant.setMicrophoneEnabled(enable,opts).then(function(){rpVoiceCall.muted=!enable;btn.textContent=enable?'MIC':'MIC OFF';btn.classList.toggle('on',enable);setVoiceCallStatus(enable?'secure channel connected':'microphone muted','live');setVoiceAgentState(enable?'Listening':'Microphone muted',enable?'speak naturally':'the call remains connected');voiceDeviceMessage(enable?'Microphone published to the active call.':'Microphone muted; the voice channel remains connected.',enable?'ok':'warn');}).catch(function(e){rpVoiceCall.muted=true;btn.textContent='RETRY MIC';btn.classList.remove('on');setVoiceCallStatus('channel connected - microphone blocked','busy');voiceDeviceMessage('Microphone retry failed: '+(e&&e.message||String(e)),'bad');setVoiceEvent('Microphone blocked',e&&e.message||String(e));}).finally(function(){btn.disabled=false;});
3053
3071
  }
3054
3072
  function finishVoiceCall(reason){
3055
3073
  if(rpVoiceCall.ending)return; rpVoiceCall.ending=true; var session=rpVoiceCall.session, room=rpVoiceCall.room;
@@ -350,6 +350,17 @@ export class MeshServer {
350
350
  return;
351
351
  }
352
352
  const remote = req.socket.remoteAddress ?? 'unknown';
353
+ if (req.method === 'GET' && path === '/fed/ui-build') {
354
+ const marker = this.opts.dashboardHtml?.match(/<meta name="robopark-ui-build" content="([^"]+)">/)?.[1] ?? 'none';
355
+ res.writeHead(200, {
356
+ 'content-type': 'application/json; charset=utf-8',
357
+ 'cache-control': 'no-store, no-cache, must-revalidate, max-age=0',
358
+ pragma: 'no-cache',
359
+ expires: '0',
360
+ });
361
+ res.end(JSON.stringify({ build: marker }));
362
+ return;
363
+ }
353
364
  // The mesh node serves the full Park-enabled RoboPark Control Center. Its
354
365
  // product APIs remain proxied under /robopark/* to the scheduler.
355
366
  if (req.method === 'GET' && (path === '/' || path === '/ui' || path === '/dashboard')) {
@@ -359,7 +370,9 @@ export class MeshServer {
359
370
  }
360
371
  res.writeHead(200, {
361
372
  'content-type': 'text/html; charset=utf-8',
362
- 'cache-control': 'no-store',
373
+ 'cache-control': 'no-store, no-cache, must-revalidate, max-age=0',
374
+ pragma: 'no-cache',
375
+ expires: '0',
363
376
  ...(this.opts.token && this.presentedToken(req)
364
377
  ? { 'set-cookie': `robopark_auth=${encodeURIComponent(this.presentedToken(req))}; Path=/; SameSite=Lax` }
365
378
  : {}),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "infinicode",
3
- "version": "2.8.71",
3
+ "version": "2.8.73",
4
4
  "description": "OpenKernel — provider-agnostic AI execution kernel. Native coding agent + mission-driven execution runtime.",
5
5
  "type": "module",
6
6
  "main": "./dist/kernel/index.js",