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.
- package/apps/desktop/package.json +1 -1
- package/apps/desktop/renderer/tabs.js +12 -1
- package/apps/desktop/resources/component.js +1 -1
- package/apps/desktop/styles.css +7 -1
- package/apps/desktop/terminal.html +38 -4
- package/bin/cli-subcommand.mjs +13 -3
- package/dist/component.js +1 -1
- package/dist/hj.js +1630 -0
- package/dist/index.js +47 -45
- package/dist/server.js +47 -45
- package/dist/test.js +847 -0
- package/package.json +9 -3
|
@@ -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.
|
|
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')
|
package/apps/desktop/styles.css
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
1209
|
-
|
|
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 =
|
|
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, '&').replace(/</g, '<').replace(/>/g, '>')
|
|
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
|
// ==========================================
|
package/bin/cli-subcommand.mjs
CHANGED
|
@@ -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
|
|
99
|
-
const
|
|
100
|
-
|
|
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] }),
|