myagent-ai 1.23.49 → 1.23.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/core/stt.py CHANGED
@@ -68,6 +68,29 @@ async def _stt_sensevoice(audio_data: bytes, audio_format: Optional[str] = None)
68
68
  os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
69
69
  'models', 'sensevoice',
70
70
  )
71
+ # [v1.23.49] 首次加载:将 ModelScope 缓存复制到本地 model_dir,后续不再联网
72
+ if not os.path.isdir(model_dir) or not os.listdir(model_dir):
73
+ import shutil
74
+ ms_cache = os.path.expanduser("~/.cache/modelscope/hub/models/iic/SenseVoiceSmall")
75
+ if os.path.isdir(ms_cache) and os.listdir(ms_cache):
76
+ os.makedirs(model_dir, exist_ok=True)
77
+ logger.info(f"复制 SenseVoice 模型: {ms_cache} -> {model_dir}")
78
+ # 复制模型文件(排除缓存元数据)
79
+ for item in os.listdir(ms_cache):
80
+ if item.endswith('.tmp') or item in ('.lock', '__pycache__'):
81
+ continue
82
+ src = os.path.join(ms_cache, item)
83
+ dst = os.path.join(model_dir, item)
84
+ if os.path.isdir(src):
85
+ if os.path.exists(dst):
86
+ shutil.rmtree(dst)
87
+ shutil.copytree(src, dst)
88
+ else:
89
+ shutil.copy2(src, dst)
90
+ else:
91
+ # ModelScope 缓存也没有,首次下载到本地
92
+ os.makedirs(model_dir, exist_ok=True)
93
+ logger.info("SenseVoice 模型首次下载到本地...")
71
94
  _sensevoice_model = AutoModel(
72
95
  model="iic/SenseVoiceSmall",
73
96
  model_dir=model_dir,
@@ -75,7 +98,7 @@ async def _stt_sensevoice(audio_data: bytes, audio_format: Optional[str] = None)
75
98
  disable_pbar=True,
76
99
  disable_update=True,
77
100
  )
78
- logger.info("SenseVoice 模型已加载 (iic/SenseVoiceSmall, CPU)")
101
+ logger.info("SenseVoice 模型已加载 (iic/SenseVoiceSmall, CPU, 本地缓存)")
79
102
 
80
103
  # [v1.23.2] 增强: pydub 转换失败记录警告、WAV 头验证、音频长度检查
81
104
  wav_data = _convert_to_wav(audio_data, audio_format)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "myagent-ai",
3
- "version": "1.23.49",
3
+ "version": "1.23.51",
4
4
  "description": "本地桌面端执行型AI助手 - Open Interpreter 风格 | Local Desktop Execution-Oriented AI Assistant",
5
5
  "main": "main.py",
6
6
  "bin": {
@@ -351,11 +351,11 @@ async function initChat() {
351
351
  // [v1.16.12] 初始化附件上传 UI
352
352
  initAttachmentUI();
353
353
 
354
- // URL 参数处理: ?agent=xxx&mode=exec&session=xxx&popout=1
354
+ // URL 参数处理: ?a=xxx&mode=exec&s=xxx&popout=1(agent/session 使用 UrlCodec 编码)
355
355
  const urlParams = new URLSearchParams(window.location.search);
356
- const urlAgent = urlParams.get('agent');
356
+ const urlAgent = UrlCodec.decode(urlParams.get('a') || '') || UrlCodec.decode(urlParams.get('agent') || '');
357
357
  const urlMode = urlParams.get('mode');
358
- const urlSession = urlParams.get('session');
358
+ const urlSession = UrlCodec.decode(urlParams.get('s') || '') || UrlCodec.decode(urlParams.get('session') || '');
359
359
  const isPopout = urlParams.get('popout') === '1';
360
360
  if (urlMode === 'chat' || urlMode === 'exec') {
361
361
  state.chatMode = urlMode;
@@ -1977,7 +1977,7 @@ async function loadSessions() {
1977
1977
  // Auto-select most recent session if none selected
1978
1978
  // 优先级: URL session 参数 > localStorage 持久化的 session > 最新 session
1979
1979
  const urlParams = new URLSearchParams(window.location.search);
1980
- const urlSession = urlParams.get('session');
1980
+ const urlSession = UrlCodec.decode(urlParams.get('s') || '') || UrlCodec.decode(urlParams.get('session') || '');
1981
1981
  var targetSessionId = null;
1982
1982
 
1983
1983
  if (urlSession && state.sessions.some(s => s.id === urlSession)) {
@@ -1994,7 +1994,7 @@ async function loadSessions() {
1994
1994
  // 更新 URL 为 canonical ID,避免下次刷新再走 fallback
1995
1995
  try {
1996
1996
  var _fixUrl = new URL(window.location.href);
1997
- _fixUrl.searchParams.set('session', prefixMatch.id);
1997
+ _fixUrl.searchParams.set('s', UrlCodec.encode(prefixMatch.id));
1998
1998
  window.history.replaceState({}, '', _fixUrl.toString());
1999
1999
  } catch (_) {}
2000
2000
  }
@@ -2135,8 +2135,9 @@ function newChat() {
2135
2135
  // ── 更新 URL(新对话移除 session 参数) ──
2136
2136
  try {
2137
2137
  const url = new URL(window.location.href);
2138
+ url.searchParams.delete('s');
2138
2139
  url.searchParams.delete('session');
2139
- url.searchParams.set('agent', state.activeAgent || 'default');
2140
+ url.searchParams.set('a', UrlCodec.encode(state.activeAgent || 'default'));
2140
2141
  window.history.replaceState({}, '', url.toString());
2141
2142
  } catch (_) {}
2142
2143
  state.messages = [];
@@ -2263,8 +2264,8 @@ async function selectSession(id) {
2263
2264
  // ── 更新 URL 参数,保留会话 ID(刷新页面可恢复会话) ──
2264
2265
  try {
2265
2266
  const url = new URL(window.location.href);
2266
- url.searchParams.set('session', id);
2267
- url.searchParams.set('agent', state.activeAgent || 'default');
2267
+ url.searchParams.set('s', UrlCodec.encode(id));
2268
+ url.searchParams.set('a', UrlCodec.encode(state.activeAgent || 'default'));
2268
2269
  if (state.chatMode) url.searchParams.set('mode', state.chatMode);
2269
2270
  window.history.replaceState({}, '', url.toString());
2270
2271
  } catch (_) {}
@@ -1619,8 +1619,8 @@ async function sendMessage(opts) {
1619
1619
  // ── 更新 URL 参数,携带会话 ID(刷新页面可恢复) ──
1620
1620
  try {
1621
1621
  const url = new URL(window.location.href);
1622
- url.searchParams.set('session', sessionId);
1623
- url.searchParams.set('agent', state.activeAgent || 'default');
1622
+ url.searchParams.set('s', UrlCodec.encode(sessionId));
1623
+ url.searchParams.set('a', UrlCodec.encode(state.activeAgent || 'default'));
1624
1624
  window.history.replaceState({}, '', url.toString());
1625
1625
  } catch (_) {}
1626
1626
  }
@@ -1770,7 +1770,7 @@ async function sendMessage(opts) {
1770
1770
  // ── 更新 URL 参数(后端返回的 session ID 可能与前端不同) ──
1771
1771
  try {
1772
1772
  const _url = new URL(window.location.href);
1773
- _url.searchParams.set('session', evt.session_id);
1773
+ _url.searchParams.set('s', UrlCodec.encode(evt.session_id));
1774
1774
  window.history.replaceState({}, '', _url.toString());
1775
1775
  } catch (_) {}
1776
1776
  } else if (evt.type === 'user_files') {
@@ -1,3 +1,32 @@
1
+ // ══════════════════════════════════════════════════════
2
+ // ── URL Codec(避免 agent/session 明文暴露在 URL) ──
3
+ // [v1.23.50] 放在最先加载的文件中,供所有模块使用
4
+ // ══════════════════════════════════════════════════════
5
+ var UrlCodec = (function() {
6
+ var _p = 'x';
7
+ function _encode(str) {
8
+ if (!str) return '';
9
+ try {
10
+ var bytes = new TextEncoder().encode(str);
11
+ var bin = '';
12
+ for (var i = 0; i < bytes.length; i++) bin += String.fromCharCode(bytes[i]);
13
+ return _p + btoa(bin).replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_');
14
+ } catch(e) { return str; }
15
+ }
16
+ function _decode(encoded) {
17
+ if (!encoded || encoded[0] !== _p) return encoded;
18
+ try {
19
+ var b64 = encoded.substring(1).replace(/-/g, '+').replace(/_/g, '/');
20
+ while (b64.length % 4) b64 += '=';
21
+ var bin = atob(b64);
22
+ var bytes = new Uint8Array(bin.length);
23
+ for (var i = 0; i < bin.length; i++) bytes[i] = bin.charCodeAt(i);
24
+ return new TextDecoder().decode(bytes);
25
+ } catch(e) { return encoded; }
26
+ }
27
+ return { encode: _encode, decode: _decode };
28
+ })();
29
+
1
30
  // ══════════════════════════════════════════════════════
2
31
  // ── Group Chat: 群聊模块 ──
3
32
  // ── 负责群聊的创建、管理、消息渲染与发送 ──