@jack200714/mafw 4.8.0 → 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.
Files changed (42) hide show
  1. package/README.md +27 -3
  2. package/gateway/dist/core/manager/goal-snapshot.js +2 -2
  3. package/gateway/dist/core/manager/manager-session-runtime.js +59 -0
  4. package/gateway/dist/core/manager/milestone-push.js +25 -10
  5. package/gateway/dist/index.js +465 -440
  6. package/gateway/dist/media/media-plugin-loader.js +25 -1
  7. package/gateway/dist/media/resolve-prompt.js +20 -0
  8. package/gateway/dist/memory/gateway-db.js +23 -0
  9. package/gateway/dist/opencode-adapter.js +53 -4
  10. package/gateway/dist/plugins/package-context.js +24 -0
  11. package/gateway/dist/plugins/package-host.js +331 -0
  12. package/gateway/dist/plugins/package-types.js +2 -0
  13. package/gateway/dist/recall/gateway-db-migrate.js +5 -2
  14. package/gateway/dist/recall/redact.js +53 -0
  15. package/gateway/dist/recall/turn-pipeline.js +2 -0
  16. package/gateway/dist/routes/event-publish.js +44 -0
  17. package/gateway/dist/routes/plugins.js +4 -1
  18. package/gateway/dist/routes/registry.js +125 -0
  19. package/gateway/dist/routes/route-catalog.js +192 -0
  20. package/gateway/dist/routes/triage-dismiss.js +32 -0
  21. package/gateway/dist/routes/waitwhat-command.js +43 -0
  22. package/gateway/dist/routes/wave1-handlers.js +62 -0
  23. package/gateway/dist/routes/wave2-handlers.js +47 -0
  24. package/gateway/dist/runtime/contract.js +4 -1
  25. package/gateway/dist/runtime/event-broadcast.js +8 -0
  26. package/gateway/dist/runtime/loader.js +22 -1
  27. package/gateway/dist/runtime/normalize.js +13 -0
  28. package/gateway/dist/runtime/opencode-runtime.js +18 -2
  29. package/gateway/dist/runtime/pi/pi-approval-bridge.js +12 -2
  30. package/gateway/dist/runtime/pi/pi-approval-extension.js +11 -3
  31. package/gateway/dist/runtime/pi/pi-session.js +21 -3
  32. package/gateway/dist/runtime/plugins/pi-runtime.js +6 -3
  33. package/gateway/dist/runtime/serve-sidecar.js +4 -1
  34. package/gateway/dist/runtime/serve-supervisor.js +19 -20
  35. package/gateway/dist/runtime/validate.js +39 -0
  36. package/gateway/dist/skills/manager-identity.js +6 -1
  37. package/gateway/dist/usage/builtin-plugins/gateway.js +91 -36
  38. package/gateway/dist/usage/plugin-context.js +42 -2
  39. package/gateway/dist/usage/plugin-loader.js +32 -2
  40. package/gateway/package.json +2 -1
  41. package/package.json +3 -1
  42. package/packages/tui/dist/cli.js +114 -51
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "name": "mafw-gateway",
3
- "version": "4.8.0",
3
+ "version": "4.10.0",
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.8.0",
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",
@@ -14,6 +14,8 @@
14
14
  "postinstall": "node -e \"var p=require('path'),f=require('fs'),d=p.join(__dirname,'gateway'),ts=p.join(d,'node_modules','typescript','bin','tsc');if(f.existsSync(d)){if(f.existsSync(ts)){console.log('[mafw] gateway dev deps present, skip prod install')}else{require('child_process').execSync('npm install --omit=dev --no-audit --no-fund --loglevel=error',{cwd:d,stdio:'inherit'})}}\"",
15
15
  "prepare": "node -e \"var p=require('path'),f=require('fs'),ts=p.join(__dirname,'gateway','node_modules','typescript','bin','tsc');if(!f.existsSync(ts)){console.log('[mafw] gateway dev deps missing, skip prepare build (fresh CI install)');process.exit(0)}require('child_process').execSync('npm run build',{cwd:__dirname,stdio:'inherit'})\"",
16
16
  "pack:install": "npm run build && npm pack && npm install -g jack200714-mafw-*.tgz && mafw version",
17
+ "version:set": "node scripts/bump-version.mjs",
18
+ "version:check": "node scripts/bump-version.mjs --check",
17
19
  "test": "npm test --prefix gateway",
18
20
  "test:unit": "npm test --prefix gateway",
19
21
  "test:tui": "node --test packages/tui/tests/*.test.ts"
@@ -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");
@@ -380,13 +387,13 @@ var require_client = __commonJS({
380
387
  return { id: data.projectDir || ".", worktree: data.projectDir || "." };
381
388
  },
382
389
  setCurrent: async (path) => {
383
- await this.request("/api/projects/register", {
390
+ await this.request("/register", {
384
391
  method: "POST",
385
392
  body: JSON.stringify({ projectDir: path, mafwDir: path + "/.mafw" })
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,10 +419,19 @@ var require_client = __commonJS({
412
419
  }
413
420
  };
414
421
  },
415
- /** SSE 连接状态(onopen/onerror 维护;供监督器健康轮询)。 */
416
- connected: () => this._sse.connected
422
+ /** SSE 杩炴帴鐘舵€侊紙onopen/onerror 缁存姢锛涗緵鐩戠潱鍣ㄥ仴搴疯疆璇級銆?*/
423
+ connected: () => this._sse.connected,
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 閫氱煡璇箟锛屾棤娉ㄥ唽鍒讹級銆?*/
428
+ publish: async (event) => this.request("/api/events", {
429
+ method: "POST",
430
+ headers: { "Content-Type": "application/json" },
431
+ body: JSON.stringify(event)
432
+ })
417
433
  };
418
- // ── Runtime ──
434
+ // 鈹€鈹€ Runtime 鈹€鈹€
419
435
  runtime = {
420
436
  /** Get active runtime identity, capabilities, and plugin scan state. */
421
437
  get: async () => {
@@ -427,7 +443,7 @@ var require_client = __commonJS({
427
443
  * @returns The new active runtime state.
428
444
  */
429
445
  switch: async (plugin) => {
430
- const res = await fetch(`${this.baseUrl}/api/runtime/switch`, {
446
+ const res = await this.fetchPath(`/api/runtime/switch`, {
431
447
  method: "POST",
432
448
  headers: { "Content-Type": "application/json" },
433
449
  body: JSON.stringify({ plugin })
@@ -440,7 +456,7 @@ var require_client = __commonJS({
440
456
  },
441
457
  /** Restart the agent runtime (opencode serve). */
442
458
  restartAgent: async () => {
443
- const res = await fetch(`${this.baseUrl}/api/runtime/restart-agent`, {
459
+ const res = await this.fetchPath(`/api/runtime/restart-agent`, {
444
460
  method: "POST",
445
461
  headers: { "Content-Type": "application/json" }
446
462
  });
@@ -451,7 +467,7 @@ var require_client = __commonJS({
451
467
  return res.json();
452
468
  }
453
469
  };
454
- // ── Plugins Hub ──
470
+ // 鈹€鈹€ Plugins Hub 鈹€鈹€
455
471
  plugins = {
456
472
  list: async () => this.request("/api/plugins"),
457
473
  install: async (input) => {
@@ -460,7 +476,7 @@ var require_client = __commonJS({
460
476
  params.set("type", input.type);
461
477
  if (input.overwrite)
462
478
  params.set("overwrite", "1");
463
- const res = await this.fetchImpl(`${this.baseUrl}/api/plugins/install?${params.toString()}`, {
479
+ const res = await this.fetchPath(`/api/plugins/install?${params.toString()}`, {
464
480
  method: "POST",
465
481
  headers: { "Content-Type": "application/octet-stream" },
466
482
  body: input.bytes
@@ -472,7 +488,7 @@ var require_client = __commonJS({
472
488
  return res.json();
473
489
  },
474
490
  enable: async (type, filename) => {
475
- const res = await this.fetchImpl(`${this.baseUrl}/api/plugins/enable`, {
491
+ const res = await this.fetchPath(`/api/plugins/enable`, {
476
492
  method: "POST",
477
493
  headers: { "Content-Type": "application/json" },
478
494
  body: JSON.stringify({ type, filename })
@@ -484,7 +500,7 @@ var require_client = __commonJS({
484
500
  return res.json();
485
501
  },
486
502
  disable: async (type, filename) => {
487
- const res = await this.fetchImpl(`${this.baseUrl}/api/plugins/disable`, {
503
+ const res = await this.fetchPath(`/api/plugins/disable`, {
488
504
  method: "POST",
489
505
  headers: { "Content-Type": "application/json" },
490
506
  body: JSON.stringify({ type, filename })
@@ -496,7 +512,7 @@ var require_client = __commonJS({
496
512
  return res.json();
497
513
  },
498
514
  delete: async (type, filename) => {
499
- const res = await this.fetchImpl(`${this.baseUrl}/api/plugins/delete`, {
515
+ const res = await this.fetchPath(`/api/plugins/delete`, {
500
516
  method: "POST",
501
517
  headers: { "Content-Type": "application/json" },
502
518
  body: JSON.stringify({ type, filename })
@@ -508,7 +524,7 @@ var require_client = __commonJS({
508
524
  return res.json();
509
525
  }
510
526
  };
511
- // ── Config ──
527
+ // 鈹€鈹€ Config 鈹€鈹€
512
528
  config = {
513
529
  get: async (key) => {
514
530
  const data = await this.request("/api/config");
@@ -517,21 +533,21 @@ var require_client = __commonJS({
517
533
  set: async (key, value) => {
518
534
  const current = await this.request("/api/config");
519
535
  current[key] = value;
520
- await fetch(`${this.baseUrl}/api/config`, {
536
+ await this.fetchPath(`/api/config`, {
521
537
  method: "PUT",
522
538
  headers: { "Content-Type": "application/json" },
523
539
  body: JSON.stringify(current)
524
540
  });
525
541
  }
526
542
  };
527
- // ── OpenCode config (native opencode /config) ──
543
+ // 鈹€鈹€ OpenCode config (native opencode /config) 鈹€鈹€
528
544
  opencodeConfig = {
529
545
  get: async () => {
530
546
  const data = await this.request("/api/opencode-config");
531
547
  return data.config;
532
548
  },
533
549
  update: async (config) => {
534
- const res = await fetch(`${this.baseUrl}/api/opencode-config`, {
550
+ const res = await this.fetchPath(`/api/opencode-config`, {
535
551
  method: "PATCH",
536
552
  headers: { "Content-Type": "application/json" },
537
553
  body: JSON.stringify(config)
@@ -541,7 +557,7 @@ var require_client = __commonJS({
541
557
  return res.json();
542
558
  }
543
559
  };
544
- // ── Goals ──
560
+ // 鈹€鈹€ Goals 鈹€鈹€
545
561
  goals = {
546
562
  list: async () => {
547
563
  const data = await this.request("/api/goals");
@@ -571,9 +587,12 @@ var require_client = __commonJS({
571
587
  method: "POST",
572
588
  body: JSON.stringify(action)
573
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) });
574
593
  }
575
594
  };
576
- // ── Memory ──
595
+ // 鈹€鈹€ Memory 鈹€鈹€
577
596
  memory = {
578
597
  search: async (opts) => {
579
598
  const params = new URLSearchParams({ query: opts.query });
@@ -616,7 +635,7 @@ var require_client = __commonJS({
616
635
  });
617
636
  }
618
637
  };
619
- // ── Approvals ──
638
+ // 鈹€鈹€ Approvals 鈹€鈹€
620
639
  approvals = {
621
640
  list: async () => {
622
641
  const data = await this.request("/api/approvals");
@@ -629,7 +648,7 @@ var require_client = __commonJS({
629
648
  });
630
649
  }
631
650
  };
632
- // ── Triage ──
651
+ // 鈹€鈹€ Triage 鈹€鈹€
633
652
  triage = {
634
653
  list: async () => {
635
654
  const data = await this.request("/api/triage");
@@ -651,7 +670,7 @@ var require_client = __commonJS({
651
670
  });
652
671
  }
653
672
  };
654
- // ── Questions (AskCard proxies the native opencode Question API) ──
673
+ // 鈹€鈹€ Questions (AskCard 鈥?proxies the native opencode Question API) 鈹€鈹€
655
674
  questions = {
656
675
  list: async () => {
657
676
  const data = await this.request("/api/questions");
@@ -667,7 +686,7 @@ var require_client = __commonJS({
667
686
  await this.request(`/api/questions/${id}/reject`, { method: "POST" });
668
687
  }
669
688
  };
670
- // ── Permissions (PermissionCard proxies the native opencode Permission API) ──
689
+ // 鈹€鈹€ Permissions (PermissionCard 鈥?proxies the native opencode Permission API) 鈹€鈹€
671
690
  permissions = {
672
691
  list: async () => {
673
692
  const data = await this.request("/api/permissions");
@@ -680,10 +699,10 @@ var require_client = __commonJS({
680
699
  });
681
700
  }
682
701
  };
683
- // ── Chat ──
702
+ // 鈹€鈹€ Chat 鈹€鈹€
684
703
  chat = {
685
704
  send: async (message, sessionID) => {
686
- const res = await fetch(`${this.baseUrl}/api/chat`, {
705
+ const res = await this.fetchPath(`/api/chat`, {
687
706
  method: "POST",
688
707
  headers: { "Content-Type": "application/json" },
689
708
  body: JSON.stringify({ message, sessionID })
@@ -693,7 +712,7 @@ var require_client = __commonJS({
693
712
  return res.json();
694
713
  },
695
714
  sendEnriched: async (opts) => {
696
- const res = await fetch(`${this.baseUrl}/api/chat/enriched`, {
715
+ const res = await this.fetchPath(`/api/chat/enriched`, {
697
716
  method: "POST",
698
717
  headers: { "Content-Type": "application/json" },
699
718
  body: JSON.stringify(opts)
@@ -703,7 +722,7 @@ var require_client = __commonJS({
703
722
  return res.json();
704
723
  }
705
724
  };
706
- // ── Media (A2A Media Agent) ──
725
+ // 鈹€鈹€ Media (A2A Media Agent) 鈹€鈹€
707
726
  media = {
708
727
  /** List media engine plugins (status + modalities). */
709
728
  plugins: async () => {
@@ -715,7 +734,7 @@ var require_client = __commonJS({
715
734
  * @returns The new media engine configuration.
716
735
  */
717
736
  switch: async (opts) => {
718
- const res = await fetch(`${this.baseUrl}/api/media/switch`, {
737
+ const res = await this.fetchPath(`/api/media/switch`, {
719
738
  method: "POST",
720
739
  headers: { "Content-Type": "application/json" },
721
740
  body: JSON.stringify(opts)
@@ -730,7 +749,7 @@ var require_client = __commonJS({
730
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" }];
731
750
  if (opts.question)
732
751
  parts.push({ text: opts.question });
733
- const res = await fetch(`${this.baseUrl}/a2a`, {
752
+ const res = await this.fetchPath(`/a2a`, {
734
753
  method: "POST",
735
754
  headers: { "Content-Type": "application/json", "A2A-Version": "1.0" },
736
755
  body: JSON.stringify({
@@ -756,12 +775,42 @@ var require_client = __commonJS({
756
775
  if (!task?.id)
757
776
  throw new Error("Vision createTask failed: no task returned");
758
777
  return { id: task.id, contextId: task.contextId, state: task.status?.state || "" };
759
- }
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}`
760
809
  };
761
- // ── TTS (MiMo-V2.5-TTS speech synthesis) ──
810
+ // 鈹€鈹€ TTS (MiMo-V2.5-TTS speech synthesis) 鈹€鈹€
762
811
  tts = {
763
812
  speak: async (opts) => {
764
- const res = await fetch(`${this.baseUrl}/api/tts`, {
813
+ const res = await this.fetchPath(`/api/tts`, {
765
814
  method: "POST",
766
815
  headers: { "Content-Type": "application/json" },
767
816
  body: JSON.stringify(opts)
@@ -778,16 +827,16 @@ var require_client = __commonJS({
778
827
  return res.json();
779
828
  },
780
829
  voices: async () => {
781
- const res = await fetch(`${this.baseUrl}/api/tts/voices`);
830
+ const res = await this.fetchPath(`/api/tts/voices`);
782
831
  if (!res.ok)
783
832
  throw new Error(`TTS voices failed: HTTP ${res.status}`);
784
833
  return res.json();
785
834
  },
786
- /** 流式 TTS:返回 async iterable of base64 PCM16 chunks(24kHz mono)。 */
835
+ /** 娴佸紡 TTS锛氳繑鍥?async iterable of base64 PCM16 chunks锛?4kHz mono锛夈€?*/
787
836
  speakStream: (opts) => {
788
- const base = this.baseUrl;
837
+ const client = this;
789
838
  return (async function* () {
790
- const res = await fetch(`${base}/api/tts/stream`, {
839
+ const res = await client.fetchPath(`/api/tts/stream`, {
791
840
  method: "POST",
792
841
  headers: { "Content-Type": "application/json" },
793
842
  body: JSON.stringify(opts)
@@ -823,9 +872,11 @@ var require_client = __commonJS({
823
872
  reader.releaseLock();
824
873
  }
825
874
  })();
826
- }
875
+ },
876
+ /** 娴佸紡 TTS 绔偣 URL锛堝绾﹀綊 SDK锛欼PC 鏃犳硶鍏嬮殕 SSE 娴侊紝renderer 鐩磋繛 fetch 鏃剁敤姝ゆ瀯閫狅級銆?*/
877
+ streamUrl: () => `${this.baseUrl}/api/tts/stream`
827
878
  };
828
- // ── Providers & Agents (composer model pill / @agent mention) ──
879
+ // 鈹€鈹€ Providers & Agents (composer model pill / @agent mention) 鈹€鈹€
829
880
  providers = {
830
881
  list: async () => {
831
882
  const data = await this.request("/api/provider");
@@ -838,13 +889,13 @@ var require_client = __commonJS({
838
889
  return data.items || [];
839
890
  }
840
891
  };
841
- // ── Model config (recall worker + media models) ──
892
+ // 鈹€鈹€ Model config (recall worker + media models) 鈹€鈹€
842
893
  models = {
843
894
  get: async () => {
844
895
  return this.request("/api/model-config");
845
896
  },
846
897
  update: async (opts) => {
847
- const res = await fetch(`${this.baseUrl}/api/model-config`, {
898
+ const res = await this.fetchPath(`/api/model-config`, {
848
899
  method: "POST",
849
900
  headers: { "Content-Type": "application/json" },
850
901
  body: JSON.stringify(opts)
@@ -856,13 +907,13 @@ var require_client = __commonJS({
856
907
  return res.json();
857
908
  }
858
909
  };
859
- // ── Memory embedding config (hot-swap engine, no restart) ──
910
+ // 鈹€鈹€ Memory embedding config (hot-swap engine, no restart) 鈹€鈹€
860
911
  embedding = {
861
912
  get: async () => {
862
913
  return this.request("/api/memory/embedding-config");
863
914
  },
864
915
  update: async (opts) => {
865
- const res = await fetch(`${this.baseUrl}/api/memory/embedding-config`, {
916
+ const res = await this.fetchPath(`/api/memory/embedding-config`, {
866
917
  method: "POST",
867
918
  headers: { "Content-Type": "application/json" },
868
919
  body: JSON.stringify(opts)
@@ -874,7 +925,7 @@ var require_client = __commonJS({
874
925
  return res.json();
875
926
  }
876
927
  };
877
- // ── Automations ──
928
+ // 鈹€鈹€ Automations 鈹€鈹€
878
929
  automations = {
879
930
  list: async () => {
880
931
  const data = await this.request("/api/automations");
@@ -886,7 +937,7 @@ var require_client = __commonJS({
886
937
  body: JSON.stringify({ enabled })
887
938
  });
888
939
  },
889
- /** 起草规则(enabled=false 落盘,需手动启用)。返回校验结果。 */
940
+ /** 璧疯崏瑙勫垯锛坋nabled=false 钀界洏锛岄渶鎵嬪姩鍚敤锛夈€傝繑鍥炴牎楠岀粨鏋溿€?*/
890
941
  draft: async (input) => {
891
942
  return this.request("/api/automations/draft", {
892
943
  method: "POST",
@@ -1831,6 +1882,7 @@ var init_command_registry = __esm({
1831
1882
  { name: "status", description: "\u4F1A\u8BDD\u72B6\u6001\u56DE\u987E\uFF08\u672C\u5730\u8BA1\u7B97\uFF09", category: "\u4F1A\u8BDD", immediate: true },
1832
1883
  { name: "queue", description: "\u6392\u961F\u6D88\u606F\u7BA1\u7406\uFF08\u6536\u56DE/\u4E22\u5F03\uFF09", category: "\u4F1A\u8BDD", aliases: ["q"], immediate: true },
1833
1884
  { name: "btw", description: "\u652F\u7EBF\u95EE\u7B54\uFF1A/btw <\u95EE\u9898>", category: "\u4F1A\u8BDD" },
1885
+ { name: "waitwhat", description: "\u6CA1\u542C\u61C2\uFF1A\u7528\u7B80\u660E\u8BED\u8A00+\u9879\u76EE\u672F\u8BED\u91CD\u8FF0\u4E0A\u4E00\u6761\u56DE\u590D", category: "\u4F1A\u8BDD", immediate: true },
1834
1886
  { name: "compact", description: "\u538B\u7F29\u5F53\u524D\u4F1A\u8BDD\u4E0A\u4E0B\u6587", category: "\u4E0A\u4E0B\u6587", destructive: true, immediate: true },
1835
1887
  { name: "undo", description: "\u56DE\u9000\u6700\u540E\u4E00\u8F6E\u5BF9\u8BDD", category: "\u4E0A\u4E0B\u6587", destructive: true },
1836
1888
  { name: "redo", description: "\u6062\u590D\u4E0A\u4E00\u6B21\u56DE\u9000", category: "\u4E0A\u4E0B\u6587", destructive: true },
@@ -2165,6 +2217,8 @@ function createSlashHandler(deps) {
2165
2217
  case "status":
2166
2218
  deps.showStatusRecap();
2167
2219
  return null;
2220
+ case "waitwhat":
2221
+ return deps.waitwhat();
2168
2222
  case "queue":
2169
2223
  await deps.showQueueManager();
2170
2224
  return null;
@@ -3246,7 +3300,8 @@ var init_memory_tab = __esm({
3246
3300
  const { store } = this.deps;
3247
3301
  const lines = [];
3248
3302
  const budget = store.budget ? `\u{1F4DD} ${store.sticky.length}/${store.budget.max}` : "";
3249
- 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}`));
3250
3305
  lines.push(theme.accent(`\u68C0\u7D22\u7ED3\u679C (${store.results.length})`));
3251
3306
  if (store.results.length === 0) lines.push(theme.dim(" \uFF08\u7A7A\u2014\u2014\u5728\u4E0A\u65B9\u8F93\u5165\u5173\u952E\u8BCD\uFF09"));
3252
3307
  store.results.forEach((u, i) => lines.push(memoryLine(u, i === this.selected)));
@@ -3921,6 +3976,14 @@ async function runApp(opts) {
3921
3976
  if ("error" in r) return `btw \u5931\u8D25: ${r.error}`;
3922
3977
  return null;
3923
3978
  },
3979
+ waitwhat: async () => {
3980
+ const sid = chatStore.sessionID;
3981
+ if (!sid) return "\u5F53\u524D\u65E0\u4F1A\u8BDD";
3982
+ const r = await client.mafwCommands.run({ command: "waitwhat", sessionID: sid }).catch((e) => ({ error: e.message }));
3983
+ if ("error" in r) return `waitwhat \u5931\u8D25: ${r.error}`;
3984
+ if (r.ok === false) return `waitwhat: ${r.error ?? "\u6CA1\u6709\u53EF\u91CD\u8FF0\u7684\u56DE\u590D"}`;
3985
+ return null;
3986
+ },
3924
3987
  showSessionPicker,
3925
3988
  showQueueManager,
3926
3989
  showModelPicker,