claude-pager 0.3.21 → 0.3.24
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/dist/channels/ntfy/provider.d.ts.map +1 -1
- package/dist/channels/ntfy/provider.js +11 -2
- package/dist/channels/ntfy/provider.js.map +1 -1
- package/dist/channels/telegram/provider.d.ts.map +1 -1
- package/dist/channels/telegram/provider.js +35 -10
- package/dist/channels/telegram/provider.js.map +1 -1
- package/dist/daemon/__tests__/server.test.js +27 -1
- package/dist/daemon/__tests__/server.test.js.map +1 -1
- package/dist/daemon/server.d.ts.map +1 -1
- package/dist/daemon/server.js +24 -4
- package/dist/daemon/server.js.map +1 -1
- package/dist/daemon/terminal.d.ts +2 -0
- package/dist/daemon/terminal.d.ts.map +1 -1
- package/dist/daemon/terminal.js +22 -0
- package/dist/daemon/terminal.js.map +1 -1
- package/dist/dashboard/html.d.ts +1 -1
- package/dist/dashboard/html.d.ts.map +1 -1
- package/dist/dashboard/html.js +269 -22
- package/dist/dashboard/html.js.map +1 -1
- package/dist/utils/__tests__/ask-user-question.test.d.ts +2 -0
- package/dist/utils/__tests__/ask-user-question.test.d.ts.map +1 -0
- package/dist/utils/__tests__/ask-user-question.test.js +75 -0
- package/dist/utils/__tests__/ask-user-question.test.js.map +1 -0
- package/dist/utils/ask-user-question.d.ts +13 -0
- package/dist/utils/ask-user-question.d.ts.map +1 -0
- package/dist/utils/ask-user-question.js +65 -0
- package/dist/utils/ask-user-question.js.map +1 -0
- package/package.json +1 -1
package/dist/dashboard/html.js
CHANGED
|
@@ -131,6 +131,19 @@ exports.DASHBOARD_HTML = `<!DOCTYPE html>
|
|
|
131
131
|
|
|
132
132
|
.dismiss-btn:hover { opacity: 0.8; color: #f85149; }
|
|
133
133
|
|
|
134
|
+
.sound-btn {
|
|
135
|
+
background: none;
|
|
136
|
+
border: none;
|
|
137
|
+
cursor: pointer;
|
|
138
|
+
font-size: 16px;
|
|
139
|
+
opacity: 0.7;
|
|
140
|
+
transition: opacity 0.2s, transform 0.1s;
|
|
141
|
+
padding: 2px 6px;
|
|
142
|
+
}
|
|
143
|
+
.sound-btn:hover { opacity: 1; }
|
|
144
|
+
.sound-btn:active { transform: scale(0.92); }
|
|
145
|
+
.sound-btn.muted { opacity: 0.35; }
|
|
146
|
+
|
|
134
147
|
.ci-row {
|
|
135
148
|
display: flex;
|
|
136
149
|
gap: 12px;
|
|
@@ -310,6 +323,31 @@ exports.DASHBOARD_HTML = `<!DOCTYPE html>
|
|
|
310
323
|
float: right;
|
|
311
324
|
}
|
|
312
325
|
|
|
326
|
+
.aq-warning {
|
|
327
|
+
background: #2a1810;
|
|
328
|
+
border: 1px solid #5a2a02;
|
|
329
|
+
border-radius: 4px;
|
|
330
|
+
color: #f0883e;
|
|
331
|
+
font-size: 11px;
|
|
332
|
+
padding: 6px 8px;
|
|
333
|
+
margin: 6px 0 8px;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
.aq-list { font-size: 12px; color: #c9d1d9; max-height: 260px; overflow-y: auto; }
|
|
337
|
+
.aq-question { margin: 6px 0; padding: 6px 8px; background: #0d1117; border-radius: 4px; }
|
|
338
|
+
.aq-header { color: #58a6ff; font-weight: 600; font-size: 11px; text-transform: uppercase; letter-spacing: 0.4px; margin-bottom: 3px; }
|
|
339
|
+
.aq-q { color: #f0f6fc; font-weight: 600; margin-bottom: 4px; }
|
|
340
|
+
.aq-options { list-style: none; padding: 0; margin: 0; }
|
|
341
|
+
.aq-options li { padding: 2px 0; }
|
|
342
|
+
.aq-opt-label { color: #c9d1d9; font-weight: 600; }
|
|
343
|
+
.aq-opt-desc { color: #8b949e; }
|
|
344
|
+
|
|
345
|
+
.action-btn.aq-allow {
|
|
346
|
+
background: #0d419d;
|
|
347
|
+
color: #cbe2ff;
|
|
348
|
+
}
|
|
349
|
+
.action-btn.aq-allow:hover { background: #1158c7; }
|
|
350
|
+
|
|
313
351
|
.action-row {
|
|
314
352
|
display: flex;
|
|
315
353
|
gap: 8px;
|
|
@@ -573,6 +611,30 @@ exports.DASHBOARD_HTML = `<!DOCTYPE html>
|
|
|
573
611
|
.term-body { flex: 1; min-height: 0; padding: 8px; }
|
|
574
612
|
.term-body .xterm { height: 100%; }
|
|
575
613
|
|
|
614
|
+
.term-keys-row {
|
|
615
|
+
display: flex;
|
|
616
|
+
gap: 6px;
|
|
617
|
+
padding: 8px 14px;
|
|
618
|
+
border-top: 1px solid #21262d;
|
|
619
|
+
flex-wrap: wrap;
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
.term-key-btn {
|
|
623
|
+
background: #161b22;
|
|
624
|
+
border: 1px solid #30363d;
|
|
625
|
+
border-radius: 4px;
|
|
626
|
+
color: #c9d1d9;
|
|
627
|
+
font-family: 'JetBrains Mono', monospace;
|
|
628
|
+
font-size: 11px;
|
|
629
|
+
padding: 3px 8px;
|
|
630
|
+
cursor: pointer;
|
|
631
|
+
min-width: 28px;
|
|
632
|
+
transition: background 0.15s, border-color 0.15s;
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
.term-key-btn:hover { background: #21262d; border-color: #58a6ff; }
|
|
636
|
+
.term-key-btn:active { background: #0d419d; }
|
|
637
|
+
|
|
576
638
|
.term-input-row {
|
|
577
639
|
display: flex;
|
|
578
640
|
gap: 8px;
|
|
@@ -755,6 +817,7 @@ exports.DASHBOARD_HTML = `<!DOCTYPE html>
|
|
|
755
817
|
</div>
|
|
756
818
|
<div class="meta">
|
|
757
819
|
<button class="action-btn allow-all" id="allowAllBtn" style="display:none" onclick="allowAll()">Allow All</button>
|
|
820
|
+
<button class="sound-btn" id="soundBtn" onclick="toggleSound()" title="Toggle notification sound">🔔</button>
|
|
758
821
|
<span class="status-dot connected" id="statusDot"></span>
|
|
759
822
|
<span id="lastUpdate">connecting...</span>
|
|
760
823
|
</div>
|
|
@@ -851,6 +914,65 @@ exports.DASHBOARD_HTML = `<!DOCTYPE html>
|
|
|
851
914
|
return '<pre style="font-size:10px;color:#8b949e;word-break:break-all;white-space:pre-wrap;margin:4px 0;max-height:200px;overflow-y:auto">' + escapeHtml(input.slice(0, 3000)) + '</pre>';
|
|
852
915
|
}
|
|
853
916
|
|
|
917
|
+
function parseAskUserQuestion(toolInput) {
|
|
918
|
+
try {
|
|
919
|
+
const obj = typeof toolInput === 'string' ? JSON.parse(toolInput) : toolInput;
|
|
920
|
+
if (!obj || !Array.isArray(obj.questions)) return null;
|
|
921
|
+
return obj.questions.map(q => ({
|
|
922
|
+
header: q.header || '',
|
|
923
|
+
question: q.question || '',
|
|
924
|
+
options: Array.isArray(q.options)
|
|
925
|
+
? q.options.map(o => ({ label: o.label || '', description: o.description || '' }))
|
|
926
|
+
: [],
|
|
927
|
+
}));
|
|
928
|
+
} catch { return null; }
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
function renderAskUser(questions) {
|
|
932
|
+
return '<div class="aq-list">' + questions.map((q, i) => {
|
|
933
|
+
const head = q.header ? '<div class="aq-header">' + escapeHtml(q.header) + '</div>' : '';
|
|
934
|
+
const opts = q.options.map((o, j) =>
|
|
935
|
+
'<li><span class="aq-opt-label">' + escapeHtml(o.label) + '</span>'
|
|
936
|
+
+ (o.description ? '<span class="aq-opt-desc"> — ' + escapeHtml(o.description.slice(0, 200)) + (o.description.length > 200 ? '…' : '') + '</span>' : '')
|
|
937
|
+
+ '</li>'
|
|
938
|
+
).join('');
|
|
939
|
+
return '<div class="aq-question">'
|
|
940
|
+
+ head
|
|
941
|
+
+ '<div class="aq-q">' + escapeHtml(q.question) + '</div>'
|
|
942
|
+
+ (opts ? '<ul class="aq-options">' + opts + '</ul>' : '')
|
|
943
|
+
+ '</div>';
|
|
944
|
+
}).join('') + '</div>';
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
async function openAskUserPicker(eventId, sessionId, pane, btn) {
|
|
948
|
+
if (btn) btn.disabled = true;
|
|
949
|
+
try {
|
|
950
|
+
showToast(btn, 'Allow envoyé…', false);
|
|
951
|
+
// Allow the AskUserQuestion tool so Claude renders the picker in tmux.
|
|
952
|
+
// We tell the user *exactly* this happened so the action is never
|
|
953
|
+
// mistaken for picking an option.
|
|
954
|
+
const res = await fetch('/api/v1/respond-to', {
|
|
955
|
+
method: 'POST',
|
|
956
|
+
headers: { 'Content-Type': 'application/json' },
|
|
957
|
+
body: JSON.stringify({ eventId, response: 'allow' }),
|
|
958
|
+
});
|
|
959
|
+
if (!res.ok) {
|
|
960
|
+
let msg = 'Allow failed';
|
|
961
|
+
try { msg = (await res.json()).error || msg; } catch {}
|
|
962
|
+
showToast(btn, msg, true);
|
|
963
|
+
if (btn) btn.disabled = false;
|
|
964
|
+
return;
|
|
965
|
+
}
|
|
966
|
+
// Give the picker a moment to render, then open the terminal modal so
|
|
967
|
+
// the user can navigate with the arrow keys + Enter.
|
|
968
|
+
setTimeout(() => openTerminal(sessionId, pane), 400);
|
|
969
|
+
} catch (e) {
|
|
970
|
+
console.error('openAskUserPicker error:', e);
|
|
971
|
+
showToast(btn, 'Allow error: ' + e, true);
|
|
972
|
+
}
|
|
973
|
+
if (btn) btn.disabled = false;
|
|
974
|
+
}
|
|
975
|
+
|
|
854
976
|
function stateLabel(state) {
|
|
855
977
|
const labels = {
|
|
856
978
|
working: 'Working',
|
|
@@ -876,28 +998,52 @@ exports.DASHBOARD_HTML = `<!DOCTYPE html>
|
|
|
876
998
|
const contextInfo = q.context
|
|
877
999
|
? '<div style="font-size:11px;color:#c9d1d9;margin-bottom:6px;white-space:pre-wrap">' + escapeHtml(q.context.slice(-300)) + '</div>'
|
|
878
1000
|
: '';
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
<
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
1001
|
+
|
|
1002
|
+
// Special-case AskUserQuestion: this Claude Code tool opens an
|
|
1003
|
+
// interactive multi-question picker in the terminal. Allow only
|
|
1004
|
+
// *opens* the picker (does NOT pick an option) — clicking what looks
|
|
1005
|
+
// like an answer button would mislead the user. Render the questions
|
|
1006
|
+
// for context and route the user to the terminal modal to navigate.
|
|
1007
|
+
const askUser = (q.toolName === 'AskUserQuestion' && q.toolInput)
|
|
1008
|
+
? parseAskUserQuestion(q.toolInput) : null;
|
|
1009
|
+
|
|
1010
|
+
if (askUser && s.tmuxPane) {
|
|
1011
|
+
pending = \`
|
|
1012
|
+
<div class="pending-box">
|
|
1013
|
+
<span class="ago">\${timeAgo(Date.now() - q.agoSeconds * 1000)}</span>
|
|
1014
|
+
\${contextInfo}
|
|
1015
|
+
<div class="aq-warning">⚠ Question interactive — Allow ouvre le picker mais ne répond pas. Utilise le terminal pour naviguer.</div>
|
|
1016
|
+
\${renderAskUser(askUser)}
|
|
1017
|
+
<div class="action-row">
|
|
1018
|
+
<button class="action-btn aq-allow" onclick="openAskUserPicker('\${q.eventId}','\${s.sessionId}','\${s.tmuxPane}', this)" title="Autorise le tool AskUserQuestion, puis ouvre la modal terminal pour naviguer le picker">📟 Allow + ouvrir le terminal</button>
|
|
1019
|
+
<button class="action-btn deny" onclick="respondTo('\${q.eventId}', 'deny', this)">✗ Deny</button>
|
|
1020
|
+
</div>
|
|
1021
|
+
</div>
|
|
1022
|
+
\`;
|
|
1023
|
+
} else {
|
|
1024
|
+
const toolInfo = q.toolName
|
|
1025
|
+
? contextInfo + '<span class="tool">' + escapeHtml(q.toolName) + '</span>' +
|
|
1026
|
+
(q.toolInput ? '<br>' + formatToolInput(q.toolInput) : '')
|
|
1027
|
+
: '<div class="prompt-msg" style="font-size:12px;color:#c9d1d9;white-space:pre-wrap;max-height:240px;overflow-y:auto">' + escapeHtml(q.message) + '</div>';
|
|
1028
|
+
|
|
1029
|
+
const actions = isPermission
|
|
1030
|
+
? \`<div class="action-row">
|
|
1031
|
+
<button class="action-btn allow" onclick="respondTo('\${q.eventId}', 'allow', this)">✓ Allow</button>
|
|
1032
|
+
<button class="action-btn deny" onclick="respondTo('\${q.eventId}', 'deny', this)">✗ Deny</button>
|
|
1033
|
+
</div>\`
|
|
1034
|
+
: \`<div class="action-row" style="align-items:center">
|
|
1035
|
+
<input type="text" class="reply-input" id="reply-\${q.eventId}" placeholder="Type a reply..." onkeydown="if(event.key==='Enter')respondTo('\${q.eventId}',this.value,this)">
|
|
1036
|
+
<button class="action-btn allow" onclick="respondTo('\${q.eventId}',document.getElementById('reply-\${q.eventId}').value,this)">Send</button>
|
|
1037
|
+
</div>\`;
|
|
1038
|
+
|
|
1039
|
+
pending = \`
|
|
1040
|
+
<div class="pending-box">
|
|
1041
|
+
<span class="ago">\${timeAgo(Date.now() - q.agoSeconds * 1000)}</span>
|
|
1042
|
+
\${toolInfo}
|
|
1043
|
+
\${actions}
|
|
1044
|
+
</div>
|
|
1045
|
+
\`;
|
|
1046
|
+
}
|
|
901
1047
|
}
|
|
902
1048
|
|
|
903
1049
|
const hasGit = s.git.branch !== 'unknown';
|
|
@@ -1064,6 +1210,7 @@ exports.DASHBOARD_HTML = `<!DOCTYPE html>
|
|
|
1064
1210
|
}
|
|
1065
1211
|
|
|
1066
1212
|
function render(data) {
|
|
1213
|
+
detectNewPending(data);
|
|
1067
1214
|
const container = document.getElementById('projects');
|
|
1068
1215
|
if (!data.projects || data.projects.length === 0) {
|
|
1069
1216
|
container.innerHTML = \`
|
|
@@ -1404,6 +1551,77 @@ exports.DASHBOARD_HTML = `<!DOCTYPE html>
|
|
|
1404
1551
|
fetchDashboard();
|
|
1405
1552
|
}
|
|
1406
1553
|
|
|
1554
|
+
// --- Notification sound ---
|
|
1555
|
+
// Tracks pending event ids we already showed; new ones trigger the ding.
|
|
1556
|
+
// First render seeds the set without sounding so a page reload doesn't
|
|
1557
|
+
// beep for prompts that were already pending.
|
|
1558
|
+
let soundEnabled = localStorage.getItem('soundEnabled') !== 'false';
|
|
1559
|
+
let audioCtx = null;
|
|
1560
|
+
let seenEventIds = new Set();
|
|
1561
|
+
let firstSoundCheck = true;
|
|
1562
|
+
|
|
1563
|
+
function updateSoundBtn() {
|
|
1564
|
+
const btn = document.getElementById('soundBtn');
|
|
1565
|
+
if (!btn) return;
|
|
1566
|
+
btn.textContent = soundEnabled ? '🔔' : '🔕';
|
|
1567
|
+
btn.classList.toggle('muted', !soundEnabled);
|
|
1568
|
+
}
|
|
1569
|
+
|
|
1570
|
+
function initAudio() {
|
|
1571
|
+
if (audioCtx) return;
|
|
1572
|
+
try { audioCtx = new (window.AudioContext || window.webkitAudioContext)(); } catch {}
|
|
1573
|
+
}
|
|
1574
|
+
|
|
1575
|
+
function playNotificationSound() {
|
|
1576
|
+
if (!soundEnabled) return;
|
|
1577
|
+
initAudio();
|
|
1578
|
+
if (!audioCtx) return;
|
|
1579
|
+
if (audioCtx.state === 'suspended') audioCtx.resume();
|
|
1580
|
+
const t0 = audioCtx.currentTime;
|
|
1581
|
+
// Two-note ding: E5 then C5, sine wave with a soft attack + decay so
|
|
1582
|
+
// it doesn't pop. Quiet (peak 0.18) — meant to be noticed, not jarring.
|
|
1583
|
+
[659.25, 523.25].forEach((freq, i) => {
|
|
1584
|
+
const start = t0 + i * 0.13;
|
|
1585
|
+
const osc = audioCtx.createOscillator();
|
|
1586
|
+
const gain = audioCtx.createGain();
|
|
1587
|
+
osc.type = 'sine';
|
|
1588
|
+
osc.frequency.value = freq;
|
|
1589
|
+
gain.gain.setValueAtTime(0.0001, start);
|
|
1590
|
+
gain.gain.exponentialRampToValueAtTime(0.18, start + 0.02);
|
|
1591
|
+
gain.gain.exponentialRampToValueAtTime(0.0001, start + 0.22);
|
|
1592
|
+
osc.connect(gain);
|
|
1593
|
+
gain.connect(audioCtx.destination);
|
|
1594
|
+
osc.start(start);
|
|
1595
|
+
osc.stop(start + 0.25);
|
|
1596
|
+
});
|
|
1597
|
+
}
|
|
1598
|
+
|
|
1599
|
+
function toggleSound() {
|
|
1600
|
+
initAudio();
|
|
1601
|
+
soundEnabled = !soundEnabled;
|
|
1602
|
+
localStorage.setItem('soundEnabled', String(soundEnabled));
|
|
1603
|
+
updateSoundBtn();
|
|
1604
|
+
if (soundEnabled) playNotificationSound(); // sample so the user hears what they enabled
|
|
1605
|
+
}
|
|
1606
|
+
|
|
1607
|
+
function detectNewPending(data) {
|
|
1608
|
+
const current = new Set();
|
|
1609
|
+
if (data && Array.isArray(data.projects)) {
|
|
1610
|
+
for (const p of data.projects) {
|
|
1611
|
+
for (const s of (p.sessions || [])) {
|
|
1612
|
+
if (s.pendingQuestion && s.pendingQuestion.eventId) current.add(s.pendingQuestion.eventId);
|
|
1613
|
+
}
|
|
1614
|
+
}
|
|
1615
|
+
}
|
|
1616
|
+
if (!firstSoundCheck) {
|
|
1617
|
+
for (const id of current) {
|
|
1618
|
+
if (!seenEventIds.has(id)) { playNotificationSound(); break; }
|
|
1619
|
+
}
|
|
1620
|
+
}
|
|
1621
|
+
seenEventIds = current;
|
|
1622
|
+
firstSoundCheck = false;
|
|
1623
|
+
}
|
|
1624
|
+
|
|
1407
1625
|
// --- Terminal view ---
|
|
1408
1626
|
let termState = null; // { overlay, term, sessionId, pollTimer }
|
|
1409
1627
|
|
|
@@ -1412,6 +1630,8 @@ exports.DASHBOARD_HTML = `<!DOCTYPE html>
|
|
|
1412
1630
|
|
|
1413
1631
|
const overlay = document.createElement('div');
|
|
1414
1632
|
overlay.className = 'term-overlay';
|
|
1633
|
+
const keyBtn = (label, k) =>
|
|
1634
|
+
'<button class="term-key-btn" data-key="' + k + '" title="Send ' + k + '">' + label + '</button>';
|
|
1415
1635
|
overlay.innerHTML =
|
|
1416
1636
|
'<div class="term-modal">'
|
|
1417
1637
|
+ '<div class="term-head">'
|
|
@@ -1420,6 +1640,11 @@ exports.DASHBOARD_HTML = `<!DOCTYPE html>
|
|
|
1420
1640
|
+ '<button class="term-close" title="Close">✕</button>'
|
|
1421
1641
|
+ '</div>'
|
|
1422
1642
|
+ '<div class="term-body"><div class="term-xterm"></div></div>'
|
|
1643
|
+
+ '<div class="term-keys-row">'
|
|
1644
|
+
+ keyBtn('↑', 'Up') + keyBtn('↓', 'Down') + keyBtn('←', 'Left') + keyBtn('→', 'Right')
|
|
1645
|
+
+ keyBtn('⏎', 'Enter') + keyBtn('Esc', 'Escape') + keyBtn('Tab', 'Tab')
|
|
1646
|
+
+ keyBtn('⌫', 'BSpace') + keyBtn('^C', 'C-c')
|
|
1647
|
+
+ '</div>'
|
|
1423
1648
|
+ '<div class="term-input-row">'
|
|
1424
1649
|
+ '<input type="text" class="term-send" placeholder="Type and press Enter to send to the session...">'
|
|
1425
1650
|
+ '</div>'
|
|
@@ -1452,6 +1677,14 @@ exports.DASHBOARD_HTML = `<!DOCTYPE html>
|
|
|
1452
1677
|
};
|
|
1453
1678
|
sendInput.focus();
|
|
1454
1679
|
|
|
1680
|
+
overlay.querySelectorAll('.term-key-btn').forEach(btn => {
|
|
1681
|
+
btn.onclick = (e) => {
|
|
1682
|
+
e.preventDefault();
|
|
1683
|
+
sendTerminalSpecialKey(sessionId, btn.dataset.key);
|
|
1684
|
+
sendInput.focus();
|
|
1685
|
+
};
|
|
1686
|
+
});
|
|
1687
|
+
|
|
1455
1688
|
await refreshTerminal();
|
|
1456
1689
|
termState.pollTimer = setInterval(refreshTerminal, 2000);
|
|
1457
1690
|
}
|
|
@@ -1495,6 +1728,19 @@ exports.DASHBOARD_HTML = `<!DOCTYPE html>
|
|
|
1495
1728
|
}
|
|
1496
1729
|
}
|
|
1497
1730
|
|
|
1731
|
+
async function sendTerminalSpecialKey(sessionId, key) {
|
|
1732
|
+
try {
|
|
1733
|
+
await fetch('/api/v1/session/' + sessionId + '/keys', {
|
|
1734
|
+
method: 'POST',
|
|
1735
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1736
|
+
body: JSON.stringify({ key }),
|
|
1737
|
+
});
|
|
1738
|
+
setTimeout(refreshTerminal, 150);
|
|
1739
|
+
} catch (e) {
|
|
1740
|
+
console.error('terminal special-key error:', e);
|
|
1741
|
+
}
|
|
1742
|
+
}
|
|
1743
|
+
|
|
1498
1744
|
async function fetchDashboard() {
|
|
1499
1745
|
try {
|
|
1500
1746
|
const res = await fetch('/api/v1/dashboard');
|
|
@@ -1508,6 +1754,7 @@ exports.DASHBOARD_HTML = `<!DOCTYPE html>
|
|
|
1508
1754
|
}
|
|
1509
1755
|
}
|
|
1510
1756
|
|
|
1757
|
+
updateSoundBtn();
|
|
1511
1758
|
fetchDashboard();
|
|
1512
1759
|
|
|
1513
1760
|
// SSE for instant push — polling as fallback
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"html.js","sourceRoot":"","sources":["../../src/dashboard/html.ts"],"names":[],"mappings":";;;AAAa,QAAA,cAAc,GAAG
|
|
1
|
+
{"version":3,"file":"html.js","sourceRoot":"","sources":["../../src/dashboard/html.ts"],"names":[],"mappings":";;;AAAa,QAAA,cAAc,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA+uDtB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ask-user-question.test.d.ts","sourceRoot":"","sources":["../../../src/utils/__tests__/ask-user-question.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const node_test_1 = require("node:test");
|
|
7
|
+
const strict_1 = __importDefault(require("node:assert/strict"));
|
|
8
|
+
const ask_user_question_js_1 = require("../ask-user-question.js");
|
|
9
|
+
const sample = JSON.stringify({
|
|
10
|
+
questions: [
|
|
11
|
+
{
|
|
12
|
+
header: 'Modèle de zone AAR',
|
|
13
|
+
question: 'Comment modéliser une zone de ravitaillement en base ?',
|
|
14
|
+
options: [
|
|
15
|
+
{ label: 'Entité dédiée RefuelingZone', description: 'Nouvelle entité' },
|
|
16
|
+
{ label: 'Étendre Zone existante', description: 'Ajout zoneType=AAR' },
|
|
17
|
+
],
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
header: 'Propriété',
|
|
21
|
+
question: 'Qui possède la zone ?',
|
|
22
|
+
options: [
|
|
23
|
+
{ label: 'Théâtre' },
|
|
24
|
+
{ label: 'Mission' },
|
|
25
|
+
],
|
|
26
|
+
},
|
|
27
|
+
],
|
|
28
|
+
});
|
|
29
|
+
(0, node_test_1.describe)('AskUserQuestion utils', () => {
|
|
30
|
+
(0, node_test_1.it)('detects the tool name', () => {
|
|
31
|
+
strict_1.default.equal((0, ask_user_question_js_1.isAskUserQuestion)('AskUserQuestion'), true);
|
|
32
|
+
strict_1.default.equal((0, ask_user_question_js_1.isAskUserQuestion)('Bash'), false);
|
|
33
|
+
strict_1.default.equal((0, ask_user_question_js_1.isAskUserQuestion)(undefined), false);
|
|
34
|
+
});
|
|
35
|
+
(0, node_test_1.it)('parses well-formed input', () => {
|
|
36
|
+
const out = (0, ask_user_question_js_1.parseAskUserQuestion)(sample);
|
|
37
|
+
strict_1.default.ok(out);
|
|
38
|
+
strict_1.default.equal(out.length, 2);
|
|
39
|
+
strict_1.default.equal(out[0].header, 'Modèle de zone AAR');
|
|
40
|
+
strict_1.default.equal(out[0].options.length, 2);
|
|
41
|
+
strict_1.default.equal(out[0].options[0].label, 'Entité dédiée RefuelingZone');
|
|
42
|
+
strict_1.default.equal(out[1].options[0].description, undefined);
|
|
43
|
+
});
|
|
44
|
+
(0, node_test_1.it)('returns null on garbage', () => {
|
|
45
|
+
strict_1.default.equal((0, ask_user_question_js_1.parseAskUserQuestion)(undefined), null);
|
|
46
|
+
strict_1.default.equal((0, ask_user_question_js_1.parseAskUserQuestion)(''), null);
|
|
47
|
+
strict_1.default.equal((0, ask_user_question_js_1.parseAskUserQuestion)('not json'), null);
|
|
48
|
+
strict_1.default.equal((0, ask_user_question_js_1.parseAskUserQuestion)('{}'), null);
|
|
49
|
+
strict_1.default.equal((0, ask_user_question_js_1.parseAskUserQuestion)('{"questions": "nope"}'), null);
|
|
50
|
+
});
|
|
51
|
+
(0, node_test_1.it)('drops entries with no question text', () => {
|
|
52
|
+
const out = (0, ask_user_question_js_1.parseAskUserQuestion)(JSON.stringify({
|
|
53
|
+
questions: [{ options: [] }, { question: 'real one', options: [] }],
|
|
54
|
+
}));
|
|
55
|
+
strict_1.default.equal(out.length, 1);
|
|
56
|
+
strict_1.default.equal(out[0].question, 'real one');
|
|
57
|
+
});
|
|
58
|
+
(0, node_test_1.it)('formats text rendering with caps', () => {
|
|
59
|
+
const out = (0, ask_user_question_js_1.parseAskUserQuestion)(sample);
|
|
60
|
+
const text = (0, ask_user_question_js_1.formatAskUserQuestionText)(out, 1000);
|
|
61
|
+
strict_1.default.match(text, /Q1\. Comment/);
|
|
62
|
+
strict_1.default.match(text, /\[Modèle de zone AAR\]/);
|
|
63
|
+
strict_1.default.match(text, /1\) Entité dédiée/);
|
|
64
|
+
strict_1.default.match(text, /Q2\. Qui possède/);
|
|
65
|
+
});
|
|
66
|
+
(0, node_test_1.it)('truncates long descriptions', () => {
|
|
67
|
+
const long = 'A'.repeat(500);
|
|
68
|
+
const input = JSON.stringify({ questions: [{ question: 'q', options: [{ label: 'l', description: long }] }] });
|
|
69
|
+
const out = (0, ask_user_question_js_1.parseAskUserQuestion)(input);
|
|
70
|
+
const text = (0, ask_user_question_js_1.formatAskUserQuestionText)(out, 50);
|
|
71
|
+
strict_1.default.match(text, /AAAA…/);
|
|
72
|
+
strict_1.default.ok(!text.includes(long));
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
//# sourceMappingURL=ask-user-question.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ask-user-question.test.js","sourceRoot":"","sources":["../../../src/utils/__tests__/ask-user-question.test.ts"],"names":[],"mappings":";;;;;AAAA,yCAAyC;AACzC,gEAAwC;AACxC,kEAA6G;AAE7G,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC;IAC5B,SAAS,EAAE;QACT;YACE,MAAM,EAAE,oBAAoB;YAC5B,QAAQ,EAAE,wDAAwD;YAClE,OAAO,EAAE;gBACP,EAAE,KAAK,EAAE,6BAA6B,EAAE,WAAW,EAAE,iBAAiB,EAAE;gBACxE,EAAE,KAAK,EAAE,wBAAwB,EAAE,WAAW,EAAE,oBAAoB,EAAE;aACvE;SACF;QACD;YACE,MAAM,EAAE,WAAW;YACnB,QAAQ,EAAE,uBAAuB;YACjC,OAAO,EAAE;gBACP,EAAE,KAAK,EAAE,SAAS,EAAE;gBACpB,EAAE,KAAK,EAAE,SAAS,EAAE;aACrB;SACF;KACF;CACF,CAAC,CAAC;AAEH,IAAA,oBAAQ,EAAC,uBAAuB,EAAE,GAAG,EAAE;IACrC,IAAA,cAAE,EAAC,uBAAuB,EAAE,GAAG,EAAE;QAC/B,gBAAM,CAAC,KAAK,CAAC,IAAA,wCAAiB,EAAC,iBAAiB,CAAC,EAAE,IAAI,CAAC,CAAC;QACzD,gBAAM,CAAC,KAAK,CAAC,IAAA,wCAAiB,EAAC,MAAM,CAAC,EAAE,KAAK,CAAC,CAAC;QAC/C,gBAAM,CAAC,KAAK,CAAC,IAAA,wCAAiB,EAAC,SAAS,CAAC,EAAE,KAAK,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;IAEH,IAAA,cAAE,EAAC,0BAA0B,EAAE,GAAG,EAAE;QAClC,MAAM,GAAG,GAAG,IAAA,2CAAoB,EAAC,MAAM,CAAC,CAAC;QACzC,gBAAM,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;QACf,gBAAM,CAAC,KAAK,CAAC,GAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAC7B,gBAAM,CAAC,KAAK,CAAC,GAAI,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC;QACnD,gBAAM,CAAC,KAAK,CAAC,GAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACxC,gBAAM,CAAC,KAAK,CAAC,GAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,6BAA6B,CAAC,CAAC;QACtE,gBAAM,CAAC,KAAK,CAAC,GAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,IAAA,cAAE,EAAC,yBAAyB,EAAE,GAAG,EAAE;QACjC,gBAAM,CAAC,KAAK,CAAC,IAAA,2CAAoB,EAAC,SAAS,CAAC,EAAE,IAAI,CAAC,CAAC;QACpD,gBAAM,CAAC,KAAK,CAAC,IAAA,2CAAoB,EAAC,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC;QAC7C,gBAAM,CAAC,KAAK,CAAC,IAAA,2CAAoB,EAAC,UAAU,CAAC,EAAE,IAAI,CAAC,CAAC;QACrD,gBAAM,CAAC,KAAK,CAAC,IAAA,2CAAoB,EAAC,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC;QAC/C,gBAAM,CAAC,KAAK,CAAC,IAAA,2CAAoB,EAAC,uBAAuB,CAAC,EAAE,IAAI,CAAC,CAAC;IACpE,CAAC,CAAC,CAAC;IAEH,IAAA,cAAE,EAAC,qCAAqC,EAAE,GAAG,EAAE;QAC7C,MAAM,GAAG,GAAG,IAAA,2CAAoB,EAAC,IAAI,CAAC,SAAS,CAAC;YAC9C,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;SACpE,CAAC,CAAC,CAAC;QACJ,gBAAM,CAAC,KAAK,CAAC,GAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAC7B,gBAAM,CAAC,KAAK,CAAC,GAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,IAAA,cAAE,EAAC,kCAAkC,EAAE,GAAG,EAAE;QAC1C,MAAM,GAAG,GAAG,IAAA,2CAAoB,EAAC,MAAM,CAAE,CAAC;QAC1C,MAAM,IAAI,GAAG,IAAA,gDAAyB,EAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAClD,gBAAM,CAAC,KAAK,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;QACnC,gBAAM,CAAC,KAAK,CAAC,IAAI,EAAE,wBAAwB,CAAC,CAAC;QAC7C,gBAAM,CAAC,KAAK,CAAC,IAAI,EAAE,mBAAmB,CAAC,CAAC;QACxC,gBAAM,CAAC,KAAK,CAAC,IAAI,EAAE,kBAAkB,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,IAAA,cAAE,EAAC,6BAA6B,EAAE,GAAG,EAAE;QACrC,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QAC/G,MAAM,GAAG,GAAG,IAAA,2CAAoB,EAAC,KAAK,CAAE,CAAC;QACzC,MAAM,IAAI,GAAG,IAAA,gDAAyB,EAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QAChD,gBAAM,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC5B,gBAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface AskUserOption {
|
|
2
|
+
label: string;
|
|
3
|
+
description?: string;
|
|
4
|
+
}
|
|
5
|
+
export interface AskUserQuestion {
|
|
6
|
+
header?: string;
|
|
7
|
+
question: string;
|
|
8
|
+
options: AskUserOption[];
|
|
9
|
+
}
|
|
10
|
+
export declare function isAskUserQuestion(toolName: string | undefined): boolean;
|
|
11
|
+
export declare function parseAskUserQuestion(toolInput: string | undefined): AskUserQuestion[] | null;
|
|
12
|
+
export declare function formatAskUserQuestionText(questions: AskUserQuestion[], maxDescChars?: number): string;
|
|
13
|
+
//# sourceMappingURL=ask-user-question.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ask-user-question.d.ts","sourceRoot":"","sources":["../../src/utils/ask-user-question.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,aAAa,EAAE,CAAC;CAC1B;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAEvE;AAED,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,eAAe,EAAE,GAAG,IAAI,CAwB5F;AAID,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,eAAe,EAAE,EAAE,YAAY,SAAM,GAAG,MAAM,CAiBlG"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Helpers shared by the dashboard, Telegram and ntfy channels to detect and
|
|
3
|
+
// pretty-render Claude Code's AskUserQuestion tool input. That tool serialises
|
|
4
|
+
// a multi-question multi-option wizard into a single JSON blob in tool_input,
|
|
5
|
+
// which is unreadable and — worse — pairs with the regular Allow/Deny buttons
|
|
6
|
+
// that look like an answer but actually only let the picker open in the tmux
|
|
7
|
+
// pane. Surfacing the structure + a warning is the safe minimum.
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.isAskUserQuestion = isAskUserQuestion;
|
|
10
|
+
exports.parseAskUserQuestion = parseAskUserQuestion;
|
|
11
|
+
exports.formatAskUserQuestionText = formatAskUserQuestionText;
|
|
12
|
+
function isAskUserQuestion(toolName) {
|
|
13
|
+
return toolName === 'AskUserQuestion';
|
|
14
|
+
}
|
|
15
|
+
function parseAskUserQuestion(toolInput) {
|
|
16
|
+
if (!toolInput)
|
|
17
|
+
return null;
|
|
18
|
+
try {
|
|
19
|
+
const obj = JSON.parse(toolInput);
|
|
20
|
+
if (!Array.isArray(obj.questions))
|
|
21
|
+
return null;
|
|
22
|
+
const out = [];
|
|
23
|
+
for (const raw of obj.questions) {
|
|
24
|
+
const q = raw;
|
|
25
|
+
if (typeof q.question !== 'string')
|
|
26
|
+
continue;
|
|
27
|
+
const options = [];
|
|
28
|
+
if (Array.isArray(q.options)) {
|
|
29
|
+
for (const opt of q.options) {
|
|
30
|
+
const o = opt;
|
|
31
|
+
if (typeof o.label === 'string') {
|
|
32
|
+
options.push({ label: o.label, description: typeof o.description === 'string' ? o.description : undefined });
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
out.push({ header: typeof q.header === 'string' ? q.header : undefined, question: q.question, options });
|
|
37
|
+
}
|
|
38
|
+
return out.length > 0 ? out : null;
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
// Plain-text rendering for ntfy and any other text channel. Caps descriptions
|
|
45
|
+
// to a short snippet to keep notifications skimmable.
|
|
46
|
+
function formatAskUserQuestionText(questions, maxDescChars = 140) {
|
|
47
|
+
return questions.map((q, qi) => {
|
|
48
|
+
const lines = [];
|
|
49
|
+
if (q.header)
|
|
50
|
+
lines.push(`[${q.header}]`);
|
|
51
|
+
lines.push(`Q${qi + 1}. ${q.question}`);
|
|
52
|
+
q.options.forEach((o, oi) => {
|
|
53
|
+
let line = ` ${oi + 1}) ${o.label}`;
|
|
54
|
+
if (o.description) {
|
|
55
|
+
const snippet = o.description.length > maxDescChars
|
|
56
|
+
? o.description.slice(0, maxDescChars).trim() + '…'
|
|
57
|
+
: o.description;
|
|
58
|
+
line += ` — ${snippet}`;
|
|
59
|
+
}
|
|
60
|
+
lines.push(line);
|
|
61
|
+
});
|
|
62
|
+
return lines.join('\n');
|
|
63
|
+
}).join('\n\n');
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=ask-user-question.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ask-user-question.js","sourceRoot":"","sources":["../../src/utils/ask-user-question.ts"],"names":[],"mappings":"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"}
|