tassello 0.2.0 → 0.3.0

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 (49) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/README.md +112 -8
  3. package/dist/server/behavior_tree_files.d.ts +0 -1
  4. package/dist/server/behavior_tree_files.js +2 -25
  5. package/dist/server/diagnostics.d.ts +16 -0
  6. package/dist/server/diagnostics.js +200 -0
  7. package/dist/server/diagnostics_state.d.ts +23 -0
  8. package/dist/server/diagnostics_state.js +146 -0
  9. package/dist/server/disks.d.ts +14 -0
  10. package/dist/server/disks.js +152 -0
  11. package/dist/server/file_manager.d.ts +25 -0
  12. package/dist/server/file_manager.js +717 -0
  13. package/dist/server/http.js +248 -5
  14. package/dist/server/netpbm.d.ts +3 -0
  15. package/dist/server/netpbm.js +69 -0
  16. package/dist/server/pty.d.ts +26 -0
  17. package/dist/server/pty.js +150 -0
  18. package/dist/server/server.js +9 -2
  19. package/dist/server/session.d.ts +7 -1
  20. package/dist/server/session.js +67 -1
  21. package/dist/server/terminal_output.d.ts +25 -0
  22. package/dist/server/terminal_output.js +108 -0
  23. package/dist/server/terminals.d.ts +32 -0
  24. package/dist/server/terminals.js +366 -0
  25. package/dist/server/util.d.ts +4 -0
  26. package/dist/server/util.js +45 -1
  27. package/dist/shared/file_manager.d.ts +130 -0
  28. package/dist/shared/file_manager.js +7 -0
  29. package/dist/shared/protocol.d.ts +87 -2
  30. package/dist/shared/protocol.js +8 -0
  31. package/dist/types/client/api.d.ts +22 -0
  32. package/dist/types/client/connection.d.ts +22 -1
  33. package/dist/types/client/icons.d.ts +27 -0
  34. package/dist/types/client/sdk/index.d.ts +4 -3
  35. package/dist/types/shared/file_manager.d.ts +130 -0
  36. package/dist/types/shared/protocol.d.ts +87 -2
  37. package/dist/www/assets/Joystick.js +1 -1
  38. package/dist/www/assets/RobotModelView.js +2 -2
  39. package/dist/www/assets/TerminalView.css +1 -0
  40. package/dist/www/assets/TerminalView.js +17 -0
  41. package/dist/www/assets/dialogs.js +1 -0
  42. package/dist/www/assets/icons.js +1 -1
  43. package/dist/www/assets/index.css +1 -1
  44. package/dist/www/assets/index.js +59 -19
  45. package/dist/www/assets/keys.js +3 -0
  46. package/dist/www/assets/shared/tassello-sdk.js +1 -1
  47. package/dist/www/index.html +2 -0
  48. package/docs/plugins.md +20 -0
  49. package/package.json +6 -2
@@ -192,7 +192,44 @@ export interface RosoutSubscribe {
192
192
  id: number;
193
193
  topic: string;
194
194
  }
195
- export type ClientMessage = TwistCommand | ImageSubscribe | GridSubscribe | TfSubscribe | PathSubscribe | TopicSubscribe | ServicesSubscribe | ServiceAction | LogsSubscribe | Unsubscribe | FrameAck | PosePublish | CommandRun | CommandStop | ArmSubscribe | ArmJog | RosPublish | RosCall | PluginRequest | PluginSubscribe | BehaviorTreeSubscribe | BehaviorTreeRecord | BehaviorTreePlaybackSubscribe | BehaviorTreePlaybackControl | BehaviorTreeFileSubscribe | BehaviorTreeFileSave | RosoutSubscribe;
195
+ export interface DiagnosticsSubscribe {
196
+ type: 'diagnostics.subscribe';
197
+ id: number;
198
+ topic: string;
199
+ }
200
+ export interface TerminalOpen {
201
+ type: 'terminal.open';
202
+ id: number;
203
+ terminal: string;
204
+ command: string;
205
+ folder: string;
206
+ cols: number;
207
+ rows: number;
208
+ started: number | null;
209
+ offset: number | null;
210
+ }
211
+ export interface TerminalInput {
212
+ type: 'terminal.input';
213
+ id: number;
214
+ data: string;
215
+ }
216
+ export interface TerminalResize {
217
+ type: 'terminal.resize';
218
+ id: number;
219
+ cols: number;
220
+ rows: number;
221
+ }
222
+ export interface TerminalAck {
223
+ type: 'terminal.ack';
224
+ id: number;
225
+ started: number;
226
+ offset: number;
227
+ }
228
+ export interface TerminalRestart {
229
+ type: 'terminal.restart';
230
+ id: number;
231
+ }
232
+ export type ClientMessage = TwistCommand | ImageSubscribe | GridSubscribe | TfSubscribe | PathSubscribe | TopicSubscribe | ServicesSubscribe | ServiceAction | LogsSubscribe | Unsubscribe | FrameAck | PosePublish | CommandRun | CommandStop | ArmSubscribe | ArmJog | RosPublish | RosCall | PluginRequest | PluginSubscribe | BehaviorTreeSubscribe | BehaviorTreeRecord | BehaviorTreePlaybackSubscribe | BehaviorTreePlaybackControl | BehaviorTreeFileSubscribe | BehaviorTreeFileSave | RosoutSubscribe | DiagnosticsSubscribe | TerminalOpen | TerminalInput | TerminalResize | TerminalAck | TerminalRestart;
196
233
  export interface Hello {
197
234
  type: 'hello';
198
235
  clientId: string;
@@ -429,7 +466,51 @@ export interface RosoutUpdate {
429
466
  skipped: number;
430
467
  nodes: string[] | null;
431
468
  }
432
- export type ServerMessage = Hello | CommandStates | CommandUpdate | StreamStatus | TfUpdate | PathUpdate | TopicMessage | ServicesUpdate | ServiceResult | LogsUpdate | ArmUpdate | Result | PluginData | BehaviorTreeInfo | BehaviorTreeUpdate | BehaviorTreeRecording | BehaviorTreePlaybackState | BehaviorTreeFile | BehaviorTreeModels | RosoutUpdate | PanelsChanged | ErrorMessage;
469
+ export interface DiagnosticEntry {
470
+ id: number;
471
+ name: string;
472
+ level: number;
473
+ message: string;
474
+ hardwareId: string;
475
+ values: {
476
+ key: string;
477
+ value: string;
478
+ }[];
479
+ stale: boolean;
480
+ updated: number;
481
+ since: number;
482
+ }
483
+ export interface DiagnosticChange {
484
+ seq: number;
485
+ time: number;
486
+ status: number;
487
+ level: number;
488
+ message: string;
489
+ }
490
+ export interface DiagnosticsUpdate {
491
+ type: 'diagnostics';
492
+ id: number;
493
+ reset: boolean;
494
+ started: number;
495
+ statuses: DiagnosticEntry[];
496
+ changes: DiagnosticChange[];
497
+ }
498
+ export interface TerminalOutput {
499
+ type: 'terminal.output';
500
+ id: number;
501
+ started: number;
502
+ offset: number;
503
+ reset: boolean;
504
+ data: string;
505
+ title: string | null;
506
+ }
507
+ export interface TerminalExit {
508
+ type: 'terminal.exit';
509
+ id: number;
510
+ started: number;
511
+ exitCode: number | null;
512
+ }
513
+ export type ServerMessage = Hello | CommandStates | CommandUpdate | StreamStatus | TfUpdate | PathUpdate | TopicMessage | ServicesUpdate | ServiceResult | LogsUpdate | ArmUpdate | Result | PluginData | BehaviorTreeInfo | BehaviorTreeUpdate | BehaviorTreeRecording | BehaviorTreePlaybackState | BehaviorTreeFile | BehaviorTreeModels | RosoutUpdate | DiagnosticsUpdate | TerminalOutput | TerminalExit | PanelsChanged | ErrorMessage;
433
514
  export declare const FRAME_HEADER_BYTES = 11;
434
515
  export declare const IMAGE_FORMATS: readonly ['image/jpeg', 'image/png'];
435
516
  export interface GridInfo {
@@ -452,6 +533,10 @@ export declare const ARM_STATE_RATE = 10;
452
533
  export declare const BT_RATE = 10;
453
534
  export declare const ROSOUT_RATE = 10;
454
535
  export declare const ROSOUT_HISTORY = 10000;
536
+ export declare const DIAGNOSTICS_RATE = 4;
537
+ export declare const DIAGNOSTICS_CHANGES = 1000;
538
+ export declare const TERMINAL_SCROLLBACK = 2000;
539
+ export declare const TERMINAL_WINDOW: number;
455
540
  export declare const DASHBOARD_CLIENT_HEADER = "X-Dashboard-Client";
456
541
  export interface PluginInfo {
457
542
  name: string;
@@ -1 +1 @@
1
- import{n as e}from"./rolldown-runtime.js";import{t}from"./react.js";import{it as n,lt as r,u as i}from"./icons.js";import{t as a}from"./jsx-runtime.js";async function o(e,t,i){let a=await fetch(t,{method:e,headers:{"Content-Type":`application/json`,[r]:n.clientId??``},body:i===void 0?void 0:JSON.stringify(i)});if(!a.ok){let e=`${a.status} ${a.statusText}`;try{e=(await a.json()).error??e}catch{}throw Error(e)}return a.status===204?void 0:await a.json()}var s=e=>`/api/panels/${encodeURIComponent(e)}`;async function c(e){let t=await fetch(`/api/uploads`,{method:`POST`,body:e});if(!t.ok){let e=await t.json().catch(()=>null);throw Error(e?.error??`${t.status} ${t.statusText}`)}return await t.json()}function l(e){let t=e.trim();if(t.startsWith(`uploads/`))return`/api/uploads/${encodeURIComponent(t.slice(8))}`;let n=/^package:\/\/([^/]+)\/(.+)$/.exec(t);return n?`/api/packages/${encodeURIComponent(n[1])}/${n[2].split(`/`).map(encodeURIComponent).join(`/`)}`:t.startsWith(`/`)||t.startsWith(`~/`)?`/api/files?path=${encodeURIComponent(t)}`:null}var u={listPanels:()=>o(`GET`,`/api/panels`),getPanel:e=>o(`GET`,s(e)),createPanel:e=>o(`POST`,`/api/panels`,e),savePanel:e=>o(`PUT`,s(e.id),e),deletePanel:e=>o(`DELETE`,s(e)),listTopics:()=>o(`GET`,`/api/topics`),listPlugins:()=>o(`GET`,`/api/plugins`),listFiles:(e,t=`image`)=>o(`GET`,`/api/files/list?dir=${encodeURIComponent(e)}&kind=${t}`),uploadFile:async e=>`uploads/${(await c(e)).name}`},d=e(t(),1),f=e(a(),1);function p({title:e,onClose:t,children:n,wide:r=!1,resizable:a=!1}){return(0,d.useEffect)(()=>{let e=e=>{e.key===`Escape`&&t()};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[t]),(0,f.jsx)(`div`,{className:`modal-backdrop`,onPointerDown:e=>e.target===e.currentTarget&&t(),children:(0,f.jsxs)(`div`,{className:`modal${r?` wide`:``}${a?` resizable`:``}`,role:`dialog`,"aria-modal":`true`,"aria-label":e,children:[(0,f.jsxs)(`header`,{className:`modal-header`,children:[(0,f.jsx)(`h2`,{children:e}),(0,f.jsx)(`button`,{type:`button`,className:`icon-button`,"aria-label":`Close`,onClick:t,children:(0,f.jsx)(i,{})})]}),n]})})}var m=1,h=(0,d.createContext)(null);function g(){let e=(0,d.useContext)(h);if(!e)throw Error(`useDialogs() outside of <DialogProvider>`);return e}function _({children:e}){let[t,n]=(0,d.useState)(null),r=(0,d.useMemo)(()=>({confirm:e=>new Promise(t=>n({id:m++,kind:`confirm`,resolve:t,...e})),prompt:e=>new Promise(t=>n({id:m++,kind:`prompt`,resolve:t,...e}))}),[]);return(0,f.jsxs)(h.Provider,{value:r,children:[e,t&&(0,f.jsx)(v,{request:t,onDone:()=>n(null)},t.id)]})}function v({request:e,onDone:t}){let[n,r]=(0,d.useState)(e.kind===`prompt`?e.initial??``:``),i=(0,d.useRef)(null);(0,d.useEffect)(()=>i.current?.select(),[]);let a=r=>{e.kind===`confirm`?e.resolve(r):e.resolve(r&&n.trim()?n.trim():null),t()};return(0,f.jsx)(p,{title:e.title,onClose:()=>a(!1),children:(0,f.jsxs)(`form`,{className:`modal-body`,onSubmit:e=>{e.preventDefault(),a(!0)},children:[e.kind===`confirm`?e.message&&(0,f.jsx)(`div`,{className:`dialog-message`,children:e.message}):(0,f.jsxs)(`label`,{className:`field`,children:[(0,f.jsx)(`span`,{className:`field-label`,children:e.label}),(0,f.jsx)(`input`,{ref:i,value:n,onChange:e=>r(e.target.value),autoFocus:!0})]}),(0,f.jsxs)(`div`,{className:`modal-actions`,children:[(0,f.jsx)(`button`,{type:`button`,className:`button`,onClick:()=>a(!1),children:`Cancel`}),(0,f.jsx)(`button`,{type:`submit`,className:`button ${e.kind===`confirm`&&e.danger?`danger`:`primary`}`,disabled:e.kind===`prompt`&&!n.trim(),autoFocus:e.kind===`confirm`,children:e.confirmLabel??`OK`})]})]})})}var y=5e3,b=[],x=1,S=new Set;function C(e){b=e,S.forEach(e=>e())}function w(e){C(b.filter(t=>t.id!==e))}function T(e,t=`info`,n){let r=x++;C([...b.filter(t=>t.message!==e),{id:r,message:e,kind:t,action:n}].slice(-4)),setTimeout(()=>w(r),y)}function E(e){return S.add(e),()=>S.delete(e)}function D(){let e=(0,d.useSyncExternalStore)(E,()=>b);return(0,f.jsx)(`div`,{className:`notifications`,role:`status`,"aria-live":`polite`,children:e.map(e=>(0,f.jsxs)(`div`,{className:`notification ${e.kind}`,children:[(0,f.jsx)(`span`,{children:e.message}),e.action&&(0,f.jsx)(`button`,{type:`button`,className:`link-button`,onClick:()=>{e.action?.run(),w(e.id)},children:e.action.label}),(0,f.jsx)(`button`,{type:`button`,className:`notification-close`,"aria-label":`Dismiss`,onClick:()=>w(e.id),children:`×`})]},e.id))})}function O(e){return e}function k(e){return e}var A=34,j=.08;function M(e){let t=Math.abs(e);return t<j?0:Math.sign(e)*(t-j)/.92}function N({axes:e,onMove:t,disabled:n,label:r}){let i=(0,d.useRef)(null),a=(0,d.useRef)(null),[o,s]=(0,d.useState)({x:0,y:0}),[c,l]=(0,d.useState)(!1),u=(0,d.useRef)(t);u.current=t;let p=(e,t)=>{s({x:e,y:t}),u.current(M(e),M(t))},m=t=>{let n=i.current.getBoundingClientRect(),r=n.width*A/100,a=e===`y`?0:(t.clientX-(n.left+n.width/2))/r,o=e===`x`?0:-(t.clientY-(n.top+n.height/2))/r,s=Math.hypot(a,o);s>1&&(a/=s,o/=s),p(a,o)},h=e=>{a.current===null||e&&e.pointerId!==a.current||(a.current=null,l(!1),p(0,0))},g=(0,d.useRef)(h);return g.current=h,(0,d.useEffect)(()=>{let e=()=>document.hidden&&g.current();return document.addEventListener(`visibilitychange`,e),()=>document.removeEventListener(`visibilitychange`,e)},[]),(0,d.useEffect)(()=>{n&&g.current()},[n]),(0,f.jsxs)(`div`,{className:`joystick-slot`,children:[(0,f.jsxs)(`div`,{ref:i,className:`joystick${e===`x`?` horizontal`:e===`y`?` vertical`:``}${c?` active`:``}${n?` disabled`:``}`,onPointerDown:e=>{n||a.current!==null||e.button!==0||(a.current=e.pointerId,l(!0),e.currentTarget.setPointerCapture(e.pointerId),m(e))},onPointerMove:e=>e.pointerId===a.current&&m(e),onPointerUp:h,onPointerCancel:h,onLostPointerCapture:h,children:[(0,f.jsx)(`div`,{className:`joystick-track`}),(0,f.jsx)(`div`,{className:`joystick-knob`,style:{left:`${50+o.x*A}%`,top:`${50-o.y*A}%`}})]}),(0,f.jsx)(`span`,{className:`joystick-label`,children:r})]})}export{T as a,g as c,D as i,u as l,k as n,_ as o,O as r,p as s,N as t,l as u};
1
+ import{n as e}from"./rolldown-runtime.js";import{t}from"./react.js";import{It as n,jt as r}from"./icons.js";import{t as i}from"./jsx-runtime.js";var a=class extends Error{status;constructor(e,t){super(t),this.status=e}};async function o(e,t,i){let o=await fetch(t,{method:e,headers:{"Content-Type":`application/json`,[n]:r.clientId??``},body:i===void 0?void 0:JSON.stringify(i)});if(!o.ok){let e=`${o.status} ${o.statusText}`;try{e=(await o.json()).error??e}catch{}throw new a(o.status,e)}return o.status===204?void 0:await o.json()}var s=e=>`/api/panels/${encodeURIComponent(e)}`;async function c(e){let t=await fetch(`/api/uploads`,{method:`POST`,body:e});if(!t.ok){let e=await t.json().catch(()=>null);throw Error(e?.error??`${t.status} ${t.statusText}`)}return await t.json()}function l(e){let t=e.trim();if(t.startsWith(`uploads/`))return`/api/uploads/${encodeURIComponent(t.slice(8))}`;let n=/^package:\/\/([^/]+)\/(.+)$/.exec(t);return n?`/api/packages/${encodeURIComponent(n[1])}/${n[2].split(`/`).map(encodeURIComponent).join(`/`)}`:t.startsWith(`/`)||t.startsWith(`~/`)?`/api/files?path=${encodeURIComponent(t)}`:null}var u={listPanels:()=>o(`GET`,`/api/panels`),getPanel:e=>o(`GET`,s(e)),createPanel:e=>o(`POST`,`/api/panels`,e),savePanel:e=>o(`PUT`,s(e.id),e),deletePanel:e=>o(`DELETE`,s(e)),listTopics:()=>o(`GET`,`/api/topics`),listPlugins:()=>o(`GET`,`/api/plugins`),listFiles:(e,t=`image`)=>o(`GET`,`/api/files/list?dir=${encodeURIComponent(e)}&kind=${t}`),uploadFile:async e=>`uploads/${(await c(e)).name}`};function d(e,t={}){let n=new URLSearchParams;for(let[e,r]of Object.entries(t))for(let t of r==null?[]:[r].flat())n.append(e,t);let r=n.toString();return`/api/fs/${e}${r?`?${r}`:``}`}var f={places:()=>o(`GET`,d(`places`)),list:(e,t)=>o(`GET`,d(`list`,{path:e,known:t})),details:e=>o(`GET`,d(`details`,{path:e})),disks:()=>o(`GET`,d(`disks`)),analyze:e=>o(`GET`,d(`analysis`,{path:e})),readText:(e,t)=>o(`GET`,d(`text`,{path:e,stamp:t})),saveText:(e,t,n,r=!1)=>o(`PUT`,d(`text`),{path:e,text:t,base:n,create:r}),operate:e=>o(`POST`,d(`op`),e),downloadUrl:e=>d(`download`,{path:e}),viewUrl:(e,t)=>d(`view`,{path:e,v:t}),upload(e,t,i,a,o){let s=new XMLHttpRequest;return{result:new Promise((c,l)=>{s.open(`POST`,d(`upload`,{path:e,name:t,conflict:a})),s.setRequestHeader(n,r.clientId??``),s.upload.onprogress=e=>o(e.loaded),s.onload=()=>{let e=null;try{e=JSON.parse(s.responseText)}catch{}s.status>=200&&s.status<300&&e?c(e):l(Error(e?.error??`${s.status} ${s.statusText}`))},s.onerror=()=>l(Error(`Cannot reach the robot`)),s.onabort=()=>l(new DOMException(`Cancelled`,`AbortError`)),s.send(i)}),abort:()=>s.abort()}}},p=e(t(),1),m=e(i(),1),h=5e3,g=[],_=1,v=new Set;function y(e){g=e,v.forEach(e=>e())}function b(e){y(g.filter(t=>t.id!==e))}function x(e,t=`info`,n){let r=_++;y([...g.filter(t=>t.message!==e),{id:r,message:e,kind:t,action:n}].slice(-4)),setTimeout(()=>b(r),h)}function S(e){return v.add(e),()=>v.delete(e)}function C(){let e=(0,p.useSyncExternalStore)(S,()=>g);return(0,m.jsx)(`div`,{className:`notifications`,role:`status`,"aria-live":`polite`,children:e.map(e=>(0,m.jsxs)(`div`,{className:`notification ${e.kind}`,children:[(0,m.jsx)(`span`,{children:e.message}),e.action&&(0,m.jsx)(`button`,{type:`button`,className:`link-button`,onClick:()=>{e.action?.run(),b(e.id)},children:e.action.label}),(0,m.jsx)(`button`,{type:`button`,className:`notification-close`,"aria-label":`Dismiss`,onClick:()=>b(e.id),children:`×`})]},e.id))})}function w(e){return e}function T(e){return e}var E=34,D=.08;function O(e){let t=Math.abs(e);return t<D?0:Math.sign(e)*(t-D)/.92}function k({axes:e,onMove:t,disabled:n,label:r}){let i=(0,p.useRef)(null),a=(0,p.useRef)(null),[o,s]=(0,p.useState)({x:0,y:0}),[c,l]=(0,p.useState)(!1),u=(0,p.useRef)(t);u.current=t;let d=(e,t)=>{s({x:e,y:t}),u.current(O(e),O(t))},f=t=>{let n=i.current.getBoundingClientRect(),r=n.width*E/100,a=e===`y`?0:(t.clientX-(n.left+n.width/2))/r,o=e===`x`?0:-(t.clientY-(n.top+n.height/2))/r,s=Math.hypot(a,o);s>1&&(a/=s,o/=s),d(a,o)},h=e=>{a.current===null||e&&e.pointerId!==a.current||(a.current=null,l(!1),d(0,0))},g=(0,p.useRef)(h);return g.current=h,(0,p.useEffect)(()=>{let e=()=>document.hidden&&g.current();return document.addEventListener(`visibilitychange`,e),()=>document.removeEventListener(`visibilitychange`,e)},[]),(0,p.useEffect)(()=>{n&&g.current()},[n]),(0,m.jsxs)(`div`,{className:`joystick-slot`,children:[(0,m.jsxs)(`div`,{ref:i,className:`joystick${e===`x`?` horizontal`:e===`y`?` vertical`:``}${c?` active`:``}${n?` disabled`:``}`,onPointerDown:e=>{n||a.current!==null||e.button!==0||(a.current=e.pointerId,l(!0),e.currentTarget.setPointerCapture(e.pointerId),f(e))},onPointerMove:e=>e.pointerId===a.current&&f(e),onPointerUp:h,onPointerCancel:h,onLostPointerCapture:h,children:[(0,m.jsx)(`div`,{className:`joystick-track`}),(0,m.jsx)(`div`,{className:`joystick-knob`,style:{left:`${50+o.x*E}%`,top:`${50-o.y*E}%`}})]}),(0,m.jsx)(`span`,{className:`joystick-label`,children:r})]})}export{x as a,f as c,C as i,l,T as n,a as o,w as r,u as s,k as t};