@wendongfly/myhi 1.3.48 → 1.3.51
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/chat.html +43 -20
- package/dist/index.html +1 -1
- package/dist/index.js +1 -1
- package/dist/index.min.js +2 -2
- package/dist/terminal.html +1 -1
- package/package.json +1 -1
package/dist/chat.html
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
<link rel="manifest" href="/manifest.json">
|
|
10
10
|
<link rel="apple-touch-icon" href="/icon.png">
|
|
11
11
|
<title>myhi 会话</title>
|
|
12
|
-
<script src="/
|
|
12
|
+
<script src="/sio-client/socket.io.min.js"></script>
|
|
13
13
|
<style>
|
|
14
14
|
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
15
15
|
html, body { height: 100%; background: #0d1117; color: #e6edf3; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; overflow: hidden; }
|
|
@@ -2769,35 +2769,58 @@
|
|
|
2769
2769
|
addStatusMessage(`会话统计: ${inputs} 条提问, ${assistants} 条回复, ${tools} 次工具调用`);
|
|
2770
2770
|
};
|
|
2771
2771
|
|
|
2772
|
+
// ── 图片上传(拍照 / 选文件 / 剪贴板粘贴共用) ──────────
|
|
2773
|
+
// 压缩源 Blob → POST /upload → setPendingImage
|
|
2774
|
+
async function uploadImageBlob(srcBlob, filename) {
|
|
2775
|
+
const img = new Image(); const url = URL.createObjectURL(srcBlob);
|
|
2776
|
+
const blob = await new Promise((resolve, reject) => {
|
|
2777
|
+
img.onload = () => { URL.revokeObjectURL(url); let {width:w, height:h} = img;
|
|
2778
|
+
// 压缩策略:长边限制 1024px,JPEG 质量 0.7,适合截图分析
|
|
2779
|
+
const M = 1024;
|
|
2780
|
+
if(w>M||h>M){if(w>=h){h=Math.round(h*M/w);w=M}else{w=Math.round(w*M/h);h=M}}
|
|
2781
|
+
const c=document.createElement('canvas');c.width=w;c.height=h;c.getContext('2d').drawImage(img,0,0,w,h);
|
|
2782
|
+
c.toBlob(b=>b?resolve(b):reject(new Error('toBlob failed')),'image/jpeg',0.7); };
|
|
2783
|
+
img.onerror=reject; img.src=url; });
|
|
2784
|
+
const form = new FormData(); form.append('image', blob, filename || 'image.jpg');
|
|
2785
|
+
const res = await fetch(`/upload?sessionId=${SESSION_ID}`, { method: 'POST', body: form });
|
|
2786
|
+
const data = await res.json();
|
|
2787
|
+
if (!data.path) throw new Error(data.error || '上传失败');
|
|
2788
|
+
setPendingImage(data.path, URL.createObjectURL(blob));
|
|
2789
|
+
}
|
|
2790
|
+
|
|
2772
2791
|
// ── 拍照上传 ──────────────────────────────────
|
|
2773
2792
|
window.openCamera = async function() {
|
|
2774
2793
|
const input = document.createElement('input'); input.type = 'file'; input.accept = 'image/*';
|
|
2775
2794
|
input.onchange = async () => {
|
|
2776
2795
|
const file = input.files?.[0]; if (!file) return;
|
|
2777
2796
|
const btn = document.getElementById('btn-photo'); btn.classList.add('active'); btn.disabled = true;
|
|
2778
|
-
try {
|
|
2779
|
-
|
|
2780
|
-
const blob = await new Promise((resolve, reject) => {
|
|
2781
|
-
img.onload = () => { URL.revokeObjectURL(url); let {width:w, height:h} = img;
|
|
2782
|
-
// 压缩策略:长边限制 1024px,JPEG 质量 0.7,适合截图分析
|
|
2783
|
-
const M = 1024;
|
|
2784
|
-
if(w>M||h>M){if(w>=h){h=Math.round(h*M/w);w=M}else{w=Math.round(w*M/h);h=M}}
|
|
2785
|
-
const c=document.createElement('canvas');c.width=w;c.height=h;c.getContext('2d').drawImage(img,0,0,w,h);
|
|
2786
|
-
c.toBlob(b=>b?resolve(b):reject(new Error('toBlob failed')),'image/jpeg',0.7); };
|
|
2787
|
-
img.onerror=reject; img.src=url; });
|
|
2788
|
-
const form = new FormData(); form.append('image', blob, 'photo.jpg');
|
|
2789
|
-
const res = await fetch(`/upload?sessionId=${SESSION_ID}`, { method: 'POST', body: form }); const data = await res.json();
|
|
2790
|
-
if (data.path) {
|
|
2791
|
-
// 暂存图片,等用户输入文字后一起发送
|
|
2792
|
-
const thumbUrl = URL.createObjectURL(blob);
|
|
2793
|
-
setPendingImage(data.path, thumbUrl);
|
|
2794
|
-
}
|
|
2795
|
-
else addStatusMessage('上传失败: ' + (data.error || '未知'));
|
|
2796
|
-
} catch (e) { addStatusMessage('出错: ' + e.message); }
|
|
2797
|
+
try { await uploadImageBlob(file, 'photo.jpg'); }
|
|
2798
|
+
catch (e) { addStatusMessage('出错: ' + e.message); }
|
|
2797
2799
|
finally { btn.classList.remove('active'); btn.disabled = false; }
|
|
2798
2800
|
}; input.click();
|
|
2799
2801
|
};
|
|
2800
2802
|
|
|
2803
|
+
// ── 剪贴板粘贴图片(桌面端 Ctrl+V)──────────────
|
|
2804
|
+
// document 级监听:截图后切到浏览器直接 Ctrl+V,无需先聚焦输入框
|
|
2805
|
+
document.addEventListener('paste', async (e) => {
|
|
2806
|
+
const items = e.clipboardData?.items;
|
|
2807
|
+
if (!items) return;
|
|
2808
|
+
for (const item of items) {
|
|
2809
|
+
if (item.kind === 'file' && item.type.startsWith('image/')) {
|
|
2810
|
+
const blob = item.getAsFile();
|
|
2811
|
+
if (!blob) continue;
|
|
2812
|
+
e.preventDefault(); // 阻止浏览器把图片当文本塞进 textarea
|
|
2813
|
+
addStatusMessage('粘贴图片上传中...');
|
|
2814
|
+
try {
|
|
2815
|
+
await uploadImageBlob(blob, 'paste.png');
|
|
2816
|
+
document.getElementById('cmd-input')?.focus();
|
|
2817
|
+
} catch (err) { addStatusMessage('上传失败: ' + err.message); }
|
|
2818
|
+
return; // 只处理第一张
|
|
2819
|
+
}
|
|
2820
|
+
}
|
|
2821
|
+
// 剪贴板里没有图片 → 不拦截,文本粘贴走默认行为
|
|
2822
|
+
});
|
|
2823
|
+
|
|
2801
2824
|
// ── 语音输入 ──────────────────────────────────
|
|
2802
2825
|
let recognition = null;
|
|
2803
2826
|
let isRecording = false;
|
package/dist/index.html
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
<link rel="manifest" href="/manifest.json">
|
|
11
11
|
<link rel="apple-touch-icon" href="/icon.png">
|
|
12
12
|
<title>myhi</title>
|
|
13
|
-
<script src="/
|
|
13
|
+
<script src="/sio-client/socket.io.min.js"></script>
|
|
14
14
|
<style>
|
|
15
15
|
:root {
|
|
16
16
|
--bg: #0d1117;
|