@jack200714/mafw 4.10.1 → 4.10.2

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,54 +1,43 @@
1
1
  "use strict";
2
2
  /**
3
- * Serve 进程唯一所有者:kill / spawn / 就绪等待 / 健康探测。
3
+ * Serve 进程唯一编排者:adopt / kill / spawn / 就绪等待。
4
4
  * 从 index.ts 下沉(原 killProcessOnPort + startServe + isServeHealthy 的动作段)。
5
- * kill spawn 都是 runtime 契约原语(killServePort / agentProcess.spawnServe),
6
- * 本模块只做通用编排;gateway 编排层(recoverServe/watchdog)在其上叠加事件流重订。
7
- * deps 全部注入以便单测;生产装配见 index.ts。
5
+ * 原则:gateway 只编排,不实现——健康检测经 runtime 契约(health())、
6
+ * 地址归 runtime(baseUrl())、kill/spawn 都是 runtime 原语,gateway 不传
7
+ * host/port(serve 端口是 runtime 实现细节)。deps 全部注入以便单测。
8
8
  */
9
9
  Object.defineProperty(exports, "__esModule", { value: true });
10
10
  exports.createServeSupervisor = createServeSupervisor;
11
11
  function createServeSupervisor(deps) {
12
- const host = deps.host ?? '127.0.0.1';
13
12
  const probeIntervalMs = deps.probeIntervalMs ?? 500;
14
13
  const probeTimeoutMs = deps.probeTimeoutMs ?? 60_000;
15
14
  let instance;
16
15
  let starting;
17
- const refused = () => new Error('external agent process is not managed by the gateway');
16
+ const refused = () => new Error('unmanaged runtime: gateway holds no start/stop primitives');
18
17
  const spawnAndWait = async () => {
19
- instance = await deps.spawn({ host, port: deps.port, timeoutMs: probeTimeoutMs });
18
+ instance = await deps.spawn({ timeoutMs: probeTimeoutMs });
20
19
  const deadline = Date.now() + probeTimeoutMs;
21
20
  while (Date.now() < deadline) {
22
- if (await deps.probe(instance.url))
23
- return instance.url;
21
+ if (await deps.health())
22
+ return deps.baseUrl();
24
23
  await new Promise(r => setTimeout(r, probeIntervalMs));
25
24
  }
26
- throw new Error(`serve did not become healthy within ${probeTimeoutMs}ms`);
25
+ throw new Error(`runtime did not become healthy within ${probeTimeoutMs}ms`);
27
26
  };
28
27
  return {
29
- get owned() { return !deps.external; },
28
+ get owned() { return deps.managed(); },
30
29
  async ensureStarted() {
31
- if (deps.external)
30
+ if (!deps.managed())
32
31
  throw refused();
33
- if (instance && await deps.probe(instance.url))
34
- return instance.url;
35
- // Adopt: gateway startup may have adopted a healthy serve, or a
36
- // user-managed opencode may already listen here — never killPort a
37
- // healthy listener on this port (that would drop every SSE/desktop/TUI
38
- // connection on a pi→opencode switch).
39
- const candidateUrl = `http://${host}:${deps.port}`;
40
- try {
41
- if (await deps.probe(candidateUrl)) {
42
- instance = { url: candidateUrl, close: () => { } };
43
- return candidateUrl;
44
- }
45
- }
46
- catch { /* not healthy → spawn below */ }
32
+ // Adopt:runtime 健康(含用户自管/已有监听)直接收养,绝不 kill——
33
+ // 健康判定来自 runtime 契约,gateway 不构造候选 URL。
34
+ if (await deps.health())
35
+ return deps.baseUrl();
47
36
  if (starting)
48
37
  return starting;
49
38
  starting = (async () => {
50
39
  try {
51
- deps.killPort(deps.port);
40
+ deps.killServe();
52
41
  instance = undefined;
53
42
  return await spawnAndWait();
54
43
  }
@@ -59,13 +48,13 @@ function createServeSupervisor(deps) {
59
48
  return starting;
60
49
  },
61
50
  async restart() {
62
- if (deps.external)
51
+ if (!deps.managed())
63
52
  throw refused();
64
53
  if (starting)
65
54
  return starting;
66
55
  starting = (async () => {
67
56
  try {
68
- deps.killPort(deps.port);
57
+ deps.killServe();
69
58
  instance?.close();
70
59
  instance = undefined;
71
60
  return await spawnAndWait();
@@ -77,9 +66,7 @@ function createServeSupervisor(deps) {
77
66
  return starting;
78
67
  },
79
68
  async health() {
80
- if (!instance)
81
- return false;
82
- return deps.probe(instance.url);
69
+ return deps.health();
83
70
  },
84
71
  close() {
85
72
  try {
@@ -4,6 +4,7 @@
4
4
  "description": "MAFW Gateway v5.0 —SSE Event-Driven Scheduler",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
7
+ "emit:openapi": "ts-node --project tsconfig.json scripts/emit-openapi.ts",
7
8
  "build": "tsc && node -e \"const fs=require('fs'),p=require('path');const cp=(s,d)=>{if(fs.existsSync(s)){fs.cpSync(s,d,{recursive:true});console.log('[copy] '+d)}else{console.log('[skip] '+s)};};cp(p.join(__dirname,'src','dashboard','public'),p.join(__dirname,'dist','dashboard','public'));cp(p.join(__dirname,'src','tray','tray.ps1'),p.join(__dirname,'dist','tray','tray.ps1'));cp(p.join(__dirname,'src','usage','builtin-plugins'),p.join(__dirname,'dist','usage','builtin-plugins'));\"",
8
9
  "start": "node dist/index.js",
9
10
  "dev": "ts-node src/index.ts",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jack200714/mafw",
3
- "version": "4.10.1",
3
+ "version": "4.10.2",
4
4
  "description": "MAFW Loop Agent Plugin for OpenCode - Phase Relay + TMEM + Dynamic Compression",
5
5
  "repository": {
6
6
  "type": "git",
@@ -157,7 +157,14 @@ var require_client = __commonJS({
157
157
  }
158
158
  return res.json();
159
159
  }
160
- // ── Session ──
160
+ /**
161
+ * 裸 fetch 的编译期约束入口:与 request 同一 ApiPath 契约,但返回原始 Response,
162
+ * 供 SSE 流/二进制体/自定义错误处理的调用方使用(P3 收编,fetch 直调仅剩此出口)。
163
+ */
164
+ fetchPath(path, init) {
165
+ return this.fetchImpl(`${this.baseUrl}${path}`, init);
166
+ }
167
+ // 鈹€鈹€ Session 鈹€鈹€
161
168
  session = {
162
169
  create: async (params) => {
163
170
  return this.request("/api/session", {
@@ -234,7 +241,7 @@ var require_client = __commonJS({
234
241
  });
235
242
  },
236
243
  promptAsync: async (params) => {
237
- const res = await fetch(`${this.baseUrl}/api/session/${params.path.id}/promptAsync`, {
244
+ const res = await this.fetchPath(`/api/session/${params.path.id}/promptAsync`, {
238
245
  method: "POST",
239
246
  headers: { "Content-Type": "application/json" },
240
247
  body: JSON.stringify({
@@ -312,7 +319,7 @@ var require_client = __commonJS({
312
319
  };
313
320
  },
314
321
  command: async (params) => {
315
- const res = await fetch(`${this.baseUrl}/api/session/${params.path.id}/command`, {
322
+ const res = await this.fetchPath(`/api/session/${params.path.id}/command`, {
316
323
  method: "POST",
317
324
  headers: { "Content-Type": "application/json" },
318
325
  body: JSON.stringify(params.body)
@@ -321,7 +328,7 @@ var require_client = __commonJS({
321
328
  throw new Error(`HTTP ${res.status}: ${res.statusText}`);
322
329
  }
323
330
  };
324
- // ── Commands & skills (opencode serve, proxied by the gateway) ──
331
+ // 鈹€鈹€ Commands & skills (opencode serve, proxied by the gateway) 鈹€鈹€
325
332
  command = {
326
333
  list: async (directory) => {
327
334
  const query = directory ? `?directory=${encodeURIComponent(directory)}` : "";
@@ -340,7 +347,7 @@ var require_client = __commonJS({
340
347
  return data.items || data.skills || [];
341
348
  }
342
349
  };
343
- // ── MAFW native commands (desktop slash panel) ──
350
+ // 鈹€鈹€ MAFW native commands (desktop slash panel) 鈹€鈹€
344
351
  mafwCommands = {
345
352
  run: async (params) => {
346
353
  return this.request("/api/mafw-commands/run", {
@@ -349,7 +356,7 @@ var require_client = __commonJS({
349
356
  });
350
357
  }
351
358
  };
352
- // ── Manager session (authoritative per-project manager, from gateway DB) ──
359
+ // 鈹€鈹€ Manager session (authoritative per-project manager, from gateway DB) 鈹€鈹€
353
360
  manager = {
354
361
  session: async (projectDir) => {
355
362
  const q = projectDir ? `?projectDir=${encodeURIComponent(projectDir)}` : "";
@@ -367,7 +374,7 @@ var require_client = __commonJS({
367
374
  });
368
375
  }
369
376
  };
370
- // ── Project ──
377
+ // 鈹€鈹€ Project 鈹€鈹€
371
378
  project = {
372
379
  list: async () => {
373
380
  const data = await this.request("/api/projects");
@@ -386,7 +393,7 @@ var require_client = __commonJS({
386
393
  });
387
394
  }
388
395
  };
389
- // ── Event ──
396
+ // 鈹€鈹€ Event 鈹€鈹€
390
397
  event = {
391
398
  subscribe: async () => {
392
399
  this._sse.connect(this.baseUrl);
@@ -412,17 +419,19 @@ var require_client = __commonJS({
412
419
  }
413
420
  };
414
421
  },
415
- /** SSE 连接状态(onopen/onerror 维护;供监督器健康轮询)。 */
422
+ /** SSE 杩炴帴鐘舵€侊紙onopen/onerror 缁存姢锛涗緵鐩戠潱鍣ㄥ仴搴疯疆璇級銆?*/
416
423
  connected: () => this._sse.connected,
417
- /** 发布自定义事件到全部 UI 通道(SSE/WS/推送)。type 建议命名空间
418
- * 'plugin:<name>:<event>';消费方对未知 type 忽略(SSE 通知语义,无注册制)。 */
424
+ /** SSE 绔偣 URL锛堝绾﹀綊 SDK锛歳enderer 鐩磋繛 EventSource 鏃剁敤姝ゆ瀯閫狅紝涓嶈嚜宸辨嫾瀛楃涓诧級銆?*/
425
+ url: (sessionID) => sessionID ? `${this.baseUrl}/api/events?sessionID=${encodeURIComponent(sessionID)}` : `${this.baseUrl}/api/events`,
426
+ /** 鍙戝竷鑷畾涔変簨浠跺埌鍏ㄩ儴 UI 閫氶亾锛圫SE/WS/鎺ㄩ€侊級銆倀ype 寤鸿鍛藉悕绌洪棿
427
+ * 'plugin:<name>:<event>'锛涙秷璐规柟瀵规湭鐭?type 蹇界暐锛圫SE 閫氱煡璇箟锛屾棤娉ㄥ唽鍒讹級銆?*/
419
428
  publish: async (event) => this.request("/api/events", {
420
429
  method: "POST",
421
430
  headers: { "Content-Type": "application/json" },
422
431
  body: JSON.stringify(event)
423
432
  })
424
433
  };
425
- // ── Runtime ──
434
+ // 鈹€鈹€ Runtime 鈹€鈹€
426
435
  runtime = {
427
436
  /** Get active runtime identity, capabilities, and plugin scan state. */
428
437
  get: async () => {
@@ -434,7 +443,7 @@ var require_client = __commonJS({
434
443
  * @returns The new active runtime state.
435
444
  */
436
445
  switch: async (plugin) => {
437
- const res = await fetch(`${this.baseUrl}/api/runtime/switch`, {
446
+ const res = await this.fetchPath(`/api/runtime/switch`, {
438
447
  method: "POST",
439
448
  headers: { "Content-Type": "application/json" },
440
449
  body: JSON.stringify({ plugin })
@@ -447,7 +456,7 @@ var require_client = __commonJS({
447
456
  },
448
457
  /** Restart the agent runtime (opencode serve). */
449
458
  restartAgent: async () => {
450
- const res = await fetch(`${this.baseUrl}/api/runtime/restart-agent`, {
459
+ const res = await this.fetchPath(`/api/runtime/restart-agent`, {
451
460
  method: "POST",
452
461
  headers: { "Content-Type": "application/json" }
453
462
  });
@@ -458,7 +467,7 @@ var require_client = __commonJS({
458
467
  return res.json();
459
468
  }
460
469
  };
461
- // ── Plugins Hub ──
470
+ // 鈹€鈹€ Plugins Hub 鈹€鈹€
462
471
  plugins = {
463
472
  list: async () => this.request("/api/plugins"),
464
473
  install: async (input) => {
@@ -467,7 +476,7 @@ var require_client = __commonJS({
467
476
  params.set("type", input.type);
468
477
  if (input.overwrite)
469
478
  params.set("overwrite", "1");
470
- const res = await this.fetchImpl(`${this.baseUrl}/api/plugins/install?${params.toString()}`, {
479
+ const res = await this.fetchPath(`/api/plugins/install?${params.toString()}`, {
471
480
  method: "POST",
472
481
  headers: { "Content-Type": "application/octet-stream" },
473
482
  body: input.bytes
@@ -479,7 +488,7 @@ var require_client = __commonJS({
479
488
  return res.json();
480
489
  },
481
490
  enable: async (type, filename) => {
482
- const res = await this.fetchImpl(`${this.baseUrl}/api/plugins/enable`, {
491
+ const res = await this.fetchPath(`/api/plugins/enable`, {
483
492
  method: "POST",
484
493
  headers: { "Content-Type": "application/json" },
485
494
  body: JSON.stringify({ type, filename })
@@ -491,7 +500,7 @@ var require_client = __commonJS({
491
500
  return res.json();
492
501
  },
493
502
  disable: async (type, filename) => {
494
- const res = await this.fetchImpl(`${this.baseUrl}/api/plugins/disable`, {
503
+ const res = await this.fetchPath(`/api/plugins/disable`, {
495
504
  method: "POST",
496
505
  headers: { "Content-Type": "application/json" },
497
506
  body: JSON.stringify({ type, filename })
@@ -503,7 +512,7 @@ var require_client = __commonJS({
503
512
  return res.json();
504
513
  },
505
514
  delete: async (type, filename) => {
506
- const res = await this.fetchImpl(`${this.baseUrl}/api/plugins/delete`, {
515
+ const res = await this.fetchPath(`/api/plugins/delete`, {
507
516
  method: "POST",
508
517
  headers: { "Content-Type": "application/json" },
509
518
  body: JSON.stringify({ type, filename })
@@ -515,7 +524,7 @@ var require_client = __commonJS({
515
524
  return res.json();
516
525
  }
517
526
  };
518
- // ── Config ──
527
+ // 鈹€鈹€ Config 鈹€鈹€
519
528
  config = {
520
529
  get: async (key) => {
521
530
  const data = await this.request("/api/config");
@@ -524,21 +533,21 @@ var require_client = __commonJS({
524
533
  set: async (key, value) => {
525
534
  const current = await this.request("/api/config");
526
535
  current[key] = value;
527
- await fetch(`${this.baseUrl}/api/config`, {
536
+ await this.fetchPath(`/api/config`, {
528
537
  method: "PUT",
529
538
  headers: { "Content-Type": "application/json" },
530
539
  body: JSON.stringify(current)
531
540
  });
532
541
  }
533
542
  };
534
- // ── OpenCode config (native opencode /config) ──
543
+ // 鈹€鈹€ OpenCode config (native opencode /config) 鈹€鈹€
535
544
  opencodeConfig = {
536
545
  get: async () => {
537
546
  const data = await this.request("/api/opencode-config");
538
547
  return data.config;
539
548
  },
540
549
  update: async (config) => {
541
- const res = await fetch(`${this.baseUrl}/api/opencode-config`, {
550
+ const res = await this.fetchPath(`/api/opencode-config`, {
542
551
  method: "PATCH",
543
552
  headers: { "Content-Type": "application/json" },
544
553
  body: JSON.stringify(config)
@@ -548,7 +557,7 @@ var require_client = __commonJS({
548
557
  return res.json();
549
558
  }
550
559
  };
551
- // ── Goals ──
560
+ // 鈹€鈹€ Goals 鈹€鈹€
552
561
  goals = {
553
562
  list: async () => {
554
563
  const data = await this.request("/api/goals");
@@ -578,9 +587,12 @@ var require_client = __commonJS({
578
587
  method: "POST",
579
588
  body: JSON.stringify(action)
580
589
  });
590
+ },
591
+ respondQuestion: async (goalId, questionId, input) => {
592
+ return this.request(`/api/goals/${encodeURIComponent(goalId)}/questions/${encodeURIComponent(questionId)}/respond`, { method: "POST", body: JSON.stringify(input) });
581
593
  }
582
594
  };
583
- // ── Memory ──
595
+ // 鈹€鈹€ Memory 鈹€鈹€
584
596
  memory = {
585
597
  search: async (opts) => {
586
598
  const params = new URLSearchParams({ query: opts.query });
@@ -623,7 +635,7 @@ var require_client = __commonJS({
623
635
  });
624
636
  }
625
637
  };
626
- // ── Approvals ──
638
+ // 鈹€鈹€ Approvals 鈹€鈹€
627
639
  approvals = {
628
640
  list: async () => {
629
641
  const data = await this.request("/api/approvals");
@@ -636,7 +648,7 @@ var require_client = __commonJS({
636
648
  });
637
649
  }
638
650
  };
639
- // ── Triage ──
651
+ // 鈹€鈹€ Triage 鈹€鈹€
640
652
  triage = {
641
653
  list: async () => {
642
654
  const data = await this.request("/api/triage");
@@ -658,7 +670,7 @@ var require_client = __commonJS({
658
670
  });
659
671
  }
660
672
  };
661
- // ── Questions (AskCard proxies the native opencode Question API) ──
673
+ // 鈹€鈹€ Questions (AskCard 鈥?proxies the native opencode Question API) 鈹€鈹€
662
674
  questions = {
663
675
  list: async () => {
664
676
  const data = await this.request("/api/questions");
@@ -674,7 +686,7 @@ var require_client = __commonJS({
674
686
  await this.request(`/api/questions/${id}/reject`, { method: "POST" });
675
687
  }
676
688
  };
677
- // ── Permissions (PermissionCard proxies the native opencode Permission API) ──
689
+ // 鈹€鈹€ Permissions (PermissionCard 鈥?proxies the native opencode Permission API) 鈹€鈹€
678
690
  permissions = {
679
691
  list: async () => {
680
692
  const data = await this.request("/api/permissions");
@@ -687,10 +699,10 @@ var require_client = __commonJS({
687
699
  });
688
700
  }
689
701
  };
690
- // ── Chat ──
702
+ // 鈹€鈹€ Chat 鈹€鈹€
691
703
  chat = {
692
704
  send: async (message, sessionID) => {
693
- const res = await fetch(`${this.baseUrl}/api/chat`, {
705
+ const res = await this.fetchPath(`/api/chat`, {
694
706
  method: "POST",
695
707
  headers: { "Content-Type": "application/json" },
696
708
  body: JSON.stringify({ message, sessionID })
@@ -700,7 +712,7 @@ var require_client = __commonJS({
700
712
  return res.json();
701
713
  },
702
714
  sendEnriched: async (opts) => {
703
- const res = await fetch(`${this.baseUrl}/api/chat/enriched`, {
715
+ const res = await this.fetchPath(`/api/chat/enriched`, {
704
716
  method: "POST",
705
717
  headers: { "Content-Type": "application/json" },
706
718
  body: JSON.stringify(opts)
@@ -710,7 +722,7 @@ var require_client = __commonJS({
710
722
  return res.json();
711
723
  }
712
724
  };
713
- // ── Media (A2A Media Agent) ──
725
+ // 鈹€鈹€ Media (A2A Media Agent) 鈹€鈹€
714
726
  media = {
715
727
  /** List media engine plugins (status + modalities). */
716
728
  plugins: async () => {
@@ -722,7 +734,7 @@ var require_client = __commonJS({
722
734
  * @returns The new media engine configuration.
723
735
  */
724
736
  switch: async (opts) => {
725
- const res = await fetch(`${this.baseUrl}/api/media/switch`, {
737
+ const res = await this.fetchPath(`/api/media/switch`, {
726
738
  method: "POST",
727
739
  headers: { "Content-Type": "application/json" },
728
740
  body: JSON.stringify(opts)
@@ -737,7 +749,7 @@ var require_client = __commonJS({
737
749
  const parts = opts.artifactId ? [{ url: `/a2a/artifacts/${opts.artifactId}`, mediaType: opts.mediaType || "application/octet-stream", filename: "upload.bin" }] : [{ raw: opts.dataUrl?.split(",")[1] || "", mediaType: opts.mediaType || "image/png", filename: "paste.bin" }];
738
750
  if (opts.question)
739
751
  parts.push({ text: opts.question });
740
- const res = await fetch(`${this.baseUrl}/a2a`, {
752
+ const res = await this.fetchPath(`/a2a`, {
741
753
  method: "POST",
742
754
  headers: { "Content-Type": "application/json", "A2A-Version": "1.0" },
743
755
  body: JSON.stringify({
@@ -763,12 +775,42 @@ var require_client = __commonJS({
763
775
  if (!task?.id)
764
776
  throw new Error("Vision createTask failed: no task returned");
765
777
  return { id: task.id, contextId: task.contextId, state: task.status?.state || "" };
766
- }
778
+ },
779
+ upload: async (input) => {
780
+ const res = await this.fetchPath(`/api/media/upload?type=${encodeURIComponent(input.mediaType)}`, {
781
+ method: "POST",
782
+ headers: { "Content-Type": "application/octet-stream" },
783
+ body: input.bytes
784
+ });
785
+ if (!res.ok)
786
+ throw new Error(`\u6FEF\u638D\u7D8B\u6D93\u5A41\u7D36\u6FB6\u8FAB\u89E6: HTTP ${res.status}`);
787
+ const data = await res.json();
788
+ if (!data?.artifactId)
789
+ throw new Error("\u6FEF\u638D\u7D8B\u6D93\u5A41\u7D36\u6FB6\u8FAB\u89E6: \u93C3?artifactId");
790
+ return { artifactId: data.artifactId };
791
+ },
792
+ uploadAndCreate: async (input) => {
793
+ const qs = new URLSearchParams({ type: input.mediaType });
794
+ if (input.question)
795
+ qs.set("question", input.question);
796
+ const res = await this.fetchPath(`/api/media/upload-and-create?${qs.toString()}`, {
797
+ method: "POST",
798
+ headers: { "Content-Type": "application/octet-stream" },
799
+ body: input.bytes
800
+ });
801
+ if (!res.ok)
802
+ throw new Error(`\u6FEF\u638D\u7D8B\u6D93\u5A41\u7D36\u6FB6\u8FAB\u89E6: HTTP ${res.status}`);
803
+ const data = await res.json();
804
+ if (!data?.id)
805
+ throw new Error("\u6FEF\u638D\u7D8B\u6D93\u5A41\u7D36\u6FB6\u8FAB\u89E6: \u93C3?task id");
806
+ return { id: data.id, contextId: data.contextId, state: data.state, artifactId: data.artifactId, mediaType: data.mediaType, size: data.size };
807
+ },
808
+ artifactUrl: (id) => `${this.baseUrl}/a2a/artifacts/${id}`
767
809
  };
768
- // ── TTS (MiMo-V2.5-TTS speech synthesis) ──
810
+ // 鈹€鈹€ TTS (MiMo-V2.5-TTS speech synthesis) 鈹€鈹€
769
811
  tts = {
770
812
  speak: async (opts) => {
771
- const res = await fetch(`${this.baseUrl}/api/tts`, {
813
+ const res = await this.fetchPath(`/api/tts`, {
772
814
  method: "POST",
773
815
  headers: { "Content-Type": "application/json" },
774
816
  body: JSON.stringify(opts)
@@ -785,16 +827,16 @@ var require_client = __commonJS({
785
827
  return res.json();
786
828
  },
787
829
  voices: async () => {
788
- const res = await fetch(`${this.baseUrl}/api/tts/voices`);
830
+ const res = await this.fetchPath(`/api/tts/voices`);
789
831
  if (!res.ok)
790
832
  throw new Error(`TTS voices failed: HTTP ${res.status}`);
791
833
  return res.json();
792
834
  },
793
- /** 流式 TTS:返回 async iterable of base64 PCM16 chunks(24kHz mono)。 */
835
+ /** 娴佸紡 TTS锛氳繑鍥?async iterable of base64 PCM16 chunks锛?4kHz mono锛夈€?*/
794
836
  speakStream: (opts) => {
795
- const base = this.baseUrl;
837
+ const client = this;
796
838
  return (async function* () {
797
- const res = await fetch(`${base}/api/tts/stream`, {
839
+ const res = await client.fetchPath(`/api/tts/stream`, {
798
840
  method: "POST",
799
841
  headers: { "Content-Type": "application/json" },
800
842
  body: JSON.stringify(opts)
@@ -830,9 +872,11 @@ var require_client = __commonJS({
830
872
  reader.releaseLock();
831
873
  }
832
874
  })();
833
- }
875
+ },
876
+ /** 娴佸紡 TTS 绔偣 URL锛堝绾﹀綊 SDK锛欼PC 鏃犳硶鍏嬮殕 SSE 娴侊紝renderer 鐩磋繛 fetch 鏃剁敤姝ゆ瀯閫狅級銆?*/
877
+ streamUrl: () => `${this.baseUrl}/api/tts/stream`
834
878
  };
835
- // ── Providers & Agents (composer model pill / @agent mention) ──
879
+ // 鈹€鈹€ Providers & Agents (composer model pill / @agent mention) 鈹€鈹€
836
880
  providers = {
837
881
  list: async () => {
838
882
  const data = await this.request("/api/provider");
@@ -845,13 +889,13 @@ var require_client = __commonJS({
845
889
  return data.items || [];
846
890
  }
847
891
  };
848
- // ── Model config (recall worker + media models) ──
892
+ // 鈹€鈹€ Model config (recall worker + media models) 鈹€鈹€
849
893
  models = {
850
894
  get: async () => {
851
895
  return this.request("/api/model-config");
852
896
  },
853
897
  update: async (opts) => {
854
- const res = await fetch(`${this.baseUrl}/api/model-config`, {
898
+ const res = await this.fetchPath(`/api/model-config`, {
855
899
  method: "POST",
856
900
  headers: { "Content-Type": "application/json" },
857
901
  body: JSON.stringify(opts)
@@ -863,13 +907,13 @@ var require_client = __commonJS({
863
907
  return res.json();
864
908
  }
865
909
  };
866
- // ── Memory embedding config (hot-swap engine, no restart) ──
910
+ // 鈹€鈹€ Memory embedding config (hot-swap engine, no restart) 鈹€鈹€
867
911
  embedding = {
868
912
  get: async () => {
869
913
  return this.request("/api/memory/embedding-config");
870
914
  },
871
915
  update: async (opts) => {
872
- const res = await fetch(`${this.baseUrl}/api/memory/embedding-config`, {
916
+ const res = await this.fetchPath(`/api/memory/embedding-config`, {
873
917
  method: "POST",
874
918
  headers: { "Content-Type": "application/json" },
875
919
  body: JSON.stringify(opts)
@@ -881,7 +925,7 @@ var require_client = __commonJS({
881
925
  return res.json();
882
926
  }
883
927
  };
884
- // ── Automations ──
928
+ // 鈹€鈹€ Automations 鈹€鈹€
885
929
  automations = {
886
930
  list: async () => {
887
931
  const data = await this.request("/api/automations");
@@ -893,7 +937,7 @@ var require_client = __commonJS({
893
937
  body: JSON.stringify({ enabled })
894
938
  });
895
939
  },
896
- /** 起草规则(enabled=false 落盘,需手动启用)。返回校验结果。 */
940
+ /** 璧疯崏瑙勫垯锛坋nabled=false 钀界洏锛岄渶鎵嬪姩鍚敤锛夈€傝繑鍥炴牎楠岀粨鏋溿€?*/
897
941
  draft: async (input) => {
898
942
  return this.request("/api/automations/draft", {
899
943
  method: "POST",
@@ -3256,7 +3300,8 @@ var init_memory_tab = __esm({
3256
3300
  const { store } = this.deps;
3257
3301
  const lines = [];
3258
3302
  const budget = store.budget ? `\u{1F4DD} ${store.sticky.length}/${store.budget.max}` : "";
3259
- lines.push(theme.accent("\u641C\u7D22: ") + (this._focused ? theme.dim("\u8F93\u5165\u540E Enter \u68C0\u7D22 \xB7 Esc \u5230\u5217\u8868") : theme.dim("i \u805A\u7126\u8F93\u5165\u6846")) + theme.dim(` \xB7 ${budget}`));
3303
+ const meta = [store.retriever, budget].filter(Boolean).join(" \xB7 ");
3304
+ lines.push(theme.accent("\u641C\u7D22: ") + (this._focused ? theme.dim("\u8F93\u5165\u540E Enter \u68C0\u7D22 \xB7 Esc \u5230\u5217\u8868") : theme.dim("i \u805A\u7126\u8F93\u5165\u6846")) + theme.dim(` \xB7 ${meta}`));
3260
3305
  lines.push(theme.accent(`\u68C0\u7D22\u7ED3\u679C (${store.results.length})`));
3261
3306
  if (store.results.length === 0) lines.push(theme.dim(" \uFF08\u7A7A\u2014\u2014\u5728\u4E0A\u65B9\u8F93\u5165\u5173\u952E\u8BCD\uFF09"));
3262
3307
  store.results.forEach((u, i) => lines.push(memoryLine(u, i === this.selected)));