@mingxy/ocosay 1.1.0 → 1.1.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 (73) hide show
  1. package/README.md +43 -653
  2. package/dist/config.js +2 -1
  3. package/dist/core/logger.d.ts +46 -0
  4. package/dist/core/logger.js +126 -0
  5. package/dist/core/notification.d.ts +27 -0
  6. package/dist/core/notification.js +86 -0
  7. package/dist/core/speaker.js +5 -35
  8. package/dist/core/stream-reader.js +2 -1
  9. package/dist/index.d.ts +1 -0
  10. package/dist/index.js +1 -0
  11. package/dist/package.json +7 -4
  12. package/dist/plugin.js +220 -197
  13. package/dist/tools/tts.js +2 -1
  14. package/dist/utils/logger.d.ts +6 -0
  15. package/dist/utils/logger.js +42 -6
  16. package/package.json +4 -2
  17. package/scripts/compile-native.cjs +48 -0
  18. package/scripts/install-portaudio.cjs +117 -0
  19. package/.idea/UniappTool.xml +0 -10
  20. package/.idea/inspectionProfiles/profiles_settings.xml +0 -5
  21. package/.idea/modules.xml +0 -8
  22. package/.idea/ocosay.iml +0 -12
  23. package/.idea/vcs.xml +0 -6
  24. package/.sisyphus/boulder.json +0 -23
  25. package/dist/config.d.ts.map +0 -1
  26. package/dist/config.js.map +0 -1
  27. package/dist/core/backends/afplay-backend.d.ts.map +0 -1
  28. package/dist/core/backends/afplay-backend.js.map +0 -1
  29. package/dist/core/backends/aplay-backend.d.ts.map +0 -1
  30. package/dist/core/backends/aplay-backend.js.map +0 -1
  31. package/dist/core/backends/base.d.ts.map +0 -1
  32. package/dist/core/backends/base.js.map +0 -1
  33. package/dist/core/backends/howler-backend.d.ts.map +0 -1
  34. package/dist/core/backends/howler-backend.js.map +0 -1
  35. package/dist/core/backends/index.d.ts.map +0 -1
  36. package/dist/core/backends/index.js.map +0 -1
  37. package/dist/core/backends/naudiodon-backend.d.ts.map +0 -1
  38. package/dist/core/backends/naudiodon-backend.js.map +0 -1
  39. package/dist/core/backends/powershell-backend.d.ts.map +0 -1
  40. package/dist/core/backends/powershell-backend.js.map +0 -1
  41. package/dist/core/player.d.ts.map +0 -1
  42. package/dist/core/player.js.map +0 -1
  43. package/dist/core/speaker.d.ts.map +0 -1
  44. package/dist/core/speaker.js.map +0 -1
  45. package/dist/core/stream-player.d.ts.map +0 -1
  46. package/dist/core/stream-player.js.map +0 -1
  47. package/dist/core/stream-reader.d.ts.map +0 -1
  48. package/dist/core/stream-reader.js.map +0 -1
  49. package/dist/core/streaming-synthesizer.d.ts.map +0 -1
  50. package/dist/core/streaming-synthesizer.js.map +0 -1
  51. package/dist/core/types.d.ts.map +0 -1
  52. package/dist/core/types.js.map +0 -1
  53. package/dist/index.d.ts.map +0 -1
  54. package/dist/index.js.map +0 -1
  55. package/dist/plugin.d.ts.map +0 -1
  56. package/dist/plugin.js.map +0 -7
  57. package/dist/providers/base.d.ts.map +0 -1
  58. package/dist/providers/base.js.map +0 -1
  59. package/dist/providers/minimax.d.ts.map +0 -1
  60. package/dist/providers/minimax.js.map +0 -1
  61. package/dist/services/notification-service.d.ts.map +0 -1
  62. package/dist/services/notification-service.js.map +0 -1
  63. package/dist/services/speaker-service.d.ts.map +0 -1
  64. package/dist/services/speaker-service.js.map +0 -1
  65. package/dist/services/streaming-service.d.ts.map +0 -1
  66. package/dist/services/streaming-service.js.map +0 -1
  67. package/dist/tools/tts.d.ts.map +0 -1
  68. package/dist/tools/tts.js.map +0 -1
  69. package/dist/types/config.d.ts.map +0 -1
  70. package/dist/types/config.js.map +0 -1
  71. package/dist/utils/logger.d.ts.map +0 -1
  72. package/dist/utils/logger.js.map +0 -1
  73. package/tsconfig.jest.json +0 -21
package/dist/plugin.js CHANGED
@@ -5049,15 +5049,15 @@ var require_tools = __commonJS({
5049
5049
  return data + propStr + msgStr + end;
5050
5050
  }
5051
5051
  }
5052
- function asChindings(instance2, bindings) {
5052
+ function asChindings(instance, bindings) {
5053
5053
  let value;
5054
- let data = instance2[chindingsSym];
5055
- const stringify2 = instance2[stringifySym];
5056
- const stringifySafe = instance2[stringifySafeSym];
5057
- const stringifiers = instance2[stringifiersSym];
5054
+ let data = instance[chindingsSym];
5055
+ const stringify2 = instance[stringifySym];
5056
+ const stringifySafe = instance[stringifySafeSym];
5057
+ const stringifiers = instance[stringifiersSym];
5058
5058
  const wildcardStringifier = stringifiers[wildcardFirstSym];
5059
- const serializers = instance2[serializersSym];
5060
- const formatter = instance2[formattersSym].bindings;
5059
+ const serializers = instance[serializersSym];
5060
+ const formatter = instance[formattersSym].bindings;
5061
5061
  bindings = formatter(bindings);
5062
5062
  for (const key in bindings) {
5063
5063
  value = bindings[key];
@@ -5110,7 +5110,7 @@ var require_tools = __commonJS({
5110
5110
  }
5111
5111
  }
5112
5112
  function createArgsNormalizer(defaultOptions) {
5113
- return function normalizeArgs(instance2, caller, opts = {}, stream2) {
5113
+ return function normalizeArgs(instance, caller, opts = {}, stream2) {
5114
5114
  if (typeof opts === "string") {
5115
5115
  stream2 = buildSafeSonicBoom({ dest: opts });
5116
5116
  opts = {};
@@ -5262,16 +5262,16 @@ var require_levels = __commonJS({
5262
5262
  o[k] = '{"level":' + Number(k);
5263
5263
  return o;
5264
5264
  }, {});
5265
- function genLsCache(instance2) {
5266
- const formatter = instance2[formattersSym].level;
5267
- const { labels } = instance2.levels;
5265
+ function genLsCache(instance) {
5266
+ const formatter = instance[formattersSym].level;
5267
+ const { labels } = instance.levels;
5268
5268
  const cache = {};
5269
5269
  for (const label in labels) {
5270
5270
  const level2 = formatter(labels[label], Number(label));
5271
5271
  cache[label] = JSON.stringify(level2).slice(0, -1);
5272
5272
  }
5273
- instance2[lsCacheSym] = cache;
5274
- return instance2;
5273
+ instance[lsCacheSym] = cache;
5274
+ return instance;
5275
5275
  }
5276
5276
  function isStandardLevel(level2, useOnlyCustomLevels) {
5277
5277
  if (useOnlyCustomLevels) {
@@ -5516,49 +5516,49 @@ var require_proto = __commonJS({
5516
5516
  }
5517
5517
  const serializers = this[serializersSym];
5518
5518
  const formatters = this[formattersSym];
5519
- const instance2 = Object.create(this);
5519
+ const instance = Object.create(this);
5520
5520
  if (options == null) {
5521
- if (instance2[formattersSym].bindings !== resetChildingsFormatter) {
5522
- instance2[formattersSym] = buildFormatters(
5521
+ if (instance[formattersSym].bindings !== resetChildingsFormatter) {
5522
+ instance[formattersSym] = buildFormatters(
5523
5523
  formatters.level,
5524
5524
  resetChildingsFormatter,
5525
5525
  formatters.log
5526
5526
  );
5527
5527
  }
5528
- instance2[chindingsSym] = asChindings(instance2, bindings2);
5528
+ instance[chindingsSym] = asChindings(instance, bindings2);
5529
5529
  if (this.onChild !== noop) {
5530
- this.onChild(instance2);
5530
+ this.onChild(instance);
5531
5531
  }
5532
- return instance2;
5532
+ return instance;
5533
5533
  }
5534
5534
  if (options.hasOwnProperty("serializers") === true) {
5535
- instance2[serializersSym] = /* @__PURE__ */ Object.create(null);
5535
+ instance[serializersSym] = /* @__PURE__ */ Object.create(null);
5536
5536
  for (const k in serializers) {
5537
- instance2[serializersSym][k] = serializers[k];
5537
+ instance[serializersSym][k] = serializers[k];
5538
5538
  }
5539
5539
  const parentSymbols = Object.getOwnPropertySymbols(serializers);
5540
5540
  for (var i = 0; i < parentSymbols.length; i++) {
5541
5541
  const ks = parentSymbols[i];
5542
- instance2[serializersSym][ks] = serializers[ks];
5542
+ instance[serializersSym][ks] = serializers[ks];
5543
5543
  }
5544
5544
  for (const bk in options.serializers) {
5545
- instance2[serializersSym][bk] = options.serializers[bk];
5545
+ instance[serializersSym][bk] = options.serializers[bk];
5546
5546
  }
5547
5547
  const bindingsSymbols = Object.getOwnPropertySymbols(options.serializers);
5548
5548
  for (var bi = 0; bi < bindingsSymbols.length; bi++) {
5549
5549
  const bks = bindingsSymbols[bi];
5550
- instance2[serializersSym][bks] = options.serializers[bks];
5550
+ instance[serializersSym][bks] = options.serializers[bks];
5551
5551
  }
5552
- } else instance2[serializersSym] = serializers;
5552
+ } else instance[serializersSym] = serializers;
5553
5553
  if (options.hasOwnProperty("formatters")) {
5554
5554
  const { level: level2, bindings: chindings, log } = options.formatters;
5555
- instance2[formattersSym] = buildFormatters(
5555
+ instance[formattersSym] = buildFormatters(
5556
5556
  level2 || formatters.level,
5557
5557
  chindings || resetChildingsFormatter,
5558
5558
  log || formatters.log
5559
5559
  );
5560
5560
  } else {
5561
- instance2[formattersSym] = buildFormatters(
5561
+ instance[formattersSym] = buildFormatters(
5562
5562
  formatters.level,
5563
5563
  resetChildingsFormatter,
5564
5564
  formatters.log
@@ -5566,27 +5566,27 @@ var require_proto = __commonJS({
5566
5566
  }
5567
5567
  if (options.hasOwnProperty("customLevels") === true) {
5568
5568
  assertNoLevelCollisions(this.levels, options.customLevels);
5569
- instance2.levels = mappings(options.customLevels, instance2[useOnlyCustomLevelsSym]);
5570
- genLsCache(instance2);
5569
+ instance.levels = mappings(options.customLevels, instance[useOnlyCustomLevelsSym]);
5570
+ genLsCache(instance);
5571
5571
  }
5572
5572
  if (typeof options.redact === "object" && options.redact !== null || Array.isArray(options.redact)) {
5573
- instance2.redact = options.redact;
5574
- const stringifiers = redaction(instance2.redact, stringify);
5573
+ instance.redact = options.redact;
5574
+ const stringifiers = redaction(instance.redact, stringify);
5575
5575
  const formatOpts = { stringify: stringifiers[redactFmtSym] };
5576
- instance2[stringifySym] = stringify;
5577
- instance2[stringifiersSym] = stringifiers;
5578
- instance2[formatOptsSym] = formatOpts;
5576
+ instance[stringifySym] = stringify;
5577
+ instance[stringifiersSym] = stringifiers;
5578
+ instance[formatOptsSym] = formatOpts;
5579
5579
  }
5580
5580
  if (typeof options.msgPrefix === "string") {
5581
- instance2[msgPrefixSym] = (this[msgPrefixSym] || "") + options.msgPrefix;
5581
+ instance[msgPrefixSym] = (this[msgPrefixSym] || "") + options.msgPrefix;
5582
5582
  }
5583
- instance2[chindingsSym] = asChindings(instance2, bindings2);
5583
+ instance[chindingsSym] = asChindings(instance, bindings2);
5584
5584
  if (options.level !== void 0 && options.level !== this.level || options.hasOwnProperty("customLevels")) {
5585
5585
  const childLevel = options.level || this.level;
5586
- instance2[setLevelSym](childLevel);
5586
+ instance[setLevelSym](childLevel);
5587
5587
  }
5588
- this.onChild(instance2);
5589
- return instance2;
5588
+ this.onChild(instance);
5589
+ return instance;
5590
5590
  }
5591
5591
  function bindings() {
5592
5592
  const chindings = this[chindingsSym];
@@ -6287,11 +6287,11 @@ var require_multistream = __commonJS({
6287
6287
  function write(data) {
6288
6288
  let dest;
6289
6289
  const level2 = this.lastLevel;
6290
- const { streams: streams2 } = this;
6290
+ const { streams } = this;
6291
6291
  let recordedLevel = 0;
6292
6292
  let stream2;
6293
- for (let i = initLoopVar(streams2.length, opts.dedupe); checkLoopVar(i, streams2.length, opts.dedupe); i = adjustLoopVar(i, opts.dedupe)) {
6294
- dest = streams2[i];
6293
+ for (let i = initLoopVar(streams.length, opts.dedupe); checkLoopVar(i, streams.length, opts.dedupe); i = adjustLoopVar(i, opts.dedupe)) {
6294
+ dest = streams[i];
6295
6295
  if (dest.level <= level2) {
6296
6296
  if (recordedLevel !== 0 && recordedLevel !== dest.level) {
6297
6297
  break;
@@ -6337,7 +6337,7 @@ var require_multistream = __commonJS({
6337
6337
  if (!isStream) {
6338
6338
  throw Error("stream object needs to implement either StreamEntry or DestinationStream interface");
6339
6339
  }
6340
- const { streams: streams2, streamLevels: streamLevels2 } = this;
6340
+ const { streams, streamLevels: streamLevels2 } = this;
6341
6341
  let level2;
6342
6342
  if (typeof dest.levelVal === "number") {
6343
6343
  level2 = dest.levelVal;
@@ -6354,18 +6354,18 @@ var require_multistream = __commonJS({
6354
6354
  levelVal: void 0,
6355
6355
  id: ++res.lastId
6356
6356
  };
6357
- streams2.unshift(dest_);
6358
- streams2.sort(compareByLevel);
6359
- this.minLevel = streams2[0].level;
6357
+ streams.unshift(dest_);
6358
+ streams.sort(compareByLevel);
6359
+ this.minLevel = streams[0].level;
6360
6360
  return res;
6361
6361
  }
6362
6362
  function remove(id2) {
6363
- const { streams: streams2 } = this;
6364
- const index = streams2.findIndex((s) => s.id === id2);
6363
+ const { streams } = this;
6364
+ const index = streams.findIndex((s) => s.id === id2);
6365
6365
  if (index >= 0) {
6366
- streams2.splice(index, 1);
6367
- streams2.sort(compareByLevel);
6368
- this.minLevel = streams2.length > 0 ? streams2[0].level : -1;
6366
+ streams.splice(index, 1);
6367
+ streams.sort(compareByLevel);
6368
+ this.minLevel = streams.length > 0 ? streams[0].level : -1;
6369
6369
  }
6370
6370
  return res;
6371
6371
  }
@@ -6378,9 +6378,9 @@ var require_multistream = __commonJS({
6378
6378
  }
6379
6379
  }
6380
6380
  function clone(level2) {
6381
- const streams2 = new Array(this.streams.length);
6382
- for (let i = 0; i < streams2.length; i++) {
6383
- streams2[i] = {
6381
+ const streams = new Array(this.streams.length);
6382
+ for (let i = 0; i < streams.length; i++) {
6383
+ streams[i] = {
6384
6384
  level: level2,
6385
6385
  stream: this.streams[i].stream
6386
6386
  };
@@ -6390,7 +6390,7 @@ var require_multistream = __commonJS({
6390
6390
  add,
6391
6391
  remove,
6392
6392
  minLevel: level2,
6393
- streams: streams2,
6393
+ streams,
6394
6394
  clone,
6395
6395
  emit,
6396
6396
  flushSync,
@@ -6502,8 +6502,8 @@ var require_pino = __commonJS({
6502
6502
  var normalize = createArgsNormalizer(defaultOptions);
6503
6503
  var serializers = Object.assign(/* @__PURE__ */ Object.create(null), stdSerializers);
6504
6504
  function pino2(...args) {
6505
- const instance2 = {};
6506
- const { opts, stream: stream2 } = normalize(instance2, caller(), ...args);
6505
+ const instance = {};
6506
+ const { opts, stream: stream2 } = normalize(instance, caller(), ...args);
6507
6507
  if (opts.level && typeof opts.level === "string" && DEFAULT_LEVELS[opts.level.toLowerCase()] !== void 0) opts.level = opts.level.toLowerCase();
6508
6508
  const {
6509
6509
  redact,
@@ -6571,7 +6571,7 @@ var require_pino = __commonJS({
6571
6571
  }
6572
6572
  assertLevelComparison(levelComparison);
6573
6573
  const levelCompFunc = genLevelComparison(levelComparison);
6574
- Object.assign(instance2, {
6574
+ Object.assign(instance, {
6575
6575
  levels,
6576
6576
  [levelCompSym]: levelCompFunc,
6577
6577
  [useOnlyCustomLevelsSym]: useOnlyCustomLevels,
@@ -6598,10 +6598,10 @@ var require_pino = __commonJS({
6598
6598
  onChild,
6599
6599
  [msgPrefixSym]: msgPrefix
6600
6600
  });
6601
- Object.setPrototypeOf(instance2, proto());
6602
- genLsCache(instance2);
6603
- instance2[setLevelSym](level2);
6604
- return instance2;
6601
+ Object.setPrototypeOf(instance, proto());
6602
+ genLsCache(instance);
6603
+ instance[setLevelSym](level2);
6604
+ return instance;
6605
6605
  }
6606
6606
  module.exports = pino2;
6607
6607
  module.exports.destination = (dest = process.stdout.fd) => {
@@ -7391,6 +7391,7 @@ var HowlerBackend = class {
7391
7391
 
7392
7392
  // src/utils/logger.ts
7393
7393
  var import_pino = __toESM(require_pino(), 1);
7394
+ import { Transform } from "stream";
7394
7395
  import { homedir } from "os";
7395
7396
  import { join as join4 } from "path";
7396
7397
  import { existsSync as existsSync4, mkdirSync } from "fs";
@@ -7402,22 +7403,52 @@ if (!existsSync4(logDir)) {
7402
7403
  } catch {
7403
7404
  }
7404
7405
  }
7405
- var streams = [
7406
- { stream: process.stdout }
7407
- ];
7406
+ var level = process.env.NODE_ENV !== "production" ? "debug" : process.env.OCOSAY_LOG_LEVEL || "info";
7407
+ var formatLog = (log) => {
7408
+ const time = log.time ? new Date(log.time).toISOString().replace("T", " ").replace("Z", "") : "";
7409
+ const levelStr = log.level === 30 ? "INFO" : log.level === 40 ? "WARNING" : log.level === 50 ? "ERROR" : "DEBUG";
7410
+ const module = log.module || "App";
7411
+ const msg = log.msg || "";
7412
+ return `[Ocosay][${time}][${levelStr}][${module}] \u5BF9\u5E94\u4E8B\u4EF6{${msg}}
7413
+ `;
7414
+ };
7415
+ var createFormatStream = () => new Transform({
7416
+ transform(chunk, _encoding, callback) {
7417
+ try {
7418
+ const log = JSON.parse(chunk.toString());
7419
+ this.push(formatLog(log));
7420
+ } catch {
7421
+ this.push(chunk);
7422
+ }
7423
+ callback();
7424
+ }
7425
+ });
7426
+ var stdoutStream = createFormatStream();
7427
+ stdoutStream.pipe(process.stdout);
7428
+ var fileStream = null;
7408
7429
  try {
7409
- streams.push({ stream: import_pino.default.destination({ dest: logFile, mkdir: true }) });
7430
+ const fileDest = import_pino.default.destination({ dest: logFile, mkdir: true });
7431
+ fileStream = createFormatStream();
7432
+ fileStream.pipe(fileDest);
7410
7433
  } catch {
7411
7434
  }
7412
- var level = process.env.NODE_ENV !== "production" ? "debug" : process.env.OCOSAY_LOG_LEVEL || "info";
7413
7435
  var logger = (0, import_pino.default)(
7414
7436
  {
7415
7437
  level,
7416
7438
  base: { service: "ocosay" },
7417
- timestamp: import_pino.default.stdTimeFunctions.isoTime
7439
+ timestamp: import_pino.default.stdTimeFunctions.isoTime,
7440
+ formatters: {
7441
+ level: (label) => ({ level: label })
7442
+ }
7418
7443
  },
7419
- import_pino.default.multistream(streams)
7444
+ import_pino.default.multistream([
7445
+ { stream: stdoutStream },
7446
+ ...fileStream ? [{ stream: fileStream }] : []
7447
+ ])
7420
7448
  );
7449
+ function createModuleLogger(module) {
7450
+ return logger.child({ module });
7451
+ }
7421
7452
 
7422
7453
  // src/core/backends/index.ts
7423
7454
  function isNaudiodonAvailable() {
@@ -7639,22 +7670,81 @@ var AudioPlayer = class extends EventEmitter {
7639
7670
  }
7640
7671
  };
7641
7672
 
7642
- // src/core/speaker.ts
7643
- function toast(options) {
7644
- const tui2 = global.__opencode_tui__;
7645
- if (tui2?.showToast) {
7673
+ // src/core/notification.ts
7674
+ var logger2 = createModuleLogger("NotificationService");
7675
+ var NotificationService = class {
7676
+ tui = null;
7677
+ pendingToasts = [];
7678
+ retryTimer;
7679
+ setTui(tui) {
7680
+ this.tui = tui;
7681
+ logger2.debug("tui reference set");
7682
+ this.flushPending();
7683
+ }
7684
+ showToast(options) {
7685
+ const { title, message, variant = "info", duration = 5e3 } = options;
7686
+ if (!this.tui) {
7687
+ logger2.debug({ title }, "tui not ready, queueing toast");
7688
+ this.pendingToasts.push(options);
7689
+ this.scheduleRetry();
7690
+ return false;
7691
+ }
7646
7692
  try {
7647
- tui2.showToast({
7648
- title: options.title,
7649
- message: options.body,
7650
- variant: options.type,
7651
- duration: 3e3
7693
+ this.tui.showToast({
7694
+ body: {
7695
+ title,
7696
+ message,
7697
+ variant,
7698
+ duration
7699
+ }
7652
7700
  });
7701
+ logger2.debug({ title, variant }, "toast shown");
7702
+ return true;
7653
7703
  } catch (err) {
7654
- logger.warn({ err }, "toast call failed");
7704
+ logger2.warn({ err, title }, "toast call failed, queueing for retry");
7705
+ this.pendingToasts.push(options);
7706
+ this.scheduleRetry();
7707
+ return false;
7655
7708
  }
7656
7709
  }
7657
- }
7710
+ scheduleRetry() {
7711
+ if (this.retryTimer) return;
7712
+ this.retryTimer = setTimeout(() => {
7713
+ this.retryTimer = void 0;
7714
+ this.flushPending();
7715
+ }, 2e3);
7716
+ }
7717
+ flushPending() {
7718
+ if (this.pendingToasts.length === 0 || !this.tui) return;
7719
+ logger2.info({ count: this.pendingToasts.length }, "flushing pending toasts");
7720
+ const pending = [...this.pendingToasts];
7721
+ this.pendingToasts = [];
7722
+ for (const toast of pending) {
7723
+ try {
7724
+ this.showToast(toast);
7725
+ } catch (err) {
7726
+ this.pendingToasts.push(toast);
7727
+ logger2.warn({ err }, "showToast threw unexpected error, re-queued");
7728
+ }
7729
+ }
7730
+ }
7731
+ success(title, message, duration) {
7732
+ return this.showToast({ title, message, variant: "success", duration });
7733
+ }
7734
+ error(title, message, duration) {
7735
+ return this.showToast({ title, message, variant: "error", duration });
7736
+ }
7737
+ info(title, message, duration) {
7738
+ return this.showToast({ title, message, variant: "info", duration });
7739
+ }
7740
+ warning(title, message, duration) {
7741
+ return this.showToast({ title, message, variant: "warning", duration });
7742
+ }
7743
+ };
7744
+ var notificationService = new NotificationService();
7745
+
7746
+ // src/core/speaker.ts
7747
+ var logger3 = createModuleLogger("Speaker");
7658
7748
  var Speaker = class extends EventEmitter2 {
7659
7749
  constructor(options = {}) {
7660
7750
  super();
@@ -7664,11 +7754,10 @@ var Speaker = class extends EventEmitter2 {
7664
7754
  onEnd: () => {
7665
7755
  this.isSpeaking = false;
7666
7756
  this.emit("end", this.currentText);
7667
- toast({
7668
- title: "TTS playback success",
7669
- body: "Audio generated and playing",
7670
- type: "info"
7671
- });
7757
+ notificationService.info(
7758
+ "TTS playback success",
7759
+ "Audio generated and playing"
7760
+ );
7672
7761
  },
7673
7762
  onError: (error) => this.emit("error", error),
7674
7763
  onPause: () => {
@@ -7731,17 +7820,16 @@ var Speaker = class extends EventEmitter2 {
7731
7820
  });
7732
7821
  if (this.player) {
7733
7822
  await this.player.play(result.audioData, result.format);
7734
- logger.info({ textLength: text.length, model: options.model }, "TTS playback completed");
7823
+ logger3.info({ textLength: text.length, model: options.model }, "TTS playback completed");
7735
7824
  }
7736
7825
  } catch (error) {
7737
7826
  this.isSpeaking = false;
7738
- logger.error({ error }, "speak failed");
7827
+ logger3.error({ error }, "speak failed");
7739
7828
  const errorMessage = error instanceof Error ? error.message : "Unknown error";
7740
- toast({
7741
- title: "TTS playback error",
7742
- body: errorMessage,
7743
- type: "error"
7744
- });
7829
+ notificationService.error(
7830
+ "TTS playback error",
7831
+ errorMessage
7832
+ );
7745
7833
  if (error instanceof TTSError) {
7746
7834
  this.emit("error", error);
7747
7835
  throw error;
@@ -8321,6 +8409,7 @@ async function stream(text, options) {
8321
8409
  }
8322
8410
 
8323
8411
  // src/tools/tts.ts
8412
+ var logger4 = createModuleLogger("TTS");
8324
8413
  function extractTextArg(args) {
8325
8414
  if (!args || typeof args !== "object") {
8326
8415
  return void 0;
@@ -8333,26 +8422,26 @@ function extractTextArg(args) {
8333
8422
  const text7 = argObj.text7;
8334
8423
  if (text7 != null) {
8335
8424
  if (typeof text7 === "string" && text7.trim().length > 0) {
8336
- logger.warn("received text7 instead of text from OpenCode framework");
8425
+ logger4.warn("received text7 instead of text from OpenCode framework");
8337
8426
  return text7.trim();
8338
8427
  }
8339
8428
  if (typeof text7 === "object") {
8340
8429
  if ("split" in text7 && "content" in text7) {
8341
8430
  const content = text7.content;
8342
8431
  if (typeof content === "string" && content.trim().length > 0) {
8343
- logger.info("text7 split format detected");
8432
+ logger4.info("text7 split format detected");
8344
8433
  return content.trim();
8345
8434
  }
8346
8435
  }
8347
8436
  if ("content" in text7) {
8348
8437
  const content = text7.content;
8349
8438
  if (typeof content === "string" && content.trim().length > 0) {
8350
- logger.info("text7 content format detected");
8439
+ logger4.info("text7 content format detected");
8351
8440
  return content.trim();
8352
8441
  }
8353
8442
  }
8354
8443
  }
8355
- logger.warn({ type: typeof text7 }, "text7 is not a valid string or object with content");
8444
+ logger4.warn({ type: typeof text7 }, "text7 is not a valid string or object with content");
8356
8445
  return void 0;
8357
8446
  }
8358
8447
  for (const key of Object.keys(argObj)) {
@@ -8364,7 +8453,7 @@ function extractTextArg(args) {
8364
8453
  }
8365
8454
  }
8366
8455
  if (text !== void 0) {
8367
- logger.warn({ type: typeof text }, "text arg is not a valid string");
8456
+ logger4.warn({ type: typeof text }, "text arg is not a valid string");
8368
8457
  }
8369
8458
  return void 0;
8370
8459
  }
@@ -8424,9 +8513,9 @@ async function handleToolCall(toolName, args) {
8424
8513
  if (streamingService) {
8425
8514
  const textArg = extractTextArg(args);
8426
8515
  if (textArg && typeof textArg === "string" && textArg.trim().length > 0) {
8427
- logger.info({ text: textArg.substring(0, 50) + "..." }, "synthesizing text");
8516
+ logger4.info({ text: textArg.substring(0, 50) + "..." }, "synthesizing text");
8428
8517
  stream(textArg).catch((error) => {
8429
- logger.error({ error }, "stream failed");
8518
+ logger4.error({ error }, "stream failed");
8430
8519
  });
8431
8520
  }
8432
8521
  return { success: true, message: "Stream speak started" };
@@ -8922,6 +9011,7 @@ var MINIMAX_VOICES = [
8922
9011
 
8923
9012
  // src/core/stream-reader.ts
8924
9013
  import { EventEmitter as EventEmitter5 } from "events";
9014
+ var logger5 = createModuleLogger("StreamReader");
8925
9015
  var StreamReader = class extends EventEmitter5 {
8926
9016
  constructor(bufferSize = 30, bufferTimeout = 2e3) {
8927
9017
  super();
@@ -8948,7 +9038,7 @@ var StreamReader = class extends EventEmitter5 {
8948
9038
  }
8949
9039
  handleDelta(sessionID, messageID, partID, delta) {
8950
9040
  if (typeof delta !== "string") {
8951
- logger.warn({ delta }, "handleDelta received non-string delta, skipping");
9041
+ logger5.warn({ delta }, "handleDelta received non-string delta, skipping");
8952
9042
  return;
8953
9043
  }
8954
9044
  if (this.state === "idle" /* IDLE */) {
@@ -8957,11 +9047,11 @@ var StreamReader = class extends EventEmitter5 {
8957
9047
  this.messageID = messageID;
8958
9048
  this.partID = partID;
8959
9049
  this.emit("streamStart");
8960
- logger.debug({ sessionID, messageID, partID }, "Stream started");
9050
+ logger5.debug({ sessionID, messageID, partID }, "Stream started");
8961
9051
  }
8962
9052
  this.buffer += delta;
8963
9053
  this.resetTimeout();
8964
- logger.debug({ deltaLength: delta.length, bufferLength: this.buffer.length }, "Delta received");
9054
+ logger5.debug({ deltaLength: delta.length, bufferLength: this.buffer.length }, "Delta received");
8965
9055
  if (this.shouldFlush()) {
8966
9056
  this.flushBuffer();
8967
9057
  }
@@ -9314,6 +9404,7 @@ function getStreamStatus() {
9314
9404
  import * as fs2 from "fs";
9315
9405
  import * as path from "path";
9316
9406
  import * as os from "os";
9407
+ var logger6 = createModuleLogger("Config");
9317
9408
  var DEFAULT_CONFIG = {
9318
9409
  enabled: true,
9319
9410
  autoPlay: false,
@@ -9412,12 +9503,12 @@ function loadOrCreateConfig() {
9412
9503
  try {
9413
9504
  fs2.mkdirSync(configDir, { recursive: true });
9414
9505
  } catch (err) {
9415
- logger.error({ err }, "failed to create config directory");
9506
+ logger6.error({ err }, "failed to create config directory");
9416
9507
  throw new Error(`[ocosay] \u65E0\u6CD5\u521B\u5EFA\u914D\u7F6E\u76EE\u5F55 ${configDir}: ${err}`);
9417
9508
  }
9418
9509
  }
9419
9510
  if (!fs2.existsSync(CONFIG_PATH)) {
9420
- logger.info("config file not found, creating default config");
9511
+ logger6.info("config file not found, creating default config");
9421
9512
  const defaultConfig = generateDefaultConfig();
9422
9513
  const configContent = JSON.stringify(defaultConfig, null, 2);
9423
9514
  try {
@@ -9425,14 +9516,14 @@ function loadOrCreateConfig() {
9425
9516
  try {
9426
9517
  fs2.chmodSync(CONFIG_PATH, 384);
9427
9518
  } catch (err) {
9428
- logger.warn({ err }, "failed to set config file permissions");
9519
+ logger6.warn({ err }, "failed to set config file permissions");
9429
9520
  }
9430
9521
  } catch (err) {
9431
- logger.error({ err }, "failed to write config file");
9522
+ logger6.error({ err }, "failed to write config file");
9432
9523
  throw new Error(`[ocosay] cannot write config file ${CONFIG_PATH}: ${err}`);
9433
9524
  }
9434
- logger.info({ path: CONFIG_PATH }, "config file created");
9435
- logger.info("please edit config file to add API Key and Base URL");
9525
+ logger6.info({ path: CONFIG_PATH }, "config file created");
9526
+ logger6.info("please edit config file to add API Key and Base URL");
9436
9527
  return defaultConfig;
9437
9528
  }
9438
9529
  try {
@@ -9454,96 +9545,16 @@ function loadOrCreateConfig() {
9454
9545
  }
9455
9546
  };
9456
9547
  } catch (error) {
9457
- logger.error({ error }, "config file read failed, using default config");
9548
+ logger6.error({ error }, "config file read failed, using default config");
9458
9549
  return generateDefaultConfig();
9459
9550
  }
9460
9551
  }
9461
9552
 
9462
- // src/services/notification-service.ts
9463
- var instance;
9464
- var tui = null;
9465
- var initialized2 = false;
9466
- var NotificationService = class _NotificationService {
9467
- constructor() {
9468
- }
9469
- static getInstance() {
9470
- if (!instance) {
9471
- instance = new _NotificationService();
9472
- }
9473
- return instance;
9474
- }
9475
- initialize(tuiInstance) {
9476
- if (initialized2) return;
9477
- tui = tuiInstance;
9478
- initialized2 = true;
9479
- logger.debug("NotificationService initialized");
9480
- }
9481
- isReady() {
9482
- return initialized2 && tui !== null;
9483
- }
9484
- showToast(message, type = "info") {
9485
- const title = this.getTitleForType(type);
9486
- if (tui?.showToast) {
9487
- try {
9488
- tui.showToast({
9489
- title,
9490
- message,
9491
- variant: type,
9492
- duration: type === "error" ? 8e3 : 5e3
9493
- });
9494
- return;
9495
- } catch (err) {
9496
- logger.warn({ err }, "tui.showToast failed");
9497
- }
9498
- }
9499
- this.fallbackLog(type, title, message);
9500
- }
9501
- success(message) {
9502
- this.showToast(message, "success");
9503
- }
9504
- error(message) {
9505
- this.showToast(message, "error");
9506
- }
9507
- warning(message) {
9508
- this.showToast(message, "warning");
9509
- }
9510
- info(message) {
9511
- this.showToast(message, "info");
9512
- }
9513
- getTitleForType(type) {
9514
- const titles = {
9515
- success: "Success",
9516
- error: "Error",
9517
- warning: "Warning",
9518
- info: "Info"
9519
- };
9520
- return titles[type];
9521
- }
9522
- fallbackLog(type, title, message) {
9523
- const timestamp = (/* @__PURE__ */ new Date()).toISOString();
9524
- switch (type) {
9525
- case "error":
9526
- logger.error({ title, message, timestamp }, "Toast (fallback)");
9527
- break;
9528
- case "warning":
9529
- logger.warn({ title, message, timestamp }, "Toast (fallback)");
9530
- break;
9531
- default:
9532
- logger.info({ title, message, timestamp }, "Toast (fallback)");
9533
- }
9534
- }
9535
- };
9536
- function showToast(message, type = "info") {
9537
- NotificationService.getInstance().showToast(message, type);
9538
- }
9539
- function initializeNotificationService(tuiInstance) {
9540
- NotificationService.getInstance().initialize(tuiInstance);
9541
- }
9542
-
9543
9553
  // src/plugin.ts
9544
9554
  import { readFileSync as readFileSync2 } from "fs";
9545
9555
  import { fileURLToPath } from "url";
9546
9556
  import { dirname as dirname2, join as join7 } from "path";
9557
+ var logger7 = createModuleLogger("Plugin");
9547
9558
  var __filename = fileURLToPath(import.meta.url);
9548
9559
  var __dirname2 = dirname2(__filename);
9549
9560
  var id = "ocosay";
@@ -9683,18 +9694,26 @@ var server = (async (input, _options) => {
9683
9694
  });
9684
9695
  } catch (err) {
9685
9696
  initError = err instanceof Error ? err : new Error(String(err));
9686
- logger.error({ error: initError }, "initialization failed");
9697
+ logger7.error({ error: initError }, "initialization failed");
9687
9698
  }
9688
9699
  const opencodeTui = input.client?.tui;
9689
9700
  global.__opencode_tui__ = opencodeTui;
9690
- initializeNotificationService(opencodeTui);
9691
- setTimeout(async () => {
9701
+ notificationService.setTui(opencodeTui);
9702
+ setTimeout(() => {
9692
9703
  if (initError) {
9693
- showToast(`Ocosay v${pluginVersion} Initialization Failed: please check config`, "error");
9704
+ notificationService.error(
9705
+ `Ocosay v${pluginVersion} Init Failed`,
9706
+ "Please check your config file",
9707
+ 8e3
9708
+ );
9694
9709
  } else {
9695
- showToast(`Ocosay v${pluginVersion} Plugin Loaded (Auto-read: ${config.autoRead ? "ON" : "OFF"})`, "success");
9710
+ notificationService.success(
9711
+ `Ocosay v${pluginVersion} Ready`,
9712
+ `Auto-read: ${config.autoRead ? "ON" : "OFF"}`,
9713
+ 5e3
9714
+ );
9696
9715
  }
9697
- }, 7e3);
9716
+ }, 1500);
9698
9717
  return {
9699
9718
  tool: {
9700
9719
  tts_speak: ttsSpeakTool,
@@ -9727,7 +9746,11 @@ var server = (async (input, _options) => {
9727
9746
  });
9728
9747
  initError = null;
9729
9748
  } catch (err) {
9730
- showToast(`Ocosay v${pluginVersion} Initialization Failed: please check config`, "error");
9749
+ notificationService.error(
9750
+ `Ocosay v${pluginVersion} Init Failed`,
9751
+ "Initialization failed, please check config",
9752
+ 8e3
9753
+ );
9731
9754
  }
9732
9755
  }
9733
9756
  }