@huynle/hub 0.9.2 → 0.10.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.
- package/CHANGELOG.md +296 -0
- package/Dockerfile +5 -1
- package/README.md +152 -77
- package/package.json +7 -4
- package/packages/claude-code/package.json +1 -1
- package/packages/cli/dist/hub-cli.js +532 -261
- package/packages/cli/package.json +1 -1
- package/packages/cli/src/cli.ts +36 -1
- package/packages/cli/src/subscriptions.ts +49 -0
- package/packages/codex/package.json +1 -1
- package/packages/codex/src/sessions.ts +10 -6
- package/packages/codex/src/spoke.ts +2 -1
- package/packages/node/package.json +1 -1
- package/packages/preset/package.json +1 -1
- package/packages/protocol/package.json +1 -1
- package/packages/protocol/schema/app-delivery/v1.schema.json +7 -5
- package/packages/protocol/schema/app-front/v1.schema.json +410 -0
- package/packages/protocol/src/app-front.ts +293 -0
- package/packages/protocol/src/concierge.ts +10 -1
- package/packages/protocol/src/context-cards.ts +59 -0
- package/packages/protocol/src/credentials.ts +39 -2
- package/packages/protocol/src/index.ts +69 -11
- package/packages/runtime-openshell/package.json +1 -1
- package/packages/runtime-sdk/package.json +1 -1
- package/packages/sdk/package.json +1 -1
- package/packages/sdk/src/app-front.ts +524 -0
- package/packages/sdk/src/client.ts +37 -4
- package/packages/sdk/src/envelope.ts +9 -2
- package/packages/sdk/src/errors.ts +1 -0
- package/packages/sdk/src/index.ts +1 -0
- package/packages/sdk/src/types.ts +39 -1
- package/packages/spoke-sdk/package.json +1 -1
- package/packages/spoke-sdk/src/delivery.ts +17 -1
- package/packages/spoke-sdk/src/harness-spoke.ts +4 -3
- package/packages/voice-client/README.md +146 -0
- package/packages/voice-client/src/vad/LICENSE +21 -0
- package/src/central/agent/acting-routes.ts +17 -3
- package/src/central/agent/acting.ts +12 -3
- package/src/central/agent/actor.ts +6 -1
- package/src/central/agent/app-decisions.ts +146 -0
- package/src/central/agent/app-tokens.ts +9 -3
- package/src/central/agent/audit.ts +3 -0
- package/src/central/agent/connect-routes.ts +64 -0
- package/src/central/agent/connect.ts +868 -0
- package/src/central/agent/conversation.ts +625 -0
- package/src/central/agent/decisions.ts +71 -6
- package/src/central/agent/delivery.ts +3 -0
- package/src/central/agent/directory.ts +5 -0
- package/src/central/agent/errors.ts +2 -0
- package/src/central/agent/grant-requests.ts +46 -9
- package/src/central/agent/grants.ts +13 -2
- package/src/central/agent/message-limits.ts +2 -2
- package/src/central/agent/message-routes.ts +13 -4
- package/src/central/agent/read-routes.ts +16 -2
- package/src/central/agent/routes.ts +108 -6
- package/src/central/agent/speech-routes.ts +316 -0
- package/src/central/agent/subscription-routes.ts +174 -0
- package/src/central/agent/subscriptions.ts +980 -0
- package/src/central/agent-data.ts +43 -1
- package/src/central/backend/memory-counters.ts +2 -2
- package/src/central/backend/types.ts +5 -2
- package/src/central/backend/valkey-counters.ts +5 -4
- package/src/central/client-address.ts +16 -0
- package/src/central/concierge/board-render.ts +52 -1
- package/src/central/concierge/board-routes.ts +25 -2
- package/src/central/concierge/board.ts +11 -1
- package/src/central/concierge/context.ts +29 -8
- package/src/central/concierge/grant-request.ts +216 -0
- package/src/central/concierge/prompt.ts +49 -2
- package/src/central/concierge/session-routes.ts +3 -0
- package/src/central/config.ts +64 -3
- package/src/central/context-cards/budget.ts +121 -0
- package/src/central/context-cards/changes.ts +29 -0
- package/src/central/context-cards/config.ts +145 -0
- package/src/central/context-cards/engine.ts +379 -0
- package/src/central/context-cards/inputs.ts +111 -0
- package/src/central/context-cards/pickup.ts +134 -0
- package/src/central/context-cards/registry.ts +89 -0
- package/src/central/context-cards/routes.ts +37 -0
- package/src/central/context-cards/service.ts +367 -0
- package/src/central/context-cards/store.ts +67 -0
- package/src/central/context-cards/types.ts +88 -0
- package/src/central/fetcher.ts +10 -2
- package/src/central/front-relays.ts +423 -0
- package/src/central/http.ts +516 -56
- package/src/central/human-activity.ts +453 -0
- package/src/central/llm/chat.ts +133 -0
- package/src/central/registry.ts +162 -9
- package/src/central/speech/service.ts +9 -0
- package/src/central/spoke-ws.ts +13 -0
- package/src/central/store.ts +9 -12
- package/src/config.ts +30 -13
- package/src/index.ts +45 -43
- package/src/rpc.ts +33 -4
- package/src/spoke/concierge-agent.ts +1 -1
- package/src/spoke/conversation.ts +6 -75
- package/src/spoke/deliver.ts +18 -8
- package/src/spoke/hub-rpc.ts +7 -2
- package/src/spoke/hub-tool-subscriptions.ts +82 -0
- package/src/spoke/hub-tool-title.ts +89 -0
- package/src/spoke/hub-tool.ts +56 -18
- package/src/spoke/session-context.ts +10 -2
- package/src/spoke/spoke.ts +209 -238
- package/src/spoke/summary.ts +36 -1
- package/src/spoke/taskboard.ts +5 -6
- package/src/spoke/voice-front.ts +323 -30
- package/src/spoke/who-teams.ts +51 -2
- package/src/tui-messaging.ts +24 -10
- package/src/tui.ts +6 -6
- package/web/dist/assets/{ArtifactPage-BKISN-Qj.js → ArtifactPage-Bz992ZX6.js} +1 -1
- package/web/dist/assets/{ArtifactPane-CKOiAUNH.js → ArtifactPane-BJZNixJC.js} +1 -1
- package/web/dist/assets/ArtifactWorkbench-Dti3VP07.js +6 -0
- package/web/dist/assets/{Diagram-vdpmp3xu.css → Diagram-7y8kg3og.css} +1 -1
- package/web/dist/assets/Diagram-B4HdUxw0.js +1 -0
- package/web/dist/assets/{Library-CcjZXsfF.js → Library-CpzD2HDW.js} +2 -2
- package/web/dist/assets/Lightbox-BlbivCkd.js +1 -0
- package/web/dist/assets/MediaImage-Ch3ryIdR.js +4 -0
- package/web/dist/assets/ProfilesDestination-DlQeogea.js +1 -0
- package/web/dist/assets/{TeamsPage-CDyjrK-I.js → TeamsPage-4xdWCaI-.js} +1 -1
- package/web/dist/assets/{Watchtower-DYwoUWME.js → Watchtower-CpQdIRns.js} +2 -2
- package/web/dist/assets/{artifacts-DU9uRgs1.js → artifacts-But87Jfo.js} +1 -1
- package/web/dist/assets/index-BC0O1gfR.css +1 -0
- package/web/dist/assets/index-BS6lA6fN.js +33 -0
- package/web/dist/assets/{live-ycZ_aQZO.js → live-CVUFIdUX.js} +2 -2
- package/web/dist/assets/{pane-layout-0RrLHGDr.js → pane-layout-BW0RdX5a.js} +1 -1
- package/web/dist/assets/{renderer2d-BIwbgRoX.js → renderer2d-IaJiloPi.js} +1 -1
- package/web/dist/assets/{renderer3d-C1a7eYGQ.js → renderer3d-ZiD1uKGW.js} +1 -1
- package/web/dist/assets/{safe-area-DHhPy61Q.js → safe-area-C7IAlkgY.js} +1 -1
- package/web/dist/assets/{source-BWlvaODa.js → source-C-De8L3s.js} +1 -1
- package/web/dist/assets/toast-CXTwTvDw.js +9 -0
- package/web/dist/assets/vad-worklet-BfxJhrXy.js +27 -0
- package/web/dist/index.html +6 -6
- package/web/dist/assets/ArtifactWorkbench-d7R1o-rs.js +0 -6
- package/web/dist/assets/Diagram-azw2B_QH.js +0 -1
- package/web/dist/assets/Lightbox-Du56MXGX.js +0 -1
- package/web/dist/assets/MediaImage-Ds_JUx3a.js +0 -4
- package/web/dist/assets/ProfilesDestination-DdzbzmeK.js +0 -1
- package/web/dist/assets/index-C3ci5UtY.css +0 -1
- package/web/dist/assets/index-LNMZCqgE.js +0 -36
- package/web/dist/assets/toast-Cuu2K0hx.js +0 -1
- /package/{web/src/voice → packages/voice-client/src}/turn/LICENSE +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{J as e}from"./ui-CFB4wQfF.js";var t=class extends Error{status;code;field;hint;details;constructor(e,t){super(t),this.status=e}},n=class extends Error{cause;name=`NetworkError`;constructor(e){super(`Can't reach the hub: the connection dropped. Check your network and try again.`),this.cause=e}},r;function i(e){r=e}async function a(e,{method:i=`GET`,json:a,body:o,headers:s={},signal:c,keepalive:l}={}){let u={method:i,credentials:`same-origin`,headers:{...s},signal:c,keepalive:l};a===void 0?o!==void 0&&(u.body=o):(u.headers[`content-type`]=`application/json`,u.body=JSON.stringify(a));let d;try{d=await fetch(e,u)}catch(e){throw e instanceof TypeError?new n(e):e}if(!d.ok){let e=await d.json().catch(()=>({}));d.status===401&&r?.();let n=e.error&&typeof e.error==`object`?e.error:e,i=typeof e.error==`string`?e.error:typeof n.message==`string`?n.message:``,a=new t(d.status,i||`HTTP ${d.status}`);throw typeof n.field==`string`&&(a.field=n.field),typeof n.code==`string`&&(a.code=n.code),typeof n.hint==`string`&&(a.hint=n.hint),e.error&&typeof e.error==`object`&&(a.details=n),a}return d}var o=async e=>(await a(e)).json(),s=async(e,t={})=>(await a(e,{method:`POST`,json:t})).json().catch(()=>({})),c=encodeURIComponent,l=e=>`/api/sessions/${c(e)}`,u=e=>e instanceof Error?e.message:String(e),d=e=>typeof e==`object`&&!!e&&!Array.isArray(e),f=/^[A-Za-z0-9_.:@/+~-]{1,300}$/,p=/[\p{Cc}\p{Cf}\u2028\u2029]/u,ee={workspace:`ws`,binding:`wsb`,member:`wsm`,assignment:`asg`,supervision:`sup`,checkpoint:`chk`,sideChat:`chat`,profile:`prof`,artifact:`art`,revision:`rev`,blob:`blob`,aiJob:`job`,team:`team`,staffing:`stf`,intake:`itk`},te=/^[A-Za-z0-9]{16,32}$/;function ne(e,t){if(typeof t!=`string`)return!1;let n=`${ee[e]}_`;return t.startsWith(n)&&te.test(t.slice(n.length))}var re=/^[a-z0-9-]{2,40}$/,m=e=>typeof e==`string`&&re.test(e),h=(e,t=120)=>typeof e==`string`&&e.trim().length>0&&e.length<=t&&!p.test(e),g=4e3,_=/[\u0000-\u0009\u000b-\u001f\u007f\u2028\u2029\u200b-\u200f\u202a-\u202e\u2066-\u2069]/,v=(e,t=g)=>typeof e==`string`&&e.length<=t&&!_.test(e);function y(e){if(e!==void 0){if(!Array.isArray(e)||e.length>32)return`tags must be a list of at most 32`;if(!e.every(m))return`each tag must be 2–40 lowercase letters, digits or dashes`;if(new Set(e).size!==e.length)return`tags must be unique`}}function b(e){if(e===void 0)return;if(typeof e!=`object`||!e||Array.isArray(e))return`metadata must be an object`;let t=Object.entries(e);if(t.length>32)return`metadata has more than 32 keys`;for(let[e,n]of t){if(!m(e))return`metadata key ${JSON.stringify(String(e).slice(0,50))} must be a slug`;if(!h(n,200))return`metadata.${e} must be 1–200 characters of text`}}var x=e=>e.signedIn,S=[{id:`sessions`,label:`All sessions`,icon:`home`,route:`/`,order:10,available:e=>x(e)?!0:`hidden`},{id:`concierge`,label:`Concierge`,icon:`spark`,route:`/concierge`,order:15,available:e=>x(e)&&e.concierge!==void 0&&e.concierge!==`disabled`?!0:`hidden`},{id:`artifacts`,label:`Artifacts`,icon:`file`,route:`/artifacts`,order:20,available:e=>x(e)?!0:`hidden`},{id:`teams`,label:`Teams`,icon:`team`,route:`/teams`,order:25,available:e=>x(e)?!0:`hidden`},{id:`watchtower`,label:`Watchtower`,icon:`watchtower`,route:`/watchtower`,order:30,available:e=>x(e)?!0:`hidden`},{id:`profiles`,label:`Agent profiles`,icon:`settings`,route:`/profiles`,order:40,available:e=>x(e)?!0:`hidden`}],ie={"/birds-eye":`/watchtower`};function ae(e,t=``,n=``){for(let[r,i]of Object.entries(ie))if(e===r||e.startsWith(`${r}/`))return`${i}${e.slice(r.length)}${t}${n}`}function C(e,t){try{return e.available(t)}catch{return`hidden`}}function oe(e,t=S){return[...t].sort((e,t)=>e.order-t.order).flatMap(t=>{let n=C(t,e);return n===`hidden`?[]:[{dest:t,enabled:n===!0}]})}var se=(e,t)=>C(e,t)===!0?`ok`:`unavailable`;function w(e,t=S){for(let n of t)if(n.route!==`/`&&(e===n.route||e.startsWith(`${n.route}/`)))try{return{dest:n,rest:e.slice(n.route.length).split(`/`).filter(Boolean).map(decodeURIComponent)}}catch{return}}function ce(e,t=S){return e===`/`?t.find(e=>e.route===`/`)?.id:w(e,t)?.dest.id}function T(e){return e.supported?e.permission===`denied`?{state:`blocked`,message:`Notifications are blocked for this site. Allow them in the browser's site settings, then reload.`,action:`none`,warn:!0}:e.permission==="default"?{state:`off`,message:`Notifications are off on this device.`,action:`enable`,warn:!0}:!e.worker||!e.endpoint||!e.hubSubscribed?{state:`repair`,message:`Allowed, but this device is not subscribed on this hub, so nothing will arrive (this happens after the hub moves to a new address). Enable again to fix it.`,action:`enable`,warn:!0}:{state:`on`,message:`On for this device.`,action:`disable`,warn:!1}:{state:`unsupported`,message:`This browser can't get notifications here. On iPhone, add the app to the Home Screen first (iOS 16.4+); everywhere else the hub must be on https.`,action:`none`,warn:!0}}var E=e=>e.supported&&e.permission===`granted`&&(!e.endpoint||!e.hubSubscribed);function D(e){if(e.subscriptions===0)return{ok:!1,text:`This device is not subscribed; enable notifications first`};if(e.sent>0)return{ok:!0,text:e.sent===1?`Test notification sent to this device`:`Test notification sent (${e.sent} subscriptions)`};let t=e.failed[0];return t?{ok:!1,text:`Test failed: ${t.host} ${t.status===void 0?`did not answer`:`answered ${t.status}`}`}:{ok:!1,text:`Test failed`}}var O=[1,2,5,10,15,30,60],k=[{title:`Needs you`,kinds:[{key:`question`,label:`Question`,description:`A session or subagent asks you something.`},{key:`permission`,label:`Needs permission`,description:`A tool call waits for your OK (answer from the notification).`},{key:`decision`,label:`Decision`,description:`A session asks you to decide (hub ask @me), with options and a recommendation.`},{key:`message`,label:`Message`,description:`Agent messaging needs you: a message to you, an unanswered ask, or sessions looping.`},{key:`concierge`,label:`Concierge`,description:`Your Concierge needs you or has news: its questions, permissions, decisions, messages and spoken replies.`}]},{title:`Session`,kinds:[{key:`done`,label:`All done`,description:`The session and all its subagents and scripts finished; nothing waits on you. Once per run.`},{key:`failed`,label:`Failed`,description:`The session's run failed (provider or tool error), with the reason.`},{key:`providerError`,label:`Model provider error`,description:`Quota, budget, auth or model-routing errors of the session or a subagent; once per run.`},{key:`turn`,label:`Turn finished`,description:`Every reply of the main session, also the short ones between subagents. Noisy.`},{key:`stopped`,label:`Stopped`,description:`A run stopped without you asking (OpenCode shut down, inactivity).`},{key:`retry`,label:`Retrying`,description:`The provider failed and OpenCode is retrying the request.`}]},{title:`Subagents`,kinds:[{key:`subagentDone`,label:`Subagent finished`,description:`Each subagent that finishes, by name.`},{key:`subagentFailed`,label:`Subagent failed`,description:`Each subagent that fails, with the reason.`}]},{title:`Scripts and tools`,kinds:[{key:`jobDone`,label:`Script finished`,description:`A background shell or terminal exited 0.`},{key:`jobFailed`,label:`Script failed`,description:`A background shell or terminal exited non-zero, was killed or timed out.`},{key:`longTool`,label:`Long tool finished`,description:`A tool call that ran 30 seconds or more ended.`}]},{title:`Voice`,kinds:[{key:`say`,label:`Spoken reply`,description:`Voice mode replies while no device shows the session.`},{key:`handoff`,label:`Hand-off`,description:`A session sent to this device from the terminal (ignores quiet hours).`}]},{title:`Activity digest`,kinds:[{key:`activity`,label:`Activity`,description:`One quiet, self-replacing summary per session: subagents, long tools, scripts, idle.`}]}],A=k.flatMap(e=>e.kinds);function j(e){let t=A.filter(t=>e[t.key]).map(e=>e.label);return t.length?`You'll get: ${t.join(`, `)}.`:`You'll get no notifications on this device.`}function M(){try{return Intl.DateTimeFormat().resolvedOptions().timeZone||`UTC`}catch{return`UTC`}}var N=[{id:`general`,label:`General`,description:`Account, theme, text size and the Hub app`},{id:`notifications`,label:`Notifications`,description:`This device's notifications, what to notify about, quiet hours`},{id:`voice`,label:`Voice & speech`,description:`Voice mode, mic sensitivity, speech-to-text and text-to-speech`},{id:`media`,label:`Media`,description:`Web images in replies: the sites whose images load at once`},{id:`machines`,label:`Machines & devices`,description:`Connected machines, approvals, signed-in browsers and apps`},{id:`agents`,label:`Agents & access`,description:`App tokens, acting switches, grants and agent activity`},{id:`concierge`,label:`Concierge`,description:`Your hub-managed assistant: machine, directory, model and its grant`},{id:`teams`,label:`Teams`,description:`Team isolation: what team members see`},{id:`admin`,label:`Admin`,description:`Users, all machines, approvals and the audit log`,admin:!0}],P=e=>N.filter(t=>e||!t.admin);function F(e){if(e!==`/settings`&&!e.startsWith(`/settings/`))return;let t=e.slice(10).split(`/`)[0]??``;if(!t)return{};try{return{section:decodeURIComponent(t)}}catch{return{section:t}}}function I(e,t){return e===void 0?t.phone?`list`:`general`:P(t.admin).find(t=>t.id===e)?.id}var L={account:`general`,appearance:`general`,notifications:`notifications`,voice:`voice`,speech:`voice`,machines:`machines`,devices:`machines`,agents:`agents`,admin:`admin`};function R(e){let t=e.replace(/^#/,``);if(!t)return;let n=L[t];if(n)return`/settings/${n}#${t}`;if(N.some(e=>e.id===t))return`/settings/${t}`}var z=[{id:`account`,section:`general`,label:`Account`,description:`Who you are signed in as; sign out of this device`,keywords:`sign out logout user email`},{id:`set-theme`,section:`general`,label:`Color theme`,description:`Light, dark or the system's theme`,keywords:`appearance light dark system mode`},{id:`set-text-size`,section:`general`,label:`Text size`,description:`How big text is on this device`,keywords:`appearance font scale zoom`},{id:`add-app`,section:`general`,label:`Add the Hub app`,description:`Link the Hub app on a phone or tablet with a QR code`,keywords:`mobile android ios install pair link`},{id:`notifications`,section:`notifications`,label:`Notifications on this device`,description:`Enable or turn off push notifications here; permission and subscription status`,keywords:`push enable subscribe permission service worker`},{id:`notify-test`,section:`notifications`,label:`Send test notification`,description:`Check that notifications reach this device`,keywords:`push try`},{id:`quiet-hours`,section:`notifications`,label:`Quiet hours`,description:`No notifications at night (hand-offs still come through)`,keywords:`do not disturb night sleep time`},{id:`set-voice-speed`,section:`voice`,label:`Voice speed`,description:`How fast replies are spoken`,keywords:`rate tts`},{id:`set-sensitivity`,section:`voice`,label:`Mic sensitivity`,description:`How sure Voice mode must be that you are speaking to it`,keywords:`microphone noise vad`},{id:`set-turn-detection`,section:`voice`,label:`Turn detection`,description:`When Voice mode decides you finished speaking: silence timers, or the Smart Turn audio model (experimental)`,keywords:`end of turn endpointing smart turn pause hold vad experimental`},{id:`set-voice-front`,section:`voice`,label:`Voice front (experimental)`,description:`A fast voice agent answers in front of the session: it says what it understood, then relays to the session, which keeps its own agent`,keywords:`front echo relay fast assistant agent experimental`},{id:`set-cues`,section:`voice`,label:`Progress cues`,description:`Tones and short acknowledgements while the agent works`,keywords:`sounds acknowledgement`},{id:`set-background`,section:`voice`,label:`Keep listening when the screen is off`,description:`Lock-screen controls and listening with the screen off`,keywords:`background lock screen`},{id:`recording`,section:`voice`,label:`Record voice conversations (developer)`,description:`Saves your voice segments, transcripts, replies, timing and Concierge actions on this hub, for 7 days; export or delete them`,keywords:`record debug developer training audio export delete`},{id:`speech`,section:`voice`,label:`Speech`,description:`Speech-to-text and text-to-speech provider, model, voice and API keys`,keywords:`stt tts transcription openrouter openai key`},{id:`media-allowlist`,section:`media`,label:`Web images`,description:`Sites whose images in replies load at once; images from other sites wait for a tap`,keywords:`allowlist allow remote image picture domain host site github load`},{id:`machines`,section:`machines`,label:`Machines`,description:`Computers running OpenCode connected to this hub; approve or revoke them`,keywords:`computer approve enrollment revoke opencode`},{id:`setup-machine`,section:`machines`,label:`Set up Hub on a machine`,description:`A one-line installer for macOS, Linux or Windows that connects a computer to this hub`,keywords:`setup install connect add new computer server laptop hubctl curl powershell windows linux macos enroll`},{id:`devices`,section:`machines`,label:`Devices`,description:`Browsers and the Hub app signed in to your account; revoke them`,keywords:`browser phone sessions revoke sign out`},{id:`agents`,section:`agents`,label:`Acting switch`,description:`Whether sessions and apps may act for you at all`,keywords:`pause kill switch acting`},{id:`app-tokens`,section:`agents`,label:`App tokens`,description:`Tokens for MCP gateways, CLIs and other apps, with their scopes`,keywords:`api key token scopes mcp cli`},{id:`grants`,section:`agents`,label:`Grants`,description:`What sessions and apps may approve, deny, answer, prompt or stop for you`,keywords:`permissions delegate allow`},{id:`agent-activity`,section:`agents`,label:`Agent activity`,description:`What agents did for you (the agent audit)`,keywords:`audit log history`},{id:`concierge`,section:`concierge`,label:`Concierge`,description:`Turn the Concierge on or off, pick its machine and directory, restart it`,keywords:`assistant butler watch sessions`},{id:`concierge-grant`,section:`concierge`,label:`Concierge grant`,description:`What the Concierge may do for you without asking; renew or remove it`,keywords:`permissions approve deny preset`},{id:`team-isolation`,section:`teams`,label:`Team isolation`,description:`Team members see only their teams' sessions, not your other sessions`,keywords:`teams privacy hide members`}],B=[{id:`admin`,section:`admin`,label:`Users`,description:`Everyone on this hub: roles, disable, remove`,keywords:`admin accounts people`},{id:`admin-machines`,section:`admin`,label:`All machines`,description:`Every machine connected to this hub, by owner`,keywords:`admin revoke`},{id:`admin-audit`,section:`admin`,label:`Audit log`,description:`Who changed what on this hub`,keywords:`admin history`}],V=(e,t)=>({id:`pref-${e.key}`,section:`notifications`,label:e.label,description:e.description,keywords:`notify ${t}`});function H(e){return[...z,...k.flatMap(e=>e.kinds.map(t=>V(t,e.title))),...e?B:[]]}var U=e=>N.find(t=>t.id===e)?.label??e;function le(e,t){let n=e.trim().toLowerCase();if(!n)return[];let r=n.split(/\s+/),i=e=>{let t=e.label.toLowerCase();return t.startsWith(n)?0:t.includes(n)?1:r.every(e=>t.includes(e))?2:3};return t.filter(e=>{let t=`${e.label} ${e.description} ${e.keywords??``} ${U(e.section)}`.toLowerCase();return r.every(e=>t.includes(e))}).map((e,t)=>({e,i:t,r:i(e)})).sort((e,t)=>e.r-t.r||e.i-t.i).map(e=>e.e)}function W(e,t){let n=e.filter(e=>e.key in t);if(!n.length)return``;let r=n.filter(e=>t[e.key]);return r.length===n.length?`All on`:r.length?`${r.length} of ${n.length} on: ${r.map(e=>e.label).join(`, `)}`:`All off`}var ue=e=>e&&e.startsWith(`/`)&&!e.startsWith(`//`)&&!e.includes(`\\`)?e:`/`;function de(e){let t=e.pathname,n=e.searchParams;if(t===`/pair`)return{name:`pair`,next:ue(n.get(`next`)),error:n.get(`error`)??``};if(t===`/approve`)return{name:`approve`,code:n.get(`code`)??``};if(t===`/new`)return{name:`new`,machine:n.get(`machine`)??void 0,dir:n.get(`dir`)??void 0,key:n.get(`key`)??void 0};if(t===`/panes`)return{name:`panes`};if(t===`/concierge`||t.startsWith(`/concierge/`))return{name:`concierge`};let r=F(t);if(r)return{name:`settings`,...r};let i=w(t);if(i)return{name:`feature`,id:i.dest.id,rest:i.rest};let a=/^\/s\/([^/]+)$/.exec(t);if(a)try{return{name:`session`,id:decodeURIComponent(a[1])}}catch{return{name:`home`}}return{name:`home`}}function G(){let e=(location.pathname===`/settings`?R(location.hash):void 0)??ae(location.pathname,location.search,location.hash);return e&&history.replaceState(history.state,``,e),new URL(location.href)}var[K,q]=e(G()),fe=K,pe=()=>de(K()),J=0;function Y(e,{replace:t=!1}={}){let n=new URL(e,location.origin);n.pathname+n.search+n.hash!==location.pathname+location.search+location.hash&&(history[t?`replaceState`:`pushState`]({},``,n.pathname+n.search+n.hash),t||J++),q(G())}function me(e=`/`){J>0?history.back():Y(e)}window.addEventListener(`popstate`,()=>{J=Math.max(0,J-1),q(G())}),document.addEventListener(`click`,e=>{let t=e.target?.closest?.(`a[href]`);if(!t||t.target||t.hasAttribute(`download`)||e.defaultPrevented||e.button!==0||e.metaKey||e.ctrlKey||e.shiftKey||e.altKey)return;let n=t.getAttribute(`href`)??``;!n.startsWith(`/`)||n.startsWith(`//`)||n.startsWith(`/auth/`)||n.startsWith(`/api/`)||(e.preventDefault(),Y(n))});var X=()=>new Set;function he(e){X=e}var ge=e=>X().has(e),_e=e=>X().has(e)?`/concierge`:`/s/${encodeURIComponent(e)}`,[Z,Q]=e(),ve=Z,ye=0,$;function be(e,t=``,n){let r=++ye;Q({id:r,text:e,kind:t,action:n}),clearTimeout($),$=setTimeout(()=>Z()?.id===r&&Q(void 0),n||t?8e3:4e3)}var xe=()=>Q(void 0);export{h as A,c as B,E as C,se as D,oe as E,f as F,i as G,o as H,d as I,t as L,v as M,b as N,g as O,y as P,n as R,j as S,ce as T,s as U,u as V,l as W,k as _,ge as a,M as b,pe as c,W as d,I as f,O as g,P as h,me as i,m as j,ne as k,_e as l,H as m,xe as n,fe as o,le as p,be as r,Y as s,ve as t,he as u,A as v,S as w,T as x,D as y,a as z};
|
|
File without changes
|