morphbox
Version:
Docker-based AI sandbox for development with Claude integration
487 lines (432 loc) • 680 kB
JavaScript
import { c as create_ssr_component, b as subscribe, v as validate_component, d as add_attribute, f as each, e as escape, l as createEventDispatcher, m as missing_component, o as onDestroy, g as get_store_value } from './ssr-Bi8A3Ffq.js';
import { p as page } from './stores-eQz-6iWd.js';
import { s as settings, a as panels, b as activePanel, c as customPanels, d as builtinPanels, e as panelRegistry, t as tick, p as panelStore } from './registry-kTtxA5oL.js';
import { w as writable, d as derived } from './index-6zo8caE3.js';
import { I as Icon } from './Icon-BX2G3WyD.js';
import { D as Download } from './download-RwF-ht7F.js';
import './client-BuRfMCoZ.js';
import './exports-DKuYoYKl.js';
function _slicedToArray(arr, i) {
return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
}
function _arrayWithHoles(arr) {
if (Array.isArray(arr)) return arr;
}
function _iterableToArrayLimit(arr, i) {
if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return;
var _arr = [];
var _n = true;
var _d = false;
var _e = undefined;
try {
for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
_arr.push(_s.value);
if (i && _arr.length === i) break;
}
} catch (err) {
_d = true;
_e = err;
} finally {
try {
if (!_n && _i["return"] != null) _i["return"]();
} finally {
if (_d) throw _e;
}
}
return _arr;
}
function _unsupportedIterableToArray(o, minLen) {
if (!o) return;
if (typeof o === "string") return _arrayLikeToArray(o, minLen);
var n = Object.prototype.toString.call(o).slice(8, -1);
if (n === "Object" && o.constructor) n = o.constructor.name;
if (n === "Map" || n === "Set") return Array.from(o);
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
}
function _arrayLikeToArray(arr, len) {
if (len == null || len > arr.length) len = arr.length;
for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
return arr2;
}
function _nonIterableRest() {
throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _defineProperty(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
function ownKeys(object, enumerableOnly) {
var keys = Object.keys(object);
if (Object.getOwnPropertySymbols) {
var symbols = Object.getOwnPropertySymbols(object);
if (enumerableOnly) symbols = symbols.filter(function (sym) {
return Object.getOwnPropertyDescriptor(object, sym).enumerable;
});
keys.push.apply(keys, symbols);
}
return keys;
}
function _objectSpread2(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i] != null ? arguments[i] : {};
if (i % 2) {
ownKeys(Object(source), true).forEach(function (key) {
_defineProperty(target, key, source[key]);
});
} else if (Object.getOwnPropertyDescriptors) {
Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
} else {
ownKeys(Object(source)).forEach(function (key) {
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
});
}
}
return target;
}
function compose() {
for (var _len = arguments.length, fns = new Array(_len), _key = 0; _key < _len; _key++) {
fns[_key] = arguments[_key];
}
return function (x) {
return fns.reduceRight(function (y, f) {
return f(y);
}, x);
};
}
function curry$1(fn) {
return function curried() {
var _this = this;
for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
args[_key2] = arguments[_key2];
}
return args.length >= fn.length ? fn.apply(this, args) : function () {
for (var _len3 = arguments.length, nextArgs = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
nextArgs[_key3] = arguments[_key3];
}
return curried.apply(_this, [].concat(args, nextArgs));
};
};
}
function isObject(value) {
return {}.toString.call(value).includes('Object');
}
function isEmpty(obj) {
return !Object.keys(obj).length;
}
function isFunction(value) {
return typeof value === 'function';
}
function hasOwnProperty(object, property) {
return Object.prototype.hasOwnProperty.call(object, property);
}
function validateChanges(initial, changes) {
if (!isObject(changes)) errorHandler('changeType');
if (Object.keys(changes).some(function (field) {
return !hasOwnProperty(initial, field);
})) errorHandler('changeField');
return changes;
}
function validateSelector(selector) {
if (!isFunction(selector)) errorHandler('selectorType');
}
function validateHandler(handler) {
if (!(isFunction(handler) || isObject(handler))) errorHandler('handlerType');
if (isObject(handler) && Object.values(handler).some(function (_handler) {
return !isFunction(_handler);
})) errorHandler('handlersType');
}
function validateInitial(initial) {
if (!initial) errorHandler('initialIsRequired');
if (!isObject(initial)) errorHandler('initialType');
if (isEmpty(initial)) errorHandler('initialContent');
}
function throwError$1(errorMessages, type) {
throw new Error(errorMessages[type] || errorMessages["default"]);
}
var errorMessages$1 = {
initialIsRequired: 'initial state is required',
initialType: 'initial state should be an object',
initialContent: 'initial state shouldn\'t be an empty object',
handlerType: 'handler should be an object or a function',
handlersType: 'all handlers should be a functions',
selectorType: 'selector should be a function',
changeType: 'provided value of changes should be an object',
changeField: 'it seams you want to change a field in the state which is not specified in the "initial" state',
"default": 'an unknown error accured in `state-local` package'
};
var errorHandler = curry$1(throwError$1)(errorMessages$1);
var validators = {
changes: validateChanges,
selector: validateSelector,
handler: validateHandler,
initial: validateInitial
};
function create(initial) {
var handler = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
validators.initial(initial);
validators.handler(handler);
var state = {
current: initial
};
var didUpdate = curry$1(didStateUpdate)(state, handler);
var update = curry$1(updateState)(state);
var validate = curry$1(validators.changes)(initial);
var getChanges = curry$1(extractChanges)(state);
function getState() {
var selector = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function (state) {
return state;
};
validators.selector(selector);
return selector(state.current);
}
function setState(causedChanges) {
compose(didUpdate, update, validate, getChanges)(causedChanges);
}
return [getState, setState];
}
function extractChanges(state, causedChanges) {
return isFunction(causedChanges) ? causedChanges(state.current) : causedChanges;
}
function updateState(state, changes) {
state.current = _objectSpread2(_objectSpread2({}, state.current), changes);
return changes;
}
function didStateUpdate(state, handler, changes) {
isFunction(handler) ? handler(state.current) : Object.keys(changes).forEach(function (field) {
var _handler$field;
return (_handler$field = handler[field]) === null || _handler$field === void 0 ? void 0 : _handler$field.call(handler, state.current[field]);
});
return changes;
}
var index = {
create: create
};
var config = {
paths: {
vs: 'https://cdn.jsdelivr.net/npm/monaco-editor@0.52.2/min/vs'
}
};
function curry(fn) {
return function curried() {
var _this = this;
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
return args.length >= fn.length ? fn.apply(this, args) : function () {
for (var _len2 = arguments.length, nextArgs = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
nextArgs[_key2] = arguments[_key2];
}
return curried.apply(_this, [].concat(args, nextArgs));
};
};
}
function throwError(errorMessages, type) {
throw new Error(errorMessages[type] || errorMessages["default"]);
}
var errorMessages = {
configIsRequired: 'the configuration object is required',
configType: 'the configuration object should be an object',
"default": 'an unknown error accured in `@monaco-editor/loader` package',
deprecation: "Deprecation warning!\n You are using deprecated way of configuration.\n\n Instead of using\n monaco.config({ urls: { monacoBase: '...' } })\n use\n monaco.config({ paths: { vs: '...' } })\n\n For more please check the link https://github.com/suren-atoyan/monaco-loader#config\n "
};
curry(throwError)(errorMessages);
/** the local state of the module */
var _state$create = index.create({
config: config,
isInitialized: false,
resolve: null,
reject: null,
monaco: null
}),
_state$create2 = _slicedToArray(_state$create, 2);
_state$create2[0];
var setState = _state$create2[1];
new Promise(function (resolve, reject) {
return setState({
resolve: resolve,
reject: reject
});
});
class BrowserLogger {
queue = [];
batchTimer = null;
batchDelay = 1e3;
// 1 second
maxBatchSize = 50;
endpoint = "/api/log/browser";
isEnabled = true;
constructor() {
this.interceptConsole();
if (typeof window !== "undefined") {
window.addEventListener("beforeunload", () => {
this.flush();
});
}
}
interceptConsole() {
if (typeof window === "undefined") return;
const originalLog = console.log;
const originalError = console.error;
const originalWarn = console.warn;
const originalDebug = console.debug;
console.log = (...args) => {
this.log("info", args);
originalLog.apply(console, args);
};
console.error = (...args) => {
this.log("error", args);
originalError.apply(console, args);
};
console.warn = (...args) => {
this.log("warn", args);
originalWarn.apply(console, args);
};
console.debug = (...args) => {
this.log("debug", args);
originalDebug.apply(console, args);
};
}
getBrowserInfo() {
if (typeof window === "undefined") {
return {
userAgent: "unknown",
url: "unknown",
viewport: { width: 0, height: 0 }
};
}
return {
userAgent: navigator.userAgent,
url: window.location.href,
viewport: {
width: window.innerWidth,
height: window.innerHeight
}
};
}
formatMessage(args) {
return args.map((arg) => {
if (typeof arg === "object") {
try {
return JSON.stringify(arg, null, 2);
} catch (e) {
return String(arg);
}
}
return String(arg);
}).join(" ");
}
log(level, args) {
if (!this.isEnabled) return;
const entry = {
level,
message: this.formatMessage(args),
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
browserInfo: this.getBrowserInfo()
};
if (args.length === 1 && typeof args[0] === "object") {
entry.data = args[0];
}
this.queue.push(entry);
this.scheduleBatch();
}
scheduleBatch() {
if (this.batchTimer !== null) return;
if (this.queue.length >= this.maxBatchSize) {
this.sendBatch();
return;
}
this.batchTimer = window.setTimeout(() => {
this.sendBatch();
}, this.batchDelay);
}
async sendBatch() {
if (this.batchTimer !== null) {
clearTimeout(this.batchTimer);
this.batchTimer = null;
}
if (this.queue.length === 0) return;
const batch = this.queue.splice(0, this.maxBatchSize);
try {
const response = await fetch(this.endpoint, {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({ logs: batch })
});
if (!response.ok) {
throw new Error(`Failed to send logs: ${response.status}`);
}
} catch (error) {
console.error("[BrowserLogger] Failed to send logs to server:", error);
batch.forEach((entry) => {
const fallbackMsg = `[${entry.level.toUpperCase()}] ${entry.timestamp} - ${entry.message}`;
switch (entry.level) {
case "error":
console.error(fallbackMsg, entry.data);
break;
case "warn":
console.warn(fallbackMsg, entry.data);
break;
case "debug":
console.debug(fallbackMsg, entry.data);
break;
default:
console.log(fallbackMsg, entry.data);
}
});
}
if (this.queue.length > 0) {
this.scheduleBatch();
}
}
// Public methods for direct usage
info(...args) {
this.log("info", args);
}
error(...args) {
this.log("error", args);
}
debug(...args) {
this.log("debug", args);
}
warn(...args) {
this.log("warn", args);
}
// Force send all queued logs
flush() {
if (this.queue.length > 0) {
this.sendBatch();
}
}
// Enable/disable logging
enable() {
this.isEnabled = true;
}
disable() {
this.isEnabled = false;
}
// Configuration methods
setEndpoint(endpoint) {
this.endpoint = endpoint;
}
setBatchDelay(delay) {
this.batchDelay = delay;
}
setMaxBatchSize(size) {
this.maxBatchSize = size;
}
}
const logger = new BrowserLogger();
const css$f = {
code: ".terminal-outer-container.svelte-b660cs.svelte-b660cs{width:100%;height:100%;position:relative;overflow:hidden;max-height:100%;box-sizing:border-box}.terminal-container.svelte-b660cs.svelte-b660cs{width:100%;height:100%;background-color:#1e1e1e;position:relative;box-sizing:border-box}.terminal-container.loading.svelte-b660cs.svelte-b660cs{opacity:0.2}.terminal-container.dragging-over.svelte-b660cs.svelte-b660cs{border:2px dashed var(--accent-color, #0e639c);background-color:rgba(14, 99, 156, 0.1)}.terminal-container.dragging-over.svelte-b660cs.svelte-b660cs::after{content:'Drop files here';position:absolute;top:50%;left:50%;transform:translate(-50%, -50%);color:var(--accent-color, #0e639c);font-size:18px;font-weight:bold;pointer-events:none;z-index:10;background:rgba(30, 30, 30, 0.9);padding:10px 20px;border-radius:4px;border:1px solid var(--accent-color, #0e639c)}.upload-modal-backdrop.svelte-b660cs.svelte-b660cs{position:fixed;top:0;left:0;right:0;bottom:0;background-color:rgba(0, 0, 0, 0.7);z-index:1000;display:flex;align-items:center;justify-content:center}.upload-modal.svelte-b660cs.svelte-b660cs{background-color:#2a2a2a;border:1px solid #444;border-radius:8px;padding:24px;max-width:500px;width:90%;max-height:70vh;overflow-y:auto;box-shadow:0 4px 6px rgba(0, 0, 0, 0.3)}.upload-modal.svelte-b660cs h3.svelte-b660cs{margin:0 0 16px 0;color:#fff;font-size:20px}.upload-modal.svelte-b660cs p.svelte-b660cs{color:#ccc;margin:0 0 16px 0;line-height:1.5}.dropped-files.svelte-b660cs.svelte-b660cs{background-color:#1e1e1e;border:1px solid #444;border-radius:4px;padding:12px;margin:16px 0}.dropped-files.svelte-b660cs p.svelte-b660cs{margin:0 0 8px 0;font-weight:bold;color:#aaa;font-size:14px}.dropped-files.svelte-b660cs ul.svelte-b660cs{margin:0;padding-left:20px;color:#ccc}.dropped-files.svelte-b660cs li.svelte-b660cs{margin:4px 0;font-family:monospace;font-size:13px}.close-modal-btn.svelte-b660cs.svelte-b660cs{background-color:var(--accent-color, #0e639c);color:white;border:none;padding:8px 24px;border-radius:4px;cursor:pointer;font-size:14px;margin-top:16px;width:100%}.close-modal-btn.svelte-b660cs.svelte-b660cs:hover{background-color:#1976d2}.loading-overlay.svelte-b660cs.svelte-b660cs{position:absolute;top:0;left:0;right:0;bottom:0;display:flex;align-items:center;justify-content:center;background-color:rgba(30, 30, 30, 0.9);z-index:100;pointer-events:none}.loading-content.svelte-b660cs.svelte-b660cs{text-align:center;color:var(--text-primary, #d4d4d4)}.loading-spinner.svelte-b660cs.svelte-b660cs{width:40px;height:40px;margin:0 auto 16px;border:3px solid rgba(255, 255, 255, 0.1);border-top-color:var(--accent-color, #0e639c);border-radius:50%;animation:svelte-b660cs-spin 1s linear infinite}.loading-text.svelte-b660cs.svelte-b660cs{font-size:16px;font-weight:500}.connection-status.svelte-b660cs.svelte-b660cs{position:absolute;top:10px;right:10px;background:rgba(0, 0, 0, 0.8);color:#fff;padding:8px 16px;border-radius:4px;font-size:14px;z-index:100;display:flex;align-items:center;gap:8px}.connection-status.reconnecting.svelte-b660cs.svelte-b660cs{background:rgba(255, 152, 0, 0.9)}.status-icon.svelte-b660cs.svelte-b660cs{display:inline-block;animation:svelte-b660cs-spin 1s linear infinite}@keyframes svelte-b660cs-spin{from{transform:rotate(0deg)}to{transform:rotate(360deg)}}.terminal-wrapper .xterm{padding:5px;height:100%;width:100%;display:block;box-sizing:border-box}.xterm-viewport{background-color:#1e1e1e;overflow-y:scroll !important;overflow-x:auto !important}.xterm-screen{margin:0;width:100% !important}.xterm-rows{min-width:0}.xterm{height:100%;width:100%;box-sizing:border-box}.terminal-wrapper{width:100% !important}.xterm .xterm-text-layer,.xterm .xterm-cursor-layer,.xterm .xterm-selection-layer{will-change:transform}.xterm.xterm-cursor-blink{animation-duration:1s}.xterm-helper-textarea{font-size:16px !important}.xterm-helper-textarea{font-size:16px !important}.xterm .xterm-rows{line-height:1.1 !important}.xterm-screen{line-height:1.1 !important}.xterm .xterm-row{line-height:1.1 !important}",
map: '{"version":3,"file":"Terminal.svelte","sources":["Terminal.svelte"],"sourcesContent":["<script lang=\\"ts\\">import { onMount, onDestroy, createEventDispatcher, beforeUpdate, afterUpdate } from \\"svelte\\";\\nimport { browser } from \\"$app/environment\\";\\nimport { settings } from \\"$lib/panels/Settings/settings-store\\";\\nimport { fade } from \\"svelte/transition\\";\\nimport logger from \\"$lib/utils/browser-logger\\";\\nconsole.log(\\"\\\\u2705\\\\u2705\\\\u2705 Terminal.svelte loaded - console logging is ENABLED \\\\u2705\\\\u2705\\\\u2705\\");\\nlet Terminal;\\nlet FitAddon;\\nlet WebLinksAddon;\\nif (browser) {\\n import(\\"@xterm/xterm\\").then((module) => {\\n Terminal = module.Terminal;\\n });\\n import(\\"@xterm/addon-fit\\").then((module) => {\\n FitAddon = module.FitAddon;\\n });\\n import(\\"@xterm/addon-web-links\\").then((module) => {\\n WebLinksAddon = module.WebLinksAddon;\\n });\\n import(\\"@xterm/xterm/css/xterm.css\\");\\n}\\nexport let websocketUrl = \\"ws://localhost:3000\\";\\nexport let autoLaunchClaude = false;\\nexport let panelId = \\"\\";\\nexport let backgroundColor = void 0;\\nexport let textColor = void 0;\\nexport let boldTextColor = void 0;\\nlet terminalContainer;\\nlet terminal;\\nlet fitAddon;\\nlet ws = null;\\nlet inputBuffer = \\"\\";\\nlet settingsUnsubscribe = null;\\nlet reconnectAttempts = 0;\\nlet isReconnecting = false;\\nlet connectionStatus = \\"disconnected\\";\\nexport let terminalSessionId = null;\\nlet sessionId = null;\\nlet agentId = null;\\nlet isInitializing = true;\\nlet hideLogoTimeout = null;\\nlet isDraggingOver = false;\\nlet showUploadModal = false;\\nlet draggedFiles = [];\\nlet resizeObserver = null;\\nlet mutationObserver = null;\\nlet windowResizeHandler = null;\\nlet orientationChangeHandler = null;\\nconst dispatch = createEventDispatcher();\\nlet claudeIdleTimeout = null;\\nlet lastDataReceived = 0;\\nlet claudeState = \\"idle\\";\\nlet accumulatedOutput = \\"\\";\\n$: if (terminal && (backgroundColor || textColor || boldTextColor)) {\\n updateTerminalSettings();\\n}\\nfunction isRemoteServer() {\\n if (!browser) return false;\\n const hostname = window.location.hostname;\\n return hostname !== \\"localhost\\" && hostname !== \\"127.0.0.1\\" && hostname !== \\"::1\\";\\n}\\nfunction handleDragOver(event) {\\n event.preventDefault();\\n event.stopPropagation();\\n isDraggingOver = true;\\n if (event.dataTransfer) {\\n event.dataTransfer.dropEffect = \\"copy\\";\\n }\\n}\\nfunction handleDragLeave(event) {\\n event.preventDefault();\\n event.stopPropagation();\\n isDraggingOver = false;\\n}\\nfunction handleDrop(event) {\\n event.preventDefault();\\n event.stopPropagation();\\n isDraggingOver = false;\\n if (!event.dataTransfer || !event.dataTransfer.files.length) {\\n return;\\n }\\n const files = Array.from(event.dataTransfer.files);\\n const items = event.dataTransfer.items ? Array.from(event.dataTransfer.items) : [];\\n if (isRemoteServer()) {\\n draggedFiles = files;\\n showUploadModal = true;\\n return;\\n }\\n processFilesForTerminal(files, items);\\n}\\nasync function processFilesForTerminal(files, items) {\\n const paths = [];\\n for (let i = 0; i < items.length; i++) {\\n const item = items[i];\\n if (item.kind === \\"file\\") {\\n const entry = item.webkitGetAsEntry ? item.webkitGetAsEntry() : null;\\n if (entry) {\\n paths.push(entry.fullPath || files[i].name);\\n } else {\\n paths.push(files[i].name);\\n }\\n }\\n }\\n if (paths.length === 0) {\\n files.forEach((file) => {\\n const path = file.path || file.webkitRelativePath || file.name;\\n paths.push(path);\\n });\\n }\\n if (paths.length > 0 && terminal) {\\n const pathString = paths.map((p) => {\\n if (p.includes(\\" \\") || p.includes(\\"(\\") || p.includes(\\")\\") || p.includes(\\"&\\")) {\\n return `\'${p}\'`;\\n }\\n return p;\\n }).join(\\" \\");\\n sendInput(pathString);\\n }\\n}\\nfunction closeUploadModal() {\\n showUploadModal = false;\\n draggedFiles = [];\\n}\\nonMount(() => {\\n dispatch(\\"ready\\", {\\n sendInput,\\n write,\\n writeln,\\n clear,\\n clearSession\\n });\\n});\\nlet outputBuffer = [];\\nlet flushTimeout = null;\\nlet earlyMessages = [];\\nconst BUFFER_FLUSH_DELAY = 16;\\nfunction flushBuffer() {\\n if (outputBuffer.length > 0 && terminal) {\\n const data = outputBuffer.join(\\"\\");\\n outputBuffer = [];\\n terminal.write(data);\\n }\\n flushTimeout = null;\\n}\\nfunction scheduleFlush() {\\n if (!flushTimeout && browser) {\\n flushTimeout = window.requestAnimationFrame(flushBuffer);\\n }\\n}\\nexport function write(data) {\\n if (terminal) {\\n const viewport = getViewportInfo();\\n if (data.length < 100 || viewport.isSmall) {\\n terminal.write(data);\\n } else {\\n outputBuffer.push(data);\\n scheduleFlush();\\n }\\n } else {\\n console.warn(\\"[Terminal.write] No terminal instance, cannot write data\\");\\n }\\n}\\nexport function writeln(data) {\\n if (terminal) {\\n write(data + \\"\\\\r\\\\n\\");\\n } else {\\n earlyMessages.push(data);\\n console.log(\\"[Terminal] Buffering early message:\\", data);\\n }\\n}\\nexport function clear() {\\n if (terminal) {\\n outputBuffer = [];\\n if (flushTimeout) {\\n cancelAnimationFrame(flushTimeout);\\n flushTimeout = null;\\n }\\n terminal.clear();\\n }\\n}\\nexport function clearSession() {\\n terminalSessionId = null;\\n if (browser) {\\n localStorage.removeItem(\\"morphbox-terminal-session\\");\\n }\\n writeln(\\"\\\\r\\\\n\\\\u{1F504} Session cleared. Next connection will start fresh.\\");\\n}\\nexport function sendInput(input) {\\n console.log(\\"[Terminal.sendInput] Called with:\\", input, \\"WebSocket state:\\", ws?.readyState);\\n if (ws && ws.readyState === WebSocket.OPEN) {\\n const message = JSON.stringify({\\n type: \\"SEND_INPUT\\",\\n payload: { input }\\n });\\n console.log(\\"[Terminal.sendInput] Sending message:\\", message);\\n ws.send(message);\\n } else {\\n console.warn(\\"[Terminal.sendInput] WebSocket not ready:\\", ws?.readyState);\\n }\\n}\\nexport function testLogging() {\\n logger.info(\\"[Terminal] Test log - Info level\\", { test: true, timestamp: Date.now() });\\n logger.error(\\"[Terminal] Test log - Error level\\", { test: true, error: \\"This is a test error\\" });\\n logger.warn(\\"[Terminal] Test log - Warning level\\", { test: true });\\n logger.debug(\\"[Terminal] Test log - Debug level\\", { test: true });\\n console.log(\\"[Terminal] Test logging completed - check logs/browser-logs.jsonl\\");\\n}\\nfunction reconnectWithBackoff() {\\n const maxDelay = 3e4;\\n const baseDelay = 1e3;\\n const delay = Math.min(baseDelay * Math.pow(2, reconnectAttempts), maxDelay);\\n writeln(`\\\\r\\nReconnecting in ${delay / 1e3} seconds... (attempt ${reconnectAttempts + 1})`);\\n setTimeout(() => {\\n if (!ws || ws.readyState === WebSocket.CLOSED) {\\n reconnectAttempts++;\\n connectWebSocket();\\n }\\n }, delay);\\n}\\nfunction connectWebSocket() {\\n if (ws && (ws.readyState === WebSocket.CONNECTING || ws.readyState === WebSocket.OPEN)) {\\n console.warn(\\"[Terminal] WebSocket already connecting or connected, skipping new connection\\");\\n return;\\n }\\n if (ws) {\\n ws.close();\\n }\\n let url = websocketUrl;\\n if (browser) {\\n const urlObj = new URL(websocketUrl);\\n if (terminalSessionId) {\\n urlObj.searchParams.set(\\"terminalSessionId\\", terminalSessionId);\\n }\\n if (sessionId) {\\n urlObj.searchParams.set(\\"sessionId\\", sessionId);\\n } else if (browser) {\\n const storedSessionId = localStorage.getItem(\\"morphbox-websocket-session\\");\\n if (storedSessionId) {\\n sessionId = storedSessionId;\\n urlObj.searchParams.set(\\"sessionId\\", sessionId);\\n }\\n }\\n urlObj.searchParams.set(\\"autoLaunchClaude\\", autoLaunchClaude.toString());\\n url = urlObj.toString();\\n }\\n console.log(\\"[Terminal] Connecting to WebSocket:\\", url);\\n console.log(\\"[Terminal] User agent:\\", navigator.userAgent);\\n console.log(\\"[Terminal] Is mobile:\\", getViewportInfo().isTouchDevice);\\n try {\\n ws = new WebSocket(url);\\n const connectionTimeout = setTimeout(() => {\\n if (ws && ws.readyState !== WebSocket.OPEN) {\\n writeln(`\\\\r\\n\\\\u274C WebSocket connection timeout. Please check if the WebSocket server is running at ${url}.`);\\n console.error(\\"WebSocket connection timeout\\");\\n }\\n }, 5e3);\\n ws.onopen = () => {\\n clearTimeout(connectionTimeout);\\n logger.info(\\"[Terminal] WebSocket connected successfully\\");\\n console.log(\\"WebSocket connected\\");\\n connectionStatus = \\"connected\\";\\n reconnectAttempts = 0;\\n isReconnecting = false;\\n if (terminalSessionId) {\\n writeln(\\"\\\\r\\\\n\\\\u{1F504} Reconnecting to existing session...\\");\\n } else {\\n writeln(\\"\\\\r\\\\n\\\\u2705 Connected to server\\");\\n }\\n dispatch(\\"connection\\", { connected: true });\\n setTimeout(() => {\\n console.log(\\"[Terminal] Hiding loading overlay after connection\\");\\n isInitializing = false;\\n }, 750);\\n };\\n ws.onmessage = (event) => {\\n try {\\n const message = JSON.parse(event.data);\\n if (message.type === \\"OUTPUT\\" && autoLaunchClaude) {\\n } else if (message.type !== \\"OUTPUT\\") {\\n }\\n switch (message.type) {\\n case \\"CONNECTED\\":\\n writeln(`\\\\r\\n${message.payload?.message || \\"Connected\\"}`);\\n if (message.payload?.sessionId) {\\n sessionId = message.payload.sessionId;\\n if (browser && sessionId) {\\n localStorage.setItem(\\"morphbox-websocket-session\\", sessionId);\\n }\\n if (message.payload.isReconnection && sessionId) {\\n writeln(`\\\\r\\n\\\\u{1F504} Reconnected to session: ${sessionId.substring(0, 8)}...`);\\n }\\n }\\n break;\\n case \\"SESSION_CREATED\\":\\n dispatch(\\"session\\", { sessionId: message.payload?.sessionId });\\n break;\\n case \\"AGENT_LAUNCHED\\":\\n agentId = message.payload?.agentId || null;\\n console.log(\\"[Terminal] Agent launched:\\", agentId);\\n isInitializing = false;\\n if (hideLogoTimeout) {\\n clearTimeout(hideLogoTimeout);\\n hideLogoTimeout = null;\\n }\\n dispatch(\\"agent\\", {\\n status: \\"Active\\",\\n agentId: message.payload?.agentId\\n });\\n break;\\n case \\"TERMINAL_SESSION_ID\\":\\n if (message.payload?.sessionId) {\\n const isNewSession = terminalSessionId !== message.payload.sessionId;\\n terminalSessionId = message.payload.sessionId;\\n if (browser && terminalSessionId) {\\n localStorage.setItem(\\"morphbox-terminal-session\\", terminalSessionId);\\n }\\n if (isNewSession && terminalSessionId) {\\n writeln(`\\\\r\\n\\\\u2728 New terminal session created: ${terminalSessionId.substring(0, 8)}...`);\\n } else if (terminalSessionId) {\\n writeln(`\\\\r\\n\\\\u2705 Terminal session restored: ${terminalSessionId.substring(0, 8)}...`);\\n }\\n }\\n break;\\n case \\"RECONNECTED\\":\\n writeln(`\\\\r\\n\\\\u2705 Reconnected to agent: ${message.payload?.agentId}`);\\n dispatch(\\"agent\\", {\\n status: \\"Active\\",\\n agentId: message.payload?.agentId\\n });\\n isInitializing = false;\\n break;\\n case \\"AGENT_EXIT\\":\\n dispatch(\\"agent\\", { status: \\"No agent\\" });\\n break;\\n case \\"OUTPUT\\":\\n if (message.payload?.data && message.payload?.agentId === agentId) {\\n if (isInitializing) {\\n console.log(\\"[Terminal] First output received, hiding loading overlay\\");\\n isInitializing = false;\\n if (hideLogoTimeout) {\\n clearTimeout(hideLogoTimeout);\\n hideLogoTimeout = null;\\n }\\n }\\n write(message.payload.data);\\n if (autoLaunchClaude) {\\n const data = message.payload.data;\\n lastDataReceived = Date.now();\\n claudeState = \\"responding\\";\\n accumulatedOutput += data;\\n if (accumulatedOutput.length > 500) {\\n accumulatedOutput = accumulatedOutput.slice(-500);\\n }\\n const cleanData = data.replace(/\\\\x1b\\\\[[0-9;]*[mGKHJ]/g, \\"\\").trim();\\n if (cleanData && cleanData.length > 5 && !cleanData.match(/^\\\\[\\\\d+[A-Z]$/)) {\\n console.log(\\"\\\\u{1F4DF} Terminal:\\", cleanData.substring(0, 80));\\n }\\n if (claudeIdleTimeout) {\\n clearTimeout(claudeIdleTimeout);\\n }\\n claudeIdleTimeout = setTimeout(() => {\\n const lowerOutput = accumulatedOutput.toLowerCase();\\n const trimmedOutput = accumulatedOutput.trim();\\n const hasClaudeCodePrompt = trimmedOutput.endsWith(\\">\\") || accumulatedOutput.includes(\\"\\\\u2500\\\\u2500\\\\u2500\\") && trimmedOutput.endsWith(\\">\\");\\n const hasRegularClaudePrompt = trimmedOutput.endsWith(\\"human:\\") || trimmedOutput.endsWith(\\"h:\\") || lowerOutput.includes(\\"human:\\") && Date.now() - lastDataReceived > 2e3;\\n const hasEscToInterrupt = accumulatedOutput.toLowerCase().includes(\\"esc to interrupt\\");\\n if (hasEscToInterrupt) {\\n console.log(\'\\\\u23F3 Claude still responding (\\"esc to interrupt\\" present)\');\\n }\\n if (typeof window !== \\"undefined\\") {\\n window.claudeDetectionData = {\\n timestamp: (/* @__PURE__ */ new Date()).toISOString(),\\n hasEscToInterrupt,\\n hasClaudeCodePrompt,\\n hasRegularClaudePrompt,\\n last100Chars: accumulatedOutput.slice(-100),\\n fullAccumulatedOutput: accumulatedOutput,\\n claudeState\\n };\\n }\\n if (!hasEscToInterrupt && accumulatedOutput.length > 10) {\\n if (claudeState !== \\"idle\\") {\\n claudeState = \\"idle\\";\\n console.log(\\"\\");\\n console.log(\\"\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\");\\n console.log(\\"\\\\u{1F3AF} CLAUDE IS NOW IDLE - DISPATCHING EVENT! \\\\u{1F3AF}\\");\\n console.log(\\"\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\");\\n console.log(\'\\\\u2705 No \\"esc to interrupt\\" found (Claude finished)\');\\n console.log(\\"\\\\u2705 Claude prompt detected:\\", hasClaudeCodePrompt ? \\">\\" : hasRegularClaudePrompt ? \\"human:\\" : \\"unknown\\");\\n console.log(\\"\\\\u{1F4C4} Last output:\\", accumulatedOutput.slice(-100).replace(/\\\\x1b\\\\[[0-9;]*[mGKHJ]/g, \\"\\"));\\n console.log(\\"\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\\\u{1F3AF}\\");\\n console.log(\\"\\");\\n if (typeof window !== \\"undefined\\") {\\n window.lastClaudeIdleEvent = {\\n timestamp: (/* @__PURE__ */ new Date()).toISOString(),\\n output: accumulatedOutput\\n };\\n }\\n dispatch(\\"claude-idle\\");\\n }\\n } else if (Date.now() - lastDataReceived > 3e3) {\\n if (claudeState !== \\"idle\\") {\\n claudeState = \\"idle\\";\\n console.log(\\"[Terminal] \\\\u{1F550} CLAUDE IS IDLE (3s timeout) - DISPATCHING EVENT\\");\\n console.log(\\"[Terminal] Time since last data:\\", Date.now() - lastDataReceived, \\"ms\\");\\n console.log(\\"[Terminal] Last output:\\", accumulatedOutput.slice(-100));\\n if (typeof window !== \\"undefined\\") {\\n window.lastClaudeIdleEvent = {\\n timestamp: (/* @__PURE__ */ new Date()).toISOString(),\\n reason: \\"timeout\\",\\n output: accumulatedOutput\\n };\\n }\\n dispatch(\\"claude-idle\\");\\n }\\n }\\n }, 4e3);\\n }\\n }\\n break;\\n case \\"ERROR\\":\\n writeln(`\\\\r\\nError: ${message.payload?.message || \\"Unknown error\\"}`);\\n break;\\n case \\"STATE_UPDATE\\":\\n if (message.payload?.agent) {\\n dispatch(\\"agent\\", {\\n status: message.payload.agent.status || \\"Active\\",\\n agentId: message.payload.agent.id\\n });\\n }\\n break;\\n case \\"CLEAR\\":\\n clear();\\n break;\\n default:\\n console.log(\\"Unknown message type:\\", message.type);\\n }\\n } catch (e) {\\n console.error(\\"Error parsing WebSocket message:\\", e);\\n write(event.data);\\n }\\n };\\n ws.onerror = (error) => {\\n logger.error(\\"[Terminal] WebSocket error:\\", error);\\n console.error(\\"WebSocket error:\\", error);\\n writeln(`\\\\r\\nWebSocket error: ${error}`);\\n };\\n ws.onclose = (event) => {\\n logger.info(\\"[Terminal] WebSocket closed\\", { code: event.code, reason: event.reason });\\n console.error(\\"[Terminal] WebSocket closed:\\", {\\n code: event.code,\\n reason: event.reason,\\n wasClean: event.wasClean,\\n readyState: ws?.readyState,\\n timestamp: (/* @__PURE__ */ new Date()).toISOString(),\\n stackTrace: new Error().stack\\n });\\n connectionStatus = \\"disconnected\\";\\n writeln(`\\\\r\\nDisconnected from server (code: ${event.code})`);\\n dispatch(\\"connection\\", { connected: false });\\n dispatch(\\"agent\\", { status: \\"No agent\\" });\\n if (event.code !== 1e3 && event.code !== 1001 && !isReconnecting) {\\n isReconnecting = true;\\n connectionStatus = \\"reconnecting\\";\\n reconnectWithBackoff();\\n }\\n };\\n } catch (error) {\\n console.error(\\"[Terminal] WebSocket setup error:\\", error);\\n isInitializing = false;\\n writeln(\\"\\\\r\\\\n\\\\u274C Failed to connect to WebSocket\\");\\n return;\\n }\\n}\\nfunction getViewportInfo() {\\n if (!browser) return { width: 1200, height: 800, isSmall: false, isTouchDevice: false };\\n const width = window.innerWidth;\\n const height = window.innerHeight;\\n const isSmall = width < 768;\\n const isTouchDevice = \\"ontouchstart\\" in window || navigator.maxTouchPoints > 0;\\n const info = { width, height, isSmall, isTouchDevice };\\n if (typeof window !== \\"undefined\\" && window.__lastViewportInfo) {\\n const last = window.__lastViewportInfo;\\n if (last.width !== width || last.height !== height || last.isSmall !== isSmall) {\\n console.log(\\"[Terminal.getViewportInfo] Viewport changed:\\", {\\n from: last,\\n to: info,\\n delta: {\\n width: width - last.width,\\n height: height - last.height\\n },\\n devicePixelRatio: window.devicePixelRatio\\n });\\n }\\n }\\n if (typeof window !== \\"undefined\\") {\\n window.__lastViewportInfo = info;\\n }\\n return info;\\n}\\nfunction getTerminalOptions() {\\n const viewport = getViewportInfo();\\n const currentSettings = $settings;\\n console.log(\\"[Terminal.getTerminalOptions] Starting calculation:\\", {\\n viewport,\\n hasContainer: !!terminalContainer,\\n currentSettings: currentSettings?.terminal\\n });\\n let fontSize = currentSettings?.terminal.fontSize || 14;\\n if (viewport.isSmall) {\\n fontSize = Math.max(12, Math.min(fontSize, 14));\\n }\\n let containerWidth = viewport.width;\\n let containerHeight = viewport.height;\\n if (terminalContainer) {\\n const rect = terminalContainer.getBoundingClientRect();\\n containerWidth = rect.width || containerWidth;\\n containerHeight = rect.height || containerHeight;\\n console.log(\\"[Terminal.getTerminalOptions] Container dimensions:\\", {\\n rectWidth: rect.width,\\n rectHeight: rect.height,\\n containerWidth,\\n containerHeight,\\n fallbackToViewport: rect.width === 0 || rect.height === 0\\n });\\n }\\n const charWidth = fontSize * 0.55;\\n const lineHeight = fontSize * (currentSettings?.terminal.lineHeight || 1.1);\\n const padding = viewport.isSmall ? 5 : 10;\\n const cols = Math.max(40, Math.floor((containerWidth - padding * 2) / charWidth));\\n const rows = Math.max(10, Math.floor((containerHeight - padding * 2) / lineHeight));\\n console.log(\\"[Terminal.getTerminalOptions] Calculated dimensions:\\", {\\n fontSize,\\n charWidth,\\n lineHeight,\\n padding,\\n cols,\\n rows,\\n availableWidth: containerWidth - padding * 2,\\n availableHeight: containerHeight - padding * 2\\n });\\n return {\\n fontSize,\\n fontFamily: currentSettings?.terminal.fontFamily || \'\\"Cascadia Code\\", \\"Fira Code\\", monospace\',\\n cols,\\n rows,\\n lineHeight: currentSettings?.terminal.lineHeight || 1.1,\\n cursorStyle: currentSettings?.terminal.cursorStyle || \\"block\\",\\n cursorBlink: currentSettings?.terminal.cursorBlink ?? true,\\n allowProposedApi: true,\\n scrollback: viewport.isSmall ? 1e3 : 5e3,\\n // Reduce scrollback on mobile for performance\\n fastScrollModifier: \\"ctrl\\",\\n smoothScrollDuration: viewport.isSmall ? 0 : 125\\n // Disable smooth scroll on mobile\\n };\\n}\\nfunction measureTerminal() {\\n console.log(\\"[Terminal.measureTerminal] Starting measurement:\\", {\\n hasBrowser: browser,\\n hasContainer: !!terminalContainer,\\n hasTerminal: !!terminal,\\n timestamp: (/* @__PURE__ */ new Date()).toISOString()\\n });\\n if (!browser || !terminalContainer || !terminal) {\\n console.warn(\\"[Terminal.measureTerminal] Missing required components, returning defaults\\");\\n return { cols: 80, rows: 24 };\\n }\\n try {\\n const rect = terminalContainer.getBoundingClientRect();\\n console.log(\\"[Terminal.measureTerminal] Container rect:\\", {\\n width: rect.width,\\n height: rect.height,\\n top: rect.top,\\n left: rect.left,\\n right: rect.right,\\n bottom: rect.bottom,\\n x: rect.x,\\n y: rect.y\\n });\\n if (rect.width === 0 || rect.height === 0) {\\n console.error(\\"[Terminal.measureTerminal] Container has zero dimensions!\\", {\\n rect,\\n containerDisplay: window.getComputedStyle(terminalContainer).display,\\n containerVisibility: window.getComputedStyle(terminalContainer).visibility,\\n containerOpacity: window.getComputedStyle(terminalContainer).opacity,\\n parentElement: terminalContainer.parentElement?.getBoundingClientRect()\\n });\\n return { cols: 80, rows: 24 };\\n }\\n if (terminal._core && terminal._core._renderService && terminal._core._renderService.dimensions) {\\n const dimensions = terminal._core._renderService.dimensions;\\n if (dimensions.actualCellWidth && dimensions.actualCellHeight) {\\n const charWidth2 = dimensions.actualCellWidth;\\n const charHeight2 = dimensions.actualCellHeight;\\n const terminalElement2 = terminalContainer.querySelector(\\".xterm\\");\\n let paddingLeft2 = 0, paddingRight2 = 0, paddingTop2 = 0, paddingBottom2 = 0;\\n if (terminalElement2) {\\n const computedStyle2 = window.getComputedStyle(terminalElement2);\\n paddingLeft2 = parseFloat(computedStyle2.paddingLeft) || 0;\\n paddingRight2 = parseFloat(computedStyle2.paddingRight) || 0;\\n paddingTop2 = parseFloat(computedStyle2.paddingTop) || 0;\\n paddingBottom2 = parseFloat(computedStyle2.paddingBottom) || 0;\\n }\\n const availableWidth2 = rect.width - paddingLeft2 - paddingRight2;\\n const availableHeight2 = rect.height - paddingTop2 - paddingBottom2;\\n const cols2 = Math.max(40, Math.floor(availableWidth2 / charWidth2));\\n const rows2 = Math.max(10, Math.floor(availableHeight2 / charHeight2));\\n console.log(\\"[Terminal] Using renderer dimensions:\\", {\\n actualCellWidth: charWidth2,\\n actualCellHeight: charHeight2,\\n availableWidth: availableWidth2,\\n availableHeight: availableHeight2,\\n cols: cols2,\\n rows: rows2\\n });\\n return { cols: cols2, rows: rows2 };\\n }\\n }\\n if (fitAddon) {\\n try {\\n const proposed = fitAddon.proposeDimensions();\\n if (proposed && proposed.cols && proposed.rows) {\\n const cols2 = Math.max(40, proposed.cols);\\n const rows2 = Math.max(10, proposed.rows);\\n console.log(\\"[Terminal] Using fitAddon.proposeDimensions:\\", {\\n proposedCols: proposed.cols,\\n proposedRows: proposed.rows,\\n cols: cols2,\\n rows: rows2\\n });\\n return { cols: cols2, rows: rows2 };\\n }\\n } catch (e) {\\n console.warn(\\"[Terminal] fitAddon.proposeDimensions failed:\\", e);\\n }\\n }\\n if (terminal._core && terminal._core._charSizeService) {\\n const charSizeService = terminal._core._charSizeService;\\n if (charSizeService.width && charSizeService.height) {\\n const charWidth2 = charSizeService.width;\\n const charHeight2 = charSizeService.height;\\n const terminalElement2 = terminalContainer.querySelector(\\".xterm\\");\\n let paddingLeft2 = 0, paddingRight2 = 0, paddingTop2 = 0, paddingBottom2 = 0;\\n if (terminalElement2) {\\n const computedStyle2 = window.getComputedStyle(terminalElement2);\\n paddingLeft2 = parseFloat(computedStyle2.paddingLeft) || 0;\\n paddingRight2 = parseFloat(computedStyle2.paddingRight) || 0;\\n paddingTop2 = parseFloat(computedStyle2.paddingTop) || 0;\\n paddingBottom2 = parseFloat(computedStyle2.paddingBottom) || 0;\\n }\\n const availableWidth2 = rect.width - paddingLeft2 - paddingRight2;\\n const availableHeight2 = rect.height - paddingTop2 - paddingBottom2;\\n const cols2 = Math.max(40, Math.floor(availableWidth2 / charWidth2));\\n const rows2 = Math.max(10, Math.floor(availableHeight2 / charHeight2));\\n console.log(\\"[Terminal] Using charSizeService dimensions:\\", {\\n charWidth: charWidth2,\\n charHeight: charHeight2,\\n availableWidth: availableWidth2,\\n availableHeight: availableHeight2,\\n cols: cols2,\\n rows: rows2\\n });\\n return { cols: cols2, rows: rows2 };\\n }\\n }\\n console.warn(\\"[Terminal] No xterm dimensions available, using manual measurement\\");\\n const terminalElement = terminalContainer.querySelector(\\".xterm\\");\\n if (!terminalElement) {\\n console.warn(\\"[Terminal] Terminal element not found, using rough estimates\\");\\n const fontSize = terminal.options.fontSize || 14;\\n const charWidth2 = fontSize * 0.55;\\n const lineHeight = fontSize * (terminal.options.lineHeight || 1.1);\\n const padding = 10;\\n const cols2 = Math.max(40, Math.floor((rect.width - padding * 2) / charWidth2));\\n const rows2 = Math.max(10, Math.floor((rect.height - padding * 2) / lineHeight));\\n return { cols: cols2, rows: rows2 };\\n }\\n const computedStyle = window.getComputedStyle(terminalElement);\\n const paddingLeft = parseFloat(computedStyle.paddingLeft) || 0;\\n const paddingRight = parseFloat(computedStyle.paddingRight) || 0;\\n const paddingTop = parseFloat(computedStyle.paddingTop) || 0;\\n const paddingBottom = parseFloat(computedStyle.paddingBottom) || 0;\\n const availableWidth = rect.width - paddingLeft - paddingRight;\\n const availableHeight = rect.height - paddingTop - paddingBottom;\\n const testElement = document.createElement(\\"div\\");\\n testElement.style.position = \\"absolute\\";\\n testElement.style.visibility = \\"hidden\\";\\n testElement.style.left = \\"-9999px\\";\\n testElement.style.fontFamily = terminal.options.fontFamily || \'\\"Cascadia Code\\", \\"Fira Code\\", monospace\';\\n testElement.style.fontSize = `${terminal.options.fontSize || 14}px`;\\n testElement.style.lineHeight = `${terminal.options.lineHeight || 1.2}`;\\n testElement.style.whiteSpace = \\"pre\\";\\n testElement.style.padding = \\"0\\";\\n testElement.style.margin = \\"0\\";\\n testElement.style.border = \\"none\\";\\n testElement.textContent = \\"0123456789\\";\\n document.body.appendChild(testElement);\\n const testRect = testElement.getBoundingClientRect();\\n const charWidth = testRect.width / 10;\\n const charHeight = testRect.height;\\n document.body.removeChild(testElement);\\n if (charWidth <= 0 || charHeight <= 0) {\\n console.error(\\"[Terminal] Invalid character measurements:\\", { charWidth, charHeight });\\n return { cols: 80, rows: 24 };\\n }\\n const cols = Math.max(40, Math.floor(availableWidth / charWidth));\\n const rows = Math.max(10, Math.floor(availableHeight / charHeight));\\n const maxCols = 300;\\n const maxRows = 100;\\n const finalCols = Math.min(cols, maxCols);\\n const finalRows = Math.min(rows, maxRows);\\n console.log(\\"[Terminal] Manual measurement dimensions:\\", {\\n containerWidth: rect.width,\\n containerHeight: rect.height,\\n availableWidth,\\n availableHeight,\\n charWidth,\\n charHeight,\\n cols: finalCols,\\n rows: finalRows\\n });\\n return { cols: finalCols, rows: finalRows };\\n } catch (error) {\\n console.error(\\"[Terminal.measureTerminal] Error during measurement:\\", {\\n error,\\n errorMessage: error?.message || \\"Unknown error\\",\\n errorStack: error?.stack || \\"\\",\\n