diff --git a/doc/reflections/das2rst.das b/doc/reflections/das2rst.das index 0064cfd7e9..3cb5d3a63c 100644 --- a/doc/reflections/das2rst.das +++ b/doc/reflections/das2rst.das @@ -256,7 +256,7 @@ def document_module_dashv(_root : string) { var mod = get_module("dashv") var groups <- array( group_by_regex("WebSocket client", mod, %regex~(make_web_socket_client|destroy_web_socket_client|open|close|is_connected|tick|send)$%%), - group_by_regex("WebSocket server lifecycle", mod, %regex~(make_web_socket_server|destroy_web_socket_server|start|stop)$%%), + group_by_regex("WebSocket server lifecycle", mod, %regex~(make_web_socket_server|destroy_web_socket_server|set_bind_host|start|stop)$%%), group_by_regex("WebSocket channel send", mod, %regex~(send)$%%), group_by_regex("Handle operations", mod, %regex~(is_alive|==|!=)$%%), group_by_regex("HTTP route registration", mod, %regex~(GET|POST|PUT|DELETE|PATCH|HEAD|ANY|SSE|STREAM)$%%), diff --git a/doc/source/reference/tutorials/dasHV_06_websockets.rst b/doc/source/reference/tutorials/dasHV_06_websockets.rst index 444ab1cb8d..c211dfcdc9 100644 --- a/doc/source/reference/tutorials/dasHV_06_websockets.rst +++ b/doc/source/reference/tutorials/dasHV_06_websockets.rst @@ -75,6 +75,8 @@ Subclass ``HvWebSocketClient`` and override: - ``onOpen()`` — connection established - ``onClose()`` — connection lost - ``onMessage(msg)`` — text message received +- ``onMessageFrame(msg, byte_count, opcode)`` — lossless text or binary frame; + ``byte_count`` is authoritative when the payload contains embedded zero bytes .. code-block:: das @@ -93,6 +95,11 @@ Subclass ``HvWebSocketClient`` and override: def override onMessage(msg : string#) { received |> push_clone(string(msg)) } + + def override onMessageFrame(msg : string#; byte_count : int; opcode : ws_opcode) { + if (opcode == ws_opcode.WS_OPCODE_TEXT) onMessage(msg) + // Binary consumers use msg together with byte_count here. + } } Connecting and Receiving @@ -257,6 +264,8 @@ Quick Reference - Client: connection lost * - ``onMessage(msg)`` - Client: text message received + * - ``onMessageFrame(msg, byte_count, opcode)`` + - Client: lossless text/binary frame (defaults to forwarding text to ``onMessage``) * - ``init(url) : int`` - Client: connect to WebSocket server * - ``send(text)`` diff --git a/doc/source/stdlib/handmade/function-dashv-close-0x963be1332f1c1550.rst b/doc/source/stdlib/handmade/function-dashv-close-0x963be1332f1c1550.rst new file mode 100644 index 0000000000..b353e501e3 --- /dev/null +++ b/doc/source/stdlib/handmade/function-dashv-close-0x963be1332f1c1550.rst @@ -0,0 +1 @@ +Closes a connected WebSocket channel. Returns 0 on success and -1 for an invalid channel handle. diff --git a/doc/source/stdlib/handmade/function-dashv-set_bind_host-0xe5ed5df2976b295.rst b/doc/source/stdlib/handmade/function-dashv-set_bind_host-0xe5ed5df2976b295.rst new file mode 100644 index 0000000000..8c3ba482ac --- /dev/null +++ b/doc/source/stdlib/handmade/function-dashv-set_bind_host-0xe5ed5df2976b295.rst @@ -0,0 +1 @@ +Selects the WebSocket server interface to bind before start. Returns false for an invalid server handle, an empty host, or a host that is too long. diff --git a/examples/hv/ws_chat_client.das b/examples/hv/ws_chat_client.das index 52c82eec7c..422a09ce47 100644 --- a/examples/hv/ws_chat_client.das +++ b/examples/hv/ws_chat_client.das @@ -33,6 +33,9 @@ class TerminalChatClient : HvWebSocketClient { def override onMessage(msg : string#) { print("{msg}\n") } + def override onMessageFrame(msg : string#; byte_count : int; opcode : ws_opcode) { + if (opcode == ws_opcode.WS_OPCODE_TEXT) onMessage(msg) + } } [export] @@ -48,13 +51,13 @@ def main() { client->process_event_que() // Non-blocking read from stdin let line = fgets(fstdin()) - if (length(line) > 0) { + if (!empty(line)) { let text = strip(line) if (text == "/quit") { client->close() break } - if (length(text) > 0) { + if (!empty(text)) { client->send(text) } } diff --git a/modules/dasHV/dashv/dashv_boost.das b/modules/dasHV/dashv/dashv_boost.das index 9c40ed32e6..334db93e7a 100644 --- a/modules/dasHV/dashv/dashv_boost.das +++ b/modules/dasHV/dashv/dashv_boost.das @@ -6,7 +6,8 @@ options no_unused_function_arguments = false //! High-level WebSocket and HTTP wrappers for the ``dashv`` C++ module. //! //! Provides ``HvWebSocketClient`` for WebSocket client connections with -//! ``onOpen``, ``onClose``, and ``onMessage`` callbacks, and ``HvWebServer`` +//! ``onOpen``, ``onClose``, ``onMessage``, and lossless ``onMessageFrame`` +//! callbacks, and ``HvWebServer`` //! for HTTP/WebSocket servers with route registration and static file serving. //! Also includes ``with_http_request`` and ``get_body_bytes`` helpers. @@ -45,6 +46,12 @@ class HvWebSocketClient { //! Called when the WebSocket connection is closed. def abstract onMessage(msg : string#) : void //! Called when a text message is received from the server. + def onMessageFrame(msg : string#; byte_count : int; opcode : ws_opcode) { + //! Called for every complete text or binary frame. ``byte_count`` is + //! authoritative and preserves embedded zero bytes. The default keeps + //! the original text-only contract by forwarding text frames. + if (opcode == ws_opcode.WS_OPCODE_TEXT) onMessage(msg) + } def is_connected : bool { //! Returns ``true`` if the WebSocket connection is currently open. return is_connected(client) @@ -100,6 +107,10 @@ class HvWebServer { //! Starts the server. Returns 0 on success. return start(server) } + def set_bind_host(host : string) : bool { + //! Selects the interface to bind before ``start`` (for example, ``127.0.0.1``). + return set_bind_host(server, host) + } def stop : int { //! Stops the server. Returns 0 on success. return stop(server) diff --git a/modules/dasHV/src/aot_hv.h b/modules/dasHV/src/aot_hv.h index 6054ecc140..7ac59f1f11 100644 --- a/modules/dasHV/src/aot_hv.h +++ b/modules/dasHV/src/aot_hv.h @@ -32,6 +32,8 @@ namespace das { int das_wss_send ( Handle h, const char * msg, ws_opcode opcode, bool fin ); int das_wss_send_buf ( Handle h, const char * buf, int32_t len, ws_opcode opcode, bool fin ); int das_wss_send_fragment ( Handle h, const char * buf, int32_t len, int32_t fragment, ws_opcode opcode ); + int das_wss_close_channel ( Handle h ); + bool das_wss_set_bind_host ( Handle h, const char * host ); int das_wss_start ( Handle h ); void das_wss_tick ( Handle h ); int das_wss_stop ( Handle h ); diff --git a/modules/dasHV/src/dasHV.cpp b/modules/dasHV/src/dasHV.cpp index 02cb7fd9dc..4c19826201 100644 --- a/modules/dasHV/src/dasHV.cpp +++ b/modules/dasHV/src/dasHV.cpp @@ -177,9 +177,10 @@ class WebSocketClient_Adapter : public hv::WebSocketClient, public HvWebSocketCl }); }; onmessage = [=]( const string & msg ) { + const auto message_opcode = opcode(); lock_guard guard(lock); - que.emplace_back([=](){ - onMessage(msg); + que.emplace_back([=]() { + onMessageFrame(msg, message_opcode); }); }; } @@ -193,9 +194,10 @@ class WebSocketClient_Adapter : public hv::WebSocketClient, public HvWebSocketCl invoke_onClose(context,fnOnClose,classPtr); } } - void onMessage ( const string & msg ) { - if ( auto fnOnMessage = get_onMessage(classPtr) ) { - invoke_onMessage(context,fnOnMessage,classPtr,(char *)msg.c_str()); + void onMessageFrame ( const string & msg, ws_opcode opcode ) { + if ( auto fnOnMessageFrame = get_onMessageFrame(classPtr) ) { + invoke_onMessageFrame(context, fnOnMessageFrame, classPtr, + (char *)msg.data(), static_cast(msg.size()), opcode); } } void tick() { @@ -591,6 +593,21 @@ int das_wss_send_fragment ( Handle h, const char * buf, in return p->send(buf, len, fragment, opcode); } +int das_wss_close_channel ( Handle h ) { + auto p = HandleRegistry::instance().lookup(h); + if ( !p ) return -1; + return p->close(); +} + +bool das_wss_set_bind_host ( Handle h, const char * host ) { + auto adapter = lookup_server(h); + if ( !adapter || !host ) return false; + const size_t len = strlen(host); + if ( len == 0 || len >= sizeof(adapter->host) ) return false; + memcpy(adapter->host, host, len + 1); + return true; +} + int das_wss_start ( Handle h ) { auto adapter = lookup_server(h); if ( !adapter ) return -1; @@ -1299,6 +1316,12 @@ class Module_HV : public Module { addExtern (*this, lib, "send", SideEffects::worstDefault, "das_wss_send_fragment") ->args({"channel","msg","len","fragment","opcode"}); + addExtern (*this, lib, "close", + SideEffects::worstDefault, "das_wss_close_channel") + ->args({"channel"}); + addExtern (*this, lib, "set_bind_host", + SideEffects::worstDefault, "das_wss_set_bind_host") + ->args({"server","host"}); addExtern (*this, lib, "start", SideEffects::worstDefault, "das_wss_start") ->args({"server"}); diff --git a/modules/dasHV/src/dasHV.h b/modules/dasHV/src/dasHV.h index bb7c3ed0db..379222fe0c 100644 --- a/modules/dasHV/src/dasHV.h +++ b/modules/dasHV/src/dasHV.h @@ -39,6 +39,8 @@ Handle makeWebSocketServer ( int port, int httpsPort, const int das_wss_send ( Handle h, const char * msg, ws_opcode opcode, bool fin ); int das_wss_send_buf ( Handle h, const char * buf, int32_t len, ws_opcode opcode, bool fin ); int das_wss_send_fragment ( Handle h, const char * buf, int32_t len, int32_t fragment, ws_opcode opcode ); +int das_wss_close_channel ( Handle h ); +bool das_wss_set_bind_host ( Handle h, const char * host ); int das_wss_start ( Handle h ); void das_wss_tick ( Handle h ); int das_wss_stop ( Handle h ); diff --git a/modules/dasHV/src/dashv_gen.inc b/modules/dasHV/src/dashv_gen.inc index 193ca940c0..cabfbd7e51 100644 --- a/modules/dasHV/src/dashv_gen.inc +++ b/modules/dasHV/src/dashv_gen.inc @@ -4,14 +4,16 @@ protected: __fn_onOpen = 0, __fn_onClose = 1, __fn_onMessage = 2, + __fn_onMessageFrame = 3, }; protected: - int _das_class_method_offset[3]; + int _das_class_method_offset[4]; public: HvWebSocketClient_Adapter ( const StructInfo * info ) { _das_class_method_offset[__fn_onOpen] = info->fields[5]->offset; _das_class_method_offset[__fn_onClose] = info->fields[6]->offset; _das_class_method_offset[__fn_onMessage] = info->fields[7]->offset; + _das_class_method_offset[__fn_onMessageFrame] = info->fields[8]->offset; } __forceinline Func get_onOpen ( void * self ) const { return getDasClassMethod(self,_das_class_method_offset[__fn_onOpen]); @@ -40,6 +42,15 @@ public: (__context__,nullptr,__funcCall__, self,msg); } + __forceinline Func get_onMessageFrame ( void * self ) const { + return getDasClassMethod(self,_das_class_method_offset[__fn_onMessageFrame]); + } + __forceinline void invoke_onMessageFrame ( Context * __context__, Func __funcCall__, void * self, char * const msg, int32_t byte_count, DAS_COMMENT(bound_enum) ws_opcode opcode ) const { + das_invoke_function::invoke + + (__context__,nullptr,__funcCall__, + self,msg,byte_count,opcode); + } }; class HvWebServer_Adapter { @@ -54,10 +65,10 @@ protected: int _das_class_method_offset[4]; public: HvWebServer_Adapter ( const StructInfo * info ) { - _das_class_method_offset[__fn_onWsOpen] = info->fields[11]->offset; - _das_class_method_offset[__fn_onWsClose] = info->fields[12]->offset; - _das_class_method_offset[__fn_onWsMessage] = info->fields[13]->offset; - _das_class_method_offset[__fn_onTick] = info->fields[14]->offset; + _das_class_method_offset[__fn_onWsOpen] = info->fields[12]->offset; + _das_class_method_offset[__fn_onWsClose] = info->fields[13]->offset; + _das_class_method_offset[__fn_onWsMessage] = info->fields[14]->offset; + _das_class_method_offset[__fn_onTick] = info->fields[15]->offset; } __forceinline Func get_onWsOpen ( void * self ) const { return getDasClassMethod(self,_das_class_method_offset[__fn_onWsOpen]); diff --git a/modules/dasTerminal/daslib/terminal.das b/modules/dasTerminal/daslib/terminal.das index ecf8d2d3ac..ee4a0a4dc5 100644 --- a/modules/dasTerminal/daslib/terminal.das +++ b/modules/dasTerminal/daslib/terminal.das @@ -391,6 +391,21 @@ def private copy_cell(cell : TerminalCell const; row, column : int) : TerminalCe hyperlink = cell.hyperlink) } +def private erased_cell(buffer : TerminalBuffer const; row, column : int) : TerminalCell { + return TerminalCell(row = row, column = column, grapheme = " ", width = 1, + attributes = buffer.pen.attributes, foreground = buffer.pen.foreground, + background = buffer.pen.background) +} + +def private erased_row(buffer : TerminalBuffer const; columns, row : int) : TerminalRow { + var result = TerminalRow() + result.cells |> reserve(columns) + for (column in range(columns)) { + result.cells |> push(erased_cell(buffer, row, column)) + } + return <- result +} + def private clear_cell(terminal : Terminal const; var buffer : TerminalBuffer; row, column : int) { if (row < 0 || row >= terminal.rows || column < 0 || column >= terminal.columns) return @@ -400,12 +415,12 @@ def private clear_cell(terminal : Terminal const; var buffer : TerminalBuffer; first-- } if (buffer.screen[physical_row].cells[first].width == 2 && first + 1 >= column) { - buffer.screen[physical_row].cells[first] = blank_cell(row, first) + buffer.screen[physical_row].cells[first] = erased_cell(buffer, row, first) if (first + 1 < terminal.columns) { - buffer.screen[physical_row].cells[first + 1] = blank_cell(row, first + 1) + buffer.screen[physical_row].cells[first + 1] = erased_cell(buffer, row, first + 1) } } else { - buffer.screen[physical_row].cells[column] = blank_cell(row, column) + buffer.screen[physical_row].cells[column] = erased_cell(buffer, row, column) } } @@ -423,7 +438,7 @@ def private scroll_up(terminal : Terminal const; var buffer : TerminalBuffer; no if (normal) append_history_row(buffer, buffer.screen[first]) buffer.screen_start = (buffer.screen_start + 1) % terminal.rows let last = screen_index(buffer, terminal.rows - 1) - buffer.screen[last] <- blank_row(terminal.columns, terminal.rows - 1) + buffer.screen[last] <- erased_row(buffer, terminal.columns, terminal.rows - 1) } def private scroll_rows_up(terminal : Terminal const; var buffer : TerminalBuffer; @@ -445,7 +460,7 @@ def private scroll_rows_up(terminal : Terminal const; var buffer : TerminalBuffe } for (row in range(last - count + 1, last + 1)) { let destination = screen_index(buffer, row) - buffer.screen[destination] <- blank_row(terminal.columns, row) + buffer.screen[destination] <- erased_row(buffer, terminal.columns, row) } } @@ -459,7 +474,7 @@ def private scroll_rows_down(terminal : Terminal const; var buffer : TerminalBuf for (_ in range(count)) { buffer.screen_start = (buffer.screen_start + terminal.rows - 1) % terminal.rows let top = screen_index(buffer, 0) - buffer.screen[top] <- blank_row(terminal.columns, 0) + buffer.screen[top] <- erased_row(buffer, terminal.columns, 0) } return } @@ -472,7 +487,7 @@ def private scroll_rows_down(terminal : Terminal const; var buffer : TerminalBuf } for (blank in range(first, first + count)) { let destination = screen_index(buffer, blank) - buffer.screen[destination] <- blank_row(terminal.columns, blank) + buffer.screen[destination] <- erased_row(buffer, terminal.columns, blank) } } @@ -624,7 +639,7 @@ def private erase_display(terminal : Terminal const; var buffer : TerminalBuffer if (mode == 2 || mode == 3) { for (row in range(terminal.rows)) { let physical = screen_index(buffer, row) - buffer.screen[physical] <- blank_row(terminal.columns, row) + buffer.screen[physical] <- erased_row(buffer, terminal.columns, row) } if (mode == 3) { buffer.history |> clear() @@ -634,13 +649,13 @@ def private erase_display(terminal : Terminal const; var buffer : TerminalBuffer erase_line(terminal, buffer, 0) for (row in range(buffer.cursor.row + 1, terminal.rows)) { let physical = screen_index(buffer, row) - buffer.screen[physical] <- blank_row(terminal.columns, row) + buffer.screen[physical] <- erased_row(buffer, terminal.columns, row) } } elif (mode == 1) { erase_line(terminal, buffer, 1) for (row in range(0, buffer.cursor.row)) { let physical = screen_index(buffer, row) - buffer.screen[physical] <- blank_row(terminal.columns, row) + buffer.screen[physical] <- erased_row(buffer, terminal.columns, row) } } } diff --git a/modules/dasTerminal/tests/app_compat/oracle-snapshots.json b/modules/dasTerminal/tests/app_compat/oracle-snapshots.json index 4463ba5a31..30923e9e62 100644 --- a/modules/dasTerminal/tests/app_compat/oracle-snapshots.json +++ b/modules/dasTerminal/tests/app_compat/oracle-snapshots.json @@ -4849,6 +4849,385 @@ } ] }, + { + "id": "opencode/background-color-erase", + "checkpoints": [ + { + "checkpoint": "panel", + "screen": [ + "", + " prompt" + ], + "history": [], + "cursor": { + "row": 1, + "column": 10 + }, + "alternate_active": false, + "title": "", + "replies": [], + "cells": [ + { + "row": 0, + "column": 2, + "grapheme": " ", + "width": 1, + "attributes": 0, + "foreground": { + "kind": "default_color", + "index": 0, + "red": 0, + "green": 0, + "blue": 0 + }, + "background": { + "kind": "rgb", + "index": 0, + "red": 30, + "green": 30, + "blue": 30 + } + }, + { + "row": 0, + "column": 3, + "grapheme": " ", + "width": 1, + "attributes": 0, + "foreground": { + "kind": "default_color", + "index": 0, + "red": 0, + "green": 0, + "blue": 0 + }, + "background": { + "kind": "rgb", + "index": 0, + "red": 30, + "green": 30, + "blue": 30 + } + }, + { + "row": 0, + "column": 4, + "grapheme": " ", + "width": 1, + "attributes": 0, + "foreground": { + "kind": "default_color", + "index": 0, + "red": 0, + "green": 0, + "blue": 0 + }, + "background": { + "kind": "rgb", + "index": 0, + "red": 30, + "green": 30, + "blue": 30 + } + }, + { + "row": 0, + "column": 5, + "grapheme": " ", + "width": 1, + "attributes": 0, + "foreground": { + "kind": "default_color", + "index": 0, + "red": 0, + "green": 0, + "blue": 0 + }, + "background": { + "kind": "rgb", + "index": 0, + "red": 30, + "green": 30, + "blue": 30 + } + }, + { + "row": 0, + "column": 6, + "grapheme": " ", + "width": 1, + "attributes": 0, + "foreground": { + "kind": "default_color", + "index": 0, + "red": 0, + "green": 0, + "blue": 0 + }, + "background": { + "kind": "rgb", + "index": 0, + "red": 30, + "green": 30, + "blue": 30 + } + }, + { + "row": 0, + "column": 7, + "grapheme": " ", + "width": 1, + "attributes": 0, + "foreground": { + "kind": "default_color", + "index": 0, + "red": 0, + "green": 0, + "blue": 0 + }, + "background": { + "kind": "rgb", + "index": 0, + "red": 30, + "green": 30, + "blue": 30 + } + }, + { + "row": 0, + "column": 8, + "grapheme": " ", + "width": 1, + "attributes": 0, + "foreground": { + "kind": "default_color", + "index": 0, + "red": 0, + "green": 0, + "blue": 0 + }, + "background": { + "kind": "rgb", + "index": 0, + "red": 30, + "green": 30, + "blue": 30 + } + }, + { + "row": 0, + "column": 9, + "grapheme": " ", + "width": 1, + "attributes": 0, + "foreground": { + "kind": "default_color", + "index": 0, + "red": 0, + "green": 0, + "blue": 0 + }, + "background": { + "kind": "rgb", + "index": 0, + "red": 30, + "green": 30, + "blue": 30 + } + }, + { + "row": 1, + "column": 2, + "grapheme": " ", + "width": 1, + "attributes": 0, + "foreground": { + "kind": "default_color", + "index": 0, + "red": 0, + "green": 0, + "blue": 0 + }, + "background": { + "kind": "rgb", + "index": 0, + "red": 30, + "green": 30, + "blue": 30 + } + }, + { + "row": 1, + "column": 3, + "grapheme": " ", + "width": 1, + "attributes": 0, + "foreground": { + "kind": "default_color", + "index": 0, + "red": 0, + "green": 0, + "blue": 0 + }, + "background": { + "kind": "rgb", + "index": 0, + "red": 30, + "green": 30, + "blue": 30 + } + }, + { + "row": 1, + "column": 4, + "grapheme": "p", + "width": 1, + "attributes": 0, + "foreground": { + "kind": "default_color", + "index": 0, + "red": 0, + "green": 0, + "blue": 0 + }, + "background": { + "kind": "rgb", + "index": 0, + "red": 30, + "green": 30, + "blue": 30 + } + }, + { + "row": 1, + "column": 5, + "grapheme": "r", + "width": 1, + "attributes": 0, + "foreground": { + "kind": "default_color", + "index": 0, + "red": 0, + "green": 0, + "blue": 0 + }, + "background": { + "kind": "rgb", + "index": 0, + "red": 30, + "green": 30, + "blue": 30 + } + }, + { + "row": 1, + "column": 6, + "grapheme": "o", + "width": 1, + "attributes": 0, + "foreground": { + "kind": "default_color", + "index": 0, + "red": 0, + "green": 0, + "blue": 0 + }, + "background": { + "kind": "rgb", + "index": 0, + "red": 30, + "green": 30, + "blue": 30 + } + }, + { + "row": 1, + "column": 7, + "grapheme": "m", + "width": 1, + "attributes": 0, + "foreground": { + "kind": "default_color", + "index": 0, + "red": 0, + "green": 0, + "blue": 0 + }, + "background": { + "kind": "rgb", + "index": 0, + "red": 30, + "green": 30, + "blue": 30 + } + }, + { + "row": 1, + "column": 8, + "grapheme": "p", + "width": 1, + "attributes": 0, + "foreground": { + "kind": "default_color", + "index": 0, + "red": 0, + "green": 0, + "blue": 0 + }, + "background": { + "kind": "rgb", + "index": 0, + "red": 30, + "green": 30, + "blue": 30 + } + }, + { + "row": 1, + "column": 9, + "grapheme": "t", + "width": 1, + "attributes": 0, + "foreground": { + "kind": "default_color", + "index": 0, + "red": 0, + "green": 0, + "blue": 0 + }, + "background": { + "kind": "rgb", + "index": 0, + "red": 30, + "green": 30, + "blue": 30 + } + }, + { + "row": 1, + "column": 10, + "grapheme": " ", + "width": 1, + "attributes": 0, + "foreground": { + "kind": "default_color", + "index": 0, + "red": 0, + "green": 0, + "blue": 0 + }, + "background": { + "kind": "rgb", + "index": 0, + "red": 30, + "green": 30, + "blue": 30 + } + } + ] + } + ] + }, { "id": "claude-code/captured-startup-and-teardown", "checkpoints": [ diff --git a/modules/dasTerminal/tests/app_compat/scenario-source.mjs b/modules/dasTerminal/tests/app_compat/scenario-source.mjs index 4638540582..48341b7434 100644 --- a/modules/dasTerminal/tests/app_compat/scenario-source.mjs +++ b/modules/dasTerminal/tests/app_compat/scenario-source.mjs @@ -157,6 +157,21 @@ export const corpus = { { checkpoint: "probes-consumed" } ] }, + { + id: "opencode/background-color-erase", + source: "OpenCode 1.18.4, Windows ConPTY capture, 2026-07-20", + columns: 12, + rows: 2, + steps: [ + { + feed: bytes( + `${ESC}[48;2;30;30;30m${ESC}[1;3H${ESC}[8X` + + `${ESC}[2;3H prompt${ESC}[1X` + ) + }, + { checkpoint: "panel" } + ] + }, { id: "claude-code/captured-startup-and-teardown", source: "Claude Code 2.1.215, Windows ConPTY capture, 2026-07-19", diff --git a/modules/dasTerminal/tests/app_compat/scenarios.json b/modules/dasTerminal/tests/app_compat/scenarios.json index e508db49ff..6eaa51a578 100644 --- a/modules/dasTerminal/tests/app_compat/scenarios.json +++ b/modules/dasTerminal/tests/app_compat/scenarios.json @@ -717,6 +717,65 @@ } ] }, + { + "id": "opencode/background-color-erase", + "source": "OpenCode 1.18.4, Windows ConPTY capture, 2026-07-20", + "columns": 12, + "rows": 2, + "steps": [ + { + "feed": [ + 27, + 91, + 52, + 56, + 59, + 50, + 59, + 51, + 48, + 59, + 51, + 48, + 59, + 51, + 48, + 109, + 27, + 91, + 49, + 59, + 51, + 72, + 27, + 91, + 56, + 88, + 27, + 91, + 50, + 59, + 51, + 72, + 32, + 32, + 112, + 114, + 111, + 109, + 112, + 116, + 27, + 91, + 49, + 88 + ] + }, + { + "checkpoint": "panel" + } + ] + }, { "id": "claude-code/captured-startup-and-teardown", "source": "Claude Code 2.1.215, Windows ConPTY capture, 2026-07-19", diff --git a/modules/dasTerminal/tests/terminal_semantics.das b/modules/dasTerminal/tests/terminal_semantics.das index 46a339aa9d..751c781b74 100644 --- a/modules/dasTerminal/tests/terminal_semantics.das +++ b/modules/dasTerminal/tests/terminal_semantics.das @@ -108,6 +108,7 @@ def main { let bytes <- [uint8(0xe4), uint8(0xb8), uint8(0xad)] terminal_feed_bytes(styled, bytes) terminal_snapshot(styled, snapshot) + assert(snapshot.normal.cells[3].grapheme == "中") assert(snapshot.normal.cells[3].width == 2) var key_bytes : array diff --git a/tests/dasHV/test_websockets.das b/tests/dasHV/test_websockets.das index 494198b9c7..1c8300bab4 100644 --- a/tests/dasHV/test_websockets.das +++ b/tests/dasHV/test_websockets.das @@ -40,6 +40,11 @@ class WsTestServer : HvWebServer { } clients |> insert_clone(channel, nickname) send(channel, "welcome {nickname}", ws_opcode.WS_OPCODE_TEXT, true) + var binary = fixed_array(0x41u, 0u, 0x42u) + unsafe { + send(channel, reinterpret(addr(binary[0])), length(binary), + ws_opcode.WS_OPCODE_BINARY, true) + } } def override onWsClose(channel : WebSocketChannel) { @@ -70,6 +75,8 @@ class WsTestServer : HvWebServer { class TestWsClient : HvWebSocketClient { received : array + binary_received : array + binary_frames : int connected : bool = false closed : bool = false @@ -83,7 +90,35 @@ class TestWsClient : HvWebSocketClient { } def override onMessage(msg : string#) { - received |> push_clone(string(msg)) + received |> push(string(msg)) + } + def override onMessageFrame(msg : string#; byte_count : int; opcode : ws_opcode) { + if (opcode == ws_opcode.WS_OPCODE_TEXT) { + onMessage(msg) + } elif (opcode == ws_opcode.WS_OPCODE_BINARY) { + binary_frames++ + binary_received |> resize(byte_count) + if (byte_count > 0) { + unsafe { memcpy(addr(binary_received[0]), reinterpret(msg), byte_count) } + } + } + } +} + +// Compatibility client intentionally implements only the original text callback. +// HvWebSocketClient.onMessageFrame must continue forwarding text frames here. +class LegacyTextWsClient : HvWebSocketClient { + received : array + connected : bool + closed : bool + + def override onOpen { connected = true } + def override onClose { + connected = false + closed = true + } + def override onMessage(msg : string#) { + received |> push(string(msg)) } } @@ -96,7 +131,16 @@ def wait_messages(var client : TestWsClient?; count : int; max_ms : int = 3000) while (length(client.received) < count && elapsed < max_ms) { client->process_event_que() sleep(1u) - elapsed += 1 + elapsed++ + } +} + +def wait_binary_frames(var client : TestWsClient?; count : int; max_ms : int = 3000) { + var elapsed = 0 + while (client.binary_frames < count && elapsed < max_ms) { + client->process_event_que() + sleep(1u) + elapsed++ } } @@ -106,7 +150,7 @@ def wait_closed(var client : TestWsClient?; max_ms : int = 3000) { while (!client.closed && elapsed < max_ms) { client->process_event_que() sleep(1u) - elapsed += 1 + elapsed++ } } @@ -151,7 +195,7 @@ def with_ws_test_server(port : int; blk : block<(ws_url : string; http_url : str [test] def test_websockets(t : T?) { - with_ws_test_server(PORT_WEBSOCKETS) <| $(ws_url, http_url) { + with_ws_test_server(PORT_WEBSOCKETS) $(ws_url, http_url) { t |> run("connect and receive welcome") @(t : T?) { var client = new TestWsClient() @@ -168,6 +212,45 @@ def test_websockets(t : T?) { } } + t |> run("onMessage-only clients retain text compatibility") @(t : T?) { + var client = new LegacyTextWsClient() + client->init("{ws_url}/ws") + var elapsed = 0 + while (length(client.received) < 1 && elapsed < 3000) { + client->process_event_que() + sleep(1u) + elapsed++ + } + t |> success(client.connected, "legacy client is connected") + t |> equal(length(client.received), 1) + t |> success(starts_with(client.received[0], "welcome "), + "default frame callback forwards text") + client->close() + while (!client.closed && elapsed < 6000) { + client->process_event_que() + sleep(1u) + elapsed++ + } + client->cleanup() + unsafe { delete client } + } + + t |> run("binary frames preserve opcode, length, and embedded zero bytes") @(t : T?) { + var client = new TestWsClient() + client->init("{ws_url}/ws") + wait_messages(client, 1) + wait_binary_frames(client, 1) + t |> equal(client.binary_frames, 1) + t |> equal(length(client.binary_received), 3) + t |> equal(client.binary_received[0], uint8(0x41)) + t |> equal(client.binary_received[1], uint8(0)) + t |> equal(client.binary_received[2], uint8(0x42)) + client->close() + wait_closed(client) + client->cleanup() + unsafe { delete client } + } + t |> run("send and receive echo") @(t : T?) { var client = new TestWsClient() client->init("{ws_url}/ws") diff --git a/tutorials/dasHV/06_websockets.das b/tutorials/dasHV/06_websockets.das index 8962494814..2b2dc15143 100644 --- a/tutorials/dasHV/06_websockets.das +++ b/tutorials/dasHV/06_websockets.das @@ -2,7 +2,8 @@ // // This tutorial covers: // - Creating a WebSocket server with HvWebServer (onWsOpen, onWsClose, onWsMessage) -// - Creating a WebSocket client with HvWebSocketClient (onOpen, onClose, onMessage) +// - Creating a WebSocket client with HvWebSocketClient +// (onOpen, onClose, onMessage, onMessageFrame) // - Sending text messages (client → server, server → client) // - Broadcasting messages to all connected clients // - Tracking connected clients with a channel table @@ -99,6 +100,7 @@ class ChatServer : HvWebServer { // onOpen() — connection established // onClose() — connection lost // onMessage(msg) — text message received +// onMessageFrame(msg, byte_count, opcode) — lossless text/binary frame received // // Call init(url) to connect, send(text) to send, process_event_que() to // pump the event queue, and is_connected() to check state. @@ -117,7 +119,10 @@ class ChatClient : HvWebSocketClient { def override onMessage(msg : string#) { print("[{name}] received: {msg}\n") - received |> push_clone(string(msg)) + received |> push(string(msg)) + } + def override onMessageFrame(msg : string#; byte_count : int; opcode : ws_opcode) { + if (opcode == ws_opcode.WS_OPCODE_TEXT) onMessage(msg) } } diff --git a/utils/dasHerd/WORKTREES_AND_TASK_TERMINALS.md b/utils/dasHerd/WORKTREES_AND_TASK_TERMINALS.md new file mode 100644 index 0000000000..0b6ff34276 --- /dev/null +++ b/utils/dasHerd/WORKTREES_AND_TASK_TERMINALS.md @@ -0,0 +1,501 @@ +# Worktrees and task terminals + +Status: discussion draft + +This is a focused design document for the first dasHerd workspace application. +It is intentionally separate from `PLAN.md`: the worktree, Git, task-terminal, +and automation contracts have enough nuance that they must be discussed one +section at a time. + +No section below authorizes implementation merely by appearing here. Discuss +and settle each section before implementing the stage that depends on it. + +## Established direction + +- A detachable command host is the foundation beneath dasHerd. Callers do not + own launched OS processes directly: JIT invocations, Git commands, setup + scripts, shells, tests, and agents all execute as hosted command sessions. +- Every hosted command session has process state, a terminal, and a durable + log whether or not its terminal is currently visible. The UI and automation + attach to the session; detaching or closing the UI does not stop it. +- Git observation is asynchronous from the first implementation. No Git + command runs on the UI/render thread. +- The application lists the main checkout and linked worktrees, and inspects + the selected tree. +- The repository base and the main checkout are distinct. For example, a + repository may use `origin/master` as its base while its main checkout is on + a feature branch. The UI must show both values rather than label the main + checkout "master". +- A worktree can have a PowerShell terminal rooted in that tree and later an + agent session. +- Worktree creation supports a setup recipe. The built-in MCP bootstrap + (`utils/mcp/setup.das`) is the default recipe; `None` and a user-specified + recipe are alternatives. +- Removal is preceded by an explainable "is it safe to remove?" evaluation. +- Terminals are a general control and debugging surface. Git and setup work + can have visible, colored, scrollable terminals whose output is also logged. +- Every terminal is addressable through live commands. A human, Codex, another + agent, or later automation uses the same read/write terminal operations. +- Execution is not assumed to be local forever. A repository, worktree, Git + process, setup task, shell, or agent may live behind SSH. The UI must always + provide a route to the terminal that owns or can repair the operation. + +## Section 0: detachable command host + +Discussion status: foundational direction agreed; contract details open + +The host is not an agent-specific service added late in the product. It is the +single execution building block used whenever dasHerd calls something. A JIT +compiler run, a Git query, a setup recipe, a test, an interactive PowerShell, +and a long-lived coding agent differ in profile and lifetime, not in whether +they receive a hosted session. + +The caller supplies a target, working directory, structured command and +arguments, environment additions, terminal geometry, and retention policy. +The host owns: + +- process creation and lifetime; +- the PTY and renderless terminal emulator; +- input serialization; +- terminal revisions, scrollback, title, CWD hints, and process status; +- an append-only session log and bounded retained terminal state; +- attach/detach and recovery after the UI disconnects; +- explicit termination and final exit status. + +The same session remains inspectable while running and after exit. A terminal +window is one client of that state, not its owner. Live commands, the human UI, +and future agent routing attach through the same session contract. + +Structured callers such as the Git observer still receive an explicit command +result and raw/captured output suitable for parsing. They do not reconstruct a +result by scraping rendered cells. Their hosted terminal and log remain +available for diagnostics even when the normal UI shows only structured state. + +The host must survive dasHerd UI exit from its first useful version. The later +SSH design decides where the host process physically runs, but not whether the +session has this contract. + +Questions to settle before implementation: + +- Host topology: one OS host process per command session, a supervisor with + child sessions, or a small supervisor plus isolated per-session hosts. +- The local attach protocol, discovery records, versioning, and authentication. +- Log format, rotation, crash consistency, terminal replay, and input-payload + privacy. +- Whether very short structured commands allocate a PTY or use a capture mode + that still exposes the same terminal/log/session API. +- Session retention after successful exit, failed exit, and explicit cleanup. +- What state can be reconstructed after the command host itself crashes; a PTY + cannot be recovered if its owning process is gone. + +### Chunk 0: measure terminal execution overhead + +Discussion status: agreed + +Before choosing a capture fast path or optimizing host topology, measure local +Git through the terminal stack that already exists. SSH Git is a separate Git +installation and execution target; it gets the same probe after SSH exists. + +Compare the same forced-color Git argv through: + +1. direct process capture; +2. direct process capture plus a raw durable log; +3. ConPTY, terminal emulation, and a raw durable log. + +The probe records launch-to-first-output, launch-to-exit, final-output drain, +terminal poll/feed time, log-write time, byte count, and exit code. It separates +the cold first run from warmed median and p95 samples. The command set contains +a process-launch baseline, a representative colored repository status, and an +intentional failure to prove nonzero exit propagation. + +One windowed run displays the real terminal with color and scrolling while +retaining its raw log and final exit code. Repeated timing runs are headless. +This first comparison measures in-process ConPTY/emulator/log overhead; the +same probe is rerun through detach/IPC after the minimal host exists. + +No capture-mode or short-command optimization is selected until these numbers +exist. + +The first measurement found raw logging indistinguishable from noise and +in-process terminal overhead of roughly 5-16 ms at process exit. dasHerd keeps +one terminal execution path; it does not add a direct-capture fast path. The +conservative post-exit drain must not block result delivery or scheduling. + +### Chunk 1: measure an isolated session process + +Discussion status: agreed; first measurement complete + +The first process-isolation probe launches a fresh interpreted daScript worker +for every session. The worker owns ConPTY, terminal emulation, and logging and +acknowledges readiness over a pipe. This deliberately simple prototype measures +the complete extra process and runtime boundary before it becomes architecture. + +The fresh worker added roughly 334-345 ms at median and peaked near 71 MiB +working set in one status sample. Almost all latency occurred before the worker +ready acknowledgement; terminal execution inside the worker continued to match +the in-process lane. Therefore an interpreted worker compiled afresh per Git +query is rejected. Per-session isolation itself remains open pending the same +probe with a small AOT/native host; a persistent per-worktree host is the next +fallback, not an unmeasured optimization. + +### Chunk 2: smallest persistent watcher + +Discussion status: first local slice implemented + +One persistent JIT watcher owns multiple PTYs and terminal emulators. Browser, +UI, live-command, and future agent surfaces are clients of this process; they +do not own its child processes. The first client is a minimal browser control +panel. The local protocol is authenticated HTTP plus WebSocket on +`127.0.0.1` only. + +The first API provides health and session listing, launch, UTF-8 input, resize, +termination, attach/detach, snapshots, and controller heartbeats. Many clients +may observe a session, but only one client holds its controller lease. Browser +close, explicit detach, and heartbeat expiry release that lease without +terminating the child. Polling is bounded per session on each watcher tick so +one noisy PTY cannot create an unbounded drain loop. + +Each session writes the following under +`logs/dasHerd/watcher/sessions//`: + +- `session.json`: immutable launch request; +- `output.raw`: exact PTY output bytes, flushed as they arrive; +- `events.jsonl`: lifecycle, timeout, exit, drain, and controller events. + +Input payload contents are deliberately absent from the event log. An optional +external wall deadline terminates hung children and retains `wall_timeout` as +the final reason. Process exit is reported immediately; raw-output drain uses +the existing conservative 250 ms quiet interval without delaying the exit +observation. + +Focused validation covers normal output and exit, wall timeout, exclusive +controller transfer, browser/WebSocket disconnect while the child continues, +heartbeat lease expiry, loopback token rejection, and watcher crash. A forced +watcher crash loses its live PTYs as expected, kills their children when the +ConPTY owner disappears, and leaves already-flushed raw logs readable. PTY +recovery after watcher death is explicitly not part of this slice. + +Still deferred are remote authentication/pairing, TLS/LAN binding, SSH target +transport, styled browser terminal rendering, replay after watcher restart, +log rotation and retention policy, native dasHerd UI integration, and the +live-command terminal schema. + +## Section 1: repository, base, and worktree identity + +Discussion status: open + +The first model needs to distinguish: + +- an execution target, initially the local machine and later an SSH target; +- a repository identity on that target; +- the repository's configured or detected base ref; +- the main checkout, which is a special worktree but not necessarily the base + branch; +- linked worktrees discovered from Git; +- worktrees created and managed by dasHerd; +- a stable session identity independent of a branch name. + +A path alone is not a global identity once SSH exists. Candidate identities +therefore include at least `target ID + repository Git-common-dir` for a +repository and `repository ID + canonical worktree path` for an initial +worktree identity. Session records get their own generated IDs. + +Questions to settle: + +- Is the base ref stored per repository, per worktree, or both with an + override? +- Are externally created worktrees fully manageable or initially read-only? +- Where are default managed worktrees placed, and how editable is that path? +- Do we show a virtual base row, or show the base only in the repository header + until it has a real worktree? + +## Section 2: asynchronous Git observation + +Discussion status: open + +Background observation needs structured, non-interactive results. It submits +commands through the detachable host, uses Git's porcelain/plumbing output +without color, and publishes versioned snapshots to the UI. Its hosted +terminal and log remain addressable for diagnostics, but terminal text is +never the authority for repository state. + +The initial observer covers: + +- repository and Git-common-dir discovery; +- default-base detection, preferring `origin/HEAD` when available; +- main and linked worktree inventory; +- branch or detached HEAD and commit identity; +- staged, unstaged, untracked, renamed, and conflicted state; +- ahead/behind or containment relative to the selected base; +- locked and prunable worktree state; +- errors, last-success time, and whether a result is refreshing or stale. + +The local Git is currently 2.17.1, so the implementation cannot require modern +options such as `git worktree list --porcelain -z` or +`git branch --show-current`. Managed paths can reject CR/LF, while spaces and +Unicode remain supported. + +Worker rules: + +- invoke Git through hosted sessions with argument arrays, never interpolated + shell commands; +- send immutable/versioned results back to the UI thread; +- discard stale generations and coalesce redundant refresh requests; +- allow independent reads while serializing repository mutations; +- refresh after every mutation; +- do not fetch the network implicitly. + +Questions to settle: + +- Refresh triggers and cadence for selected and unselected worktrees. +- Whether a manual refresh means local observation only, with a separate + explicit Fetch action. +- How much per-command timing and argv detail is retained for the Git debug + window. + +## Section 3: execution targets and command sessions + +Discussion status: open + +Git cannot be designed as "run a Windows process in this local directory." +Commands run against an execution target. The first target implementation is +local; an SSH target later provides the same operations: + +- execute a structured non-interactive command and return a result; +- start or attach to a PTY terminal; +- identify a working directory on that target; +- observe process state and exit status; +- stream updates and retain diagnostics; +- terminate only through an explicit authorized action. + +Target-specific path syntax stays behind this boundary. UI and persisted +records carry a target ID together with paths rather than treating local +absolute paths as universal. + +Questions to settle: + +- How much of the target protocol is defined before implementing local-only + execution? +- Whether the future SSH host runs a small dasHerd helper or begins with direct + SSH command and PTY channels. +- Which environment, credential, and agent-command settings belong to a target + profile. + +## Section 4: Git and setup task terminals + +Discussion status: open + +User-initiated Git mutations, setup recipes, and repair work are activities +with terminals. Their terminal provides: + +- live colored output through a PTY; +- normal terminal scrolling, selection, search, links, and zoom; +- retained logs and structured process status; +- input when credentials, confirmation, or repair is required; +- an obvious "go to terminal" action from the worktree and activity UI; +- a recovery shell in the same target and working directory when a task fails. + +Short background observations remain structured jobs rather than flooding a +terminal. The Git debug UI can show their invocation, timing, exit status, and +bounded output, and can offer a terminal rerun or recovery shell. After any +interactive/mutating task, the structured observer refreshes Git state; the +colored terminal output is not parsed as truth. + +Logs live in the dasHerd user-data `logs/` area with rotation. A completed task +terminal remains inspectable after its process exits. Long setup tasks should +survive closing the UI, which may pull the detachable session host earlier in +the implementation order than agent launching. + +Questions to settle: + +- Which successful task terminals close automatically, remain as history, or + leave an interactive shell open? +- Whether a failed command automatically drops to a shell or offers an + explicit Open recovery shell action. +- Log retention, rotation, and whether input payloads are logged. Input can + contain secrets, so logging output and logging typed input are separate + decisions. +- Whether every mutation must be visibly terminal-backed or whether very short + non-interactive mutations may use the job path while retaining a one-click + diagnostic terminal. + +## Section 5: terminal identity and live-command control + +Discussion status: open + +Every terminal has a stable terminal/session ID independent of whether its +window is currently visible. Live commands must be able to: + +- list terminals with target, worktree, task/session, process, and activity + state; +- open or focus a terminal in the UI; +- inspect its bounded visible viewport and requested scrollback; +- read semantic text or changes since a known terminal revision; +- write UTF-8 text atomically; +- send normalized keys and paste operations; +- observe cursor, title, current-directory hint, exit state, and revisions. + +The same operations serve the user, Codex controlling dasHerd, another agent, +and future automation. The PTY receives the same bytes regardless of source; +there is no weaker "automation terminal." The control plane may still record +origin metadata outside the byte stream for audit, loop prevention, and +permissions. + +Input operations are serialized as complete events so a paste or prompt cannot +interleave byte-by-byte with human typing. This must be reconciled with the +single-input-lease rule for detachable sessions: live commands from the +lease-owning client are straightforward, while cross-client and cross-agent +writes need an explicit transfer, queue, or policy. + +Questions to settle: + +- The exact live-command names and bounded read/inspection schemas. +- Text, key, and paste operations versus an expert raw-byte operation. +- Whether writes require the input lease, can be queued for its owner, or can + use separately granted automation capability. +- What provenance is retained without making terminal behavior differ by + writer. + +## Section 6: basic application layout and navigation + +Discussion status: open + +The first application shape is: + +- a repository header that shows target and base; +- a draggable left rail containing the main checkout and linked worktrees; +- a right workspace for inspection and the selected terminal; +- a Git/tasks activity window containing running and retained jobs; +- status and failure affordances that always navigate to the relevant + terminal or recovery terminal. + +Each worktree row eventually shows branch/HEAD, dirty/conflict state, +refresh/error state, setup state, and live terminal/agent activity. Switching +worktrees does not restart their terminals. + +The Git/tasks window is a terminal when a task has a terminal, not a custom +plain-text log approximation. Structured Git observations may appear as debug +records beside the terminal activities. + +Questions to settle: + +- Default docking: fixed worktree rail plus terminal, or fully dockable + inspector/activity windows from the first version. +- Whether inspection sits above the terminal, in a separate dock, or behind a + tab. +- How completed task terminals are grouped and pruned from the activity UI. + +## Section 7: worktree creation and setup recipes + +Discussion status: open + +The initial creation flow collects a name, new branch, base ref, target path, +setup recipe, and post-create action. The default setup recipe is the MCP +worktree bootstrap; `None` and a user-entered recipe remain available. + +Recipes are structured command profiles with an executable, argument array, +working directory, environment additions, and placeholders such as repository +root, worktree root, target, and bootstrap daslang. Repository-provided recipes +must not execute merely because a repository was opened. + +Creation progresses through visible, retryable states: + +1. validate branch, base, target, and path; +2. create the worktree; +3. publish refreshed structured state; +4. run the selected setup recipe in a task terminal; +5. preserve and clearly mark the tree if setup fails; +6. open a shell or launch the selected agent after success. + +Once Git has created a real worktree, setup failure does not silently delete +it. The user can repair it in the task/recovery terminal, retry setup, keep the +tree, or proceed to the separately guarded removal flow. + +Questions to settle: + +- New branches only in v1, or attaching an existing branch too. +- Default worktree path and branch-name derivation. +- Recipe configuration location and first-use trust UI. +- Whether a shell may open while setup is still running. + +## Section 8: removal safety and recovery + +Discussion status: open + +"Is it safe to remove?" produces `Safe`, `Needs review`, or `Blocked` with +specific evidence. The mutation worker revalidates immediately before removal +to avoid acting on a stale UI snapshot. + +Initial evidence includes: + +- main checkout and protected-target rules; +- locked/prunable state; +- dasHerd-owned terminals, agents, setup jobs, and mutations; +- staged, unstaged, untracked, and conflicted changes; +- branch containment relative to the selected base; +- whether the branch is checked out elsewhere; +- whether repository, target, and path still match the inspected identity. + +Every blocking or review condition offers a route to the relevant terminal so +the user or an agent can inspect, commit, move, clean, or otherwise repair the +tree and ask again. + +Initial removal uses `git worktree remove` without force. Worktree removal and +branch deletion are separate operations; branch deletion uses the safe Git +operation rather than forced deletion. A force-removal design, if added, is a +later discussion. + +Questions to settle: + +- Exact distinction between `Needs review` and `Blocked`. +- Whether unpushed and not-contained-in-base are separate warnings. +- What evidence is sufficient for remote targets whose connection is down. +- Whether removal of worktrees not created by dasHerd is permitted in v1. + +## Section 9: agents, cross-agent communication, and self-prompting + +Discussion status: open, future-facing + +Agent integration should be built on terminal/session capabilities rather than +brand-specific screen scraping. A hosted PowerShell rooted in the worktree can +launch Codex, Claude Code, Pi, OpenCode, or a custom command. Closing the UI +must not stop the hosted terminal or agent. + +Cross-agent communication is a routed terminal write to a stable session ID. +Self-prompting is the same operation with source and destination equal. Both +use the ordinary terminal read/write contract; neither requires a second +hidden agent-control protocol. + +Terminal equivalence does not mean uncontrolled recursion. The control plane +can retain source session, destination session, event ID, parent event, and +timestamp outside the PTY stream. Later policy can use that provenance for +authorization, rate limits, hop/loop protection, and an inspectable audit +trail without changing what bytes the terminal receives. + +Questions to settle later: + +- Per-session permission to accept user, live-command, cross-agent, and + self-prompt writes. +- Loop and runaway protection that remains visible and overridable. +- Delivery acknowledgement: accepted into the terminal input queue versus + semantically acted upon by the agent. +- How an agent discovers addressable sessions without exposing unrelated + repositories or targets. + +## Tentative discussion and implementation order + +This order is a discussion aid, not an approved implementation schedule: + +1. Settle Section 0 and the core of Section 5: host, log, terminal, attach, and + live-command contracts. +2. Implement and stress the minimal local detachable host before building + worktree or agent policy on it. +3. Settle Sections 1-3: identity, asynchronous observation, execution target. +4. Implement the tested hosted Git observer and basic worktree/inspection app. +5. Settle Sections 4 and 6: task-terminal behavior and UI navigation. +6. Add worktree PowerShell terminals, Git activity/debug terminals, and the + live-command terminal surface. +7. Settle and implement Section 7 creation/setup. +8. Settle and implement Section 8 safe removal/recovery. +9. Settle Section 9 before one-click durable agent launching and any + cross-agent or self-prompt automation. diff --git a/utils/dasHerd/chunk0/README.md b/utils/dasHerd/chunk0/README.md new file mode 100644 index 0000000000..10cdc89c8e --- /dev/null +++ b/utils/dasHerd/chunk0/README.md @@ -0,0 +1,58 @@ +# Chunk 0: local Git through the terminal + +This probe measures the cost of using the existing Windows terminal stack for +Git before dasHerd chooses a fast path or moves terminal ownership into a +detachable host. + +It compares the same Git operation through three lanes: + +1. direct process capture; +2. direct capture plus a raw log; +3. ConPTY plus terminal emulation plus a raw log. + +Run the headless benchmark from the repository root: + +```text +bin\Release\daslang.exe utils\dasHerd\chunk0\benchmark_git_terminal.das -- --warmup=5 --rounds=30 +``` + +Run the visible terminal probe with the local dasImgui module: + +```text +bin\Release\daslang-live.exe -load_module modules\dasLiveHost -load_module modules\dasImgui utils\dasHerd\chunk0\git_terminal_window.das +``` + +The visible probe starts maximized at 150% zoom, displays the invocation in a +dim `$ command` visual header followed by colored Git output, and writes the +process's raw byte stream under `logs/dasHerd/`. The header is terminal view +state, separate from emulator state and the raw log. Ctrl+mouse-wheel and the +bottom buttons change zoom in 5% steps. `imgui_snapshot` exposes the terminal's +`visual_header`, screen text, cursor, selection, scrolling, and rendering +metrics to live commands, so an agent can inspect the same terminal without +image recognition. + +## First measurement + +Measured 2026-07-20 on Windows 11 Pro 10.0.26200, an AMD Ryzen Threadripper +3990X, Git 2.17.1.windows.1, and Release daScript binaries. Each result has five +unrecorded warmups and 30 recorded samples. + +The table reports launch-to-root-process-exit latency. This is the fair measure +of execution overhead; terminal `total` additionally includes the conservative +250 ms quiet period used to retain late ConHost output. + +| command | direct p50 / p95 | direct + log p50 / p95 | terminal + log p50 / p95 | terminal p50 overhead | +| --- | ---: | ---: | ---: | ---: | +| `git --version` | 40.2 / 51.0 ms | 39.3 / 49.9 ms | 44.9 / 60.4 ms | +4.7 ms vs 40.2 ms, 1.12x | +| colored `git status --short --branch` | 71.5 / 79.0 ms | 71.3 / 85.5 ms | 87.2 / 92.0 ms | +15.7 ms, 1.22x | +| intentional missing ref | 42.6 / 46.4 ms | 42.9 / 50.5 ms | 58.5 / 59.9 ms | +15.9 ms, 1.37x | + +Raw-log-only median differences were -0.9 ms, -0.2 ms, and +0.3 ms. At this +sample size that is scheduler noise, so logging does not justify a separate +fast path. ConPTY and terminal emulation have a real but modest cost for these +short commands. We should repeat this probe after detach/IPC exists before +deciding whether that additional boundary needs optimization. + +Both successful commands returned zero through every lane. The missing-ref +command returned 128, and every lane contained the expected diagnostic. The +terminal logs also retained the forced ANSI color stream. diff --git a/utils/dasHerd/chunk0/benchmark_git_terminal.das b/utils/dasHerd/chunk0/benchmark_git_terminal.das new file mode 100644 index 0000000000..6aa632105b --- /dev/null +++ b/utils/dasHerd/chunk0/benchmark_git_terminal.das @@ -0,0 +1,202 @@ +options gen2 +options indenting = 4 + +require git_terminal_probe +require daslib/fio +require strings +require math + +struct BenchmarkOptions { + repository : string + warmup : int = 5 + rounds : int = 30 +} + +struct LaneSummary { + ok : bool + total_p50_us : int64 = -1l + total_p95_us : int64 = -1l + exit_p50_us : int64 = -1l + exit_p95_us : int64 = -1l + first_p50_us : int64 = -1l + first_p95_us : int64 = -1l +} + +def private parse_options() : BenchmarkOptions { + var cfg = BenchmarkOptions(repository = get_das_root()) + for (arg in get_command_line_arguments()) { + if (starts_with(arg, "--repo=")) { + cfg.repository = slice(arg, length("--repo=")) + } elif (starts_with(arg, "--warmup=")) { + cfg.warmup = max(0, to_int(slice(arg, length("--warmup=")))) + } elif (starts_with(arg, "--rounds=")) { + cfg.rounds = max(1, to_int(slice(arg, length("--rounds=")))) + } + } + return cfg +} + +def private lane_name(lane : GitProbeLane) : string { + if (lane == GitProbeLane.direct_capture) return "direct" + if (lane == GitProbeLane.direct_logged) return "direct+log" + return "terminal+log" +} + +def private percentile_us(var values : array; numerator : int) : int64 { + if (empty(values)) return -1l + sort(values) + let index = clamp((length(values) * numerator + 99) / 100 - 1, + 0, length(values) - 1) + return values[index] +} + +def private summarize(samples : array const) : LaneSummary { + var total : array + var exit : array + var first : array + total |> reserve(length(samples)) + exit |> reserve(length(samples)) + first |> reserve(length(samples)) + for (sample in samples) { + total |> push(sample.total_us) + exit |> push(sample.exit_us) + if (sample.first_output_us >= 0l) first |> push(sample.first_output_us) + } + return LaneSummary( + ok = true, + total_p50_us = percentile_us(total, 50), + total_p95_us = percentile_us(total, 95), + exit_p50_us = percentile_us(exit, 50), + exit_p95_us = percentile_us(exit, 95), + first_p50_us = percentile_us(first, 50), + first_p95_us = percentile_us(first, 95)) +} + +def private summary_text(summary : LaneSummary const) : string { + return ("total p50={summary.total_p50_us}us p95={summary.total_p95_us}us; " + + "exit p50={summary.exit_p50_us}us p95={summary.exit_p95_us}us; " + + "first p50={summary.first_p50_us}us p95={summary.first_p95_us}us") +} + +def private sample_tsv(sample : GitProbeSample const; iteration : int) : string { + return ("{sample.command}\t{lane_name(sample.lane)}\t{iteration}\t" + + "{sample.exit_code}\t{sample.output_bytes}\t{sample.launch_us}\t" + + "{sample.first_output_us}\t{sample.exit_us}\t{sample.drained_us}\t" + + "{sample.poll_feed_us}\t{sample.log_write_us}\t{sample.total_us}\t" + + "{sample.error}\n") +} + +def private sample_ok(command : GitProbeCommand const; + sample : GitProbeSample const) : bool { + if (!empty(sample.error)) return false + let exit_ok = command.expected_success ? sample.exit_code == 0l : sample.exit_code != 0l + return exit_ok && find(sample.output_text, command.expected_text) >= 0 +} + +def private run_lane(command : GitProbeCommand const; lane : GitProbeLane; + warmup, rounds : int; root : string; + var result_file : FILE const?) : LaneSummary { + var samples : array + samples |> reserve(rounds) + let prefix = "{command.name}_{lane_name(lane)}" + for (iteration in range(warmup + rounds)) { + let measured = iteration >= warmup + let log_path = (lane == GitProbeLane.direct_capture ? "" : + path_join(root, "logs/{prefix}_{iteration}.raw")) + var sample <- (lane == GitProbeLane.terminal_logged ? + run_terminal_probe(command, log_path) : + run_direct_probe(command, log_path)) + if (!sample_ok(command, sample)) { + print(("FAIL {command.name}/{lane_name(lane)}: rc={sample.exit_code} " + + "error={sample.error}\n")) + return LaneSummary() + } + if (measured) { + if (result_file != null) { + fwrite(result_file, sample_tsv(sample, iteration - warmup)) + } + samples |> emplace(sample) + } + // Preserve one representative raw log per logged lane; remove warmup + // and intermediate logs after their measured writes have completed. + if (!empty(log_path) && iteration != warmup + rounds - 1) { + var remove_error : string + let _ = remove(log_path, remove_error) + } + } + let summary = summarize(samples) + print(("{command.name}/{lane_name(lane)}: {summary_text(summary)}; " + + "bytes={samples[length(samples) - 1].output_bytes}; " + + "rc={samples[length(samples) - 1].exit_code}\n")) + return summary +} + +def private overhead_text(base, measured : int64) : string { + let delta = measured - base + let ratio = base > 0l ? double(measured) / double(base) : 0.0lf + return "{delta}us ({fmt(":.2f", ratio)}x)" +} + +[export] +def main() : int { + let cfg = parse_options() + if (!fexist(cfg.repository)) { + print("repository does not exist: {cfg.repository}\n") + return 2 + } + let temp = create_temp_directory_result("dasherd_git_terminal_chunk0_") + if (!(temp is value)) { + print("could not create benchmark directory: {temp as error}\n") + return 2 + } + let root = temp as value + var mkdir_error : string + if (!mkdir(path_join(root, "logs"), mkdir_error)) { + print("could not create log directory: {mkdir_error}\n") + return 2 + } + let result_path = path_join(root, "samples.tsv") + var result_file = fopen(result_path, "wb") + if (result_file == null) { + print("could not create results file: {result_path}\n") + return 2 + } + fwrite(result_file, + ("command\tlane\titeration\texit_code\toutput_bytes\tlaunch_us\t" + + "first_output_us\texit_us\tdrained_us\tpoll_feed_us\tlog_write_us\t" + + "total_us\terror\n")) + + print("Chunk 0 local Git terminal overhead\n") + print("repository: {cfg.repository}\n") + print("warmup={cfg.warmup}, rounds={cfg.rounds}\n") + print("drain policy: 250000us quiet after root-process exit\n") + var ok = true + for (command in make_git_probe_commands(cfg.repository)) { + var summaries : array + summaries |> reserve(3) + for (lane in [GitProbeLane.direct_capture, + GitProbeLane.direct_logged, + GitProbeLane.terminal_logged]) { + let summary = run_lane(command, lane, cfg.warmup, cfg.rounds, + root, result_file) + summaries |> push(summary) + if (!summary.ok) { + ok = false + break + } + } + if (ok && length(summaries) == 3) { + print(("{command.name}/overhead at process exit: log=" + + overhead_text(summaries[0].exit_p50_us, summaries[1].exit_p50_us) + + "; terminal+log=" + + overhead_text(summaries[0].exit_p50_us, summaries[2].exit_p50_us) + + "\n")) + } + break if (!ok) + } + fflush(result_file) + fclose(result_file) + print("samples: {result_path}\n") + print("representative logs: {path_join(root, "logs")}\n") + return ok ? 0 : 1 +} diff --git a/utils/dasHerd/chunk0/git_terminal_probe.das b/utils/dasHerd/chunk0/git_terminal_probe.das new file mode 100644 index 0000000000..1bc9e57ccf --- /dev/null +++ b/utils/dasHerd/chunk0/git_terminal_probe.das @@ -0,0 +1,234 @@ +options gen2 +options indenting = 4 + +module git_terminal_probe shared + +require terminal/terminal public +require daslib/fio public +require daslib/strings_boost +require strings public + +enum public GitProbeLane { + direct_capture + direct_logged + terminal_logged +} + +struct public GitProbeCommand { + name : string + argv : array + command_line : string + expected_text : string + expected_success : bool = true +} + +struct public GitProbeSample { + command : string + lane : GitProbeLane + exit_code : int64 = -1l + output_bytes : int + launch_us : int64 = -1l + first_output_us : int64 = -1l + exit_us : int64 = -1l + drained_us : int64 = -1l + poll_feed_us : int64 + log_write_us : int64 + total_us : int64 + log_path : string + output_text : string + error : string +} + +def private elapsed_us(started : int64) : int64 { + return get_time_nsec(started) / 1000l +} + +def private quote_terminal_arg(arg : string) : string { + if (empty(arg)) return "\"\"" + if (find(arg, " ") < 0 && find(arg, "\t") < 0 && find(arg, "\"") < 0) { + return arg + } + // Chunk 0 targets Windows ConPTY. Windows paths cannot contain a quote; + // reject that uncommon case instead of pretending this is a general shell + // command-line encoder. + if (find(arg, "\"") >= 0) return "" + return "\"{arg}\"" +} + +def public make_terminal_command_line(argv : array const) : string { + var parts : array + parts |> reserve(length(argv)) + for (arg in argv) { + let quoted = quote_terminal_arg(arg) + if (empty(quoted)) return "" + parts |> push(quoted) + } + return join(parts, " ") +} + +def private make_command(name : string; argv : array; + expected_text : string; + expected_success : bool = true) : GitProbeCommand { + var owned_argv : array + owned_argv := argv + return GitProbeCommand( + name = name, + command_line = make_terminal_command_line(owned_argv), + argv <- owned_argv, + expected_text = expected_text, + expected_success = expected_success) +} + +def public make_git_probe_commands(repository : string) : array { + return <- [ + <- make_command("version", ["git", "--version"], "git version"), + <- make_command("status", [ + "git", "-C", repository, "-c", "color.ui=always", + "status", "--short", "--branch"], "##"), + <- make_command("missing-ref", [ + "git", "-C", repository, "-c", "color.ui=always", + "rev-parse", "refs/heads/__dasherd_chunk0_missing_ref__"], + "fatal: ambiguous argument", false)] +} + +def public run_direct_probe(command : GitProbeCommand const; + log_path : string = "") : GitProbeSample { + var sample = GitProbeSample( + command = command.name, + lane = empty(log_path) ? GitProbeLane.direct_capture : GitProbeLane.direct_logged, + log_path = log_path) + var first_byte : array + first_byte |> resize(1) + var first_count = 0 + var remainder : string + let started = ref_time_ticks() + let rc = unsafe(popen_argv(command.argv, 0.0, $(f) { + sample.launch_us = elapsed_us(started) + if (f == null) { + sample.error = "popen_argv returned a null output stream" + return + } + first_count = fread(f, first_byte) + if (first_count > 0) { + sample.first_output_us = elapsed_us(started) + } + remainder = unsafe(fread_to_eof(f)) + })) + sample.exit_us = elapsed_us(started) + sample.drained_us = sample.exit_us + sample.exit_code = int64(rc) + sample.output_bytes = first_count + length(remainder) + sample.output_text = (first_count > 0 ? to_char(int(first_byte[0])) : "") + remainder + if (!empty(log_path)) { + let log_started = ref_time_ticks() + var log_file = fopen(log_path, "wb") + if (log_file == null) { + sample.error = "could not open log: {log_path}" + } else { + if (first_count > 0) { + let _ = fwrite(log_file, first_byte) + } + if (!empty(remainder)) { + fwrite(log_file, remainder) + } + fflush(log_file) + fclose(log_file) + } + sample.log_write_us = elapsed_us(log_started) + } + sample.total_us = elapsed_us(started) + return <- sample +} + +def public run_terminal_probe(command : GitProbeCommand const; + log_path : string; + drain_quiet_us : int64 = 250000l; + timeout_us : int64 = 10000000l) : GitProbeSample { + var sample = GitProbeSample( + command = command.name, + lane = GitProbeLane.terminal_logged, + log_path = log_path) + var log_file = fopen(log_path, "wb") + if (log_file == null) { + sample.error = "could not open log: {log_path}" + return <- sample + } + + let started = ref_time_ticks() + var inscope terminal <- terminal_launch(command.command_line, "", 100, 30) + sample.launch_us = elapsed_us(started) + if (terminal_process_id(terminal) == 0) { + sample.error = terminal_transport_error(terminal) + sample.total_us = elapsed_us(started) + fclose(log_file) + return <- sample + } + + var exit_seen = false + var last_data_us = 0l + while (true) { + let poll_started = ref_time_ticks() + let poll_status = terminal_poll(terminal) + sample.poll_feed_us += elapsed_us(poll_started) + let now_us = elapsed_us(started) + if (poll_status == TerminalPollStatus.data) { + if (sample.first_output_us < 0l) { + sample.first_output_us = now_us + } + sample.output_bytes += length(terminal.read_buffer) + last_data_us = now_us + let log_started = ref_time_ticks() + let _ = fwrite(log_file, terminal.read_buffer) + sample.log_write_us += elapsed_us(log_started) + } elif (poll_status == TerminalPollStatus.error) { + sample.error = terminal_transport_error(terminal) + break + } + + if (!exit_seen && terminal_process_exited(terminal)) { + exit_seen = true + sample.exit_us = now_us + sample.exit_code = terminal_exit_code(terminal) + if (last_data_us == 0l) { + last_data_us = now_us + } + } + + if (poll_status == TerminalPollStatus.closed) { + sample.drained_us = now_us + break + } + // ConPTY keeps its output pipe open after the root process exits. A + // bounded quiet interval after the last observed bytes is the Chunk 0 + // drain policy. ConHost can flush noticeably after root exit when the + // UI polls once per frame; exit_us remains the apples-to-apples primary + // metric and drained_us reports this conservative logging policy. + if (exit_seen && now_us - last_data_us >= drain_quiet_us) { + sample.drained_us = now_us + break + } + if (now_us >= timeout_us) { + sample.error = "terminal probe timed out" + if (!exit_seen) { + let _ = terminal_terminate(terminal) + } + break + } + sleep(0u) + } + + fflush(log_file) + fclose(log_file) + sample.total_us = elapsed_us(started) + if (sample.drained_us < 0l) { + sample.drained_us = sample.total_us + } + if (sample.exit_code < 0l && terminal_process_exited(terminal)) { + sample.exit_code = terminal_exit_code(terminal) + sample.exit_us = elapsed_us(started) + } + var viewport = TerminalViewportSnapshot() + terminal_viewport_snapshot(terminal, 0, viewport) + sample.output_text = viewport.screen_text + return <- sample +} diff --git a/utils/dasHerd/chunk0/git_terminal_window.das b/utils/dasHerd/chunk0/git_terminal_window.das new file mode 100644 index 0000000000..35a3ea4453 --- /dev/null +++ b/utils/dasHerd/chunk0/git_terminal_window.das @@ -0,0 +1,205 @@ +options gen2 +options gc +options persistent_heap + +require imgui/imgui_harness +require imgui/imgui_terminal +require imgui/imgui_fonts +require daslib/safe_addr +require git_terminal_probe +require math +require strings + +var private g_terminal = Terminal() +var private g_terminal_view = ImGuiTerminalState() +var private g_terminal_cache = ImGuiTerminalCache() +var private g_terminal_font : ImFont? +var private g_font_sources : array +var private g_log_file : FILE const? = null +var private g_log_path : string +var private g_command_name : string +var private g_command_line : string +var private g_visual_header : string +var private g_zoom_percent = 150 +var private g_started = 0l +var private g_launch_us = -1l +var private g_first_output_us = -1l +var private g_exit_us = -1l +var private g_drained_us = -1l +var private g_last_data_us = 0l +var private g_output_bytes = 0 +var private g_exit_code = -1l +var private g_done = false +var private g_error : string + +def private elapsed_us() : int64 { + return get_time_nsec(g_started) / 1000l +} + +def private option_value(prefix : string; fallback : string) : string { + for (arg in get_command_line_arguments()) { + if (starts_with(arg, prefix)) return slice(arg, length(prefix)) + } + return fallback +} + +def private select_command(repository : string) { + let requested = option_value("--probe=", "status") + let commands <- make_git_probe_commands(repository) + var index = 1 + if (requested == "version") { + index = 0 + } elif (requested == "missing-ref") { + index = 2 + } + g_command_name = commands[index].name + g_command_line = commands[index].command_line + g_visual_header = "$ {g_command_line}" +} + +def private zoom_by(delta : int) { + g_zoom_percent = clamp(g_zoom_percent + delta, 50, 300) +} + +def private poll_terminal() { + return if (g_done) + for (_ in range(64)) { + let status = terminal_poll(g_terminal) + let now_us = elapsed_us() + if (status == TerminalPollStatus.data) { + if (g_first_output_us < 0l) { + g_first_output_us = now_us + } + g_last_data_us = now_us + g_output_bytes += length(g_terminal.read_buffer) + if (g_log_file != null) { + let _written = fwrite(g_log_file, g_terminal.read_buffer) + fflush(g_log_file) + } + } elif (status == TerminalPollStatus.error) { + g_error = terminal_transport_error(g_terminal) + g_done = true + break + } + if (g_exit_us < 0l && terminal_process_exited(g_terminal)) { + g_exit_us = now_us + g_exit_code = terminal_exit_code(g_terminal) + if (g_last_data_us == 0l) { + g_last_data_us = now_us + } + } + if (status == TerminalPollStatus.closed) { + g_drained_us = now_us + g_done = true + break + } + if (g_exit_us >= 0l && now_us - g_last_data_us >= 250000l) { + g_drained_us = now_us + g_done = true + break + } + break if (status == TerminalPollStatus.idle) + } +} + +[export] +def init() { + harness_init("dasHerd Chunk 0 - Git terminal", 1100, 720) + harness_maximize_window() + g_terminal_font = load_unicode_ui_font(14.0f, g_font_sources) + let repository = option_value("--repo=", get_das_root()) + select_command(repository) + let log_dir = path_join(get_das_root(), "logs/dasHerd") + var mkdir_error : string + let _ = mkdir_rec(log_dir, mkdir_error) + g_log_path = path_join(log_dir, "chunk0_{g_command_name}.raw") + g_log_file = fopen(g_log_path, "wb") + if (g_log_file == null) { + g_error = "could not open raw log: {g_log_path}" + } + g_started = ref_time_ticks() + var inscope launched <- terminal_launch(g_command_line, "", 100, 30) + g_terminal := launched + g_launch_us = elapsed_us() + if (terminal_process_id(g_terminal) == 0) { + g_error = terminal_transport_error(g_terminal) + g_done = true + } +} + +[export] +def update() { + if (!harness_begin_frame()) return + poll_terminal() + harness_new_frame() + GetStyle().FontScaleMain = float(g_zoom_percent) / 100.0f + let viewport = GetMainViewport() + SetNextWindowPos(viewport.WorkPos, ImGuiCond.Always) + SetNextWindowSize(viewport.WorkSize, ImGuiCond.Always) + window(CHUNK0_WIN, (text = "dasHerd Chunk 0 - Git terminal", + closable = false, + flags = ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoMove)) { + text("Git through ConPTY + terminal emulator + raw log") + separator() + let io & = unsafe(GetIO()) + if (IsWindowHovered(ImGuiHoveredFlags.RootAndChildWindows) && io.KeyCtrl) { + if (io.MouseWheel > 0.0f) { + zoom_by(5) + } elif (io.MouseWheel < 0.0f) { + zoom_by(-5) + } + } + let terminal_style = ImGuiTerminalStyle( + visual_header = g_visual_header, + view_height = max(GetTextLineHeight(), + GetContentRegionAvail().y - GetFrameHeightWithSpacing() * 2.0f + - GetStyle().ItemSpacing.y * 2.0f)) + with_font(g_terminal_font) { + let _ = imgui_terminal("git", g_terminal, g_terminal_view, + g_terminal_cache, terminal_style) + } + separator() + text_show(CHUNK0_METRICS, ("exit={g_exit_code} bytes={g_output_bytes} " + + "launch={g_launch_us}us first={g_first_output_us}us " + + "exit_seen={g_exit_us}us drained={g_drained_us}us")) + text_disabled("raw log: {g_log_path}") + if (!empty(g_error)) { + text_colored(CHUNK0_ERROR, + (color = float4(1.0f, 0.35f, 0.30f, 1.0f), text = g_error)) + } + if (small_button(CHUNK0_ZOOM_OUT, (text = "-5%"))) { + zoom_by(-5) + } + same_line() + if (small_button(CHUNK0_ZOOM_IN, (text = "+5%"))) { + zoom_by(5) + } + same_line() + text("Zoom {g_zoom_percent}%") + } + harness_end_frame() +} + +[export] +def shutdown() { + if (!terminal_process_exited(g_terminal)) { + let _ = terminal_terminate(g_terminal) + } + if (g_log_file != null) { + fflush(g_log_file) + fclose(g_log_file) + g_log_file = null + } + terminal_dispose(g_terminal) + harness_shutdown() +} + +[export] +def main() { + init() + while (!exit_requested()) { + update() + harness_maybe_collect_gc() + } + shutdown() +} diff --git a/utils/dasHerd/chunk1/README.md b/utils/dasHerd/chunk1/README.md new file mode 100644 index 0000000000..06bb61d06f --- /dev/null +++ b/utils/dasHerd/chunk1/README.md @@ -0,0 +1,60 @@ +# Chunk 1: fresh process-per-session overhead + +This probe measures the deliberately simplest isolated topology before dasHerd +commits to it. For every command, the benchmark launches a fresh +`daslang.exe` worker. That worker compiles the session-host script, acknowledges +readiness through a flushed stdout pipe, and then owns the same ConPTY, +renderless terminal emulator, and raw log used by Chunk 0. + +The three contemporaneous lanes are: + +1. direct process capture plus raw log; +2. in-process ConPTY, terminal emulation, and raw log; +3. a fresh daScript worker process containing lane 2, with a minimal pipe + acknowledgement standing in for the attach protocol. + +Run from the repository root: + +```text +bin\Release\daslang.exe utils\dasHerd\chunk1\benchmark_session_host.das -- --warmup=5 --rounds=30 +``` + +Add `--discard` for disposable smoke runs. The worker's ready timestamp +includes OS process creation, daScript startup, compilation, module +initialization, and delivery of the first IPC byte. Hosted exit time is ready +time plus the worker's independently measured launch-to-target-exit time. The +250 ms conservative ConHost drain is included only in worker total, not hosted +exit. + +## First measurement + +Measured 2026-07-20 on the same machine and Release build as Chunk 0, using +five unrecorded warmups and 30 recorded samples per command. + +| command | direct exit p50 / p95 | in-process terminal p50 / p95 | fresh host p50 / p95 | fresh-host delta | +| --- | ---: | ---: | ---: | ---: | +| `git --version` | 42.1 / 54.7 ms | 56.0 / 69.0 ms | 389.9 / 437.2 ms | +333.8 ms | +| colored `git status --short --branch` | 74.0 / 86.5 ms | 89.5 / 99.5 ms | 432.6 / 525.8 ms | +343.0 ms | +| intentional missing ref | 45.7 / 57.6 ms | 57.8 / 70.2 ms | 402.4 / 514.7 ms | +344.6 ms | + +The worker-ready median was 339.8-340.4 ms. Its p95 was 376.7 ms for the first +command and rose to 435.8-450.8 ms during the longer repeated run. The terminal +operation inside the worker remained close to the in-process result: 55.3, +88.8, and 59.6 ms respectively. The additional latency is therefore fresh +daScript process startup and script compilation, not the PTY, emulator, log, +or pipe protocol. + +One separately sampled status worker peaked at approximately 70.8 MiB working +set and 52.5 MiB private memory. This is an interpreted compiler process, so it +is an upper bound rather than a prediction for a small AOT/native host. + +## Decision supported by this probe + +Do not launch and compile an interpreted daScript worker for every short +command. That implementation adds roughly a third of a second per session and +substantial transient memory. + +This result does not reject per-session process isolation. The next fair +topology measurement is a small AOT/native session-host bootstrap running the +same daScript session core. A persistent per-worktree host is the fallback if +an isolated compiled host still costs too much; pooling is not justified yet. diff --git a/utils/dasHerd/chunk1/benchmark_session_host.das b/utils/dasHerd/chunk1/benchmark_session_host.das new file mode 100644 index 0000000000..bd9c6f3bd5 --- /dev/null +++ b/utils/dasHerd/chunk1/benchmark_session_host.das @@ -0,0 +1,315 @@ +options gen2 +options indenting = 4 + +require ../chunk0/git_terminal_probe.das +require daslib/fio +require daslib/strings_boost +require strings +require math + +struct BenchmarkOptions { + repository : string + warmup : int = 5 + rounds : int = 30 + discard : bool +} + +struct HostedSample { + ok : bool + exit_code : int64 = -1l + ready_us : int64 = -1l + hosted_exit_us : int64 = -1l + inner_exit_us : int64 = -1l + inner_total_us : int64 = -1l + outer_total_us : int64 = -1l + output_bytes : int + output_text : string + error : string +} + +struct ComparisonSummary { + direct_exit_p50 : int64 + direct_exit_p95 : int64 + terminal_exit_p50 : int64 + terminal_exit_p95 : int64 + host_ready_p50 : int64 + host_ready_p95 : int64 + hosted_exit_p50 : int64 + hosted_exit_p95 : int64 + hosted_inner_p50 : int64 + hosted_outer_p50 : int64 +} + +def private elapsed_us(started : int64) : int64 { + return get_time_nsec(started) / 1000l +} + +def private parse_options() : BenchmarkOptions { + var cfg = BenchmarkOptions(repository = get_das_root()) + for (arg in get_command_line_arguments()) { + if (starts_with(arg, "--repo=")) { + cfg.repository = slice(arg, length("--repo=")) + } elif (starts_with(arg, "--warmup=")) { + cfg.warmup = max(0, to_int(slice(arg, length("--warmup=")))) + } elif (starts_with(arg, "--rounds=")) { + cfg.rounds = max(1, to_int(slice(arg, length("--rounds=")))) + } elif (arg == "--discard") { + cfg.discard = true + } + } + return cfg +} + +def private percentile_us(var values : array; numerator : int) : int64 { + if (empty(values)) return -1l + sort(values) + let index = clamp((length(values) * numerator + 99) / 100 - 1, + 0, length(values) - 1) + return values[index] +} + +def private read_file(path : string; var error : string) : string { + var file = fopen(path, "rb") + if (file == null) { + error = "could not read {path}" + return "" + } + let result = unsafe(fread_to_eof(file)) + fclose(file) + return result +} + +def private parse_host_result(output : string; var sample : HostedSample) { + for (line in split_by_chars(output, "\n")) { + if (!starts_with(line, "DASHERD_HOST_RESULT\t")) continue + let fields <- split_by_chars(strip(line), "\t") + if (length(fields) != 10) { + sample.error = "malformed host result: {line}" + return + } + sample.exit_code = to_int64(fields[1]) + sample.inner_exit_us = to_int64(fields[4]) + sample.inner_total_us = to_int64(fields[8]) + sample.output_bytes = to_int(fields[9]) + sample.ok = true + return + } + sample.error = "session host produced no result: {output}" +} + +def private run_hosted_probe(command : GitProbeCommand const; + repository, log_path, screen_path : string) : HostedSample { + var sample = HostedSample() + let root = get_das_root() + let executable = path_join(root, "bin/Release/daslang.exe") + let worker = path_join(root, + "utils/dasHerd/chunk1/session_host_worker.das") + let argv = [executable, worker, "--", "--repo={repository}", + "--probe={command.name}", "--log={log_path}", "--screen={screen_path}"] + var first_byte : array + first_byte |> resize(1) + var first_count = 0 + var remainder : string + let started = ref_time_ticks() + let worker_rc = unsafe(popen_argv(argv, 0.0, $(f) { + if (f == null) { + sample.error = "session host returned a null output stream" + return + } + first_count = fread(f, first_byte) + if (first_count > 0) { + sample.ready_us = elapsed_us(started) + } + remainder = unsafe(fread_to_eof(f)) + })) + sample.outer_total_us = elapsed_us(started) + let output = (first_count > 0 ? to_char(int(first_byte[0])) : "") + remainder + if (worker_rc != 0) { + sample.error = "session host exited {worker_rc}: {output}" + return <- sample + } + parse_host_result(output, sample) + if (!sample.ok) return <- sample + sample.hosted_exit_us = sample.ready_us + sample.inner_exit_us + sample.output_text = read_file(screen_path, sample.error) + sample.ok = empty(sample.error) + return <- sample +} + +def private expected(command : GitProbeCommand const; exit_code : int64; + output : string; error : string) : bool { + if (!empty(error)) return false + let exit_ok = command.expected_success ? exit_code == 0l : exit_code != 0l + return exit_ok && find(output, command.expected_text) >= 0 +} + +def private remove_if_present(path : string) { + if (empty(path) || !fexist(path)) return + var error : string + let _ = remove(path, error) +} + +def private collect_exit(samples : array const) : array { + var values : array + values |> reserve(length(samples)) + for (sample in samples) { + values |> push(sample.exit_us) + } + return <- values +} + +def private collect_host(samples : array const; + selector : int) : array { + var values : array + values |> reserve(length(samples)) + for (sample in samples) { + if (selector == 0) { + values |> push(sample.ready_us) + } elif (selector == 1) { + values |> push(sample.hosted_exit_us) + } elif (selector == 2) { + values |> push(sample.inner_exit_us) + } else { + values |> push(sample.outer_total_us) + } + } + return <- values +} + +def private summarize(direct, terminal : array const; + hosted : array const) : ComparisonSummary { + var direct_exit <- collect_exit(direct) + var terminal_exit <- collect_exit(terminal) + var host_ready <- collect_host(hosted, 0) + var hosted_exit <- collect_host(hosted, 1) + var hosted_inner <- collect_host(hosted, 2) + var hosted_outer <- collect_host(hosted, 3) + return ComparisonSummary( + direct_exit_p50 = percentile_us(direct_exit, 50), + direct_exit_p95 = percentile_us(direct_exit, 95), + terminal_exit_p50 = percentile_us(terminal_exit, 50), + terminal_exit_p95 = percentile_us(terminal_exit, 95), + host_ready_p50 = percentile_us(host_ready, 50), + host_ready_p95 = percentile_us(host_ready, 95), + hosted_exit_p50 = percentile_us(hosted_exit, 50), + hosted_exit_p95 = percentile_us(hosted_exit, 95), + hosted_inner_p50 = percentile_us(hosted_inner, 50), + hosted_outer_p50 = percentile_us(hosted_outer, 50)) +} + +def private run_command(command : GitProbeCommand const; cfg : BenchmarkOptions const; + root : string; var results : FILE const?) : bool { + var direct : array + var terminal : array + var hosted : array + direct |> reserve(cfg.rounds) + terminal |> reserve(cfg.rounds) + hosted |> reserve(cfg.rounds) + for (iteration in range(cfg.warmup + cfg.rounds)) { + let measured = iteration >= cfg.warmup + let suffix = "{command.name}_{iteration}" + let direct_log = path_join(root, "logs/{suffix}_direct.raw") + let terminal_log = path_join(root, "logs/{suffix}_terminal.raw") + let hosted_log = path_join(root, "logs/{suffix}_hosted.raw") + let screen_path = path_join(root, "{suffix}.screen") + var direct_sample <- run_direct_probe(command, direct_log) + var terminal_sample <- run_terminal_probe(command, terminal_log) + var hosted_sample <- run_hosted_probe(command, cfg.repository, + hosted_log, screen_path) + if (!expected(command, direct_sample.exit_code, + direct_sample.output_text, direct_sample.error) + || !expected(command, terminal_sample.exit_code, + terminal_sample.output_text, terminal_sample.error) + || !expected(command, hosted_sample.exit_code, + hosted_sample.output_text, hosted_sample.error)) { + print(("FAIL {command.name} iteration {iteration}: " + + "direct='{direct_sample.error}' terminal='{terminal_sample.error}' " + + "hosted='{hosted_sample.error}'\n")) + return false + } + if (measured) { + direct |> emplace(direct_sample) + terminal |> emplace(terminal_sample) + hosted |> emplace(hosted_sample) + if (results != null) { + let index = iteration - cfg.warmup + fwrite(results, ("{command.name}\t{index}\t" + + "{direct[length(direct) - 1].exit_us}\t" + + "{terminal[length(terminal) - 1].exit_us}\t" + + "{hosted[length(hosted) - 1].ready_us}\t" + + "{hosted[length(hosted) - 1].inner_exit_us}\t" + + "{hosted[length(hosted) - 1].hosted_exit_us}\t" + + "{hosted[length(hosted) - 1].outer_total_us}\n")) + } + } + remove_if_present(screen_path) + if (iteration != cfg.warmup + cfg.rounds - 1) { + remove_if_present(direct_log) + remove_if_present(terminal_log) + remove_if_present(hosted_log) + } + } + + let summary = summarize(direct, terminal, hosted) + let terminal_overhead = summary.terminal_exit_p50 - summary.direct_exit_p50 + let host_overhead = summary.hosted_exit_p50 - summary.terminal_exit_p50 + print(("{command.name}: direct={summary.direct_exit_p50}us " + + "(p95 {summary.direct_exit_p95}); in-process terminal=" + + "{summary.terminal_exit_p50}us (p95 {summary.terminal_exit_p95}); " + + "session host={summary.hosted_exit_p50}us " + + "(p95 {summary.hosted_exit_p95})\n")) + print(("{command.name}: terminal delta={terminal_overhead}us; " + + "fresh-host delta={host_overhead}us; host ready=" + + "{summary.host_ready_p50}us (p95 {summary.host_ready_p95}); " + + "inner terminal={summary.hosted_inner_p50}us; " + + "worker total including drain={summary.hosted_outer_p50}us\n")) + return true +} + +[export] +def main() : int { + let cfg = parse_options() + let temp = create_temp_directory_result("dasherd_session_host_chunk1_") + if (!(temp is value)) { + print("could not create benchmark directory: {temp as error}\n") + return 2 + } + let root = temp as value + var mkdir_error : string + if (!mkdir(path_join(root, "logs"), mkdir_error)) { + print("could not create log directory: {mkdir_error}\n") + return 2 + } + let result_path = path_join(root, "samples.tsv") + var results = fopen(result_path, "wb") + if (results == null) { + print("could not create result file: {result_path}\n") + return 2 + } + fwrite(results, ("command\titeration\tdirect_exit_us\tterminal_exit_us\t" + + "host_ready_us\thost_inner_exit_us\thosted_exit_us\thost_total_us\n")) + print("Chunk 1 fresh process-per-session overhead\n") + print("repository: {cfg.repository}\n") + print("warmup={cfg.warmup}, rounds={cfg.rounds}\n") + var ok = true + for (command in make_git_probe_commands(cfg.repository)) { + if (!run_command(command, cfg, root, results)) { + ok = false + break + } + } + fflush(results) + fclose(results) + if (cfg.discard && ok) { + let removed = rmdir_rec_result(root) + if (!(removed is value)) { + print("could not discard benchmark directory: {removed as error}\n") + return 2 + } + print("benchmark artifacts discarded\n") + } else { + print("samples: {result_path}\n") + print("representative logs: {path_join(root, "logs")}\n") + } + return ok ? 0 : 1 +} diff --git a/utils/dasHerd/chunk1/session_host_worker.das b/utils/dasHerd/chunk1/session_host_worker.das new file mode 100644 index 0000000000..81a605c5e7 --- /dev/null +++ b/utils/dasHerd/chunk1/session_host_worker.das @@ -0,0 +1,74 @@ +options gen2 +options indenting = 4 + +require ../chunk0/git_terminal_probe.das +require daslib/fio +require strings + +struct WorkerOptions { + repository : string + probe : string = "status" + log_path : string + screen_path : string +} + +def private option_value(prefix : string; fallback : string = "") : string { + for (arg in get_command_line_arguments()) { + if (starts_with(arg, prefix)) return slice(arg, length(prefix)) + } + return fallback +} + +def private parse_options() : WorkerOptions { + return WorkerOptions( + repository = option_value("--repo=", get_das_root()), + probe = option_value("--probe=", "status"), + log_path = option_value("--log="), + screen_path = option_value("--screen=")) +} + +def private command_index(name : string) : int { + if (name == "version") return 0 + if (name == "missing-ref") return 2 + return 1 +} + +[export] +def main() : int { + let cfg = parse_options() + if (empty(cfg.log_path) || empty(cfg.screen_path)) { + fprint(fstderr(), "session host requires --log and --screen\n") + return 2 + } + + // This flushed byte is the minimal IPC-ready acknowledgement. The parent + // timestamps its arrival, so process creation, daScript compilation, and + // worker initialization are measured rather than inferred. + fprint(fstdout(), "DASHERD_HOST_READY\n") + fflush(fstdout()) + + let commands <- make_git_probe_commands(cfg.repository) + let sample <- run_terminal_probe(commands[command_index(cfg.probe)], + cfg.log_path) + if (!empty(sample.error)) { + fprint(fstderr(), "session host probe failed: {sample.error}\n") + return 1 + } + + var screen = fopen(cfg.screen_path, "wb") + if (screen == null) { + fprint(fstderr(), "could not create screen snapshot: {cfg.screen_path}\n") + return 1 + } + fwrite(screen, sample.output_text) + fflush(screen) + fclose(screen) + + fprint(fstdout(), + ("DASHERD_HOST_RESULT\t{sample.exit_code}\t{sample.launch_us}\t" + + "{sample.first_output_us}\t{sample.exit_us}\t{sample.drained_us}\t" + + "{sample.poll_feed_us}\t{sample.log_write_us}\t{sample.total_us}\t" + + "{sample.output_bytes}\n")) + fflush(fstdout()) + return 0 +} diff --git a/utils/dasHerd/watcher/README.md b/utils/dasHerd/watcher/README.md new file mode 100644 index 0000000000..8f4e1264a2 --- /dev/null +++ b/utils/dasHerd/watcher/README.md @@ -0,0 +1,58 @@ +# dasHerd watcher + +The watcher is dasHerd's local detachable terminal host. One persistent JIT +process owns multiple PTYs, terminal emulators, and durable session logs while +native/live-command surfaces attach as clients. The browser panel is an +interactive debug and recovery fallback; the ImGui client remains the primary UI. + +Run it from the repository root: + +```powershell +bin\Release\daslang.exe -jit utils\dasHerd\watcher\main.das +``` + +Run the docked native client with the token printed by the watcher: + +```powershell +bin\Release\daslang-live.exe utils\dasHerd\watcher\rich_client.das -- --token= +``` + +The client opens maximized at 150% zoom. Its left pane lists sessions and can +launch or terminate them; the right pane attaches with control and renders raw +PTY bytes through the daScript terminal emulator. `--port=9191` is available on +both processes when the default port is occupied. + +The watcher prints a token-bearing control-panel URL. Optional arguments after +`--` are `--port=9191`, `--token=`, and `--log-root=`. + +This first slice binds only to `127.0.0.1`. Its startup token prevents +accidental access from an unrelated local page; it is not the future remote +authentication design. Do not expose this port through a proxy or tunnel. + +HTTP endpoints under `/api/v1/` provide health, session listing, launch, +input, resize, termination, and a deferred `POST /gc` diagnostic. `/ws` provides attach/detach, controller +leases, heartbeats, session listing/launch/termination, input, resize, terminal +snapshots, and bounded raw PTY replay. +Raw output is delivered as binary WebSocket frames, so the browser can render +the same color and control sequences and send keyboard input back to the PTY. +Every request must include the startup token as the `token` query parameter. + +The script exposes `init`, `update`, and `shutdown` for lifecycle hosts. Its +standalone loop performs optional GC only after `update` returns, when request +temporaries are dead; all state that must survive collection is globally rooted. +Automatic collection is fragmentation-driven and rate-limited. `POST /gc` +coalesces a request for a validated collection at that same safe boundary. + +The browser terminal vendors xterm.js 5.5.0 with the matching fit 0.10.0, +Unicode 11 0.8.0, and web-links 0.11.0 addons under `vendor/xterm/`. It works +offline; the corresponding MIT license files are kept beside the assets. + +Session logs are stored under +`logs/dasHerd/watcher/sessions//`. Closing a client releases its +controller lease but does not stop its child. Killing the watcher necessarily +loses its live PTYs; already-flushed logs remain readable. + +The native terminal registers its full `ImGuiTerminalState` with the live-command +surface. `imgui_snapshot` can therefore read terminal text, selection, geometry, +cursor/blink state, performance counters, and input revisions without a screenshot; +`imgui_click` plus `imgui_key_type` drives the same input path as a human user. diff --git a/utils/dasHerd/watcher/control.html b/utils/dasHerd/watcher/control.html new file mode 100644 index 0000000000..d0c341b5f1 --- /dev/null +++ b/utils/dasHerd/watcher/control.html @@ -0,0 +1,291 @@ + + + + + + dasHerd watcher terminal + + + +
+ +
+
+ + + + + + No session selected +
+
$
+
+
+
+ Loading terminal... + + + + + 150% +
+
+ + + diff --git a/utils/dasHerd/watcher/main.das b/utils/dasHerd/watcher/main.das new file mode 100644 index 0000000000..5691dad880 --- /dev/null +++ b/utils/dasHerd/watcher/main.das @@ -0,0 +1,217 @@ +options gen2 +options rtti +options persistent_heap +options gc +options indenting = 4 + +require ./watcher_server.das +require daslib/random +require daslib/fio +require daslib/module_path +require live_host +require strings +require math + +// Lifecycle state is global: standalone JIT heap collection cannot see ordinary stack locals as +// GC roots. main therefore keeps no collectable value alive across maybe_collect_gc(). The same +// init/update/shutdown boundary also lets daslang-live (and future hosts) own the outer loop. +var private g_server : DasHerdWatcherServer? +var private g_args_parsed = false +var private g_watcher_initialized = false +var private g_server_started = false +var private g_exit_code = 0 +var private g_port = 9191 +var private g_token : string +var private g_log_root : string +var private g_last_memory_log_at = 0l +var private g_last_gc_at = 0l +let GC_MIN_INTERVAL_SECONDS = 60l + +def private option_value(prefix : string; fallback : string = "") : string { + for (argument in get_command_line_arguments()) { + if (starts_with(argument, prefix)) return slice(argument, length(prefix)) + } + return fallback +} + +def private make_local_token : string { + // This first slice is deliberately loopback-only. The token prevents an + // accidental drive-by from another local page; remote deployment will use + // a real authentication and pairing design. + var seed = random_seed(int(ref_time_ticks())) + return "{random_uint(seed)}-{random_uint(seed)}-{random_uint(seed)}-{random_uint(seed)}" +} + +// Parse directly into global lifecycle state so no command-line strings survive on main's stack. +def private parse_watcher_args() { + g_args_parsed = true + g_exit_code = 0 + g_port = clamp(to_int(option_value("--port=", "9191")), 1024, 65535) + g_token = option_value("--token=") + if (empty(g_token)) { + g_token = make_local_token() + } + g_log_root = option_value("--log-root=", + path_join(get_das_root(), "logs/dasHerd/watcher/sessions")) +} + +// Log das-managed memory independently of process RSS. All formatting temporaries die before +// main reaches maybe_collect_gc(). +def private log_memory_if_due() { + let now = int64(get_clock()) + if (g_last_memory_log_at != 0l && now - g_last_memory_log_at < 60l) return + g_last_memory_log_at = now + print("dasHerd watcher: memory das_heap={heap_bytes_allocated()}/{heap_total_allocated()} " + + "string_heap={string_heap_bytes_allocated()}/{string_heap_total_allocated()} " + + "allocations={heap_allocation_count()} string_allocations={string_heap_allocation_count()}\n") +} + +// Standalone-loop GC. Request and HTTP-handler locals lived inside update() and are dead by the +// time main calls this function. daslang-live already collects between update calls; an explicit +// request remains useful there for diagnostics. +def private maybe_collect_gc() { + let forced = watcher_take_gc_request() + return if (is_live_mode() && !forced) + let now = int64(get_clock()) + if (!forced && g_last_gc_at != 0l && now - g_last_gc_at < GC_MIN_INTERVAL_SECONDS) return + if (forced) { + g_last_gc_at = now + let gc_started = ref_time_ticks() + print("dasHerd watcher: GC begin reason=forced_endpoint validate=true " + + "das_heap={heap_bytes_allocated()}/{heap_total_allocated()} " + + "string_heap={string_heap_bytes_allocated()}/{string_heap_total_allocated()}\n") + unsafe(heap_collect(true, true)) + print("dasHerd watcher: GC end reason=forced_endpoint " + + "elapsed_ms={int64(get_time_usec(gc_started)) / 1000l} " + + "das_heap={heap_bytes_allocated()}/{heap_total_allocated()} " + + "string_heap={string_heap_bytes_allocated()}/{string_heap_total_allocated()}\n") + return + } + let string_used = string_heap_bytes_allocated() + let string_total = string_heap_total_allocated() + if (string_total > 0ul && string_used * 3ul < string_total * 2ul) { + g_last_gc_at = now + let gc_started = ref_time_ticks() + print("dasHerd watcher: GC begin reason=string_fragmentation validate=true " + + "das_heap={heap_bytes_allocated()}/{heap_total_allocated()} " + + "string_heap={string_used}/{string_total}\n") + unsafe(heap_collect(true, true)) + print("dasHerd watcher: GC end reason=string_fragmentation " + + "elapsed_ms={int64(get_time_usec(gc_started)) / 1000l} " + + "das_heap={heap_bytes_allocated()}/{heap_total_allocated()} " + + "string_heap={string_heap_bytes_allocated()}/{string_heap_total_allocated()}\n") + return + } + let heap_used = heap_bytes_allocated() + let heap_total = heap_total_allocated() + if (heap_total > 0ul && heap_used * 3ul < heap_total) { + g_last_gc_at = now + let gc_started = ref_time_ticks() + print("dasHerd watcher: GC begin reason=heap_fragmentation validate=true " + + "das_heap={heap_used}/{heap_total} " + + "string_heap={string_heap_bytes_allocated()}/{string_heap_total_allocated()}\n") + unsafe(heap_collect(true, true)) + print("dasHerd watcher: GC end reason=heap_fragmentation " + + "elapsed_ms={int64(get_time_usec(gc_started)) / 1000l} " + + "das_heap={heap_bytes_allocated()}/{heap_total_allocated()} " + + "string_heap={string_heap_bytes_allocated()}/{string_heap_total_allocated()}\n") + } +} + +[export] +def init() { + if (!g_args_parsed) { + parse_watcher_args() + } + if (g_server != null || g_watcher_initialized) { + print("dasHerd watcher: init called while already initialized\n") + g_exit_code = 1 + request_exit() + return + } + watcher_reset_gc_request() + g_last_memory_log_at = 0l + g_last_gc_at = 0l + let init_error = watcher_init(g_log_root) + if (!empty(init_error)) { + print("dasHerd watcher: could not initialize logs: {init_error}\n") + g_exit_code = 2 + request_exit() + return + } + g_watcher_initialized = true + + g_server = new DasHerdWatcherServer() + g_server.token = g_token + let watcher_dir = get_this_module_dir() + let vendor_dir = path_join(watcher_dir, "vendor/xterm") + g_server.control_html = path_join(watcher_dir, "control.html") + g_server.xterm_js = path_join(vendor_dir, "xterm.js") + g_server.xterm_css = path_join(vendor_dir, "xterm.css") + g_server.xterm_fit_js = path_join(vendor_dir, "addon-fit.js") + g_server.xterm_unicode_js = path_join(vendor_dir, "addon-unicode11.js") + g_server.xterm_web_links_js = path_join(vendor_dir, "addon-web-links.js") + g_server->init(g_port) + if (!g_server->set_bind_host("127.0.0.1")) { + print("dasHerd watcher: could not select loopback bind address\n") + g_exit_code = 3 + request_exit() + return + } + let start_result = g_server->start() + if (start_result != 0) { + print("dasHerd watcher: server start failed ({start_result})\n") + g_exit_code = 4 + request_exit() + return + } + g_server_started = true + + print("dasHerd watcher ready\n") + print(" control: http://127.0.0.1:{g_port}/?token={g_token}\n") + print(" logs: {g_log_root}\n") + print(" bind: 127.0.0.1:{g_port}\n") +} + +[export] +def update() { + if (!g_server_started || g_server == null) { + request_exit() + return + } + g_server->tick() + log_memory_if_due() + sleep(2u) +} + +// Release lifecycle-owned objects in dependency order. Safe after a partially failed init. +[export] +def shutdown() { + if (g_server_started && g_server != null) { + let _ = g_server->stop() + } + g_server_started = false + if (g_server != null) { + g_server->cleanup_clients() + g_server->cleanup() + unsafe { delete g_server } + g_server = null + } + if (g_watcher_initialized) { + watcher_shutdown() + g_watcher_initialized = false + } + watcher_reset_gc_request() +} + +[export] +def main : int { + parse_watcher_args() + init() + while (!exit_requested()) { + update() + maybe_collect_gc() + } + shutdown() + return g_exit_code +} diff --git a/utils/dasHerd/watcher/rich_client.das b/utils/dasHerd/watcher/rich_client.das new file mode 100644 index 0000000000..1df7b09f66 --- /dev/null +++ b/utils/dasHerd/watcher/rich_client.das @@ -0,0 +1,469 @@ +options gen2 +options gc +options persistent_heap +options no_unused_function_arguments = false + +require imgui/imgui_harness +require imgui/imgui_terminal +require imgui/imgui_fonts +require dashv/dashv_boost +require clipboard/clipboard +require daslib/safe_addr +require daslib/json_boost +require ./watcher_core.das +require math +require strings + +struct private WatcherEnvelope { + @rename = "type" _type : string +} + +struct private WatcherConnectedMessage { + @rename = "type" _type : string + client_id : int +} + +struct private WatcherAttachedMessage { + @rename = "type" _type : string + session_id : string + controls : bool +} + +struct private WatcherSessionMessage { + @rename = "type" _type : string + session_id : string +} + +struct private WatcherErrorMessage { + @rename = "type" _type : string + error : string +} + +struct private WatcherSessionsMessage { + @rename = "type" _type : string + data : array +} + +struct private WatcherRawResetMessage { + @rename = "type" _type : string + offset : int64 +} + +var private g_terminal = Terminal() +var private g_terminal_view = ImGuiTerminalState() +var private g_terminal_cache = ImGuiTerminalCache() +var private g_terminal_font : ImFont? +var private g_font_sources : array +var private g_zoom_percent = 150 +var private g_status = "Starting" +var private g_url : string +var private g_token : string +var private SESSION_ROW : table + +def private option_value(prefix : string; fallback : string = "") : string { + for (argument in get_command_line_arguments()) { + if (starts_with(argument, prefix)) return slice(argument, length(prefix)) + } + return fallback +} + +def private reset_terminal(columns : int = 100; rows : int = 30) { + terminal_dispose(g_terminal) + var inscope created <- terminal_create(columns, rows) + g_terminal := created + g_terminal_view = ImGuiTerminalState() + g_terminal_cache = ImGuiTerminalCache() +} + +def private feed_terminal_frame(message : string#; byte_count : int) { + var bytes : array + bytes |> resize(byte_count) + if (byte_count > 0) { + unsafe { memcpy(addr(bytes[0]), reinterpret(message), byte_count) } + terminal_feed_bytes(g_terminal, bytes) + } +} + +class private WatcherRichClient : HvWebSocketClient { + connected : bool + attached : bool + controls : bool + client_id : int + selected_id : string + attached_id : string + sessions : array + error : string + last_heartbeat : int64 + last_list : int64 + sent_input_bytes : int64 + desired_columns : int + desired_rows : int + sent_columns : int + sent_rows : int + + def override onOpen { + connected = true + error = "" + last_heartbeat = ref_time_ticks() + last_list = ref_time_ticks() + send("\{\"op\":\"list\"\}") + } + + def override onClose { + connected = false + attached = false + controls = false + sent_columns = 0 + sent_rows = 0 + error = "watcher connection closed" + } + + def override onMessage(message : string#) { + var envelope : WatcherEnvelope + let body = string(message) + if (!sscan_json(body, envelope)) { + error = "invalid watcher message" + return + } + if (envelope._type == "connected") { + var incoming : WatcherConnectedMessage + if (sscan_json(body, incoming)) { + client_id = incoming.client_id + } + } elif (envelope._type == "sessions") { + var incoming : WatcherSessionsMessage + if (sscan_json(body, incoming)) { + sessions <- incoming.data + if (empty(selected_id)) { + for (session in sessions) { + if (session.state == "running") { + attach_session(session.id) + break + } + } + } + } + } elif (envelope._type == "launched") { + var incoming : WatcherSessionMessage + if (sscan_json(body, incoming)) { + attach_session(incoming.session_id) + } + } elif (envelope._type == "attached") { + var incoming : WatcherAttachedMessage + if (sscan_json(body, incoming)) { + attached_id = incoming.session_id + attached = true + controls = incoming.controls + g_status = incoming.controls ? "Attached with control" : "Attached read-only" + if (controls) { + if (desired_columns <= 0 || desired_rows <= 0) { + desired_columns = g_terminal.columns + desired_rows = g_terminal.rows + } + flush_resize() + } + } + } elif (envelope._type == "detached") { + attached = false + controls = false + attached_id = "" + sent_columns = 0 + sent_rows = 0 + } elif (envelope._type == "raw_reset") { + var incoming : WatcherRawResetMessage + if (sscan_json(body, incoming)) { + reset_terminal(g_terminal.columns, g_terminal.rows) + g_status = "Raw replay reset at byte {incoming.offset}" + } + } elif (envelope._type == "error") { + var incoming : WatcherErrorMessage + if (sscan_json(body, incoming)) { + error = incoming.error + } + } + } + + def override onMessageFrame(message : string#; byte_count : int; opcode : ws_opcode) { + if (opcode == ws_opcode.WS_OPCODE_TEXT) { + onMessage(message) + } elif (opcode == ws_opcode.WS_OPCODE_BINARY) { + feed_terminal_frame(message, byte_count) + } + } + + def attach_session(session_id : string) { + if (!connected || empty(session_id)) return + var columns = 100 + var rows = 30 + for (session in sessions) { + if (session.id == session_id) { + columns = max(20, session.columns) + rows = max(5, session.rows) + break + } + } + selected_id = session_id + attached = false + controls = false + sent_columns = 0 + sent_rows = 0 + error = "" + reset_terminal(columns, rows) + send("\{\"op\":\"attach\",\"session_id\":{sprint_json(session_id, false)}," + + "\"control\":true,\"raw\":true\}") + } + + def launch(command_line, cwd : string) { + if (!connected) { + error = "watcher is not connected" + return + } + send("\{\"op\":\"launch\",\"command_line\":{sprint_json(command_line, false)}," + + "\"cwd\":{sprint_json(cwd, false)},\"columns\":100,\"rows\":30," + + "\"timeout_ms\":0\}") + } + + def send_input(text : string) { + if (!controls || empty(text)) return + send("\{\"op\":\"input\",\"text\":{sprint_json(text, false)}\}") + sent_input_bytes += int64(length(text)) + } + + def request_resize(columns, rows : int) { + desired_columns = columns + desired_rows = rows + flush_resize() + } + + def flush_resize() { + if (!controls || desired_columns <= 0 || desired_rows <= 0 || + (desired_columns == sent_columns && desired_rows == sent_rows)) return + send("\{\"op\":\"resize\",\"columns\":{desired_columns},\"rows\":{desired_rows}\}") + sent_columns = desired_columns + sent_rows = desired_rows + } + + def terminate_selected() { + if (!connected || empty(selected_id)) return + send("\{\"op\":\"terminate\",\"session_id\":{sprint_json(selected_id, false)}\}") + } + + def refresh() { + if (connected) send("\{\"op\":\"list\"\}") + } + + def pump() { + process_event_que() + if (!connected) return + if (get_time_nsec(last_heartbeat) / 1000000l >= 1000l) { + send("\{\"op\":\"heartbeat\"\}") + last_heartbeat = ref_time_ticks() + } + if (get_time_nsec(last_list) / 1000000l >= 1000l) { + refresh() + last_list = ref_time_ticks() + } + } +} + +var private g_client : WatcherRichClient? + +def private zoom_by(delta : int) { + g_zoom_percent = clamp(g_zoom_percent + delta, 50, 300) +} + +def private selected_session_label() : string { + if (g_client == null || empty(g_client.selected_id)) return "No session selected" + for (session in g_client.sessions) { + if (session.id == g_client.selected_id) { + return "{session.state} pid {session.pid} {session.command_line}" + } + } + return g_client.selected_id +} + +def private draw_session_list() { + let connection = g_client != null && g_client.connected ? "connected" : "disconnected" + text("Watcher: {connection}") + if (small_button(REFRESH_SESSIONS, (text = "Refresh")) && g_client != null) { + g_client->refresh() + } + same_line() + if (small_button(TERMINATE_SESSION, (text = "Terminate")) && g_client != null) { + g_client->terminate_selected() + } + separator() + child(SESSIONS_CHILD, (text = "sessions", size = float2(0.0f, -150.0f), + child_flags = ImGuiChildFlags.Borders, window_flags = ImGuiWindowFlags.None)) { + if (g_client != null && empty(g_client.sessions)) { + text_disabled("No sessions") + } elif (g_client != null) { + for (index in range(length(g_client.sessions))) { + let session = g_client.sessions[index] + let row_text = "[{session.state}] {session.command_line}##{session.id}" + if (selectable(SESSION_ROW[index], (text = row_text))) { + g_client->attach_session(session.id) + } + SESSION_ROW[index].value = session.id == g_client.selected_id + } + } + } + text("New terminal") + input_text_growable(LAUNCH_COMMAND, (text = "Command")) + input_text_growable(LAUNCH_CWD, (text = "Working directory")) + if (button(LAUNCH_SESSION, (text = "Launch and attach")) && g_client != null) { + g_client->launch(LAUNCH_COMMAND.value, LAUNCH_CWD.value) + } +} + +def private draw_terminal_footer() { + if (small_button(TERMINAL_EDIT_MENU, (text = "Edit"))) { + open_popup("terminal_edit_menu") + } + popup_window(TERMINAL_EDIT_POPUP, + (str_id = "terminal_edit_menu", flags = ImGuiWindowFlags.AlwaysAutoResize)) { + if (menu_label(TERMINAL_COPY, (text = "Copy", shortcut = "Ctrl+C", + enabled = g_terminal_view.selection_active))) { + g_status = (imgui_terminal_copy_selection(g_terminal, g_terminal_view) + ? "Selection copied" : "Nothing selected") + } + if (menu_label(TERMINAL_PASTE, (text = "Paste", shortcut = "Ctrl+V"))) { + var pasted = "" + if (clipboard_get_text(pasted) == ClipboardStatus.ok && g_client != null) { + g_client->send_input(terminal_encode_paste(g_terminal, pasted)) + g_status = "Clipboard pasted" + } else { + g_status = "Clipboard unavailable" + } + } + separator() + if (menu_label(TERMINAL_SELECT_ALL, (text = "Select all"))) { + imgui_terminal_select_all(g_terminal, g_terminal_view) + } + if (menu_label(TERMINAL_CLEAR_SELECTION, + (text = "Clear selection", enabled = g_terminal_view.selection_active))) { + imgui_terminal_clear_selection(g_terminal_view) + } + } + same_line() + if (small_button(TERMINAL_VIEW_MENU, (text = "View"))) { + open_popup("terminal_view_menu") + } + popup_window(TERMINAL_VIEW_POPUP, + (str_id = "terminal_view_menu", flags = ImGuiWindowFlags.AlwaysAutoResize)) { + if (menu_label(TERMINAL_ZOOM_IN, (text = "Zoom in", shortcut = "Ctrl++"))) zoom_by(5) + if (menu_label(TERMINAL_ZOOM_OUT, (text = "Zoom out", shortcut = "Ctrl+-"))) zoom_by(-5) + if (menu_label(TERMINAL_ZOOM_RESET, (text = "Reset zoom", shortcut = "Ctrl+0"))) { + g_zoom_percent = 100 + } + separator() + if (menu_label(TERMINAL_SCROLL_BOTTOM, (text = "Scroll to bottom"))) { + g_terminal_view.scroll_offset = 0 + } + } + same_line() + if (small_button(TERMINAL_ZOOM_OUT_BUTTON, (text = "-5%"))) zoom_by(-5) + same_line() + if (small_button(TERMINAL_ZOOM_IN_BUTTON, (text = "+5%"))) zoom_by(5) + same_line() + text("Zoom {g_zoom_percent}%") + same_line() + text_disabled("{g_terminal_view.scrollback_rows} history lines - {g_status}") + if (g_client != null) { + same_line() + text_disabled("input sent {g_client.sent_input_bytes} bytes") + } +} + +[export] +def init() { + harness_init("dasHerd", 1280, 800) + harness_maximize_window() + g_terminal_font = load_unicode_ui_font(14.0f, g_font_sources) + reset_terminal() + LAUNCH_COMMAND.value = "powershell.exe -NoLogo -NoProfile" + LAUNCH_CWD.value = get_das_root() + let port = clamp(to_int(option_value("--port=", "9191")), 1024, 65535) + g_token = option_value("--token=") + g_url = "ws://127.0.0.1:{port}/ws?token={g_token}" + g_client = new WatcherRichClient() + if (empty(g_token)) { + g_client.error = "Pass the watcher token with --token=" + return + } + let result = g_client->init(g_url) + if (result != 0) { + g_client.error = "watcher connection failed ({result})" + } +} + +[export] +def update() { + if (!harness_begin_frame()) return + if (g_client != null) g_client->pump() + harness_new_frame() + GetStyle().FontScaleMain = float(g_zoom_percent) / 100.0f + let viewport = GetMainViewport() + SetNextWindowPos(viewport.WorkPos, ImGuiCond.Always) + SetNextWindowSize(viewport.WorkSize, ImGuiCond.Always) + window(HERDER_WIN, (text = "dasHerd", closable = false, + flags = ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoMove)) { + let io & = unsafe(GetIO()) + if (IsWindowHovered(ImGuiHoveredFlags.RootAndChildWindows) && io.KeyCtrl) { + if (io.MouseWheel > 0.0f) zoom_by(5) + elif (io.MouseWheel < 0.0f) zoom_by(-5) + } + child(SIDEBAR_CHILD, (text = "sidebar", size = float2(330.0f, 0.0f), + child_flags = ImGuiChildFlags.None, window_flags = ImGuiWindowFlags.None)) { + draw_session_list() + } + same_line() + child(TERMINAL_CHILD, (text = "terminal", size = float2(0.0f, 0.0f), + child_flags = ImGuiChildFlags.None, window_flags = ImGuiWindowFlags.None)) { + text(SESSION_LABEL, (text = selected_session_label())) + if (g_client != null && !empty(g_client.error)) { + text_colored(CLIENT_ERROR, + (color = float4(1.0f, 0.35f, 0.30f, 1.0f), text = g_client.error)) + } + separator() + let terminal_style = ImGuiTerminalStyle( + external_input = true, + view_height = max(GetTextLineHeight(), + GetContentRegionAvail().y - GetFrameHeightWithSpacing() + - GetStyle().ItemSpacing.y)) + with_font(g_terminal_font) { + let result <- imgui_terminal("watcher", g_terminal, g_terminal_view, + g_terminal_cache, terminal_style) + if (g_client != null) { + if (!empty(result.input_text)) g_client->send_input(result.input_text) + if (result.resized) g_client->request_resize(result.columns, result.rows) + } + } + separator() + draw_terminal_footer() + } + } + harness_end_frame() +} + +[export] +def shutdown() { + if (g_client != null) { + g_client->close() + g_client->cleanup() + unsafe { delete g_client } + g_client = null + } + terminal_dispose(g_terminal) + harness_shutdown() +} + +[export] +def main() { + init() + while (!exit_requested()) { + update() + harness_maybe_collect_gc() + } + shutdown() +} diff --git a/utils/dasHerd/watcher/tests/test_watcher_core.das b/utils/dasHerd/watcher/tests/test_watcher_core.das new file mode 100644 index 0000000000..7d4b6b806e --- /dev/null +++ b/utils/dasHerd/watcher/tests/test_watcher_core.das @@ -0,0 +1,89 @@ +options gen2 +options rtti + +require dastest/testing_boost public +require ../watcher_core.das +require daslib/fio +require strings + +def private wait_for(session_id, state : string; timeout_ms : int64) : bool { + let started = ref_time_ticks() + while (get_time_nsec(started) / 1000000l < timeout_ms) { + watcher_tick() + let snapshot = watcher_snapshot_json(session_id) + if (find(snapshot, "\"state\":\"{state}\"") >= 0 && + find(snapshot, "\"drained\":true") >= 0) return true + sleep(1u) + } + return false +} + +[test] +def test_watcher_process_lifecycle(t : T?) { + if (get_platform_name() != "windows") return + t |> run("persistent core logs output, times out hangs, and arbitrates control") <| @(t : T?) { + let temp = create_temp_directory_result("dasherd_watcher_test_") + if (!(temp is value)) { + t |> failure("could not create temporary test directory") + return + } + let root = temp as value + t |> equal(watcher_init(path_join(root, "sessions")), "") + + let missing_command = path_join(root, "missing-watcher-command.exe") + let failed = watcher_launch(WatcherLaunchRequest( + command_line = "\"{missing_command}\"", cwd = root, + columns = 80, rows = 20, timeout_ms = 5000l)) + t |> success(!failed.ok, "failed PTY launch is reported to the caller") + t |> success(!empty(failed.session_id), "failed PTY launch retains its diagnostic session") + t |> success(find(watcher_snapshot_json(failed.session_id), "\"state\":\"failed\"") >= 0, + "failed PTY launch is retained in watcher state") + + let quick = watcher_launch(WatcherLaunchRequest( + command_line = "powershell.exe -NoProfile -Command \"Write-Output watcher-core-ok\"", + cwd = root, columns = 80, rows = 20, timeout_ms = 5000l)) + t |> success(quick.ok, quick.error) + t |> success(watcher_accepts_input(quick.session_id), "running session accepts input") + t |> success(wait_for(quick.session_id, "exited", 5000l), "quick command exits and drains") + t |> success(!watcher_accepts_input(quick.session_id), "exited session is replay-only") + let quick_snapshot = watcher_snapshot_json(quick.session_id) + t |> success(find(quick_snapshot, "watcher-core-ok") >= 0, "viewport retains command output") + t |> success(find(quick_snapshot, "\"exit_code\":0") >= 0, "exit code is retained") + let raw <- watcher_output_since(quick.session_id, 0l) + t |> success(find(string(raw.bytes), "watcher-core-ok") >= 0, "raw PTY history can be replayed") + let raw_tail <- watcher_output_since(quick.session_id, raw.next_offset) + t |> equal(length(raw_tail.bytes), 0, "raw replay offset does not duplicate output") + t |> success(fexist(path_join(path_join(path_join(root, "sessions"), quick.session_id), "output.raw")), + "raw output log exists") + + for (iteration in range(6)) { + let close_race = watcher_launch(WatcherLaunchRequest( + command_line = "cmd.exe /d /c exit 0", cwd = root, + columns = 80, rows = 20, timeout_ms = 5000l)) + t |> success(close_race.ok, close_race.error) + t |> success(wait_for(close_race.session_id, "exited", 5000l), + "pipe closure still converges to process exit ({iteration})") + } + + let hung = watcher_launch(WatcherLaunchRequest( + command_line = "powershell.exe -NoProfile -Command \"Start-Sleep -Seconds 30\"", + cwd = root, columns = 80, rows = 20, timeout_ms = 250l)) + t |> success(hung.ok, hung.error) + t |> success(wait_for(hung.session_id, "exited", 4000l), "hung command is externally terminated") + t |> success(find(watcher_snapshot_json(hung.session_id), "\"reason\":\"wall_timeout\"") >= 0, + "timeout reason is retained") + + let controlled = watcher_launch(WatcherLaunchRequest( + command_line = "powershell.exe -NoProfile -Command \"Start-Sleep -Seconds 5\"", + cwd = root, columns = 80, rows = 20, timeout_ms = 10000l)) + t |> success(controlled.ok, controlled.error) + t |> success(watcher_claim_controller(controlled.session_id, 11), "first controller claims lease") + t |> success(!watcher_claim_controller(controlled.session_id, 12), "second controller is rejected") + watcher_release_controller(controlled.session_id, 11, "test_detach") + t |> success(watcher_claim_controller(controlled.session_id, 12), "released lease can be reclaimed") + t |> equal(watcher_terminate(controlled.session_id, "test_complete"), "") + t |> success(wait_for(controlled.session_id, "exited", 4000l), "terminated command exits and drains") + watcher_shutdown(true) + rmdir_rec(root) + } +} diff --git a/utils/dasHerd/watcher/vendor/xterm/LICENSE.addon-fit.txt b/utils/dasHerd/watcher/vendor/xterm/LICENSE.addon-fit.txt new file mode 100644 index 0000000000..8f17892587 --- /dev/null +++ b/utils/dasHerd/watcher/vendor/xterm/LICENSE.addon-fit.txt @@ -0,0 +1,19 @@ +Copyright (c) 2019, The xterm.js authors (https://github.com/xtermjs/xterm.js) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/utils/dasHerd/watcher/vendor/xterm/LICENSE.addon-unicode11.txt b/utils/dasHerd/watcher/vendor/xterm/LICENSE.addon-unicode11.txt new file mode 100644 index 0000000000..8f17892587 --- /dev/null +++ b/utils/dasHerd/watcher/vendor/xterm/LICENSE.addon-unicode11.txt @@ -0,0 +1,19 @@ +Copyright (c) 2019, The xterm.js authors (https://github.com/xtermjs/xterm.js) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/utils/dasHerd/watcher/vendor/xterm/LICENSE.addon-web-links.txt b/utils/dasHerd/watcher/vendor/xterm/LICENSE.addon-web-links.txt new file mode 100644 index 0000000000..e597698cc6 --- /dev/null +++ b/utils/dasHerd/watcher/vendor/xterm/LICENSE.addon-web-links.txt @@ -0,0 +1,19 @@ +Copyright (c) 2017, The xterm.js authors (https://github.com/xtermjs/xterm.js) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/utils/dasHerd/watcher/vendor/xterm/LICENSE.xterm.txt b/utils/dasHerd/watcher/vendor/xterm/LICENSE.xterm.txt new file mode 100644 index 0000000000..4472336c9f --- /dev/null +++ b/utils/dasHerd/watcher/vendor/xterm/LICENSE.xterm.txt @@ -0,0 +1,21 @@ +Copyright (c) 2017-2019, The xterm.js authors (https://github.com/xtermjs/xterm.js) +Copyright (c) 2014-2016, SourceLair Private Company (https://www.sourcelair.com) +Copyright (c) 2012-2013, Christopher Jeffrey (https://github.com/chjj/) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/utils/dasHerd/watcher/vendor/xterm/README.md b/utils/dasHerd/watcher/vendor/xterm/README.md new file mode 100644 index 0000000000..95da4e8595 --- /dev/null +++ b/utils/dasHerd/watcher/vendor/xterm/README.md @@ -0,0 +1,12 @@ +# Vendored xterm.js browser assets + +These files are copied without modification from the following MIT-licensed +npm packages: + +- `@xterm/xterm` 5.5.0 (`xterm.js`, `xterm.css`) +- `@xterm/addon-fit` 0.10.0 (`addon-fit.js`) +- `@xterm/addon-unicode11` 0.8.0 (`addon-unicode11.js`) +- `@xterm/addon-web-links` 0.11.0 (`addon-web-links.js`) + +The package versions are the mutually compatible set published with xterm.js +5.5.0. Each package's license is preserved beside its browser asset. diff --git a/utils/dasHerd/watcher/vendor/xterm/addon-fit.js b/utils/dasHerd/watcher/vendor/xterm/addon-fit.js new file mode 100644 index 0000000000..038897193d --- /dev/null +++ b/utils/dasHerd/watcher/vendor/xterm/addon-fit.js @@ -0,0 +1,2 @@ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.FitAddon=t():e.FitAddon=t()}(self,(()=>(()=>{"use strict";var e={};return(()=>{var t=e;Object.defineProperty(t,"__esModule",{value:!0}),t.FitAddon=void 0,t.FitAddon=class{activate(e){this._terminal=e}dispose(){}fit(){const e=this.proposeDimensions();if(!e||!this._terminal||isNaN(e.cols)||isNaN(e.rows))return;const t=this._terminal._core;this._terminal.rows===e.rows&&this._terminal.cols===e.cols||(t._renderService.clear(),this._terminal.resize(e.cols,e.rows))}proposeDimensions(){if(!this._terminal)return;if(!this._terminal.element||!this._terminal.element.parentElement)return;const e=this._terminal._core,t=e._renderService.dimensions;if(0===t.css.cell.width||0===t.css.cell.height)return;const r=0===this._terminal.options.scrollback?0:e.viewport.scrollBarWidth,i=window.getComputedStyle(this._terminal.element.parentElement),o=parseInt(i.getPropertyValue("height")),s=Math.max(0,parseInt(i.getPropertyValue("width"))),n=window.getComputedStyle(this._terminal.element),l=o-(parseInt(n.getPropertyValue("padding-top"))+parseInt(n.getPropertyValue("padding-bottom"))),a=s-(parseInt(n.getPropertyValue("padding-right"))+parseInt(n.getPropertyValue("padding-left")))-r;return{cols:Math.max(2,Math.floor(a/t.css.cell.width)),rows:Math.max(1,Math.floor(l/t.css.cell.height))}}}})(),e})())); +//# sourceMappingURL=addon-fit.js.map \ No newline at end of file diff --git a/utils/dasHerd/watcher/vendor/xterm/addon-unicode11.js b/utils/dasHerd/watcher/vendor/xterm/addon-unicode11.js new file mode 100644 index 0000000000..63247d5a0a --- /dev/null +++ b/utils/dasHerd/watcher/vendor/xterm/addon-unicode11.js @@ -0,0 +1,2 @@ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.Unicode11Addon=t():e.Unicode11Addon=t()}(this,(()=>(()=>{"use strict";var e={433:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.UnicodeV11=void 0;const r=i(938),s=[[768,879],[1155,1161],[1425,1469],[1471,1471],[1473,1474],[1476,1477],[1479,1479],[1536,1541],[1552,1562],[1564,1564],[1611,1631],[1648,1648],[1750,1757],[1759,1764],[1767,1768],[1770,1773],[1807,1807],[1809,1809],[1840,1866],[1958,1968],[2027,2035],[2045,2045],[2070,2073],[2075,2083],[2085,2087],[2089,2093],[2137,2139],[2259,2306],[2362,2362],[2364,2364],[2369,2376],[2381,2381],[2385,2391],[2402,2403],[2433,2433],[2492,2492],[2497,2500],[2509,2509],[2530,2531],[2558,2558],[2561,2562],[2620,2620],[2625,2626],[2631,2632],[2635,2637],[2641,2641],[2672,2673],[2677,2677],[2689,2690],[2748,2748],[2753,2757],[2759,2760],[2765,2765],[2786,2787],[2810,2815],[2817,2817],[2876,2876],[2879,2879],[2881,2884],[2893,2893],[2902,2902],[2914,2915],[2946,2946],[3008,3008],[3021,3021],[3072,3072],[3076,3076],[3134,3136],[3142,3144],[3146,3149],[3157,3158],[3170,3171],[3201,3201],[3260,3260],[3263,3263],[3270,3270],[3276,3277],[3298,3299],[3328,3329],[3387,3388],[3393,3396],[3405,3405],[3426,3427],[3530,3530],[3538,3540],[3542,3542],[3633,3633],[3636,3642],[3655,3662],[3761,3761],[3764,3772],[3784,3789],[3864,3865],[3893,3893],[3895,3895],[3897,3897],[3953,3966],[3968,3972],[3974,3975],[3981,3991],[3993,4028],[4038,4038],[4141,4144],[4146,4151],[4153,4154],[4157,4158],[4184,4185],[4190,4192],[4209,4212],[4226,4226],[4229,4230],[4237,4237],[4253,4253],[4448,4607],[4957,4959],[5906,5908],[5938,5940],[5970,5971],[6002,6003],[6068,6069],[6071,6077],[6086,6086],[6089,6099],[6109,6109],[6155,6158],[6277,6278],[6313,6313],[6432,6434],[6439,6440],[6450,6450],[6457,6459],[6679,6680],[6683,6683],[6742,6742],[6744,6750],[6752,6752],[6754,6754],[6757,6764],[6771,6780],[6783,6783],[6832,6846],[6912,6915],[6964,6964],[6966,6970],[6972,6972],[6978,6978],[7019,7027],[7040,7041],[7074,7077],[7080,7081],[7083,7085],[7142,7142],[7144,7145],[7149,7149],[7151,7153],[7212,7219],[7222,7223],[7376,7378],[7380,7392],[7394,7400],[7405,7405],[7412,7412],[7416,7417],[7616,7673],[7675,7679],[8203,8207],[8234,8238],[8288,8292],[8294,8303],[8400,8432],[11503,11505],[11647,11647],[11744,11775],[12330,12333],[12441,12442],[42607,42610],[42612,42621],[42654,42655],[42736,42737],[43010,43010],[43014,43014],[43019,43019],[43045,43046],[43204,43205],[43232,43249],[43263,43263],[43302,43309],[43335,43345],[43392,43394],[43443,43443],[43446,43449],[43452,43453],[43493,43493],[43561,43566],[43569,43570],[43573,43574],[43587,43587],[43596,43596],[43644,43644],[43696,43696],[43698,43700],[43703,43704],[43710,43711],[43713,43713],[43756,43757],[43766,43766],[44005,44005],[44008,44008],[44013,44013],[64286,64286],[65024,65039],[65056,65071],[65279,65279],[65529,65531]],n=[[66045,66045],[66272,66272],[66422,66426],[68097,68099],[68101,68102],[68108,68111],[68152,68154],[68159,68159],[68325,68326],[68900,68903],[69446,69456],[69633,69633],[69688,69702],[69759,69761],[69811,69814],[69817,69818],[69821,69821],[69837,69837],[69888,69890],[69927,69931],[69933,69940],[70003,70003],[70016,70017],[70070,70078],[70089,70092],[70191,70193],[70196,70196],[70198,70199],[70206,70206],[70367,70367],[70371,70378],[70400,70401],[70459,70460],[70464,70464],[70502,70508],[70512,70516],[70712,70719],[70722,70724],[70726,70726],[70750,70750],[70835,70840],[70842,70842],[70847,70848],[70850,70851],[71090,71093],[71100,71101],[71103,71104],[71132,71133],[71219,71226],[71229,71229],[71231,71232],[71339,71339],[71341,71341],[71344,71349],[71351,71351],[71453,71455],[71458,71461],[71463,71467],[71727,71735],[71737,71738],[72148,72151],[72154,72155],[72160,72160],[72193,72202],[72243,72248],[72251,72254],[72263,72263],[72273,72278],[72281,72283],[72330,72342],[72344,72345],[72752,72758],[72760,72765],[72767,72767],[72850,72871],[72874,72880],[72882,72883],[72885,72886],[73009,73014],[73018,73018],[73020,73021],[73023,73029],[73031,73031],[73104,73105],[73109,73109],[73111,73111],[73459,73460],[78896,78904],[92912,92916],[92976,92982],[94031,94031],[94095,94098],[113821,113822],[113824,113827],[119143,119145],[119155,119170],[119173,119179],[119210,119213],[119362,119364],[121344,121398],[121403,121452],[121461,121461],[121476,121476],[121499,121503],[121505,121519],[122880,122886],[122888,122904],[122907,122913],[122915,122916],[122918,122922],[123184,123190],[123628,123631],[125136,125142],[125252,125258],[917505,917505],[917536,917631],[917760,917999]],o=[[4352,4447],[8986,8987],[9001,9002],[9193,9196],[9200,9200],[9203,9203],[9725,9726],[9748,9749],[9800,9811],[9855,9855],[9875,9875],[9889,9889],[9898,9899],[9917,9918],[9924,9925],[9934,9934],[9940,9940],[9962,9962],[9970,9971],[9973,9973],[9978,9978],[9981,9981],[9989,9989],[9994,9995],[10024,10024],[10060,10060],[10062,10062],[10067,10069],[10071,10071],[10133,10135],[10160,10160],[10175,10175],[11035,11036],[11088,11088],[11093,11093],[11904,11929],[11931,12019],[12032,12245],[12272,12283],[12288,12329],[12334,12350],[12353,12438],[12443,12543],[12549,12591],[12593,12686],[12688,12730],[12736,12771],[12784,12830],[12832,12871],[12880,19903],[19968,42124],[42128,42182],[43360,43388],[44032,55203],[63744,64255],[65040,65049],[65072,65106],[65108,65126],[65128,65131],[65281,65376],[65504,65510]],c=[[94176,94179],[94208,100343],[100352,101106],[110592,110878],[110928,110930],[110948,110951],[110960,111355],[126980,126980],[127183,127183],[127374,127374],[127377,127386],[127488,127490],[127504,127547],[127552,127560],[127568,127569],[127584,127589],[127744,127776],[127789,127797],[127799,127868],[127870,127891],[127904,127946],[127951,127955],[127968,127984],[127988,127988],[127992,128062],[128064,128064],[128066,128252],[128255,128317],[128331,128334],[128336,128359],[128378,128378],[128405,128406],[128420,128420],[128507,128591],[128640,128709],[128716,128716],[128720,128722],[128725,128725],[128747,128748],[128756,128762],[128992,129003],[129293,129393],[129395,129398],[129402,129442],[129445,129450],[129454,129482],[129485,129535],[129648,129651],[129656,129658],[129664,129666],[129680,129685],[131072,196605],[196608,262141]];let l;function d(e,t){let i,r=0,s=t.length-1;if(et[s][1])return!1;for(;s>=r;)if(i=r+s>>1,e>t[i][1])r=i+1;else{if(!(ei&&(i=e)}return r.UnicodeService.createPropertyValue(0,i,s)}}},345:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.runAndSubscribe=t.forwardEvent=t.EventEmitter=void 0,t.EventEmitter=class{constructor(){this._listeners=[],this._disposed=!1}get event(){return this._event||(this._event=e=>(this._listeners.push(e),{dispose:()=>{if(!this._disposed)for(let t=0;tt.fire(e)))},t.runAndSubscribe=function(e,t){return t(void 0),e((e=>t(e)))}},490:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.UnicodeV6=void 0;const r=i(938),s=[[768,879],[1155,1158],[1160,1161],[1425,1469],[1471,1471],[1473,1474],[1476,1477],[1479,1479],[1536,1539],[1552,1557],[1611,1630],[1648,1648],[1750,1764],[1767,1768],[1770,1773],[1807,1807],[1809,1809],[1840,1866],[1958,1968],[2027,2035],[2305,2306],[2364,2364],[2369,2376],[2381,2381],[2385,2388],[2402,2403],[2433,2433],[2492,2492],[2497,2500],[2509,2509],[2530,2531],[2561,2562],[2620,2620],[2625,2626],[2631,2632],[2635,2637],[2672,2673],[2689,2690],[2748,2748],[2753,2757],[2759,2760],[2765,2765],[2786,2787],[2817,2817],[2876,2876],[2879,2879],[2881,2883],[2893,2893],[2902,2902],[2946,2946],[3008,3008],[3021,3021],[3134,3136],[3142,3144],[3146,3149],[3157,3158],[3260,3260],[3263,3263],[3270,3270],[3276,3277],[3298,3299],[3393,3395],[3405,3405],[3530,3530],[3538,3540],[3542,3542],[3633,3633],[3636,3642],[3655,3662],[3761,3761],[3764,3769],[3771,3772],[3784,3789],[3864,3865],[3893,3893],[3895,3895],[3897,3897],[3953,3966],[3968,3972],[3974,3975],[3984,3991],[3993,4028],[4038,4038],[4141,4144],[4146,4146],[4150,4151],[4153,4153],[4184,4185],[4448,4607],[4959,4959],[5906,5908],[5938,5940],[5970,5971],[6002,6003],[6068,6069],[6071,6077],[6086,6086],[6089,6099],[6109,6109],[6155,6157],[6313,6313],[6432,6434],[6439,6440],[6450,6450],[6457,6459],[6679,6680],[6912,6915],[6964,6964],[6966,6970],[6972,6972],[6978,6978],[7019,7027],[7616,7626],[7678,7679],[8203,8207],[8234,8238],[8288,8291],[8298,8303],[8400,8431],[12330,12335],[12441,12442],[43014,43014],[43019,43019],[43045,43046],[64286,64286],[65024,65039],[65056,65059],[65279,65279],[65529,65531]],n=[[68097,68099],[68101,68102],[68108,68111],[68152,68154],[68159,68159],[119143,119145],[119155,119170],[119173,119179],[119210,119213],[119362,119364],[917505,917505],[917536,917631],[917760,917999]];let o;t.UnicodeV6=class{constructor(){if(this.version="6",!o){o=new Uint8Array(65536),o.fill(1),o[0]=0,o.fill(0,1,32),o.fill(0,127,160),o.fill(2,4352,4448),o[9001]=2,o[9002]=2,o.fill(2,11904,42192),o[12351]=1,o.fill(2,44032,55204),o.fill(2,63744,64256),o.fill(2,65040,65050),o.fill(2,65072,65136),o.fill(2,65280,65377),o.fill(2,65504,65511);for(let e=0;et[s][1])return!1;for(;s>=r;)if(i=r+s>>1,e>t[i][1])r=i+1;else{if(!(e=131072&&e<=196605||e>=196608&&e<=262141?2:1}charProperties(e,t){let i=this.wcwidth(e),s=0===i&&0!==t;if(s){const e=r.UnicodeService.extractWidth(t);0===e?s=!1:e>i&&(i=e)}return r.UnicodeService.createPropertyValue(0,i,s)}}},938:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.UnicodeService=void 0;const r=i(345),s=i(490);class n{static extractShouldJoin(e){return 0!=(1&e)}static extractWidth(e){return e>>1&3}static extractCharKind(e){return e>>3}static createPropertyValue(e,t,i=!1){return(16777215&e)<<3|(3&t)<<1|(i?1:0)}constructor(){this._providers=Object.create(null),this._active="",this._onChange=new r.EventEmitter,this.onChange=this._onChange.event;const e=new s.UnicodeV6;this.register(e),this._active=e.version,this._activeProvider=e}dispose(){this._onChange.dispose()}get versions(){return Object.keys(this._providers)}get activeVersion(){return this._active}set activeVersion(e){if(!this._providers[e])throw new Error(`unknown Unicode version "${e}"`);this._active=e,this._activeProvider=this._providers[e],this._onChange.fire(e)}register(e){this._providers[e.version]=e}wcwidth(e){return this._activeProvider.wcwidth(e)}getStringCellWidth(e){let t=0,i=0;const r=e.length;for(let s=0;s=r)return t+this.wcwidth(o);const i=e.charCodeAt(s);56320<=i&&i<=57343?o=1024*(o-55296)+i-56320+65536:t+=this.wcwidth(i)}const c=this.charProperties(o,i);let l=n.extractWidth(c);n.extractShouldJoin(c)&&(l-=n.extractWidth(i)),t+=l,i=c}return t}charProperties(e,t){return this._activeProvider.charProperties(e,t)}}t.UnicodeService=n}},t={};function i(r){var s=t[r];if(void 0!==s)return s.exports;var n=t[r]={exports:{}};return e[r](n,n.exports,i),n.exports}var r={};return(()=>{var e=r;Object.defineProperty(e,"__esModule",{value:!0}),e.Unicode11Addon=void 0;const t=i(433);e.Unicode11Addon=class{activate(e){e.unicode.register(new t.UnicodeV11)}dispose(){}}})(),r})())); +//# sourceMappingURL=addon-unicode11.js.map \ No newline at end of file diff --git a/utils/dasHerd/watcher/vendor/xterm/addon-web-links.js b/utils/dasHerd/watcher/vendor/xterm/addon-web-links.js new file mode 100644 index 0000000000..2131376cdd --- /dev/null +++ b/utils/dasHerd/watcher/vendor/xterm/addon-web-links.js @@ -0,0 +1,2 @@ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.WebLinksAddon=t():e.WebLinksAddon=t()}(self,(()=>(()=>{"use strict";var e={6:(e,t)=>{function n(e){try{const t=new URL(e),n=t.password&&t.username?`${t.protocol}//${t.username}:${t.password}@${t.host}`:t.username?`${t.protocol}//${t.username}@${t.host}`:`${t.protocol}//${t.host}`;return e.toLocaleLowerCase().startsWith(n.toLocaleLowerCase())}catch(e){return!1}}Object.defineProperty(t,"__esModule",{value:!0}),t.LinkComputer=t.WebLinkProvider=void 0,t.WebLinkProvider=class{constructor(e,t,n,o={}){this._terminal=e,this._regex=t,this._handler=n,this._options=o}provideLinks(e,t){const n=o.computeLink(e,this._regex,this._terminal,this._handler);t(this._addCallbacks(n))}_addCallbacks(e){return e.map((e=>(e.leave=this._options.leave,e.hover=(t,n)=>{if(this._options.hover){const{range:o}=e;this._options.hover(t,n,o)}},e)))}};class o{static computeLink(e,t,r,i){const s=new RegExp(t.source,(t.flags||"")+"g"),[a,c]=o._getWindowedLineStrings(e-1,r),l=a.join("");let d;const p=[];for(;d=s.exec(l);){const e=d[0];if(!n(e))continue;const[t,s]=o._mapStrIdx(r,c,0,d.index),[a,l]=o._mapStrIdx(r,t,s,e.length);if(-1===t||-1===s||-1===a||-1===l)continue;const h={start:{x:s+1,y:t+1},end:{x:l,y:a+1}};p.push({range:h,text:e,activate:i})}return p}static _getWindowedLineStrings(e,t){let n,o=e,r=e,i=0,s="";const a=[];if(n=t.buffer.active.getLine(e)){const e=n.translateToString(!0);if(n.isWrapped&&" "!==e[0]){for(i=0;(n=t.buffer.active.getLine(--o))&&i<2048&&(s=n.translateToString(!0),i+=s.length,a.push(s),n.isWrapped&&-1===s.indexOf(" ")););a.reverse()}for(a.push(e),i=0;(n=t.buffer.active.getLine(++r))&&n.isWrapped&&i<2048&&(s=n.translateToString(!0),i+=s.length,a.push(s),-1===s.indexOf(" ")););}return[a,o]}static _mapStrIdx(e,t,n,o){const r=e.buffer.active,i=r.getNullCell();let s=n;for(;o;){const e=r.getLine(t);if(!e)return[-1,-1];for(let n=s;n{var e=o;Object.defineProperty(e,"__esModule",{value:!0}),e.WebLinksAddon=void 0;const t=n(6),r=/(https?|HTTPS?):[/]{2}[^\s"'!*(){}|\\\^<>`]*[^\s"':,.!?{}|\\\^~\[\]`()<>]/;function i(e,t){const n=window.open();if(n){try{n.opener=null}catch{}n.location.href=t}else console.warn("Opening link blocked as opener could not be cleared")}e.WebLinksAddon=class{constructor(e=i,t={}){this._handler=e,this._options=t}activate(e){this._terminal=e;const n=this._options,o=n.urlRegex||r;this._linkProvider=this._terminal.registerLinkProvider(new t.WebLinkProvider(this._terminal,o,this._handler,n))}dispose(){this._linkProvider?.dispose()}}})(),o})())); +//# sourceMappingURL=addon-web-links.js.map \ No newline at end of file diff --git a/utils/dasHerd/watcher/vendor/xterm/xterm.css b/utils/dasHerd/watcher/vendor/xterm/xterm.css new file mode 100644 index 0000000000..e97b643905 --- /dev/null +++ b/utils/dasHerd/watcher/vendor/xterm/xterm.css @@ -0,0 +1,218 @@ +/** + * Copyright (c) 2014 The xterm.js authors. All rights reserved. + * Copyright (c) 2012-2013, Christopher Jeffrey (MIT License) + * https://github.com/chjj/term.js + * @license MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * Originally forked from (with the author's permission): + * Fabrice Bellard's javascript vt100 for jslinux: + * http://bellard.org/jslinux/ + * Copyright (c) 2011 Fabrice Bellard + * The original design remains. The terminal itself + * has been extended to include xterm CSI codes, among + * other features. + */ + +/** + * Default styles for xterm.js + */ + +.xterm { + cursor: text; + position: relative; + user-select: none; + -ms-user-select: none; + -webkit-user-select: none; +} + +.xterm.focus, +.xterm:focus { + outline: none; +} + +.xterm .xterm-helpers { + position: absolute; + top: 0; + /** + * The z-index of the helpers must be higher than the canvases in order for + * IMEs to appear on top. + */ + z-index: 5; +} + +.xterm .xterm-helper-textarea { + padding: 0; + border: 0; + margin: 0; + /* Move textarea out of the screen to the far left, so that the cursor is not visible */ + position: absolute; + opacity: 0; + left: -9999em; + top: 0; + width: 0; + height: 0; + z-index: -5; + /** Prevent wrapping so the IME appears against the textarea at the correct position */ + white-space: nowrap; + overflow: hidden; + resize: none; +} + +.xterm .composition-view { + /* TODO: Composition position got messed up somewhere */ + background: #000; + color: #FFF; + display: none; + position: absolute; + white-space: nowrap; + z-index: 1; +} + +.xterm .composition-view.active { + display: block; +} + +.xterm .xterm-viewport { + /* On OS X this is required in order for the scroll bar to appear fully opaque */ + background-color: #000; + overflow-y: scroll; + cursor: default; + position: absolute; + right: 0; + left: 0; + top: 0; + bottom: 0; +} + +.xterm .xterm-screen { + position: relative; +} + +.xterm .xterm-screen canvas { + position: absolute; + left: 0; + top: 0; +} + +.xterm .xterm-scroll-area { + visibility: hidden; +} + +.xterm-char-measure-element { + display: inline-block; + visibility: hidden; + position: absolute; + top: 0; + left: -9999em; + line-height: normal; +} + +.xterm.enable-mouse-events { + /* When mouse events are enabled (eg. tmux), revert to the standard pointer cursor */ + cursor: default; +} + +.xterm.xterm-cursor-pointer, +.xterm .xterm-cursor-pointer { + cursor: pointer; +} + +.xterm.column-select.focus { + /* Column selection mode */ + cursor: crosshair; +} + +.xterm .xterm-accessibility:not(.debug), +.xterm .xterm-message { + position: absolute; + left: 0; + top: 0; + bottom: 0; + right: 0; + z-index: 10; + color: transparent; + pointer-events: none; +} + +.xterm .xterm-accessibility-tree:not(.debug) *::selection { + color: transparent; +} + +.xterm .xterm-accessibility-tree { + user-select: text; + white-space: pre; +} + +.xterm .live-region { + position: absolute; + left: -9999px; + width: 1px; + height: 1px; + overflow: hidden; +} + +.xterm-dim { + /* Dim should not apply to background, so the opacity of the foreground color is applied + * explicitly in the generated class and reset to 1 here */ + opacity: 1 !important; +} + +.xterm-underline-1 { text-decoration: underline; } +.xterm-underline-2 { text-decoration: double underline; } +.xterm-underline-3 { text-decoration: wavy underline; } +.xterm-underline-4 { text-decoration: dotted underline; } +.xterm-underline-5 { text-decoration: dashed underline; } + +.xterm-overline { + text-decoration: overline; +} + +.xterm-overline.xterm-underline-1 { text-decoration: overline underline; } +.xterm-overline.xterm-underline-2 { text-decoration: overline double underline; } +.xterm-overline.xterm-underline-3 { text-decoration: overline wavy underline; } +.xterm-overline.xterm-underline-4 { text-decoration: overline dotted underline; } +.xterm-overline.xterm-underline-5 { text-decoration: overline dashed underline; } + +.xterm-strikethrough { + text-decoration: line-through; +} + +.xterm-screen .xterm-decoration-container .xterm-decoration { + z-index: 6; + position: absolute; +} + +.xterm-screen .xterm-decoration-container .xterm-decoration.xterm-decoration-top-layer { + z-index: 7; +} + +.xterm-decoration-overview-ruler { + z-index: 8; + position: absolute; + top: 0; + right: 0; + pointer-events: none; +} + +.xterm-decoration-top { + z-index: 2; + position: relative; +} diff --git a/utils/dasHerd/watcher/vendor/xterm/xterm.js b/utils/dasHerd/watcher/vendor/xterm/xterm.js new file mode 100644 index 0000000000..7ca75f8e5e --- /dev/null +++ b/utils/dasHerd/watcher/vendor/xterm/xterm.js @@ -0,0 +1,2 @@ +!function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var i=t();for(var s in i)("object"==typeof exports?exports:e)[s]=i[s]}}(globalThis,(()=>(()=>{"use strict";var e={4567:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.AccessibilityManager=void 0;const n=i(9042),o=i(9924),a=i(844),h=i(4725),c=i(2585),l=i(3656);let d=t.AccessibilityManager=class extends a.Disposable{constructor(e,t,i,s){super(),this._terminal=e,this._coreBrowserService=i,this._renderService=s,this._rowColumns=new WeakMap,this._liveRegionLineCount=0,this._charsToConsume=[],this._charsToAnnounce="",this._accessibilityContainer=this._coreBrowserService.mainDocument.createElement("div"),this._accessibilityContainer.classList.add("xterm-accessibility"),this._rowContainer=this._coreBrowserService.mainDocument.createElement("div"),this._rowContainer.setAttribute("role","list"),this._rowContainer.classList.add("xterm-accessibility-tree"),this._rowElements=[];for(let e=0;ethis._handleBoundaryFocus(e,0),this._bottomBoundaryFocusListener=e=>this._handleBoundaryFocus(e,1),this._rowElements[0].addEventListener("focus",this._topBoundaryFocusListener),this._rowElements[this._rowElements.length-1].addEventListener("focus",this._bottomBoundaryFocusListener),this._refreshRowsDimensions(),this._accessibilityContainer.appendChild(this._rowContainer),this._liveRegion=this._coreBrowserService.mainDocument.createElement("div"),this._liveRegion.classList.add("live-region"),this._liveRegion.setAttribute("aria-live","assertive"),this._accessibilityContainer.appendChild(this._liveRegion),this._liveRegionDebouncer=this.register(new o.TimeBasedDebouncer(this._renderRows.bind(this))),!this._terminal.element)throw new Error("Cannot enable accessibility before Terminal.open");this._terminal.element.insertAdjacentElement("afterbegin",this._accessibilityContainer),this.register(this._terminal.onResize((e=>this._handleResize(e.rows)))),this.register(this._terminal.onRender((e=>this._refreshRows(e.start,e.end)))),this.register(this._terminal.onScroll((()=>this._refreshRows()))),this.register(this._terminal.onA11yChar((e=>this._handleChar(e)))),this.register(this._terminal.onLineFeed((()=>this._handleChar("\n")))),this.register(this._terminal.onA11yTab((e=>this._handleTab(e)))),this.register(this._terminal.onKey((e=>this._handleKey(e.key)))),this.register(this._terminal.onBlur((()=>this._clearLiveRegion()))),this.register(this._renderService.onDimensionsChange((()=>this._refreshRowsDimensions()))),this.register((0,l.addDisposableDomListener)(document,"selectionchange",(()=>this._handleSelectionChange()))),this.register(this._coreBrowserService.onDprChange((()=>this._refreshRowsDimensions()))),this._refreshRows(),this.register((0,a.toDisposable)((()=>{this._accessibilityContainer.remove(),this._rowElements.length=0})))}_handleTab(e){for(let t=0;t0?this._charsToConsume.shift()!==e&&(this._charsToAnnounce+=e):this._charsToAnnounce+=e,"\n"===e&&(this._liveRegionLineCount++,21===this._liveRegionLineCount&&(this._liveRegion.textContent+=n.tooMuchOutput)))}_clearLiveRegion(){this._liveRegion.textContent="",this._liveRegionLineCount=0}_handleKey(e){this._clearLiveRegion(),/\p{Control}/u.test(e)||this._charsToConsume.push(e)}_refreshRows(e,t){this._liveRegionDebouncer.refresh(e,t,this._terminal.rows)}_renderRows(e,t){const i=this._terminal.buffer,s=i.lines.length.toString();for(let r=e;r<=t;r++){const e=i.lines.get(i.ydisp+r),t=[],n=e?.translateToString(!0,void 0,void 0,t)||"",o=(i.ydisp+r+1).toString(),a=this._rowElements[r];a&&(0===n.length?(a.innerText=" ",this._rowColumns.set(a,[0,1])):(a.textContent=n,this._rowColumns.set(a,t)),a.setAttribute("aria-posinset",o),a.setAttribute("aria-setsize",s))}this._announceCharacters()}_announceCharacters(){0!==this._charsToAnnounce.length&&(this._liveRegion.textContent+=this._charsToAnnounce,this._charsToAnnounce="")}_handleBoundaryFocus(e,t){const i=e.target,s=this._rowElements[0===t?1:this._rowElements.length-2];if(i.getAttribute("aria-posinset")===(0===t?"1":`${this._terminal.buffer.lines.length}`))return;if(e.relatedTarget!==s)return;let r,n;if(0===t?(r=i,n=this._rowElements.pop(),this._rowContainer.removeChild(n)):(r=this._rowElements.shift(),n=i,this._rowContainer.removeChild(r)),r.removeEventListener("focus",this._topBoundaryFocusListener),n.removeEventListener("focus",this._bottomBoundaryFocusListener),0===t){const e=this._createAccessibilityTreeNode();this._rowElements.unshift(e),this._rowContainer.insertAdjacentElement("afterbegin",e)}else{const e=this._createAccessibilityTreeNode();this._rowElements.push(e),this._rowContainer.appendChild(e)}this._rowElements[0].addEventListener("focus",this._topBoundaryFocusListener),this._rowElements[this._rowElements.length-1].addEventListener("focus",this._bottomBoundaryFocusListener),this._terminal.scrollLines(0===t?-1:1),this._rowElements[0===t?1:this._rowElements.length-2].focus(),e.preventDefault(),e.stopImmediatePropagation()}_handleSelectionChange(){if(0===this._rowElements.length)return;const e=document.getSelection();if(!e)return;if(e.isCollapsed)return void(this._rowContainer.contains(e.anchorNode)&&this._terminal.clearSelection());if(!e.anchorNode||!e.focusNode)return void console.error("anchorNode and/or focusNode are null");let t={node:e.anchorNode,offset:e.anchorOffset},i={node:e.focusNode,offset:e.focusOffset};if((t.node.compareDocumentPosition(i.node)&Node.DOCUMENT_POSITION_PRECEDING||t.node===i.node&&t.offset>i.offset)&&([t,i]=[i,t]),t.node.compareDocumentPosition(this._rowElements[0])&(Node.DOCUMENT_POSITION_CONTAINED_BY|Node.DOCUMENT_POSITION_FOLLOWING)&&(t={node:this._rowElements[0].childNodes[0],offset:0}),!this._rowContainer.contains(t.node))return;const s=this._rowElements.slice(-1)[0];if(i.node.compareDocumentPosition(s)&(Node.DOCUMENT_POSITION_CONTAINED_BY|Node.DOCUMENT_POSITION_PRECEDING)&&(i={node:s,offset:s.textContent?.length??0}),!this._rowContainer.contains(i.node))return;const r=({node:e,offset:t})=>{const i=e instanceof Text?e.parentNode:e;let s=parseInt(i?.getAttribute("aria-posinset"),10)-1;if(isNaN(s))return console.warn("row is invalid. Race condition?"),null;const r=this._rowColumns.get(i);if(!r)return console.warn("columns is null. Race condition?"),null;let n=t=this._terminal.cols&&(++s,n=0),{row:s,column:n}},n=r(t),o=r(i);if(n&&o){if(n.row>o.row||n.row===o.row&&n.column>=o.column)throw new Error("invalid range");this._terminal.select(n.column,n.row,(o.row-n.row)*this._terminal.cols-n.column+o.column)}}_handleResize(e){this._rowElements[this._rowElements.length-1].removeEventListener("focus",this._bottomBoundaryFocusListener);for(let e=this._rowContainer.children.length;ee;)this._rowContainer.removeChild(this._rowElements.pop());this._rowElements[this._rowElements.length-1].addEventListener("focus",this._bottomBoundaryFocusListener),this._refreshRowsDimensions()}_createAccessibilityTreeNode(){const e=this._coreBrowserService.mainDocument.createElement("div");return e.setAttribute("role","listitem"),e.tabIndex=-1,this._refreshRowDimensions(e),e}_refreshRowsDimensions(){if(this._renderService.dimensions.css.cell.height){this._accessibilityContainer.style.width=`${this._renderService.dimensions.css.canvas.width}px`,this._rowElements.length!==this._terminal.rows&&this._handleResize(this._terminal.rows);for(let e=0;e{function i(e){return e.replace(/\r?\n/g,"\r")}function s(e,t){return t?"[200~"+e+"[201~":e}function r(e,t,r,n){e=s(e=i(e),r.decPrivateModes.bracketedPasteMode&&!0!==n.rawOptions.ignoreBracketedPasteMode),r.triggerDataEvent(e,!0),t.value=""}function n(e,t,i){const s=i.getBoundingClientRect(),r=e.clientX-s.left-10,n=e.clientY-s.top-10;t.style.width="20px",t.style.height="20px",t.style.left=`${r}px`,t.style.top=`${n}px`,t.style.zIndex="1000",t.focus()}Object.defineProperty(t,"__esModule",{value:!0}),t.rightClickHandler=t.moveTextAreaUnderMouseCursor=t.paste=t.handlePasteEvent=t.copyHandler=t.bracketTextForPaste=t.prepareTextForTerminal=void 0,t.prepareTextForTerminal=i,t.bracketTextForPaste=s,t.copyHandler=function(e,t){e.clipboardData&&e.clipboardData.setData("text/plain",t.selectionText),e.preventDefault()},t.handlePasteEvent=function(e,t,i,s){e.stopPropagation(),e.clipboardData&&r(e.clipboardData.getData("text/plain"),t,i,s)},t.paste=r,t.moveTextAreaUnderMouseCursor=n,t.rightClickHandler=function(e,t,i,s,r){n(e,t,i),r&&s.rightClickSelect(e),t.value=s.selectionText,t.select()}},7239:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.ColorContrastCache=void 0;const s=i(1505);t.ColorContrastCache=class{constructor(){this._color=new s.TwoKeyMap,this._css=new s.TwoKeyMap}setCss(e,t,i){this._css.set(e,t,i)}getCss(e,t){return this._css.get(e,t)}setColor(e,t,i){this._color.set(e,t,i)}getColor(e,t){return this._color.get(e,t)}clear(){this._color.clear(),this._css.clear()}}},3656:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.addDisposableDomListener=void 0,t.addDisposableDomListener=function(e,t,i,s){e.addEventListener(t,i,s);let r=!1;return{dispose:()=>{r||(r=!0,e.removeEventListener(t,i,s))}}}},3551:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.Linkifier=void 0;const n=i(3656),o=i(8460),a=i(844),h=i(2585),c=i(4725);let l=t.Linkifier=class extends a.Disposable{get currentLink(){return this._currentLink}constructor(e,t,i,s,r){super(),this._element=e,this._mouseService=t,this._renderService=i,this._bufferService=s,this._linkProviderService=r,this._linkCacheDisposables=[],this._isMouseOut=!0,this._wasResized=!1,this._activeLine=-1,this._onShowLinkUnderline=this.register(new o.EventEmitter),this.onShowLinkUnderline=this._onShowLinkUnderline.event,this._onHideLinkUnderline=this.register(new o.EventEmitter),this.onHideLinkUnderline=this._onHideLinkUnderline.event,this.register((0,a.getDisposeArrayDisposable)(this._linkCacheDisposables)),this.register((0,a.toDisposable)((()=>{this._lastMouseEvent=void 0,this._activeProviderReplies?.clear()}))),this.register(this._bufferService.onResize((()=>{this._clearCurrentLink(),this._wasResized=!0}))),this.register((0,n.addDisposableDomListener)(this._element,"mouseleave",(()=>{this._isMouseOut=!0,this._clearCurrentLink()}))),this.register((0,n.addDisposableDomListener)(this._element,"mousemove",this._handleMouseMove.bind(this))),this.register((0,n.addDisposableDomListener)(this._element,"mousedown",this._handleMouseDown.bind(this))),this.register((0,n.addDisposableDomListener)(this._element,"mouseup",this._handleMouseUp.bind(this)))}_handleMouseMove(e){this._lastMouseEvent=e;const t=this._positionFromMouseEvent(e,this._element,this._mouseService);if(!t)return;this._isMouseOut=!1;const i=e.composedPath();for(let e=0;e{e?.forEach((e=>{e.link.dispose&&e.link.dispose()}))})),this._activeProviderReplies=new Map,this._activeLine=e.y);let i=!1;for(const[s,r]of this._linkProviderService.linkProviders.entries())if(t){const t=this._activeProviderReplies?.get(s);t&&(i=this._checkLinkProviderResult(s,e,i))}else r.provideLinks(e.y,(t=>{if(this._isMouseOut)return;const r=t?.map((e=>({link:e})));this._activeProviderReplies?.set(s,r),i=this._checkLinkProviderResult(s,e,i),this._activeProviderReplies?.size===this._linkProviderService.linkProviders.length&&this._removeIntersectingLinks(e.y,this._activeProviderReplies)}))}_removeIntersectingLinks(e,t){const i=new Set;for(let s=0;se?this._bufferService.cols:s.link.range.end.x;for(let e=n;e<=o;e++){if(i.has(e)){r.splice(t--,1);break}i.add(e)}}}}_checkLinkProviderResult(e,t,i){if(!this._activeProviderReplies)return i;const s=this._activeProviderReplies.get(e);let r=!1;for(let t=0;tthis._linkAtPosition(e.link,t)));e&&(i=!0,this._handleNewLink(e))}if(this._activeProviderReplies.size===this._linkProviderService.linkProviders.length&&!i)for(let e=0;ethis._linkAtPosition(e.link,t)));if(s){i=!0,this._handleNewLink(s);break}}return i}_handleMouseDown(){this._mouseDownLink=this._currentLink}_handleMouseUp(e){if(!this._currentLink)return;const t=this._positionFromMouseEvent(e,this._element,this._mouseService);t&&this._mouseDownLink===this._currentLink&&this._linkAtPosition(this._currentLink.link,t)&&this._currentLink.link.activate(e,this._currentLink.link.text)}_clearCurrentLink(e,t){this._currentLink&&this._lastMouseEvent&&(!e||!t||this._currentLink.link.range.start.y>=e&&this._currentLink.link.range.end.y<=t)&&(this._linkLeave(this._element,this._currentLink.link,this._lastMouseEvent),this._currentLink=void 0,(0,a.disposeArray)(this._linkCacheDisposables))}_handleNewLink(e){if(!this._lastMouseEvent)return;const t=this._positionFromMouseEvent(this._lastMouseEvent,this._element,this._mouseService);t&&this._linkAtPosition(e.link,t)&&(this._currentLink=e,this._currentLink.state={decorations:{underline:void 0===e.link.decorations||e.link.decorations.underline,pointerCursor:void 0===e.link.decorations||e.link.decorations.pointerCursor},isHovered:!0},this._linkHover(this._element,e.link,this._lastMouseEvent),e.link.decorations={},Object.defineProperties(e.link.decorations,{pointerCursor:{get:()=>this._currentLink?.state?.decorations.pointerCursor,set:e=>{this._currentLink?.state&&this._currentLink.state.decorations.pointerCursor!==e&&(this._currentLink.state.decorations.pointerCursor=e,this._currentLink.state.isHovered&&this._element.classList.toggle("xterm-cursor-pointer",e))}},underline:{get:()=>this._currentLink?.state?.decorations.underline,set:t=>{this._currentLink?.state&&this._currentLink?.state?.decorations.underline!==t&&(this._currentLink.state.decorations.underline=t,this._currentLink.state.isHovered&&this._fireUnderlineEvent(e.link,t))}}}),this._linkCacheDisposables.push(this._renderService.onRenderedViewportChange((e=>{if(!this._currentLink)return;const t=0===e.start?0:e.start+1+this._bufferService.buffer.ydisp,i=this._bufferService.buffer.ydisp+1+e.end;if(this._currentLink.link.range.start.y>=t&&this._currentLink.link.range.end.y<=i&&(this._clearCurrentLink(t,i),this._lastMouseEvent)){const e=this._positionFromMouseEvent(this._lastMouseEvent,this._element,this._mouseService);e&&this._askForLink(e,!1)}}))))}_linkHover(e,t,i){this._currentLink?.state&&(this._currentLink.state.isHovered=!0,this._currentLink.state.decorations.underline&&this._fireUnderlineEvent(t,!0),this._currentLink.state.decorations.pointerCursor&&e.classList.add("xterm-cursor-pointer")),t.hover&&t.hover(i,t.text)}_fireUnderlineEvent(e,t){const i=e.range,s=this._bufferService.buffer.ydisp,r=this._createLinkUnderlineEvent(i.start.x-1,i.start.y-s-1,i.end.x,i.end.y-s-1,void 0);(t?this._onShowLinkUnderline:this._onHideLinkUnderline).fire(r)}_linkLeave(e,t,i){this._currentLink?.state&&(this._currentLink.state.isHovered=!1,this._currentLink.state.decorations.underline&&this._fireUnderlineEvent(t,!1),this._currentLink.state.decorations.pointerCursor&&e.classList.remove("xterm-cursor-pointer")),t.leave&&t.leave(i,t.text)}_linkAtPosition(e,t){const i=e.range.start.y*this._bufferService.cols+e.range.start.x,s=e.range.end.y*this._bufferService.cols+e.range.end.x,r=t.y*this._bufferService.cols+t.x;return i<=r&&r<=s}_positionFromMouseEvent(e,t,i){const s=i.getCoords(e,t,this._bufferService.cols,this._bufferService.rows);if(s)return{x:s[0],y:s[1]+this._bufferService.buffer.ydisp}}_createLinkUnderlineEvent(e,t,i,s,r){return{x1:e,y1:t,x2:i,y2:s,cols:this._bufferService.cols,fg:r}}};t.Linkifier=l=s([r(1,c.IMouseService),r(2,c.IRenderService),r(3,h.IBufferService),r(4,c.ILinkProviderService)],l)},9042:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.tooMuchOutput=t.promptLabel=void 0,t.promptLabel="Terminal input",t.tooMuchOutput="Too much output to announce, navigate to rows manually to read"},3730:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.OscLinkProvider=void 0;const n=i(511),o=i(2585);let a=t.OscLinkProvider=class{constructor(e,t,i){this._bufferService=e,this._optionsService=t,this._oscLinkService=i}provideLinks(e,t){const i=this._bufferService.buffer.lines.get(e-1);if(!i)return void t(void 0);const s=[],r=this._optionsService.rawOptions.linkHandler,o=new n.CellData,a=i.getTrimmedLength();let c=-1,l=-1,d=!1;for(let t=0;tr?r.activate(e,t,n):h(0,t),hover:(e,t)=>r?.hover?.(e,t,n),leave:(e,t)=>r?.leave?.(e,t,n)})}d=!1,o.hasExtendedAttrs()&&o.extended.urlId?(l=t,c=o.extended.urlId):(l=-1,c=-1)}}t(s)}};function h(e,t){if(confirm(`Do you want to navigate to ${t}?\n\nWARNING: This link could potentially be dangerous`)){const e=window.open();if(e){try{e.opener=null}catch{}e.location.href=t}else console.warn("Opening link blocked as opener could not be cleared")}}t.OscLinkProvider=a=s([r(0,o.IBufferService),r(1,o.IOptionsService),r(2,o.IOscLinkService)],a)},6193:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.RenderDebouncer=void 0,t.RenderDebouncer=class{constructor(e,t){this._renderCallback=e,this._coreBrowserService=t,this._refreshCallbacks=[]}dispose(){this._animationFrame&&(this._coreBrowserService.window.cancelAnimationFrame(this._animationFrame),this._animationFrame=void 0)}addRefreshCallback(e){return this._refreshCallbacks.push(e),this._animationFrame||(this._animationFrame=this._coreBrowserService.window.requestAnimationFrame((()=>this._innerRefresh()))),this._animationFrame}refresh(e,t,i){this._rowCount=i,e=void 0!==e?e:0,t=void 0!==t?t:this._rowCount-1,this._rowStart=void 0!==this._rowStart?Math.min(this._rowStart,e):e,this._rowEnd=void 0!==this._rowEnd?Math.max(this._rowEnd,t):t,this._animationFrame||(this._animationFrame=this._coreBrowserService.window.requestAnimationFrame((()=>this._innerRefresh())))}_innerRefresh(){if(this._animationFrame=void 0,void 0===this._rowStart||void 0===this._rowEnd||void 0===this._rowCount)return void this._runRefreshCallbacks();const e=Math.max(this._rowStart,0),t=Math.min(this._rowEnd,this._rowCount-1);this._rowStart=void 0,this._rowEnd=void 0,this._renderCallback(e,t),this._runRefreshCallbacks()}_runRefreshCallbacks(){for(const e of this._refreshCallbacks)e(0);this._refreshCallbacks=[]}}},3236:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.Terminal=void 0;const s=i(3614),r=i(3656),n=i(3551),o=i(9042),a=i(3730),h=i(1680),c=i(3107),l=i(5744),d=i(2950),_=i(1296),u=i(428),f=i(4269),v=i(5114),p=i(8934),g=i(3230),m=i(9312),S=i(4725),C=i(6731),b=i(8055),w=i(8969),y=i(8460),E=i(844),k=i(6114),L=i(8437),D=i(2584),R=i(7399),x=i(5941),A=i(9074),B=i(2585),T=i(5435),M=i(4567),O=i(779);class P extends w.CoreTerminal{get onFocus(){return this._onFocus.event}get onBlur(){return this._onBlur.event}get onA11yChar(){return this._onA11yCharEmitter.event}get onA11yTab(){return this._onA11yTabEmitter.event}get onWillOpen(){return this._onWillOpen.event}constructor(e={}){super(e),this.browser=k,this._keyDownHandled=!1,this._keyDownSeen=!1,this._keyPressHandled=!1,this._unprocessedDeadKey=!1,this._accessibilityManager=this.register(new E.MutableDisposable),this._onCursorMove=this.register(new y.EventEmitter),this.onCursorMove=this._onCursorMove.event,this._onKey=this.register(new y.EventEmitter),this.onKey=this._onKey.event,this._onRender=this.register(new y.EventEmitter),this.onRender=this._onRender.event,this._onSelectionChange=this.register(new y.EventEmitter),this.onSelectionChange=this._onSelectionChange.event,this._onTitleChange=this.register(new y.EventEmitter),this.onTitleChange=this._onTitleChange.event,this._onBell=this.register(new y.EventEmitter),this.onBell=this._onBell.event,this._onFocus=this.register(new y.EventEmitter),this._onBlur=this.register(new y.EventEmitter),this._onA11yCharEmitter=this.register(new y.EventEmitter),this._onA11yTabEmitter=this.register(new y.EventEmitter),this._onWillOpen=this.register(new y.EventEmitter),this._setup(),this._decorationService=this._instantiationService.createInstance(A.DecorationService),this._instantiationService.setService(B.IDecorationService,this._decorationService),this._linkProviderService=this._instantiationService.createInstance(O.LinkProviderService),this._instantiationService.setService(S.ILinkProviderService,this._linkProviderService),this._linkProviderService.registerLinkProvider(this._instantiationService.createInstance(a.OscLinkProvider)),this.register(this._inputHandler.onRequestBell((()=>this._onBell.fire()))),this.register(this._inputHandler.onRequestRefreshRows(((e,t)=>this.refresh(e,t)))),this.register(this._inputHandler.onRequestSendFocus((()=>this._reportFocus()))),this.register(this._inputHandler.onRequestReset((()=>this.reset()))),this.register(this._inputHandler.onRequestWindowsOptionsReport((e=>this._reportWindowsOptions(e)))),this.register(this._inputHandler.onColor((e=>this._handleColorEvent(e)))),this.register((0,y.forwardEvent)(this._inputHandler.onCursorMove,this._onCursorMove)),this.register((0,y.forwardEvent)(this._inputHandler.onTitleChange,this._onTitleChange)),this.register((0,y.forwardEvent)(this._inputHandler.onA11yChar,this._onA11yCharEmitter)),this.register((0,y.forwardEvent)(this._inputHandler.onA11yTab,this._onA11yTabEmitter)),this.register(this._bufferService.onResize((e=>this._afterResize(e.cols,e.rows)))),this.register((0,E.toDisposable)((()=>{this._customKeyEventHandler=void 0,this.element?.parentNode?.removeChild(this.element)})))}_handleColorEvent(e){if(this._themeService)for(const t of e){let e,i="";switch(t.index){case 256:e="foreground",i="10";break;case 257:e="background",i="11";break;case 258:e="cursor",i="12";break;default:e="ansi",i="4;"+t.index}switch(t.type){case 0:const s=b.color.toColorRGB("ansi"===e?this._themeService.colors.ansi[t.index]:this._themeService.colors[e]);this.coreService.triggerDataEvent(`${D.C0.ESC}]${i};${(0,x.toRgbString)(s)}${D.C1_ESCAPED.ST}`);break;case 1:if("ansi"===e)this._themeService.modifyColors((e=>e.ansi[t.index]=b.channels.toColor(...t.color)));else{const i=e;this._themeService.modifyColors((e=>e[i]=b.channels.toColor(...t.color)))}break;case 2:this._themeService.restoreColor(t.index)}}}_setup(){super._setup(),this._customKeyEventHandler=void 0}get buffer(){return this.buffers.active}focus(){this.textarea&&this.textarea.focus({preventScroll:!0})}_handleScreenReaderModeOptionChange(e){e?!this._accessibilityManager.value&&this._renderService&&(this._accessibilityManager.value=this._instantiationService.createInstance(M.AccessibilityManager,this)):this._accessibilityManager.clear()}_handleTextAreaFocus(e){this.coreService.decPrivateModes.sendFocus&&this.coreService.triggerDataEvent(D.C0.ESC+"[I"),this.element.classList.add("focus"),this._showCursor(),this._onFocus.fire()}blur(){return this.textarea?.blur()}_handleTextAreaBlur(){this.textarea.value="",this.refresh(this.buffer.y,this.buffer.y),this.coreService.decPrivateModes.sendFocus&&this.coreService.triggerDataEvent(D.C0.ESC+"[O"),this.element.classList.remove("focus"),this._onBlur.fire()}_syncTextArea(){if(!this.textarea||!this.buffer.isCursorInViewport||this._compositionHelper.isComposing||!this._renderService)return;const e=this.buffer.ybase+this.buffer.y,t=this.buffer.lines.get(e);if(!t)return;const i=Math.min(this.buffer.x,this.cols-1),s=this._renderService.dimensions.css.cell.height,r=t.getWidth(i),n=this._renderService.dimensions.css.cell.width*r,o=this.buffer.y*this._renderService.dimensions.css.cell.height,a=i*this._renderService.dimensions.css.cell.width;this.textarea.style.left=a+"px",this.textarea.style.top=o+"px",this.textarea.style.width=n+"px",this.textarea.style.height=s+"px",this.textarea.style.lineHeight=s+"px",this.textarea.style.zIndex="-5"}_initGlobal(){this._bindKeys(),this.register((0,r.addDisposableDomListener)(this.element,"copy",(e=>{this.hasSelection()&&(0,s.copyHandler)(e,this._selectionService)})));const e=e=>(0,s.handlePasteEvent)(e,this.textarea,this.coreService,this.optionsService);this.register((0,r.addDisposableDomListener)(this.textarea,"paste",e)),this.register((0,r.addDisposableDomListener)(this.element,"paste",e)),k.isFirefox?this.register((0,r.addDisposableDomListener)(this.element,"mousedown",(e=>{2===e.button&&(0,s.rightClickHandler)(e,this.textarea,this.screenElement,this._selectionService,this.options.rightClickSelectsWord)}))):this.register((0,r.addDisposableDomListener)(this.element,"contextmenu",(e=>{(0,s.rightClickHandler)(e,this.textarea,this.screenElement,this._selectionService,this.options.rightClickSelectsWord)}))),k.isLinux&&this.register((0,r.addDisposableDomListener)(this.element,"auxclick",(e=>{1===e.button&&(0,s.moveTextAreaUnderMouseCursor)(e,this.textarea,this.screenElement)})))}_bindKeys(){this.register((0,r.addDisposableDomListener)(this.textarea,"keyup",(e=>this._keyUp(e)),!0)),this.register((0,r.addDisposableDomListener)(this.textarea,"keydown",(e=>this._keyDown(e)),!0)),this.register((0,r.addDisposableDomListener)(this.textarea,"keypress",(e=>this._keyPress(e)),!0)),this.register((0,r.addDisposableDomListener)(this.textarea,"compositionstart",(()=>this._compositionHelper.compositionstart()))),this.register((0,r.addDisposableDomListener)(this.textarea,"compositionupdate",(e=>this._compositionHelper.compositionupdate(e)))),this.register((0,r.addDisposableDomListener)(this.textarea,"compositionend",(()=>this._compositionHelper.compositionend()))),this.register((0,r.addDisposableDomListener)(this.textarea,"input",(e=>this._inputEvent(e)),!0)),this.register(this.onRender((()=>this._compositionHelper.updateCompositionElements())))}open(e){if(!e)throw new Error("Terminal requires a parent element.");if(e.isConnected||this._logService.debug("Terminal.open was called on an element that was not attached to the DOM"),this.element?.ownerDocument.defaultView&&this._coreBrowserService)return void(this.element.ownerDocument.defaultView!==this._coreBrowserService.window&&(this._coreBrowserService.window=this.element.ownerDocument.defaultView));this._document=e.ownerDocument,this.options.documentOverride&&this.options.documentOverride instanceof Document&&(this._document=this.optionsService.rawOptions.documentOverride),this.element=this._document.createElement("div"),this.element.dir="ltr",this.element.classList.add("terminal"),this.element.classList.add("xterm"),e.appendChild(this.element);const t=this._document.createDocumentFragment();this._viewportElement=this._document.createElement("div"),this._viewportElement.classList.add("xterm-viewport"),t.appendChild(this._viewportElement),this._viewportScrollArea=this._document.createElement("div"),this._viewportScrollArea.classList.add("xterm-scroll-area"),this._viewportElement.appendChild(this._viewportScrollArea),this.screenElement=this._document.createElement("div"),this.screenElement.classList.add("xterm-screen"),this.register((0,r.addDisposableDomListener)(this.screenElement,"mousemove",(e=>this.updateCursorStyle(e)))),this._helperContainer=this._document.createElement("div"),this._helperContainer.classList.add("xterm-helpers"),this.screenElement.appendChild(this._helperContainer),t.appendChild(this.screenElement),this.textarea=this._document.createElement("textarea"),this.textarea.classList.add("xterm-helper-textarea"),this.textarea.setAttribute("aria-label",o.promptLabel),k.isChromeOS||this.textarea.setAttribute("aria-multiline","false"),this.textarea.setAttribute("autocorrect","off"),this.textarea.setAttribute("autocapitalize","off"),this.textarea.setAttribute("spellcheck","false"),this.textarea.tabIndex=0,this._coreBrowserService=this.register(this._instantiationService.createInstance(v.CoreBrowserService,this.textarea,e.ownerDocument.defaultView??window,this._document??"undefined"!=typeof window?window.document:null)),this._instantiationService.setService(S.ICoreBrowserService,this._coreBrowserService),this.register((0,r.addDisposableDomListener)(this.textarea,"focus",(e=>this._handleTextAreaFocus(e)))),this.register((0,r.addDisposableDomListener)(this.textarea,"blur",(()=>this._handleTextAreaBlur()))),this._helperContainer.appendChild(this.textarea),this._charSizeService=this._instantiationService.createInstance(u.CharSizeService,this._document,this._helperContainer),this._instantiationService.setService(S.ICharSizeService,this._charSizeService),this._themeService=this._instantiationService.createInstance(C.ThemeService),this._instantiationService.setService(S.IThemeService,this._themeService),this._characterJoinerService=this._instantiationService.createInstance(f.CharacterJoinerService),this._instantiationService.setService(S.ICharacterJoinerService,this._characterJoinerService),this._renderService=this.register(this._instantiationService.createInstance(g.RenderService,this.rows,this.screenElement)),this._instantiationService.setService(S.IRenderService,this._renderService),this.register(this._renderService.onRenderedViewportChange((e=>this._onRender.fire(e)))),this.onResize((e=>this._renderService.resize(e.cols,e.rows))),this._compositionView=this._document.createElement("div"),this._compositionView.classList.add("composition-view"),this._compositionHelper=this._instantiationService.createInstance(d.CompositionHelper,this.textarea,this._compositionView),this._helperContainer.appendChild(this._compositionView),this._mouseService=this._instantiationService.createInstance(p.MouseService),this._instantiationService.setService(S.IMouseService,this._mouseService),this.linkifier=this.register(this._instantiationService.createInstance(n.Linkifier,this.screenElement)),this.element.appendChild(t);try{this._onWillOpen.fire(this.element)}catch{}this._renderService.hasRenderer()||this._renderService.setRenderer(this._createRenderer()),this.viewport=this._instantiationService.createInstance(h.Viewport,this._viewportElement,this._viewportScrollArea),this.viewport.onRequestScrollLines((e=>this.scrollLines(e.amount,e.suppressScrollEvent,1))),this.register(this._inputHandler.onRequestSyncScrollBar((()=>this.viewport.syncScrollArea()))),this.register(this.viewport),this.register(this.onCursorMove((()=>{this._renderService.handleCursorMove(),this._syncTextArea()}))),this.register(this.onResize((()=>this._renderService.handleResize(this.cols,this.rows)))),this.register(this.onBlur((()=>this._renderService.handleBlur()))),this.register(this.onFocus((()=>this._renderService.handleFocus()))),this.register(this._renderService.onDimensionsChange((()=>this.viewport.syncScrollArea()))),this._selectionService=this.register(this._instantiationService.createInstance(m.SelectionService,this.element,this.screenElement,this.linkifier)),this._instantiationService.setService(S.ISelectionService,this._selectionService),this.register(this._selectionService.onRequestScrollLines((e=>this.scrollLines(e.amount,e.suppressScrollEvent)))),this.register(this._selectionService.onSelectionChange((()=>this._onSelectionChange.fire()))),this.register(this._selectionService.onRequestRedraw((e=>this._renderService.handleSelectionChanged(e.start,e.end,e.columnSelectMode)))),this.register(this._selectionService.onLinuxMouseSelection((e=>{this.textarea.value=e,this.textarea.focus(),this.textarea.select()}))),this.register(this._onScroll.event((e=>{this.viewport.syncScrollArea(),this._selectionService.refresh()}))),this.register((0,r.addDisposableDomListener)(this._viewportElement,"scroll",(()=>this._selectionService.refresh()))),this.register(this._instantiationService.createInstance(c.BufferDecorationRenderer,this.screenElement)),this.register((0,r.addDisposableDomListener)(this.element,"mousedown",(e=>this._selectionService.handleMouseDown(e)))),this.coreMouseService.areMouseEventsActive?(this._selectionService.disable(),this.element.classList.add("enable-mouse-events")):this._selectionService.enable(),this.options.screenReaderMode&&(this._accessibilityManager.value=this._instantiationService.createInstance(M.AccessibilityManager,this)),this.register(this.optionsService.onSpecificOptionChange("screenReaderMode",(e=>this._handleScreenReaderModeOptionChange(e)))),this.options.overviewRulerWidth&&(this._overviewRulerRenderer=this.register(this._instantiationService.createInstance(l.OverviewRulerRenderer,this._viewportElement,this.screenElement))),this.optionsService.onSpecificOptionChange("overviewRulerWidth",(e=>{!this._overviewRulerRenderer&&e&&this._viewportElement&&this.screenElement&&(this._overviewRulerRenderer=this.register(this._instantiationService.createInstance(l.OverviewRulerRenderer,this._viewportElement,this.screenElement)))})),this._charSizeService.measure(),this.refresh(0,this.rows-1),this._initGlobal(),this.bindMouse()}_createRenderer(){return this._instantiationService.createInstance(_.DomRenderer,this,this._document,this.element,this.screenElement,this._viewportElement,this._helperContainer,this.linkifier)}bindMouse(){const e=this,t=this.element;function i(t){const i=e._mouseService.getMouseReportCoords(t,e.screenElement);if(!i)return!1;let s,r;switch(t.overrideType||t.type){case"mousemove":r=32,void 0===t.buttons?(s=3,void 0!==t.button&&(s=t.button<3?t.button:3)):s=1&t.buttons?0:4&t.buttons?1:2&t.buttons?2:3;break;case"mouseup":r=0,s=t.button<3?t.button:3;break;case"mousedown":r=1,s=t.button<3?t.button:3;break;case"wheel":if(e._customWheelEventHandler&&!1===e._customWheelEventHandler(t))return!1;if(0===e.viewport.getLinesScrolled(t))return!1;r=t.deltaY<0?0:1,s=4;break;default:return!1}return!(void 0===r||void 0===s||s>4)&&e.coreMouseService.triggerMouseEvent({col:i.col,row:i.row,x:i.x,y:i.y,button:s,action:r,ctrl:t.ctrlKey,alt:t.altKey,shift:t.shiftKey})}const s={mouseup:null,wheel:null,mousedrag:null,mousemove:null},n={mouseup:e=>(i(e),e.buttons||(this._document.removeEventListener("mouseup",s.mouseup),s.mousedrag&&this._document.removeEventListener("mousemove",s.mousedrag)),this.cancel(e)),wheel:e=>(i(e),this.cancel(e,!0)),mousedrag:e=>{e.buttons&&i(e)},mousemove:e=>{e.buttons||i(e)}};this.register(this.coreMouseService.onProtocolChange((e=>{e?("debug"===this.optionsService.rawOptions.logLevel&&this._logService.debug("Binding to mouse events:",this.coreMouseService.explainEvents(e)),this.element.classList.add("enable-mouse-events"),this._selectionService.disable()):(this._logService.debug("Unbinding from mouse events."),this.element.classList.remove("enable-mouse-events"),this._selectionService.enable()),8&e?s.mousemove||(t.addEventListener("mousemove",n.mousemove),s.mousemove=n.mousemove):(t.removeEventListener("mousemove",s.mousemove),s.mousemove=null),16&e?s.wheel||(t.addEventListener("wheel",n.wheel,{passive:!1}),s.wheel=n.wheel):(t.removeEventListener("wheel",s.wheel),s.wheel=null),2&e?s.mouseup||(s.mouseup=n.mouseup):(this._document.removeEventListener("mouseup",s.mouseup),s.mouseup=null),4&e?s.mousedrag||(s.mousedrag=n.mousedrag):(this._document.removeEventListener("mousemove",s.mousedrag),s.mousedrag=null)}))),this.coreMouseService.activeProtocol=this.coreMouseService.activeProtocol,this.register((0,r.addDisposableDomListener)(t,"mousedown",(e=>{if(e.preventDefault(),this.focus(),this.coreMouseService.areMouseEventsActive&&!this._selectionService.shouldForceSelection(e))return i(e),s.mouseup&&this._document.addEventListener("mouseup",s.mouseup),s.mousedrag&&this._document.addEventListener("mousemove",s.mousedrag),this.cancel(e)}))),this.register((0,r.addDisposableDomListener)(t,"wheel",(e=>{if(!s.wheel){if(this._customWheelEventHandler&&!1===this._customWheelEventHandler(e))return!1;if(!this.buffer.hasScrollback){const t=this.viewport.getLinesScrolled(e);if(0===t)return;const i=D.C0.ESC+(this.coreService.decPrivateModes.applicationCursorKeys?"O":"[")+(e.deltaY<0?"A":"B");let s="";for(let e=0;e{if(!this.coreMouseService.areMouseEventsActive)return this.viewport.handleTouchStart(e),this.cancel(e)}),{passive:!0})),this.register((0,r.addDisposableDomListener)(t,"touchmove",(e=>{if(!this.coreMouseService.areMouseEventsActive)return this.viewport.handleTouchMove(e)?void 0:this.cancel(e)}),{passive:!1}))}refresh(e,t){this._renderService?.refreshRows(e,t)}updateCursorStyle(e){this._selectionService?.shouldColumnSelect(e)?this.element.classList.add("column-select"):this.element.classList.remove("column-select")}_showCursor(){this.coreService.isCursorInitialized||(this.coreService.isCursorInitialized=!0,this.refresh(this.buffer.y,this.buffer.y))}scrollLines(e,t,i=0){1===i?(super.scrollLines(e,t,i),this.refresh(0,this.rows-1)):this.viewport?.scrollLines(e)}paste(e){(0,s.paste)(e,this.textarea,this.coreService,this.optionsService)}attachCustomKeyEventHandler(e){this._customKeyEventHandler=e}attachCustomWheelEventHandler(e){this._customWheelEventHandler=e}registerLinkProvider(e){return this._linkProviderService.registerLinkProvider(e)}registerCharacterJoiner(e){if(!this._characterJoinerService)throw new Error("Terminal must be opened first");const t=this._characterJoinerService.register(e);return this.refresh(0,this.rows-1),t}deregisterCharacterJoiner(e){if(!this._characterJoinerService)throw new Error("Terminal must be opened first");this._characterJoinerService.deregister(e)&&this.refresh(0,this.rows-1)}get markers(){return this.buffer.markers}registerMarker(e){return this.buffer.addMarker(this.buffer.ybase+this.buffer.y+e)}registerDecoration(e){return this._decorationService.registerDecoration(e)}hasSelection(){return!!this._selectionService&&this._selectionService.hasSelection}select(e,t,i){this._selectionService.setSelection(e,t,i)}getSelection(){return this._selectionService?this._selectionService.selectionText:""}getSelectionPosition(){if(this._selectionService&&this._selectionService.hasSelection)return{start:{x:this._selectionService.selectionStart[0],y:this._selectionService.selectionStart[1]},end:{x:this._selectionService.selectionEnd[0],y:this._selectionService.selectionEnd[1]}}}clearSelection(){this._selectionService?.clearSelection()}selectAll(){this._selectionService?.selectAll()}selectLines(e,t){this._selectionService?.selectLines(e,t)}_keyDown(e){if(this._keyDownHandled=!1,this._keyDownSeen=!0,this._customKeyEventHandler&&!1===this._customKeyEventHandler(e))return!1;const t=this.browser.isMac&&this.options.macOptionIsMeta&&e.altKey;if(!t&&!this._compositionHelper.keydown(e))return this.options.scrollOnUserInput&&this.buffer.ybase!==this.buffer.ydisp&&this.scrollToBottom(),!1;t||"Dead"!==e.key&&"AltGraph"!==e.key||(this._unprocessedDeadKey=!0);const i=(0,R.evaluateKeyboardEvent)(e,this.coreService.decPrivateModes.applicationCursorKeys,this.browser.isMac,this.options.macOptionIsMeta);if(this.updateCursorStyle(e),3===i.type||2===i.type){const t=this.rows-1;return this.scrollLines(2===i.type?-t:t),this.cancel(e,!0)}return 1===i.type&&this.selectAll(),!!this._isThirdLevelShift(this.browser,e)||(i.cancel&&this.cancel(e,!0),!i.key||!!(e.key&&!e.ctrlKey&&!e.altKey&&!e.metaKey&&1===e.key.length&&e.key.charCodeAt(0)>=65&&e.key.charCodeAt(0)<=90)||(this._unprocessedDeadKey?(this._unprocessedDeadKey=!1,!0):(i.key!==D.C0.ETX&&i.key!==D.C0.CR||(this.textarea.value=""),this._onKey.fire({key:i.key,domEvent:e}),this._showCursor(),this.coreService.triggerDataEvent(i.key,!0),!this.optionsService.rawOptions.screenReaderMode||e.altKey||e.ctrlKey?this.cancel(e,!0):void(this._keyDownHandled=!0))))}_isThirdLevelShift(e,t){const i=e.isMac&&!this.options.macOptionIsMeta&&t.altKey&&!t.ctrlKey&&!t.metaKey||e.isWindows&&t.altKey&&t.ctrlKey&&!t.metaKey||e.isWindows&&t.getModifierState("AltGraph");return"keypress"===t.type?i:i&&(!t.keyCode||t.keyCode>47)}_keyUp(e){this._keyDownSeen=!1,this._customKeyEventHandler&&!1===this._customKeyEventHandler(e)||(function(e){return 16===e.keyCode||17===e.keyCode||18===e.keyCode}(e)||this.focus(),this.updateCursorStyle(e),this._keyPressHandled=!1)}_keyPress(e){let t;if(this._keyPressHandled=!1,this._keyDownHandled)return!1;if(this._customKeyEventHandler&&!1===this._customKeyEventHandler(e))return!1;if(this.cancel(e),e.charCode)t=e.charCode;else if(null===e.which||void 0===e.which)t=e.keyCode;else{if(0===e.which||0===e.charCode)return!1;t=e.which}return!(!t||(e.altKey||e.ctrlKey||e.metaKey)&&!this._isThirdLevelShift(this.browser,e)||(t=String.fromCharCode(t),this._onKey.fire({key:t,domEvent:e}),this._showCursor(),this.coreService.triggerDataEvent(t,!0),this._keyPressHandled=!0,this._unprocessedDeadKey=!1,0))}_inputEvent(e){if(e.data&&"insertText"===e.inputType&&(!e.composed||!this._keyDownSeen)&&!this.optionsService.rawOptions.screenReaderMode){if(this._keyPressHandled)return!1;this._unprocessedDeadKey=!1;const t=e.data;return this.coreService.triggerDataEvent(t,!0),this.cancel(e),!0}return!1}resize(e,t){e!==this.cols||t!==this.rows?super.resize(e,t):this._charSizeService&&!this._charSizeService.hasValidSize&&this._charSizeService.measure()}_afterResize(e,t){this._charSizeService?.measure(),this.viewport?.syncScrollArea(!0)}clear(){if(0!==this.buffer.ybase||0!==this.buffer.y){this.buffer.clearAllMarkers(),this.buffer.lines.set(0,this.buffer.lines.get(this.buffer.ybase+this.buffer.y)),this.buffer.lines.length=1,this.buffer.ydisp=0,this.buffer.ybase=0,this.buffer.y=0;for(let e=1;e{Object.defineProperty(t,"__esModule",{value:!0}),t.TimeBasedDebouncer=void 0,t.TimeBasedDebouncer=class{constructor(e,t=1e3){this._renderCallback=e,this._debounceThresholdMS=t,this._lastRefreshMs=0,this._additionalRefreshRequested=!1}dispose(){this._refreshTimeoutID&&clearTimeout(this._refreshTimeoutID)}refresh(e,t,i){this._rowCount=i,e=void 0!==e?e:0,t=void 0!==t?t:this._rowCount-1,this._rowStart=void 0!==this._rowStart?Math.min(this._rowStart,e):e,this._rowEnd=void 0!==this._rowEnd?Math.max(this._rowEnd,t):t;const s=Date.now();if(s-this._lastRefreshMs>=this._debounceThresholdMS)this._lastRefreshMs=s,this._innerRefresh();else if(!this._additionalRefreshRequested){const e=s-this._lastRefreshMs,t=this._debounceThresholdMS-e;this._additionalRefreshRequested=!0,this._refreshTimeoutID=window.setTimeout((()=>{this._lastRefreshMs=Date.now(),this._innerRefresh(),this._additionalRefreshRequested=!1,this._refreshTimeoutID=void 0}),t)}}_innerRefresh(){if(void 0===this._rowStart||void 0===this._rowEnd||void 0===this._rowCount)return;const e=Math.max(this._rowStart,0),t=Math.min(this._rowEnd,this._rowCount-1);this._rowStart=void 0,this._rowEnd=void 0,this._renderCallback(e,t)}}},1680:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.Viewport=void 0;const n=i(3656),o=i(4725),a=i(8460),h=i(844),c=i(2585);let l=t.Viewport=class extends h.Disposable{constructor(e,t,i,s,r,o,h,c){super(),this._viewportElement=e,this._scrollArea=t,this._bufferService=i,this._optionsService=s,this._charSizeService=r,this._renderService=o,this._coreBrowserService=h,this.scrollBarWidth=0,this._currentRowHeight=0,this._currentDeviceCellHeight=0,this._lastRecordedBufferLength=0,this._lastRecordedViewportHeight=0,this._lastRecordedBufferHeight=0,this._lastTouchY=0,this._lastScrollTop=0,this._wheelPartialScroll=0,this._refreshAnimationFrame=null,this._ignoreNextScrollEvent=!1,this._smoothScrollState={startTime:0,origin:-1,target:-1},this._onRequestScrollLines=this.register(new a.EventEmitter),this.onRequestScrollLines=this._onRequestScrollLines.event,this.scrollBarWidth=this._viewportElement.offsetWidth-this._scrollArea.offsetWidth||15,this.register((0,n.addDisposableDomListener)(this._viewportElement,"scroll",this._handleScroll.bind(this))),this._activeBuffer=this._bufferService.buffer,this.register(this._bufferService.buffers.onBufferActivate((e=>this._activeBuffer=e.activeBuffer))),this._renderDimensions=this._renderService.dimensions,this.register(this._renderService.onDimensionsChange((e=>this._renderDimensions=e))),this._handleThemeChange(c.colors),this.register(c.onChangeColors((e=>this._handleThemeChange(e)))),this.register(this._optionsService.onSpecificOptionChange("scrollback",(()=>this.syncScrollArea()))),setTimeout((()=>this.syncScrollArea()))}_handleThemeChange(e){this._viewportElement.style.backgroundColor=e.background.css}reset(){this._currentRowHeight=0,this._currentDeviceCellHeight=0,this._lastRecordedBufferLength=0,this._lastRecordedViewportHeight=0,this._lastRecordedBufferHeight=0,this._lastTouchY=0,this._lastScrollTop=0,this._coreBrowserService.window.requestAnimationFrame((()=>this.syncScrollArea()))}_refresh(e){if(e)return this._innerRefresh(),void(null!==this._refreshAnimationFrame&&this._coreBrowserService.window.cancelAnimationFrame(this._refreshAnimationFrame));null===this._refreshAnimationFrame&&(this._refreshAnimationFrame=this._coreBrowserService.window.requestAnimationFrame((()=>this._innerRefresh())))}_innerRefresh(){if(this._charSizeService.height>0){this._currentRowHeight=this._renderDimensions.device.cell.height/this._coreBrowserService.dpr,this._currentDeviceCellHeight=this._renderDimensions.device.cell.height,this._lastRecordedViewportHeight=this._viewportElement.offsetHeight;const e=Math.round(this._currentRowHeight*this._lastRecordedBufferLength)+(this._lastRecordedViewportHeight-this._renderDimensions.css.canvas.height);this._lastRecordedBufferHeight!==e&&(this._lastRecordedBufferHeight=e,this._scrollArea.style.height=this._lastRecordedBufferHeight+"px")}const e=this._bufferService.buffer.ydisp*this._currentRowHeight;this._viewportElement.scrollTop!==e&&(this._ignoreNextScrollEvent=!0,this._viewportElement.scrollTop=e),this._refreshAnimationFrame=null}syncScrollArea(e=!1){if(this._lastRecordedBufferLength!==this._bufferService.buffer.lines.length)return this._lastRecordedBufferLength=this._bufferService.buffer.lines.length,void this._refresh(e);this._lastRecordedViewportHeight===this._renderService.dimensions.css.canvas.height&&this._lastScrollTop===this._activeBuffer.ydisp*this._currentRowHeight&&this._renderDimensions.device.cell.height===this._currentDeviceCellHeight||this._refresh(e)}_handleScroll(e){if(this._lastScrollTop=this._viewportElement.scrollTop,!this._viewportElement.offsetParent)return;if(this._ignoreNextScrollEvent)return this._ignoreNextScrollEvent=!1,void this._onRequestScrollLines.fire({amount:0,suppressScrollEvent:!0});const t=Math.round(this._lastScrollTop/this._currentRowHeight)-this._bufferService.buffer.ydisp;this._onRequestScrollLines.fire({amount:t,suppressScrollEvent:!0})}_smoothScroll(){if(this._isDisposed||-1===this._smoothScrollState.origin||-1===this._smoothScrollState.target)return;const e=this._smoothScrollPercent();this._viewportElement.scrollTop=this._smoothScrollState.origin+Math.round(e*(this._smoothScrollState.target-this._smoothScrollState.origin)),e<1?this._coreBrowserService.window.requestAnimationFrame((()=>this._smoothScroll())):this._clearSmoothScrollState()}_smoothScrollPercent(){return this._optionsService.rawOptions.smoothScrollDuration&&this._smoothScrollState.startTime?Math.max(Math.min((Date.now()-this._smoothScrollState.startTime)/this._optionsService.rawOptions.smoothScrollDuration,1),0):1}_clearSmoothScrollState(){this._smoothScrollState.startTime=0,this._smoothScrollState.origin=-1,this._smoothScrollState.target=-1}_bubbleScroll(e,t){const i=this._viewportElement.scrollTop+this._lastRecordedViewportHeight;return!(t<0&&0!==this._viewportElement.scrollTop||t>0&&i0&&(i=e),s=""}}return{bufferElements:r,cursorElement:i}}getLinesScrolled(e){if(0===e.deltaY||e.shiftKey)return 0;let t=this._applyScrollModifier(e.deltaY,e);return e.deltaMode===WheelEvent.DOM_DELTA_PIXEL?(t/=this._currentRowHeight+0,this._wheelPartialScroll+=t,t=Math.floor(Math.abs(this._wheelPartialScroll))*(this._wheelPartialScroll>0?1:-1),this._wheelPartialScroll%=1):e.deltaMode===WheelEvent.DOM_DELTA_PAGE&&(t*=this._bufferService.rows),t}_applyScrollModifier(e,t){const i=this._optionsService.rawOptions.fastScrollModifier;return"alt"===i&&t.altKey||"ctrl"===i&&t.ctrlKey||"shift"===i&&t.shiftKey?e*this._optionsService.rawOptions.fastScrollSensitivity*this._optionsService.rawOptions.scrollSensitivity:e*this._optionsService.rawOptions.scrollSensitivity}handleTouchStart(e){this._lastTouchY=e.touches[0].pageY}handleTouchMove(e){const t=this._lastTouchY-e.touches[0].pageY;return this._lastTouchY=e.touches[0].pageY,0!==t&&(this._viewportElement.scrollTop+=t,this._bubbleScroll(e,t))}};t.Viewport=l=s([r(2,c.IBufferService),r(3,c.IOptionsService),r(4,o.ICharSizeService),r(5,o.IRenderService),r(6,o.ICoreBrowserService),r(7,o.IThemeService)],l)},3107:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.BufferDecorationRenderer=void 0;const n=i(4725),o=i(844),a=i(2585);let h=t.BufferDecorationRenderer=class extends o.Disposable{constructor(e,t,i,s,r){super(),this._screenElement=e,this._bufferService=t,this._coreBrowserService=i,this._decorationService=s,this._renderService=r,this._decorationElements=new Map,this._altBufferIsActive=!1,this._dimensionsChanged=!1,this._container=document.createElement("div"),this._container.classList.add("xterm-decoration-container"),this._screenElement.appendChild(this._container),this.register(this._renderService.onRenderedViewportChange((()=>this._doRefreshDecorations()))),this.register(this._renderService.onDimensionsChange((()=>{this._dimensionsChanged=!0,this._queueRefresh()}))),this.register(this._coreBrowserService.onDprChange((()=>this._queueRefresh()))),this.register(this._bufferService.buffers.onBufferActivate((()=>{this._altBufferIsActive=this._bufferService.buffer===this._bufferService.buffers.alt}))),this.register(this._decorationService.onDecorationRegistered((()=>this._queueRefresh()))),this.register(this._decorationService.onDecorationRemoved((e=>this._removeDecoration(e)))),this.register((0,o.toDisposable)((()=>{this._container.remove(),this._decorationElements.clear()})))}_queueRefresh(){void 0===this._animationFrame&&(this._animationFrame=this._renderService.addRefreshCallback((()=>{this._doRefreshDecorations(),this._animationFrame=void 0})))}_doRefreshDecorations(){for(const e of this._decorationService.decorations)this._renderDecoration(e);this._dimensionsChanged=!1}_renderDecoration(e){this._refreshStyle(e),this._dimensionsChanged&&this._refreshXPosition(e)}_createElement(e){const t=this._coreBrowserService.mainDocument.createElement("div");t.classList.add("xterm-decoration"),t.classList.toggle("xterm-decoration-top-layer","top"===e?.options?.layer),t.style.width=`${Math.round((e.options.width||1)*this._renderService.dimensions.css.cell.width)}px`,t.style.height=(e.options.height||1)*this._renderService.dimensions.css.cell.height+"px",t.style.top=(e.marker.line-this._bufferService.buffers.active.ydisp)*this._renderService.dimensions.css.cell.height+"px",t.style.lineHeight=`${this._renderService.dimensions.css.cell.height}px`;const i=e.options.x??0;return i&&i>this._bufferService.cols&&(t.style.display="none"),this._refreshXPosition(e,t),t}_refreshStyle(e){const t=e.marker.line-this._bufferService.buffers.active.ydisp;if(t<0||t>=this._bufferService.rows)e.element&&(e.element.style.display="none",e.onRenderEmitter.fire(e.element));else{let i=this._decorationElements.get(e);i||(i=this._createElement(e),e.element=i,this._decorationElements.set(e,i),this._container.appendChild(i),e.onDispose((()=>{this._decorationElements.delete(e),i.remove()}))),i.style.top=t*this._renderService.dimensions.css.cell.height+"px",i.style.display=this._altBufferIsActive?"none":"block",e.onRenderEmitter.fire(i)}}_refreshXPosition(e,t=e.element){if(!t)return;const i=e.options.x??0;"right"===(e.options.anchor||"left")?t.style.right=i?i*this._renderService.dimensions.css.cell.width+"px":"":t.style.left=i?i*this._renderService.dimensions.css.cell.width+"px":""}_removeDecoration(e){this._decorationElements.get(e)?.remove(),this._decorationElements.delete(e),e.dispose()}};t.BufferDecorationRenderer=h=s([r(1,a.IBufferService),r(2,n.ICoreBrowserService),r(3,a.IDecorationService),r(4,n.IRenderService)],h)},5871:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.ColorZoneStore=void 0,t.ColorZoneStore=class{constructor(){this._zones=[],this._zonePool=[],this._zonePoolIndex=0,this._linePadding={full:0,left:0,center:0,right:0}}get zones(){return this._zonePool.length=Math.min(this._zonePool.length,this._zones.length),this._zones}clear(){this._zones.length=0,this._zonePoolIndex=0}addDecoration(e){if(e.options.overviewRulerOptions){for(const t of this._zones)if(t.color===e.options.overviewRulerOptions.color&&t.position===e.options.overviewRulerOptions.position){if(this._lineIntersectsZone(t,e.marker.line))return;if(this._lineAdjacentToZone(t,e.marker.line,e.options.overviewRulerOptions.position))return void this._addLineToZone(t,e.marker.line)}if(this._zonePoolIndex=e.startBufferLine&&t<=e.endBufferLine}_lineAdjacentToZone(e,t,i){return t>=e.startBufferLine-this._linePadding[i||"full"]&&t<=e.endBufferLine+this._linePadding[i||"full"]}_addLineToZone(e,t){e.startBufferLine=Math.min(e.startBufferLine,t),e.endBufferLine=Math.max(e.endBufferLine,t)}}},5744:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.OverviewRulerRenderer=void 0;const n=i(5871),o=i(4725),a=i(844),h=i(2585),c={full:0,left:0,center:0,right:0},l={full:0,left:0,center:0,right:0},d={full:0,left:0,center:0,right:0};let _=t.OverviewRulerRenderer=class extends a.Disposable{get _width(){return this._optionsService.options.overviewRulerWidth||0}constructor(e,t,i,s,r,o,h){super(),this._viewportElement=e,this._screenElement=t,this._bufferService=i,this._decorationService=s,this._renderService=r,this._optionsService=o,this._coreBrowserService=h,this._colorZoneStore=new n.ColorZoneStore,this._shouldUpdateDimensions=!0,this._shouldUpdateAnchor=!0,this._lastKnownBufferLength=0,this._canvas=this._coreBrowserService.mainDocument.createElement("canvas"),this._canvas.classList.add("xterm-decoration-overview-ruler"),this._refreshCanvasDimensions(),this._viewportElement.parentElement?.insertBefore(this._canvas,this._viewportElement);const c=this._canvas.getContext("2d");if(!c)throw new Error("Ctx cannot be null");this._ctx=c,this._registerDecorationListeners(),this._registerBufferChangeListeners(),this._registerDimensionChangeListeners(),this.register((0,a.toDisposable)((()=>{this._canvas?.remove()})))}_registerDecorationListeners(){this.register(this._decorationService.onDecorationRegistered((()=>this._queueRefresh(void 0,!0)))),this.register(this._decorationService.onDecorationRemoved((()=>this._queueRefresh(void 0,!0))))}_registerBufferChangeListeners(){this.register(this._renderService.onRenderedViewportChange((()=>this._queueRefresh()))),this.register(this._bufferService.buffers.onBufferActivate((()=>{this._canvas.style.display=this._bufferService.buffer===this._bufferService.buffers.alt?"none":"block"}))),this.register(this._bufferService.onScroll((()=>{this._lastKnownBufferLength!==this._bufferService.buffers.normal.lines.length&&(this._refreshDrawHeightConstants(),this._refreshColorZonePadding())})))}_registerDimensionChangeListeners(){this.register(this._renderService.onRender((()=>{this._containerHeight&&this._containerHeight===this._screenElement.clientHeight||(this._queueRefresh(!0),this._containerHeight=this._screenElement.clientHeight)}))),this.register(this._optionsService.onSpecificOptionChange("overviewRulerWidth",(()=>this._queueRefresh(!0)))),this.register(this._coreBrowserService.onDprChange((()=>this._queueRefresh(!0)))),this._queueRefresh(!0)}_refreshDrawConstants(){const e=Math.floor(this._canvas.width/3),t=Math.ceil(this._canvas.width/3);l.full=this._canvas.width,l.left=e,l.center=t,l.right=e,this._refreshDrawHeightConstants(),d.full=0,d.left=0,d.center=l.left,d.right=l.left+l.center}_refreshDrawHeightConstants(){c.full=Math.round(2*this._coreBrowserService.dpr);const e=this._canvas.height/this._bufferService.buffer.lines.length,t=Math.round(Math.max(Math.min(e,12),6)*this._coreBrowserService.dpr);c.left=t,c.center=t,c.right=t}_refreshColorZonePadding(){this._colorZoneStore.setPadding({full:Math.floor(this._bufferService.buffers.active.lines.length/(this._canvas.height-1)*c.full),left:Math.floor(this._bufferService.buffers.active.lines.length/(this._canvas.height-1)*c.left),center:Math.floor(this._bufferService.buffers.active.lines.length/(this._canvas.height-1)*c.center),right:Math.floor(this._bufferService.buffers.active.lines.length/(this._canvas.height-1)*c.right)}),this._lastKnownBufferLength=this._bufferService.buffers.normal.lines.length}_refreshCanvasDimensions(){this._canvas.style.width=`${this._width}px`,this._canvas.width=Math.round(this._width*this._coreBrowserService.dpr),this._canvas.style.height=`${this._screenElement.clientHeight}px`,this._canvas.height=Math.round(this._screenElement.clientHeight*this._coreBrowserService.dpr),this._refreshDrawConstants(),this._refreshColorZonePadding()}_refreshDecorations(){this._shouldUpdateDimensions&&this._refreshCanvasDimensions(),this._ctx.clearRect(0,0,this._canvas.width,this._canvas.height),this._colorZoneStore.clear();for(const e of this._decorationService.decorations)this._colorZoneStore.addDecoration(e);this._ctx.lineWidth=1;const e=this._colorZoneStore.zones;for(const t of e)"full"!==t.position&&this._renderColorZone(t);for(const t of e)"full"===t.position&&this._renderColorZone(t);this._shouldUpdateDimensions=!1,this._shouldUpdateAnchor=!1}_renderColorZone(e){this._ctx.fillStyle=e.color,this._ctx.fillRect(d[e.position||"full"],Math.round((this._canvas.height-1)*(e.startBufferLine/this._bufferService.buffers.active.lines.length)-c[e.position||"full"]/2),l[e.position||"full"],Math.round((this._canvas.height-1)*((e.endBufferLine-e.startBufferLine)/this._bufferService.buffers.active.lines.length)+c[e.position||"full"]))}_queueRefresh(e,t){this._shouldUpdateDimensions=e||this._shouldUpdateDimensions,this._shouldUpdateAnchor=t||this._shouldUpdateAnchor,void 0===this._animationFrame&&(this._animationFrame=this._coreBrowserService.window.requestAnimationFrame((()=>{this._refreshDecorations(),this._animationFrame=void 0})))}};t.OverviewRulerRenderer=_=s([r(2,h.IBufferService),r(3,h.IDecorationService),r(4,o.IRenderService),r(5,h.IOptionsService),r(6,o.ICoreBrowserService)],_)},2950:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.CompositionHelper=void 0;const n=i(4725),o=i(2585),a=i(2584);let h=t.CompositionHelper=class{get isComposing(){return this._isComposing}constructor(e,t,i,s,r,n){this._textarea=e,this._compositionView=t,this._bufferService=i,this._optionsService=s,this._coreService=r,this._renderService=n,this._isComposing=!1,this._isSendingComposition=!1,this._compositionPosition={start:0,end:0},this._dataAlreadySent=""}compositionstart(){this._isComposing=!0,this._compositionPosition.start=this._textarea.value.length,this._compositionView.textContent="",this._dataAlreadySent="",this._compositionView.classList.add("active")}compositionupdate(e){this._compositionView.textContent=e.data,this.updateCompositionElements(),setTimeout((()=>{this._compositionPosition.end=this._textarea.value.length}),0)}compositionend(){this._finalizeComposition(!0)}keydown(e){if(this._isComposing||this._isSendingComposition){if(229===e.keyCode)return!1;if(16===e.keyCode||17===e.keyCode||18===e.keyCode)return!1;this._finalizeComposition(!1)}return 229!==e.keyCode||(this._handleAnyTextareaChanges(),!1)}_finalizeComposition(e){if(this._compositionView.classList.remove("active"),this._isComposing=!1,e){const e={start:this._compositionPosition.start,end:this._compositionPosition.end};this._isSendingComposition=!0,setTimeout((()=>{if(this._isSendingComposition){let t;this._isSendingComposition=!1,e.start+=this._dataAlreadySent.length,t=this._isComposing?this._textarea.value.substring(e.start,e.end):this._textarea.value.substring(e.start),t.length>0&&this._coreService.triggerDataEvent(t,!0)}}),0)}else{this._isSendingComposition=!1;const e=this._textarea.value.substring(this._compositionPosition.start,this._compositionPosition.end);this._coreService.triggerDataEvent(e,!0)}}_handleAnyTextareaChanges(){const e=this._textarea.value;setTimeout((()=>{if(!this._isComposing){const t=this._textarea.value,i=t.replace(e,"");this._dataAlreadySent=i,t.length>e.length?this._coreService.triggerDataEvent(i,!0):t.lengththis.updateCompositionElements(!0)),0)}}};t.CompositionHelper=h=s([r(2,o.IBufferService),r(3,o.IOptionsService),r(4,o.ICoreService),r(5,n.IRenderService)],h)},9806:(e,t)=>{function i(e,t,i){const s=i.getBoundingClientRect(),r=e.getComputedStyle(i),n=parseInt(r.getPropertyValue("padding-left")),o=parseInt(r.getPropertyValue("padding-top"));return[t.clientX-s.left-n,t.clientY-s.top-o]}Object.defineProperty(t,"__esModule",{value:!0}),t.getCoords=t.getCoordsRelativeToElement=void 0,t.getCoordsRelativeToElement=i,t.getCoords=function(e,t,s,r,n,o,a,h,c){if(!o)return;const l=i(e,t,s);return l?(l[0]=Math.ceil((l[0]+(c?a/2:0))/a),l[1]=Math.ceil(l[1]/h),l[0]=Math.min(Math.max(l[0],1),r+(c?1:0)),l[1]=Math.min(Math.max(l[1],1),n),l):void 0}},9504:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.moveToCellSequence=void 0;const s=i(2584);function r(e,t,i,s){const r=e-n(e,i),a=t-n(t,i),l=Math.abs(r-a)-function(e,t,i){let s=0;const r=e-n(e,i),a=t-n(t,i);for(let n=0;n=0&&et?"A":"B"}function a(e,t,i,s,r,n){let o=e,a=t,h="";for(;o!==i||a!==s;)o+=r?1:-1,r&&o>n.cols-1?(h+=n.buffer.translateBufferLineToString(a,!1,e,o),o=0,e=0,a++):!r&&o<0&&(h+=n.buffer.translateBufferLineToString(a,!1,0,e+1),o=n.cols-1,e=o,a--);return h+n.buffer.translateBufferLineToString(a,!1,e,o)}function h(e,t){const i=t?"O":"[";return s.C0.ESC+i+e}function c(e,t){e=Math.floor(e);let i="";for(let s=0;s0?s-n(s,o):t;const _=s,u=function(e,t,i,s,o,a){let h;return h=r(i,s,o,a).length>0?s-n(s,o):t,e=i&&he?"D":"C",c(Math.abs(o-e),h(d,s));d=l>t?"D":"C";const _=Math.abs(l-t);return c(function(e,t){return t.cols-e}(l>t?e:o,i)+(_-1)*i.cols+1+((l>t?o:e)-1),h(d,s))}},1296:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.DomRenderer=void 0;const n=i(3787),o=i(2550),a=i(2223),h=i(6171),c=i(6052),l=i(4725),d=i(8055),_=i(8460),u=i(844),f=i(2585),v="xterm-dom-renderer-owner-",p="xterm-rows",g="xterm-fg-",m="xterm-bg-",S="xterm-focus",C="xterm-selection";let b=1,w=t.DomRenderer=class extends u.Disposable{constructor(e,t,i,s,r,a,l,d,f,g,m,S,w){super(),this._terminal=e,this._document=t,this._element=i,this._screenElement=s,this._viewportElement=r,this._helperContainer=a,this._linkifier2=l,this._charSizeService=f,this._optionsService=g,this._bufferService=m,this._coreBrowserService=S,this._themeService=w,this._terminalClass=b++,this._rowElements=[],this._selectionRenderModel=(0,c.createSelectionRenderModel)(),this.onRequestRedraw=this.register(new _.EventEmitter).event,this._rowContainer=this._document.createElement("div"),this._rowContainer.classList.add(p),this._rowContainer.style.lineHeight="normal",this._rowContainer.setAttribute("aria-hidden","true"),this._refreshRowElements(this._bufferService.cols,this._bufferService.rows),this._selectionContainer=this._document.createElement("div"),this._selectionContainer.classList.add(C),this._selectionContainer.setAttribute("aria-hidden","true"),this.dimensions=(0,h.createRenderDimensions)(),this._updateDimensions(),this.register(this._optionsService.onOptionChange((()=>this._handleOptionsChanged()))),this.register(this._themeService.onChangeColors((e=>this._injectCss(e)))),this._injectCss(this._themeService.colors),this._rowFactory=d.createInstance(n.DomRendererRowFactory,document),this._element.classList.add(v+this._terminalClass),this._screenElement.appendChild(this._rowContainer),this._screenElement.appendChild(this._selectionContainer),this.register(this._linkifier2.onShowLinkUnderline((e=>this._handleLinkHover(e)))),this.register(this._linkifier2.onHideLinkUnderline((e=>this._handleLinkLeave(e)))),this.register((0,u.toDisposable)((()=>{this._element.classList.remove(v+this._terminalClass),this._rowContainer.remove(),this._selectionContainer.remove(),this._widthCache.dispose(),this._themeStyleElement.remove(),this._dimensionsStyleElement.remove()}))),this._widthCache=new o.WidthCache(this._document,this._helperContainer),this._widthCache.setFont(this._optionsService.rawOptions.fontFamily,this._optionsService.rawOptions.fontSize,this._optionsService.rawOptions.fontWeight,this._optionsService.rawOptions.fontWeightBold),this._setDefaultSpacing()}_updateDimensions(){const e=this._coreBrowserService.dpr;this.dimensions.device.char.width=this._charSizeService.width*e,this.dimensions.device.char.height=Math.ceil(this._charSizeService.height*e),this.dimensions.device.cell.width=this.dimensions.device.char.width+Math.round(this._optionsService.rawOptions.letterSpacing),this.dimensions.device.cell.height=Math.floor(this.dimensions.device.char.height*this._optionsService.rawOptions.lineHeight),this.dimensions.device.char.left=0,this.dimensions.device.char.top=0,this.dimensions.device.canvas.width=this.dimensions.device.cell.width*this._bufferService.cols,this.dimensions.device.canvas.height=this.dimensions.device.cell.height*this._bufferService.rows,this.dimensions.css.canvas.width=Math.round(this.dimensions.device.canvas.width/e),this.dimensions.css.canvas.height=Math.round(this.dimensions.device.canvas.height/e),this.dimensions.css.cell.width=this.dimensions.css.canvas.width/this._bufferService.cols,this.dimensions.css.cell.height=this.dimensions.css.canvas.height/this._bufferService.rows;for(const e of this._rowElements)e.style.width=`${this.dimensions.css.canvas.width}px`,e.style.height=`${this.dimensions.css.cell.height}px`,e.style.lineHeight=`${this.dimensions.css.cell.height}px`,e.style.overflow="hidden";this._dimensionsStyleElement||(this._dimensionsStyleElement=this._document.createElement("style"),this._screenElement.appendChild(this._dimensionsStyleElement));const t=`${this._terminalSelector} .${p} span { display: inline-block; height: 100%; vertical-align: top;}`;this._dimensionsStyleElement.textContent=t,this._selectionContainer.style.height=this._viewportElement.style.height,this._screenElement.style.width=`${this.dimensions.css.canvas.width}px`,this._screenElement.style.height=`${this.dimensions.css.canvas.height}px`}_injectCss(e){this._themeStyleElement||(this._themeStyleElement=this._document.createElement("style"),this._screenElement.appendChild(this._themeStyleElement));let t=`${this._terminalSelector} .${p} { color: ${e.foreground.css}; font-family: ${this._optionsService.rawOptions.fontFamily}; font-size: ${this._optionsService.rawOptions.fontSize}px; font-kerning: none; white-space: pre}`;t+=`${this._terminalSelector} .${p} .xterm-dim { color: ${d.color.multiplyOpacity(e.foreground,.5).css};}`,t+=`${this._terminalSelector} span:not(.xterm-bold) { font-weight: ${this._optionsService.rawOptions.fontWeight};}${this._terminalSelector} span.xterm-bold { font-weight: ${this._optionsService.rawOptions.fontWeightBold};}${this._terminalSelector} span.xterm-italic { font-style: italic;}`;const i=`blink_underline_${this._terminalClass}`,s=`blink_bar_${this._terminalClass}`,r=`blink_block_${this._terminalClass}`;t+=`@keyframes ${i} { 50% { border-bottom-style: hidden; }}`,t+=`@keyframes ${s} { 50% { box-shadow: none; }}`,t+=`@keyframes ${r} { 0% { background-color: ${e.cursor.css}; color: ${e.cursorAccent.css}; } 50% { background-color: inherit; color: ${e.cursor.css}; }}`,t+=`${this._terminalSelector} .${p}.${S} .xterm-cursor.xterm-cursor-blink.xterm-cursor-underline { animation: ${i} 1s step-end infinite;}${this._terminalSelector} .${p}.${S} .xterm-cursor.xterm-cursor-blink.xterm-cursor-bar { animation: ${s} 1s step-end infinite;}${this._terminalSelector} .${p}.${S} .xterm-cursor.xterm-cursor-blink.xterm-cursor-block { animation: ${r} 1s step-end infinite;}${this._terminalSelector} .${p} .xterm-cursor.xterm-cursor-block { background-color: ${e.cursor.css}; color: ${e.cursorAccent.css};}${this._terminalSelector} .${p} .xterm-cursor.xterm-cursor-block:not(.xterm-cursor-blink) { background-color: ${e.cursor.css} !important; color: ${e.cursorAccent.css} !important;}${this._terminalSelector} .${p} .xterm-cursor.xterm-cursor-outline { outline: 1px solid ${e.cursor.css}; outline-offset: -1px;}${this._terminalSelector} .${p} .xterm-cursor.xterm-cursor-bar { box-shadow: ${this._optionsService.rawOptions.cursorWidth}px 0 0 ${e.cursor.css} inset;}${this._terminalSelector} .${p} .xterm-cursor.xterm-cursor-underline { border-bottom: 1px ${e.cursor.css}; border-bottom-style: solid; height: calc(100% - 1px);}`,t+=`${this._terminalSelector} .${C} { position: absolute; top: 0; left: 0; z-index: 1; pointer-events: none;}${this._terminalSelector}.focus .${C} div { position: absolute; background-color: ${e.selectionBackgroundOpaque.css};}${this._terminalSelector} .${C} div { position: absolute; background-color: ${e.selectionInactiveBackgroundOpaque.css};}`;for(const[i,s]of e.ansi.entries())t+=`${this._terminalSelector} .${g}${i} { color: ${s.css}; }${this._terminalSelector} .${g}${i}.xterm-dim { color: ${d.color.multiplyOpacity(s,.5).css}; }${this._terminalSelector} .${m}${i} { background-color: ${s.css}; }`;t+=`${this._terminalSelector} .${g}${a.INVERTED_DEFAULT_COLOR} { color: ${d.color.opaque(e.background).css}; }${this._terminalSelector} .${g}${a.INVERTED_DEFAULT_COLOR}.xterm-dim { color: ${d.color.multiplyOpacity(d.color.opaque(e.background),.5).css}; }${this._terminalSelector} .${m}${a.INVERTED_DEFAULT_COLOR} { background-color: ${e.foreground.css}; }`,this._themeStyleElement.textContent=t}_setDefaultSpacing(){const e=this.dimensions.css.cell.width-this._widthCache.get("W",!1,!1);this._rowContainer.style.letterSpacing=`${e}px`,this._rowFactory.defaultSpacing=e}handleDevicePixelRatioChange(){this._updateDimensions(),this._widthCache.clear(),this._setDefaultSpacing()}_refreshRowElements(e,t){for(let e=this._rowElements.length;e<=t;e++){const e=this._document.createElement("div");this._rowContainer.appendChild(e),this._rowElements.push(e)}for(;this._rowElements.length>t;)this._rowContainer.removeChild(this._rowElements.pop())}handleResize(e,t){this._refreshRowElements(e,t),this._updateDimensions(),this.handleSelectionChanged(this._selectionRenderModel.selectionStart,this._selectionRenderModel.selectionEnd,this._selectionRenderModel.columnSelectMode)}handleCharSizeChanged(){this._updateDimensions(),this._widthCache.clear(),this._setDefaultSpacing()}handleBlur(){this._rowContainer.classList.remove(S),this.renderRows(0,this._bufferService.rows-1)}handleFocus(){this._rowContainer.classList.add(S),this.renderRows(this._bufferService.buffer.y,this._bufferService.buffer.y)}handleSelectionChanged(e,t,i){if(this._selectionContainer.replaceChildren(),this._rowFactory.handleSelectionChanged(e,t,i),this.renderRows(0,this._bufferService.rows-1),!e||!t)return;this._selectionRenderModel.update(this._terminal,e,t,i);const s=this._selectionRenderModel.viewportStartRow,r=this._selectionRenderModel.viewportEndRow,n=this._selectionRenderModel.viewportCappedStartRow,o=this._selectionRenderModel.viewportCappedEndRow;if(n>=this._bufferService.rows||o<0)return;const a=this._document.createDocumentFragment();if(i){const i=e[0]>t[0];a.appendChild(this._createSelectionElement(n,i?t[0]:e[0],i?e[0]:t[0],o-n+1))}else{const i=s===n?e[0]:0,h=n===r?t[0]:this._bufferService.cols;a.appendChild(this._createSelectionElement(n,i,h));const c=o-n-1;if(a.appendChild(this._createSelectionElement(n+1,0,this._bufferService.cols,c)),n!==o){const e=r===o?t[0]:this._bufferService.cols;a.appendChild(this._createSelectionElement(o,0,e))}}this._selectionContainer.appendChild(a)}_createSelectionElement(e,t,i,s=1){const r=this._document.createElement("div"),n=t*this.dimensions.css.cell.width;let o=this.dimensions.css.cell.width*(i-t);return n+o>this.dimensions.css.canvas.width&&(o=this.dimensions.css.canvas.width-n),r.style.height=s*this.dimensions.css.cell.height+"px",r.style.top=e*this.dimensions.css.cell.height+"px",r.style.left=`${n}px`,r.style.width=`${o}px`,r}handleCursorMove(){}_handleOptionsChanged(){this._updateDimensions(),this._injectCss(this._themeService.colors),this._widthCache.setFont(this._optionsService.rawOptions.fontFamily,this._optionsService.rawOptions.fontSize,this._optionsService.rawOptions.fontWeight,this._optionsService.rawOptions.fontWeightBold),this._setDefaultSpacing()}clear(){for(const e of this._rowElements)e.replaceChildren()}renderRows(e,t){const i=this._bufferService.buffer,s=i.ybase+i.y,r=Math.min(i.x,this._bufferService.cols-1),n=this._optionsService.rawOptions.cursorBlink,o=this._optionsService.rawOptions.cursorStyle,a=this._optionsService.rawOptions.cursorInactiveStyle;for(let h=e;h<=t;h++){const e=h+i.ydisp,t=this._rowElements[h],c=i.lines.get(e);if(!t||!c)break;t.replaceChildren(...this._rowFactory.createRow(c,e,e===s,o,a,r,n,this.dimensions.css.cell.width,this._widthCache,-1,-1))}}get _terminalSelector(){return`.${v}${this._terminalClass}`}_handleLinkHover(e){this._setCellUnderline(e.x1,e.x2,e.y1,e.y2,e.cols,!0)}_handleLinkLeave(e){this._setCellUnderline(e.x1,e.x2,e.y1,e.y2,e.cols,!1)}_setCellUnderline(e,t,i,s,r,n){i<0&&(e=0),s<0&&(t=0);const o=this._bufferService.rows-1;i=Math.max(Math.min(i,o),0),s=Math.max(Math.min(s,o),0),r=Math.min(r,this._bufferService.cols);const a=this._bufferService.buffer,h=a.ybase+a.y,c=Math.min(a.x,r-1),l=this._optionsService.rawOptions.cursorBlink,d=this._optionsService.rawOptions.cursorStyle,_=this._optionsService.rawOptions.cursorInactiveStyle;for(let o=i;o<=s;++o){const u=o+a.ydisp,f=this._rowElements[o],v=a.lines.get(u);if(!f||!v)break;f.replaceChildren(...this._rowFactory.createRow(v,u,u===h,d,_,c,l,this.dimensions.css.cell.width,this._widthCache,n?o===i?e:0:-1,n?(o===s?t:r)-1:-1))}}};t.DomRenderer=w=s([r(7,f.IInstantiationService),r(8,l.ICharSizeService),r(9,f.IOptionsService),r(10,f.IBufferService),r(11,l.ICoreBrowserService),r(12,l.IThemeService)],w)},3787:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.DomRendererRowFactory=void 0;const n=i(2223),o=i(643),a=i(511),h=i(2585),c=i(8055),l=i(4725),d=i(4269),_=i(6171),u=i(3734);let f=t.DomRendererRowFactory=class{constructor(e,t,i,s,r,n,o){this._document=e,this._characterJoinerService=t,this._optionsService=i,this._coreBrowserService=s,this._coreService=r,this._decorationService=n,this._themeService=o,this._workCell=new a.CellData,this._columnSelectMode=!1,this.defaultSpacing=0}handleSelectionChanged(e,t,i){this._selectionStart=e,this._selectionEnd=t,this._columnSelectMode=i}createRow(e,t,i,s,r,a,h,l,_,f,p){const g=[],m=this._characterJoinerService.getJoinedCharacters(t),S=this._themeService.colors;let C,b=e.getNoBgTrimmedLength();i&&b0&&M===m[0][0]){O=!0;const t=m.shift();I=new d.JoinedCellData(this._workCell,e.translateToString(!0,t[0],t[1]),t[1]-t[0]),P=t[1]-1,b=I.getWidth()}const H=this._isCellInSelection(M,t),F=i&&M===a,W=T&&M>=f&&M<=p;let U=!1;this._decorationService.forEachDecorationAtCell(M,t,void 0,(e=>{U=!0}));let N=I.getChars()||o.WHITESPACE_CELL_CHAR;if(" "===N&&(I.isUnderline()||I.isOverline())&&(N=" "),A=b*l-_.get(N,I.isBold(),I.isItalic()),C){if(w&&(H&&x||!H&&!x&&I.bg===E)&&(H&&x&&S.selectionForeground||I.fg===k)&&I.extended.ext===L&&W===D&&A===R&&!F&&!O&&!U){I.isInvisible()?y+=o.WHITESPACE_CELL_CHAR:y+=N,w++;continue}w&&(C.textContent=y),C=this._document.createElement("span"),w=0,y=""}else C=this._document.createElement("span");if(E=I.bg,k=I.fg,L=I.extended.ext,D=W,R=A,x=H,O&&a>=M&&a<=P&&(a=M),!this._coreService.isCursorHidden&&F&&this._coreService.isCursorInitialized)if(B.push("xterm-cursor"),this._coreBrowserService.isFocused)h&&B.push("xterm-cursor-blink"),B.push("bar"===s?"xterm-cursor-bar":"underline"===s?"xterm-cursor-underline":"xterm-cursor-block");else if(r)switch(r){case"outline":B.push("xterm-cursor-outline");break;case"block":B.push("xterm-cursor-block");break;case"bar":B.push("xterm-cursor-bar");break;case"underline":B.push("xterm-cursor-underline")}if(I.isBold()&&B.push("xterm-bold"),I.isItalic()&&B.push("xterm-italic"),I.isDim()&&B.push("xterm-dim"),y=I.isInvisible()?o.WHITESPACE_CELL_CHAR:I.getChars()||o.WHITESPACE_CELL_CHAR,I.isUnderline()&&(B.push(`xterm-underline-${I.extended.underlineStyle}`)," "===y&&(y=" "),!I.isUnderlineColorDefault()))if(I.isUnderlineColorRGB())C.style.textDecorationColor=`rgb(${u.AttributeData.toColorRGB(I.getUnderlineColor()).join(",")})`;else{let e=I.getUnderlineColor();this._optionsService.rawOptions.drawBoldTextInBrightColors&&I.isBold()&&e<8&&(e+=8),C.style.textDecorationColor=S.ansi[e].css}I.isOverline()&&(B.push("xterm-overline")," "===y&&(y=" ")),I.isStrikethrough()&&B.push("xterm-strikethrough"),W&&(C.style.textDecoration="underline");let $=I.getFgColor(),j=I.getFgColorMode(),z=I.getBgColor(),K=I.getBgColorMode();const q=!!I.isInverse();if(q){const e=$;$=z,z=e;const t=j;j=K,K=t}let V,G,X,J=!1;switch(this._decorationService.forEachDecorationAtCell(M,t,void 0,(e=>{"top"!==e.options.layer&&J||(e.backgroundColorRGB&&(K=50331648,z=e.backgroundColorRGB.rgba>>8&16777215,V=e.backgroundColorRGB),e.foregroundColorRGB&&(j=50331648,$=e.foregroundColorRGB.rgba>>8&16777215,G=e.foregroundColorRGB),J="top"===e.options.layer)})),!J&&H&&(V=this._coreBrowserService.isFocused?S.selectionBackgroundOpaque:S.selectionInactiveBackgroundOpaque,z=V.rgba>>8&16777215,K=50331648,J=!0,S.selectionForeground&&(j=50331648,$=S.selectionForeground.rgba>>8&16777215,G=S.selectionForeground)),J&&B.push("xterm-decoration-top"),K){case 16777216:case 33554432:X=S.ansi[z],B.push(`xterm-bg-${z}`);break;case 50331648:X=c.channels.toColor(z>>16,z>>8&255,255&z),this._addStyle(C,`background-color:#${v((z>>>0).toString(16),"0",6)}`);break;default:q?(X=S.foreground,B.push(`xterm-bg-${n.INVERTED_DEFAULT_COLOR}`)):X=S.background}switch(V||I.isDim()&&(V=c.color.multiplyOpacity(X,.5)),j){case 16777216:case 33554432:I.isBold()&&$<8&&this._optionsService.rawOptions.drawBoldTextInBrightColors&&($+=8),this._applyMinimumContrast(C,X,S.ansi[$],I,V,void 0)||B.push(`xterm-fg-${$}`);break;case 50331648:const e=c.channels.toColor($>>16&255,$>>8&255,255&$);this._applyMinimumContrast(C,X,e,I,V,G)||this._addStyle(C,`color:#${v($.toString(16),"0",6)}`);break;default:this._applyMinimumContrast(C,X,S.foreground,I,V,G)||q&&B.push(`xterm-fg-${n.INVERTED_DEFAULT_COLOR}`)}B.length&&(C.className=B.join(" "),B.length=0),F||O||U?C.textContent=y:w++,A!==this.defaultSpacing&&(C.style.letterSpacing=`${A}px`),g.push(C),M=P}return C&&w&&(C.textContent=y),g}_applyMinimumContrast(e,t,i,s,r,n){if(1===this._optionsService.rawOptions.minimumContrastRatio||(0,_.treatGlyphAsBackgroundColor)(s.getCode()))return!1;const o=this._getContrastCache(s);let a;if(r||n||(a=o.getColor(t.rgba,i.rgba)),void 0===a){const e=this._optionsService.rawOptions.minimumContrastRatio/(s.isDim()?2:1);a=c.color.ensureContrastRatio(r||t,n||i,e),o.setColor((r||t).rgba,(n||i).rgba,a??null)}return!!a&&(this._addStyle(e,`color:${a.css}`),!0)}_getContrastCache(e){return e.isDim()?this._themeService.colors.halfContrastCache:this._themeService.colors.contrastCache}_addStyle(e,t){e.setAttribute("style",`${e.getAttribute("style")||""}${t};`)}_isCellInSelection(e,t){const i=this._selectionStart,s=this._selectionEnd;return!(!i||!s)&&(this._columnSelectMode?i[0]<=s[0]?e>=i[0]&&t>=i[1]&&e=i[1]&&e>=s[0]&&t<=s[1]:t>i[1]&&t=i[0]&&e=i[0])}};function v(e,t,i){for(;e.length{Object.defineProperty(t,"__esModule",{value:!0}),t.WidthCache=void 0,t.WidthCache=class{constructor(e,t){this._flat=new Float32Array(256),this._font="",this._fontSize=0,this._weight="normal",this._weightBold="bold",this._measureElements=[],this._container=e.createElement("div"),this._container.classList.add("xterm-width-cache-measure-container"),this._container.setAttribute("aria-hidden","true"),this._container.style.whiteSpace="pre",this._container.style.fontKerning="none";const i=e.createElement("span");i.classList.add("xterm-char-measure-element");const s=e.createElement("span");s.classList.add("xterm-char-measure-element"),s.style.fontWeight="bold";const r=e.createElement("span");r.classList.add("xterm-char-measure-element"),r.style.fontStyle="italic";const n=e.createElement("span");n.classList.add("xterm-char-measure-element"),n.style.fontWeight="bold",n.style.fontStyle="italic",this._measureElements=[i,s,r,n],this._container.appendChild(i),this._container.appendChild(s),this._container.appendChild(r),this._container.appendChild(n),t.appendChild(this._container),this.clear()}dispose(){this._container.remove(),this._measureElements.length=0,this._holey=void 0}clear(){this._flat.fill(-9999),this._holey=new Map}setFont(e,t,i,s){e===this._font&&t===this._fontSize&&i===this._weight&&s===this._weightBold||(this._font=e,this._fontSize=t,this._weight=i,this._weightBold=s,this._container.style.fontFamily=this._font,this._container.style.fontSize=`${this._fontSize}px`,this._measureElements[0].style.fontWeight=`${i}`,this._measureElements[1].style.fontWeight=`${s}`,this._measureElements[2].style.fontWeight=`${i}`,this._measureElements[3].style.fontWeight=`${s}`,this.clear())}get(e,t,i){let s=0;if(!t&&!i&&1===e.length&&(s=e.charCodeAt(0))<256){if(-9999!==this._flat[s])return this._flat[s];const t=this._measure(e,0);return t>0&&(this._flat[s]=t),t}let r=e;t&&(r+="B"),i&&(r+="I");let n=this._holey.get(r);if(void 0===n){let s=0;t&&(s|=1),i&&(s|=2),n=this._measure(e,s),n>0&&this._holey.set(r,n)}return n}_measure(e,t){const i=this._measureElements[t];return i.textContent=e.repeat(32),i.offsetWidth/32}}},2223:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.TEXT_BASELINE=t.DIM_OPACITY=t.INVERTED_DEFAULT_COLOR=void 0;const s=i(6114);t.INVERTED_DEFAULT_COLOR=257,t.DIM_OPACITY=.5,t.TEXT_BASELINE=s.isFirefox||s.isLegacyEdge?"bottom":"ideographic"},6171:(e,t)=>{function i(e){return 57508<=e&&e<=57558}function s(e){return e>=128512&&e<=128591||e>=127744&&e<=128511||e>=128640&&e<=128767||e>=9728&&e<=9983||e>=9984&&e<=10175||e>=65024&&e<=65039||e>=129280&&e<=129535||e>=127462&&e<=127487}Object.defineProperty(t,"__esModule",{value:!0}),t.computeNextVariantOffset=t.createRenderDimensions=t.treatGlyphAsBackgroundColor=t.allowRescaling=t.isEmoji=t.isRestrictedPowerlineGlyph=t.isPowerlineGlyph=t.throwIfFalsy=void 0,t.throwIfFalsy=function(e){if(!e)throw new Error("value must not be falsy");return e},t.isPowerlineGlyph=i,t.isRestrictedPowerlineGlyph=function(e){return 57520<=e&&e<=57527},t.isEmoji=s,t.allowRescaling=function(e,t,r,n){return 1===t&&r>Math.ceil(1.5*n)&&void 0!==e&&e>255&&!s(e)&&!i(e)&&!function(e){return 57344<=e&&e<=63743}(e)},t.treatGlyphAsBackgroundColor=function(e){return i(e)||function(e){return 9472<=e&&e<=9631}(e)},t.createRenderDimensions=function(){return{css:{canvas:{width:0,height:0},cell:{width:0,height:0}},device:{canvas:{width:0,height:0},cell:{width:0,height:0},char:{width:0,height:0,left:0,top:0}}}},t.computeNextVariantOffset=function(e,t,i=0){return(e-(2*Math.round(t)-i))%(2*Math.round(t))}},6052:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.createSelectionRenderModel=void 0;class i{constructor(){this.clear()}clear(){this.hasSelection=!1,this.columnSelectMode=!1,this.viewportStartRow=0,this.viewportEndRow=0,this.viewportCappedStartRow=0,this.viewportCappedEndRow=0,this.startCol=0,this.endCol=0,this.selectionStart=void 0,this.selectionEnd=void 0}update(e,t,i,s=!1){if(this.selectionStart=t,this.selectionEnd=i,!t||!i||t[0]===i[0]&&t[1]===i[1])return void this.clear();const r=e.buffers.active.ydisp,n=t[1]-r,o=i[1]-r,a=Math.max(n,0),h=Math.min(o,e.rows-1);a>=e.rows||h<0?this.clear():(this.hasSelection=!0,this.columnSelectMode=s,this.viewportStartRow=n,this.viewportEndRow=o,this.viewportCappedStartRow=a,this.viewportCappedEndRow=h,this.startCol=t[0],this.endCol=i[0])}isCellSelected(e,t,i){return!!this.hasSelection&&(i-=e.buffer.active.viewportY,this.columnSelectMode?this.startCol<=this.endCol?t>=this.startCol&&i>=this.viewportCappedStartRow&&t=this.viewportCappedStartRow&&t>=this.endCol&&i<=this.viewportCappedEndRow:i>this.viewportStartRow&&i=this.startCol&&t=this.startCol)}}t.createSelectionRenderModel=function(){return new i}},456:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.SelectionModel=void 0,t.SelectionModel=class{constructor(e){this._bufferService=e,this.isSelectAllActive=!1,this.selectionStartLength=0}clearSelection(){this.selectionStart=void 0,this.selectionEnd=void 0,this.isSelectAllActive=!1,this.selectionStartLength=0}get finalSelectionStart(){return this.isSelectAllActive?[0,0]:this.selectionEnd&&this.selectionStart&&this.areSelectionValuesReversed()?this.selectionEnd:this.selectionStart}get finalSelectionEnd(){if(this.isSelectAllActive)return[this._bufferService.cols,this._bufferService.buffer.ybase+this._bufferService.rows-1];if(this.selectionStart){if(!this.selectionEnd||this.areSelectionValuesReversed()){const e=this.selectionStart[0]+this.selectionStartLength;return e>this._bufferService.cols?e%this._bufferService.cols==0?[this._bufferService.cols,this.selectionStart[1]+Math.floor(e/this._bufferService.cols)-1]:[e%this._bufferService.cols,this.selectionStart[1]+Math.floor(e/this._bufferService.cols)]:[e,this.selectionStart[1]]}if(this.selectionStartLength&&this.selectionEnd[1]===this.selectionStart[1]){const e=this.selectionStart[0]+this.selectionStartLength;return e>this._bufferService.cols?[e%this._bufferService.cols,this.selectionStart[1]+Math.floor(e/this._bufferService.cols)]:[Math.max(e,this.selectionEnd[0]),this.selectionEnd[1]]}return this.selectionEnd}}areSelectionValuesReversed(){const e=this.selectionStart,t=this.selectionEnd;return!(!e||!t)&&(e[1]>t[1]||e[1]===t[1]&&e[0]>t[0])}handleTrim(e){return this.selectionStart&&(this.selectionStart[1]-=e),this.selectionEnd&&(this.selectionEnd[1]-=e),this.selectionEnd&&this.selectionEnd[1]<0?(this.clearSelection(),!0):(this.selectionStart&&this.selectionStart[1]<0&&(this.selectionStart[1]=0),!1)}}},428:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.CharSizeService=void 0;const n=i(2585),o=i(8460),a=i(844);let h=t.CharSizeService=class extends a.Disposable{get hasValidSize(){return this.width>0&&this.height>0}constructor(e,t,i){super(),this._optionsService=i,this.width=0,this.height=0,this._onCharSizeChange=this.register(new o.EventEmitter),this.onCharSizeChange=this._onCharSizeChange.event;try{this._measureStrategy=this.register(new d(this._optionsService))}catch{this._measureStrategy=this.register(new l(e,t,this._optionsService))}this.register(this._optionsService.onMultipleOptionChange(["fontFamily","fontSize"],(()=>this.measure())))}measure(){const e=this._measureStrategy.measure();e.width===this.width&&e.height===this.height||(this.width=e.width,this.height=e.height,this._onCharSizeChange.fire())}};t.CharSizeService=h=s([r(2,n.IOptionsService)],h);class c extends a.Disposable{constructor(){super(...arguments),this._result={width:0,height:0}}_validateAndSet(e,t){void 0!==e&&e>0&&void 0!==t&&t>0&&(this._result.width=e,this._result.height=t)}}class l extends c{constructor(e,t,i){super(),this._document=e,this._parentElement=t,this._optionsService=i,this._measureElement=this._document.createElement("span"),this._measureElement.classList.add("xterm-char-measure-element"),this._measureElement.textContent="W".repeat(32),this._measureElement.setAttribute("aria-hidden","true"),this._measureElement.style.whiteSpace="pre",this._measureElement.style.fontKerning="none",this._parentElement.appendChild(this._measureElement)}measure(){return this._measureElement.style.fontFamily=this._optionsService.rawOptions.fontFamily,this._measureElement.style.fontSize=`${this._optionsService.rawOptions.fontSize}px`,this._validateAndSet(Number(this._measureElement.offsetWidth)/32,Number(this._measureElement.offsetHeight)),this._result}}class d extends c{constructor(e){super(),this._optionsService=e,this._canvas=new OffscreenCanvas(100,100),this._ctx=this._canvas.getContext("2d");const t=this._ctx.measureText("W");if(!("width"in t&&"fontBoundingBoxAscent"in t&&"fontBoundingBoxDescent"in t))throw new Error("Required font metrics not supported")}measure(){this._ctx.font=`${this._optionsService.rawOptions.fontSize}px ${this._optionsService.rawOptions.fontFamily}`;const e=this._ctx.measureText("W");return this._validateAndSet(e.width,e.fontBoundingBoxAscent+e.fontBoundingBoxDescent),this._result}}},4269:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.CharacterJoinerService=t.JoinedCellData=void 0;const n=i(3734),o=i(643),a=i(511),h=i(2585);class c extends n.AttributeData{constructor(e,t,i){super(),this.content=0,this.combinedData="",this.fg=e.fg,this.bg=e.bg,this.combinedData=t,this._width=i}isCombined(){return 2097152}getWidth(){return this._width}getChars(){return this.combinedData}getCode(){return 2097151}setFromCharData(e){throw new Error("not implemented")}getAsCharData(){return[this.fg,this.getChars(),this.getWidth(),this.getCode()]}}t.JoinedCellData=c;let l=t.CharacterJoinerService=class e{constructor(e){this._bufferService=e,this._characterJoiners=[],this._nextCharacterJoinerId=0,this._workCell=new a.CellData}register(e){const t={id:this._nextCharacterJoinerId++,handler:e};return this._characterJoiners.push(t),t.id}deregister(e){for(let t=0;t1){const e=this._getJoinedRanges(s,a,n,t,r);for(let t=0;t1){const e=this._getJoinedRanges(s,a,n,t,r);for(let t=0;t{Object.defineProperty(t,"__esModule",{value:!0}),t.CoreBrowserService=void 0;const s=i(844),r=i(8460),n=i(3656);class o extends s.Disposable{constructor(e,t,i){super(),this._textarea=e,this._window=t,this.mainDocument=i,this._isFocused=!1,this._cachedIsFocused=void 0,this._screenDprMonitor=new a(this._window),this._onDprChange=this.register(new r.EventEmitter),this.onDprChange=this._onDprChange.event,this._onWindowChange=this.register(new r.EventEmitter),this.onWindowChange=this._onWindowChange.event,this.register(this.onWindowChange((e=>this._screenDprMonitor.setWindow(e)))),this.register((0,r.forwardEvent)(this._screenDprMonitor.onDprChange,this._onDprChange)),this._textarea.addEventListener("focus",(()=>this._isFocused=!0)),this._textarea.addEventListener("blur",(()=>this._isFocused=!1))}get window(){return this._window}set window(e){this._window!==e&&(this._window=e,this._onWindowChange.fire(this._window))}get dpr(){return this.window.devicePixelRatio}get isFocused(){return void 0===this._cachedIsFocused&&(this._cachedIsFocused=this._isFocused&&this._textarea.ownerDocument.hasFocus(),queueMicrotask((()=>this._cachedIsFocused=void 0))),this._cachedIsFocused}}t.CoreBrowserService=o;class a extends s.Disposable{constructor(e){super(),this._parentWindow=e,this._windowResizeListener=this.register(new s.MutableDisposable),this._onDprChange=this.register(new r.EventEmitter),this.onDprChange=this._onDprChange.event,this._outerListener=()=>this._setDprAndFireIfDiffers(),this._currentDevicePixelRatio=this._parentWindow.devicePixelRatio,this._updateDpr(),this._setWindowResizeListener(),this.register((0,s.toDisposable)((()=>this.clearListener())))}setWindow(e){this._parentWindow=e,this._setWindowResizeListener(),this._setDprAndFireIfDiffers()}_setWindowResizeListener(){this._windowResizeListener.value=(0,n.addDisposableDomListener)(this._parentWindow,"resize",(()=>this._setDprAndFireIfDiffers()))}_setDprAndFireIfDiffers(){this._parentWindow.devicePixelRatio!==this._currentDevicePixelRatio&&this._onDprChange.fire(this._parentWindow.devicePixelRatio),this._updateDpr()}_updateDpr(){this._outerListener&&(this._resolutionMediaMatchList?.removeListener(this._outerListener),this._currentDevicePixelRatio=this._parentWindow.devicePixelRatio,this._resolutionMediaMatchList=this._parentWindow.matchMedia(`screen and (resolution: ${this._parentWindow.devicePixelRatio}dppx)`),this._resolutionMediaMatchList.addListener(this._outerListener))}clearListener(){this._resolutionMediaMatchList&&this._outerListener&&(this._resolutionMediaMatchList.removeListener(this._outerListener),this._resolutionMediaMatchList=void 0,this._outerListener=void 0)}}},779:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.LinkProviderService=void 0;const s=i(844);class r extends s.Disposable{constructor(){super(),this.linkProviders=[],this.register((0,s.toDisposable)((()=>this.linkProviders.length=0)))}registerLinkProvider(e){return this.linkProviders.push(e),{dispose:()=>{const t=this.linkProviders.indexOf(e);-1!==t&&this.linkProviders.splice(t,1)}}}}t.LinkProviderService=r},8934:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.MouseService=void 0;const n=i(4725),o=i(9806);let a=t.MouseService=class{constructor(e,t){this._renderService=e,this._charSizeService=t}getCoords(e,t,i,s,r){return(0,o.getCoords)(window,e,t,i,s,this._charSizeService.hasValidSize,this._renderService.dimensions.css.cell.width,this._renderService.dimensions.css.cell.height,r)}getMouseReportCoords(e,t){const i=(0,o.getCoordsRelativeToElement)(window,e,t);if(this._charSizeService.hasValidSize)return i[0]=Math.min(Math.max(i[0],0),this._renderService.dimensions.css.canvas.width-1),i[1]=Math.min(Math.max(i[1],0),this._renderService.dimensions.css.canvas.height-1),{col:Math.floor(i[0]/this._renderService.dimensions.css.cell.width),row:Math.floor(i[1]/this._renderService.dimensions.css.cell.height),x:Math.floor(i[0]),y:Math.floor(i[1])}}};t.MouseService=a=s([r(0,n.IRenderService),r(1,n.ICharSizeService)],a)},3230:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.RenderService=void 0;const n=i(6193),o=i(4725),a=i(8460),h=i(844),c=i(7226),l=i(2585);let d=t.RenderService=class extends h.Disposable{get dimensions(){return this._renderer.value.dimensions}constructor(e,t,i,s,r,o,l,d){super(),this._rowCount=e,this._charSizeService=s,this._renderer=this.register(new h.MutableDisposable),this._pausedResizeTask=new c.DebouncedIdleTask,this._observerDisposable=this.register(new h.MutableDisposable),this._isPaused=!1,this._needsFullRefresh=!1,this._isNextRenderRedrawOnly=!0,this._needsSelectionRefresh=!1,this._canvasWidth=0,this._canvasHeight=0,this._selectionState={start:void 0,end:void 0,columnSelectMode:!1},this._onDimensionsChange=this.register(new a.EventEmitter),this.onDimensionsChange=this._onDimensionsChange.event,this._onRenderedViewportChange=this.register(new a.EventEmitter),this.onRenderedViewportChange=this._onRenderedViewportChange.event,this._onRender=this.register(new a.EventEmitter),this.onRender=this._onRender.event,this._onRefreshRequest=this.register(new a.EventEmitter),this.onRefreshRequest=this._onRefreshRequest.event,this._renderDebouncer=new n.RenderDebouncer(((e,t)=>this._renderRows(e,t)),l),this.register(this._renderDebouncer),this.register(l.onDprChange((()=>this.handleDevicePixelRatioChange()))),this.register(o.onResize((()=>this._fullRefresh()))),this.register(o.buffers.onBufferActivate((()=>this._renderer.value?.clear()))),this.register(i.onOptionChange((()=>this._handleOptionsChanged()))),this.register(this._charSizeService.onCharSizeChange((()=>this.handleCharSizeChanged()))),this.register(r.onDecorationRegistered((()=>this._fullRefresh()))),this.register(r.onDecorationRemoved((()=>this._fullRefresh()))),this.register(i.onMultipleOptionChange(["customGlyphs","drawBoldTextInBrightColors","letterSpacing","lineHeight","fontFamily","fontSize","fontWeight","fontWeightBold","minimumContrastRatio","rescaleOverlappingGlyphs"],(()=>{this.clear(),this.handleResize(o.cols,o.rows),this._fullRefresh()}))),this.register(i.onMultipleOptionChange(["cursorBlink","cursorStyle"],(()=>this.refreshRows(o.buffer.y,o.buffer.y,!0)))),this.register(d.onChangeColors((()=>this._fullRefresh()))),this._registerIntersectionObserver(l.window,t),this.register(l.onWindowChange((e=>this._registerIntersectionObserver(e,t))))}_registerIntersectionObserver(e,t){if("IntersectionObserver"in e){const i=new e.IntersectionObserver((e=>this._handleIntersectionChange(e[e.length-1])),{threshold:0});i.observe(t),this._observerDisposable.value=(0,h.toDisposable)((()=>i.disconnect()))}}_handleIntersectionChange(e){this._isPaused=void 0===e.isIntersecting?0===e.intersectionRatio:!e.isIntersecting,this._isPaused||this._charSizeService.hasValidSize||this._charSizeService.measure(),!this._isPaused&&this._needsFullRefresh&&(this._pausedResizeTask.flush(),this.refreshRows(0,this._rowCount-1),this._needsFullRefresh=!1)}refreshRows(e,t,i=!1){this._isPaused?this._needsFullRefresh=!0:(i||(this._isNextRenderRedrawOnly=!1),this._renderDebouncer.refresh(e,t,this._rowCount))}_renderRows(e,t){this._renderer.value&&(e=Math.min(e,this._rowCount-1),t=Math.min(t,this._rowCount-1),this._renderer.value.renderRows(e,t),this._needsSelectionRefresh&&(this._renderer.value.handleSelectionChanged(this._selectionState.start,this._selectionState.end,this._selectionState.columnSelectMode),this._needsSelectionRefresh=!1),this._isNextRenderRedrawOnly||this._onRenderedViewportChange.fire({start:e,end:t}),this._onRender.fire({start:e,end:t}),this._isNextRenderRedrawOnly=!0)}resize(e,t){this._rowCount=t,this._fireOnCanvasResize()}_handleOptionsChanged(){this._renderer.value&&(this.refreshRows(0,this._rowCount-1),this._fireOnCanvasResize())}_fireOnCanvasResize(){this._renderer.value&&(this._renderer.value.dimensions.css.canvas.width===this._canvasWidth&&this._renderer.value.dimensions.css.canvas.height===this._canvasHeight||this._onDimensionsChange.fire(this._renderer.value.dimensions))}hasRenderer(){return!!this._renderer.value}setRenderer(e){this._renderer.value=e,this._renderer.value&&(this._renderer.value.onRequestRedraw((e=>this.refreshRows(e.start,e.end,!0))),this._needsSelectionRefresh=!0,this._fullRefresh())}addRefreshCallback(e){return this._renderDebouncer.addRefreshCallback(e)}_fullRefresh(){this._isPaused?this._needsFullRefresh=!0:this.refreshRows(0,this._rowCount-1)}clearTextureAtlas(){this._renderer.value&&(this._renderer.value.clearTextureAtlas?.(),this._fullRefresh())}handleDevicePixelRatioChange(){this._charSizeService.measure(),this._renderer.value&&(this._renderer.value.handleDevicePixelRatioChange(),this.refreshRows(0,this._rowCount-1))}handleResize(e,t){this._renderer.value&&(this._isPaused?this._pausedResizeTask.set((()=>this._renderer.value?.handleResize(e,t))):this._renderer.value.handleResize(e,t),this._fullRefresh())}handleCharSizeChanged(){this._renderer.value?.handleCharSizeChanged()}handleBlur(){this._renderer.value?.handleBlur()}handleFocus(){this._renderer.value?.handleFocus()}handleSelectionChanged(e,t,i){this._selectionState.start=e,this._selectionState.end=t,this._selectionState.columnSelectMode=i,this._renderer.value?.handleSelectionChanged(e,t,i)}handleCursorMove(){this._renderer.value?.handleCursorMove()}clear(){this._renderer.value?.clear()}};t.RenderService=d=s([r(2,l.IOptionsService),r(3,o.ICharSizeService),r(4,l.IDecorationService),r(5,l.IBufferService),r(6,o.ICoreBrowserService),r(7,o.IThemeService)],d)},9312:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.SelectionService=void 0;const n=i(9806),o=i(9504),a=i(456),h=i(4725),c=i(8460),l=i(844),d=i(6114),_=i(4841),u=i(511),f=i(2585),v=String.fromCharCode(160),p=new RegExp(v,"g");let g=t.SelectionService=class extends l.Disposable{constructor(e,t,i,s,r,n,o,h,d){super(),this._element=e,this._screenElement=t,this._linkifier=i,this._bufferService=s,this._coreService=r,this._mouseService=n,this._optionsService=o,this._renderService=h,this._coreBrowserService=d,this._dragScrollAmount=0,this._enabled=!0,this._workCell=new u.CellData,this._mouseDownTimeStamp=0,this._oldHasSelection=!1,this._oldSelectionStart=void 0,this._oldSelectionEnd=void 0,this._onLinuxMouseSelection=this.register(new c.EventEmitter),this.onLinuxMouseSelection=this._onLinuxMouseSelection.event,this._onRedrawRequest=this.register(new c.EventEmitter),this.onRequestRedraw=this._onRedrawRequest.event,this._onSelectionChange=this.register(new c.EventEmitter),this.onSelectionChange=this._onSelectionChange.event,this._onRequestScrollLines=this.register(new c.EventEmitter),this.onRequestScrollLines=this._onRequestScrollLines.event,this._mouseMoveListener=e=>this._handleMouseMove(e),this._mouseUpListener=e=>this._handleMouseUp(e),this._coreService.onUserInput((()=>{this.hasSelection&&this.clearSelection()})),this._trimListener=this._bufferService.buffer.lines.onTrim((e=>this._handleTrim(e))),this.register(this._bufferService.buffers.onBufferActivate((e=>this._handleBufferActivate(e)))),this.enable(),this._model=new a.SelectionModel(this._bufferService),this._activeSelectionMode=0,this.register((0,l.toDisposable)((()=>{this._removeMouseDownListeners()})))}reset(){this.clearSelection()}disable(){this.clearSelection(),this._enabled=!1}enable(){this._enabled=!0}get selectionStart(){return this._model.finalSelectionStart}get selectionEnd(){return this._model.finalSelectionEnd}get hasSelection(){const e=this._model.finalSelectionStart,t=this._model.finalSelectionEnd;return!(!e||!t||e[0]===t[0]&&e[1]===t[1])}get selectionText(){const e=this._model.finalSelectionStart,t=this._model.finalSelectionEnd;if(!e||!t)return"";const i=this._bufferService.buffer,s=[];if(3===this._activeSelectionMode){if(e[0]===t[0])return"";const r=e[0]e.replace(p," "))).join(d.isWindows?"\r\n":"\n")}clearSelection(){this._model.clearSelection(),this._removeMouseDownListeners(),this.refresh(),this._onSelectionChange.fire()}refresh(e){this._refreshAnimationFrame||(this._refreshAnimationFrame=this._coreBrowserService.window.requestAnimationFrame((()=>this._refresh()))),d.isLinux&&e&&this.selectionText.length&&this._onLinuxMouseSelection.fire(this.selectionText)}_refresh(){this._refreshAnimationFrame=void 0,this._onRedrawRequest.fire({start:this._model.finalSelectionStart,end:this._model.finalSelectionEnd,columnSelectMode:3===this._activeSelectionMode})}_isClickInSelection(e){const t=this._getMouseBufferCoords(e),i=this._model.finalSelectionStart,s=this._model.finalSelectionEnd;return!!(i&&s&&t)&&this._areCoordsInSelection(t,i,s)}isCellInSelection(e,t){const i=this._model.finalSelectionStart,s=this._model.finalSelectionEnd;return!(!i||!s)&&this._areCoordsInSelection([e,t],i,s)}_areCoordsInSelection(e,t,i){return e[1]>t[1]&&e[1]=t[0]&&e[0]=t[0]}_selectWordAtCursor(e,t){const i=this._linkifier.currentLink?.link?.range;if(i)return this._model.selectionStart=[i.start.x-1,i.start.y-1],this._model.selectionStartLength=(0,_.getRangeLength)(i,this._bufferService.cols),this._model.selectionEnd=void 0,!0;const s=this._getMouseBufferCoords(e);return!!s&&(this._selectWordAt(s,t),this._model.selectionEnd=void 0,!0)}selectAll(){this._model.isSelectAllActive=!0,this.refresh(),this._onSelectionChange.fire()}selectLines(e,t){this._model.clearSelection(),e=Math.max(e,0),t=Math.min(t,this._bufferService.buffer.lines.length-1),this._model.selectionStart=[0,e],this._model.selectionEnd=[this._bufferService.cols,t],this.refresh(),this._onSelectionChange.fire()}_handleTrim(e){this._model.handleTrim(e)&&this.refresh()}_getMouseBufferCoords(e){const t=this._mouseService.getCoords(e,this._screenElement,this._bufferService.cols,this._bufferService.rows,!0);if(t)return t[0]--,t[1]--,t[1]+=this._bufferService.buffer.ydisp,t}_getMouseEventScrollAmount(e){let t=(0,n.getCoordsRelativeToElement)(this._coreBrowserService.window,e,this._screenElement)[1];const i=this._renderService.dimensions.css.canvas.height;return t>=0&&t<=i?0:(t>i&&(t-=i),t=Math.min(Math.max(t,-50),50),t/=50,t/Math.abs(t)+Math.round(14*t))}shouldForceSelection(e){return d.isMac?e.altKey&&this._optionsService.rawOptions.macOptionClickForcesSelection:e.shiftKey}handleMouseDown(e){if(this._mouseDownTimeStamp=e.timeStamp,(2!==e.button||!this.hasSelection)&&0===e.button){if(!this._enabled){if(!this.shouldForceSelection(e))return;e.stopPropagation()}e.preventDefault(),this._dragScrollAmount=0,this._enabled&&e.shiftKey?this._handleIncrementalClick(e):1===e.detail?this._handleSingleClick(e):2===e.detail?this._handleDoubleClick(e):3===e.detail&&this._handleTripleClick(e),this._addMouseDownListeners(),this.refresh(!0)}}_addMouseDownListeners(){this._screenElement.ownerDocument&&(this._screenElement.ownerDocument.addEventListener("mousemove",this._mouseMoveListener),this._screenElement.ownerDocument.addEventListener("mouseup",this._mouseUpListener)),this._dragScrollIntervalTimer=this._coreBrowserService.window.setInterval((()=>this._dragScroll()),50)}_removeMouseDownListeners(){this._screenElement.ownerDocument&&(this._screenElement.ownerDocument.removeEventListener("mousemove",this._mouseMoveListener),this._screenElement.ownerDocument.removeEventListener("mouseup",this._mouseUpListener)),this._coreBrowserService.window.clearInterval(this._dragScrollIntervalTimer),this._dragScrollIntervalTimer=void 0}_handleIncrementalClick(e){this._model.selectionStart&&(this._model.selectionEnd=this._getMouseBufferCoords(e))}_handleSingleClick(e){if(this._model.selectionStartLength=0,this._model.isSelectAllActive=!1,this._activeSelectionMode=this.shouldColumnSelect(e)?3:0,this._model.selectionStart=this._getMouseBufferCoords(e),!this._model.selectionStart)return;this._model.selectionEnd=void 0;const t=this._bufferService.buffer.lines.get(this._model.selectionStart[1]);t&&t.length!==this._model.selectionStart[0]&&0===t.hasWidth(this._model.selectionStart[0])&&this._model.selectionStart[0]++}_handleDoubleClick(e){this._selectWordAtCursor(e,!0)&&(this._activeSelectionMode=1)}_handleTripleClick(e){const t=this._getMouseBufferCoords(e);t&&(this._activeSelectionMode=2,this._selectLineAt(t[1]))}shouldColumnSelect(e){return e.altKey&&!(d.isMac&&this._optionsService.rawOptions.macOptionClickForcesSelection)}_handleMouseMove(e){if(e.stopImmediatePropagation(),!this._model.selectionStart)return;const t=this._model.selectionEnd?[this._model.selectionEnd[0],this._model.selectionEnd[1]]:null;if(this._model.selectionEnd=this._getMouseBufferCoords(e),!this._model.selectionEnd)return void this.refresh(!0);2===this._activeSelectionMode?this._model.selectionEnd[1]0?this._model.selectionEnd[0]=this._bufferService.cols:this._dragScrollAmount<0&&(this._model.selectionEnd[0]=0));const i=this._bufferService.buffer;if(this._model.selectionEnd[1]0?(3!==this._activeSelectionMode&&(this._model.selectionEnd[0]=this._bufferService.cols),this._model.selectionEnd[1]=Math.min(e.ydisp+this._bufferService.rows,e.lines.length-1)):(3!==this._activeSelectionMode&&(this._model.selectionEnd[0]=0),this._model.selectionEnd[1]=e.ydisp),this.refresh()}}_handleMouseUp(e){const t=e.timeStamp-this._mouseDownTimeStamp;if(this._removeMouseDownListeners(),this.selectionText.length<=1&&t<500&&e.altKey&&this._optionsService.rawOptions.altClickMovesCursor){if(this._bufferService.buffer.ybase===this._bufferService.buffer.ydisp){const t=this._mouseService.getCoords(e,this._element,this._bufferService.cols,this._bufferService.rows,!1);if(t&&void 0!==t[0]&&void 0!==t[1]){const e=(0,o.moveToCellSequence)(t[0]-1,t[1]-1,this._bufferService,this._coreService.decPrivateModes.applicationCursorKeys);this._coreService.triggerDataEvent(e,!0)}}}else this._fireEventIfSelectionChanged()}_fireEventIfSelectionChanged(){const e=this._model.finalSelectionStart,t=this._model.finalSelectionEnd,i=!(!e||!t||e[0]===t[0]&&e[1]===t[1]);i?e&&t&&(this._oldSelectionStart&&this._oldSelectionEnd&&e[0]===this._oldSelectionStart[0]&&e[1]===this._oldSelectionStart[1]&&t[0]===this._oldSelectionEnd[0]&&t[1]===this._oldSelectionEnd[1]||this._fireOnSelectionChange(e,t,i)):this._oldHasSelection&&this._fireOnSelectionChange(e,t,i)}_fireOnSelectionChange(e,t,i){this._oldSelectionStart=e,this._oldSelectionEnd=t,this._oldHasSelection=i,this._onSelectionChange.fire()}_handleBufferActivate(e){this.clearSelection(),this._trimListener.dispose(),this._trimListener=e.activeBuffer.lines.onTrim((e=>this._handleTrim(e)))}_convertViewportColToCharacterIndex(e,t){let i=t;for(let s=0;t>=s;s++){const r=e.loadCell(s,this._workCell).getChars().length;0===this._workCell.getWidth()?i--:r>1&&t!==s&&(i+=r-1)}return i}setSelection(e,t,i){this._model.clearSelection(),this._removeMouseDownListeners(),this._model.selectionStart=[e,t],this._model.selectionStartLength=i,this.refresh(),this._fireEventIfSelectionChanged()}rightClickSelect(e){this._isClickInSelection(e)||(this._selectWordAtCursor(e,!1)&&this.refresh(!0),this._fireEventIfSelectionChanged())}_getWordAt(e,t,i=!0,s=!0){if(e[0]>=this._bufferService.cols)return;const r=this._bufferService.buffer,n=r.lines.get(e[1]);if(!n)return;const o=r.translateBufferLineToString(e[1],!1);let a=this._convertViewportColToCharacterIndex(n,e[0]),h=a;const c=e[0]-a;let l=0,d=0,_=0,u=0;if(" "===o.charAt(a)){for(;a>0&&" "===o.charAt(a-1);)a--;for(;h1&&(u+=s-1,h+=s-1);t>0&&a>0&&!this._isCharWordSeparator(n.loadCell(t-1,this._workCell));){n.loadCell(t-1,this._workCell);const e=this._workCell.getChars().length;0===this._workCell.getWidth()?(l++,t--):e>1&&(_+=e-1,a-=e-1),a--,t--}for(;i1&&(u+=e-1,h+=e-1),h++,i++}}h++;let f=a+c-l+_,v=Math.min(this._bufferService.cols,h-a+l+d-_-u);if(t||""!==o.slice(a,h).trim()){if(i&&0===f&&32!==n.getCodePoint(0)){const t=r.lines.get(e[1]-1);if(t&&n.isWrapped&&32!==t.getCodePoint(this._bufferService.cols-1)){const t=this._getWordAt([this._bufferService.cols-1,e[1]-1],!1,!0,!1);if(t){const e=this._bufferService.cols-t.start;f-=e,v+=e}}}if(s&&f+v===this._bufferService.cols&&32!==n.getCodePoint(this._bufferService.cols-1)){const t=r.lines.get(e[1]+1);if(t?.isWrapped&&32!==t.getCodePoint(0)){const t=this._getWordAt([0,e[1]+1],!1,!1,!0);t&&(v+=t.length)}}return{start:f,length:v}}}_selectWordAt(e,t){const i=this._getWordAt(e,t);if(i){for(;i.start<0;)i.start+=this._bufferService.cols,e[1]--;this._model.selectionStart=[i.start,e[1]],this._model.selectionStartLength=i.length}}_selectToWordAt(e){const t=this._getWordAt(e,!0);if(t){let i=e[1];for(;t.start<0;)t.start+=this._bufferService.cols,i--;if(!this._model.areSelectionValuesReversed())for(;t.start+t.length>this._bufferService.cols;)t.length-=this._bufferService.cols,i++;this._model.selectionEnd=[this._model.areSelectionValuesReversed()?t.start:t.start+t.length,i]}}_isCharWordSeparator(e){return 0!==e.getWidth()&&this._optionsService.rawOptions.wordSeparator.indexOf(e.getChars())>=0}_selectLineAt(e){const t=this._bufferService.buffer.getWrappedRangeForLine(e),i={start:{x:0,y:t.first},end:{x:this._bufferService.cols-1,y:t.last}};this._model.selectionStart=[0,t.first],this._model.selectionEnd=void 0,this._model.selectionStartLength=(0,_.getRangeLength)(i,this._bufferService.cols)}};t.SelectionService=g=s([r(3,f.IBufferService),r(4,f.ICoreService),r(5,h.IMouseService),r(6,f.IOptionsService),r(7,h.IRenderService),r(8,h.ICoreBrowserService)],g)},4725:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.ILinkProviderService=t.IThemeService=t.ICharacterJoinerService=t.ISelectionService=t.IRenderService=t.IMouseService=t.ICoreBrowserService=t.ICharSizeService=void 0;const s=i(8343);t.ICharSizeService=(0,s.createDecorator)("CharSizeService"),t.ICoreBrowserService=(0,s.createDecorator)("CoreBrowserService"),t.IMouseService=(0,s.createDecorator)("MouseService"),t.IRenderService=(0,s.createDecorator)("RenderService"),t.ISelectionService=(0,s.createDecorator)("SelectionService"),t.ICharacterJoinerService=(0,s.createDecorator)("CharacterJoinerService"),t.IThemeService=(0,s.createDecorator)("ThemeService"),t.ILinkProviderService=(0,s.createDecorator)("LinkProviderService")},6731:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.ThemeService=t.DEFAULT_ANSI_COLORS=void 0;const n=i(7239),o=i(8055),a=i(8460),h=i(844),c=i(2585),l=o.css.toColor("#ffffff"),d=o.css.toColor("#000000"),_=o.css.toColor("#ffffff"),u=o.css.toColor("#000000"),f={css:"rgba(255, 255, 255, 0.3)",rgba:4294967117};t.DEFAULT_ANSI_COLORS=Object.freeze((()=>{const e=[o.css.toColor("#2e3436"),o.css.toColor("#cc0000"),o.css.toColor("#4e9a06"),o.css.toColor("#c4a000"),o.css.toColor("#3465a4"),o.css.toColor("#75507b"),o.css.toColor("#06989a"),o.css.toColor("#d3d7cf"),o.css.toColor("#555753"),o.css.toColor("#ef2929"),o.css.toColor("#8ae234"),o.css.toColor("#fce94f"),o.css.toColor("#729fcf"),o.css.toColor("#ad7fa8"),o.css.toColor("#34e2e2"),o.css.toColor("#eeeeec")],t=[0,95,135,175,215,255];for(let i=0;i<216;i++){const s=t[i/36%6|0],r=t[i/6%6|0],n=t[i%6];e.push({css:o.channels.toCss(s,r,n),rgba:o.channels.toRgba(s,r,n)})}for(let t=0;t<24;t++){const i=8+10*t;e.push({css:o.channels.toCss(i,i,i),rgba:o.channels.toRgba(i,i,i)})}return e})());let v=t.ThemeService=class extends h.Disposable{get colors(){return this._colors}constructor(e){super(),this._optionsService=e,this._contrastCache=new n.ColorContrastCache,this._halfContrastCache=new n.ColorContrastCache,this._onChangeColors=this.register(new a.EventEmitter),this.onChangeColors=this._onChangeColors.event,this._colors={foreground:l,background:d,cursor:_,cursorAccent:u,selectionForeground:void 0,selectionBackgroundTransparent:f,selectionBackgroundOpaque:o.color.blend(d,f),selectionInactiveBackgroundTransparent:f,selectionInactiveBackgroundOpaque:o.color.blend(d,f),ansi:t.DEFAULT_ANSI_COLORS.slice(),contrastCache:this._contrastCache,halfContrastCache:this._halfContrastCache},this._updateRestoreColors(),this._setTheme(this._optionsService.rawOptions.theme),this.register(this._optionsService.onSpecificOptionChange("minimumContrastRatio",(()=>this._contrastCache.clear()))),this.register(this._optionsService.onSpecificOptionChange("theme",(()=>this._setTheme(this._optionsService.rawOptions.theme))))}_setTheme(e={}){const i=this._colors;if(i.foreground=p(e.foreground,l),i.background=p(e.background,d),i.cursor=p(e.cursor,_),i.cursorAccent=p(e.cursorAccent,u),i.selectionBackgroundTransparent=p(e.selectionBackground,f),i.selectionBackgroundOpaque=o.color.blend(i.background,i.selectionBackgroundTransparent),i.selectionInactiveBackgroundTransparent=p(e.selectionInactiveBackground,i.selectionBackgroundTransparent),i.selectionInactiveBackgroundOpaque=o.color.blend(i.background,i.selectionInactiveBackgroundTransparent),i.selectionForeground=e.selectionForeground?p(e.selectionForeground,o.NULL_COLOR):void 0,i.selectionForeground===o.NULL_COLOR&&(i.selectionForeground=void 0),o.color.isOpaque(i.selectionBackgroundTransparent)){const e=.3;i.selectionBackgroundTransparent=o.color.opacity(i.selectionBackgroundTransparent,e)}if(o.color.isOpaque(i.selectionInactiveBackgroundTransparent)){const e=.3;i.selectionInactiveBackgroundTransparent=o.color.opacity(i.selectionInactiveBackgroundTransparent,e)}if(i.ansi=t.DEFAULT_ANSI_COLORS.slice(),i.ansi[0]=p(e.black,t.DEFAULT_ANSI_COLORS[0]),i.ansi[1]=p(e.red,t.DEFAULT_ANSI_COLORS[1]),i.ansi[2]=p(e.green,t.DEFAULT_ANSI_COLORS[2]),i.ansi[3]=p(e.yellow,t.DEFAULT_ANSI_COLORS[3]),i.ansi[4]=p(e.blue,t.DEFAULT_ANSI_COLORS[4]),i.ansi[5]=p(e.magenta,t.DEFAULT_ANSI_COLORS[5]),i.ansi[6]=p(e.cyan,t.DEFAULT_ANSI_COLORS[6]),i.ansi[7]=p(e.white,t.DEFAULT_ANSI_COLORS[7]),i.ansi[8]=p(e.brightBlack,t.DEFAULT_ANSI_COLORS[8]),i.ansi[9]=p(e.brightRed,t.DEFAULT_ANSI_COLORS[9]),i.ansi[10]=p(e.brightGreen,t.DEFAULT_ANSI_COLORS[10]),i.ansi[11]=p(e.brightYellow,t.DEFAULT_ANSI_COLORS[11]),i.ansi[12]=p(e.brightBlue,t.DEFAULT_ANSI_COLORS[12]),i.ansi[13]=p(e.brightMagenta,t.DEFAULT_ANSI_COLORS[13]),i.ansi[14]=p(e.brightCyan,t.DEFAULT_ANSI_COLORS[14]),i.ansi[15]=p(e.brightWhite,t.DEFAULT_ANSI_COLORS[15]),e.extendedAnsi){const s=Math.min(i.ansi.length-16,e.extendedAnsi.length);for(let r=0;r{Object.defineProperty(t,"__esModule",{value:!0}),t.CircularList=void 0;const s=i(8460),r=i(844);class n extends r.Disposable{constructor(e){super(),this._maxLength=e,this.onDeleteEmitter=this.register(new s.EventEmitter),this.onDelete=this.onDeleteEmitter.event,this.onInsertEmitter=this.register(new s.EventEmitter),this.onInsert=this.onInsertEmitter.event,this.onTrimEmitter=this.register(new s.EventEmitter),this.onTrim=this.onTrimEmitter.event,this._array=new Array(this._maxLength),this._startIndex=0,this._length=0}get maxLength(){return this._maxLength}set maxLength(e){if(this._maxLength===e)return;const t=new Array(e);for(let i=0;ithis._length)for(let t=this._length;t=e;t--)this._array[this._getCyclicIndex(t+i.length)]=this._array[this._getCyclicIndex(t)];for(let t=0;tthis._maxLength){const e=this._length+i.length-this._maxLength;this._startIndex+=e,this._length=this._maxLength,this.onTrimEmitter.fire(e)}else this._length+=i.length}trimStart(e){e>this._length&&(e=this._length),this._startIndex+=e,this._length-=e,this.onTrimEmitter.fire(e)}shiftElements(e,t,i){if(!(t<=0)){if(e<0||e>=this._length)throw new Error("start argument out of range");if(e+i<0)throw new Error("Cannot shift elements in list beyond index 0");if(i>0){for(let s=t-1;s>=0;s--)this.set(e+s+i,this.get(e+s));const s=e+t+i-this._length;if(s>0)for(this._length+=s;this._length>this._maxLength;)this._length--,this._startIndex++,this.onTrimEmitter.fire(1)}else for(let s=0;s{Object.defineProperty(t,"__esModule",{value:!0}),t.clone=void 0,t.clone=function e(t,i=5){if("object"!=typeof t)return t;const s=Array.isArray(t)?[]:{};for(const r in t)s[r]=i<=1?t[r]:t[r]&&e(t[r],i-1);return s}},8055:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.contrastRatio=t.toPaddedHex=t.rgba=t.rgb=t.css=t.color=t.channels=t.NULL_COLOR=void 0;let i=0,s=0,r=0,n=0;var o,a,h,c,l;function d(e){const t=e.toString(16);return t.length<2?"0"+t:t}function _(e,t){return e>>0},e.toColor=function(t,i,s,r){return{css:e.toCss(t,i,s,r),rgba:e.toRgba(t,i,s,r)}}}(o||(t.channels=o={})),function(e){function t(e,t){return n=Math.round(255*t),[i,s,r]=l.toChannels(e.rgba),{css:o.toCss(i,s,r,n),rgba:o.toRgba(i,s,r,n)}}e.blend=function(e,t){if(n=(255&t.rgba)/255,1===n)return{css:t.css,rgba:t.rgba};const a=t.rgba>>24&255,h=t.rgba>>16&255,c=t.rgba>>8&255,l=e.rgba>>24&255,d=e.rgba>>16&255,_=e.rgba>>8&255;return i=l+Math.round((a-l)*n),s=d+Math.round((h-d)*n),r=_+Math.round((c-_)*n),{css:o.toCss(i,s,r),rgba:o.toRgba(i,s,r)}},e.isOpaque=function(e){return 255==(255&e.rgba)},e.ensureContrastRatio=function(e,t,i){const s=l.ensureContrastRatio(e.rgba,t.rgba,i);if(s)return o.toColor(s>>24&255,s>>16&255,s>>8&255)},e.opaque=function(e){const t=(255|e.rgba)>>>0;return[i,s,r]=l.toChannels(t),{css:o.toCss(i,s,r),rgba:t}},e.opacity=t,e.multiplyOpacity=function(e,i){return n=255&e.rgba,t(e,n*i/255)},e.toColorRGB=function(e){return[e.rgba>>24&255,e.rgba>>16&255,e.rgba>>8&255]}}(a||(t.color=a={})),function(e){let t,a;try{const e=document.createElement("canvas");e.width=1,e.height=1;const i=e.getContext("2d",{willReadFrequently:!0});i&&(t=i,t.globalCompositeOperation="copy",a=t.createLinearGradient(0,0,1,1))}catch{}e.toColor=function(e){if(e.match(/#[\da-f]{3,8}/i))switch(e.length){case 4:return i=parseInt(e.slice(1,2).repeat(2),16),s=parseInt(e.slice(2,3).repeat(2),16),r=parseInt(e.slice(3,4).repeat(2),16),o.toColor(i,s,r);case 5:return i=parseInt(e.slice(1,2).repeat(2),16),s=parseInt(e.slice(2,3).repeat(2),16),r=parseInt(e.slice(3,4).repeat(2),16),n=parseInt(e.slice(4,5).repeat(2),16),o.toColor(i,s,r,n);case 7:return{css:e,rgba:(parseInt(e.slice(1),16)<<8|255)>>>0};case 9:return{css:e,rgba:parseInt(e.slice(1),16)>>>0}}const h=e.match(/rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(,\s*(0|1|\d?\.(\d+))\s*)?\)/);if(h)return i=parseInt(h[1]),s=parseInt(h[2]),r=parseInt(h[3]),n=Math.round(255*(void 0===h[5]?1:parseFloat(h[5]))),o.toColor(i,s,r,n);if(!t||!a)throw new Error("css.toColor: Unsupported css format");if(t.fillStyle=a,t.fillStyle=e,"string"!=typeof t.fillStyle)throw new Error("css.toColor: Unsupported css format");if(t.fillRect(0,0,1,1),[i,s,r,n]=t.getImageData(0,0,1,1).data,255!==n)throw new Error("css.toColor: Unsupported css format");return{rgba:o.toRgba(i,s,r,n),css:e}}}(h||(t.css=h={})),function(e){function t(e,t,i){const s=e/255,r=t/255,n=i/255;return.2126*(s<=.03928?s/12.92:Math.pow((s+.055)/1.055,2.4))+.7152*(r<=.03928?r/12.92:Math.pow((r+.055)/1.055,2.4))+.0722*(n<=.03928?n/12.92:Math.pow((n+.055)/1.055,2.4))}e.relativeLuminance=function(e){return t(e>>16&255,e>>8&255,255&e)},e.relativeLuminance2=t}(c||(t.rgb=c={})),function(e){function t(e,t,i){const s=e>>24&255,r=e>>16&255,n=e>>8&255;let o=t>>24&255,a=t>>16&255,h=t>>8&255,l=_(c.relativeLuminance2(o,a,h),c.relativeLuminance2(s,r,n));for(;l0||a>0||h>0);)o-=Math.max(0,Math.ceil(.1*o)),a-=Math.max(0,Math.ceil(.1*a)),h-=Math.max(0,Math.ceil(.1*h)),l=_(c.relativeLuminance2(o,a,h),c.relativeLuminance2(s,r,n));return(o<<24|a<<16|h<<8|255)>>>0}function a(e,t,i){const s=e>>24&255,r=e>>16&255,n=e>>8&255;let o=t>>24&255,a=t>>16&255,h=t>>8&255,l=_(c.relativeLuminance2(o,a,h),c.relativeLuminance2(s,r,n));for(;l>>0}e.blend=function(e,t){if(n=(255&t)/255,1===n)return t;const a=t>>24&255,h=t>>16&255,c=t>>8&255,l=e>>24&255,d=e>>16&255,_=e>>8&255;return i=l+Math.round((a-l)*n),s=d+Math.round((h-d)*n),r=_+Math.round((c-_)*n),o.toRgba(i,s,r)},e.ensureContrastRatio=function(e,i,s){const r=c.relativeLuminance(e>>8),n=c.relativeLuminance(i>>8);if(_(r,n)>8));if(o_(r,c.relativeLuminance(t>>8))?n:t}return n}const o=a(e,i,s),h=_(r,c.relativeLuminance(o>>8));if(h_(r,c.relativeLuminance(n>>8))?o:n}return o}},e.reduceLuminance=t,e.increaseLuminance=a,e.toChannels=function(e){return[e>>24&255,e>>16&255,e>>8&255,255&e]}}(l||(t.rgba=l={})),t.toPaddedHex=d,t.contrastRatio=_},8969:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.CoreTerminal=void 0;const s=i(844),r=i(2585),n=i(4348),o=i(7866),a=i(744),h=i(7302),c=i(6975),l=i(8460),d=i(1753),_=i(1480),u=i(7994),f=i(9282),v=i(5435),p=i(5981),g=i(2660);let m=!1;class S extends s.Disposable{get onScroll(){return this._onScrollApi||(this._onScrollApi=this.register(new l.EventEmitter),this._onScroll.event((e=>{this._onScrollApi?.fire(e.position)}))),this._onScrollApi.event}get cols(){return this._bufferService.cols}get rows(){return this._bufferService.rows}get buffers(){return this._bufferService.buffers}get options(){return this.optionsService.options}set options(e){for(const t in e)this.optionsService.options[t]=e[t]}constructor(e){super(),this._windowsWrappingHeuristics=this.register(new s.MutableDisposable),this._onBinary=this.register(new l.EventEmitter),this.onBinary=this._onBinary.event,this._onData=this.register(new l.EventEmitter),this.onData=this._onData.event,this._onLineFeed=this.register(new l.EventEmitter),this.onLineFeed=this._onLineFeed.event,this._onResize=this.register(new l.EventEmitter),this.onResize=this._onResize.event,this._onWriteParsed=this.register(new l.EventEmitter),this.onWriteParsed=this._onWriteParsed.event,this._onScroll=this.register(new l.EventEmitter),this._instantiationService=new n.InstantiationService,this.optionsService=this.register(new h.OptionsService(e)),this._instantiationService.setService(r.IOptionsService,this.optionsService),this._bufferService=this.register(this._instantiationService.createInstance(a.BufferService)),this._instantiationService.setService(r.IBufferService,this._bufferService),this._logService=this.register(this._instantiationService.createInstance(o.LogService)),this._instantiationService.setService(r.ILogService,this._logService),this.coreService=this.register(this._instantiationService.createInstance(c.CoreService)),this._instantiationService.setService(r.ICoreService,this.coreService),this.coreMouseService=this.register(this._instantiationService.createInstance(d.CoreMouseService)),this._instantiationService.setService(r.ICoreMouseService,this.coreMouseService),this.unicodeService=this.register(this._instantiationService.createInstance(_.UnicodeService)),this._instantiationService.setService(r.IUnicodeService,this.unicodeService),this._charsetService=this._instantiationService.createInstance(u.CharsetService),this._instantiationService.setService(r.ICharsetService,this._charsetService),this._oscLinkService=this._instantiationService.createInstance(g.OscLinkService),this._instantiationService.setService(r.IOscLinkService,this._oscLinkService),this._inputHandler=this.register(new v.InputHandler(this._bufferService,this._charsetService,this.coreService,this._logService,this.optionsService,this._oscLinkService,this.coreMouseService,this.unicodeService)),this.register((0,l.forwardEvent)(this._inputHandler.onLineFeed,this._onLineFeed)),this.register(this._inputHandler),this.register((0,l.forwardEvent)(this._bufferService.onResize,this._onResize)),this.register((0,l.forwardEvent)(this.coreService.onData,this._onData)),this.register((0,l.forwardEvent)(this.coreService.onBinary,this._onBinary)),this.register(this.coreService.onRequestScrollToBottom((()=>this.scrollToBottom()))),this.register(this.coreService.onUserInput((()=>this._writeBuffer.handleUserInput()))),this.register(this.optionsService.onMultipleOptionChange(["windowsMode","windowsPty"],(()=>this._handleWindowsPtyOptionChange()))),this.register(this._bufferService.onScroll((e=>{this._onScroll.fire({position:this._bufferService.buffer.ydisp,source:0}),this._inputHandler.markRangeDirty(this._bufferService.buffer.scrollTop,this._bufferService.buffer.scrollBottom)}))),this.register(this._inputHandler.onScroll((e=>{this._onScroll.fire({position:this._bufferService.buffer.ydisp,source:0}),this._inputHandler.markRangeDirty(this._bufferService.buffer.scrollTop,this._bufferService.buffer.scrollBottom)}))),this._writeBuffer=this.register(new p.WriteBuffer(((e,t)=>this._inputHandler.parse(e,t)))),this.register((0,l.forwardEvent)(this._writeBuffer.onWriteParsed,this._onWriteParsed))}write(e,t){this._writeBuffer.write(e,t)}writeSync(e,t){this._logService.logLevel<=r.LogLevelEnum.WARN&&!m&&(this._logService.warn("writeSync is unreliable and will be removed soon."),m=!0),this._writeBuffer.writeSync(e,t)}input(e,t=!0){this.coreService.triggerDataEvent(e,t)}resize(e,t){isNaN(e)||isNaN(t)||(e=Math.max(e,a.MINIMUM_COLS),t=Math.max(t,a.MINIMUM_ROWS),this._bufferService.resize(e,t))}scroll(e,t=!1){this._bufferService.scroll(e,t)}scrollLines(e,t,i){this._bufferService.scrollLines(e,t,i)}scrollPages(e){this.scrollLines(e*(this.rows-1))}scrollToTop(){this.scrollLines(-this._bufferService.buffer.ydisp)}scrollToBottom(){this.scrollLines(this._bufferService.buffer.ybase-this._bufferService.buffer.ydisp)}scrollToLine(e){const t=e-this._bufferService.buffer.ydisp;0!==t&&this.scrollLines(t)}registerEscHandler(e,t){return this._inputHandler.registerEscHandler(e,t)}registerDcsHandler(e,t){return this._inputHandler.registerDcsHandler(e,t)}registerCsiHandler(e,t){return this._inputHandler.registerCsiHandler(e,t)}registerOscHandler(e,t){return this._inputHandler.registerOscHandler(e,t)}_setup(){this._handleWindowsPtyOptionChange()}reset(){this._inputHandler.reset(),this._bufferService.reset(),this._charsetService.reset(),this.coreService.reset(),this.coreMouseService.reset()}_handleWindowsPtyOptionChange(){let e=!1;const t=this.optionsService.rawOptions.windowsPty;t&&void 0!==t.buildNumber&&void 0!==t.buildNumber?e=!!("conpty"===t.backend&&t.buildNumber<21376):this.optionsService.rawOptions.windowsMode&&(e=!0),e?this._enableWindowsWrappingHeuristics():this._windowsWrappingHeuristics.clear()}_enableWindowsWrappingHeuristics(){if(!this._windowsWrappingHeuristics.value){const e=[];e.push(this.onLineFeed(f.updateWindowsModeWrappedState.bind(null,this._bufferService))),e.push(this.registerCsiHandler({final:"H"},(()=>((0,f.updateWindowsModeWrappedState)(this._bufferService),!1)))),this._windowsWrappingHeuristics.value=(0,s.toDisposable)((()=>{for(const t of e)t.dispose()}))}}}t.CoreTerminal=S},8460:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.runAndSubscribe=t.forwardEvent=t.EventEmitter=void 0,t.EventEmitter=class{constructor(){this._listeners=[],this._disposed=!1}get event(){return this._event||(this._event=e=>(this._listeners.push(e),{dispose:()=>{if(!this._disposed)for(let t=0;tt.fire(e)))},t.runAndSubscribe=function(e,t){return t(void 0),e((e=>t(e)))}},5435:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.InputHandler=t.WindowsOptionsReportType=void 0;const n=i(2584),o=i(7116),a=i(2015),h=i(844),c=i(482),l=i(8437),d=i(8460),_=i(643),u=i(511),f=i(3734),v=i(2585),p=i(1480),g=i(6242),m=i(6351),S=i(5941),C={"(":0,")":1,"*":2,"+":3,"-":1,".":2},b=131072;function w(e,t){if(e>24)return t.setWinLines||!1;switch(e){case 1:return!!t.restoreWin;case 2:return!!t.minimizeWin;case 3:return!!t.setWinPosition;case 4:return!!t.setWinSizePixels;case 5:return!!t.raiseWin;case 6:return!!t.lowerWin;case 7:return!!t.refreshWin;case 8:return!!t.setWinSizeChars;case 9:return!!t.maximizeWin;case 10:return!!t.fullscreenWin;case 11:return!!t.getWinState;case 13:return!!t.getWinPosition;case 14:return!!t.getWinSizePixels;case 15:return!!t.getScreenSizePixels;case 16:return!!t.getCellSizePixels;case 18:return!!t.getWinSizeChars;case 19:return!!t.getScreenSizeChars;case 20:return!!t.getIconTitle;case 21:return!!t.getWinTitle;case 22:return!!t.pushTitle;case 23:return!!t.popTitle;case 24:return!!t.setWinLines}return!1}var y;!function(e){e[e.GET_WIN_SIZE_PIXELS=0]="GET_WIN_SIZE_PIXELS",e[e.GET_CELL_SIZE_PIXELS=1]="GET_CELL_SIZE_PIXELS"}(y||(t.WindowsOptionsReportType=y={}));let E=0;class k extends h.Disposable{getAttrData(){return this._curAttrData}constructor(e,t,i,s,r,h,_,f,v=new a.EscapeSequenceParser){super(),this._bufferService=e,this._charsetService=t,this._coreService=i,this._logService=s,this._optionsService=r,this._oscLinkService=h,this._coreMouseService=_,this._unicodeService=f,this._parser=v,this._parseBuffer=new Uint32Array(4096),this._stringDecoder=new c.StringToUtf32,this._utf8Decoder=new c.Utf8ToUtf32,this._workCell=new u.CellData,this._windowTitle="",this._iconName="",this._windowTitleStack=[],this._iconNameStack=[],this._curAttrData=l.DEFAULT_ATTR_DATA.clone(),this._eraseAttrDataInternal=l.DEFAULT_ATTR_DATA.clone(),this._onRequestBell=this.register(new d.EventEmitter),this.onRequestBell=this._onRequestBell.event,this._onRequestRefreshRows=this.register(new d.EventEmitter),this.onRequestRefreshRows=this._onRequestRefreshRows.event,this._onRequestReset=this.register(new d.EventEmitter),this.onRequestReset=this._onRequestReset.event,this._onRequestSendFocus=this.register(new d.EventEmitter),this.onRequestSendFocus=this._onRequestSendFocus.event,this._onRequestSyncScrollBar=this.register(new d.EventEmitter),this.onRequestSyncScrollBar=this._onRequestSyncScrollBar.event,this._onRequestWindowsOptionsReport=this.register(new d.EventEmitter),this.onRequestWindowsOptionsReport=this._onRequestWindowsOptionsReport.event,this._onA11yChar=this.register(new d.EventEmitter),this.onA11yChar=this._onA11yChar.event,this._onA11yTab=this.register(new d.EventEmitter),this.onA11yTab=this._onA11yTab.event,this._onCursorMove=this.register(new d.EventEmitter),this.onCursorMove=this._onCursorMove.event,this._onLineFeed=this.register(new d.EventEmitter),this.onLineFeed=this._onLineFeed.event,this._onScroll=this.register(new d.EventEmitter),this.onScroll=this._onScroll.event,this._onTitleChange=this.register(new d.EventEmitter),this.onTitleChange=this._onTitleChange.event,this._onColor=this.register(new d.EventEmitter),this.onColor=this._onColor.event,this._parseStack={paused:!1,cursorStartX:0,cursorStartY:0,decodedLength:0,position:0},this._specialColors=[256,257,258],this.register(this._parser),this._dirtyRowTracker=new L(this._bufferService),this._activeBuffer=this._bufferService.buffer,this.register(this._bufferService.buffers.onBufferActivate((e=>this._activeBuffer=e.activeBuffer))),this._parser.setCsiHandlerFallback(((e,t)=>{this._logService.debug("Unknown CSI code: ",{identifier:this._parser.identToString(e),params:t.toArray()})})),this._parser.setEscHandlerFallback((e=>{this._logService.debug("Unknown ESC code: ",{identifier:this._parser.identToString(e)})})),this._parser.setExecuteHandlerFallback((e=>{this._logService.debug("Unknown EXECUTE code: ",{code:e})})),this._parser.setOscHandlerFallback(((e,t,i)=>{this._logService.debug("Unknown OSC code: ",{identifier:e,action:t,data:i})})),this._parser.setDcsHandlerFallback(((e,t,i)=>{"HOOK"===t&&(i=i.toArray()),this._logService.debug("Unknown DCS code: ",{identifier:this._parser.identToString(e),action:t,payload:i})})),this._parser.setPrintHandler(((e,t,i)=>this.print(e,t,i))),this._parser.registerCsiHandler({final:"@"},(e=>this.insertChars(e))),this._parser.registerCsiHandler({intermediates:" ",final:"@"},(e=>this.scrollLeft(e))),this._parser.registerCsiHandler({final:"A"},(e=>this.cursorUp(e))),this._parser.registerCsiHandler({intermediates:" ",final:"A"},(e=>this.scrollRight(e))),this._parser.registerCsiHandler({final:"B"},(e=>this.cursorDown(e))),this._parser.registerCsiHandler({final:"C"},(e=>this.cursorForward(e))),this._parser.registerCsiHandler({final:"D"},(e=>this.cursorBackward(e))),this._parser.registerCsiHandler({final:"E"},(e=>this.cursorNextLine(e))),this._parser.registerCsiHandler({final:"F"},(e=>this.cursorPrecedingLine(e))),this._parser.registerCsiHandler({final:"G"},(e=>this.cursorCharAbsolute(e))),this._parser.registerCsiHandler({final:"H"},(e=>this.cursorPosition(e))),this._parser.registerCsiHandler({final:"I"},(e=>this.cursorForwardTab(e))),this._parser.registerCsiHandler({final:"J"},(e=>this.eraseInDisplay(e,!1))),this._parser.registerCsiHandler({prefix:"?",final:"J"},(e=>this.eraseInDisplay(e,!0))),this._parser.registerCsiHandler({final:"K"},(e=>this.eraseInLine(e,!1))),this._parser.registerCsiHandler({prefix:"?",final:"K"},(e=>this.eraseInLine(e,!0))),this._parser.registerCsiHandler({final:"L"},(e=>this.insertLines(e))),this._parser.registerCsiHandler({final:"M"},(e=>this.deleteLines(e))),this._parser.registerCsiHandler({final:"P"},(e=>this.deleteChars(e))),this._parser.registerCsiHandler({final:"S"},(e=>this.scrollUp(e))),this._parser.registerCsiHandler({final:"T"},(e=>this.scrollDown(e))),this._parser.registerCsiHandler({final:"X"},(e=>this.eraseChars(e))),this._parser.registerCsiHandler({final:"Z"},(e=>this.cursorBackwardTab(e))),this._parser.registerCsiHandler({final:"`"},(e=>this.charPosAbsolute(e))),this._parser.registerCsiHandler({final:"a"},(e=>this.hPositionRelative(e))),this._parser.registerCsiHandler({final:"b"},(e=>this.repeatPrecedingCharacter(e))),this._parser.registerCsiHandler({final:"c"},(e=>this.sendDeviceAttributesPrimary(e))),this._parser.registerCsiHandler({prefix:">",final:"c"},(e=>this.sendDeviceAttributesSecondary(e))),this._parser.registerCsiHandler({final:"d"},(e=>this.linePosAbsolute(e))),this._parser.registerCsiHandler({final:"e"},(e=>this.vPositionRelative(e))),this._parser.registerCsiHandler({final:"f"},(e=>this.hVPosition(e))),this._parser.registerCsiHandler({final:"g"},(e=>this.tabClear(e))),this._parser.registerCsiHandler({final:"h"},(e=>this.setMode(e))),this._parser.registerCsiHandler({prefix:"?",final:"h"},(e=>this.setModePrivate(e))),this._parser.registerCsiHandler({final:"l"},(e=>this.resetMode(e))),this._parser.registerCsiHandler({prefix:"?",final:"l"},(e=>this.resetModePrivate(e))),this._parser.registerCsiHandler({final:"m"},(e=>this.charAttributes(e))),this._parser.registerCsiHandler({final:"n"},(e=>this.deviceStatus(e))),this._parser.registerCsiHandler({prefix:"?",final:"n"},(e=>this.deviceStatusPrivate(e))),this._parser.registerCsiHandler({intermediates:"!",final:"p"},(e=>this.softReset(e))),this._parser.registerCsiHandler({intermediates:" ",final:"q"},(e=>this.setCursorStyle(e))),this._parser.registerCsiHandler({final:"r"},(e=>this.setScrollRegion(e))),this._parser.registerCsiHandler({final:"s"},(e=>this.saveCursor(e))),this._parser.registerCsiHandler({final:"t"},(e=>this.windowOptions(e))),this._parser.registerCsiHandler({final:"u"},(e=>this.restoreCursor(e))),this._parser.registerCsiHandler({intermediates:"'",final:"}"},(e=>this.insertColumns(e))),this._parser.registerCsiHandler({intermediates:"'",final:"~"},(e=>this.deleteColumns(e))),this._parser.registerCsiHandler({intermediates:'"',final:"q"},(e=>this.selectProtected(e))),this._parser.registerCsiHandler({intermediates:"$",final:"p"},(e=>this.requestMode(e,!0))),this._parser.registerCsiHandler({prefix:"?",intermediates:"$",final:"p"},(e=>this.requestMode(e,!1))),this._parser.setExecuteHandler(n.C0.BEL,(()=>this.bell())),this._parser.setExecuteHandler(n.C0.LF,(()=>this.lineFeed())),this._parser.setExecuteHandler(n.C0.VT,(()=>this.lineFeed())),this._parser.setExecuteHandler(n.C0.FF,(()=>this.lineFeed())),this._parser.setExecuteHandler(n.C0.CR,(()=>this.carriageReturn())),this._parser.setExecuteHandler(n.C0.BS,(()=>this.backspace())),this._parser.setExecuteHandler(n.C0.HT,(()=>this.tab())),this._parser.setExecuteHandler(n.C0.SO,(()=>this.shiftOut())),this._parser.setExecuteHandler(n.C0.SI,(()=>this.shiftIn())),this._parser.setExecuteHandler(n.C1.IND,(()=>this.index())),this._parser.setExecuteHandler(n.C1.NEL,(()=>this.nextLine())),this._parser.setExecuteHandler(n.C1.HTS,(()=>this.tabSet())),this._parser.registerOscHandler(0,new g.OscHandler((e=>(this.setTitle(e),this.setIconName(e),!0)))),this._parser.registerOscHandler(1,new g.OscHandler((e=>this.setIconName(e)))),this._parser.registerOscHandler(2,new g.OscHandler((e=>this.setTitle(e)))),this._parser.registerOscHandler(4,new g.OscHandler((e=>this.setOrReportIndexedColor(e)))),this._parser.registerOscHandler(8,new g.OscHandler((e=>this.setHyperlink(e)))),this._parser.registerOscHandler(10,new g.OscHandler((e=>this.setOrReportFgColor(e)))),this._parser.registerOscHandler(11,new g.OscHandler((e=>this.setOrReportBgColor(e)))),this._parser.registerOscHandler(12,new g.OscHandler((e=>this.setOrReportCursorColor(e)))),this._parser.registerOscHandler(104,new g.OscHandler((e=>this.restoreIndexedColor(e)))),this._parser.registerOscHandler(110,new g.OscHandler((e=>this.restoreFgColor(e)))),this._parser.registerOscHandler(111,new g.OscHandler((e=>this.restoreBgColor(e)))),this._parser.registerOscHandler(112,new g.OscHandler((e=>this.restoreCursorColor(e)))),this._parser.registerEscHandler({final:"7"},(()=>this.saveCursor())),this._parser.registerEscHandler({final:"8"},(()=>this.restoreCursor())),this._parser.registerEscHandler({final:"D"},(()=>this.index())),this._parser.registerEscHandler({final:"E"},(()=>this.nextLine())),this._parser.registerEscHandler({final:"H"},(()=>this.tabSet())),this._parser.registerEscHandler({final:"M"},(()=>this.reverseIndex())),this._parser.registerEscHandler({final:"="},(()=>this.keypadApplicationMode())),this._parser.registerEscHandler({final:">"},(()=>this.keypadNumericMode())),this._parser.registerEscHandler({final:"c"},(()=>this.fullReset())),this._parser.registerEscHandler({final:"n"},(()=>this.setgLevel(2))),this._parser.registerEscHandler({final:"o"},(()=>this.setgLevel(3))),this._parser.registerEscHandler({final:"|"},(()=>this.setgLevel(3))),this._parser.registerEscHandler({final:"}"},(()=>this.setgLevel(2))),this._parser.registerEscHandler({final:"~"},(()=>this.setgLevel(1))),this._parser.registerEscHandler({intermediates:"%",final:"@"},(()=>this.selectDefaultCharset())),this._parser.registerEscHandler({intermediates:"%",final:"G"},(()=>this.selectDefaultCharset()));for(const e in o.CHARSETS)this._parser.registerEscHandler({intermediates:"(",final:e},(()=>this.selectCharset("("+e))),this._parser.registerEscHandler({intermediates:")",final:e},(()=>this.selectCharset(")"+e))),this._parser.registerEscHandler({intermediates:"*",final:e},(()=>this.selectCharset("*"+e))),this._parser.registerEscHandler({intermediates:"+",final:e},(()=>this.selectCharset("+"+e))),this._parser.registerEscHandler({intermediates:"-",final:e},(()=>this.selectCharset("-"+e))),this._parser.registerEscHandler({intermediates:".",final:e},(()=>this.selectCharset("."+e))),this._parser.registerEscHandler({intermediates:"/",final:e},(()=>this.selectCharset("/"+e)));this._parser.registerEscHandler({intermediates:"#",final:"8"},(()=>this.screenAlignmentPattern())),this._parser.setErrorHandler((e=>(this._logService.error("Parsing error: ",e),e))),this._parser.registerDcsHandler({intermediates:"$",final:"q"},new m.DcsHandler(((e,t)=>this.requestStatusString(e,t))))}_preserveStack(e,t,i,s){this._parseStack.paused=!0,this._parseStack.cursorStartX=e,this._parseStack.cursorStartY=t,this._parseStack.decodedLength=i,this._parseStack.position=s}_logSlowResolvingAsync(e){this._logService.logLevel<=v.LogLevelEnum.WARN&&Promise.race([e,new Promise(((e,t)=>setTimeout((()=>t("#SLOW_TIMEOUT")),5e3)))]).catch((e=>{if("#SLOW_TIMEOUT"!==e)throw e;console.warn("async parser handler taking longer than 5000 ms")}))}_getCurrentLinkId(){return this._curAttrData.extended.urlId}parse(e,t){let i,s=this._activeBuffer.x,r=this._activeBuffer.y,n=0;const o=this._parseStack.paused;if(o){if(i=this._parser.parse(this._parseBuffer,this._parseStack.decodedLength,t))return this._logSlowResolvingAsync(i),i;s=this._parseStack.cursorStartX,r=this._parseStack.cursorStartY,this._parseStack.paused=!1,e.length>b&&(n=this._parseStack.position+b)}if(this._logService.logLevel<=v.LogLevelEnum.DEBUG&&this._logService.debug("parsing data"+("string"==typeof e?` "${e}"`:` "${Array.prototype.map.call(e,(e=>String.fromCharCode(e))).join("")}"`),"string"==typeof e?e.split("").map((e=>e.charCodeAt(0))):e),this._parseBuffer.lengthb)for(let t=n;t0&&2===f.getWidth(this._activeBuffer.x-1)&&f.setCellFromCodepoint(this._activeBuffer.x-1,0,1,u);let v=this._parser.precedingJoinState;for(let g=t;ga)if(h){const e=f;let t=this._activeBuffer.x-m;for(this._activeBuffer.x=m,this._activeBuffer.y++,this._activeBuffer.y===this._activeBuffer.scrollBottom+1?(this._activeBuffer.y--,this._bufferService.scroll(this._eraseAttrData(),!0)):(this._activeBuffer.y>=this._bufferService.rows&&(this._activeBuffer.y=this._bufferService.rows-1),this._activeBuffer.lines.get(this._activeBuffer.ybase+this._activeBuffer.y).isWrapped=!0),f=this._activeBuffer.lines.get(this._activeBuffer.ybase+this._activeBuffer.y),m>0&&f instanceof l.BufferLine&&f.copyCellsFrom(e,t,0,m,!1);t=0;)f.setCellFromCodepoint(this._activeBuffer.x++,0,0,u)}else if(d&&(f.insertCells(this._activeBuffer.x,r-m,this._activeBuffer.getNullCell(u)),2===f.getWidth(a-1)&&f.setCellFromCodepoint(a-1,_.NULL_CELL_CODE,_.NULL_CELL_WIDTH,u)),f.setCellFromCodepoint(this._activeBuffer.x++,s,r,u),r>0)for(;--r;)f.setCellFromCodepoint(this._activeBuffer.x++,0,0,u)}this._parser.precedingJoinState=v,this._activeBuffer.x0&&0===f.getWidth(this._activeBuffer.x)&&!f.hasContent(this._activeBuffer.x)&&f.setCellFromCodepoint(this._activeBuffer.x,0,1,u),this._dirtyRowTracker.markDirty(this._activeBuffer.y)}registerCsiHandler(e,t){return"t"!==e.final||e.prefix||e.intermediates?this._parser.registerCsiHandler(e,t):this._parser.registerCsiHandler(e,(e=>!w(e.params[0],this._optionsService.rawOptions.windowOptions)||t(e)))}registerDcsHandler(e,t){return this._parser.registerDcsHandler(e,new m.DcsHandler(t))}registerEscHandler(e,t){return this._parser.registerEscHandler(e,t)}registerOscHandler(e,t){return this._parser.registerOscHandler(e,new g.OscHandler(t))}bell(){return this._onRequestBell.fire(),!0}lineFeed(){return this._dirtyRowTracker.markDirty(this._activeBuffer.y),this._optionsService.rawOptions.convertEol&&(this._activeBuffer.x=0),this._activeBuffer.y++,this._activeBuffer.y===this._activeBuffer.scrollBottom+1?(this._activeBuffer.y--,this._bufferService.scroll(this._eraseAttrData())):this._activeBuffer.y>=this._bufferService.rows?this._activeBuffer.y=this._bufferService.rows-1:this._activeBuffer.lines.get(this._activeBuffer.ybase+this._activeBuffer.y).isWrapped=!1,this._activeBuffer.x>=this._bufferService.cols&&this._activeBuffer.x--,this._dirtyRowTracker.markDirty(this._activeBuffer.y),this._onLineFeed.fire(),!0}carriageReturn(){return this._activeBuffer.x=0,!0}backspace(){if(!this._coreService.decPrivateModes.reverseWraparound)return this._restrictCursor(),this._activeBuffer.x>0&&this._activeBuffer.x--,!0;if(this._restrictCursor(this._bufferService.cols),this._activeBuffer.x>0)this._activeBuffer.x--;else if(0===this._activeBuffer.x&&this._activeBuffer.y>this._activeBuffer.scrollTop&&this._activeBuffer.y<=this._activeBuffer.scrollBottom&&this._activeBuffer.lines.get(this._activeBuffer.ybase+this._activeBuffer.y)?.isWrapped){this._activeBuffer.lines.get(this._activeBuffer.ybase+this._activeBuffer.y).isWrapped=!1,this._activeBuffer.y--,this._activeBuffer.x=this._bufferService.cols-1;const e=this._activeBuffer.lines.get(this._activeBuffer.ybase+this._activeBuffer.y);e.hasWidth(this._activeBuffer.x)&&!e.hasContent(this._activeBuffer.x)&&this._activeBuffer.x--}return this._restrictCursor(),!0}tab(){if(this._activeBuffer.x>=this._bufferService.cols)return!0;const e=this._activeBuffer.x;return this._activeBuffer.x=this._activeBuffer.nextStop(),this._optionsService.rawOptions.screenReaderMode&&this._onA11yTab.fire(this._activeBuffer.x-e),!0}shiftOut(){return this._charsetService.setgLevel(1),!0}shiftIn(){return this._charsetService.setgLevel(0),!0}_restrictCursor(e=this._bufferService.cols-1){this._activeBuffer.x=Math.min(e,Math.max(0,this._activeBuffer.x)),this._activeBuffer.y=this._coreService.decPrivateModes.origin?Math.min(this._activeBuffer.scrollBottom,Math.max(this._activeBuffer.scrollTop,this._activeBuffer.y)):Math.min(this._bufferService.rows-1,Math.max(0,this._activeBuffer.y)),this._dirtyRowTracker.markDirty(this._activeBuffer.y)}_setCursor(e,t){this._dirtyRowTracker.markDirty(this._activeBuffer.y),this._coreService.decPrivateModes.origin?(this._activeBuffer.x=e,this._activeBuffer.y=this._activeBuffer.scrollTop+t):(this._activeBuffer.x=e,this._activeBuffer.y=t),this._restrictCursor(),this._dirtyRowTracker.markDirty(this._activeBuffer.y)}_moveCursor(e,t){this._restrictCursor(),this._setCursor(this._activeBuffer.x+e,this._activeBuffer.y+t)}cursorUp(e){const t=this._activeBuffer.y-this._activeBuffer.scrollTop;return t>=0?this._moveCursor(0,-Math.min(t,e.params[0]||1)):this._moveCursor(0,-(e.params[0]||1)),!0}cursorDown(e){const t=this._activeBuffer.scrollBottom-this._activeBuffer.y;return t>=0?this._moveCursor(0,Math.min(t,e.params[0]||1)):this._moveCursor(0,e.params[0]||1),!0}cursorForward(e){return this._moveCursor(e.params[0]||1,0),!0}cursorBackward(e){return this._moveCursor(-(e.params[0]||1),0),!0}cursorNextLine(e){return this.cursorDown(e),this._activeBuffer.x=0,!0}cursorPrecedingLine(e){return this.cursorUp(e),this._activeBuffer.x=0,!0}cursorCharAbsolute(e){return this._setCursor((e.params[0]||1)-1,this._activeBuffer.y),!0}cursorPosition(e){return this._setCursor(e.length>=2?(e.params[1]||1)-1:0,(e.params[0]||1)-1),!0}charPosAbsolute(e){return this._setCursor((e.params[0]||1)-1,this._activeBuffer.y),!0}hPositionRelative(e){return this._moveCursor(e.params[0]||1,0),!0}linePosAbsolute(e){return this._setCursor(this._activeBuffer.x,(e.params[0]||1)-1),!0}vPositionRelative(e){return this._moveCursor(0,e.params[0]||1),!0}hVPosition(e){return this.cursorPosition(e),!0}tabClear(e){const t=e.params[0];return 0===t?delete this._activeBuffer.tabs[this._activeBuffer.x]:3===t&&(this._activeBuffer.tabs={}),!0}cursorForwardTab(e){if(this._activeBuffer.x>=this._bufferService.cols)return!0;let t=e.params[0]||1;for(;t--;)this._activeBuffer.x=this._activeBuffer.nextStop();return!0}cursorBackwardTab(e){if(this._activeBuffer.x>=this._bufferService.cols)return!0;let t=e.params[0]||1;for(;t--;)this._activeBuffer.x=this._activeBuffer.prevStop();return!0}selectProtected(e){const t=e.params[0];return 1===t&&(this._curAttrData.bg|=536870912),2!==t&&0!==t||(this._curAttrData.bg&=-536870913),!0}_eraseInBufferLine(e,t,i,s=!1,r=!1){const n=this._activeBuffer.lines.get(this._activeBuffer.ybase+e);n.replaceCells(t,i,this._activeBuffer.getNullCell(this._eraseAttrData()),r),s&&(n.isWrapped=!1)}_resetBufferLine(e,t=!1){const i=this._activeBuffer.lines.get(this._activeBuffer.ybase+e);i&&(i.fill(this._activeBuffer.getNullCell(this._eraseAttrData()),t),this._bufferService.buffer.clearMarkers(this._activeBuffer.ybase+e),i.isWrapped=!1)}eraseInDisplay(e,t=!1){let i;switch(this._restrictCursor(this._bufferService.cols),e.params[0]){case 0:for(i=this._activeBuffer.y,this._dirtyRowTracker.markDirty(i),this._eraseInBufferLine(i++,this._activeBuffer.x,this._bufferService.cols,0===this._activeBuffer.x,t);i=this._bufferService.cols&&(this._activeBuffer.lines.get(i+1).isWrapped=!1);i--;)this._resetBufferLine(i,t);this._dirtyRowTracker.markDirty(0);break;case 2:for(i=this._bufferService.rows,this._dirtyRowTracker.markDirty(i-1);i--;)this._resetBufferLine(i,t);this._dirtyRowTracker.markDirty(0);break;case 3:const e=this._activeBuffer.lines.length-this._bufferService.rows;e>0&&(this._activeBuffer.lines.trimStart(e),this._activeBuffer.ybase=Math.max(this._activeBuffer.ybase-e,0),this._activeBuffer.ydisp=Math.max(this._activeBuffer.ydisp-e,0),this._onScroll.fire(0))}return!0}eraseInLine(e,t=!1){switch(this._restrictCursor(this._bufferService.cols),e.params[0]){case 0:this._eraseInBufferLine(this._activeBuffer.y,this._activeBuffer.x,this._bufferService.cols,0===this._activeBuffer.x,t);break;case 1:this._eraseInBufferLine(this._activeBuffer.y,0,this._activeBuffer.x+1,!1,t);break;case 2:this._eraseInBufferLine(this._activeBuffer.y,0,this._bufferService.cols,!0,t)}return this._dirtyRowTracker.markDirty(this._activeBuffer.y),!0}insertLines(e){this._restrictCursor();let t=e.params[0]||1;if(this._activeBuffer.y>this._activeBuffer.scrollBottom||this._activeBuffer.ythis._activeBuffer.scrollBottom||this._activeBuffer.ythis._activeBuffer.scrollBottom||this._activeBuffer.ythis._activeBuffer.scrollBottom||this._activeBuffer.ythis._activeBuffer.scrollBottom||this._activeBuffer.ythis._activeBuffer.scrollBottom||this._activeBuffer.y65535?2:1}let h=a;for(let e=1;e0||(this._is("xterm")||this._is("rxvt-unicode")||this._is("screen")?this._coreService.triggerDataEvent(n.C0.ESC+"[?1;2c"):this._is("linux")&&this._coreService.triggerDataEvent(n.C0.ESC+"[?6c")),!0}sendDeviceAttributesSecondary(e){return e.params[0]>0||(this._is("xterm")?this._coreService.triggerDataEvent(n.C0.ESC+"[>0;276;0c"):this._is("rxvt-unicode")?this._coreService.triggerDataEvent(n.C0.ESC+"[>85;95;0c"):this._is("linux")?this._coreService.triggerDataEvent(e.params[0]+"c"):this._is("screen")&&this._coreService.triggerDataEvent(n.C0.ESC+"[>83;40003;0c")),!0}_is(e){return 0===(this._optionsService.rawOptions.termName+"").indexOf(e)}setMode(e){for(let t=0;te?1:2,u=e.params[0];return f=u,v=t?2===u?4:4===u?_(o.modes.insertMode):12===u?3:20===u?_(d.convertEol):0:1===u?_(i.applicationCursorKeys):3===u?d.windowOptions.setWinLines?80===h?2:132===h?1:0:0:6===u?_(i.origin):7===u?_(i.wraparound):8===u?3:9===u?_("X10"===s):12===u?_(d.cursorBlink):25===u?_(!o.isCursorHidden):45===u?_(i.reverseWraparound):66===u?_(i.applicationKeypad):67===u?4:1e3===u?_("VT200"===s):1002===u?_("DRAG"===s):1003===u?_("ANY"===s):1004===u?_(i.sendFocus):1005===u?4:1006===u?_("SGR"===r):1015===u?4:1016===u?_("SGR_PIXELS"===r):1048===u?1:47===u||1047===u||1049===u?_(c===l):2004===u?_(i.bracketedPasteMode):0,o.triggerDataEvent(`${n.C0.ESC}[${t?"":"?"}${f};${v}$y`),!0;var f,v}_updateAttrColor(e,t,i,s,r){return 2===t?(e|=50331648,e&=-16777216,e|=f.AttributeData.fromColorRGB([i,s,r])):5===t&&(e&=-50331904,e|=33554432|255&i),e}_extractColor(e,t,i){const s=[0,0,-1,0,0,0];let r=0,n=0;do{if(s[n+r]=e.params[t+n],e.hasSubParams(t+n)){const i=e.getSubParams(t+n);let o=0;do{5===s[1]&&(r=1),s[n+o+1+r]=i[o]}while(++o=2||2===s[1]&&n+r>=5)break;s[1]&&(r=1)}while(++n+t5)&&(e=1),t.extended.underlineStyle=e,t.fg|=268435456,0===e&&(t.fg&=-268435457),t.updateExtended()}_processSGR0(e){e.fg=l.DEFAULT_ATTR_DATA.fg,e.bg=l.DEFAULT_ATTR_DATA.bg,e.extended=e.extended.clone(),e.extended.underlineStyle=0,e.extended.underlineColor&=-67108864,e.updateExtended()}charAttributes(e){if(1===e.length&&0===e.params[0])return this._processSGR0(this._curAttrData),!0;const t=e.length;let i;const s=this._curAttrData;for(let r=0;r=30&&i<=37?(s.fg&=-50331904,s.fg|=16777216|i-30):i>=40&&i<=47?(s.bg&=-50331904,s.bg|=16777216|i-40):i>=90&&i<=97?(s.fg&=-50331904,s.fg|=16777224|i-90):i>=100&&i<=107?(s.bg&=-50331904,s.bg|=16777224|i-100):0===i?this._processSGR0(s):1===i?s.fg|=134217728:3===i?s.bg|=67108864:4===i?(s.fg|=268435456,this._processUnderline(e.hasSubParams(r)?e.getSubParams(r)[0]:1,s)):5===i?s.fg|=536870912:7===i?s.fg|=67108864:8===i?s.fg|=1073741824:9===i?s.fg|=2147483648:2===i?s.bg|=134217728:21===i?this._processUnderline(2,s):22===i?(s.fg&=-134217729,s.bg&=-134217729):23===i?s.bg&=-67108865:24===i?(s.fg&=-268435457,this._processUnderline(0,s)):25===i?s.fg&=-536870913:27===i?s.fg&=-67108865:28===i?s.fg&=-1073741825:29===i?s.fg&=2147483647:39===i?(s.fg&=-67108864,s.fg|=16777215&l.DEFAULT_ATTR_DATA.fg):49===i?(s.bg&=-67108864,s.bg|=16777215&l.DEFAULT_ATTR_DATA.bg):38===i||48===i||58===i?r+=this._extractColor(e,r,s):53===i?s.bg|=1073741824:55===i?s.bg&=-1073741825:59===i?(s.extended=s.extended.clone(),s.extended.underlineColor=-1,s.updateExtended()):100===i?(s.fg&=-67108864,s.fg|=16777215&l.DEFAULT_ATTR_DATA.fg,s.bg&=-67108864,s.bg|=16777215&l.DEFAULT_ATTR_DATA.bg):this._logService.debug("Unknown SGR attribute: %d.",i);return!0}deviceStatus(e){switch(e.params[0]){case 5:this._coreService.triggerDataEvent(`${n.C0.ESC}[0n`);break;case 6:const e=this._activeBuffer.y+1,t=this._activeBuffer.x+1;this._coreService.triggerDataEvent(`${n.C0.ESC}[${e};${t}R`)}return!0}deviceStatusPrivate(e){if(6===e.params[0]){const e=this._activeBuffer.y+1,t=this._activeBuffer.x+1;this._coreService.triggerDataEvent(`${n.C0.ESC}[?${e};${t}R`)}return!0}softReset(e){return this._coreService.isCursorHidden=!1,this._onRequestSyncScrollBar.fire(),this._activeBuffer.scrollTop=0,this._activeBuffer.scrollBottom=this._bufferService.rows-1,this._curAttrData=l.DEFAULT_ATTR_DATA.clone(),this._coreService.reset(),this._charsetService.reset(),this._activeBuffer.savedX=0,this._activeBuffer.savedY=this._activeBuffer.ybase,this._activeBuffer.savedCurAttrData.fg=this._curAttrData.fg,this._activeBuffer.savedCurAttrData.bg=this._curAttrData.bg,this._activeBuffer.savedCharset=this._charsetService.charset,this._coreService.decPrivateModes.origin=!1,!0}setCursorStyle(e){const t=e.params[0]||1;switch(t){case 1:case 2:this._optionsService.options.cursorStyle="block";break;case 3:case 4:this._optionsService.options.cursorStyle="underline";break;case 5:case 6:this._optionsService.options.cursorStyle="bar"}const i=t%2==1;return this._optionsService.options.cursorBlink=i,!0}setScrollRegion(e){const t=e.params[0]||1;let i;return(e.length<2||(i=e.params[1])>this._bufferService.rows||0===i)&&(i=this._bufferService.rows),i>t&&(this._activeBuffer.scrollTop=t-1,this._activeBuffer.scrollBottom=i-1,this._setCursor(0,0)),!0}windowOptions(e){if(!w(e.params[0],this._optionsService.rawOptions.windowOptions))return!0;const t=e.length>1?e.params[1]:0;switch(e.params[0]){case 14:2!==t&&this._onRequestWindowsOptionsReport.fire(y.GET_WIN_SIZE_PIXELS);break;case 16:this._onRequestWindowsOptionsReport.fire(y.GET_CELL_SIZE_PIXELS);break;case 18:this._bufferService&&this._coreService.triggerDataEvent(`${n.C0.ESC}[8;${this._bufferService.rows};${this._bufferService.cols}t`);break;case 22:0!==t&&2!==t||(this._windowTitleStack.push(this._windowTitle),this._windowTitleStack.length>10&&this._windowTitleStack.shift()),0!==t&&1!==t||(this._iconNameStack.push(this._iconName),this._iconNameStack.length>10&&this._iconNameStack.shift());break;case 23:0!==t&&2!==t||this._windowTitleStack.length&&this.setTitle(this._windowTitleStack.pop()),0!==t&&1!==t||this._iconNameStack.length&&this.setIconName(this._iconNameStack.pop())}return!0}saveCursor(e){return this._activeBuffer.savedX=this._activeBuffer.x,this._activeBuffer.savedY=this._activeBuffer.ybase+this._activeBuffer.y,this._activeBuffer.savedCurAttrData.fg=this._curAttrData.fg,this._activeBuffer.savedCurAttrData.bg=this._curAttrData.bg,this._activeBuffer.savedCharset=this._charsetService.charset,!0}restoreCursor(e){return this._activeBuffer.x=this._activeBuffer.savedX||0,this._activeBuffer.y=Math.max(this._activeBuffer.savedY-this._activeBuffer.ybase,0),this._curAttrData.fg=this._activeBuffer.savedCurAttrData.fg,this._curAttrData.bg=this._activeBuffer.savedCurAttrData.bg,this._charsetService.charset=this._savedCharset,this._activeBuffer.savedCharset&&(this._charsetService.charset=this._activeBuffer.savedCharset),this._restrictCursor(),!0}setTitle(e){return this._windowTitle=e,this._onTitleChange.fire(e),!0}setIconName(e){return this._iconName=e,!0}setOrReportIndexedColor(e){const t=[],i=e.split(";");for(;i.length>1;){const e=i.shift(),s=i.shift();if(/^\d+$/.exec(e)){const i=parseInt(e);if(D(i))if("?"===s)t.push({type:0,index:i});else{const e=(0,S.parseColor)(s);e&&t.push({type:1,index:i,color:e})}}}return t.length&&this._onColor.fire(t),!0}setHyperlink(e){const t=e.split(";");return!(t.length<2)&&(t[1]?this._createHyperlink(t[0],t[1]):!t[0]&&this._finishHyperlink())}_createHyperlink(e,t){this._getCurrentLinkId()&&this._finishHyperlink();const i=e.split(":");let s;const r=i.findIndex((e=>e.startsWith("id=")));return-1!==r&&(s=i[r].slice(3)||void 0),this._curAttrData.extended=this._curAttrData.extended.clone(),this._curAttrData.extended.urlId=this._oscLinkService.registerLink({id:s,uri:t}),this._curAttrData.updateExtended(),!0}_finishHyperlink(){return this._curAttrData.extended=this._curAttrData.extended.clone(),this._curAttrData.extended.urlId=0,this._curAttrData.updateExtended(),!0}_setOrReportSpecialColor(e,t){const i=e.split(";");for(let e=0;e=this._specialColors.length);++e,++t)if("?"===i[e])this._onColor.fire([{type:0,index:this._specialColors[t]}]);else{const s=(0,S.parseColor)(i[e]);s&&this._onColor.fire([{type:1,index:this._specialColors[t],color:s}])}return!0}setOrReportFgColor(e){return this._setOrReportSpecialColor(e,0)}setOrReportBgColor(e){return this._setOrReportSpecialColor(e,1)}setOrReportCursorColor(e){return this._setOrReportSpecialColor(e,2)}restoreIndexedColor(e){if(!e)return this._onColor.fire([{type:2}]),!0;const t=[],i=e.split(";");for(let e=0;e=this._bufferService.rows&&(this._activeBuffer.y=this._bufferService.rows-1),this._restrictCursor(),!0}tabSet(){return this._activeBuffer.tabs[this._activeBuffer.x]=!0,!0}reverseIndex(){if(this._restrictCursor(),this._activeBuffer.y===this._activeBuffer.scrollTop){const e=this._activeBuffer.scrollBottom-this._activeBuffer.scrollTop;this._activeBuffer.lines.shiftElements(this._activeBuffer.ybase+this._activeBuffer.y,e,1),this._activeBuffer.lines.set(this._activeBuffer.ybase+this._activeBuffer.y,this._activeBuffer.getBlankLine(this._eraseAttrData())),this._dirtyRowTracker.markRangeDirty(this._activeBuffer.scrollTop,this._activeBuffer.scrollBottom)}else this._activeBuffer.y--,this._restrictCursor();return!0}fullReset(){return this._parser.reset(),this._onRequestReset.fire(),!0}reset(){this._curAttrData=l.DEFAULT_ATTR_DATA.clone(),this._eraseAttrDataInternal=l.DEFAULT_ATTR_DATA.clone()}_eraseAttrData(){return this._eraseAttrDataInternal.bg&=-67108864,this._eraseAttrDataInternal.bg|=67108863&this._curAttrData.bg,this._eraseAttrDataInternal}setgLevel(e){return this._charsetService.setgLevel(e),!0}screenAlignmentPattern(){const e=new u.CellData;e.content=1<<22|"E".charCodeAt(0),e.fg=this._curAttrData.fg,e.bg=this._curAttrData.bg,this._setCursor(0,0);for(let t=0;t(this._coreService.triggerDataEvent(`${n.C0.ESC}${e}${n.C0.ESC}\\`),!0))('"q'===e?`P1$r${this._curAttrData.isProtected()?1:0}"q`:'"p'===e?'P1$r61;1"p':"r"===e?`P1$r${i.scrollTop+1};${i.scrollBottom+1}r`:"m"===e?"P1$r0m":" q"===e?`P1$r${{block:2,underline:4,bar:6}[s.cursorStyle]-(s.cursorBlink?1:0)} q`:"P0$r")}markRangeDirty(e,t){this._dirtyRowTracker.markRangeDirty(e,t)}}t.InputHandler=k;let L=class{constructor(e){this._bufferService=e,this.clearRange()}clearRange(){this.start=this._bufferService.buffer.y,this.end=this._bufferService.buffer.y}markDirty(e){ethis.end&&(this.end=e)}markRangeDirty(e,t){e>t&&(E=e,e=t,t=E),ethis.end&&(this.end=t)}markAllDirty(){this.markRangeDirty(0,this._bufferService.rows-1)}};function D(e){return 0<=e&&e<256}L=s([r(0,v.IBufferService)],L)},844:(e,t)=>{function i(e){for(const t of e)t.dispose();e.length=0}Object.defineProperty(t,"__esModule",{value:!0}),t.getDisposeArrayDisposable=t.disposeArray=t.toDisposable=t.MutableDisposable=t.Disposable=void 0,t.Disposable=class{constructor(){this._disposables=[],this._isDisposed=!1}dispose(){this._isDisposed=!0;for(const e of this._disposables)e.dispose();this._disposables.length=0}register(e){return this._disposables.push(e),e}unregister(e){const t=this._disposables.indexOf(e);-1!==t&&this._disposables.splice(t,1)}},t.MutableDisposable=class{constructor(){this._isDisposed=!1}get value(){return this._isDisposed?void 0:this._value}set value(e){this._isDisposed||e===this._value||(this._value?.dispose(),this._value=e)}clear(){this.value=void 0}dispose(){this._isDisposed=!0,this._value?.dispose(),this._value=void 0}},t.toDisposable=function(e){return{dispose:e}},t.disposeArray=i,t.getDisposeArrayDisposable=function(e){return{dispose:()=>i(e)}}},1505:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.FourKeyMap=t.TwoKeyMap=void 0;class i{constructor(){this._data={}}set(e,t,i){this._data[e]||(this._data[e]={}),this._data[e][t]=i}get(e,t){return this._data[e]?this._data[e][t]:void 0}clear(){this._data={}}}t.TwoKeyMap=i,t.FourKeyMap=class{constructor(){this._data=new i}set(e,t,s,r,n){this._data.get(e,t)||this._data.set(e,t,new i),this._data.get(e,t).set(s,r,n)}get(e,t,i,s){return this._data.get(e,t)?.get(i,s)}clear(){this._data.clear()}}},6114:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.isChromeOS=t.isLinux=t.isWindows=t.isIphone=t.isIpad=t.isMac=t.getSafariVersion=t.isSafari=t.isLegacyEdge=t.isFirefox=t.isNode=void 0,t.isNode="undefined"!=typeof process&&"title"in process;const i=t.isNode?"node":navigator.userAgent,s=t.isNode?"node":navigator.platform;t.isFirefox=i.includes("Firefox"),t.isLegacyEdge=i.includes("Edge"),t.isSafari=/^((?!chrome|android).)*safari/i.test(i),t.getSafariVersion=function(){if(!t.isSafari)return 0;const e=i.match(/Version\/(\d+)/);return null===e||e.length<2?0:parseInt(e[1])},t.isMac=["Macintosh","MacIntel","MacPPC","Mac68K"].includes(s),t.isIpad="iPad"===s,t.isIphone="iPhone"===s,t.isWindows=["Windows","Win16","Win32","WinCE"].includes(s),t.isLinux=s.indexOf("Linux")>=0,t.isChromeOS=/\bCrOS\b/.test(i)},6106:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.SortedList=void 0;let i=0;t.SortedList=class{constructor(e){this._getKey=e,this._array=[]}clear(){this._array.length=0}insert(e){0!==this._array.length?(i=this._search(this._getKey(e)),this._array.splice(i,0,e)):this._array.push(e)}delete(e){if(0===this._array.length)return!1;const t=this._getKey(e);if(void 0===t)return!1;if(i=this._search(t),-1===i)return!1;if(this._getKey(this._array[i])!==t)return!1;do{if(this._array[i]===e)return this._array.splice(i,1),!0}while(++i=this._array.length)&&this._getKey(this._array[i])===e))do{yield this._array[i]}while(++i=this._array.length)&&this._getKey(this._array[i])===e))do{t(this._array[i])}while(++i=t;){let s=t+i>>1;const r=this._getKey(this._array[s]);if(r>e)i=s-1;else{if(!(r0&&this._getKey(this._array[s-1])===e;)s--;return s}t=s+1}}return t}}},7226:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.DebouncedIdleTask=t.IdleTaskQueue=t.PriorityTaskQueue=void 0;const s=i(6114);class r{constructor(){this._tasks=[],this._i=0}enqueue(e){this._tasks.push(e),this._start()}flush(){for(;this._ir)return s-t<-20&&console.warn(`task queue exceeded allotted deadline by ${Math.abs(Math.round(s-t))}ms`),void this._start();s=r}this.clear()}}class n extends r{_requestCallback(e){return setTimeout((()=>e(this._createDeadline(16))))}_cancelCallback(e){clearTimeout(e)}_createDeadline(e){const t=Date.now()+e;return{timeRemaining:()=>Math.max(0,t-Date.now())}}}t.PriorityTaskQueue=n,t.IdleTaskQueue=!s.isNode&&"requestIdleCallback"in window?class extends r{_requestCallback(e){return requestIdleCallback(e)}_cancelCallback(e){cancelIdleCallback(e)}}:n,t.DebouncedIdleTask=class{constructor(){this._queue=new t.IdleTaskQueue}set(e){this._queue.clear(),this._queue.enqueue(e)}flush(){this._queue.flush()}}},9282:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.updateWindowsModeWrappedState=void 0;const s=i(643);t.updateWindowsModeWrappedState=function(e){const t=e.buffer.lines.get(e.buffer.ybase+e.buffer.y-1),i=t?.get(e.cols-1),r=e.buffer.lines.get(e.buffer.ybase+e.buffer.y);r&&i&&(r.isWrapped=i[s.CHAR_DATA_CODE_INDEX]!==s.NULL_CELL_CODE&&i[s.CHAR_DATA_CODE_INDEX]!==s.WHITESPACE_CELL_CODE)}},3734:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.ExtendedAttrs=t.AttributeData=void 0;class i{constructor(){this.fg=0,this.bg=0,this.extended=new s}static toColorRGB(e){return[e>>>16&255,e>>>8&255,255&e]}static fromColorRGB(e){return(255&e[0])<<16|(255&e[1])<<8|255&e[2]}clone(){const e=new i;return e.fg=this.fg,e.bg=this.bg,e.extended=this.extended.clone(),e}isInverse(){return 67108864&this.fg}isBold(){return 134217728&this.fg}isUnderline(){return this.hasExtendedAttrs()&&0!==this.extended.underlineStyle?1:268435456&this.fg}isBlink(){return 536870912&this.fg}isInvisible(){return 1073741824&this.fg}isItalic(){return 67108864&this.bg}isDim(){return 134217728&this.bg}isStrikethrough(){return 2147483648&this.fg}isProtected(){return 536870912&this.bg}isOverline(){return 1073741824&this.bg}getFgColorMode(){return 50331648&this.fg}getBgColorMode(){return 50331648&this.bg}isFgRGB(){return 50331648==(50331648&this.fg)}isBgRGB(){return 50331648==(50331648&this.bg)}isFgPalette(){return 16777216==(50331648&this.fg)||33554432==(50331648&this.fg)}isBgPalette(){return 16777216==(50331648&this.bg)||33554432==(50331648&this.bg)}isFgDefault(){return 0==(50331648&this.fg)}isBgDefault(){return 0==(50331648&this.bg)}isAttributeDefault(){return 0===this.fg&&0===this.bg}getFgColor(){switch(50331648&this.fg){case 16777216:case 33554432:return 255&this.fg;case 50331648:return 16777215&this.fg;default:return-1}}getBgColor(){switch(50331648&this.bg){case 16777216:case 33554432:return 255&this.bg;case 50331648:return 16777215&this.bg;default:return-1}}hasExtendedAttrs(){return 268435456&this.bg}updateExtended(){this.extended.isEmpty()?this.bg&=-268435457:this.bg|=268435456}getUnderlineColor(){if(268435456&this.bg&&~this.extended.underlineColor)switch(50331648&this.extended.underlineColor){case 16777216:case 33554432:return 255&this.extended.underlineColor;case 50331648:return 16777215&this.extended.underlineColor;default:return this.getFgColor()}return this.getFgColor()}getUnderlineColorMode(){return 268435456&this.bg&&~this.extended.underlineColor?50331648&this.extended.underlineColor:this.getFgColorMode()}isUnderlineColorRGB(){return 268435456&this.bg&&~this.extended.underlineColor?50331648==(50331648&this.extended.underlineColor):this.isFgRGB()}isUnderlineColorPalette(){return 268435456&this.bg&&~this.extended.underlineColor?16777216==(50331648&this.extended.underlineColor)||33554432==(50331648&this.extended.underlineColor):this.isFgPalette()}isUnderlineColorDefault(){return 268435456&this.bg&&~this.extended.underlineColor?0==(50331648&this.extended.underlineColor):this.isFgDefault()}getUnderlineStyle(){return 268435456&this.fg?268435456&this.bg?this.extended.underlineStyle:1:0}getUnderlineVariantOffset(){return this.extended.underlineVariantOffset}}t.AttributeData=i;class s{get ext(){return this._urlId?-469762049&this._ext|this.underlineStyle<<26:this._ext}set ext(e){this._ext=e}get underlineStyle(){return this._urlId?5:(469762048&this._ext)>>26}set underlineStyle(e){this._ext&=-469762049,this._ext|=e<<26&469762048}get underlineColor(){return 67108863&this._ext}set underlineColor(e){this._ext&=-67108864,this._ext|=67108863&e}get urlId(){return this._urlId}set urlId(e){this._urlId=e}get underlineVariantOffset(){const e=(3758096384&this._ext)>>29;return e<0?4294967288^e:e}set underlineVariantOffset(e){this._ext&=536870911,this._ext|=e<<29&3758096384}constructor(e=0,t=0){this._ext=0,this._urlId=0,this._ext=e,this._urlId=t}clone(){return new s(this._ext,this._urlId)}isEmpty(){return 0===this.underlineStyle&&0===this._urlId}}t.ExtendedAttrs=s},9092:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.Buffer=t.MAX_BUFFER_SIZE=void 0;const s=i(6349),r=i(7226),n=i(3734),o=i(8437),a=i(4634),h=i(511),c=i(643),l=i(4863),d=i(7116);t.MAX_BUFFER_SIZE=4294967295,t.Buffer=class{constructor(e,t,i){this._hasScrollback=e,this._optionsService=t,this._bufferService=i,this.ydisp=0,this.ybase=0,this.y=0,this.x=0,this.tabs={},this.savedY=0,this.savedX=0,this.savedCurAttrData=o.DEFAULT_ATTR_DATA.clone(),this.savedCharset=d.DEFAULT_CHARSET,this.markers=[],this._nullCell=h.CellData.fromCharData([0,c.NULL_CELL_CHAR,c.NULL_CELL_WIDTH,c.NULL_CELL_CODE]),this._whitespaceCell=h.CellData.fromCharData([0,c.WHITESPACE_CELL_CHAR,c.WHITESPACE_CELL_WIDTH,c.WHITESPACE_CELL_CODE]),this._isClearing=!1,this._memoryCleanupQueue=new r.IdleTaskQueue,this._memoryCleanupPosition=0,this._cols=this._bufferService.cols,this._rows=this._bufferService.rows,this.lines=new s.CircularList(this._getCorrectBufferLength(this._rows)),this.scrollTop=0,this.scrollBottom=this._rows-1,this.setupTabStops()}getNullCell(e){return e?(this._nullCell.fg=e.fg,this._nullCell.bg=e.bg,this._nullCell.extended=e.extended):(this._nullCell.fg=0,this._nullCell.bg=0,this._nullCell.extended=new n.ExtendedAttrs),this._nullCell}getWhitespaceCell(e){return e?(this._whitespaceCell.fg=e.fg,this._whitespaceCell.bg=e.bg,this._whitespaceCell.extended=e.extended):(this._whitespaceCell.fg=0,this._whitespaceCell.bg=0,this._whitespaceCell.extended=new n.ExtendedAttrs),this._whitespaceCell}getBlankLine(e,t){return new o.BufferLine(this._bufferService.cols,this.getNullCell(e),t)}get hasScrollback(){return this._hasScrollback&&this.lines.maxLength>this._rows}get isCursorInViewport(){const e=this.ybase+this.y-this.ydisp;return e>=0&&et.MAX_BUFFER_SIZE?t.MAX_BUFFER_SIZE:i}fillViewportRows(e){if(0===this.lines.length){void 0===e&&(e=o.DEFAULT_ATTR_DATA);let t=this._rows;for(;t--;)this.lines.push(this.getBlankLine(e))}}clear(){this.ydisp=0,this.ybase=0,this.y=0,this.x=0,this.lines=new s.CircularList(this._getCorrectBufferLength(this._rows)),this.scrollTop=0,this.scrollBottom=this._rows-1,this.setupTabStops()}resize(e,t){const i=this.getNullCell(o.DEFAULT_ATTR_DATA);let s=0;const r=this._getCorrectBufferLength(t);if(r>this.lines.maxLength&&(this.lines.maxLength=r),this.lines.length>0){if(this._cols0&&this.lines.length<=this.ybase+this.y+n+1?(this.ybase--,n++,this.ydisp>0&&this.ydisp--):this.lines.push(new o.BufferLine(e,i)));else for(let e=this._rows;e>t;e--)this.lines.length>t+this.ybase&&(this.lines.length>this.ybase+this.y+1?this.lines.pop():(this.ybase++,this.ydisp++));if(r0&&(this.lines.trimStart(e),this.ybase=Math.max(this.ybase-e,0),this.ydisp=Math.max(this.ydisp-e,0),this.savedY=Math.max(this.savedY-e,0)),this.lines.maxLength=r}this.x=Math.min(this.x,e-1),this.y=Math.min(this.y,t-1),n&&(this.y+=n),this.savedX=Math.min(this.savedX,e-1),this.scrollTop=0}if(this.scrollBottom=t-1,this._isReflowEnabled&&(this._reflow(e,t),this._cols>e))for(let t=0;t.1*this.lines.length&&(this._memoryCleanupPosition=0,this._memoryCleanupQueue.enqueue((()=>this._batchedMemoryCleanup())))}_batchedMemoryCleanup(){let e=!0;this._memoryCleanupPosition>=this.lines.length&&(this._memoryCleanupPosition=0,e=!1);let t=0;for(;this._memoryCleanupPosition100)return!0;return e}get _isReflowEnabled(){const e=this._optionsService.rawOptions.windowsPty;return e&&e.buildNumber?this._hasScrollback&&"conpty"===e.backend&&e.buildNumber>=21376:this._hasScrollback&&!this._optionsService.rawOptions.windowsMode}_reflow(e,t){this._cols!==e&&(e>this._cols?this._reflowLarger(e,t):this._reflowSmaller(e,t))}_reflowLarger(e,t){const i=(0,a.reflowLargerGetLinesToRemove)(this.lines,this._cols,e,this.ybase+this.y,this.getNullCell(o.DEFAULT_ATTR_DATA));if(i.length>0){const s=(0,a.reflowLargerCreateNewLayout)(this.lines,i);(0,a.reflowLargerApplyNewLayout)(this.lines,s.layout),this._reflowLargerAdjustViewport(e,t,s.countRemoved)}}_reflowLargerAdjustViewport(e,t,i){const s=this.getNullCell(o.DEFAULT_ATTR_DATA);let r=i;for(;r-- >0;)0===this.ybase?(this.y>0&&this.y--,this.lines.length=0;n--){let h=this.lines.get(n);if(!h||!h.isWrapped&&h.getTrimmedLength()<=e)continue;const c=[h];for(;h.isWrapped&&n>0;)h=this.lines.get(--n),c.unshift(h);const l=this.ybase+this.y;if(l>=n&&l0&&(s.push({start:n+c.length+r,newLines:v}),r+=v.length),c.push(...v);let p=_.length-1,g=_[p];0===g&&(p--,g=_[p]);let m=c.length-u-1,S=d;for(;m>=0;){const e=Math.min(S,g);if(void 0===c[p])break;if(c[p].copyCellsFrom(c[m],S-e,g-e,e,!0),g-=e,0===g&&(p--,g=_[p]),S-=e,0===S){m--;const e=Math.max(m,0);S=(0,a.getWrappedLineTrimmedLength)(c,e,this._cols)}}for(let t=0;t0;)0===this.ybase?this.y0){const e=[],t=[];for(let e=0;e=0;c--)if(a&&a.start>n+h){for(let e=a.newLines.length-1;e>=0;e--)this.lines.set(c--,a.newLines[e]);c++,e.push({index:n+1,amount:a.newLines.length}),h+=a.newLines.length,a=s[++o]}else this.lines.set(c,t[n--]);let c=0;for(let t=e.length-1;t>=0;t--)e[t].index+=c,this.lines.onInsertEmitter.fire(e[t]),c+=e[t].amount;const l=Math.max(0,i+r-this.lines.maxLength);l>0&&this.lines.onTrimEmitter.fire(l)}}translateBufferLineToString(e,t,i=0,s){const r=this.lines.get(e);return r?r.translateToString(t,i,s):""}getWrappedRangeForLine(e){let t=e,i=e;for(;t>0&&this.lines.get(t).isWrapped;)t--;for(;i+10;);return e>=this._cols?this._cols-1:e<0?0:e}nextStop(e){for(null==e&&(e=this.x);!this.tabs[++e]&&e=this._cols?this._cols-1:e<0?0:e}clearMarkers(e){this._isClearing=!0;for(let t=0;t{t.line-=e,t.line<0&&t.dispose()}))),t.register(this.lines.onInsert((e=>{t.line>=e.index&&(t.line+=e.amount)}))),t.register(this.lines.onDelete((e=>{t.line>=e.index&&t.linee.index&&(t.line-=e.amount)}))),t.register(t.onDispose((()=>this._removeMarker(t)))),t}_removeMarker(e){this._isClearing||this.markers.splice(this.markers.indexOf(e),1)}}},8437:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.BufferLine=t.DEFAULT_ATTR_DATA=void 0;const s=i(3734),r=i(511),n=i(643),o=i(482);t.DEFAULT_ATTR_DATA=Object.freeze(new s.AttributeData);let a=0;class h{constructor(e,t,i=!1){this.isWrapped=i,this._combined={},this._extendedAttrs={},this._data=new Uint32Array(3*e);const s=t||r.CellData.fromCharData([0,n.NULL_CELL_CHAR,n.NULL_CELL_WIDTH,n.NULL_CELL_CODE]);for(let t=0;t>22,2097152&t?this._combined[e].charCodeAt(this._combined[e].length-1):i]}set(e,t){this._data[3*e+1]=t[n.CHAR_DATA_ATTR_INDEX],t[n.CHAR_DATA_CHAR_INDEX].length>1?(this._combined[e]=t[1],this._data[3*e+0]=2097152|e|t[n.CHAR_DATA_WIDTH_INDEX]<<22):this._data[3*e+0]=t[n.CHAR_DATA_CHAR_INDEX].charCodeAt(0)|t[n.CHAR_DATA_WIDTH_INDEX]<<22}getWidth(e){return this._data[3*e+0]>>22}hasWidth(e){return 12582912&this._data[3*e+0]}getFg(e){return this._data[3*e+1]}getBg(e){return this._data[3*e+2]}hasContent(e){return 4194303&this._data[3*e+0]}getCodePoint(e){const t=this._data[3*e+0];return 2097152&t?this._combined[e].charCodeAt(this._combined[e].length-1):2097151&t}isCombined(e){return 2097152&this._data[3*e+0]}getString(e){const t=this._data[3*e+0];return 2097152&t?this._combined[e]:2097151&t?(0,o.stringFromCodePoint)(2097151&t):""}isProtected(e){return 536870912&this._data[3*e+2]}loadCell(e,t){return a=3*e,t.content=this._data[a+0],t.fg=this._data[a+1],t.bg=this._data[a+2],2097152&t.content&&(t.combinedData=this._combined[e]),268435456&t.bg&&(t.extended=this._extendedAttrs[e]),t}setCell(e,t){2097152&t.content&&(this._combined[e]=t.combinedData),268435456&t.bg&&(this._extendedAttrs[e]=t.extended),this._data[3*e+0]=t.content,this._data[3*e+1]=t.fg,this._data[3*e+2]=t.bg}setCellFromCodepoint(e,t,i,s){268435456&s.bg&&(this._extendedAttrs[e]=s.extended),this._data[3*e+0]=t|i<<22,this._data[3*e+1]=s.fg,this._data[3*e+2]=s.bg}addCodepointToCell(e,t,i){let s=this._data[3*e+0];2097152&s?this._combined[e]+=(0,o.stringFromCodePoint)(t):2097151&s?(this._combined[e]=(0,o.stringFromCodePoint)(2097151&s)+(0,o.stringFromCodePoint)(t),s&=-2097152,s|=2097152):s=t|1<<22,i&&(s&=-12582913,s|=i<<22),this._data[3*e+0]=s}insertCells(e,t,i){if((e%=this.length)&&2===this.getWidth(e-1)&&this.setCellFromCodepoint(e-1,0,1,i),t=0;--i)this.setCell(e+t+i,this.loadCell(e+i,s));for(let s=0;sthis.length){if(this._data.buffer.byteLength>=4*i)this._data=new Uint32Array(this._data.buffer,0,i);else{const e=new Uint32Array(i);e.set(this._data),this._data=e}for(let i=this.length;i=e&&delete this._combined[s]}const s=Object.keys(this._extendedAttrs);for(let t=0;t=e&&delete this._extendedAttrs[i]}}return this.length=e,4*i*2=0;--e)if(4194303&this._data[3*e+0])return e+(this._data[3*e+0]>>22);return 0}getNoBgTrimmedLength(){for(let e=this.length-1;e>=0;--e)if(4194303&this._data[3*e+0]||50331648&this._data[3*e+2])return e+(this._data[3*e+0]>>22);return 0}copyCellsFrom(e,t,i,s,r){const n=e._data;if(r)for(let r=s-1;r>=0;r--){for(let e=0;e<3;e++)this._data[3*(i+r)+e]=n[3*(t+r)+e];268435456&n[3*(t+r)+2]&&(this._extendedAttrs[i+r]=e._extendedAttrs[t+r])}else for(let r=0;r=t&&(this._combined[r-t+i]=e._combined[r])}}translateToString(e,t,i,s){t=t??0,i=i??this.length,e&&(i=Math.min(i,this.getTrimmedLength())),s&&(s.length=0);let r="";for(;t>22||1}return s&&s.push(t),r}}t.BufferLine=h},4841:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.getRangeLength=void 0,t.getRangeLength=function(e,t){if(e.start.y>e.end.y)throw new Error(`Buffer range end (${e.end.x}, ${e.end.y}) cannot be before start (${e.start.x}, ${e.start.y})`);return t*(e.end.y-e.start.y)+(e.end.x-e.start.x+1)}},4634:(e,t)=>{function i(e,t,i){if(t===e.length-1)return e[t].getTrimmedLength();const s=!e[t].hasContent(i-1)&&1===e[t].getWidth(i-1),r=2===e[t+1].getWidth(0);return s&&r?i-1:i}Object.defineProperty(t,"__esModule",{value:!0}),t.getWrappedLineTrimmedLength=t.reflowSmallerGetNewLineLengths=t.reflowLargerApplyNewLayout=t.reflowLargerCreateNewLayout=t.reflowLargerGetLinesToRemove=void 0,t.reflowLargerGetLinesToRemove=function(e,t,s,r,n){const o=[];for(let a=0;a=a&&r0&&(e>d||0===l[e].getTrimmedLength());e--)v++;v>0&&(o.push(a+l.length-v),o.push(v)),a+=l.length-1}return o},t.reflowLargerCreateNewLayout=function(e,t){const i=[];let s=0,r=t[s],n=0;for(let o=0;oi(e,r,t))).reduce(((e,t)=>e+t));let o=0,a=0,h=0;for(;hc&&(o-=c,a++);const l=2===e[a].getWidth(o-1);l&&o--;const d=l?s-1:s;r.push(d),h+=d}return r},t.getWrappedLineTrimmedLength=i},5295:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.BufferSet=void 0;const s=i(8460),r=i(844),n=i(9092);class o extends r.Disposable{constructor(e,t){super(),this._optionsService=e,this._bufferService=t,this._onBufferActivate=this.register(new s.EventEmitter),this.onBufferActivate=this._onBufferActivate.event,this.reset(),this.register(this._optionsService.onSpecificOptionChange("scrollback",(()=>this.resize(this._bufferService.cols,this._bufferService.rows)))),this.register(this._optionsService.onSpecificOptionChange("tabStopWidth",(()=>this.setupTabStops())))}reset(){this._normal=new n.Buffer(!0,this._optionsService,this._bufferService),this._normal.fillViewportRows(),this._alt=new n.Buffer(!1,this._optionsService,this._bufferService),this._activeBuffer=this._normal,this._onBufferActivate.fire({activeBuffer:this._normal,inactiveBuffer:this._alt}),this.setupTabStops()}get alt(){return this._alt}get active(){return this._activeBuffer}get normal(){return this._normal}activateNormalBuffer(){this._activeBuffer!==this._normal&&(this._normal.x=this._alt.x,this._normal.y=this._alt.y,this._alt.clearAllMarkers(),this._alt.clear(),this._activeBuffer=this._normal,this._onBufferActivate.fire({activeBuffer:this._normal,inactiveBuffer:this._alt}))}activateAltBuffer(e){this._activeBuffer!==this._alt&&(this._alt.fillViewportRows(e),this._alt.x=this._normal.x,this._alt.y=this._normal.y,this._activeBuffer=this._alt,this._onBufferActivate.fire({activeBuffer:this._alt,inactiveBuffer:this._normal}))}resize(e,t){this._normal.resize(e,t),this._alt.resize(e,t),this.setupTabStops(e)}setupTabStops(e){this._normal.setupTabStops(e),this._alt.setupTabStops(e)}}t.BufferSet=o},511:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.CellData=void 0;const s=i(482),r=i(643),n=i(3734);class o extends n.AttributeData{constructor(){super(...arguments),this.content=0,this.fg=0,this.bg=0,this.extended=new n.ExtendedAttrs,this.combinedData=""}static fromCharData(e){const t=new o;return t.setFromCharData(e),t}isCombined(){return 2097152&this.content}getWidth(){return this.content>>22}getChars(){return 2097152&this.content?this.combinedData:2097151&this.content?(0,s.stringFromCodePoint)(2097151&this.content):""}getCode(){return this.isCombined()?this.combinedData.charCodeAt(this.combinedData.length-1):2097151&this.content}setFromCharData(e){this.fg=e[r.CHAR_DATA_ATTR_INDEX],this.bg=0;let t=!1;if(e[r.CHAR_DATA_CHAR_INDEX].length>2)t=!0;else if(2===e[r.CHAR_DATA_CHAR_INDEX].length){const i=e[r.CHAR_DATA_CHAR_INDEX].charCodeAt(0);if(55296<=i&&i<=56319){const s=e[r.CHAR_DATA_CHAR_INDEX].charCodeAt(1);56320<=s&&s<=57343?this.content=1024*(i-55296)+s-56320+65536|e[r.CHAR_DATA_WIDTH_INDEX]<<22:t=!0}else t=!0}else this.content=e[r.CHAR_DATA_CHAR_INDEX].charCodeAt(0)|e[r.CHAR_DATA_WIDTH_INDEX]<<22;t&&(this.combinedData=e[r.CHAR_DATA_CHAR_INDEX],this.content=2097152|e[r.CHAR_DATA_WIDTH_INDEX]<<22)}getAsCharData(){return[this.fg,this.getChars(),this.getWidth(),this.getCode()]}}t.CellData=o},643:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.WHITESPACE_CELL_CODE=t.WHITESPACE_CELL_WIDTH=t.WHITESPACE_CELL_CHAR=t.NULL_CELL_CODE=t.NULL_CELL_WIDTH=t.NULL_CELL_CHAR=t.CHAR_DATA_CODE_INDEX=t.CHAR_DATA_WIDTH_INDEX=t.CHAR_DATA_CHAR_INDEX=t.CHAR_DATA_ATTR_INDEX=t.DEFAULT_EXT=t.DEFAULT_ATTR=t.DEFAULT_COLOR=void 0,t.DEFAULT_COLOR=0,t.DEFAULT_ATTR=256|t.DEFAULT_COLOR<<9,t.DEFAULT_EXT=0,t.CHAR_DATA_ATTR_INDEX=0,t.CHAR_DATA_CHAR_INDEX=1,t.CHAR_DATA_WIDTH_INDEX=2,t.CHAR_DATA_CODE_INDEX=3,t.NULL_CELL_CHAR="",t.NULL_CELL_WIDTH=1,t.NULL_CELL_CODE=0,t.WHITESPACE_CELL_CHAR=" ",t.WHITESPACE_CELL_WIDTH=1,t.WHITESPACE_CELL_CODE=32},4863:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.Marker=void 0;const s=i(8460),r=i(844);class n{get id(){return this._id}constructor(e){this.line=e,this.isDisposed=!1,this._disposables=[],this._id=n._nextId++,this._onDispose=this.register(new s.EventEmitter),this.onDispose=this._onDispose.event}dispose(){this.isDisposed||(this.isDisposed=!0,this.line=-1,this._onDispose.fire(),(0,r.disposeArray)(this._disposables),this._disposables.length=0)}register(e){return this._disposables.push(e),e}}t.Marker=n,n._nextId=1},7116:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.DEFAULT_CHARSET=t.CHARSETS=void 0,t.CHARSETS={},t.DEFAULT_CHARSET=t.CHARSETS.B,t.CHARSETS[0]={"`":"◆",a:"▒",b:"␉",c:"␌",d:"␍",e:"␊",f:"°",g:"±",h:"␤",i:"␋",j:"┘",k:"┐",l:"┌",m:"└",n:"┼",o:"⎺",p:"⎻",q:"─",r:"⎼",s:"⎽",t:"├",u:"┤",v:"┴",w:"┬",x:"│",y:"≤",z:"≥","{":"π","|":"≠","}":"£","~":"·"},t.CHARSETS.A={"#":"£"},t.CHARSETS.B=void 0,t.CHARSETS[4]={"#":"£","@":"¾","[":"ij","\\":"½","]":"|","{":"¨","|":"f","}":"¼","~":"´"},t.CHARSETS.C=t.CHARSETS[5]={"[":"Ä","\\":"Ö","]":"Å","^":"Ü","`":"é","{":"ä","|":"ö","}":"å","~":"ü"},t.CHARSETS.R={"#":"£","@":"à","[":"°","\\":"ç","]":"§","{":"é","|":"ù","}":"è","~":"¨"},t.CHARSETS.Q={"@":"à","[":"â","\\":"ç","]":"ê","^":"î","`":"ô","{":"é","|":"ù","}":"è","~":"û"},t.CHARSETS.K={"@":"§","[":"Ä","\\":"Ö","]":"Ü","{":"ä","|":"ö","}":"ü","~":"ß"},t.CHARSETS.Y={"#":"£","@":"§","[":"°","\\":"ç","]":"é","`":"ù","{":"à","|":"ò","}":"è","~":"ì"},t.CHARSETS.E=t.CHARSETS[6]={"@":"Ä","[":"Æ","\\":"Ø","]":"Å","^":"Ü","`":"ä","{":"æ","|":"ø","}":"å","~":"ü"},t.CHARSETS.Z={"#":"£","@":"§","[":"¡","\\":"Ñ","]":"¿","{":"°","|":"ñ","}":"ç"},t.CHARSETS.H=t.CHARSETS[7]={"@":"É","[":"Ä","\\":"Ö","]":"Å","^":"Ü","`":"é","{":"ä","|":"ö","}":"å","~":"ü"},t.CHARSETS["="]={"#":"ù","@":"à","[":"é","\\":"ç","]":"ê","^":"î",_:"è","`":"ô","{":"ä","|":"ö","}":"ü","~":"û"}},2584:(e,t)=>{var i,s,r;Object.defineProperty(t,"__esModule",{value:!0}),t.C1_ESCAPED=t.C1=t.C0=void 0,function(e){e.NUL="\0",e.SOH="",e.STX="",e.ETX="",e.EOT="",e.ENQ="",e.ACK="",e.BEL="",e.BS="\b",e.HT="\t",e.LF="\n",e.VT="\v",e.FF="\f",e.CR="\r",e.SO="",e.SI="",e.DLE="",e.DC1="",e.DC2="",e.DC3="",e.DC4="",e.NAK="",e.SYN="",e.ETB="",e.CAN="",e.EM="",e.SUB="",e.ESC="",e.FS="",e.GS="",e.RS="",e.US="",e.SP=" ",e.DEL=""}(i||(t.C0=i={})),function(e){e.PAD="€",e.HOP="",e.BPH="‚",e.NBH="ƒ",e.IND="„",e.NEL="…",e.SSA="†",e.ESA="‡",e.HTS="ˆ",e.HTJ="‰",e.VTS="Š",e.PLD="‹",e.PLU="Œ",e.RI="",e.SS2="Ž",e.SS3="",e.DCS="",e.PU1="‘",e.PU2="’",e.STS="“",e.CCH="”",e.MW="•",e.SPA="–",e.EPA="—",e.SOS="˜",e.SGCI="™",e.SCI="š",e.CSI="›",e.ST="œ",e.OSC="",e.PM="ž",e.APC="Ÿ"}(s||(t.C1=s={})),function(e){e.ST=`${i.ESC}\\`}(r||(t.C1_ESCAPED=r={}))},7399:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.evaluateKeyboardEvent=void 0;const s=i(2584),r={48:["0",")"],49:["1","!"],50:["2","@"],51:["3","#"],52:["4","$"],53:["5","%"],54:["6","^"],55:["7","&"],56:["8","*"],57:["9","("],186:[";",":"],187:["=","+"],188:[",","<"],189:["-","_"],190:[".",">"],191:["/","?"],192:["`","~"],219:["[","{"],220:["\\","|"],221:["]","}"],222:["'",'"']};t.evaluateKeyboardEvent=function(e,t,i,n){const o={type:0,cancel:!1,key:void 0},a=(e.shiftKey?1:0)|(e.altKey?2:0)|(e.ctrlKey?4:0)|(e.metaKey?8:0);switch(e.keyCode){case 0:"UIKeyInputUpArrow"===e.key?o.key=t?s.C0.ESC+"OA":s.C0.ESC+"[A":"UIKeyInputLeftArrow"===e.key?o.key=t?s.C0.ESC+"OD":s.C0.ESC+"[D":"UIKeyInputRightArrow"===e.key?o.key=t?s.C0.ESC+"OC":s.C0.ESC+"[C":"UIKeyInputDownArrow"===e.key&&(o.key=t?s.C0.ESC+"OB":s.C0.ESC+"[B");break;case 8:o.key=e.ctrlKey?"\b":s.C0.DEL,e.altKey&&(o.key=s.C0.ESC+o.key);break;case 9:if(e.shiftKey){o.key=s.C0.ESC+"[Z";break}o.key=s.C0.HT,o.cancel=!0;break;case 13:o.key=e.altKey?s.C0.ESC+s.C0.CR:s.C0.CR,o.cancel=!0;break;case 27:o.key=s.C0.ESC,e.altKey&&(o.key=s.C0.ESC+s.C0.ESC),o.cancel=!0;break;case 37:if(e.metaKey)break;a?(o.key=s.C0.ESC+"[1;"+(a+1)+"D",o.key===s.C0.ESC+"[1;3D"&&(o.key=s.C0.ESC+(i?"b":"[1;5D"))):o.key=t?s.C0.ESC+"OD":s.C0.ESC+"[D";break;case 39:if(e.metaKey)break;a?(o.key=s.C0.ESC+"[1;"+(a+1)+"C",o.key===s.C0.ESC+"[1;3C"&&(o.key=s.C0.ESC+(i?"f":"[1;5C"))):o.key=t?s.C0.ESC+"OC":s.C0.ESC+"[C";break;case 38:if(e.metaKey)break;a?(o.key=s.C0.ESC+"[1;"+(a+1)+"A",i||o.key!==s.C0.ESC+"[1;3A"||(o.key=s.C0.ESC+"[1;5A")):o.key=t?s.C0.ESC+"OA":s.C0.ESC+"[A";break;case 40:if(e.metaKey)break;a?(o.key=s.C0.ESC+"[1;"+(a+1)+"B",i||o.key!==s.C0.ESC+"[1;3B"||(o.key=s.C0.ESC+"[1;5B")):o.key=t?s.C0.ESC+"OB":s.C0.ESC+"[B";break;case 45:e.shiftKey||e.ctrlKey||(o.key=s.C0.ESC+"[2~");break;case 46:o.key=a?s.C0.ESC+"[3;"+(a+1)+"~":s.C0.ESC+"[3~";break;case 36:o.key=a?s.C0.ESC+"[1;"+(a+1)+"H":t?s.C0.ESC+"OH":s.C0.ESC+"[H";break;case 35:o.key=a?s.C0.ESC+"[1;"+(a+1)+"F":t?s.C0.ESC+"OF":s.C0.ESC+"[F";break;case 33:e.shiftKey?o.type=2:e.ctrlKey?o.key=s.C0.ESC+"[5;"+(a+1)+"~":o.key=s.C0.ESC+"[5~";break;case 34:e.shiftKey?o.type=3:e.ctrlKey?o.key=s.C0.ESC+"[6;"+(a+1)+"~":o.key=s.C0.ESC+"[6~";break;case 112:o.key=a?s.C0.ESC+"[1;"+(a+1)+"P":s.C0.ESC+"OP";break;case 113:o.key=a?s.C0.ESC+"[1;"+(a+1)+"Q":s.C0.ESC+"OQ";break;case 114:o.key=a?s.C0.ESC+"[1;"+(a+1)+"R":s.C0.ESC+"OR";break;case 115:o.key=a?s.C0.ESC+"[1;"+(a+1)+"S":s.C0.ESC+"OS";break;case 116:o.key=a?s.C0.ESC+"[15;"+(a+1)+"~":s.C0.ESC+"[15~";break;case 117:o.key=a?s.C0.ESC+"[17;"+(a+1)+"~":s.C0.ESC+"[17~";break;case 118:o.key=a?s.C0.ESC+"[18;"+(a+1)+"~":s.C0.ESC+"[18~";break;case 119:o.key=a?s.C0.ESC+"[19;"+(a+1)+"~":s.C0.ESC+"[19~";break;case 120:o.key=a?s.C0.ESC+"[20;"+(a+1)+"~":s.C0.ESC+"[20~";break;case 121:o.key=a?s.C0.ESC+"[21;"+(a+1)+"~":s.C0.ESC+"[21~";break;case 122:o.key=a?s.C0.ESC+"[23;"+(a+1)+"~":s.C0.ESC+"[23~";break;case 123:o.key=a?s.C0.ESC+"[24;"+(a+1)+"~":s.C0.ESC+"[24~";break;default:if(!e.ctrlKey||e.shiftKey||e.altKey||e.metaKey)if(i&&!n||!e.altKey||e.metaKey)!i||e.altKey||e.ctrlKey||e.shiftKey||!e.metaKey?e.key&&!e.ctrlKey&&!e.altKey&&!e.metaKey&&e.keyCode>=48&&1===e.key.length?o.key=e.key:e.key&&e.ctrlKey&&("_"===e.key&&(o.key=s.C0.US),"@"===e.key&&(o.key=s.C0.NUL)):65===e.keyCode&&(o.type=1);else{const t=r[e.keyCode],i=t?.[e.shiftKey?1:0];if(i)o.key=s.C0.ESC+i;else if(e.keyCode>=65&&e.keyCode<=90){const t=e.ctrlKey?e.keyCode-64:e.keyCode+32;let i=String.fromCharCode(t);e.shiftKey&&(i=i.toUpperCase()),o.key=s.C0.ESC+i}else if(32===e.keyCode)o.key=s.C0.ESC+(e.ctrlKey?s.C0.NUL:" ");else if("Dead"===e.key&&e.code.startsWith("Key")){let t=e.code.slice(3,4);e.shiftKey||(t=t.toLowerCase()),o.key=s.C0.ESC+t,o.cancel=!0}}else e.keyCode>=65&&e.keyCode<=90?o.key=String.fromCharCode(e.keyCode-64):32===e.keyCode?o.key=s.C0.NUL:e.keyCode>=51&&e.keyCode<=55?o.key=String.fromCharCode(e.keyCode-51+27):56===e.keyCode?o.key=s.C0.DEL:219===e.keyCode?o.key=s.C0.ESC:220===e.keyCode?o.key=s.C0.FS:221===e.keyCode&&(o.key=s.C0.GS)}return o}},482:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.Utf8ToUtf32=t.StringToUtf32=t.utf32ToString=t.stringFromCodePoint=void 0,t.stringFromCodePoint=function(e){return e>65535?(e-=65536,String.fromCharCode(55296+(e>>10))+String.fromCharCode(e%1024+56320)):String.fromCharCode(e)},t.utf32ToString=function(e,t=0,i=e.length){let s="";for(let r=t;r65535?(t-=65536,s+=String.fromCharCode(55296+(t>>10))+String.fromCharCode(t%1024+56320)):s+=String.fromCharCode(t)}return s},t.StringToUtf32=class{constructor(){this._interim=0}clear(){this._interim=0}decode(e,t){const i=e.length;if(!i)return 0;let s=0,r=0;if(this._interim){const i=e.charCodeAt(r++);56320<=i&&i<=57343?t[s++]=1024*(this._interim-55296)+i-56320+65536:(t[s++]=this._interim,t[s++]=i),this._interim=0}for(let n=r;n=i)return this._interim=r,s;const o=e.charCodeAt(n);56320<=o&&o<=57343?t[s++]=1024*(r-55296)+o-56320+65536:(t[s++]=r,t[s++]=o)}else 65279!==r&&(t[s++]=r)}return s}},t.Utf8ToUtf32=class{constructor(){this.interim=new Uint8Array(3)}clear(){this.interim.fill(0)}decode(e,t){const i=e.length;if(!i)return 0;let s,r,n,o,a=0,h=0,c=0;if(this.interim[0]){let s=!1,r=this.interim[0];r&=192==(224&r)?31:224==(240&r)?15:7;let n,o=0;for(;(n=63&this.interim[++o])&&o<4;)r<<=6,r|=n;const h=192==(224&this.interim[0])?2:224==(240&this.interim[0])?3:4,l=h-o;for(;c=i)return 0;if(n=e[c++],128!=(192&n)){c--,s=!0;break}this.interim[o++]=n,r<<=6,r|=63&n}s||(2===h?r<128?c--:t[a++]=r:3===h?r<2048||r>=55296&&r<=57343||65279===r||(t[a++]=r):r<65536||r>1114111||(t[a++]=r)),this.interim.fill(0)}const l=i-4;let d=c;for(;d=i)return this.interim[0]=s,a;if(r=e[d++],128!=(192&r)){d--;continue}if(h=(31&s)<<6|63&r,h<128){d--;continue}t[a++]=h}else if(224==(240&s)){if(d>=i)return this.interim[0]=s,a;if(r=e[d++],128!=(192&r)){d--;continue}if(d>=i)return this.interim[0]=s,this.interim[1]=r,a;if(n=e[d++],128!=(192&n)){d--;continue}if(h=(15&s)<<12|(63&r)<<6|63&n,h<2048||h>=55296&&h<=57343||65279===h)continue;t[a++]=h}else if(240==(248&s)){if(d>=i)return this.interim[0]=s,a;if(r=e[d++],128!=(192&r)){d--;continue}if(d>=i)return this.interim[0]=s,this.interim[1]=r,a;if(n=e[d++],128!=(192&n)){d--;continue}if(d>=i)return this.interim[0]=s,this.interim[1]=r,this.interim[2]=n,a;if(o=e[d++],128!=(192&o)){d--;continue}if(h=(7&s)<<18|(63&r)<<12|(63&n)<<6|63&o,h<65536||h>1114111)continue;t[a++]=h}}return a}}},225:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.UnicodeV6=void 0;const s=i(1480),r=[[768,879],[1155,1158],[1160,1161],[1425,1469],[1471,1471],[1473,1474],[1476,1477],[1479,1479],[1536,1539],[1552,1557],[1611,1630],[1648,1648],[1750,1764],[1767,1768],[1770,1773],[1807,1807],[1809,1809],[1840,1866],[1958,1968],[2027,2035],[2305,2306],[2364,2364],[2369,2376],[2381,2381],[2385,2388],[2402,2403],[2433,2433],[2492,2492],[2497,2500],[2509,2509],[2530,2531],[2561,2562],[2620,2620],[2625,2626],[2631,2632],[2635,2637],[2672,2673],[2689,2690],[2748,2748],[2753,2757],[2759,2760],[2765,2765],[2786,2787],[2817,2817],[2876,2876],[2879,2879],[2881,2883],[2893,2893],[2902,2902],[2946,2946],[3008,3008],[3021,3021],[3134,3136],[3142,3144],[3146,3149],[3157,3158],[3260,3260],[3263,3263],[3270,3270],[3276,3277],[3298,3299],[3393,3395],[3405,3405],[3530,3530],[3538,3540],[3542,3542],[3633,3633],[3636,3642],[3655,3662],[3761,3761],[3764,3769],[3771,3772],[3784,3789],[3864,3865],[3893,3893],[3895,3895],[3897,3897],[3953,3966],[3968,3972],[3974,3975],[3984,3991],[3993,4028],[4038,4038],[4141,4144],[4146,4146],[4150,4151],[4153,4153],[4184,4185],[4448,4607],[4959,4959],[5906,5908],[5938,5940],[5970,5971],[6002,6003],[6068,6069],[6071,6077],[6086,6086],[6089,6099],[6109,6109],[6155,6157],[6313,6313],[6432,6434],[6439,6440],[6450,6450],[6457,6459],[6679,6680],[6912,6915],[6964,6964],[6966,6970],[6972,6972],[6978,6978],[7019,7027],[7616,7626],[7678,7679],[8203,8207],[8234,8238],[8288,8291],[8298,8303],[8400,8431],[12330,12335],[12441,12442],[43014,43014],[43019,43019],[43045,43046],[64286,64286],[65024,65039],[65056,65059],[65279,65279],[65529,65531]],n=[[68097,68099],[68101,68102],[68108,68111],[68152,68154],[68159,68159],[119143,119145],[119155,119170],[119173,119179],[119210,119213],[119362,119364],[917505,917505],[917536,917631],[917760,917999]];let o;t.UnicodeV6=class{constructor(){if(this.version="6",!o){o=new Uint8Array(65536),o.fill(1),o[0]=0,o.fill(0,1,32),o.fill(0,127,160),o.fill(2,4352,4448),o[9001]=2,o[9002]=2,o.fill(2,11904,42192),o[12351]=1,o.fill(2,44032,55204),o.fill(2,63744,64256),o.fill(2,65040,65050),o.fill(2,65072,65136),o.fill(2,65280,65377),o.fill(2,65504,65511);for(let e=0;et[r][1])return!1;for(;r>=s;)if(i=s+r>>1,e>t[i][1])s=i+1;else{if(!(e=131072&&e<=196605||e>=196608&&e<=262141?2:1}charProperties(e,t){let i=this.wcwidth(e),r=0===i&&0!==t;if(r){const e=s.UnicodeService.extractWidth(t);0===e?r=!1:e>i&&(i=e)}return s.UnicodeService.createPropertyValue(0,i,r)}}},5981:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.WriteBuffer=void 0;const s=i(8460),r=i(844);class n extends r.Disposable{constructor(e){super(),this._action=e,this._writeBuffer=[],this._callbacks=[],this._pendingData=0,this._bufferOffset=0,this._isSyncWriting=!1,this._syncCalls=0,this._didUserInput=!1,this._onWriteParsed=this.register(new s.EventEmitter),this.onWriteParsed=this._onWriteParsed.event}handleUserInput(){this._didUserInput=!0}writeSync(e,t){if(void 0!==t&&this._syncCalls>t)return void(this._syncCalls=0);if(this._pendingData+=e.length,this._writeBuffer.push(e),this._callbacks.push(void 0),this._syncCalls++,this._isSyncWriting)return;let i;for(this._isSyncWriting=!0;i=this._writeBuffer.shift();){this._action(i);const e=this._callbacks.shift();e&&e()}this._pendingData=0,this._bufferOffset=2147483647,this._isSyncWriting=!1,this._syncCalls=0}write(e,t){if(this._pendingData>5e7)throw new Error("write data discarded, use flow control to avoid losing data");if(!this._writeBuffer.length){if(this._bufferOffset=0,this._didUserInput)return this._didUserInput=!1,this._pendingData+=e.length,this._writeBuffer.push(e),this._callbacks.push(t),void this._innerWrite();setTimeout((()=>this._innerWrite()))}this._pendingData+=e.length,this._writeBuffer.push(e),this._callbacks.push(t)}_innerWrite(e=0,t=!0){const i=e||Date.now();for(;this._writeBuffer.length>this._bufferOffset;){const e=this._writeBuffer[this._bufferOffset],s=this._action(e,t);if(s){const e=e=>Date.now()-i>=12?setTimeout((()=>this._innerWrite(0,e))):this._innerWrite(i,e);return void s.catch((e=>(queueMicrotask((()=>{throw e})),Promise.resolve(!1)))).then(e)}const r=this._callbacks[this._bufferOffset];if(r&&r(),this._bufferOffset++,this._pendingData-=e.length,Date.now()-i>=12)break}this._writeBuffer.length>this._bufferOffset?(this._bufferOffset>50&&(this._writeBuffer=this._writeBuffer.slice(this._bufferOffset),this._callbacks=this._callbacks.slice(this._bufferOffset),this._bufferOffset=0),setTimeout((()=>this._innerWrite()))):(this._writeBuffer.length=0,this._callbacks.length=0,this._pendingData=0,this._bufferOffset=0),this._onWriteParsed.fire()}}t.WriteBuffer=n},5941:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.toRgbString=t.parseColor=void 0;const i=/^([\da-f])\/([\da-f])\/([\da-f])$|^([\da-f]{2})\/([\da-f]{2})\/([\da-f]{2})$|^([\da-f]{3})\/([\da-f]{3})\/([\da-f]{3})$|^([\da-f]{4})\/([\da-f]{4})\/([\da-f]{4})$/,s=/^[\da-f]+$/;function r(e,t){const i=e.toString(16),s=i.length<2?"0"+i:i;switch(t){case 4:return i[0];case 8:return s;case 12:return(s+s).slice(0,3);default:return s+s}}t.parseColor=function(e){if(!e)return;let t=e.toLowerCase();if(0===t.indexOf("rgb:")){t=t.slice(4);const e=i.exec(t);if(e){const t=e[1]?15:e[4]?255:e[7]?4095:65535;return[Math.round(parseInt(e[1]||e[4]||e[7]||e[10],16)/t*255),Math.round(parseInt(e[2]||e[5]||e[8]||e[11],16)/t*255),Math.round(parseInt(e[3]||e[6]||e[9]||e[12],16)/t*255)]}}else if(0===t.indexOf("#")&&(t=t.slice(1),s.exec(t)&&[3,6,9,12].includes(t.length))){const e=t.length/3,i=[0,0,0];for(let s=0;s<3;++s){const r=parseInt(t.slice(e*s,e*s+e),16);i[s]=1===e?r<<4:2===e?r:3===e?r>>4:r>>8}return i}},t.toRgbString=function(e,t=16){const[i,s,n]=e;return`rgb:${r(i,t)}/${r(s,t)}/${r(n,t)}`}},5770:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.PAYLOAD_LIMIT=void 0,t.PAYLOAD_LIMIT=1e7},6351:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.DcsHandler=t.DcsParser=void 0;const s=i(482),r=i(8742),n=i(5770),o=[];t.DcsParser=class{constructor(){this._handlers=Object.create(null),this._active=o,this._ident=0,this._handlerFb=()=>{},this._stack={paused:!1,loopPosition:0,fallThrough:!1}}dispose(){this._handlers=Object.create(null),this._handlerFb=()=>{},this._active=o}registerHandler(e,t){void 0===this._handlers[e]&&(this._handlers[e]=[]);const i=this._handlers[e];return i.push(t),{dispose:()=>{const e=i.indexOf(t);-1!==e&&i.splice(e,1)}}}clearHandler(e){this._handlers[e]&&delete this._handlers[e]}setHandlerFallback(e){this._handlerFb=e}reset(){if(this._active.length)for(let e=this._stack.paused?this._stack.loopPosition-1:this._active.length-1;e>=0;--e)this._active[e].unhook(!1);this._stack.paused=!1,this._active=o,this._ident=0}hook(e,t){if(this.reset(),this._ident=e,this._active=this._handlers[e]||o,this._active.length)for(let e=this._active.length-1;e>=0;e--)this._active[e].hook(t);else this._handlerFb(this._ident,"HOOK",t)}put(e,t,i){if(this._active.length)for(let s=this._active.length-1;s>=0;s--)this._active[s].put(e,t,i);else this._handlerFb(this._ident,"PUT",(0,s.utf32ToString)(e,t,i))}unhook(e,t=!0){if(this._active.length){let i=!1,s=this._active.length-1,r=!1;if(this._stack.paused&&(s=this._stack.loopPosition-1,i=t,r=this._stack.fallThrough,this._stack.paused=!1),!r&&!1===i){for(;s>=0&&(i=this._active[s].unhook(e),!0!==i);s--)if(i instanceof Promise)return this._stack.paused=!0,this._stack.loopPosition=s,this._stack.fallThrough=!1,i;s--}for(;s>=0;s--)if(i=this._active[s].unhook(!1),i instanceof Promise)return this._stack.paused=!0,this._stack.loopPosition=s,this._stack.fallThrough=!0,i}else this._handlerFb(this._ident,"UNHOOK",e);this._active=o,this._ident=0}};const a=new r.Params;a.addParam(0),t.DcsHandler=class{constructor(e){this._handler=e,this._data="",this._params=a,this._hitLimit=!1}hook(e){this._params=e.length>1||e.params[0]?e.clone():a,this._data="",this._hitLimit=!1}put(e,t,i){this._hitLimit||(this._data+=(0,s.utf32ToString)(e,t,i),this._data.length>n.PAYLOAD_LIMIT&&(this._data="",this._hitLimit=!0))}unhook(e){let t=!1;if(this._hitLimit)t=!1;else if(e&&(t=this._handler(this._data,this._params),t instanceof Promise))return t.then((e=>(this._params=a,this._data="",this._hitLimit=!1,e)));return this._params=a,this._data="",this._hitLimit=!1,t}}},2015:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.EscapeSequenceParser=t.VT500_TRANSITION_TABLE=t.TransitionTable=void 0;const s=i(844),r=i(8742),n=i(6242),o=i(6351);class a{constructor(e){this.table=new Uint8Array(e)}setDefault(e,t){this.table.fill(e<<4|t)}add(e,t,i,s){this.table[t<<8|e]=i<<4|s}addMany(e,t,i,s){for(let r=0;rt)),i=(e,i)=>t.slice(e,i),s=i(32,127),r=i(0,24);r.push(25),r.push.apply(r,i(28,32));const n=i(0,14);let o;for(o in e.setDefault(1,0),e.addMany(s,0,2,0),n)e.addMany([24,26,153,154],o,3,0),e.addMany(i(128,144),o,3,0),e.addMany(i(144,152),o,3,0),e.add(156,o,0,0),e.add(27,o,11,1),e.add(157,o,4,8),e.addMany([152,158,159],o,0,7),e.add(155,o,11,3),e.add(144,o,11,9);return e.addMany(r,0,3,0),e.addMany(r,1,3,1),e.add(127,1,0,1),e.addMany(r,8,0,8),e.addMany(r,3,3,3),e.add(127,3,0,3),e.addMany(r,4,3,4),e.add(127,4,0,4),e.addMany(r,6,3,6),e.addMany(r,5,3,5),e.add(127,5,0,5),e.addMany(r,2,3,2),e.add(127,2,0,2),e.add(93,1,4,8),e.addMany(s,8,5,8),e.add(127,8,5,8),e.addMany([156,27,24,26,7],8,6,0),e.addMany(i(28,32),8,0,8),e.addMany([88,94,95],1,0,7),e.addMany(s,7,0,7),e.addMany(r,7,0,7),e.add(156,7,0,0),e.add(127,7,0,7),e.add(91,1,11,3),e.addMany(i(64,127),3,7,0),e.addMany(i(48,60),3,8,4),e.addMany([60,61,62,63],3,9,4),e.addMany(i(48,60),4,8,4),e.addMany(i(64,127),4,7,0),e.addMany([60,61,62,63],4,0,6),e.addMany(i(32,64),6,0,6),e.add(127,6,0,6),e.addMany(i(64,127),6,0,0),e.addMany(i(32,48),3,9,5),e.addMany(i(32,48),5,9,5),e.addMany(i(48,64),5,0,6),e.addMany(i(64,127),5,7,0),e.addMany(i(32,48),4,9,5),e.addMany(i(32,48),1,9,2),e.addMany(i(32,48),2,9,2),e.addMany(i(48,127),2,10,0),e.addMany(i(48,80),1,10,0),e.addMany(i(81,88),1,10,0),e.addMany([89,90,92],1,10,0),e.addMany(i(96,127),1,10,0),e.add(80,1,11,9),e.addMany(r,9,0,9),e.add(127,9,0,9),e.addMany(i(28,32),9,0,9),e.addMany(i(32,48),9,9,12),e.addMany(i(48,60),9,8,10),e.addMany([60,61,62,63],9,9,10),e.addMany(r,11,0,11),e.addMany(i(32,128),11,0,11),e.addMany(i(28,32),11,0,11),e.addMany(r,10,0,10),e.add(127,10,0,10),e.addMany(i(28,32),10,0,10),e.addMany(i(48,60),10,8,10),e.addMany([60,61,62,63],10,0,11),e.addMany(i(32,48),10,9,12),e.addMany(r,12,0,12),e.add(127,12,0,12),e.addMany(i(28,32),12,0,12),e.addMany(i(32,48),12,9,12),e.addMany(i(48,64),12,0,11),e.addMany(i(64,127),12,12,13),e.addMany(i(64,127),10,12,13),e.addMany(i(64,127),9,12,13),e.addMany(r,13,13,13),e.addMany(s,13,13,13),e.add(127,13,0,13),e.addMany([27,156,24,26],13,14,0),e.add(h,0,2,0),e.add(h,8,5,8),e.add(h,6,0,6),e.add(h,11,0,11),e.add(h,13,13,13),e}();class c extends s.Disposable{constructor(e=t.VT500_TRANSITION_TABLE){super(),this._transitions=e,this._parseStack={state:0,handlers:[],handlerPos:0,transition:0,chunkPos:0},this.initialState=0,this.currentState=this.initialState,this._params=new r.Params,this._params.addParam(0),this._collect=0,this.precedingJoinState=0,this._printHandlerFb=(e,t,i)=>{},this._executeHandlerFb=e=>{},this._csiHandlerFb=(e,t)=>{},this._escHandlerFb=e=>{},this._errorHandlerFb=e=>e,this._printHandler=this._printHandlerFb,this._executeHandlers=Object.create(null),this._csiHandlers=Object.create(null),this._escHandlers=Object.create(null),this.register((0,s.toDisposable)((()=>{this._csiHandlers=Object.create(null),this._executeHandlers=Object.create(null),this._escHandlers=Object.create(null)}))),this._oscParser=this.register(new n.OscParser),this._dcsParser=this.register(new o.DcsParser),this._errorHandler=this._errorHandlerFb,this.registerEscHandler({final:"\\"},(()=>!0))}_identifier(e,t=[64,126]){let i=0;if(e.prefix){if(e.prefix.length>1)throw new Error("only one byte as prefix supported");if(i=e.prefix.charCodeAt(0),i&&60>i||i>63)throw new Error("prefix must be in range 0x3c .. 0x3f")}if(e.intermediates){if(e.intermediates.length>2)throw new Error("only two bytes as intermediates are supported");for(let t=0;ts||s>47)throw new Error("intermediate must be in range 0x20 .. 0x2f");i<<=8,i|=s}}if(1!==e.final.length)throw new Error("final must be a single byte");const s=e.final.charCodeAt(0);if(t[0]>s||s>t[1])throw new Error(`final must be in range ${t[0]} .. ${t[1]}`);return i<<=8,i|=s,i}identToString(e){const t=[];for(;e;)t.push(String.fromCharCode(255&e)),e>>=8;return t.reverse().join("")}setPrintHandler(e){this._printHandler=e}clearPrintHandler(){this._printHandler=this._printHandlerFb}registerEscHandler(e,t){const i=this._identifier(e,[48,126]);void 0===this._escHandlers[i]&&(this._escHandlers[i]=[]);const s=this._escHandlers[i];return s.push(t),{dispose:()=>{const e=s.indexOf(t);-1!==e&&s.splice(e,1)}}}clearEscHandler(e){this._escHandlers[this._identifier(e,[48,126])]&&delete this._escHandlers[this._identifier(e,[48,126])]}setEscHandlerFallback(e){this._escHandlerFb=e}setExecuteHandler(e,t){this._executeHandlers[e.charCodeAt(0)]=t}clearExecuteHandler(e){this._executeHandlers[e.charCodeAt(0)]&&delete this._executeHandlers[e.charCodeAt(0)]}setExecuteHandlerFallback(e){this._executeHandlerFb=e}registerCsiHandler(e,t){const i=this._identifier(e);void 0===this._csiHandlers[i]&&(this._csiHandlers[i]=[]);const s=this._csiHandlers[i];return s.push(t),{dispose:()=>{const e=s.indexOf(t);-1!==e&&s.splice(e,1)}}}clearCsiHandler(e){this._csiHandlers[this._identifier(e)]&&delete this._csiHandlers[this._identifier(e)]}setCsiHandlerFallback(e){this._csiHandlerFb=e}registerDcsHandler(e,t){return this._dcsParser.registerHandler(this._identifier(e),t)}clearDcsHandler(e){this._dcsParser.clearHandler(this._identifier(e))}setDcsHandlerFallback(e){this._dcsParser.setHandlerFallback(e)}registerOscHandler(e,t){return this._oscParser.registerHandler(e,t)}clearOscHandler(e){this._oscParser.clearHandler(e)}setOscHandlerFallback(e){this._oscParser.setHandlerFallback(e)}setErrorHandler(e){this._errorHandler=e}clearErrorHandler(){this._errorHandler=this._errorHandlerFb}reset(){this.currentState=this.initialState,this._oscParser.reset(),this._dcsParser.reset(),this._params.reset(),this._params.addParam(0),this._collect=0,this.precedingJoinState=0,0!==this._parseStack.state&&(this._parseStack.state=2,this._parseStack.handlers=[])}_preserveStack(e,t,i,s,r){this._parseStack.state=e,this._parseStack.handlers=t,this._parseStack.handlerPos=i,this._parseStack.transition=s,this._parseStack.chunkPos=r}parse(e,t,i){let s,r=0,n=0,o=0;if(this._parseStack.state)if(2===this._parseStack.state)this._parseStack.state=0,o=this._parseStack.chunkPos+1;else{if(void 0===i||1===this._parseStack.state)throw this._parseStack.state=1,new Error("improper continuation due to previous async handler, giving up parsing");const t=this._parseStack.handlers;let n=this._parseStack.handlerPos-1;switch(this._parseStack.state){case 3:if(!1===i&&n>-1)for(;n>=0&&(s=t[n](this._params),!0!==s);n--)if(s instanceof Promise)return this._parseStack.handlerPos=n,s;this._parseStack.handlers=[];break;case 4:if(!1===i&&n>-1)for(;n>=0&&(s=t[n](),!0!==s);n--)if(s instanceof Promise)return this._parseStack.handlerPos=n,s;this._parseStack.handlers=[];break;case 6:if(r=e[this._parseStack.chunkPos],s=this._dcsParser.unhook(24!==r&&26!==r,i),s)return s;27===r&&(this._parseStack.transition|=1),this._params.reset(),this._params.addParam(0),this._collect=0;break;case 5:if(r=e[this._parseStack.chunkPos],s=this._oscParser.end(24!==r&&26!==r,i),s)return s;27===r&&(this._parseStack.transition|=1),this._params.reset(),this._params.addParam(0),this._collect=0}this._parseStack.state=0,o=this._parseStack.chunkPos+1,this.precedingJoinState=0,this.currentState=15&this._parseStack.transition}for(let i=o;i>4){case 2:for(let s=i+1;;++s){if(s>=t||(r=e[s])<32||r>126&&r=t||(r=e[s])<32||r>126&&r=t||(r=e[s])<32||r>126&&r=t||(r=e[s])<32||r>126&&r=0&&(s=o[a](this._params),!0!==s);a--)if(s instanceof Promise)return this._preserveStack(3,o,a,n,i),s;a<0&&this._csiHandlerFb(this._collect<<8|r,this._params),this.precedingJoinState=0;break;case 8:do{switch(r){case 59:this._params.addParam(0);break;case 58:this._params.addSubParam(-1);break;default:this._params.addDigit(r-48)}}while(++i47&&r<60);i--;break;case 9:this._collect<<=8,this._collect|=r;break;case 10:const c=this._escHandlers[this._collect<<8|r];let l=c?c.length-1:-1;for(;l>=0&&(s=c[l](),!0!==s);l--)if(s instanceof Promise)return this._preserveStack(4,c,l,n,i),s;l<0&&this._escHandlerFb(this._collect<<8|r),this.precedingJoinState=0;break;case 11:this._params.reset(),this._params.addParam(0),this._collect=0;break;case 12:this._dcsParser.hook(this._collect<<8|r,this._params);break;case 13:for(let s=i+1;;++s)if(s>=t||24===(r=e[s])||26===r||27===r||r>127&&r=t||(r=e[s])<32||r>127&&r{Object.defineProperty(t,"__esModule",{value:!0}),t.OscHandler=t.OscParser=void 0;const s=i(5770),r=i(482),n=[];t.OscParser=class{constructor(){this._state=0,this._active=n,this._id=-1,this._handlers=Object.create(null),this._handlerFb=()=>{},this._stack={paused:!1,loopPosition:0,fallThrough:!1}}registerHandler(e,t){void 0===this._handlers[e]&&(this._handlers[e]=[]);const i=this._handlers[e];return i.push(t),{dispose:()=>{const e=i.indexOf(t);-1!==e&&i.splice(e,1)}}}clearHandler(e){this._handlers[e]&&delete this._handlers[e]}setHandlerFallback(e){this._handlerFb=e}dispose(){this._handlers=Object.create(null),this._handlerFb=()=>{},this._active=n}reset(){if(2===this._state)for(let e=this._stack.paused?this._stack.loopPosition-1:this._active.length-1;e>=0;--e)this._active[e].end(!1);this._stack.paused=!1,this._active=n,this._id=-1,this._state=0}_start(){if(this._active=this._handlers[this._id]||n,this._active.length)for(let e=this._active.length-1;e>=0;e--)this._active[e].start();else this._handlerFb(this._id,"START")}_put(e,t,i){if(this._active.length)for(let s=this._active.length-1;s>=0;s--)this._active[s].put(e,t,i);else this._handlerFb(this._id,"PUT",(0,r.utf32ToString)(e,t,i))}start(){this.reset(),this._state=1}put(e,t,i){if(3!==this._state){if(1===this._state)for(;t0&&this._put(e,t,i)}}end(e,t=!0){if(0!==this._state){if(3!==this._state)if(1===this._state&&this._start(),this._active.length){let i=!1,s=this._active.length-1,r=!1;if(this._stack.paused&&(s=this._stack.loopPosition-1,i=t,r=this._stack.fallThrough,this._stack.paused=!1),!r&&!1===i){for(;s>=0&&(i=this._active[s].end(e),!0!==i);s--)if(i instanceof Promise)return this._stack.paused=!0,this._stack.loopPosition=s,this._stack.fallThrough=!1,i;s--}for(;s>=0;s--)if(i=this._active[s].end(!1),i instanceof Promise)return this._stack.paused=!0,this._stack.loopPosition=s,this._stack.fallThrough=!0,i}else this._handlerFb(this._id,"END",e);this._active=n,this._id=-1,this._state=0}}},t.OscHandler=class{constructor(e){this._handler=e,this._data="",this._hitLimit=!1}start(){this._data="",this._hitLimit=!1}put(e,t,i){this._hitLimit||(this._data+=(0,r.utf32ToString)(e,t,i),this._data.length>s.PAYLOAD_LIMIT&&(this._data="",this._hitLimit=!0))}end(e){let t=!1;if(this._hitLimit)t=!1;else if(e&&(t=this._handler(this._data),t instanceof Promise))return t.then((e=>(this._data="",this._hitLimit=!1,e)));return this._data="",this._hitLimit=!1,t}}},8742:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.Params=void 0;const i=2147483647;class s{static fromArray(e){const t=new s;if(!e.length)return t;for(let i=Array.isArray(e[0])?1:0;i256)throw new Error("maxSubParamsLength must not be greater than 256");this.params=new Int32Array(e),this.length=0,this._subParams=new Int32Array(t),this._subParamsLength=0,this._subParamsIdx=new Uint16Array(e),this._rejectDigits=!1,this._rejectSubDigits=!1,this._digitIsSub=!1}clone(){const e=new s(this.maxLength,this.maxSubParamsLength);return e.params.set(this.params),e.length=this.length,e._subParams.set(this._subParams),e._subParamsLength=this._subParamsLength,e._subParamsIdx.set(this._subParamsIdx),e._rejectDigits=this._rejectDigits,e._rejectSubDigits=this._rejectSubDigits,e._digitIsSub=this._digitIsSub,e}toArray(){const e=[];for(let t=0;t>8,s=255&this._subParamsIdx[t];s-i>0&&e.push(Array.prototype.slice.call(this._subParams,i,s))}return e}reset(){this.length=0,this._subParamsLength=0,this._rejectDigits=!1,this._rejectSubDigits=!1,this._digitIsSub=!1}addParam(e){if(this._digitIsSub=!1,this.length>=this.maxLength)this._rejectDigits=!0;else{if(e<-1)throw new Error("values lesser than -1 are not allowed");this._subParamsIdx[this.length]=this._subParamsLength<<8|this._subParamsLength,this.params[this.length++]=e>i?i:e}}addSubParam(e){if(this._digitIsSub=!0,this.length)if(this._rejectDigits||this._subParamsLength>=this.maxSubParamsLength)this._rejectSubDigits=!0;else{if(e<-1)throw new Error("values lesser than -1 are not allowed");this._subParams[this._subParamsLength++]=e>i?i:e,this._subParamsIdx[this.length-1]++}}hasSubParams(e){return(255&this._subParamsIdx[e])-(this._subParamsIdx[e]>>8)>0}getSubParams(e){const t=this._subParamsIdx[e]>>8,i=255&this._subParamsIdx[e];return i-t>0?this._subParams.subarray(t,i):null}getSubParamsAll(){const e={};for(let t=0;t>8,s=255&this._subParamsIdx[t];s-i>0&&(e[t]=this._subParams.slice(i,s))}return e}addDigit(e){let t;if(this._rejectDigits||!(t=this._digitIsSub?this._subParamsLength:this.length)||this._digitIsSub&&this._rejectSubDigits)return;const s=this._digitIsSub?this._subParams:this.params,r=s[t-1];s[t-1]=~r?Math.min(10*r+e,i):e}}t.Params=s},5741:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.AddonManager=void 0,t.AddonManager=class{constructor(){this._addons=[]}dispose(){for(let e=this._addons.length-1;e>=0;e--)this._addons[e].instance.dispose()}loadAddon(e,t){const i={instance:t,dispose:t.dispose,isDisposed:!1};this._addons.push(i),t.dispose=()=>this._wrappedAddonDispose(i),t.activate(e)}_wrappedAddonDispose(e){if(e.isDisposed)return;let t=-1;for(let i=0;i{Object.defineProperty(t,"__esModule",{value:!0}),t.BufferApiView=void 0;const s=i(3785),r=i(511);t.BufferApiView=class{constructor(e,t){this._buffer=e,this.type=t}init(e){return this._buffer=e,this}get cursorY(){return this._buffer.y}get cursorX(){return this._buffer.x}get viewportY(){return this._buffer.ydisp}get baseY(){return this._buffer.ybase}get length(){return this._buffer.lines.length}getLine(e){const t=this._buffer.lines.get(e);if(t)return new s.BufferLineApiView(t)}getNullCell(){return new r.CellData}}},3785:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.BufferLineApiView=void 0;const s=i(511);t.BufferLineApiView=class{constructor(e){this._line=e}get isWrapped(){return this._line.isWrapped}get length(){return this._line.length}getCell(e,t){if(!(e<0||e>=this._line.length))return t?(this._line.loadCell(e,t),t):this._line.loadCell(e,new s.CellData)}translateToString(e,t,i){return this._line.translateToString(e,t,i)}}},8285:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.BufferNamespaceApi=void 0;const s=i(8771),r=i(8460),n=i(844);class o extends n.Disposable{constructor(e){super(),this._core=e,this._onBufferChange=this.register(new r.EventEmitter),this.onBufferChange=this._onBufferChange.event,this._normal=new s.BufferApiView(this._core.buffers.normal,"normal"),this._alternate=new s.BufferApiView(this._core.buffers.alt,"alternate"),this._core.buffers.onBufferActivate((()=>this._onBufferChange.fire(this.active)))}get active(){if(this._core.buffers.active===this._core.buffers.normal)return this.normal;if(this._core.buffers.active===this._core.buffers.alt)return this.alternate;throw new Error("Active buffer is neither normal nor alternate")}get normal(){return this._normal.init(this._core.buffers.normal)}get alternate(){return this._alternate.init(this._core.buffers.alt)}}t.BufferNamespaceApi=o},7975:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.ParserApi=void 0,t.ParserApi=class{constructor(e){this._core=e}registerCsiHandler(e,t){return this._core.registerCsiHandler(e,(e=>t(e.toArray())))}addCsiHandler(e,t){return this.registerCsiHandler(e,t)}registerDcsHandler(e,t){return this._core.registerDcsHandler(e,((e,i)=>t(e,i.toArray())))}addDcsHandler(e,t){return this.registerDcsHandler(e,t)}registerEscHandler(e,t){return this._core.registerEscHandler(e,t)}addEscHandler(e,t){return this.registerEscHandler(e,t)}registerOscHandler(e,t){return this._core.registerOscHandler(e,t)}addOscHandler(e,t){return this.registerOscHandler(e,t)}}},7090:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.UnicodeApi=void 0,t.UnicodeApi=class{constructor(e){this._core=e}register(e){this._core.unicodeService.register(e)}get versions(){return this._core.unicodeService.versions}get activeVersion(){return this._core.unicodeService.activeVersion}set activeVersion(e){this._core.unicodeService.activeVersion=e}}},744:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.BufferService=t.MINIMUM_ROWS=t.MINIMUM_COLS=void 0;const n=i(8460),o=i(844),a=i(5295),h=i(2585);t.MINIMUM_COLS=2,t.MINIMUM_ROWS=1;let c=t.BufferService=class extends o.Disposable{get buffer(){return this.buffers.active}constructor(e){super(),this.isUserScrolling=!1,this._onResize=this.register(new n.EventEmitter),this.onResize=this._onResize.event,this._onScroll=this.register(new n.EventEmitter),this.onScroll=this._onScroll.event,this.cols=Math.max(e.rawOptions.cols||0,t.MINIMUM_COLS),this.rows=Math.max(e.rawOptions.rows||0,t.MINIMUM_ROWS),this.buffers=this.register(new a.BufferSet(e,this))}resize(e,t){this.cols=e,this.rows=t,this.buffers.resize(e,t),this._onResize.fire({cols:e,rows:t})}reset(){this.buffers.reset(),this.isUserScrolling=!1}scroll(e,t=!1){const i=this.buffer;let s;s=this._cachedBlankLine,s&&s.length===this.cols&&s.getFg(0)===e.fg&&s.getBg(0)===e.bg||(s=i.getBlankLine(e,t),this._cachedBlankLine=s),s.isWrapped=t;const r=i.ybase+i.scrollTop,n=i.ybase+i.scrollBottom;if(0===i.scrollTop){const e=i.lines.isFull;n===i.lines.length-1?e?i.lines.recycle().copyFrom(s):i.lines.push(s.clone()):i.lines.splice(n+1,0,s.clone()),e?this.isUserScrolling&&(i.ydisp=Math.max(i.ydisp-1,0)):(i.ybase++,this.isUserScrolling||i.ydisp++)}else{const e=n-r+1;i.lines.shiftElements(r+1,e-1,-1),i.lines.set(n,s.clone())}this.isUserScrolling||(i.ydisp=i.ybase),this._onScroll.fire(i.ydisp)}scrollLines(e,t,i){const s=this.buffer;if(e<0){if(0===s.ydisp)return;this.isUserScrolling=!0}else e+s.ydisp>=s.ybase&&(this.isUserScrolling=!1);const r=s.ydisp;s.ydisp=Math.max(Math.min(s.ydisp+e,s.ybase),0),r!==s.ydisp&&(t||this._onScroll.fire(s.ydisp))}};t.BufferService=c=s([r(0,h.IOptionsService)],c)},7994:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.CharsetService=void 0,t.CharsetService=class{constructor(){this.glevel=0,this._charsets=[]}reset(){this.charset=void 0,this._charsets=[],this.glevel=0}setgLevel(e){this.glevel=e,this.charset=this._charsets[e]}setgCharset(e,t){this._charsets[e]=t,this.glevel===e&&(this.charset=t)}}},1753:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.CoreMouseService=void 0;const n=i(2585),o=i(8460),a=i(844),h={NONE:{events:0,restrict:()=>!1},X10:{events:1,restrict:e=>4!==e.button&&1===e.action&&(e.ctrl=!1,e.alt=!1,e.shift=!1,!0)},VT200:{events:19,restrict:e=>32!==e.action},DRAG:{events:23,restrict:e=>32!==e.action||3!==e.button},ANY:{events:31,restrict:e=>!0}};function c(e,t){let i=(e.ctrl?16:0)|(e.shift?4:0)|(e.alt?8:0);return 4===e.button?(i|=64,i|=e.action):(i|=3&e.button,4&e.button&&(i|=64),8&e.button&&(i|=128),32===e.action?i|=32:0!==e.action||t||(i|=3)),i}const l=String.fromCharCode,d={DEFAULT:e=>{const t=[c(e,!1)+32,e.col+32,e.row+32];return t[0]>255||t[1]>255||t[2]>255?"":`${l(t[0])}${l(t[1])}${l(t[2])}`},SGR:e=>{const t=0===e.action&&4!==e.button?"m":"M";return`[<${c(e,!0)};${e.col};${e.row}${t}`},SGR_PIXELS:e=>{const t=0===e.action&&4!==e.button?"m":"M";return`[<${c(e,!0)};${e.x};${e.y}${t}`}};let _=t.CoreMouseService=class extends a.Disposable{constructor(e,t){super(),this._bufferService=e,this._coreService=t,this._protocols={},this._encodings={},this._activeProtocol="",this._activeEncoding="",this._lastEvent=null,this._onProtocolChange=this.register(new o.EventEmitter),this.onProtocolChange=this._onProtocolChange.event;for(const e of Object.keys(h))this.addProtocol(e,h[e]);for(const e of Object.keys(d))this.addEncoding(e,d[e]);this.reset()}addProtocol(e,t){this._protocols[e]=t}addEncoding(e,t){this._encodings[e]=t}get activeProtocol(){return this._activeProtocol}get areMouseEventsActive(){return 0!==this._protocols[this._activeProtocol].events}set activeProtocol(e){if(!this._protocols[e])throw new Error(`unknown protocol "${e}"`);this._activeProtocol=e,this._onProtocolChange.fire(this._protocols[e].events)}get activeEncoding(){return this._activeEncoding}set activeEncoding(e){if(!this._encodings[e])throw new Error(`unknown encoding "${e}"`);this._activeEncoding=e}reset(){this.activeProtocol="NONE",this.activeEncoding="DEFAULT",this._lastEvent=null}triggerMouseEvent(e){if(e.col<0||e.col>=this._bufferService.cols||e.row<0||e.row>=this._bufferService.rows)return!1;if(4===e.button&&32===e.action)return!1;if(3===e.button&&32!==e.action)return!1;if(4!==e.button&&(2===e.action||3===e.action))return!1;if(e.col++,e.row++,32===e.action&&this._lastEvent&&this._equalEvents(this._lastEvent,e,"SGR_PIXELS"===this._activeEncoding))return!1;if(!this._protocols[this._activeProtocol].restrict(e))return!1;const t=this._encodings[this._activeEncoding](e);return t&&("DEFAULT"===this._activeEncoding?this._coreService.triggerBinaryEvent(t):this._coreService.triggerDataEvent(t,!0)),this._lastEvent=e,!0}explainEvents(e){return{down:!!(1&e),up:!!(2&e),drag:!!(4&e),move:!!(8&e),wheel:!!(16&e)}}_equalEvents(e,t,i){if(i){if(e.x!==t.x)return!1;if(e.y!==t.y)return!1}else{if(e.col!==t.col)return!1;if(e.row!==t.row)return!1}return e.button===t.button&&e.action===t.action&&e.ctrl===t.ctrl&&e.alt===t.alt&&e.shift===t.shift}};t.CoreMouseService=_=s([r(0,n.IBufferService),r(1,n.ICoreService)],_)},6975:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.CoreService=void 0;const n=i(1439),o=i(8460),a=i(844),h=i(2585),c=Object.freeze({insertMode:!1}),l=Object.freeze({applicationCursorKeys:!1,applicationKeypad:!1,bracketedPasteMode:!1,origin:!1,reverseWraparound:!1,sendFocus:!1,wraparound:!0});let d=t.CoreService=class extends a.Disposable{constructor(e,t,i){super(),this._bufferService=e,this._logService=t,this._optionsService=i,this.isCursorInitialized=!1,this.isCursorHidden=!1,this._onData=this.register(new o.EventEmitter),this.onData=this._onData.event,this._onUserInput=this.register(new o.EventEmitter),this.onUserInput=this._onUserInput.event,this._onBinary=this.register(new o.EventEmitter),this.onBinary=this._onBinary.event,this._onRequestScrollToBottom=this.register(new o.EventEmitter),this.onRequestScrollToBottom=this._onRequestScrollToBottom.event,this.modes=(0,n.clone)(c),this.decPrivateModes=(0,n.clone)(l)}reset(){this.modes=(0,n.clone)(c),this.decPrivateModes=(0,n.clone)(l)}triggerDataEvent(e,t=!1){if(this._optionsService.rawOptions.disableStdin)return;const i=this._bufferService.buffer;t&&this._optionsService.rawOptions.scrollOnUserInput&&i.ybase!==i.ydisp&&this._onRequestScrollToBottom.fire(),t&&this._onUserInput.fire(),this._logService.debug(`sending data "${e}"`,(()=>e.split("").map((e=>e.charCodeAt(0))))),this._onData.fire(e)}triggerBinaryEvent(e){this._optionsService.rawOptions.disableStdin||(this._logService.debug(`sending binary "${e}"`,(()=>e.split("").map((e=>e.charCodeAt(0))))),this._onBinary.fire(e))}};t.CoreService=d=s([r(0,h.IBufferService),r(1,h.ILogService),r(2,h.IOptionsService)],d)},9074:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.DecorationService=void 0;const s=i(8055),r=i(8460),n=i(844),o=i(6106);let a=0,h=0;class c extends n.Disposable{get decorations(){return this._decorations.values()}constructor(){super(),this._decorations=new o.SortedList((e=>e?.marker.line)),this._onDecorationRegistered=this.register(new r.EventEmitter),this.onDecorationRegistered=this._onDecorationRegistered.event,this._onDecorationRemoved=this.register(new r.EventEmitter),this.onDecorationRemoved=this._onDecorationRemoved.event,this.register((0,n.toDisposable)((()=>this.reset())))}registerDecoration(e){if(e.marker.isDisposed)return;const t=new l(e);if(t){const e=t.marker.onDispose((()=>t.dispose()));t.onDispose((()=>{t&&(this._decorations.delete(t)&&this._onDecorationRemoved.fire(t),e.dispose())})),this._decorations.insert(t),this._onDecorationRegistered.fire(t)}return t}reset(){for(const e of this._decorations.values())e.dispose();this._decorations.clear()}*getDecorationsAtCell(e,t,i){let s=0,r=0;for(const n of this._decorations.getKeyIterator(t))s=n.options.x??0,r=s+(n.options.width??1),e>=s&&e{a=t.options.x??0,h=a+(t.options.width??1),e>=a&&e{Object.defineProperty(t,"__esModule",{value:!0}),t.InstantiationService=t.ServiceCollection=void 0;const s=i(2585),r=i(8343);class n{constructor(...e){this._entries=new Map;for(const[t,i]of e)this.set(t,i)}set(e,t){const i=this._entries.get(e);return this._entries.set(e,t),i}forEach(e){for(const[t,i]of this._entries.entries())e(t,i)}has(e){return this._entries.has(e)}get(e){return this._entries.get(e)}}t.ServiceCollection=n,t.InstantiationService=class{constructor(){this._services=new n,this._services.set(s.IInstantiationService,this)}setService(e,t){this._services.set(e,t)}getService(e){return this._services.get(e)}createInstance(e,...t){const i=(0,r.getServiceDependencies)(e).sort(((e,t)=>e.index-t.index)),s=[];for(const t of i){const i=this._services.get(t.id);if(!i)throw new Error(`[createInstance] ${e.name} depends on UNKNOWN service ${t.id}.`);s.push(i)}const n=i.length>0?i[0].index:t.length;if(t.length!==n)throw new Error(`[createInstance] First service dependency of ${e.name} at position ${n+1} conflicts with ${t.length} static arguments`);return new e(...[...t,...s])}}},7866:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.traceCall=t.setTraceLogger=t.LogService=void 0;const n=i(844),o=i(2585),a={trace:o.LogLevelEnum.TRACE,debug:o.LogLevelEnum.DEBUG,info:o.LogLevelEnum.INFO,warn:o.LogLevelEnum.WARN,error:o.LogLevelEnum.ERROR,off:o.LogLevelEnum.OFF};let h,c=t.LogService=class extends n.Disposable{get logLevel(){return this._logLevel}constructor(e){super(),this._optionsService=e,this._logLevel=o.LogLevelEnum.OFF,this._updateLogLevel(),this.register(this._optionsService.onSpecificOptionChange("logLevel",(()=>this._updateLogLevel()))),h=this}_updateLogLevel(){this._logLevel=a[this._optionsService.rawOptions.logLevel]}_evalLazyOptionalParams(e){for(let t=0;tJSON.stringify(e))).join(", ")})`);const t=s.apply(this,e);return h.trace(`GlyphRenderer#${s.name} return`,t),t}}},7302:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.OptionsService=t.DEFAULT_OPTIONS=void 0;const s=i(8460),r=i(844),n=i(6114);t.DEFAULT_OPTIONS={cols:80,rows:24,cursorBlink:!1,cursorStyle:"block",cursorWidth:1,cursorInactiveStyle:"outline",customGlyphs:!0,drawBoldTextInBrightColors:!0,documentOverride:null,fastScrollModifier:"alt",fastScrollSensitivity:5,fontFamily:"courier-new, courier, monospace",fontSize:15,fontWeight:"normal",fontWeightBold:"bold",ignoreBracketedPasteMode:!1,lineHeight:1,letterSpacing:0,linkHandler:null,logLevel:"info",logger:null,scrollback:1e3,scrollOnUserInput:!0,scrollSensitivity:1,screenReaderMode:!1,smoothScrollDuration:0,macOptionIsMeta:!1,macOptionClickForcesSelection:!1,minimumContrastRatio:1,disableStdin:!1,allowProposedApi:!1,allowTransparency:!1,tabStopWidth:8,theme:{},rescaleOverlappingGlyphs:!1,rightClickSelectsWord:n.isMac,windowOptions:{},windowsMode:!1,windowsPty:{},wordSeparator:" ()[]{}',\"`",altClickMovesCursor:!0,convertEol:!1,termName:"xterm",cancelEvents:!1,overviewRulerWidth:0};const o=["normal","bold","100","200","300","400","500","600","700","800","900"];class a extends r.Disposable{constructor(e){super(),this._onOptionChange=this.register(new s.EventEmitter),this.onOptionChange=this._onOptionChange.event;const i={...t.DEFAULT_OPTIONS};for(const t in e)if(t in i)try{const s=e[t];i[t]=this._sanitizeAndValidateOption(t,s)}catch(e){console.error(e)}this.rawOptions=i,this.options={...i},this._setupOptions(),this.register((0,r.toDisposable)((()=>{this.rawOptions.linkHandler=null,this.rawOptions.documentOverride=null})))}onSpecificOptionChange(e,t){return this.onOptionChange((i=>{i===e&&t(this.rawOptions[e])}))}onMultipleOptionChange(e,t){return this.onOptionChange((i=>{-1!==e.indexOf(i)&&t()}))}_setupOptions(){const e=e=>{if(!(e in t.DEFAULT_OPTIONS))throw new Error(`No option with key "${e}"`);return this.rawOptions[e]},i=(e,i)=>{if(!(e in t.DEFAULT_OPTIONS))throw new Error(`No option with key "${e}"`);i=this._sanitizeAndValidateOption(e,i),this.rawOptions[e]!==i&&(this.rawOptions[e]=i,this._onOptionChange.fire(e))};for(const t in this.rawOptions){const s={get:e.bind(this,t),set:i.bind(this,t)};Object.defineProperty(this.options,t,s)}}_sanitizeAndValidateOption(e,i){switch(e){case"cursorStyle":if(i||(i=t.DEFAULT_OPTIONS[e]),!function(e){return"block"===e||"underline"===e||"bar"===e}(i))throw new Error(`"${i}" is not a valid value for ${e}`);break;case"wordSeparator":i||(i=t.DEFAULT_OPTIONS[e]);break;case"fontWeight":case"fontWeightBold":if("number"==typeof i&&1<=i&&i<=1e3)break;i=o.includes(i)?i:t.DEFAULT_OPTIONS[e];break;case"cursorWidth":i=Math.floor(i);case"lineHeight":case"tabStopWidth":if(i<1)throw new Error(`${e} cannot be less than 1, value: ${i}`);break;case"minimumContrastRatio":i=Math.max(1,Math.min(21,Math.round(10*i)/10));break;case"scrollback":if((i=Math.min(i,4294967295))<0)throw new Error(`${e} cannot be less than 0, value: ${i}`);break;case"fastScrollSensitivity":case"scrollSensitivity":if(i<=0)throw new Error(`${e} cannot be less than or equal to 0, value: ${i}`);break;case"rows":case"cols":if(!i&&0!==i)throw new Error(`${e} must be numeric, value: ${i}`);break;case"windowsPty":i=i??{}}return i}}t.OptionsService=a},2660:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.OscLinkService=void 0;const n=i(2585);let o=t.OscLinkService=class{constructor(e){this._bufferService=e,this._nextId=1,this._entriesWithId=new Map,this._dataByLinkId=new Map}registerLink(e){const t=this._bufferService.buffer;if(void 0===e.id){const i=t.addMarker(t.ybase+t.y),s={data:e,id:this._nextId++,lines:[i]};return i.onDispose((()=>this._removeMarkerFromLink(s,i))),this._dataByLinkId.set(s.id,s),s.id}const i=e,s=this._getEntryIdKey(i),r=this._entriesWithId.get(s);if(r)return this.addLineToLink(r.id,t.ybase+t.y),r.id;const n=t.addMarker(t.ybase+t.y),o={id:this._nextId++,key:this._getEntryIdKey(i),data:i,lines:[n]};return n.onDispose((()=>this._removeMarkerFromLink(o,n))),this._entriesWithId.set(o.key,o),this._dataByLinkId.set(o.id,o),o.id}addLineToLink(e,t){const i=this._dataByLinkId.get(e);if(i&&i.lines.every((e=>e.line!==t))){const e=this._bufferService.buffer.addMarker(t);i.lines.push(e),e.onDispose((()=>this._removeMarkerFromLink(i,e)))}}getLinkData(e){return this._dataByLinkId.get(e)?.data}_getEntryIdKey(e){return`${e.id};;${e.uri}`}_removeMarkerFromLink(e,t){const i=e.lines.indexOf(t);-1!==i&&(e.lines.splice(i,1),0===e.lines.length&&(void 0!==e.data.id&&this._entriesWithId.delete(e.key),this._dataByLinkId.delete(e.id)))}};t.OscLinkService=o=s([r(0,n.IBufferService)],o)},8343:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.createDecorator=t.getServiceDependencies=t.serviceRegistry=void 0;const i="di$target",s="di$dependencies";t.serviceRegistry=new Map,t.getServiceDependencies=function(e){return e[s]||[]},t.createDecorator=function(e){if(t.serviceRegistry.has(e))return t.serviceRegistry.get(e);const r=function(e,t,n){if(3!==arguments.length)throw new Error("@IServiceName-decorator can only be used to decorate a parameter");!function(e,t,r){t[i]===t?t[s].push({id:e,index:r}):(t[s]=[{id:e,index:r}],t[i]=t)}(r,e,n)};return r.toString=()=>e,t.serviceRegistry.set(e,r),r}},2585:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.IDecorationService=t.IUnicodeService=t.IOscLinkService=t.IOptionsService=t.ILogService=t.LogLevelEnum=t.IInstantiationService=t.ICharsetService=t.ICoreService=t.ICoreMouseService=t.IBufferService=void 0;const s=i(8343);var r;t.IBufferService=(0,s.createDecorator)("BufferService"),t.ICoreMouseService=(0,s.createDecorator)("CoreMouseService"),t.ICoreService=(0,s.createDecorator)("CoreService"),t.ICharsetService=(0,s.createDecorator)("CharsetService"),t.IInstantiationService=(0,s.createDecorator)("InstantiationService"),function(e){e[e.TRACE=0]="TRACE",e[e.DEBUG=1]="DEBUG",e[e.INFO=2]="INFO",e[e.WARN=3]="WARN",e[e.ERROR=4]="ERROR",e[e.OFF=5]="OFF"}(r||(t.LogLevelEnum=r={})),t.ILogService=(0,s.createDecorator)("LogService"),t.IOptionsService=(0,s.createDecorator)("OptionsService"),t.IOscLinkService=(0,s.createDecorator)("OscLinkService"),t.IUnicodeService=(0,s.createDecorator)("UnicodeService"),t.IDecorationService=(0,s.createDecorator)("DecorationService")},1480:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.UnicodeService=void 0;const s=i(8460),r=i(225);class n{static extractShouldJoin(e){return 0!=(1&e)}static extractWidth(e){return e>>1&3}static extractCharKind(e){return e>>3}static createPropertyValue(e,t,i=!1){return(16777215&e)<<3|(3&t)<<1|(i?1:0)}constructor(){this._providers=Object.create(null),this._active="",this._onChange=new s.EventEmitter,this.onChange=this._onChange.event;const e=new r.UnicodeV6;this.register(e),this._active=e.version,this._activeProvider=e}dispose(){this._onChange.dispose()}get versions(){return Object.keys(this._providers)}get activeVersion(){return this._active}set activeVersion(e){if(!this._providers[e])throw new Error(`unknown Unicode version "${e}"`);this._active=e,this._activeProvider=this._providers[e],this._onChange.fire(e)}register(e){this._providers[e.version]=e}wcwidth(e){return this._activeProvider.wcwidth(e)}getStringCellWidth(e){let t=0,i=0;const s=e.length;for(let r=0;r=s)return t+this.wcwidth(o);const i=e.charCodeAt(r);56320<=i&&i<=57343?o=1024*(o-55296)+i-56320+65536:t+=this.wcwidth(i)}const a=this.charProperties(o,i);let h=n.extractWidth(a);n.extractShouldJoin(a)&&(h-=n.extractWidth(i)),t+=h,i=a}return t}charProperties(e,t){return this._activeProvider.charProperties(e,t)}}t.UnicodeService=n}},t={};function i(s){var r=t[s];if(void 0!==r)return r.exports;var n=t[s]={exports:{}};return e[s].call(n.exports,n,n.exports,i),n.exports}var s={};return(()=>{var e=s;Object.defineProperty(e,"__esModule",{value:!0}),e.Terminal=void 0;const t=i(9042),r=i(3236),n=i(844),o=i(5741),a=i(8285),h=i(7975),c=i(7090),l=["cols","rows"];class d extends n.Disposable{constructor(e){super(),this._core=this.register(new r.Terminal(e)),this._addonManager=this.register(new o.AddonManager),this._publicOptions={...this._core.options};const t=e=>this._core.options[e],i=(e,t)=>{this._checkReadonlyOptions(e),this._core.options[e]=t};for(const e in this._core.options){const s={get:t.bind(this,e),set:i.bind(this,e)};Object.defineProperty(this._publicOptions,e,s)}}_checkReadonlyOptions(e){if(l.includes(e))throw new Error(`Option "${e}" can only be set in the constructor`)}_checkProposedApi(){if(!this._core.optionsService.rawOptions.allowProposedApi)throw new Error("You must set the allowProposedApi option to true to use proposed API")}get onBell(){return this._core.onBell}get onBinary(){return this._core.onBinary}get onCursorMove(){return this._core.onCursorMove}get onData(){return this._core.onData}get onKey(){return this._core.onKey}get onLineFeed(){return this._core.onLineFeed}get onRender(){return this._core.onRender}get onResize(){return this._core.onResize}get onScroll(){return this._core.onScroll}get onSelectionChange(){return this._core.onSelectionChange}get onTitleChange(){return this._core.onTitleChange}get onWriteParsed(){return this._core.onWriteParsed}get element(){return this._core.element}get parser(){return this._parser||(this._parser=new h.ParserApi(this._core)),this._parser}get unicode(){return this._checkProposedApi(),new c.UnicodeApi(this._core)}get textarea(){return this._core.textarea}get rows(){return this._core.rows}get cols(){return this._core.cols}get buffer(){return this._buffer||(this._buffer=this.register(new a.BufferNamespaceApi(this._core))),this._buffer}get markers(){return this._checkProposedApi(),this._core.markers}get modes(){const e=this._core.coreService.decPrivateModes;let t="none";switch(this._core.coreMouseService.activeProtocol){case"X10":t="x10";break;case"VT200":t="vt200";break;case"DRAG":t="drag";break;case"ANY":t="any"}return{applicationCursorKeysMode:e.applicationCursorKeys,applicationKeypadMode:e.applicationKeypad,bracketedPasteMode:e.bracketedPasteMode,insertMode:this._core.coreService.modes.insertMode,mouseTrackingMode:t,originMode:e.origin,reverseWraparoundMode:e.reverseWraparound,sendFocusMode:e.sendFocus,wraparoundMode:e.wraparound}}get options(){return this._publicOptions}set options(e){for(const t in e)this._publicOptions[t]=e[t]}blur(){this._core.blur()}focus(){this._core.focus()}input(e,t=!0){this._core.input(e,t)}resize(e,t){this._verifyIntegers(e,t),this._core.resize(e,t)}open(e){this._core.open(e)}attachCustomKeyEventHandler(e){this._core.attachCustomKeyEventHandler(e)}attachCustomWheelEventHandler(e){this._core.attachCustomWheelEventHandler(e)}registerLinkProvider(e){return this._core.registerLinkProvider(e)}registerCharacterJoiner(e){return this._checkProposedApi(),this._core.registerCharacterJoiner(e)}deregisterCharacterJoiner(e){this._checkProposedApi(),this._core.deregisterCharacterJoiner(e)}registerMarker(e=0){return this._verifyIntegers(e),this._core.registerMarker(e)}registerDecoration(e){return this._checkProposedApi(),this._verifyPositiveIntegers(e.x??0,e.width??0,e.height??0),this._core.registerDecoration(e)}hasSelection(){return this._core.hasSelection()}select(e,t,i){this._verifyIntegers(e,t,i),this._core.select(e,t,i)}getSelection(){return this._core.getSelection()}getSelectionPosition(){return this._core.getSelectionPosition()}clearSelection(){this._core.clearSelection()}selectAll(){this._core.selectAll()}selectLines(e,t){this._verifyIntegers(e,t),this._core.selectLines(e,t)}dispose(){super.dispose()}scrollLines(e){this._verifyIntegers(e),this._core.scrollLines(e)}scrollPages(e){this._verifyIntegers(e),this._core.scrollPages(e)}scrollToTop(){this._core.scrollToTop()}scrollToBottom(){this._core.scrollToBottom()}scrollToLine(e){this._verifyIntegers(e),this._core.scrollToLine(e)}clear(){this._core.clear()}write(e,t){this._core.write(e,t)}writeln(e,t){this._core.write(e),this._core.write("\r\n",t)}paste(e){this._core.paste(e)}refresh(e,t){this._verifyIntegers(e,t),this._core.refresh(e,t)}reset(){this._core.reset()}clearTextureAtlas(){this._core.clearTextureAtlas()}loadAddon(e){this._addonManager.loadAddon(this,e)}static get strings(){return t}_verifyIntegers(...e){for(const t of e)if(t===1/0||isNaN(t)||t%1!=0)throw new Error("This API only accepts integers")}_verifyPositiveIntegers(...e){for(const t of e)if(t&&(t===1/0||isNaN(t)||t%1!=0||t<0))throw new Error("This API only accepts positive integers")}}e.Terminal=d})(),s})())); +//# sourceMappingURL=xterm.js.map \ No newline at end of file diff --git a/utils/dasHerd/watcher/watcher_core.das b/utils/dasHerd/watcher/watcher_core.das new file mode 100644 index 0000000000..60f387e7ae --- /dev/null +++ b/utils/dasHerd/watcher/watcher_core.das @@ -0,0 +1,485 @@ +options gen2 +options rtti +options persistent_heap +options gc +options indenting = 4 + +module watcher_core shared public + +require terminal/terminal public +require daslib/fio public +require daslib/json_boost public +require strings public +require math + +let private DEFAULT_DRAIN_QUIET_MS = 250l +let private MAX_COMMAND_BYTES = 32 * 1024 +let private MAX_INPUT_BYTES = 1024 * 1024 +let private MAX_RAW_HISTORY_BYTES = 8 * 1024 * 1024 +let private RAW_HISTORY_TRIM_SLACK = 1024 * 1024 + +struct public WatcherLaunchRequest { + command_line : string + cwd : string + columns : int = 100 + rows : int = 30 + timeout_ms : int64 +} + +struct public WatcherInputRequest { + session_id : string + text : string +} + +struct public WatcherResizeRequest { + session_id : string + columns : int + rows : int +} + +struct public WatcherSessionRequest { + session_id : string +} + +struct public WatcherEvent { + session_id : string + event : string + elapsed_ms : int64 + detail : string +} + +struct public WatcherSessionInfo { + id : string + command_line : string + cwd : string + state : string + reason : string + pid : int + exit_code : int64 = -1l + elapsed_ms : int64 + output_bytes : int64 + input_bytes : int64 + columns : int + rows : int + revision : int64 + status_revision : int64 + controller_id : int + drained : bool +} + +struct public WatcherSessionSnapshot { + session : WatcherSessionInfo = WatcherSessionInfo() + screen_text : string + title : string + current_directory : string + scrollback_rows : int + cursor_row : int + cursor_column : int + cursor_visible : bool + cursor_blinking : bool +} + +struct public WatcherLaunchResult { + ok : bool + session_id : string + error : string +} + +struct public WatcherOutputChunk { + bytes : array + next_offset : int64 + reset : bool +} + +class private WatcherSession { + id : string + command_line : string + cwd : string + session_dir : string + output_path : string + events_path : string + state : string = "starting" + reason : string + terminal : Terminal = Terminal() + output_file : FILE const? = null + events_file : FILE const? = null + started : int64 + timeout_ms : int64 + last_data_ms : int64 + exit_seen_ms : int64 = -1l + exit_code : int64 = -1l + output_bytes : int64 + input_bytes : int64 + raw_history : array + raw_history_start : int64 + status_revision : int64 + controller_id : int + drained : bool + def operator delete { + if (output_file != null) { + fflush(output_file) + fclose(output_file) + output_file = null + } + if (events_file != null) { + fflush(events_file) + fclose(events_file) + events_file = null + } + terminal_dispose(terminal) + } +} + +def private retain_raw_output(var session : WatcherSession?; bytes : array const) { + if (empty(bytes)) return + let old_length = length(session.raw_history) + session.raw_history |> resize(old_length + length(bytes)) + unsafe { + memcpy(addr(session.raw_history[old_length]), addr(bytes[0]), length(bytes)) + } + if (length(session.raw_history) > MAX_RAW_HISTORY_BYTES + RAW_HISTORY_TRIM_SLACK) { + let discard = length(session.raw_history) - MAX_RAW_HISTORY_BYTES + session.raw_history |> erase(0, discard) + session.raw_history_start += int64(discard) + } +} + +var private g_sessions : array +var private g_log_root : string +var private g_next_session_id = 0 + +def private elapsed_ms(session : WatcherSession?) : int64 { + return get_time_nsec(session.started) / 1000000l +} + +def private write_text_file(path, body : string) : bool { + var file = fopen(path, "wb") + if (file == null) return false + fwrite(file, body) + fflush(file) + fclose(file) + return true +} + +def private append_event(session : WatcherSession?; event, detail : string) { + if (session.events_file == null) return + let line = sprint_json(WatcherEvent(session_id = session.id, event = event, + elapsed_ms = elapsed_ms(session), detail = detail), false) + "\n" + fwrite(session.events_file, line) + fflush(session.events_file) +} + +def private session_info(session : WatcherSession?) : WatcherSessionInfo { + return WatcherSessionInfo(id = session.id, command_line = session.command_line, + cwd = session.cwd, state = session.state, reason = session.reason, + pid = terminal_process_id(session.terminal), exit_code = session.exit_code, + elapsed_ms = elapsed_ms(session), output_bytes = session.output_bytes, + input_bytes = session.input_bytes, + columns = session.terminal.columns, rows = session.terminal.rows, + revision = terminal_revision(session.terminal), status_revision = session.status_revision, + controller_id = session.controller_id, + drained = session.drained) +} + +def public watcher_init(log_root : string) : string { + g_log_root = log_root + var error : string + if (!mkdir_rec(g_log_root, error)) return error + return "" +} + +def public watcher_find_session(session_id : string) : int { + for (index in range(length(g_sessions))) { + if (g_sessions[index] != null && g_sessions[index].id == session_id) return index + } + return -1 +} + +def public watcher_accepts_input(session_id : string) : bool { + let index = watcher_find_session(session_id) + return (index >= 0 && g_sessions[index] != null && + g_sessions[index].state == "running" && !g_sessions[index].drained) +} + +def public watcher_launch(request : WatcherLaunchRequest) : WatcherLaunchResult { + if (empty(request.command_line)) { + return WatcherLaunchResult(error = "command_line is required") + } + if (length(request.command_line) > MAX_COMMAND_BYTES) { + return WatcherLaunchResult(error = "command_line is too large") + } + if (empty(g_log_root)) { + return WatcherLaunchResult(error = "watcher core is not initialized") + } + g_next_session_id++ + let session_id = "s{ref_time_ticks()}_{g_next_session_id}" + let session_dir = path_join(g_log_root, session_id) + var mkdir_error : string + if (!mkdir_rec(session_dir, mkdir_error)) { + return WatcherLaunchResult(error = "could not create session directory: {mkdir_error}") + } + + var session = new WatcherSession(id = session_id, + command_line = request.command_line, cwd = request.cwd, + session_dir = session_dir, + output_path = path_join(session_dir, "output.raw"), + events_path = path_join(session_dir, "events.jsonl"), + started = ref_time_ticks(), timeout_ms = max(0l, request.timeout_ms)) + session.output_file = fopen(session.output_path, "wb") + session.events_file = fopen(session.events_path, "wb") + if (session.output_file == null || session.events_file == null) { + unsafe { delete session } + return WatcherLaunchResult(error = "could not open session logs") + } + let spec = WatcherLaunchRequest(command_line = request.command_line, cwd = request.cwd, + columns = clamp(request.columns, 20, 400), rows = clamp(request.rows, 5, 200), + timeout_ms = max(0l, request.timeout_ms)) + if (!write_text_file(path_join(session_dir, "session.json"), sprint_json(spec, true))) { + unsafe { delete session } + return WatcherLaunchResult(error = "could not write session metadata") + } + + var inscope launched <- terminal_launch(spec.command_line, spec.cwd, spec.columns, spec.rows) + session.terminal := launched + if (terminal_process_id(session.terminal) == 0) { + session.state = "failed" + session.reason = terminal_transport_error(session.terminal) + if (empty(session.reason)) { session.reason = "terminal launch failed" } + session.drained = true + session.status_revision++ + append_event(session, "launch_failed", session.reason) + } else { + session.state = "running" + session.status_revision++ + append_event(session, "launched", "pid={terminal_process_id(session.terminal)}") + } + g_sessions |> push(session) + if (session.state == "failed") { + return WatcherLaunchResult(session_id = session_id, error = session.reason) + } + return WatcherLaunchResult(ok = true, session_id = session_id) +} + +def private observe_exit(var session : WatcherSession?; now_ms : int64) { + if (session.exit_seen_ms >= 0l || !terminal_process_exited(session.terminal)) return + session.exit_seen_ms = now_ms + session.exit_code = terminal_exit_code(session.terminal) + session.state = "exited" + session.status_revision++ + if (session.last_data_ms == 0l) { + session.last_data_ms = now_ms + } + append_event(session, "process_exited", "exit_code={session.exit_code}") +} + +def private finish_drain(var session : WatcherSession?; detail : string) { + if (session.drained) return + session.drained = true + session.status_revision++ + if (session.output_file != null) { + fflush(session.output_file) + fclose(session.output_file) + session.output_file = null + } + append_event(session, "output_drained", detail) +} + +def private enforce_timeout(var session : WatcherSession?; now_ms : int64) { + if (session.state != "running" || session.timeout_ms <= 0l || now_ms < session.timeout_ms) return + session.reason = "wall_timeout" + session.state = "terminating" + session.status_revision++ + let terminated = terminal_terminate(session.terminal) + append_event(session, "wall_timeout", "terminate={terminated}") +} + +def public watcher_tick(maximum_bytes_per_session : int = 64 * 1024) { + let bounded_bytes = clamp(maximum_bytes_per_session, 1024, 1024 * 1024) + for (session in g_sessions) { + if (session == null) continue + let now_ms = elapsed_ms(session) + if (session.drained) { + // Pipe closure can race slightly ahead of the process handle. Keep + // observing lifecycle/timeout state after output is fully drained. + observe_exit(session, now_ms) + enforce_timeout(session, now_ms) + continue + } + let status = terminal_poll(session.terminal, bounded_bytes) + if (status == TerminalPollStatus.data) { + session.last_data_ms = now_ms + session.output_bytes += int64(length(session.terminal.read_buffer)) + retain_raw_output(session, session.terminal.read_buffer) + if (session.output_file != null) { + let _ = fwrite(session.output_file, session.terminal.read_buffer) + fflush(session.output_file) + } + } elif (status == TerminalPollStatus.error) { + session.state = "failed" + session.reason = terminal_transport_error(session.terminal) + session.status_revision++ + append_event(session, "transport_error", session.reason) + finish_drain(session, "transport_error") + continue + } + observe_exit(session, now_ms) + enforce_timeout(session, now_ms) + if (status == TerminalPollStatus.closed) { + finish_drain(session, "pipe_closed") + } elif (session.exit_seen_ms >= 0l && now_ms - session.last_data_ms >= DEFAULT_DRAIN_QUIET_MS) { + finish_drain(session, "quiet_interval") + } + } +} + +def public watcher_output_since(session_id : string; requested_offset : int64; + maximum_bytes : int = 256 * 1024) : WatcherOutputChunk { + var result = WatcherOutputChunk() + let index = watcher_find_session(session_id) + if (index < 0 || g_sessions[index] == null) return <- result + let session = g_sessions[index] + var offset = requested_offset + if (offset < session.raw_history_start || offset > session.output_bytes) { + offset = session.raw_history_start + result.reset = true + } + let available = session.output_bytes - offset + let count = min(int64(clamp(maximum_bytes, 1024, 1024 * 1024)), available) + if (count > 0l) { + let source = int(offset - session.raw_history_start) + result.bytes |> resize(int(count)) + unsafe { + memcpy(addr(result.bytes[0]), addr(session.raw_history[source]), int(count)) + } + } + result.next_offset = offset + count + return <- result +} + +def private input_session(var session : WatcherSession?; text : string; client_id : int) : string { + if (session.controller_id != 0 && session.controller_id != client_id) return "controller lease is held by another client" + if (session.state != "running" || session.drained) return "session is not running" + if (!terminal_write(session.terminal, text)) return terminal_transport_error(session.terminal) + session.input_bytes += int64(length(text)) + return "" +} + +def public watcher_input(session_id, text : string; client_id : int = 0) : string { + let index = watcher_find_session(session_id) + if (index < 0) return "unknown session" + if (length(text) > MAX_INPUT_BYTES) return "input is too large" + return input_session(g_sessions[index], text, client_id) +} + +def private resize_session(var session : WatcherSession?; columns, rows, client_id : int) : string { + if (session.controller_id != 0 && session.controller_id != client_id) return "controller lease is held by another client" + terminal_resize(session.terminal, clamp(columns, 20, 400), clamp(rows, 5, 200)) + append_event(session, "resized", "{session.terminal.columns}x{session.terminal.rows}") + return "" +} + +def public watcher_resize(session_id : string; columns, rows, client_id : int) : string { + let index = watcher_find_session(session_id) + if (index < 0) return "unknown session" + return resize_session(g_sessions[index], columns, rows, client_id) +} + +def private terminate_session(var session : WatcherSession?; detail : string) : string { + if (terminal_process_exited(session.terminal)) return "" + session.reason = detail + session.state = "terminating" + session.status_revision++ + if (!terminal_terminate(session.terminal)) return terminal_transport_error(session.terminal) + append_event(session, "terminate_requested", detail) + return "" +} + +def public watcher_terminate(session_id : string; detail : string = "requested") : string { + let index = watcher_find_session(session_id) + if (index < 0) return "unknown session" + return terminate_session(g_sessions[index], detail) +} + +def private claim_session(var session : WatcherSession?; client_id : int) : bool { + if (session.controller_id != 0 && session.controller_id != client_id) return false + if (session.controller_id == 0) append_event(session, "controller_claimed", "client={client_id}") + session.controller_id = client_id + session.status_revision++ + return true +} + +def public watcher_claim_controller(session_id : string; client_id : int) : bool { + let index = watcher_find_session(session_id) + if (index < 0 || client_id == 0) return false + return claim_session(g_sessions[index], client_id) +} + +def private release_session(var session : WatcherSession?; client_id : int; detail : string) { + if (session.controller_id != client_id) return + session.controller_id = 0 + session.status_revision++ + append_event(session, "controller_released", "client={client_id}; reason={detail}") +} + +def public watcher_release_controller(session_id : string; client_id : int; detail : string = "released") { + let index = watcher_find_session(session_id) + if (index < 0) return + release_session(g_sessions[index], client_id, detail) +} + +def public watcher_list_json : string { + var result : array + result |> reserve(length(g_sessions)) + for (session in g_sessions) { + if (session != null) result |> push(session_info(session)) + } + return sprint_json(result, false) +} + +def private snapshot_session_json(session : WatcherSession?) : string { + var viewport = TerminalViewportSnapshot() + terminal_viewport_snapshot(session.terminal, 0, viewport) + let cursor = viewport.buffer.cursor + let snapshot = WatcherSessionSnapshot(session = session_info(session), + screen_text = viewport.screen_text, title = session.terminal.title, + current_directory = session.terminal.current_directory, + scrollback_rows = viewport.buffer.scrollback_rows, + cursor_row = cursor.row, cursor_column = cursor.column, + cursor_visible = cursor.visible, cursor_blinking = cursor.blinking) + return sprint_json(snapshot, false) +} + +def public watcher_snapshot_json(session_id : string) : string { + let index = watcher_find_session(session_id) + if (index < 0) return "" + return snapshot_session_json(g_sessions[index]) +} + +def public watcher_update_key(session_id : string) : string { + let index = watcher_find_session(session_id) + if (index < 0 || g_sessions[index] == null) return "" + let session = g_sessions[index] + return "{terminal_revision(session.terminal)}:{session.status_revision}" +} + +def public watcher_shutdown(terminate_running : bool = false) { + for (session in g_sessions) { + if (session == null) continue + if (terminate_running && !terminal_process_exited(session.terminal)) { + let _ = terminal_terminate(session.terminal) + } + if (session.output_file != null) { + fflush(session.output_file) + fclose(session.output_file) + session.output_file = null + } + if (session.events_file != null) { + append_event(session, "watcher_shutdown", "terminate_running={terminate_running}") + fflush(session.events_file) + fclose(session.events_file) + session.events_file = null + } + unsafe { delete session } + } + g_sessions |> clear() +} diff --git a/utils/dasHerd/watcher/watcher_server.das b/utils/dasHerd/watcher/watcher_server.das new file mode 100644 index 0000000000..3f13615394 --- /dev/null +++ b/utils/dasHerd/watcher/watcher_server.das @@ -0,0 +1,422 @@ +options gen2 +options rtti +options persistent_heap +options gc +options indenting = 4 +options no_unused_function_arguments = false +options no_unused_block_arguments = false + +module watcher_server shared public + +require dashv/dashv_boost public +require ./watcher_core.das public +require daslib/json_boost +require strings + +let private MAX_REQUEST_BODY_BYTES = 1024 * 1024 +let private CONTROLLER_HEARTBEAT_TIMEOUT_MS = 5000l +var private g_watcher_gc_requested = false + +def public watcher_request_gc() : bool { + let coalesced = g_watcher_gc_requested + g_watcher_gc_requested = true + return coalesced +} + +def public watcher_take_gc_request() : bool { + let requested = g_watcher_gc_requested + g_watcher_gc_requested = false + return requested +} + +def public watcher_reset_gc_request() { + g_watcher_gc_requested = false +} + +struct private WatcherWsMessage { + op : string + session_id : string + command_line : string + cwd : string + text : string + columns : int + rows : int + timeout_ms : int64 + control : bool + raw : bool +} + +class private WatcherClient { + @safe_when_uninitialized + channel : WebSocketChannel = default + id : int + session_id : string + controls : bool + last_heartbeat : int64 + last_update_key : string + raw : bool + raw_offset : int64 +} + +struct private WatcherOk { + ok : bool = true +} + +struct private WatcherError { + ok : bool + error : string +} + +def private json_error(message : string) : string { + return sprint_json(WatcherError(error = message), false) +} + +def private hex_nibble(value : int) : int { + if (is_number(value)) return value - '0' + if (value >= 'a' && value <= 'f') return value - 'a' + 10 + if (value >= 'A' && value <= 'F') return value - 'A' + 10 + return -1 +} + +def private percent_decode(value : string) : string { + var decoded : array + decoded |> reserve(length(value)) + peek_data(value) $(data) { + var index = 0 + while (index < length(value)) { + let byte = int(data[index]) + if (byte == '%' && index + 2 < length(value)) { + let high = hex_nibble(int(data[index + 1])) + let low = hex_nibble(int(data[index + 2])) + if (high >= 0 && low >= 0) { + decoded |> push(uint8((high << 4) | low)) + index += 3 + continue + } + } + decoded |> push(uint8(byte == '+' ? ' ' : byte)) + index++ + } + } + return string(decoded) +} + +def private query_value(url, key : string) : string { + let query = find(url, "?") + if (query < 0) return "" + let wanted = key + "=" + let url_length = length(url) + var position = query + 1 + while (position < url_length) { + let amp = find(url, "&", position) + let end = amp < 0 ? url_length : amp + if (starts_with(slice(url, position, end), wanted)) { + return percent_decode(slice(url, position + length(wanted), end)) + } + if (amp < 0) break + position = amp + 1 + } + return "" +} + +class DasHerdWatcherServer : HvWebServer { + token : string + control_html : string + xterm_js : string + xterm_css : string + xterm_fit_js : string + xterm_unicode_js : string + xterm_web_links_js : string + clients : array + next_client_id : int + + def authorized(url : string) : bool { + return !empty(token) && query_value(url, "token") == token + } + + def respond_error(var resp : HttpResponse?; status : http_status; message : string) : http_status { + return resp |> JSON(json_error(message), status) + } + + def require_auth(var req : HttpRequest?; var resp : HttpResponse?) : bool { + if (req != null && authorized(string(req.url))) return true + let _ = respond_error(resp, http_status.UNAUTHORIZED, "invalid watcher token") + return false + } + + def override onInit { + GET("/") <| @(var req : HttpRequest?; var resp : HttpResponse?) : http_status { + if (!self.require_auth(req, resp)) return http_status.UNAUTHORIZED + return resp |> SERVE_FILE(self.control_html) + } + GET("/vendor/xterm.js") <| @(var req : HttpRequest?; var resp : HttpResponse?) : http_status { + if (!self.require_auth(req, resp)) return http_status.UNAUTHORIZED + return resp |> SERVE_FILE(self.xterm_js) + } + GET("/vendor/xterm.css") <| @(var req : HttpRequest?; var resp : HttpResponse?) : http_status { + if (!self.require_auth(req, resp)) return http_status.UNAUTHORIZED + return resp |> SERVE_FILE(self.xterm_css) + } + GET("/vendor/addon-fit.js") <| @(var req : HttpRequest?; var resp : HttpResponse?) : http_status { + if (!self.require_auth(req, resp)) return http_status.UNAUTHORIZED + return resp |> SERVE_FILE(self.xterm_fit_js) + } + GET("/vendor/addon-unicode11.js") <| @(var req : HttpRequest?; var resp : HttpResponse?) : http_status { + if (!self.require_auth(req, resp)) return http_status.UNAUTHORIZED + return resp |> SERVE_FILE(self.xterm_unicode_js) + } + GET("/vendor/addon-web-links.js") <| @(var req : HttpRequest?; var resp : HttpResponse?) : http_status { + if (!self.require_auth(req, resp)) return http_status.UNAUTHORIZED + return resp |> SERVE_FILE(self.xterm_web_links_js) + } + GET("/api/v1/health") <| @(var req : HttpRequest?; var resp : HttpResponse?) : http_status { + if (!self.require_auth(req, resp)) return http_status.UNAUTHORIZED + return resp |> JSON("\{\"ok\":true,\"service\":\"dasHerd-watcher\"\}", http_status.OK) + } + GET("/api/v1/sessions") <| @(var req : HttpRequest?; var resp : HttpResponse?) : http_status { + if (!self.require_auth(req, resp)) return http_status.UNAUTHORIZED + return resp |> JSON(watcher_list_json(), http_status.OK) + } + POST("/api/v1/gc") <| @(var req : HttpRequest?; var resp : HttpResponse?) : http_status { + if (!self.require_auth(req, resp)) return http_status.UNAUTHORIZED + let coalesced = watcher_request_gc() + return resp |> JSON("\{\"ok\":true,\"scheduled\":true,\"coalesced\":{coalesced}\}", + http_status.ACCEPTED) + } + POST("/api/v1/sessions") <| @(var req : HttpRequest?; var resp : HttpResponse?) : http_status { + if (!self.require_auth(req, resp)) return http_status.UNAUTHORIZED + if (req == null || length(req.body) > MAX_REQUEST_BODY_BYTES) { + return self.respond_error(resp, http_status.BAD_REQUEST, "request body is too large") + } + var launch = WatcherLaunchRequest() + if (!sscan_json(string(req.body), launch)) { + return self.respond_error(resp, http_status.BAD_REQUEST, "invalid launch JSON") + } + let result = watcher_launch(launch) + return resp |> JSON(sprint_json(result, false), + result.ok ? http_status.CREATED : http_status.BAD_REQUEST) + } + POST("/api/v1/input") <| @(var req : HttpRequest?; var resp : HttpResponse?) : http_status { + if (!self.require_auth(req, resp)) return http_status.UNAUTHORIZED + if (req == null || length(req.body) > MAX_REQUEST_BODY_BYTES) { + return self.respond_error(resp, http_status.BAD_REQUEST, "request body is too large") + } + var input : WatcherInputRequest + if (!sscan_json(string(req.body), input)) { + return self.respond_error(resp, http_status.BAD_REQUEST, "invalid input JSON") + } + let error = watcher_input(input.session_id, input.text) + if (!empty(error)) return self.respond_error(resp, http_status.CONFLICT, error) + return resp |> JSON(sprint_json(WatcherOk(), false), http_status.OK) + } + POST("/api/v1/resize") <| @(var req : HttpRequest?; var resp : HttpResponse?) : http_status { + if (!self.require_auth(req, resp)) return http_status.UNAUTHORIZED + if (req == null || length(req.body) > MAX_REQUEST_BODY_BYTES) { + return self.respond_error(resp, http_status.BAD_REQUEST, "request body is too large") + } + var resize : WatcherResizeRequest + if (!sscan_json(string(req.body), resize)) { + return self.respond_error(resp, http_status.BAD_REQUEST, "invalid resize JSON") + } + let error = watcher_resize(resize.session_id, resize.columns, resize.rows, 0) + if (!empty(error)) return self.respond_error(resp, http_status.CONFLICT, error) + return resp |> JSON(sprint_json(WatcherOk(), false), http_status.OK) + } + POST("/api/v1/terminate") <| @(var req : HttpRequest?; var resp : HttpResponse?) : http_status { + if (!self.require_auth(req, resp)) return http_status.UNAUTHORIZED + if (req == null || length(req.body) > MAX_REQUEST_BODY_BYTES) { + return self.respond_error(resp, http_status.BAD_REQUEST, "request body is too large") + } + var request : WatcherSessionRequest + if (!sscan_json(string(req.body), request)) { + return self.respond_error(resp, http_status.BAD_REQUEST, "invalid terminate JSON") + } + let error = watcher_terminate(request.session_id) + if (!empty(error)) return self.respond_error(resp, http_status.CONFLICT, error) + return resp |> JSON(sprint_json(WatcherOk(), false), http_status.OK) + } + } + + def find_client(channel : WebSocketChannel) : int { + for (index in range(length(clients))) { + if (clients[index] != null && clients[index].channel == channel) return index + } + return -1 + } + + def send_error(channel : WebSocketChannel; message : string) { + let body = "\{\"type\":\"error\",\"error\":{sprint_json(message, false)}\}" + send(channel, body, ws_opcode.WS_OPCODE_TEXT, true) + } + + def send_sessions(channel : WebSocketChannel) { + send(channel, "\{\"type\":\"sessions\",\"data\":{watcher_list_json()}\}", + ws_opcode.WS_OPCODE_TEXT, true) + } + + def send_snapshot(var client : WatcherClient?; force : bool = false) { + if (client == null || empty(client.session_id)) return + let update_key = watcher_update_key(client.session_id) + if (!force && update_key == client.last_update_key) return + let snapshot = watcher_snapshot_json(client.session_id) + if (empty(snapshot)) { + send_error(client.channel, "unknown session") + return + } + client.last_update_key = update_key + send(client.channel, "\{\"type\":\"snapshot\",\"data\":{snapshot}\}", + ws_opcode.WS_OPCODE_TEXT, true) + } + + def send_raw_output(var client : WatcherClient?) { + if (client == null || !client.raw || empty(client.session_id)) return + var chunk <- watcher_output_since(client.session_id, client.raw_offset) + if (chunk.reset) { + let start_offset = chunk.next_offset - int64(length(chunk.bytes)) + send(client.channel, "\{\"type\":\"raw_reset\",\"offset\":{start_offset}\}", + ws_opcode.WS_OPCODE_TEXT, true) + } + client.raw_offset = chunk.next_offset + if (!empty(chunk.bytes)) { + unsafe { + send(client.channel, reinterpret(addr(chunk.bytes[0])), length(chunk.bytes), + ws_opcode.WS_OPCODE_BINARY, true) + } + } + } + + def detach(var client : WatcherClient?; detail : string) { + if (client == null) return + if (client.controls && !empty(client.session_id)) { + watcher_release_controller(client.session_id, client.id, detail) + } + client.session_id = "" + client.controls = false + client.last_update_key = "" + client.raw = false + client.raw_offset = 0l + } + + def override onWsOpen(channel : WebSocketChannel; url : string#) { + if (!authorized(string(url))) { + send_error(channel, "invalid watcher token") + close(channel) + return + } + next_client_id++ + clients |> push(new WatcherClient(channel = channel, id = next_client_id, + last_heartbeat = ref_time_ticks())) + send(channel, "\{\"type\":\"connected\",\"client_id\":{next_client_id}\}", + ws_opcode.WS_OPCODE_TEXT, true) + send_sessions(channel) + } + + def override onWsClose(channel : WebSocketChannel) { + let index = find_client(channel) + if (index < 0) return + var client = clients[index] + detach(client, "client_closed") + clients |> erase(index) + unsafe { delete client } + } + + def override onWsMessage(channel : WebSocketChannel; message : string#) { + let index = find_client(channel) + if (index < 0) return + var incoming : WatcherWsMessage + if (length(message) > MAX_REQUEST_BODY_BYTES || !sscan_json(string(message), incoming)) { + send_error(channel, "invalid WebSocket message") + return + } + var client = clients[index] + if (client == null) return + client.last_heartbeat = ref_time_ticks() + if (incoming.op == "heartbeat") { + send(channel, "\{\"type\":\"heartbeat\"\}", ws_opcode.WS_OPCODE_TEXT, true) + } elif (incoming.op == "list") { + send_sessions(channel) + } elif (incoming.op == "launch") { + let result = watcher_launch(WatcherLaunchRequest( + command_line = incoming.command_line, cwd = incoming.cwd, + columns = incoming.columns, rows = incoming.rows, + timeout_ms = incoming.timeout_ms)) + if (!result.ok) { + send_error(channel, result.error) + return + } + send(channel, "\{\"type\":\"launched\",\"session_id\":{sprint_json(result.session_id, false)}\}", + ws_opcode.WS_OPCODE_TEXT, true) + send_sessions(channel) + } elif (incoming.op == "attach") { + if (watcher_find_session(incoming.session_id) < 0) { + send_error(channel, "unknown session") + return + } + detach(client, "reattach") + client.session_id = incoming.session_id + let accepts_input = watcher_accepts_input(incoming.session_id) + client.controls = incoming.control && accepts_input && watcher_claim_controller(incoming.session_id, client.id) + client.raw = incoming.raw + client.raw_offset = 0l + if (incoming.control && !accepts_input) { + send_error(channel, "session is not running; output is replay-only") + } elif (incoming.control && !client.controls) { + send_error(channel, "controller lease is held by another client") + } + send(channel, "\{\"type\":\"attached\",\"session_id\":{sprint_json(client.session_id, false)},\"controls\":{client.controls}\}", + ws_opcode.WS_OPCODE_TEXT, true) + send_snapshot(client, true) + send_raw_output(client) + } elif (incoming.op == "detach") { + detach(client, "client_detached") + send(channel, "\{\"type\":\"detached\"\}", ws_opcode.WS_OPCODE_TEXT, true) + } elif (incoming.op == "input") { + if (!client.controls) { + send_error(channel, "client does not hold the controller lease") + return + } + let error = watcher_input(client.session_id, incoming.text, client.id) + if (!empty(error)) send_error(channel, error) + } elif (incoming.op == "resize") { + if (!client.controls) { + send_error(channel, "client does not hold the controller lease") + return + } + let error = watcher_resize(client.session_id, incoming.columns, incoming.rows, client.id) + if (!empty(error)) send_error(channel, error) + } elif (incoming.op == "terminate") { + let session_id = !empty(incoming.session_id) ? incoming.session_id : client.session_id + let error = watcher_terminate(session_id) + if (!empty(error)) send_error(channel, error) + send_sessions(channel) + } else { + send_error(channel, "unknown operation") + } + } + + def override onTick { + watcher_tick() + for (index in range(length(clients))) { + var client = clients[index] + if (client == null) continue + if (client.controls && get_time_nsec(client.last_heartbeat) / 1000000l >= CONTROLLER_HEARTBEAT_TIMEOUT_MS) { + watcher_release_controller(client.session_id, client.id, "heartbeat_timeout") + client.controls = false + send_error(client.channel, "controller lease expired") + } + send_snapshot(client) + send_raw_output(client) + } + } + + def cleanup_clients { + for (index in range(length(clients))) { + var client = clients[index] + if (client != null) { + detach(client, "server_shutdown") + unsafe { delete client } + } + } + clients |> clear() + } +}