haltija 1.2.2 → 1.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "haltija-desktop",
3
- "version": "1.2.2",
3
+ "version": "1.2.4",
4
4
  "description": "Haltija Desktop - God Mode Browser for AI Agents",
5
5
  "homepage": "https://github.com/tonioloewald/haltija",
6
6
  "author": {
@@ -150,13 +150,24 @@ export function renameTerminalTab(tab, name) {
150
150
  }
151
151
  }
152
152
 
153
+ // Track the last active content (non-terminal) tab so it stays visible
154
+ // behind terminal/agent overlays for screenshot/hj command support
155
+ let lastContentTabId = null
156
+
153
157
  export function activateTab(tabId) {
154
158
  const tab = tabs.find((t) => t.id === tabId)
155
159
  if (!tab) return
156
160
 
161
+ const isTerminalTab = tab.isTerminal || tab.url === 'terminal'
162
+ if (!isTerminalTab) lastContentTabId = tabId
163
+
157
164
  tabs.forEach((t) => {
158
165
  t.element.classList.remove('active')
159
- t.webview.classList.remove('active')
166
+ if (isTerminalTab && t.id === lastContentTabId) {
167
+ // Keep the last content webview visible behind the terminal iframe
168
+ } else {
169
+ t.webview.classList.remove('active')
170
+ }
160
171
  })
161
172
 
162
173
  tab.element.classList.add('active')
@@ -46,7 +46,7 @@
46
46
  });
47
47
 
48
48
  // src/version.ts
49
- var VERSION = "1.2.2";
49
+ var VERSION = "1.2.4";
50
50
 
51
51
  // src/text-selector.ts
52
52
  var TEXT_PSEUDO_RE = /:(?:text-is|has-text|text)\(/;
@@ -640,9 +640,15 @@ body {
640
640
  display: none;
641
641
  }
642
642
 
643
- #webview-container webview.active,
643
+ #webview-container webview.active {
644
+ display: flex;
645
+ z-index: 0;
646
+ }
647
+
644
648
  #webview-container .terminal-frame.active {
645
649
  display: flex;
650
+ z-index: 1;
651
+ opacity: 0.88;
646
652
  }
647
653
 
648
654
  #webview-container .terminal-frame {
@@ -1192,7 +1192,12 @@
1192
1192
  outputPreview.className = 'tool-output-preview'
1193
1193
  const lines = (output || '').split('\n')
1194
1194
  const previewText = lines.slice(0, 3).join('\n')
1195
- outputPreview.textContent = previewText + (lines.length > 3 ? `\n... (${lines.length} lines)` : '')
1195
+ const previewFull = previewText + (lines.length > 3 ? `\n... (${lines.length} lines)` : '')
1196
+ if (/\x1b\[/.test(previewFull)) {
1197
+ outputPreview.innerHTML = ansiToHtml(previewFull)
1198
+ } else {
1199
+ outputPreview.textContent = previewFull
1200
+ }
1196
1201
  card.appendChild(outputPreview)
1197
1202
 
1198
1203
  // Add full output to expandable body
@@ -1205,10 +1210,13 @@
1205
1210
  outputDiv.appendChild(outputLabel)
1206
1211
  const outputPre = document.createElement('pre')
1207
1212
  outputPre.style.cssText = 'margin: 0; white-space: pre-wrap;'
1208
- if (lines.length > 20) {
1209
- outputPre.textContent = lines.slice(0, 20).join('\n') + `\n... (${lines.length} lines total)`
1213
+ const fullText = lines.length > 20
1214
+ ? lines.slice(0, 20).join('\n') + `\n... (${lines.length} lines total)`
1215
+ : (output || '')
1216
+ if (/\x1b\[/.test(fullText)) {
1217
+ outputPre.innerHTML = ansiToHtml(fullText)
1210
1218
  } else {
1211
- outputPre.textContent = output || ''
1219
+ outputPre.textContent = fullText
1212
1220
  }
1213
1221
  outputDiv.appendChild(outputPre)
1214
1222
  body.appendChild(outputDiv)
@@ -1277,6 +1285,8 @@
1277
1285
  div.textContent = text
1278
1286
  } else if (type === 'summary') {
1279
1287
  div.textContent = text
1288
+ } else if (/\x1b\[/.test(text)) {
1289
+ div.innerHTML = ansiToHtml(text)
1280
1290
  } else {
1281
1291
  div.textContent = text
1282
1292
  }
@@ -1296,6 +1306,30 @@
1296
1306
  return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')
1297
1307
  }
1298
1308
 
1309
+ /** Convert ANSI escape codes to HTML spans */
1310
+ function ansiToHtml(str) {
1311
+ if (str == null) return ''
1312
+ const escaped = escapeHtml(str)
1313
+ // Map SGR codes to CSS styles
1314
+ const styles = {
1315
+ '1': 'font-weight:bold',
1316
+ '2': 'opacity:0.6',
1317
+ '3': 'font-style:italic',
1318
+ '4': 'text-decoration:underline',
1319
+ '31': 'color:#f87171', '32': 'color:#4ade80', '33': 'color:#fbbf24',
1320
+ '34': 'color:#60a5fa', '35': 'color:#c084fc', '36': 'color:#22d3ee',
1321
+ '90': 'color:#6b7280', '91': 'color:#f87171', '92': 'color:#4ade80',
1322
+ '93': 'color:#fbbf24', '94': 'color:#60a5fa', '95': 'color:#c084fc',
1323
+ '96': 'color:#22d3ee',
1324
+ }
1325
+ // Replace \e[...m sequences with styled spans
1326
+ return escaped.replace(/\x1b\[([0-9;]*)m/g, (_, codes) => {
1327
+ if (!codes || codes === '0') return '</span>'
1328
+ const css = codes.split(';').map(c => styles[c] || '').filter(Boolean).join(';')
1329
+ return css ? `<span style="${css}">` : ''
1330
+ })
1331
+ }
1332
+
1299
1333
  // ==========================================
1300
1334
  // Init
1301
1335
  // ==========================================
@@ -95,9 +95,19 @@ export const ARG_MAPS = {
95
95
  call: (args) => ({ ...parseTargetArgs(args.slice(0, 1)), method: args[1], args: args.slice(2).map(tryParseJSON) }),
96
96
  fetch: (args) => ({ url: args[0], prompt: args.slice(1).join(' ') || undefined }),
97
97
  screenshot: (args) => {
98
- const dataUrl = args.includes('--data-url')
99
- const filtered = args.filter(a => a !== '--data-url')
100
- return { ...parseTargetArgs(filtered), file: !dataUrl }
98
+ const body = { file: true }
99
+ const positional = []
100
+ for (let i = 0; i < args.length; i++) {
101
+ const a = args[i]
102
+ if (a === '--data-url') { body.file = false; continue }
103
+ if (a === '--scale') { body.scale = num(args[++i]); continue }
104
+ if (a === '--maxWidth' || a === '--max-width') { body.maxWidth = num(args[++i]); continue }
105
+ if (a === '--maxHeight' || a === '--max-height') { body.maxHeight = num(args[++i]); continue }
106
+ if (a === '--delay') { body.delay = num(args[++i]); continue }
107
+ if (a === '--no-chyron') { body.chyron = false; continue }
108
+ if (!a.startsWith('-')) { positional.push(a) }
109
+ }
110
+ return { ...body, ...parseTargetArgs(positional) }
101
111
  },
102
112
  snapshot: (args) => ({ context: args.join(' ') || undefined }),
103
113
  select: (args) => ({ action: args[0] }),
package/dist/component.js CHANGED
@@ -46,7 +46,7 @@
46
46
  });
47
47
 
48
48
  // src/version.ts
49
- var VERSION = "1.2.2";
49
+ var VERSION = "1.2.4";
50
50
 
51
51
  // src/text-selector.ts
52
52
  var TEXT_PSEUDO_RE = /:(?:text-is|has-text|text)\(/;