@fugood/buttress-server 2.26.0-beta.1 → 2.26.0-beta.12

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/README.md +190 -4
  2. package/config/function-samples/README.md +2 -0
  3. package/config/function-samples/bank-note.ts +47 -0
  4. package/config/function-samples/bank-watch-daemon.ts +63 -0
  5. package/config/function-samples/run-agent.ts +39 -0
  6. package/config/sample.toml +23 -0
  7. package/lib/agent/cli.d.ts +19 -0
  8. package/lib/agent/client.d.ts +66 -0
  9. package/lib/agent/config.d.ts +15 -0
  10. package/lib/agent/context.d.ts +11 -0
  11. package/lib/agent/device-tools.d.ts +4 -0
  12. package/lib/agent/loopback.d.ts +21 -0
  13. package/lib/agent/mcp.d.ts +23 -0
  14. package/lib/agent/models.d.ts +20 -0
  15. package/lib/agent/service.d.ts +16 -0
  16. package/lib/agent/session-fs.d.ts +3 -0
  17. package/lib/agent/sessions.d.ts +17 -0
  18. package/lib/agent/tools.d.ts +32 -0
  19. package/lib/agent/tui.d.ts +17 -0
  20. package/lib/agent/types.d.ts +125 -0
  21. package/lib/cli-CtBbHMYQ.mjs +22 -0
  22. package/lib/client-DzfRSFcJ.mjs +8 -0
  23. package/lib/config-DbRjQnNp.mjs +2 -0
  24. package/lib/functions/bank-subscribe.d.ts +46 -0
  25. package/lib/functions/bank.d.ts +21 -0
  26. package/lib/functions/daemons.d.ts +45 -0
  27. package/lib/functions/executor.d.ts +31 -4
  28. package/lib/functions/index.d.ts +17 -7
  29. package/lib/functions/registry.d.ts +7 -1
  30. package/lib/functions/status.d.ts +49 -1
  31. package/lib/functions/templates.d.ts +3 -1
  32. package/lib/functions/types.d.ts +130 -2
  33. package/lib/index.d.ts +10 -5
  34. package/lib/index.mjs +280 -58
  35. package/lib/mlx-bridge.py +681 -0
  36. package/lib/rolldown-runtime-dTnj95Mm.mjs +2 -0
  37. package/lib/routes/agents.d.ts +37 -0
  38. package/lib/routes/anthropic-messages.d.ts +2 -2
  39. package/lib/routes/index.d.ts +1 -0
  40. package/lib/routes/openai-compat.d.ts +2 -2
  41. package/lib/tui-DbQ0zW-C.mjs +2 -0
  42. package/lib/types.d.ts +11 -1
  43. package/lib/utils/config.d.ts +1 -2
  44. package/lib/utils/cors.check.d.ts +1 -0
  45. package/lib/utils/cors.d.ts +72 -0
  46. package/lib/utils/workspaceState.d.ts +9 -0
  47. package/lib/wrapper-3PX6qE3t.mjs +7 -0
  48. package/package.json +10 -5
  49. package/public/status.html +77 -1
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Agent endpoints (EXPERIMENTAL).
3
+ *
4
+ * GET /agents configured agent names
5
+ * POST /agents/:name/run run a prompt; ?stream=1 for SSE events
6
+ * (first a `session` event with the id,
7
+ * then `agent` events, then result/error)
8
+ * GET /agents/:name/sessions newest-first session summaries
9
+ * GET /agents/:name/sessions/:id full transcript (pi messages)
10
+ * POST /agents/:name/sessions/:id/abort abort the active run on a session
11
+ *
12
+ * Configured via [[agents]] tables. These endpoints double as the surface the
13
+ * `bricks-buttress agent` CLI (and future clients) consume.
14
+ *
15
+ * Auth mirrors the functions surface, not the open inference endpoints:
16
+ * agents execute local functions, so an unbound server rejects every call
17
+ * unless `[agents_options] allow_unauthenticated = true`. A bound server
18
+ * accepts workspace JWTs. The server's own ephemeral internal token (also
19
+ * written to the 0600 runtime file for same-host CLIs) is always accepted.
20
+ */
21
+ import { type AgentsService } from '../agent/types';
22
+ /**
23
+ * Slim pi agent events for the wire. `message_update` carries the FULL partial
24
+ * assistant message on every delta — per-token that would dwarf the payload —
25
+ * and tool results can be huge; clients that want the transcript fetch it
26
+ * from the sessions endpoint afterwards.
27
+ */
28
+ export declare const slimAgentEvent: (event: any) => unknown;
29
+ export declare function streamAgentRun(agents: AgentsService, name: string, body: {
30
+ prompt: string;
31
+ sessionId?: string;
32
+ fork?: boolean;
33
+ }, signal: AbortSignal | undefined): AsyncGenerator<{
34
+ readonly event: string;
35
+ readonly data: string;
36
+ }, void, unknown>;
37
+ export default function factory(agents: AgentsService): import("../types").ButtressApp;
@@ -11,7 +11,7 @@
11
11
  *
12
12
  * Note: This feature is experimental and may change in future versions.
13
13
  */
14
- import type { EventStream, Config } from '../types';
14
+ import type { EventStream } from '../types';
15
15
  /**
16
16
  * Stream an Anthropic Messages SSE response from the backend stream.
17
17
  *
@@ -52,4 +52,4 @@ export declare function streamAnthropicMessage(completionStream: ReadableStream<
52
52
  readonly event: "message_stop";
53
53
  readonly data: string;
54
54
  }, void, unknown>;
55
- export default function factory({ global: globalConfig }: Config): import("../types").ButtressApp;
55
+ export default function factory(): import("../types").ButtressApp;
@@ -4,3 +4,4 @@ export { default as status } from './status';
4
4
  export { default as openaiCompatFactory } from './openai-compat';
5
5
  export { default as anthropicMessagesFactory } from './anthropic-messages';
6
6
  export { default as functionsFactory } from './functions';
7
+ export { default as agentsFactory } from './agents';
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * Note: This feature is experimental and may change in future versions.
8
8
  */
9
- import type { EventStream, Config } from '../types';
9
+ import type { EventStream } from '../types';
10
10
  /**
11
11
  * Stream an OpenAI-compatible chat completion (SSE) from the backend stream.
12
12
  * Mirrors collectChatCompletion (the non-streaming path).
@@ -14,4 +14,4 @@ import type { EventStream, Config } from '../types';
14
14
  export declare function streamChatCompletion(completionStream: ReadableStream<EventStream>, completionId: string, created: number, modelId: string, includeUsage: boolean): AsyncGenerator<{
15
15
  readonly data: string;
16
16
  }, void, unknown>;
17
- export default function factory({ global: globalConfig }: Config): import("../types").ButtressApp;
17
+ export default function factory(): import("../types").ButtressApp;
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import{a as e,t}from"./client-DzfRSFcJ.mjs";import{Container as n,Editor as r,Loader as i,Markdown as a,ProcessTerminal as o,Text as s,TuiMainScreen as c}from"@earendil-works/pi-tui";const l=e=>t=>`\x1b[${e}m${t}\x1b[0m`,u=l(`2`),d=l(`1`),f=l(`36`),p=l(`33`),m=l(`31`),h=l(`32`),g=l(`35`),_={heading:e=>d(f(e)),link:f,linkUrl:e=>u(f(e)),code:p,codeBlock:p,codeBlockBorder:u,quote:u,quoteBorder:u,hr:u,listBullet:f,bold:d,italic:l(`3`),strikethrough:l(`9`),underline:l(`4`)},v={borderColor:u,selectList:{selectedPrefix:f,selectedText:d,description:u,scrollInfo:u,noMatch:u}},y=(e,t)=>e.length>t?`${e.slice(0,t)}…`:e;var b=class{tui;chat;thinking=null;thinkingBuffer=``;answer=null;answerBuffer=``;constructor(e,t){this.tui=e,this.chat=t}touch(){this.tui.requestRender()}appendThinking(e){this.thinking||(this.thinking=new s(``,0,0),this.chat.addChild(this.thinking)),this.thinkingBuffer+=e,this.thinking.setText(u(this.thinkingBuffer.trimEnd())),this.touch()}appendAnswer(e){this.answer||(this.answer=new a(``,0,0,_),this.chat.addChild(this.answer)),this.answerBuffer+=e,this.answer.setText(this.answerBuffer),this.touch()}addLine(e){this.answer=null,this.answerBuffer=``,this.chat.addChild(new s(e,0,0)),this.touch()}};const x=async({connection:a,agentName:l,sessionId:_,fork:x})=>{let S=new o,C=new c(S);S.setTitle(`buttress agent · ${l}`);let w=new n,T=new s(``,0,0),E=new r(C,v);C.addChild(w),C.addChild(T),C.addChild(E),C.setFocus(E);let D=_,O=x,k=null,A=null,j=e=>{T.setText(e),C.requestRender()},M=()=>{A||(A=new i(C,f,u,`thinking…`),w.addChild(A),C.requestRender())},N=()=>{A&&(w.removeChild(A),A=null,C.requestRender())},P=`${d(l)} ${u(`@ ${a.baseUrl}`)}`+(D?` ${u(`(${O?`forking`:`continuing`} ${D})`)}`:``);w.addChild(new s(P,0,0)),j(u(`Enter to send · /new fresh session · /exit or Ctrl+C to quit`));let F=async()=>{C.stop(),await S.drainInput().catch(()=>{}),process.exit(0)};C.addInputListener(e=>{if(e===``)return k?(k.abort(),k=null,{consume:!0}):(F(),{consume:!0})});let I=async n=>{w.addChild(new s(`${f(`>`)} ${n}`,0,0));let r=new b(C,w),i=D;k=new AbortController,M(),j(u(`running · Ctrl+C aborts this turn`));let o;try{o=await e(a,l,{prompt:n,sessionId:D??void 0,fork:O},{signal:k.signal,onFrame:({event:e,payload:t})=>{if(e===`session`&&t?.sessionId){t.sessionId!==D&&(D=t.sessionId,w.addChild(new s(u(`session ${D}`),0,0)));return}if(e!==`agent`)return;N();let n=t?.event;if(t?.type===`message_update`&&n)n.type===`thinking_delta`?r.appendThinking(n.delta??``):n.type===`text_delta`&&r.appendAnswer(n.delta??``);else if(t?.type===`tool_execution_start`){let e=JSON.stringify(t.args??{});r.addLine(`${p(`⚙ ${t.toolName}`)}${u(`(${y(e,120)})`)}`)}else t?.type===`tool_execution_end`?r.addLine(t.isError?m(`✗ ${t.toolName} failed`):u(`✓ ${t.toolName}`)):t?.type===`tool_emit`&&r.addLine(u(` ${t.toolName} → ${t.event}`))}})}catch(e){o={kind:`error`,message:e?.message||String(e),sessionId:D}}if(N(),k=null,o.kind===`result`){let{result:e}=o;D=e.sessionId??D;let t=e.usage||{};w.addChild(new s(u(`— ${e.stopReason} · ${t.totalTurns??`?`} turn(s) · ${t.input??0} in / ${t.output??0} out · session ${D}`),0,0))}else o.kind===`aborted`?(D=o.sessionId??D,w.addChild(new s(p(`(aborted — session is continuable)`),0,0))):o.kind===`error`?(D=o.sessionId??D,w.addChild(new s(m(`Run failed: ${o.message}`),0,0))):w.addChild(new s(m(`Connection lost mid-run.`),0,0));t(i,D)&&(O=!1),j(u(`Enter to send · /new fresh session · /exit or Ctrl+C to quit`)),C.requestRender()};E.onSubmit=e=>{let t=e.trim();if(E.setText(``),t){if(k){j(p(`A turn is still running — Ctrl+C aborts it.`));return}if(t===`/exit`||t===`/quit`){F();return}if(t===`/new`){D=null,O=!1,w.addChild(new s(`${h(`•`)} ${u(`started a fresh session`)}`,0,0)),C.requestRender();return}if(t===`/session`){w.addChild(new s(u(D?`session ${D}`:`no session yet`),0,0)),C.requestRender();return}I(t)}},w.addChild(new s(u(g(`ready`)),0,0)),C.start(),await new Promise(()=>{})};export{x as runAgentTui};
package/lib/types.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import type { Elysia, SingletonBase } from 'elysia';
2
2
  import type { ReadableStream } from 'node:stream/web';
3
- import type { Backend } from './index';
3
+ import type * as backendCore from '@fugood/buttress-backend-core';
4
+ export type Backend = typeof backendCore;
4
5
  export type HumanReadableUnit = number | string;
5
6
  type NormalizeKeys = 'max_body_size' | 'session_timeout' | 'max_size_bytes';
6
7
  export type DeepNormalize<T> = T extends object ? {
@@ -53,6 +54,10 @@ export type GlobalConfig = {
53
54
  config?: Record<string, any>;
54
55
  cors_allowed_origins?: string | string[];
55
56
  };
57
+ /** `[[agents]]` tables; validated by `agent/config.ts` at startup. */
58
+ agents?: Record<string, any>[];
59
+ /** `[agents_options]`: sessions_dir, retention, max_depth, allow_unauthenticated. */
60
+ agents_options?: Record<string, any>;
56
61
  } & Record<string, any>;
57
62
  export type AutodiscoverConfig = {
58
63
  udp: {
@@ -135,6 +140,11 @@ export type ServerInfo = {
135
140
  enabled: boolean;
136
141
  count: number;
137
142
  };
143
+ /** Agent surface: a flag and a count, for the same ANNOUNCE-size reason. */
144
+ agents?: {
145
+ enabled: boolean;
146
+ count: number;
147
+ };
138
148
  };
139
149
  export type EventStream = {
140
150
  event: string;
@@ -1,5 +1,4 @@
1
- import type { Config, AutodiscoverConfig, HumanReadableConfig } from '../types';
2
- import type { Backend } from '../index';
1
+ import type { Backend, Config, AutodiscoverConfig, HumanReadableConfig } from '../types';
3
2
  export declare const deepMerge: (target?: Record<string, any>, source?: Record<string, any>) => Record<string, any>;
4
3
  export declare const normalizeConfigInput: (input: any) => null | Record<string, any>;
5
4
  export declare const mergeGeneratorConfig: (base: any, override: any) => Record<string, any>;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,72 @@
1
+ import type { Config } from '../types';
2
+ /**
3
+ * The server's whole CORS policy, decided in one place, by path.
4
+ *
5
+ * Every surface used to install its own `@elysiajs/cors` plugin on its own
6
+ * router. That does not do what it looks like it does: the plugin works through
7
+ * an `onRequest` hook, which Elysia runs *before* routing and therefore applies
8
+ * app-wide regardless of the router it was mounted on, and the plugins' default
9
+ * response headers all merge into one map on the root app. The four policies
10
+ * ended up fighting over a single set of `Access-Control-*` headers, last
11
+ * writer winning:
12
+ *
13
+ * - `/buttress/info` ran without an explicit `allowedHeaders`, which makes
14
+ * @elysiajs/cors echo the request's own header names back. That answer
15
+ * overwrote every other surface's allow-list, so `Content-Type` was missing
16
+ * from it and any browser `POST /functions/<name>` with a JSON body failed
17
+ * preflight — the symptom that surfaced this.
18
+ * - With that route disabled the *last registered* plugin's header list won
19
+ * instead, so `/anthropic-messages` was served `/functions`'s list and lost
20
+ * `x-api-key` / `anthropic-version`.
21
+ * - `handleOrigin` only ever sets `Access-Control-Allow-Origin` on a match and
22
+ * never clears it on a miss, so an origin allow-listed for one surface stayed
23
+ * reflected on the others — per-surface `cors_allowed_origins` meant nothing.
24
+ *
25
+ * Hence: one hook, one policy per request, chosen by path. A request that no
26
+ * policy owns gets no `Access-Control-*` headers at all.
27
+ *
28
+ * This is CORS only — it decides what a *browser* is willing to hand to script.
29
+ * It is not the access gate. `functionsAuthGuard` (cross-site `Origin` /
30
+ * `Sec-Fetch-Site` check) and `buttressAuthGuard` (workspace JWT) still run on
31
+ * every call and are what actually keeps callers out.
32
+ */
33
+ export type CorsPolicy = {
34
+ /** Path the policy owns: this exact path, or anything below it. */
35
+ path: string;
36
+ /** `true` reflects whatever `Origin` asked. Only for surfaces with no secrets. */
37
+ origin: true | string | string[];
38
+ methods: string[];
39
+ allowedHeaders: string[];
40
+ /** Preflight cache lifetime, in seconds. */
41
+ maxAge: number;
42
+ /**
43
+ * Emit `Access-Control-Allow-Credentials`. Never combined with `origin: true`:
44
+ * reflecting an arbitrary origin *and* allowing credentials is the pairing
45
+ * that turns a public endpoint into a cross-site read primitive.
46
+ */
47
+ credentials: boolean;
48
+ /** Answer Chrome's Private Network Access opt-in when the client asks for it. */
49
+ privateNetwork?: boolean;
50
+ };
51
+ /**
52
+ * Build the policy table from config. The `enable*` flags mirror the conditions
53
+ * `startServer` mounts each router under, so a surface that isn't served never
54
+ * gets a CORS answer either.
55
+ */
56
+ export declare const buildCorsPolicies: (config: Config, enabled?: {
57
+ openaiCompat?: boolean;
58
+ anthropicMessages?: boolean;
59
+ functions?: boolean;
60
+ }) => CorsPolicy[];
61
+ /**
62
+ * Install the policy table as the single writer of `Access-Control-*` headers.
63
+ *
64
+ * Preflights are answered from the hook rather than from `OPTIONS` routes: the
65
+ * hook runs before routing, so there is nothing to collide with a real route,
66
+ * and a preflight for an unmounted path simply falls through to a 404. A bare
67
+ * `OPTIONS` with no `Access-Control-Request-Method` is not a preflight and is
68
+ * left to routing.
69
+ */
70
+ export declare const installCors: <T extends {
71
+ onRequest: (handler: any) => unknown;
72
+ }>(app: T, policies: CorsPolicy[]) => T;
@@ -11,9 +11,18 @@ export interface ServerKeyPair {
11
11
  privateKeyPkcs8: string;
12
12
  kid: string;
13
13
  }
14
+ export interface BankBinding {
15
+ /** Public Data Bank API base URL, e.g. https://bank.bricks.tools */
16
+ endpoint: string;
17
+ spacename: string;
18
+ spacekey: string;
19
+ keyName?: string;
20
+ issuedAt?: string;
21
+ }
14
22
  export interface WorkspaceState {
15
23
  workspace: WorkspaceBinding | null;
16
24
  serverKeyPair: ServerKeyPair | null;
25
+ bank: BankBinding | null;
17
26
  }
18
27
  export declare const resolveStateDir: () => string;
19
28
  export declare const resolveStatePath: () => string;
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ import{i as e,r as t,t as n}from"./rolldown-runtime-dTnj95Mm.mjs";var r=n(((e,t)=>{let n=[`nodebuffer`,`arraybuffer`,`fragments`],r=typeof Blob<`u`;r&&n.push(`blob`),t.exports={BINARY_TYPES:n,EMPTY_BUFFER:Buffer.alloc(0),GUID:`258EAFA5-E914-47DA-95CA-C5AB0DC85B11`,hasBlob:r,kForOnEventAttribute:Symbol(`kIsForOnEventAttribute`),kListener:Symbol(`kListener`),kStatusCode:Symbol(`status-code`),kWebSocket:Symbol(`websocket`),NOOP:()=>{}}})),i=n(((e,n)=>{let{EMPTY_BUFFER:i}=r(),a=Buffer[Symbol.species];function o(e,t){if(e.length===0)return i;if(e.length===1)return e[0];let n=Buffer.allocUnsafe(t),r=0;for(let t=0;t<e.length;t++){let i=e[t];n.set(i,r),r+=i.length}return r<t?new a(n.buffer,n.byteOffset,r):n}function s(e,t,n,r,i){for(let a=0;a<i;a++)n[r+a]=e[a]^t[a&3]}function c(e,t){for(let n=0;n<e.length;n++)e[n]^=t[n&3]}function l(e){return e.length===e.buffer.byteLength?e.buffer:e.buffer.slice(e.byteOffset,e.byteOffset+e.length)}function u(e){if(u.readOnly=!0,Buffer.isBuffer(e))return e;let t;return e instanceof ArrayBuffer?t=new a(e):ArrayBuffer.isView(e)?t=new a(e.buffer,e.byteOffset,e.byteLength):(t=Buffer.from(e),u.readOnly=!1),t}if(n.exports={concat:o,mask:s,toArrayBuffer:l,toBuffer:u,unmask:c},!process.env.WS_NO_BUFFER_UTIL)try{let e=t(`bufferutil`);n.exports.mask=function(t,n,r,i,a){a<48?s(t,n,r,i,a):e.mask(t,n,r,i,a)},n.exports.unmask=function(t,n){t.length<32?c(t,n):e.unmask(t,n)}}catch{}})),a=n(((e,t)=>{let n=Symbol(`kDone`),r=Symbol(`kRun`);t.exports=class{constructor(e){this[n]=()=>{this.pending--,this[r]()},this.concurrency=e||1/0,this.jobs=[],this.pending=0}add(e){this.jobs.push(e),this[r]()}[r](){if(this.pending!==this.concurrency&&this.jobs.length){let e=this.jobs.shift();this.pending++,e(this[n])}}}})),o=n(((e,n)=>{let o=t(`zlib`),s=i(),c=a(),{kStatusCode:l}=r(),u=Buffer[Symbol.species],d=Buffer.from([0,0,255,255]),f=Symbol(`permessage-deflate`),p=Symbol(`total-length`),m=Symbol(`callback`),h=Symbol(`buffers`),g=Symbol(`error`),_;n.exports=class{constructor(e,t,n){if(this._maxPayload=n|0,this._options=e||{},this._threshold=this._options.threshold===void 0?1024:this._options.threshold,this._isServer=!!t,this._deflate=null,this._inflate=null,this.params=null,!_){let e=this._options.concurrencyLimit===void 0?10:this._options.concurrencyLimit;_=new c(e)}}static get extensionName(){return`permessage-deflate`}offer(){let e={};return this._options.serverNoContextTakeover&&(e.server_no_context_takeover=!0),this._options.clientNoContextTakeover&&(e.client_no_context_takeover=!0),this._options.serverMaxWindowBits&&(e.server_max_window_bits=this._options.serverMaxWindowBits),this._options.clientMaxWindowBits?e.client_max_window_bits=this._options.clientMaxWindowBits:this._options.clientMaxWindowBits??(e.client_max_window_bits=!0),e}accept(e){return e=this.normalizeParams(e),this.params=this._isServer?this.acceptAsServer(e):this.acceptAsClient(e),this.params}cleanup(){if(this._inflate&&=(this._inflate.close(),null),this._deflate){let e=this._deflate[m];this._deflate.close(),this._deflate=null,e&&e(Error(`The deflate stream was closed while data was being processed`))}}acceptAsServer(e){let t=this._options,n=e.find(e=>!(t.serverNoContextTakeover===!1&&e.server_no_context_takeover||e.server_max_window_bits&&(t.serverMaxWindowBits===!1||typeof t.serverMaxWindowBits==`number`&&t.serverMaxWindowBits>e.server_max_window_bits)||typeof t.clientMaxWindowBits==`number`&&!e.client_max_window_bits));if(!n)throw Error(`None of the extension offers can be accepted`);return t.serverNoContextTakeover&&(n.server_no_context_takeover=!0),t.clientNoContextTakeover&&(n.client_no_context_takeover=!0),typeof t.serverMaxWindowBits==`number`&&(n.server_max_window_bits=t.serverMaxWindowBits),typeof t.clientMaxWindowBits==`number`?n.client_max_window_bits=t.clientMaxWindowBits:(n.client_max_window_bits===!0||t.clientMaxWindowBits===!1)&&delete n.client_max_window_bits,n}acceptAsClient(e){let t=e[0];if(this._options.clientNoContextTakeover===!1&&t.client_no_context_takeover)throw Error(`Unexpected parameter "client_no_context_takeover"`);if(!t.client_max_window_bits)typeof this._options.clientMaxWindowBits==`number`&&(t.client_max_window_bits=this._options.clientMaxWindowBits);else if(this._options.clientMaxWindowBits===!1||typeof this._options.clientMaxWindowBits==`number`&&t.client_max_window_bits>this._options.clientMaxWindowBits)throw Error(`Unexpected or invalid parameter "client_max_window_bits"`);return t}normalizeParams(e){return e.forEach(e=>{Object.keys(e).forEach(t=>{let n=e[t];if(n.length>1)throw Error(`Parameter "${t}" must have only a single value`);if(n=n[0],t===`client_max_window_bits`){if(n!==!0){let e=+n;if(!Number.isInteger(e)||e<8||e>15)throw TypeError(`Invalid value for parameter "${t}": ${n}`);n=e}else if(!this._isServer)throw TypeError(`Invalid value for parameter "${t}": ${n}`)}else if(t===`server_max_window_bits`){let e=+n;if(!Number.isInteger(e)||e<8||e>15)throw TypeError(`Invalid value for parameter "${t}": ${n}`);n=e}else if(t===`client_no_context_takeover`||t===`server_no_context_takeover`){if(n!==!0)throw TypeError(`Invalid value for parameter "${t}": ${n}`)}else throw Error(`Unknown parameter "${t}"`);e[t]=n})}),e}decompress(e,t,n){_.add(r=>{this._decompress(e,t,(e,t)=>{r(),n(e,t)})})}compress(e,t,n){_.add(r=>{this._compress(e,t,(e,t)=>{r(),n(e,t)})})}_decompress(e,t,n){let r=this._isServer?`client`:`server`;if(!this._inflate){let e=`${r}_max_window_bits`,t=typeof this.params[e]==`number`?this.params[e]:o.Z_DEFAULT_WINDOWBITS;this._inflate=o.createInflateRaw({...this._options.zlibInflateOptions,windowBits:t}),this._inflate[f]=this,this._inflate[p]=0,this._inflate[h]=[],this._inflate.on(`error`,b),this._inflate.on(`data`,y)}this._inflate[m]=n,this._inflate.write(e),t&&this._inflate.write(d),this._inflate.flush(()=>{let e=this._inflate[g];if(e){this._inflate.close(),this._inflate=null,n(e);return}let i=s.concat(this._inflate[h],this._inflate[p]);this._inflate._readableState.endEmitted?(this._inflate.close(),this._inflate=null):(this._inflate[p]=0,this._inflate[h]=[],t&&this.params[`${r}_no_context_takeover`]&&this._inflate.reset()),n(null,i)})}_compress(e,t,n){let r=this._isServer?`server`:`client`;if(!this._deflate){let e=`${r}_max_window_bits`,t=typeof this.params[e]==`number`?this.params[e]:o.Z_DEFAULT_WINDOWBITS;this._deflate=o.createDeflateRaw({...this._options.zlibDeflateOptions,windowBits:t}),this._deflate[p]=0,this._deflate[h]=[],this._deflate.on(`data`,v)}this._deflate[m]=n,this._deflate.write(e),this._deflate.flush(o.Z_SYNC_FLUSH,()=>{if(!this._deflate)return;let e=s.concat(this._deflate[h],this._deflate[p]);t&&(e=new u(e.buffer,e.byteOffset,e.length-4)),this._deflate[m]=null,this._deflate[p]=0,this._deflate[h]=[],t&&this.params[`${r}_no_context_takeover`]&&this._deflate.reset(),n(null,e)})}};function v(e){this[h].push(e),this[p]+=e.length}function y(e){if(this[p]+=e.length,this[f]._maxPayload<1||this[p]<=this[f]._maxPayload){this[h].push(e);return}this[g]=RangeError(`Max payload size exceeded`),this[g].code=`WS_ERR_UNSUPPORTED_MESSAGE_LENGTH`,this[g][l]=1009,this.removeListener(`data`,y),this.reset()}function b(e){if(this[f]._inflate=null,this[g]){this[m](this[g]);return}e[l]=1007,this[m](e)}})),s=n(((e,n)=>{let{isUtf8:i}=t(`buffer`),{hasBlob:a}=r(),o=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,1,1,1,0,0,1,1,0,1,1,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,1,0];function s(e){return e>=1e3&&e<=1014&&e!==1004&&e!==1005&&e!==1006||e>=3e3&&e<=4999}function c(e){let t=e.length,n=0;for(;n<t;)if(!(e[n]&128))n++;else if((e[n]&224)==192){if(n+1===t||(e[n+1]&192)!=128||(e[n]&254)==192)return!1;n+=2}else if((e[n]&240)==224){if(n+2>=t||(e[n+1]&192)!=128||(e[n+2]&192)!=128||e[n]===224&&(e[n+1]&224)==128||e[n]===237&&(e[n+1]&224)==160)return!1;n+=3}else if((e[n]&248)==240){if(n+3>=t||(e[n+1]&192)!=128||(e[n+2]&192)!=128||(e[n+3]&192)!=128||e[n]===240&&(e[n+1]&240)==128||e[n]===244&&e[n+1]>143||e[n]>244)return!1;n+=4}else return!1;return!0}function l(e){return a&&typeof e==`object`&&typeof e.arrayBuffer==`function`&&typeof e.type==`string`&&typeof e.stream==`function`&&(e[Symbol.toStringTag]===`Blob`||e[Symbol.toStringTag]===`File`)}if(n.exports={isBlob:l,isValidStatusCode:s,isValidUTF8:c,tokenChars:o},i)n.exports.isValidUTF8=function(e){return e.length<24?c(e):i(e)};else if(!process.env.WS_NO_UTF_8_VALIDATE)try{let e=t(`utf-8-validate`);n.exports.isValidUTF8=function(t){return t.length<32?c(t):e(t)}}catch{}})),c=n(((e,n)=>{let{Writable:a}=t(`stream`),c=o(),{BINARY_TYPES:l,EMPTY_BUFFER:u,kStatusCode:d,kWebSocket:f}=r(),{concat:p,toArrayBuffer:m,unmask:h}=i(),{isValidStatusCode:g,isValidUTF8:_}=s(),v=Buffer[Symbol.species];n.exports=class extends a{constructor(e={}){super(),this._allowSynchronousEvents=e.allowSynchronousEvents===void 0||e.allowSynchronousEvents,this._binaryType=e.binaryType||l[0],this._extensions=e.extensions||{},this._isServer=!!e.isServer,this._maxPayload=e.maxPayload|0,this._skipUTF8Validation=!!e.skipUTF8Validation,this[f]=void 0,this._bufferedBytes=0,this._buffers=[],this._compressed=!1,this._payloadLength=0,this._mask=void 0,this._fragmented=0,this._masked=!1,this._fin=!1,this._opcode=0,this._totalPayloadLength=0,this._messageLength=0,this._fragments=[],this._errored=!1,this._loop=!1,this._state=0}_write(e,t,n){if(this._opcode===8&&this._state==0)return n();this._bufferedBytes+=e.length,this._buffers.push(e),this.startLoop(n)}consume(e){if(this._bufferedBytes-=e,e===this._buffers[0].length)return this._buffers.shift();if(e<this._buffers[0].length){let t=this._buffers[0];return this._buffers[0]=new v(t.buffer,t.byteOffset+e,t.length-e),new v(t.buffer,t.byteOffset,e)}let t=Buffer.allocUnsafe(e);do{let n=this._buffers[0],r=t.length-e;e>=n.length?t.set(this._buffers.shift(),r):(t.set(new Uint8Array(n.buffer,n.byteOffset,e),r),this._buffers[0]=new v(n.buffer,n.byteOffset+e,n.length-e)),e-=n.length}while(e>0);return t}startLoop(e){this._loop=!0;do switch(this._state){case 0:this.getInfo(e);break;case 1:this.getPayloadLength16(e);break;case 2:this.getPayloadLength64(e);break;case 3:this.getMask();break;case 4:this.getData(e);break;case 5:case 6:this._loop=!1;return}while(this._loop);this._errored||e()}getInfo(e){if(this._bufferedBytes<2){this._loop=!1;return}let t=this.consume(2);if(t[0]&48){e(this.createError(RangeError,`RSV2 and RSV3 must be clear`,!0,1002,`WS_ERR_UNEXPECTED_RSV_2_3`));return}let n=(t[0]&64)==64;if(n&&!this._extensions[c.extensionName]){e(this.createError(RangeError,`RSV1 must be clear`,!0,1002,`WS_ERR_UNEXPECTED_RSV_1`));return}if(this._fin=(t[0]&128)==128,this._opcode=t[0]&15,this._payloadLength=t[1]&127,this._opcode===0){if(n){e(this.createError(RangeError,`RSV1 must be clear`,!0,1002,`WS_ERR_UNEXPECTED_RSV_1`));return}if(!this._fragmented){e(this.createError(RangeError,`invalid opcode 0`,!0,1002,`WS_ERR_INVALID_OPCODE`));return}this._opcode=this._fragmented}else if(this._opcode===1||this._opcode===2){if(this._fragmented){e(this.createError(RangeError,`invalid opcode ${this._opcode}`,!0,1002,`WS_ERR_INVALID_OPCODE`));return}this._compressed=n}else if(this._opcode>7&&this._opcode<11){if(!this._fin){e(this.createError(RangeError,`FIN must be set`,!0,1002,`WS_ERR_EXPECTED_FIN`));return}if(n){e(this.createError(RangeError,`RSV1 must be clear`,!0,1002,`WS_ERR_UNEXPECTED_RSV_1`));return}if(this._payloadLength>125||this._opcode===8&&this._payloadLength===1){e(this.createError(RangeError,`invalid payload length ${this._payloadLength}`,!0,1002,`WS_ERR_INVALID_CONTROL_PAYLOAD_LENGTH`));return}}else{e(this.createError(RangeError,`invalid opcode ${this._opcode}`,!0,1002,`WS_ERR_INVALID_OPCODE`));return}if(!this._fin&&!this._fragmented&&(this._fragmented=this._opcode),this._masked=(t[1]&128)==128,this._isServer){if(!this._masked){e(this.createError(RangeError,`MASK must be set`,!0,1002,`WS_ERR_EXPECTED_MASK`));return}}else if(this._masked){e(this.createError(RangeError,`MASK must be clear`,!0,1002,`WS_ERR_UNEXPECTED_MASK`));return}this._payloadLength===126?this._state=1:this._payloadLength===127?this._state=2:this.haveLength(e)}getPayloadLength16(e){if(this._bufferedBytes<2){this._loop=!1;return}this._payloadLength=this.consume(2).readUInt16BE(0),this.haveLength(e)}getPayloadLength64(e){if(this._bufferedBytes<8){this._loop=!1;return}let t=this.consume(8),n=t.readUInt32BE(0);if(n>2**21-1){e(this.createError(RangeError,`Unsupported WebSocket frame: payload length > 2^53 - 1`,!1,1009,`WS_ERR_UNSUPPORTED_DATA_PAYLOAD_LENGTH`));return}this._payloadLength=n*2**32+t.readUInt32BE(4),this.haveLength(e)}haveLength(e){if(this._payloadLength&&this._opcode<8&&(this._totalPayloadLength+=this._payloadLength,this._totalPayloadLength>this._maxPayload&&this._maxPayload>0)){e(this.createError(RangeError,`Max payload size exceeded`,!1,1009,`WS_ERR_UNSUPPORTED_MESSAGE_LENGTH`));return}this._masked?this._state=3:this._state=4}getMask(){if(this._bufferedBytes<4){this._loop=!1;return}this._mask=this.consume(4),this._state=4}getData(e){let t=u;if(this._payloadLength){if(this._bufferedBytes<this._payloadLength){this._loop=!1;return}t=this.consume(this._payloadLength),this._masked&&(this._mask[0]|this._mask[1]|this._mask[2]|this._mask[3])!==0&&h(t,this._mask)}if(this._opcode>7){this.controlMessage(t,e);return}if(this._compressed){this._state=5,this.decompress(t,e);return}t.length&&(this._messageLength=this._totalPayloadLength,this._fragments.push(t)),this.dataMessage(e)}decompress(e,t){this._extensions[c.extensionName].decompress(e,this._fin,(e,n)=>{if(e)return t(e);if(n.length){if(this._messageLength+=n.length,this._messageLength>this._maxPayload&&this._maxPayload>0){t(this.createError(RangeError,`Max payload size exceeded`,!1,1009,`WS_ERR_UNSUPPORTED_MESSAGE_LENGTH`));return}this._fragments.push(n)}this.dataMessage(t),this._state===0&&this.startLoop(t)})}dataMessage(e){if(!this._fin){this._state=0;return}let t=this._messageLength,n=this._fragments;if(this._totalPayloadLength=0,this._messageLength=0,this._fragmented=0,this._fragments=[],this._opcode===2){let r;r=this._binaryType===`nodebuffer`?p(n,t):this._binaryType===`arraybuffer`?m(p(n,t)):this._binaryType===`blob`?new Blob(n):n,this._allowSynchronousEvents?(this.emit(`message`,r,!0),this._state=0):(this._state=6,setImmediate(()=>{this.emit(`message`,r,!0),this._state=0,this.startLoop(e)}))}else{let r=p(n,t);if(!this._skipUTF8Validation&&!_(r)){e(this.createError(Error,`invalid UTF-8 sequence`,!0,1007,`WS_ERR_INVALID_UTF8`));return}this._state===5||this._allowSynchronousEvents?(this.emit(`message`,r,!1),this._state=0):(this._state=6,setImmediate(()=>{this.emit(`message`,r,!1),this._state=0,this.startLoop(e)}))}}controlMessage(e,t){if(this._opcode===8){if(e.length===0)this._loop=!1,this.emit(`conclude`,1005,u),this.end();else{let n=e.readUInt16BE(0);if(!g(n)){t(this.createError(RangeError,`invalid status code ${n}`,!0,1002,`WS_ERR_INVALID_CLOSE_CODE`));return}let r=new v(e.buffer,e.byteOffset+2,e.length-2);if(!this._skipUTF8Validation&&!_(r)){t(this.createError(Error,`invalid UTF-8 sequence`,!0,1007,`WS_ERR_INVALID_UTF8`));return}this._loop=!1,this.emit(`conclude`,n,r),this.end()}this._state=0;return}this._allowSynchronousEvents?(this.emit(this._opcode===9?`ping`:`pong`,e),this._state=0):(this._state=6,setImmediate(()=>{this.emit(this._opcode===9?`ping`:`pong`,e),this._state=0,this.startLoop(t)}))}createError(e,t,n,r,i){this._loop=!1,this._errored=!0;let a=new e(n?`Invalid WebSocket frame: ${t}`:t);return Error.captureStackTrace(a,this.createError),a.code=i,a[d]=r,a}}})),l=n(((e,n)=>{let{Duplex:a}=t(`stream`),{randomFillSync:c}=t(`crypto`),l=o(),{EMPTY_BUFFER:u,kWebSocket:d,NOOP:f}=r(),{isBlob:p,isValidStatusCode:m}=s(),{mask:h,toBuffer:g}=i(),_=Symbol(`kByteLength`),v=Buffer.alloc(4),y=8*1024,b,x=y;n.exports=class e{constructor(e,t,n){this._extensions=t||{},n&&(this._generateMask=n,this._maskBuffer=Buffer.alloc(4)),this._socket=e,this._firstFragment=!0,this._compress=!1,this._bufferedBytes=0,this._queue=[],this._state=0,this.onerror=f,this[d]=void 0}static frame(e,t){let n,r=!1,i=2,a=!1;t.mask&&(n=t.maskBuffer||v,t.generateMask?t.generateMask(n):(x===y&&(b===void 0&&(b=Buffer.alloc(y)),c(b,0,y),x=0),n[0]=b[x++],n[1]=b[x++],n[2]=b[x++],n[3]=b[x++]),a=(n[0]|n[1]|n[2]|n[3])===0,i=6);let o;typeof e==`string`?(!t.mask||a)&&t[_]!==void 0?o=t[_]:(e=Buffer.from(e),o=e.length):(o=e.length,r=t.mask&&t.readOnly&&!a);let s=o;o>=65536?(i+=8,s=127):o>125&&(i+=2,s=126);let l=Buffer.allocUnsafe(r?o+i:i);return l[0]=t.fin?t.opcode|128:t.opcode,t.rsv1&&(l[0]|=64),l[1]=s,s===126?l.writeUInt16BE(o,2):s===127&&(l[2]=l[3]=0,l.writeUIntBE(o,4,6)),!t.mask||(l[1]|=128,l[i-4]=n[0],l[i-3]=n[1],l[i-2]=n[2],l[i-1]=n[3],a)?[l,e]:r?(h(e,n,l,i,o),[l]):(h(e,n,e,0,o),[l,e])}close(t,n,r,i){let a;if(t===void 0)a=u;else if(typeof t!=`number`||!m(t))throw TypeError(`First argument must be a valid error code number`);else if(n===void 0||!n.length)a=Buffer.allocUnsafe(2),a.writeUInt16BE(t,0);else{let e=Buffer.byteLength(n);if(e>123)throw RangeError(`The message must not be greater than 123 bytes`);a=Buffer.allocUnsafe(2+e),a.writeUInt16BE(t,0),typeof n==`string`?a.write(n,2):a.set(n,2)}let o={[_]:a.length,fin:!0,generateMask:this._generateMask,mask:r,maskBuffer:this._maskBuffer,opcode:8,readOnly:!1,rsv1:!1};this._state===0?this.sendFrame(e.frame(a,o),i):this.enqueue([this.dispatch,a,!1,o,i])}ping(t,n,r){let i,a;if(typeof t==`string`?(i=Buffer.byteLength(t),a=!1):p(t)?(i=t.size,a=!1):(t=g(t),i=t.length,a=g.readOnly),i>125)throw RangeError(`The data size must not be greater than 125 bytes`);let o={[_]:i,fin:!0,generateMask:this._generateMask,mask:n,maskBuffer:this._maskBuffer,opcode:9,readOnly:a,rsv1:!1};p(t)?this._state===0?this.getBlobData(t,!1,o,r):this.enqueue([this.getBlobData,t,!1,o,r]):this._state===0?this.sendFrame(e.frame(t,o),r):this.enqueue([this.dispatch,t,!1,o,r])}pong(t,n,r){let i,a;if(typeof t==`string`?(i=Buffer.byteLength(t),a=!1):p(t)?(i=t.size,a=!1):(t=g(t),i=t.length,a=g.readOnly),i>125)throw RangeError(`The data size must not be greater than 125 bytes`);let o={[_]:i,fin:!0,generateMask:this._generateMask,mask:n,maskBuffer:this._maskBuffer,opcode:10,readOnly:a,rsv1:!1};p(t)?this._state===0?this.getBlobData(t,!1,o,r):this.enqueue([this.getBlobData,t,!1,o,r]):this._state===0?this.sendFrame(e.frame(t,o),r):this.enqueue([this.dispatch,t,!1,o,r])}send(e,t,n){let r=this._extensions[l.extensionName],i=t.binary?2:1,a=t.compress,o,s;typeof e==`string`?(o=Buffer.byteLength(e),s=!1):p(e)?(o=e.size,s=!1):(e=g(e),o=e.length,s=g.readOnly),this._firstFragment?(this._firstFragment=!1,a&&r&&r.params[r._isServer?`server_no_context_takeover`:`client_no_context_takeover`]&&(a=o>=r._threshold),this._compress=a):(a=!1,i=0),t.fin&&(this._firstFragment=!0);let c={[_]:o,fin:t.fin,generateMask:this._generateMask,mask:t.mask,maskBuffer:this._maskBuffer,opcode:i,readOnly:s,rsv1:a};p(e)?this._state===0?this.getBlobData(e,this._compress,c,n):this.enqueue([this.getBlobData,e,this._compress,c,n]):this._state===0?this.dispatch(e,this._compress,c,n):this.enqueue([this.dispatch,e,this._compress,c,n])}getBlobData(t,n,r,i){this._bufferedBytes+=r[_],this._state=2,t.arrayBuffer().then(t=>{if(this._socket.destroyed){let e=Error(`The socket was closed while the blob was being read`);process.nextTick(S,this,e,i);return}this._bufferedBytes-=r[_];let a=g(t);n?this.dispatch(a,n,r,i):(this._state=0,this.sendFrame(e.frame(a,r),i),this.dequeue())}).catch(e=>{process.nextTick(C,this,e,i)})}dispatch(t,n,r,i){if(!n){this.sendFrame(e.frame(t,r),i);return}let a=this._extensions[l.extensionName];this._bufferedBytes+=r[_],this._state=1,a.compress(t,r.fin,(t,n)=>{if(this._socket.destroyed){let e=Error(`The socket was closed while data was being compressed`);S(this,e,i);return}this._bufferedBytes-=r[_],this._state=0,r.readOnly=!1,this.sendFrame(e.frame(n,r),i),this.dequeue()})}dequeue(){for(;this._state===0&&this._queue.length;){let e=this._queue.shift();this._bufferedBytes-=e[3][_],Reflect.apply(e[0],this,e.slice(1))}}enqueue(e){this._bufferedBytes+=e[3][_],this._queue.push(e)}sendFrame(e,t){e.length===2?(this._socket.cork(),this._socket.write(e[0]),this._socket.write(e[1],t),this._socket.uncork()):this._socket.write(e[0],t)}};function S(e,t,n){typeof n==`function`&&n(t);for(let n=0;n<e._queue.length;n++){let r=e._queue[n],i=r[r.length-1];typeof i==`function`&&i(t)}}function C(e,t,n){S(e,t,n),e.onerror(t)}})),u=n(((e,t)=>{let{kForOnEventAttribute:n,kListener:i}=r(),a=Symbol(`kCode`),o=Symbol(`kData`),s=Symbol(`kError`),c=Symbol(`kMessage`),l=Symbol(`kReason`),u=Symbol(`kTarget`),d=Symbol(`kType`),f=Symbol(`kWasClean`);var p=class{constructor(e){this[u]=null,this[d]=e}get target(){return this[u]}get type(){return this[d]}};Object.defineProperty(p.prototype,"target",{enumerable:!0}),Object.defineProperty(p.prototype,"type",{enumerable:!0});var m=class extends p{constructor(e,t={}){super(e),this[a]=t.code===void 0?0:t.code,this[l]=t.reason===void 0?``:t.reason,this[f]=t.wasClean!==void 0&&t.wasClean}get code(){return this[a]}get reason(){return this[l]}get wasClean(){return this[f]}};Object.defineProperty(m.prototype,"code",{enumerable:!0}),Object.defineProperty(m.prototype,"reason",{enumerable:!0}),Object.defineProperty(m.prototype,"wasClean",{enumerable:!0});var h=class extends p{constructor(e,t={}){super(e),this[s]=t.error===void 0?null:t.error,this[c]=t.message===void 0?``:t.message}get error(){return this[s]}get message(){return this[c]}};Object.defineProperty(h.prototype,"error",{enumerable:!0}),Object.defineProperty(h.prototype,"message",{enumerable:!0});var g=class extends p{constructor(e,t={}){super(e),this[o]=t.data===void 0?null:t.data}get data(){return this[o]}};Object.defineProperty(g.prototype,"data",{enumerable:!0}),t.exports={CloseEvent:m,ErrorEvent:h,Event:p,EventTarget:{addEventListener(e,t,r={}){for(let a of this.listeners(e))if(!r[n]&&a[i]===t&&!a[n])return;let a;if(e===`message`)a=function(e,n){let r=new g(`message`,{data:n?e:e.toString()});r[u]=this,_(t,this,r)};else if(e===`close`)a=function(e,n){let r=new m(`close`,{code:e,reason:n.toString(),wasClean:this._closeFrameReceived&&this._closeFrameSent});r[u]=this,_(t,this,r)};else if(e===`error`)a=function(e){let n=new h(`error`,{error:e,message:e.message});n[u]=this,_(t,this,n)};else if(e===`open`)a=function(){let e=new p(`open`);e[u]=this,_(t,this,e)};else return;a[n]=!!r[n],a[i]=t,r.once?this.once(e,a):this.on(e,a)},removeEventListener(e,t){for(let r of this.listeners(e))if(r[i]===t&&!r[n]){this.removeListener(e,r);break}}},MessageEvent:g};function _(e,t,n){typeof e==`object`&&e.handleEvent?e.handleEvent.call(e,n):e.call(t,n)}})),d=n(((e,t)=>{let{tokenChars:n}=s();function r(e,t,n){e[t]===void 0?e[t]=[n]:e[t].push(n)}function i(e){let t=Object.create(null),i=Object.create(null),a=!1,o=!1,s=!1,c,l,u=-1,d=-1,f=-1,p=0;for(;p<e.length;p++)if(d=e.charCodeAt(p),c===void 0)if(f===-1&&n[d]===1)u===-1&&(u=p);else if(p!==0&&(d===32||d===9))f===-1&&u!==-1&&(f=p);else if(d===59||d===44){if(u===-1)throw SyntaxError(`Unexpected character at index ${p}`);f===-1&&(f=p);let n=e.slice(u,f);d===44?(r(t,n,i),i=Object.create(null)):c=n,u=f=-1}else throw SyntaxError(`Unexpected character at index ${p}`);else if(l===void 0)if(f===-1&&n[d]===1)u===-1&&(u=p);else if(d===32||d===9)f===-1&&u!==-1&&(f=p);else if(d===59||d===44){if(u===-1)throw SyntaxError(`Unexpected character at index ${p}`);f===-1&&(f=p),r(i,e.slice(u,f),!0),d===44&&(r(t,c,i),i=Object.create(null),c=void 0),u=f=-1}else if(d===61&&u!==-1&&f===-1)l=e.slice(u,p),u=f=-1;else throw SyntaxError(`Unexpected character at index ${p}`);else if(o){if(n[d]!==1)throw SyntaxError(`Unexpected character at index ${p}`);u===-1?u=p:a||=!0,o=!1}else if(s)if(n[d]===1)u===-1&&(u=p);else if(d===34&&u!==-1)s=!1,f=p;else if(d===92)o=!0;else throw SyntaxError(`Unexpected character at index ${p}`);else if(d===34&&e.charCodeAt(p-1)===61)s=!0;else if(f===-1&&n[d]===1)u===-1&&(u=p);else if(u!==-1&&(d===32||d===9))f===-1&&(f=p);else if(d===59||d===44){if(u===-1)throw SyntaxError(`Unexpected character at index ${p}`);f===-1&&(f=p);let n=e.slice(u,f);a&&=(n=n.replace(/\\/g,``),!1),r(i,l,n),d===44&&(r(t,c,i),i=Object.create(null),c=void 0),l=void 0,u=f=-1}else throw SyntaxError(`Unexpected character at index ${p}`);if(u===-1||s||d===32||d===9)throw SyntaxError(`Unexpected end of input`);f===-1&&(f=p);let m=e.slice(u,f);return c===void 0?r(t,m,i):(l===void 0?r(i,m,!0):a?r(i,l,m.replace(/\\/g,``)):r(i,l,m),r(t,c,i)),t}function a(e){return Object.keys(e).map(t=>{let n=e[t];return Array.isArray(n)||(n=[n]),n.map(e=>[t].concat(Object.keys(e).map(t=>{let n=e[t];return Array.isArray(n)||(n=[n]),n.map(e=>e===!0?t:`${t}=${e}`).join(`; `)})).join(`; `)).join(`, `)}).join(`, `)}t.exports={format:a,parse:i}})),f=n(((e,n)=>{let a=t(`events`),f=t(`https`),p=t(`http`),m=t(`net`),h=t(`tls`),{randomBytes:g,createHash:_}=t(`crypto`),{Duplex:v,Readable:y}=t(`stream`),{URL:b}=t(`url`),x=o(),S=c(),C=l(),{isBlob:w}=s(),{BINARY_TYPES:T,EMPTY_BUFFER:E,GUID:D,kForOnEventAttribute:O,kListener:k,kStatusCode:ee,kWebSocket:A,NOOP:j}=r(),{EventTarget:{addEventListener:M,removeEventListener:N}}=u(),{format:P,parse:F}=d(),{toBuffer:I}=i(),L=Symbol(`kAborted`),R=[8,13],z=[`CONNECTING`,`OPEN`,`CLOSING`,`CLOSED`],B=/^[!#$%&'*+\-.0-9A-Z^_`|a-z~]+$/;var V=class e extends a{constructor(t,n,r){super(),this._binaryType=T[0],this._closeCode=1006,this._closeFrameReceived=!1,this._closeFrameSent=!1,this._closeMessage=E,this._closeTimer=null,this._errorEmitted=!1,this._extensions={},this._paused=!1,this._protocol=``,this._readyState=e.CONNECTING,this._receiver=null,this._sender=null,this._socket=null,t===null?(this._autoPong=r.autoPong,this._isServer=!0):(this._bufferedAmount=0,this._isServer=!1,this._redirects=0,n===void 0?n=[]:Array.isArray(n)||(typeof n==`object`&&n?(r=n,n=[]):n=[n]),H(this,t,n,r))}get binaryType(){return this._binaryType}set binaryType(e){T.includes(e)&&(this._binaryType=e,this._receiver&&(this._receiver._binaryType=e))}get bufferedAmount(){return this._socket?this._socket._writableState.length+this._sender._bufferedBytes:this._bufferedAmount}get extensions(){return Object.keys(this._extensions).join()}get isPaused(){return this._paused}get onclose(){return null}get onerror(){return null}get onopen(){return null}get onmessage(){return null}get protocol(){return this._protocol}get readyState(){return this._readyState}get url(){return this._url}setSocket(t,n,r){let i=new S({allowSynchronousEvents:r.allowSynchronousEvents,binaryType:this.binaryType,extensions:this._extensions,isServer:this._isServer,maxPayload:r.maxPayload,skipUTF8Validation:r.skipUTF8Validation}),a=new C(t,this._extensions,r.generateMask);this._receiver=i,this._sender=a,this._socket=t,i[A]=this,a[A]=this,t[A]=this,i.on(`conclude`,ne),i.on(`drain`,re),i.on(`error`,ie),i.on(`message`,ae),i.on(`ping`,oe),i.on(`pong`,se),a.onerror=ce,t.setTimeout&&t.setTimeout(0),t.setNoDelay&&t.setNoDelay(),n.length>0&&t.unshift(n),t.on(`close`,X),t.on(`data`,Z),t.on(`end`,Q),t.on(`error`,$),this._readyState=e.OPEN,this.emit(`open`)}emitClose(){if(!this._socket){this._readyState=e.CLOSED,this.emit(`close`,this._closeCode,this._closeMessage);return}this._extensions[x.extensionName]&&this._extensions[x.extensionName].cleanup(),this._receiver.removeAllListeners(),this._readyState=e.CLOSED,this.emit(`close`,this._closeCode,this._closeMessage)}close(t,n){if(this.readyState!==e.CLOSED){if(this.readyState===e.CONNECTING){G(this,this._req,`WebSocket was closed before the connection was established`);return}if(this.readyState===e.CLOSING){this._closeFrameSent&&(this._closeFrameReceived||this._receiver._writableState.errorEmitted)&&this._socket.end();return}this._readyState=e.CLOSING,this._sender.close(t,n,!this._isServer,e=>{e||(this._closeFrameSent=!0,(this._closeFrameReceived||this._receiver._writableState.errorEmitted)&&this._socket.end())}),Y(this)}}pause(){this.readyState===e.CONNECTING||this.readyState===e.CLOSED||(this._paused=!0,this._socket.pause())}ping(t,n,r){if(this.readyState===e.CONNECTING)throw Error(`WebSocket is not open: readyState 0 (CONNECTING)`);if(typeof t==`function`?(r=t,t=n=void 0):typeof n==`function`&&(r=n,n=void 0),typeof t==`number`&&(t=t.toString()),this.readyState!==e.OPEN){K(this,t,r);return}n===void 0&&(n=!this._isServer),this._sender.ping(t||E,n,r)}pong(t,n,r){if(this.readyState===e.CONNECTING)throw Error(`WebSocket is not open: readyState 0 (CONNECTING)`);if(typeof t==`function`?(r=t,t=n=void 0):typeof n==`function`&&(r=n,n=void 0),typeof t==`number`&&(t=t.toString()),this.readyState!==e.OPEN){K(this,t,r);return}n===void 0&&(n=!this._isServer),this._sender.pong(t||E,n,r)}resume(){this.readyState===e.CONNECTING||this.readyState===e.CLOSED||(this._paused=!1,this._receiver._writableState.needDrain||this._socket.resume())}send(t,n,r){if(this.readyState===e.CONNECTING)throw Error(`WebSocket is not open: readyState 0 (CONNECTING)`);if(typeof n==`function`&&(r=n,n={}),typeof t==`number`&&(t=t.toString()),this.readyState!==e.OPEN){K(this,t,r);return}let i={binary:typeof t!=`string`,mask:!this._isServer,compress:!0,fin:!0,...n};this._extensions[x.extensionName]||(i.compress=!1),this._sender.send(t||E,i,r)}terminate(){if(this.readyState!==e.CLOSED){if(this.readyState===e.CONNECTING){G(this,this._req,`WebSocket was closed before the connection was established`);return}this._socket&&(this._readyState=e.CLOSING,this._socket.destroy())}}};Object.defineProperty(V,"CONNECTING",{enumerable:!0,value:z.indexOf(`CONNECTING`)}),Object.defineProperty(V.prototype,"CONNECTING",{enumerable:!0,value:z.indexOf(`CONNECTING`)}),Object.defineProperty(V,"OPEN",{enumerable:!0,value:z.indexOf(`OPEN`)}),Object.defineProperty(V.prototype,"OPEN",{enumerable:!0,value:z.indexOf(`OPEN`)}),Object.defineProperty(V,"CLOSING",{enumerable:!0,value:z.indexOf(`CLOSING`)}),Object.defineProperty(V.prototype,"CLOSING",{enumerable:!0,value:z.indexOf(`CLOSING`)}),Object.defineProperty(V,"CLOSED",{enumerable:!0,value:z.indexOf(`CLOSED`)}),Object.defineProperty(V.prototype,"CLOSED",{enumerable:!0,value:z.indexOf(`CLOSED`)}),[`binaryType`,`bufferedAmount`,`extensions`,`isPaused`,`protocol`,`readyState`,`url`].forEach(e=>{Object.defineProperty(V.prototype,e,{enumerable:!0})}),[`open`,`error`,`close`,`message`].forEach(e=>{Object.defineProperty(V.prototype,`on${e}`,{enumerable:!0,get(){for(let t of this.listeners(e))if(t[O])return t[k];return null},set(t){for(let t of this.listeners(e))if(t[O]){this.removeListener(e,t);break}typeof t==`function`&&this.addEventListener(e,t,{[O]:!0})}})}),V.prototype.addEventListener=M,V.prototype.removeEventListener=N,n.exports=V;function H(e,t,n,r){let i={allowSynchronousEvents:!0,autoPong:!0,protocolVersion:R[1],maxPayload:100*1024*1024,skipUTF8Validation:!1,perMessageDeflate:!0,followRedirects:!1,maxRedirects:10,...r,socketPath:void 0,hostname:void 0,protocol:void 0,timeout:void 0,method:`GET`,host:void 0,path:void 0,port:void 0};if(e._autoPong=i.autoPong,!R.includes(i.protocolVersion))throw RangeError(`Unsupported protocol version: ${i.protocolVersion} (supported versions: ${R.join(`, `)})`);let a;if(t instanceof b)a=t;else try{a=new b(t)}catch{throw SyntaxError(`Invalid URL: ${t}`)}a.protocol===`http:`?a.protocol=`ws:`:a.protocol===`https:`&&(a.protocol=`wss:`),e._url=a.href;let o=a.protocol===`wss:`,s=a.protocol===`ws+unix:`,c;if(a.protocol!==`ws:`&&!o&&!s?c=`The URL's protocol must be one of "ws:", "wss:", "http:", "https:", or "ws+unix:"`:s&&!a.pathname?c=`The URL's pathname is empty`:a.hash&&(c=`The URL contains a fragment identifier`),c){let t=SyntaxError(c);if(e._redirects===0)throw t;U(e,t);return}let l=o?443:80,u=g(16).toString(`base64`),d=o?f.request:p.request,m=new Set,h;if(i.createConnection=i.createConnection||(o?te:W),i.defaultPort=i.defaultPort||l,i.port=a.port||l,i.host=a.hostname.startsWith(`[`)?a.hostname.slice(1,-1):a.hostname,i.headers={...i.headers,"Sec-WebSocket-Version":i.protocolVersion,"Sec-WebSocket-Key":u,Connection:`Upgrade`,Upgrade:`websocket`},i.path=a.pathname+a.search,i.timeout=i.handshakeTimeout,i.perMessageDeflate&&(h=new x(i.perMessageDeflate===!0?{}:i.perMessageDeflate,!1,i.maxPayload),i.headers[`Sec-WebSocket-Extensions`]=P({[x.extensionName]:h.offer()})),n.length){for(let e of n){if(typeof e!=`string`||!B.test(e)||m.has(e))throw SyntaxError(`An invalid or duplicated subprotocol was specified`);m.add(e)}i.headers[`Sec-WebSocket-Protocol`]=n.join(`,`)}if(i.origin&&(i.protocolVersion<13?i.headers[`Sec-WebSocket-Origin`]=i.origin:i.headers.Origin=i.origin),(a.username||a.password)&&(i.auth=`${a.username}:${a.password}`),s){let e=i.path.split(`:`);i.socketPath=e[0],i.path=e[1]}let v;if(i.followRedirects){if(e._redirects===0){e._originalIpc=s,e._originalSecure=o,e._originalHostOrSocketPath=s?i.socketPath:a.host;let t=r&&r.headers;if(r={...r,headers:{}},t)for(let[e,n]of Object.entries(t))r.headers[e.toLowerCase()]=n}else if(e.listenerCount(`redirect`)===0){let t=s?e._originalIpc?i.socketPath===e._originalHostOrSocketPath:!1:!e._originalIpc&&a.host===e._originalHostOrSocketPath;(!t||e._originalSecure&&!o)&&(delete i.headers.authorization,delete i.headers.cookie,t||delete i.headers.host,i.auth=void 0)}i.auth&&!r.headers.authorization&&(r.headers.authorization=`Basic `+Buffer.from(i.auth).toString(`base64`)),v=e._req=d(i),e._redirects&&e.emit(`redirect`,e.url,v)}else v=e._req=d(i);i.timeout&&v.on(`timeout`,()=>{G(e,v,`Opening handshake has timed out`)}),v.on(`error`,t=>{v===null||v[L]||(v=e._req=null,U(e,t))}),v.on(`response`,a=>{let o=a.headers.location,s=a.statusCode;if(o&&i.followRedirects&&s>=300&&s<400){if(++e._redirects>i.maxRedirects){G(e,v,`Maximum redirects exceeded`);return}v.abort();let a;try{a=new b(o,t)}catch{U(e,SyntaxError(`Invalid URL: ${o}`));return}H(e,a,n,r)}else e.emit(`unexpected-response`,v,a)||G(e,v,`Unexpected server response: ${a.statusCode}`)}),v.on(`upgrade`,(t,n,r)=>{if(e.emit(`upgrade`,t),e.readyState!==V.CONNECTING)return;v=e._req=null;let a=t.headers.upgrade;if(a===void 0||a.toLowerCase()!==`websocket`){G(e,n,`Invalid Upgrade header`);return}let o=_(`sha1`).update(u+D).digest(`base64`);if(t.headers[`sec-websocket-accept`]!==o){G(e,n,`Invalid Sec-WebSocket-Accept header`);return}let s=t.headers[`sec-websocket-protocol`],c;if(s===void 0?m.size&&(c=`Server sent no subprotocol`):m.size?m.has(s)||(c=`Server sent an invalid subprotocol`):c=`Server sent a subprotocol but none was requested`,c){G(e,n,c);return}s&&(e._protocol=s);let l=t.headers[`sec-websocket-extensions`];if(l!==void 0){if(!h){G(e,n,`Server sent a Sec-WebSocket-Extensions header but no extension was requested`);return}let t;try{t=F(l)}catch{G(e,n,`Invalid Sec-WebSocket-Extensions header`);return}let r=Object.keys(t);if(r.length!==1||r[0]!==x.extensionName){G(e,n,`Server indicated an extension that was not requested`);return}try{h.accept(t[x.extensionName])}catch{G(e,n,`Invalid Sec-WebSocket-Extensions header`);return}e._extensions[x.extensionName]=h}e.setSocket(n,r,{allowSynchronousEvents:i.allowSynchronousEvents,generateMask:i.generateMask,maxPayload:i.maxPayload,skipUTF8Validation:i.skipUTF8Validation})}),i.finishRequest?i.finishRequest(v,e):v.end()}function U(e,t){e._readyState=V.CLOSING,e._errorEmitted=!0,e.emit(`error`,t),e.emitClose()}function W(e){return e.path=e.socketPath,m.connect(e)}function te(e){return e.path=void 0,!e.servername&&e.servername!==``&&(e.servername=m.isIP(e.host)?``:e.host),h.connect(e)}function G(e,t,n){e._readyState=V.CLOSING;let r=Error(n);Error.captureStackTrace(r,G),t.setHeader?(t[L]=!0,t.abort(),t.socket&&!t.socket.destroyed&&t.socket.destroy(),process.nextTick(U,e,r)):(t.destroy(r),t.once(`error`,e.emit.bind(e,`error`)),t.once(`close`,e.emitClose.bind(e)))}function K(e,t,n){if(t){let n=w(t)?t.size:I(t).length;e._socket?e._sender._bufferedBytes+=n:e._bufferedAmount+=n}if(n){let t=Error(`WebSocket is not open: readyState ${e.readyState} (${z[e.readyState]})`);process.nextTick(n,t)}}function ne(e,t){let n=this[A];n._closeFrameReceived=!0,n._closeMessage=t,n._closeCode=e,n._socket[A]!==void 0&&(n._socket.removeListener(`data`,Z),process.nextTick(J,n._socket),e===1005?n.close():n.close(e,t))}function re(){let e=this[A];e.isPaused||e._socket.resume()}function ie(e){let t=this[A];t._socket[A]!==void 0&&(t._socket.removeListener(`data`,Z),process.nextTick(J,t._socket),t.close(e[ee])),t._errorEmitted||(t._errorEmitted=!0,t.emit(`error`,e))}function q(){this[A].emitClose()}function ae(e,t){this[A].emit(`message`,e,t)}function oe(e){let t=this[A];t._autoPong&&t.pong(e,!this._isServer,j),t.emit(`ping`,e)}function se(e){this[A].emit(`pong`,e)}function J(e){e.resume()}function ce(e){let t=this[A];t.readyState!==V.CLOSED&&(t.readyState===V.OPEN&&(t._readyState=V.CLOSING,Y(t)),this._socket.end(),t._errorEmitted||(t._errorEmitted=!0,t.emit(`error`,e)))}function Y(e){e._closeTimer=setTimeout(e._socket.destroy.bind(e._socket),3e4)}function X(){let e=this[A];this.removeListener(`close`,X),this.removeListener(`data`,Z),this.removeListener(`end`,Q),e._readyState=V.CLOSING;let t;!this._readableState.endEmitted&&!e._closeFrameReceived&&!e._receiver._writableState.errorEmitted&&(t=e._socket.read())!==null&&e._receiver.write(t),e._receiver.end(),this[A]=void 0,clearTimeout(e._closeTimer),e._receiver._writableState.finished||e._receiver._writableState.errorEmitted?e.emitClose():(e._receiver.on(`error`,q),e._receiver.on(`finish`,q))}function Z(e){this[A]._receiver.write(e)||this.pause()}function Q(){let e=this[A];e._readyState=V.CLOSING,e._receiver.end(),this.end()}function $(){let e=this[A];this.removeListener(`error`,$),this.on(`error`,j),e&&(e._readyState=V.CLOSING,this.destroy())}})),p=n(((e,n)=>{f();let{Duplex:r}=t(`stream`);function i(e){e.emit(`close`)}function a(){!this.destroyed&&this._writableState.finished&&this.destroy()}function o(e){this.removeListener(`error`,o),this.destroy(),this.listenerCount(`error`)===0&&this.emit(`error`,e)}function s(e,t){let n=!0,s=new r({...t,autoDestroy:!1,emitClose:!1,objectMode:!1,writableObjectMode:!1});return e.on(`message`,function(t,n){let r=!n&&s._readableState.objectMode?t.toString():t;s.push(r)||e.pause()}),e.once(`error`,function(e){s.destroyed||(n=!1,s.destroy(e))}),e.once(`close`,function(){s.destroyed||s.push(null)}),s._destroy=function(t,r){if(e.readyState===e.CLOSED){r(t),process.nextTick(i,s);return}let a=!1;e.once(`error`,function(e){a=!0,r(e)}),e.once(`close`,function(){a||r(t),process.nextTick(i,s)}),n&&e.terminate()},s._final=function(t){if(e.readyState===e.CONNECTING){e.once(`open`,function(){s._final(t)});return}e._socket!==null&&(e._socket._writableState.finished?(t(),s._readableState.endEmitted&&s.destroy()):(e._socket.once(`finish`,function(){t()}),e.close()))},s._read=function(){e.isPaused&&e.resume()},s._write=function(t,n,r){if(e.readyState===e.CONNECTING){e.once(`open`,function(){s._write(t,n,r)});return}e.send(t,r)},s.on(`end`,a),s.on(`error`,o),s}n.exports=s})),m=n(((e,t)=>{let{tokenChars:n}=s();function r(e){let t=new Set,r=-1,i=-1,a=0;for(;a<e.length;a++){let o=e.charCodeAt(a);if(i===-1&&n[o]===1)r===-1&&(r=a);else if(a!==0&&(o===32||o===9))i===-1&&r!==-1&&(i=a);else if(o===44){if(r===-1)throw SyntaxError(`Unexpected character at index ${a}`);i===-1&&(i=a);let n=e.slice(r,i);if(t.has(n))throw SyntaxError(`The "${n}" subprotocol is duplicated`);t.add(n),r=i=-1}else throw SyntaxError(`Unexpected character at index ${a}`)}if(r===-1||i!==-1)throw SyntaxError(`Unexpected end of input`);let o=e.slice(r,a);if(t.has(o))throw SyntaxError(`The "${o}" subprotocol is duplicated`);return t.add(o),t}t.exports={parse:r}})),h=n(((e,n)=>{let i=t(`events`),a=t(`http`),{Duplex:s}=t(`stream`),{createHash:c}=t(`crypto`),l=d(),u=o(),p=m(),h=f(),{GUID:g,kWebSocket:_}=r(),v=/^[+/0-9A-Za-z]{22}==$/;n.exports=class extends i{constructor(e,t){if(super(),e={allowSynchronousEvents:!0,autoPong:!0,maxPayload:100*1024*1024,skipUTF8Validation:!1,perMessageDeflate:!1,handleProtocols:null,clientTracking:!0,verifyClient:null,noServer:!1,backlog:null,server:null,host:null,path:null,port:null,WebSocket:h,...e},e.port==null&&!e.server&&!e.noServer||e.port!=null&&(e.server||e.noServer)||e.server&&e.noServer)throw TypeError(`One and only one of the "port", "server", or "noServer" options must be specified`);if(e.port==null?e.server&&(this._server=e.server):(this._server=a.createServer((e,t)=>{let n=a.STATUS_CODES[426];t.writeHead(426,{"Content-Length":n.length,"Content-Type":`text/plain`}),t.end(n)}),this._server.listen(e.port,e.host,e.backlog,t)),this._server){let e=this.emit.bind(this,`connection`);this._removeListeners=y(this._server,{listening:this.emit.bind(this,`listening`),error:this.emit.bind(this,`error`),upgrade:(t,n,r)=>{this.handleUpgrade(t,n,r,e)}})}e.perMessageDeflate===!0&&(e.perMessageDeflate={}),e.clientTracking&&(this.clients=new Set,this._shouldEmitClose=!1),this.options=e,this._state=0}address(){if(this.options.noServer)throw Error(`The server is operating in "noServer" mode`);return this._server?this._server.address():null}close(e){if(this._state===2){e&&this.once(`close`,()=>{e(Error(`The server is not running`))}),process.nextTick(b,this);return}if(e&&this.once(`close`,e),this._state!==1)if(this._state=1,this.options.noServer||this.options.server)this._server&&(this._removeListeners(),this._removeListeners=this._server=null),this.clients&&this.clients.size?this._shouldEmitClose=!0:process.nextTick(b,this);else{let e=this._server;this._removeListeners(),this._removeListeners=this._server=null,e.close(()=>{b(this)})}}shouldHandle(e){if(this.options.path){let t=e.url.indexOf(`?`);if((t===-1?e.url:e.url.slice(0,t))!==this.options.path)return!1}return!0}handleUpgrade(e,t,n,r){t.on(`error`,x);let i=e.headers[`sec-websocket-key`],a=e.headers.upgrade,o=+e.headers[`sec-websocket-version`];if(e.method!==`GET`){C(this,e,t,405,`Invalid HTTP method`);return}if(a===void 0||a.toLowerCase()!==`websocket`){C(this,e,t,400,`Invalid Upgrade header`);return}if(i===void 0||!v.test(i)){C(this,e,t,400,`Missing or invalid Sec-WebSocket-Key header`);return}if(o!==13&&o!==8){C(this,e,t,400,`Missing or invalid Sec-WebSocket-Version header`,{"Sec-WebSocket-Version":`13, 8`});return}if(!this.shouldHandle(e)){S(t,400);return}let s=e.headers[`sec-websocket-protocol`],c=new Set;if(s!==void 0)try{c=p.parse(s)}catch{C(this,e,t,400,`Invalid Sec-WebSocket-Protocol header`);return}let d=e.headers[`sec-websocket-extensions`],f={};if(this.options.perMessageDeflate&&d!==void 0){let n=new u(this.options.perMessageDeflate,!0,this.options.maxPayload);try{let e=l.parse(d);e[u.extensionName]&&(n.accept(e[u.extensionName]),f[u.extensionName]=n)}catch{C(this,e,t,400,`Invalid or unacceptable Sec-WebSocket-Extensions header`);return}}if(this.options.verifyClient){let a={origin:e.headers[`${o===8?`sec-websocket-origin`:`origin`}`],secure:!!(e.socket.authorized||e.socket.encrypted),req:e};if(this.options.verifyClient.length===2){this.options.verifyClient(a,(a,o,s,l)=>{if(!a)return S(t,o||401,s,l);this.completeUpgrade(f,i,c,e,t,n,r)});return}if(!this.options.verifyClient(a))return S(t,401)}this.completeUpgrade(f,i,c,e,t,n,r)}completeUpgrade(e,t,n,r,i,a,o){if(!i.readable||!i.writable)return i.destroy();if(i[_])throw Error(`server.handleUpgrade() was called more than once with the same socket, possibly due to a misconfiguration`);if(this._state>0)return S(i,503);let s=[`HTTP/1.1 101 Switching Protocols`,`Upgrade: websocket`,`Connection: Upgrade`,`Sec-WebSocket-Accept: ${c(`sha1`).update(t+g).digest(`base64`)}`],d=new this.options.WebSocket(null,void 0,this.options);if(n.size){let e=this.options.handleProtocols?this.options.handleProtocols(n,r):n.values().next().value;e&&(s.push(`Sec-WebSocket-Protocol: ${e}`),d._protocol=e)}if(e[u.extensionName]){let t=e[u.extensionName].params,n=l.format({[u.extensionName]:[t]});s.push(`Sec-WebSocket-Extensions: ${n}`),d._extensions=e}this.emit(`headers`,s,r),i.write(s.concat(`\r
3
+ `).join(`\r
4
+ `)),i.removeListener(`error`,x),d.setSocket(i,a,{allowSynchronousEvents:this.options.allowSynchronousEvents,maxPayload:this.options.maxPayload,skipUTF8Validation:this.options.skipUTF8Validation}),this.clients&&(this.clients.add(d),d.on(`close`,()=>{this.clients.delete(d),this._shouldEmitClose&&!this.clients.size&&process.nextTick(b,this)})),o(d,r)}};function y(e,t){for(let n of Object.keys(t))e.on(n,t[n]);return function(){for(let n of Object.keys(t))e.removeListener(n,t[n])}}function b(e){e._state=2,e.emit(`close`)}function x(){this.destroy()}function S(e,t,n,r){n||=a.STATUS_CODES[t],r={Connection:`close`,"Content-Type":`text/html`,"Content-Length":Buffer.byteLength(n),...r},e.once(`finish`,e.destroy),e.end(`HTTP/1.1 ${t} ${a.STATUS_CODES[t]}\r\n`+Object.keys(r).map(e=>`${e}: ${r[e]}`).join(`\r
5
+ `)+`\r
6
+ \r
7
+ `+n)}function C(e,t,n,r,i,a){if(e.listenerCount(`wsClientError`)){let r=Error(i);Error.captureStackTrace(r,C),e.emit(`wsClientError`,r,n,t)}else S(n,r,i,a)}})),g=e(p(),1),_=e(c(),1),v=e(l(),1),y=e(f(),1),b=e(h(),1),x=y.default,S=_.default,C=v.default,w=y.default,T=b.default,E=g.default;export{S as Receiver,C as Sender,w as WebSocket,T as WebSocketServer,E as createWebSocketStream,x as default};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fugood/buttress-server",
3
- "version": "2.26.0-beta.1",
3
+ "version": "2.26.0-beta.12",
4
4
  "main": "lib/index.mjs",
5
5
  "types": "lib/index.d.ts",
6
6
  "type": "module",
@@ -19,7 +19,7 @@
19
19
  ],
20
20
  "scripts": {
21
21
  "typecheck": "tsc --noEmit",
22
- "build": "tsdown -c rolldown.config.js --config-loader native && tsc --noCheck --emitDeclarationOnly",
22
+ "build": "tsdown -c rolldown.config.js --config-loader native && tsc --noCheck --emitDeclarationOnly && cp ../buttress-backend-core/src/backends/mlx-bridge.py lib/mlx-bridge.py",
23
23
  "build:dist": "$npm_execpath scripts/build-distribution.js",
24
24
  "release": "$npm_execpath scripts/build-distribution.js",
25
25
  "release-beta": "$npm_execpath scripts/build-distribution.js --beta",
@@ -37,10 +37,13 @@
37
37
  ],
38
38
  "license": "MIT",
39
39
  "dependencies": {
40
+ "@earendil-works/pi-agent-core": "^0.85.0",
41
+ "@earendil-works/pi-ai": "0.85.0",
42
+ "@earendil-works/pi-tui": "^0.85.0",
40
43
  "@elysiajs/cors": "^1.1.1",
41
44
  "@elysiajs/node": "^1.4.2",
42
- "@fugood/llama.node": "^1.8.0-rc.4",
43
- "@fugood/whisper.node": "^1.1.2",
45
+ "@fugood/llama.node": "^1.8.0-rc.5",
46
+ "@fugood/whisper.node": "^1.1.3",
44
47
  "@huggingface/gguf": "^0.3.2",
45
48
  "@iarna/toml": "^3.0.0",
46
49
  "@modelcontextprotocol/sdk": "^1.30.0",
@@ -66,8 +69,10 @@
66
69
  "zod": "^3.25.76"
67
70
  },
68
71
  "devDependencies": {
72
+ "@fugood/bricks-cli": "^2.26.0-beta.12",
73
+ "@fugood/bricks-devtools-core": "^2.26.0-beta.11",
69
74
  "tsdown": "^0.22.4",
70
75
  "typescript": "^7.0.2"
71
76
  },
72
- "gitHead": "f440d9ba2e55864af3246f9d595829b660b07ada"
77
+ "gitHead": "257cc79e7cd4d195331338b6345bc1810a448c7e"
73
78
  }
@@ -610,6 +610,16 @@
610
610
  <span class="badge badge-info" id="functionsCount">0 functions</span>
611
611
  </div>
612
612
  <div id="functionsSummary"></div>
613
+ <div class="section" id="functionsDaemonsSection" style="display:none">
614
+ <div class="section-title collapsible" onclick="toggleSection(this)">Daemons</div>
615
+ <div class="collapsible-content" id="functionsDaemons"></div>
616
+ </div>
617
+ <div class="section" id="functionsDaemonHistorySection" style="display:none">
618
+ <div class="section-title collapsible" onclick="toggleSection(this)">Daemon Activity</div>
619
+ <div class="collapsible-content" id="functionsDaemonHistory">
620
+ <div class="empty-state">No daemon activity</div>
621
+ </div>
622
+ </div>
613
623
  <div class="section">
614
624
  <div class="section-title collapsible" onclick="toggleSection(this)">Call History</div>
615
625
  <div class="collapsible-content" id="functionsCallHistory">
@@ -1287,8 +1297,10 @@
1287
1297
  if (!fns.enabled) return
1288
1298
 
1289
1299
  const count = fns.count ?? 0
1300
+ const daemonCount = fns.daemonCount ?? 0
1290
1301
  document.getElementById('functionsCount').textContent =
1291
- `${count} function${count !== 1 ? 's' : ''}`
1302
+ `${count} function${count !== 1 ? 's' : ''}` +
1303
+ (daemonCount > 0 ? ` · ${daemonCount} daemon${daemonCount !== 1 ? 's' : ''}` : '')
1292
1304
 
1293
1305
  const c = fns.counters || {}
1294
1306
  const summary = document.getElementById('functionsSummary')
@@ -1309,6 +1321,7 @@
1309
1321
  </thead>
1310
1322
  <tbody>
1311
1323
  ${stat('Calls', c.calls?.total ?? 0, c.calls?.failed ? `${c.calls.failed} failed` : '')}
1324
+ ${stat('Daemon runs', c.daemons?.invocations ?? 0, c.daemons?.failed ? `${c.daemons.failed} failed` : '')}
1312
1325
  ${stat('Uploads', `${c.uploads?.total ?? 0} (${formatBytes(c.uploads?.bytes ?? 0)})`, c.uploads?.failed ? `${c.uploads.failed} failed` : '')}
1313
1326
  ${stat('Downloads', `${c.downloads?.total ?? 0} (${formatBytes(c.downloads?.bytes ?? 0)})`, c.downloads?.missed ? `${c.downloads.missed} missed` : '')}
1314
1327
  ${stat('Auth checks', c.auth?.total ?? 0, c.auth?.denied ? `${c.auth.denied} denied` : '')}
@@ -1319,6 +1332,8 @@
1319
1332
  `
1320
1333
  })
1321
1334
 
1335
+ renderFunctionsDaemons(fns.daemons || [], fns.history?.daemons || [])
1336
+
1322
1337
  const history = fns.history || {}
1323
1338
  const statusBadge = i => i.success ?
1324
1339
  '<span class="badge badge-success">Success</span>' :
@@ -1362,6 +1377,67 @@
1362
1377
  ])
1363
1378
  }
1364
1379
 
1380
+ // Live daemon state + recent daemon event invocations
1381
+ function renderFunctionsDaemons(daemons, activity) {
1382
+ const hasDaemons = daemons.length > 0
1383
+ document.getElementById('functionsDaemonsSection').style.display = hasDaemons ? '' : 'none'
1384
+ document.getElementById('functionsDaemonHistorySection').style.display =
1385
+ hasDaemons || activity.length > 0 ? '' : 'none'
1386
+
1387
+ if (hasDaemons) {
1388
+ const container = document.getElementById('functionsDaemons')
1389
+ const stateBadge = d => d.state === 'running' ?
1390
+ '<span class="badge badge-success">Running</span>' :
1391
+ `<span class="badge badge-error">Error${d.error ? `: ${escapeHtml(d.error)}` : ''}</span>`
1392
+ const bankBadge = d => {
1393
+ if (!d.bankSubscriptions) return '-'
1394
+ const cls = d.bank === 'connected' ? 'badge-success' :
1395
+ d.bank === 'connecting' ? 'badge-info' : 'badge-warning'
1396
+ return `<span class="badge ${cls}">${escapeHtml(d.bank || 'connecting')} (${d.bankSubscriptions})</span>`
1397
+ }
1398
+ withScrollPreserve(container, () => {
1399
+ container.innerHTML = `
1400
+ <div class="table-wrapper">
1401
+ <div class="table-inner">
1402
+ <table>
1403
+ <thead>
1404
+ <tr>
1405
+ <th>Daemon</th><th>State</th><th>Started</th><th>Timers</th>
1406
+ <th>Bank</th><th>Events</th><th>Runs</th>
1407
+ </tr>
1408
+ </thead>
1409
+ <tbody>
1410
+ ${daemons.map(d => `
1411
+ <tr>
1412
+ <td title="${escapeHtml(d.description || '')}">${escapeHtml(d.name)}</td>
1413
+ <td>${stateBadge(d)}</td>
1414
+ <td><span class="timestamp">${d.startedAt ? formatRelativeTime(d.startedAt) : '-'}</span></td>
1415
+ <td>${d.timers ?? 0}</td>
1416
+ <td>${bankBadge(d)}</td>
1417
+ <td>${d.listening ? '<span class="badge badge-info">listening</span>' : '-'}</td>
1418
+ <td>${d.counts?.runs ?? 0}${d.counts?.failed ? ` <span class="badge badge-error">${d.counts.failed} failed</span>` : ''}</td>
1419
+ </tr>
1420
+ `).join('')}
1421
+ </tbody>
1422
+ </table>
1423
+ </div>
1424
+ </div>
1425
+ `
1426
+ })
1427
+ }
1428
+
1429
+ renderHistory('functionsDaemonHistory', activity, [
1430
+ { label: 'Time', render: i => `<span class="timestamp">${formatRelativeTime(i.timestamp)}</span>` },
1431
+ { label: 'Daemon', render: i => escapeHtml(i.name) },
1432
+ { label: 'Event', render: i => `<span class="badge badge-info">${escapeHtml(i.event || '-')}</span>` },
1433
+ { label: 'Duration', render: i => `${(i.durationMs / 1000).toFixed(2)}s` },
1434
+ { label: 'Status', render: i => i.success ?
1435
+ '<span class="badge badge-success">Success</span>' :
1436
+ `<span class="badge badge-error">Failed: ${escapeHtml(i.error || 'Unknown')}</span>`
1437
+ },
1438
+ ])
1439
+ }
1440
+
1365
1441
  // Fallback: Fetch status via HTTP polling
1366
1442
  let pollingInterval = null
1367
1443