@mingxy/ocosay 1.0.35 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/config.js +4 -1
- package/dist/core/backends/index.js +8 -3
- package/dist/core/notification.d.ts +27 -0
- package/dist/core/notification.js +86 -0
- package/dist/core/speaker.js +6 -35
- package/dist/core/stream-reader.js +2 -1
- package/dist/core/streaming-synthesizer.js +2 -0
- package/dist/index.d.ts +1 -13
- package/dist/index.js +4 -23
- package/dist/package.json +2 -2
- package/dist/plugin.js +990 -586
- package/dist/providers/minimax.js +43 -20
- package/dist/services/notification-service.d.ts +17 -0
- package/dist/services/notification-service.js +74 -0
- package/dist/services/speaker-service.d.ts +34 -0
- package/dist/services/speaker-service.js +74 -0
- package/dist/services/streaming-service.d.ts +109 -0
- package/dist/services/streaming-service.js +281 -0
- package/dist/tools/tts.js +32 -19
- package/dist/utils/logger.d.ts +6 -0
- package/dist/utils/logger.js +42 -6
- package/package.json +2 -2
- package/.idea/UniappTool.xml +0 -10
- package/.idea/inspectionProfiles/profiles_settings.xml +0 -5
- package/.idea/modules.xml +0 -8
- package/.idea/ocosay.iml +0 -12
- package/.idea/vcs.xml +0 -6
- package/.sisyphus/boulder.json +0 -23
- package/dist/config.d.ts.map +0 -1
- package/dist/config.js.map +0 -1
- package/dist/core/backends/afplay-backend.d.ts.map +0 -1
- package/dist/core/backends/afplay-backend.js.map +0 -1
- package/dist/core/backends/aplay-backend.d.ts.map +0 -1
- package/dist/core/backends/aplay-backend.js.map +0 -1
- package/dist/core/backends/base.d.ts.map +0 -1
- package/dist/core/backends/base.js.map +0 -1
- package/dist/core/backends/howler-backend.d.ts.map +0 -1
- package/dist/core/backends/howler-backend.js.map +0 -1
- package/dist/core/backends/index.d.ts.map +0 -1
- package/dist/core/backends/index.js.map +0 -1
- package/dist/core/backends/naudiodon-backend.d.ts.map +0 -1
- package/dist/core/backends/naudiodon-backend.js.map +0 -1
- package/dist/core/backends/powershell-backend.d.ts.map +0 -1
- package/dist/core/backends/powershell-backend.js.map +0 -1
- package/dist/core/logger.d.ts.map +0 -1
- package/dist/core/logger.js.map +0 -1
- package/dist/core/player.d.ts.map +0 -1
- package/dist/core/player.js.map +0 -1
- package/dist/core/speaker.d.ts.map +0 -1
- package/dist/core/speaker.js.map +0 -1
- package/dist/core/stream-player.d.ts.map +0 -1
- package/dist/core/stream-player.js.map +0 -1
- package/dist/core/stream-reader.d.ts.map +0 -1
- package/dist/core/stream-reader.js.map +0 -1
- package/dist/core/streaming-synthesizer.d.ts.map +0 -1
- package/dist/core/streaming-synthesizer.js.map +0 -1
- package/dist/core/types.d.ts.map +0 -1
- package/dist/core/types.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/plugin.d.ts.map +0 -1
- package/dist/plugin.js.map +0 -7
- package/dist/providers/base.d.ts.map +0 -1
- package/dist/providers/base.js.map +0 -1
- package/dist/providers/minimax.d.ts.map +0 -1
- package/dist/providers/minimax.js.map +0 -1
- package/dist/tools/tts.d.ts.map +0 -1
- package/dist/tools/tts.js.map +0 -1
- package/dist/types/config.d.ts.map +0 -1
- package/dist/types/config.js.map +0 -1
- package/dist/utils/logger.d.ts.map +0 -1
- package/dist/utils/logger.js.map +0 -1
package/dist/plugin.js
CHANGED
|
@@ -593,17 +593,17 @@ var require_howler = __commonJS({
|
|
|
593
593
|
var duration = Math.max(0, (self._sprite[sprite][0] + self._sprite[sprite][1]) / 1e3 - seek);
|
|
594
594
|
var timeout = duration * 1e3 / Math.abs(sound._rate);
|
|
595
595
|
var start = self._sprite[sprite][0] / 1e3;
|
|
596
|
-
var
|
|
596
|
+
var stop3 = (self._sprite[sprite][0] + self._sprite[sprite][1]) / 1e3;
|
|
597
597
|
sound._sprite = sprite;
|
|
598
598
|
sound._ended = false;
|
|
599
599
|
var setParams = function() {
|
|
600
600
|
sound._paused = false;
|
|
601
601
|
sound._seek = seek;
|
|
602
602
|
sound._start = start;
|
|
603
|
-
sound._stop =
|
|
603
|
+
sound._stop = stop3;
|
|
604
604
|
sound._loop = !!(sound._loop || self._sprite[sprite][2]);
|
|
605
605
|
};
|
|
606
|
-
if (seek >=
|
|
606
|
+
if (seek >= stop3) {
|
|
607
607
|
self._ended(sound);
|
|
608
608
|
return;
|
|
609
609
|
}
|
|
@@ -3418,7 +3418,7 @@ var require_sonic_boom = __commonJS({
|
|
|
3418
3418
|
"node_modules/sonic-boom/index.js"(exports, module) {
|
|
3419
3419
|
"use strict";
|
|
3420
3420
|
var fs3 = __require("fs");
|
|
3421
|
-
var
|
|
3421
|
+
var EventEmitter7 = __require("events");
|
|
3422
3422
|
var inherits = __require("util").inherits;
|
|
3423
3423
|
var path2 = __require("path");
|
|
3424
3424
|
var sleep = require_atomic_sleep();
|
|
@@ -3655,7 +3655,7 @@ var require_sonic_boom = __commonJS({
|
|
|
3655
3655
|
sonic._asyncDrainScheduled = false;
|
|
3656
3656
|
sonic.emit("drain");
|
|
3657
3657
|
}
|
|
3658
|
-
inherits(SonicBoom,
|
|
3658
|
+
inherits(SonicBoom, EventEmitter7);
|
|
3659
3659
|
function mergeBuf(bufs, len) {
|
|
3660
3660
|
if (bufs.length === 0) {
|
|
3661
3661
|
return kEmptyBuffer;
|
|
@@ -4223,7 +4223,7 @@ var require_thread_stream = __commonJS({
|
|
|
4223
4223
|
"node_modules/thread-stream/index.js"(exports, module) {
|
|
4224
4224
|
"use strict";
|
|
4225
4225
|
var { version } = require_package();
|
|
4226
|
-
var { EventEmitter:
|
|
4226
|
+
var { EventEmitter: EventEmitter7 } = __require("events");
|
|
4227
4227
|
var { Worker } = __require("worker_threads");
|
|
4228
4228
|
var { join: join8 } = __require("path");
|
|
4229
4229
|
var { pathToFileURL } = __require("url");
|
|
@@ -4258,7 +4258,7 @@ var require_thread_stream = __commonJS({
|
|
|
4258
4258
|
}
|
|
4259
4259
|
worker.terminate();
|
|
4260
4260
|
});
|
|
4261
|
-
function createWorker(
|
|
4261
|
+
function createWorker(stream2, opts) {
|
|
4262
4262
|
const { filename, workerData } = opts;
|
|
4263
4263
|
const bundlerOverrides = "__bundlerPathsOverrides" in globalThis ? globalThis.__bundlerPathsOverrides : {};
|
|
4264
4264
|
const toExecute = bundlerOverrides["thread-stream-worker"] || join8(__dirname, "lib", "worker.js");
|
|
@@ -4267,8 +4267,8 @@ var require_thread_stream = __commonJS({
|
|
|
4267
4267
|
trackUnmanagedFds: false,
|
|
4268
4268
|
workerData: {
|
|
4269
4269
|
filename: filename.indexOf("file://") === 0 ? filename : pathToFileURL(filename).href,
|
|
4270
|
-
dataBuf:
|
|
4271
|
-
stateBuf:
|
|
4270
|
+
dataBuf: stream2[kImpl].dataBuf,
|
|
4271
|
+
stateBuf: stream2[kImpl].stateBuf,
|
|
4272
4272
|
workerData: {
|
|
4273
4273
|
$context: {
|
|
4274
4274
|
threadStreamVersion: version
|
|
@@ -4277,111 +4277,111 @@ var require_thread_stream = __commonJS({
|
|
|
4277
4277
|
}
|
|
4278
4278
|
}
|
|
4279
4279
|
});
|
|
4280
|
-
worker.stream = new FakeWeakRef(
|
|
4280
|
+
worker.stream = new FakeWeakRef(stream2);
|
|
4281
4281
|
worker.on("message", onWorkerMessage);
|
|
4282
4282
|
worker.on("exit", onWorkerExit);
|
|
4283
|
-
registry.register(
|
|
4283
|
+
registry.register(stream2, worker);
|
|
4284
4284
|
return worker;
|
|
4285
4285
|
}
|
|
4286
|
-
function drain(
|
|
4287
|
-
assert(!
|
|
4288
|
-
if (
|
|
4289
|
-
|
|
4290
|
-
|
|
4286
|
+
function drain(stream2) {
|
|
4287
|
+
assert(!stream2[kImpl].sync);
|
|
4288
|
+
if (stream2[kImpl].needDrain) {
|
|
4289
|
+
stream2[kImpl].needDrain = false;
|
|
4290
|
+
stream2.emit("drain");
|
|
4291
4291
|
}
|
|
4292
4292
|
}
|
|
4293
|
-
function nextFlush(
|
|
4294
|
-
const writeIndex = Atomics.load(
|
|
4295
|
-
let leftover =
|
|
4293
|
+
function nextFlush(stream2) {
|
|
4294
|
+
const writeIndex = Atomics.load(stream2[kImpl].state, WRITE_INDEX);
|
|
4295
|
+
let leftover = stream2[kImpl].data.length - writeIndex;
|
|
4296
4296
|
if (leftover > 0) {
|
|
4297
|
-
if (
|
|
4298
|
-
|
|
4299
|
-
if (
|
|
4300
|
-
end(
|
|
4301
|
-
} else if (
|
|
4302
|
-
process.nextTick(drain,
|
|
4297
|
+
if (stream2[kImpl].buf.length === 0) {
|
|
4298
|
+
stream2[kImpl].flushing = false;
|
|
4299
|
+
if (stream2[kImpl].ending) {
|
|
4300
|
+
end(stream2);
|
|
4301
|
+
} else if (stream2[kImpl].needDrain) {
|
|
4302
|
+
process.nextTick(drain, stream2);
|
|
4303
4303
|
}
|
|
4304
4304
|
return;
|
|
4305
4305
|
}
|
|
4306
|
-
let toWrite =
|
|
4306
|
+
let toWrite = stream2[kImpl].buf.slice(0, leftover);
|
|
4307
4307
|
let toWriteBytes = Buffer.byteLength(toWrite);
|
|
4308
4308
|
if (toWriteBytes <= leftover) {
|
|
4309
|
-
|
|
4310
|
-
write(
|
|
4309
|
+
stream2[kImpl].buf = stream2[kImpl].buf.slice(leftover);
|
|
4310
|
+
write(stream2, toWrite, nextFlush.bind(null, stream2));
|
|
4311
4311
|
} else {
|
|
4312
|
-
|
|
4313
|
-
if (
|
|
4312
|
+
stream2.flush(() => {
|
|
4313
|
+
if (stream2.destroyed) {
|
|
4314
4314
|
return;
|
|
4315
4315
|
}
|
|
4316
|
-
Atomics.store(
|
|
4317
|
-
Atomics.store(
|
|
4318
|
-
Atomics.notify(
|
|
4319
|
-
while (toWriteBytes >
|
|
4316
|
+
Atomics.store(stream2[kImpl].state, READ_INDEX, 0);
|
|
4317
|
+
Atomics.store(stream2[kImpl].state, WRITE_INDEX, 0);
|
|
4318
|
+
Atomics.notify(stream2[kImpl].state, READ_INDEX);
|
|
4319
|
+
while (toWriteBytes > stream2[kImpl].data.length) {
|
|
4320
4320
|
leftover = leftover / 2;
|
|
4321
|
-
toWrite =
|
|
4321
|
+
toWrite = stream2[kImpl].buf.slice(0, leftover);
|
|
4322
4322
|
toWriteBytes = Buffer.byteLength(toWrite);
|
|
4323
4323
|
}
|
|
4324
|
-
|
|
4325
|
-
write(
|
|
4324
|
+
stream2[kImpl].buf = stream2[kImpl].buf.slice(leftover);
|
|
4325
|
+
write(stream2, toWrite, nextFlush.bind(null, stream2));
|
|
4326
4326
|
});
|
|
4327
4327
|
}
|
|
4328
4328
|
} else if (leftover === 0) {
|
|
4329
|
-
if (writeIndex === 0 &&
|
|
4329
|
+
if (writeIndex === 0 && stream2[kImpl].buf.length === 0) {
|
|
4330
4330
|
return;
|
|
4331
4331
|
}
|
|
4332
|
-
|
|
4333
|
-
Atomics.store(
|
|
4334
|
-
Atomics.store(
|
|
4335
|
-
Atomics.notify(
|
|
4336
|
-
nextFlush(
|
|
4332
|
+
stream2.flush(() => {
|
|
4333
|
+
Atomics.store(stream2[kImpl].state, READ_INDEX, 0);
|
|
4334
|
+
Atomics.store(stream2[kImpl].state, WRITE_INDEX, 0);
|
|
4335
|
+
Atomics.notify(stream2[kImpl].state, READ_INDEX);
|
|
4336
|
+
nextFlush(stream2);
|
|
4337
4337
|
});
|
|
4338
4338
|
} else {
|
|
4339
|
-
destroy(
|
|
4339
|
+
destroy(stream2, new Error("overwritten"));
|
|
4340
4340
|
}
|
|
4341
4341
|
}
|
|
4342
4342
|
function onWorkerMessage(msg) {
|
|
4343
|
-
const
|
|
4344
|
-
if (
|
|
4343
|
+
const stream2 = this.stream.deref();
|
|
4344
|
+
if (stream2 === void 0) {
|
|
4345
4345
|
this.exited = true;
|
|
4346
4346
|
this.terminate();
|
|
4347
4347
|
return;
|
|
4348
4348
|
}
|
|
4349
4349
|
switch (msg.code) {
|
|
4350
4350
|
case "READY":
|
|
4351
|
-
this.stream = new WeakRef2(
|
|
4352
|
-
|
|
4353
|
-
|
|
4354
|
-
|
|
4351
|
+
this.stream = new WeakRef2(stream2);
|
|
4352
|
+
stream2.flush(() => {
|
|
4353
|
+
stream2[kImpl].ready = true;
|
|
4354
|
+
stream2.emit("ready");
|
|
4355
4355
|
});
|
|
4356
4356
|
break;
|
|
4357
4357
|
case "ERROR":
|
|
4358
|
-
destroy(
|
|
4358
|
+
destroy(stream2, msg.err);
|
|
4359
4359
|
break;
|
|
4360
4360
|
case "EVENT":
|
|
4361
4361
|
if (Array.isArray(msg.args)) {
|
|
4362
|
-
|
|
4362
|
+
stream2.emit(msg.name, ...msg.args);
|
|
4363
4363
|
} else {
|
|
4364
|
-
|
|
4364
|
+
stream2.emit(msg.name, msg.args);
|
|
4365
4365
|
}
|
|
4366
4366
|
break;
|
|
4367
4367
|
case "WARNING":
|
|
4368
4368
|
process.emitWarning(msg.err);
|
|
4369
4369
|
break;
|
|
4370
4370
|
default:
|
|
4371
|
-
destroy(
|
|
4371
|
+
destroy(stream2, new Error("this should not happen: " + msg.code));
|
|
4372
4372
|
}
|
|
4373
4373
|
}
|
|
4374
4374
|
function onWorkerExit(code) {
|
|
4375
|
-
const
|
|
4376
|
-
if (
|
|
4375
|
+
const stream2 = this.stream.deref();
|
|
4376
|
+
if (stream2 === void 0) {
|
|
4377
4377
|
return;
|
|
4378
4378
|
}
|
|
4379
|
-
registry.unregister(
|
|
4380
|
-
|
|
4381
|
-
|
|
4382
|
-
destroy(
|
|
4379
|
+
registry.unregister(stream2);
|
|
4380
|
+
stream2.worker.exited = true;
|
|
4381
|
+
stream2.worker.off("exit", onWorkerExit);
|
|
4382
|
+
destroy(stream2, code !== 0 ? new Error("the worker thread exited") : null);
|
|
4383
4383
|
}
|
|
4384
|
-
var ThreadStream = class extends
|
|
4384
|
+
var ThreadStream = class extends EventEmitter7 {
|
|
4385
4385
|
constructor(opts = {}) {
|
|
4386
4386
|
super();
|
|
4387
4387
|
if (opts.bufferSize < 4) {
|
|
@@ -4512,127 +4512,127 @@ var require_thread_stream = __commonJS({
|
|
|
4512
4512
|
return this[kImpl].errored;
|
|
4513
4513
|
}
|
|
4514
4514
|
};
|
|
4515
|
-
function error(
|
|
4515
|
+
function error(stream2, err) {
|
|
4516
4516
|
setImmediate(() => {
|
|
4517
|
-
|
|
4517
|
+
stream2.emit("error", err);
|
|
4518
4518
|
});
|
|
4519
4519
|
}
|
|
4520
|
-
function destroy(
|
|
4521
|
-
if (
|
|
4520
|
+
function destroy(stream2, err) {
|
|
4521
|
+
if (stream2[kImpl].destroyed) {
|
|
4522
4522
|
return;
|
|
4523
4523
|
}
|
|
4524
|
-
|
|
4524
|
+
stream2[kImpl].destroyed = true;
|
|
4525
4525
|
if (err) {
|
|
4526
|
-
|
|
4527
|
-
error(
|
|
4526
|
+
stream2[kImpl].errored = err;
|
|
4527
|
+
error(stream2, err);
|
|
4528
4528
|
}
|
|
4529
|
-
if (!
|
|
4530
|
-
|
|
4529
|
+
if (!stream2.worker.exited) {
|
|
4530
|
+
stream2.worker.terminate().catch(() => {
|
|
4531
4531
|
}).then(() => {
|
|
4532
|
-
|
|
4533
|
-
|
|
4532
|
+
stream2[kImpl].closed = true;
|
|
4533
|
+
stream2.emit("close");
|
|
4534
4534
|
});
|
|
4535
4535
|
} else {
|
|
4536
4536
|
setImmediate(() => {
|
|
4537
|
-
|
|
4538
|
-
|
|
4537
|
+
stream2[kImpl].closed = true;
|
|
4538
|
+
stream2.emit("close");
|
|
4539
4539
|
});
|
|
4540
4540
|
}
|
|
4541
4541
|
}
|
|
4542
|
-
function write(
|
|
4543
|
-
const current = Atomics.load(
|
|
4542
|
+
function write(stream2, data, cb) {
|
|
4543
|
+
const current = Atomics.load(stream2[kImpl].state, WRITE_INDEX);
|
|
4544
4544
|
const length = Buffer.byteLength(data);
|
|
4545
|
-
|
|
4546
|
-
Atomics.store(
|
|
4547
|
-
Atomics.notify(
|
|
4545
|
+
stream2[kImpl].data.write(data, current);
|
|
4546
|
+
Atomics.store(stream2[kImpl].state, WRITE_INDEX, current + length);
|
|
4547
|
+
Atomics.notify(stream2[kImpl].state, WRITE_INDEX);
|
|
4548
4548
|
cb();
|
|
4549
4549
|
return true;
|
|
4550
4550
|
}
|
|
4551
|
-
function end(
|
|
4552
|
-
if (
|
|
4551
|
+
function end(stream2) {
|
|
4552
|
+
if (stream2[kImpl].ended || !stream2[kImpl].ending || stream2[kImpl].flushing) {
|
|
4553
4553
|
return;
|
|
4554
4554
|
}
|
|
4555
|
-
|
|
4555
|
+
stream2[kImpl].ended = true;
|
|
4556
4556
|
try {
|
|
4557
|
-
|
|
4558
|
-
let readIndex = Atomics.load(
|
|
4559
|
-
Atomics.store(
|
|
4560
|
-
Atomics.notify(
|
|
4557
|
+
stream2.flushSync();
|
|
4558
|
+
let readIndex = Atomics.load(stream2[kImpl].state, READ_INDEX);
|
|
4559
|
+
Atomics.store(stream2[kImpl].state, WRITE_INDEX, -1);
|
|
4560
|
+
Atomics.notify(stream2[kImpl].state, WRITE_INDEX);
|
|
4561
4561
|
let spins = 0;
|
|
4562
4562
|
while (readIndex !== -1) {
|
|
4563
|
-
Atomics.wait(
|
|
4564
|
-
readIndex = Atomics.load(
|
|
4563
|
+
Atomics.wait(stream2[kImpl].state, READ_INDEX, readIndex, 1e3);
|
|
4564
|
+
readIndex = Atomics.load(stream2[kImpl].state, READ_INDEX);
|
|
4565
4565
|
if (readIndex === -2) {
|
|
4566
|
-
destroy(
|
|
4566
|
+
destroy(stream2, new Error("end() failed"));
|
|
4567
4567
|
return;
|
|
4568
4568
|
}
|
|
4569
4569
|
if (++spins === 10) {
|
|
4570
|
-
destroy(
|
|
4570
|
+
destroy(stream2, new Error("end() took too long (10s)"));
|
|
4571
4571
|
return;
|
|
4572
4572
|
}
|
|
4573
4573
|
}
|
|
4574
4574
|
process.nextTick(() => {
|
|
4575
|
-
|
|
4576
|
-
|
|
4575
|
+
stream2[kImpl].finished = true;
|
|
4576
|
+
stream2.emit("finish");
|
|
4577
4577
|
});
|
|
4578
4578
|
} catch (err) {
|
|
4579
|
-
destroy(
|
|
4579
|
+
destroy(stream2, err);
|
|
4580
4580
|
}
|
|
4581
4581
|
}
|
|
4582
|
-
function writeSync(
|
|
4582
|
+
function writeSync(stream2) {
|
|
4583
4583
|
const cb = () => {
|
|
4584
|
-
if (
|
|
4585
|
-
end(
|
|
4586
|
-
} else if (
|
|
4587
|
-
process.nextTick(drain,
|
|
4584
|
+
if (stream2[kImpl].ending) {
|
|
4585
|
+
end(stream2);
|
|
4586
|
+
} else if (stream2[kImpl].needDrain) {
|
|
4587
|
+
process.nextTick(drain, stream2);
|
|
4588
4588
|
}
|
|
4589
4589
|
};
|
|
4590
|
-
|
|
4591
|
-
while (
|
|
4592
|
-
const writeIndex = Atomics.load(
|
|
4593
|
-
let leftover =
|
|
4590
|
+
stream2[kImpl].flushing = false;
|
|
4591
|
+
while (stream2[kImpl].buf.length !== 0) {
|
|
4592
|
+
const writeIndex = Atomics.load(stream2[kImpl].state, WRITE_INDEX);
|
|
4593
|
+
let leftover = stream2[kImpl].data.length - writeIndex;
|
|
4594
4594
|
if (leftover === 0) {
|
|
4595
|
-
flushSync(
|
|
4596
|
-
Atomics.store(
|
|
4597
|
-
Atomics.store(
|
|
4598
|
-
Atomics.notify(
|
|
4595
|
+
flushSync(stream2);
|
|
4596
|
+
Atomics.store(stream2[kImpl].state, READ_INDEX, 0);
|
|
4597
|
+
Atomics.store(stream2[kImpl].state, WRITE_INDEX, 0);
|
|
4598
|
+
Atomics.notify(stream2[kImpl].state, READ_INDEX);
|
|
4599
4599
|
continue;
|
|
4600
4600
|
} else if (leftover < 0) {
|
|
4601
4601
|
throw new Error("overwritten");
|
|
4602
4602
|
}
|
|
4603
|
-
let toWrite =
|
|
4603
|
+
let toWrite = stream2[kImpl].buf.slice(0, leftover);
|
|
4604
4604
|
let toWriteBytes = Buffer.byteLength(toWrite);
|
|
4605
4605
|
if (toWriteBytes <= leftover) {
|
|
4606
|
-
|
|
4607
|
-
write(
|
|
4606
|
+
stream2[kImpl].buf = stream2[kImpl].buf.slice(leftover);
|
|
4607
|
+
write(stream2, toWrite, cb);
|
|
4608
4608
|
} else {
|
|
4609
|
-
flushSync(
|
|
4610
|
-
Atomics.store(
|
|
4611
|
-
Atomics.store(
|
|
4612
|
-
Atomics.notify(
|
|
4613
|
-
while (toWriteBytes >
|
|
4609
|
+
flushSync(stream2);
|
|
4610
|
+
Atomics.store(stream2[kImpl].state, READ_INDEX, 0);
|
|
4611
|
+
Atomics.store(stream2[kImpl].state, WRITE_INDEX, 0);
|
|
4612
|
+
Atomics.notify(stream2[kImpl].state, READ_INDEX);
|
|
4613
|
+
while (toWriteBytes > stream2[kImpl].buf.length) {
|
|
4614
4614
|
leftover = leftover / 2;
|
|
4615
|
-
toWrite =
|
|
4615
|
+
toWrite = stream2[kImpl].buf.slice(0, leftover);
|
|
4616
4616
|
toWriteBytes = Buffer.byteLength(toWrite);
|
|
4617
4617
|
}
|
|
4618
|
-
|
|
4619
|
-
write(
|
|
4618
|
+
stream2[kImpl].buf = stream2[kImpl].buf.slice(leftover);
|
|
4619
|
+
write(stream2, toWrite, cb);
|
|
4620
4620
|
}
|
|
4621
4621
|
}
|
|
4622
4622
|
}
|
|
4623
|
-
function flushSync(
|
|
4624
|
-
if (
|
|
4623
|
+
function flushSync(stream2) {
|
|
4624
|
+
if (stream2[kImpl].flushing) {
|
|
4625
4625
|
throw new Error("unable to flush while flushing");
|
|
4626
4626
|
}
|
|
4627
|
-
const writeIndex = Atomics.load(
|
|
4627
|
+
const writeIndex = Atomics.load(stream2[kImpl].state, WRITE_INDEX);
|
|
4628
4628
|
let spins = 0;
|
|
4629
4629
|
while (true) {
|
|
4630
|
-
const readIndex = Atomics.load(
|
|
4630
|
+
const readIndex = Atomics.load(stream2[kImpl].state, READ_INDEX);
|
|
4631
4631
|
if (readIndex === -2) {
|
|
4632
4632
|
throw Error("_flushSync failed");
|
|
4633
4633
|
}
|
|
4634
4634
|
if (readIndex !== writeIndex) {
|
|
4635
|
-
Atomics.wait(
|
|
4635
|
+
Atomics.wait(stream2[kImpl].state, READ_INDEX, readIndex, 1e3);
|
|
4636
4636
|
} else {
|
|
4637
4637
|
break;
|
|
4638
4638
|
}
|
|
@@ -4657,11 +4657,11 @@ var require_transport = __commonJS({
|
|
|
4657
4657
|
var sleep = require_atomic_sleep();
|
|
4658
4658
|
var onExit = require_on_exit_leak_free();
|
|
4659
4659
|
var ThreadStream = require_thread_stream();
|
|
4660
|
-
function setupOnExit(
|
|
4661
|
-
onExit.register(
|
|
4662
|
-
onExit.registerBeforeExit(
|
|
4663
|
-
|
|
4664
|
-
onExit.unregister(
|
|
4660
|
+
function setupOnExit(stream2) {
|
|
4661
|
+
onExit.register(stream2, autoEnd);
|
|
4662
|
+
onExit.registerBeforeExit(stream2, flush);
|
|
4663
|
+
stream2.on("close", function() {
|
|
4664
|
+
onExit.unregister(stream2);
|
|
4665
4665
|
});
|
|
4666
4666
|
}
|
|
4667
4667
|
function hasPreloadFlags() {
|
|
@@ -4754,44 +4754,44 @@ var require_transport = __commonJS({
|
|
|
4754
4754
|
}
|
|
4755
4755
|
}
|
|
4756
4756
|
workerOpts = { ...workerOpts, name };
|
|
4757
|
-
const
|
|
4757
|
+
const stream2 = new ThreadStream({
|
|
4758
4758
|
filename,
|
|
4759
4759
|
workerData,
|
|
4760
4760
|
workerOpts,
|
|
4761
4761
|
sync
|
|
4762
4762
|
});
|
|
4763
|
-
|
|
4764
|
-
|
|
4763
|
+
stream2.on("ready", onReady);
|
|
4764
|
+
stream2.on("close", function() {
|
|
4765
4765
|
process.removeListener("exit", onExit2);
|
|
4766
4766
|
});
|
|
4767
4767
|
process.on("exit", onExit2);
|
|
4768
4768
|
function onReady() {
|
|
4769
4769
|
process.removeListener("exit", onExit2);
|
|
4770
|
-
|
|
4770
|
+
stream2.unref();
|
|
4771
4771
|
if (workerOpts.autoEnd !== false) {
|
|
4772
|
-
setupOnExit(
|
|
4772
|
+
setupOnExit(stream2);
|
|
4773
4773
|
}
|
|
4774
4774
|
}
|
|
4775
4775
|
function onExit2() {
|
|
4776
|
-
if (
|
|
4776
|
+
if (stream2.closed) {
|
|
4777
4777
|
return;
|
|
4778
4778
|
}
|
|
4779
|
-
|
|
4779
|
+
stream2.flushSync();
|
|
4780
4780
|
sleep(100);
|
|
4781
|
-
|
|
4781
|
+
stream2.end();
|
|
4782
4782
|
}
|
|
4783
|
-
return
|
|
4783
|
+
return stream2;
|
|
4784
4784
|
}
|
|
4785
|
-
function autoEnd(
|
|
4786
|
-
|
|
4787
|
-
|
|
4788
|
-
|
|
4789
|
-
|
|
4790
|
-
|
|
4785
|
+
function autoEnd(stream2) {
|
|
4786
|
+
stream2.ref();
|
|
4787
|
+
stream2.flushSync();
|
|
4788
|
+
stream2.end();
|
|
4789
|
+
stream2.once("close", function() {
|
|
4790
|
+
stream2.unref();
|
|
4791
4791
|
});
|
|
4792
4792
|
}
|
|
4793
|
-
function flush(
|
|
4794
|
-
|
|
4793
|
+
function flush(stream2) {
|
|
4794
|
+
stream2.flushSync();
|
|
4795
4795
|
}
|
|
4796
4796
|
function transport(fullOptions) {
|
|
4797
4797
|
const { pipeline, targets, levels, dedupe, worker = {}, caller = getCallers(), sync = false } = fullOptions;
|
|
@@ -5071,56 +5071,56 @@ var require_tools = __commonJS({
|
|
|
5071
5071
|
}
|
|
5072
5072
|
return data;
|
|
5073
5073
|
}
|
|
5074
|
-
function hasBeenTampered(
|
|
5075
|
-
return
|
|
5074
|
+
function hasBeenTampered(stream2) {
|
|
5075
|
+
return stream2.write !== stream2.constructor.prototype.write;
|
|
5076
5076
|
}
|
|
5077
5077
|
function buildSafeSonicBoom(opts) {
|
|
5078
|
-
const
|
|
5079
|
-
|
|
5078
|
+
const stream2 = new SonicBoom(opts);
|
|
5079
|
+
stream2.on("error", filterBrokenPipe);
|
|
5080
5080
|
if (!opts.sync && isMainThread) {
|
|
5081
|
-
onExit.register(
|
|
5082
|
-
|
|
5083
|
-
onExit.unregister(
|
|
5081
|
+
onExit.register(stream2, autoEnd);
|
|
5082
|
+
stream2.on("close", function() {
|
|
5083
|
+
onExit.unregister(stream2);
|
|
5084
5084
|
});
|
|
5085
5085
|
}
|
|
5086
|
-
return
|
|
5086
|
+
return stream2;
|
|
5087
5087
|
function filterBrokenPipe(err) {
|
|
5088
5088
|
if (err.code === "EPIPE") {
|
|
5089
|
-
|
|
5090
|
-
|
|
5091
|
-
|
|
5092
|
-
|
|
5089
|
+
stream2.write = noop;
|
|
5090
|
+
stream2.end = noop;
|
|
5091
|
+
stream2.flushSync = noop;
|
|
5092
|
+
stream2.destroy = noop;
|
|
5093
5093
|
return;
|
|
5094
5094
|
}
|
|
5095
|
-
|
|
5096
|
-
|
|
5095
|
+
stream2.removeListener("error", filterBrokenPipe);
|
|
5096
|
+
stream2.emit("error", err);
|
|
5097
5097
|
}
|
|
5098
5098
|
}
|
|
5099
|
-
function autoEnd(
|
|
5100
|
-
if (
|
|
5099
|
+
function autoEnd(stream2, eventName) {
|
|
5100
|
+
if (stream2.destroyed) {
|
|
5101
5101
|
return;
|
|
5102
5102
|
}
|
|
5103
5103
|
if (eventName === "beforeExit") {
|
|
5104
|
-
|
|
5105
|
-
|
|
5106
|
-
|
|
5104
|
+
stream2.flush();
|
|
5105
|
+
stream2.on("drain", function() {
|
|
5106
|
+
stream2.end();
|
|
5107
5107
|
});
|
|
5108
5108
|
} else {
|
|
5109
|
-
|
|
5109
|
+
stream2.flushSync();
|
|
5110
5110
|
}
|
|
5111
5111
|
}
|
|
5112
5112
|
function createArgsNormalizer(defaultOptions) {
|
|
5113
|
-
return function normalizeArgs(instance, caller, opts = {},
|
|
5113
|
+
return function normalizeArgs(instance, caller, opts = {}, stream2) {
|
|
5114
5114
|
if (typeof opts === "string") {
|
|
5115
|
-
|
|
5115
|
+
stream2 = buildSafeSonicBoom({ dest: opts });
|
|
5116
5116
|
opts = {};
|
|
5117
|
-
} else if (typeof
|
|
5117
|
+
} else if (typeof stream2 === "string") {
|
|
5118
5118
|
if (opts && opts.transport) {
|
|
5119
5119
|
throw Error("only one of option.transport or stream can be specified");
|
|
5120
5120
|
}
|
|
5121
|
-
|
|
5121
|
+
stream2 = buildSafeSonicBoom({ dest: stream2 });
|
|
5122
5122
|
} else if (opts instanceof SonicBoom || opts.writable || opts._writableState) {
|
|
5123
|
-
|
|
5123
|
+
stream2 = opts;
|
|
5124
5124
|
opts = {};
|
|
5125
5125
|
} else if (opts.transport) {
|
|
5126
5126
|
if (opts.transport instanceof SonicBoom || opts.transport.writable || opts.transport._writableState) {
|
|
@@ -5133,7 +5133,7 @@ var require_tools = __commonJS({
|
|
|
5133
5133
|
if (opts.customLevels) {
|
|
5134
5134
|
customLevels = opts.useOnlyCustomLevels ? opts.customLevels : Object.assign({}, opts.levels, opts.customLevels);
|
|
5135
5135
|
}
|
|
5136
|
-
|
|
5136
|
+
stream2 = transport({ caller, ...opts.transport, levels: customLevels });
|
|
5137
5137
|
}
|
|
5138
5138
|
opts = Object.assign({}, defaultOptions, opts);
|
|
5139
5139
|
opts.serializers = Object.assign({}, defaultOptions.serializers, opts.serializers);
|
|
@@ -5144,14 +5144,14 @@ var require_tools = __commonJS({
|
|
|
5144
5144
|
const { enabled, onChild } = opts;
|
|
5145
5145
|
if (enabled === false) opts.level = "silent";
|
|
5146
5146
|
if (!onChild) opts.onChild = noop;
|
|
5147
|
-
if (!
|
|
5147
|
+
if (!stream2) {
|
|
5148
5148
|
if (!hasBeenTampered(process.stdout)) {
|
|
5149
|
-
|
|
5149
|
+
stream2 = buildSafeSonicBoom({ fd: process.stdout.fd || 1 });
|
|
5150
5150
|
} else {
|
|
5151
|
-
|
|
5151
|
+
stream2 = process.stdout;
|
|
5152
5152
|
}
|
|
5153
5153
|
}
|
|
5154
|
-
return { opts, stream };
|
|
5154
|
+
return { opts, stream: stream2 };
|
|
5155
5155
|
};
|
|
5156
5156
|
}
|
|
5157
5157
|
function stringify(obj, stringifySafeFn) {
|
|
@@ -5238,11 +5238,11 @@ var require_levels = __commonJS({
|
|
|
5238
5238
|
fatal: (hook) => {
|
|
5239
5239
|
const logFatal = genLog(DEFAULT_LEVELS.fatal, hook);
|
|
5240
5240
|
return function(...args) {
|
|
5241
|
-
const
|
|
5241
|
+
const stream2 = this[streamSym];
|
|
5242
5242
|
logFatal.call(this, ...args);
|
|
5243
|
-
if (typeof
|
|
5243
|
+
if (typeof stream2.flushSync === "function") {
|
|
5244
5244
|
try {
|
|
5245
|
-
|
|
5245
|
+
stream2.flushSync();
|
|
5246
5246
|
} catch (e) {
|
|
5247
5247
|
}
|
|
5248
5248
|
}
|
|
@@ -5424,7 +5424,7 @@ var require_meta = __commonJS({
|
|
|
5424
5424
|
var require_proto = __commonJS({
|
|
5425
5425
|
"node_modules/pino/lib/proto.js"(exports, module) {
|
|
5426
5426
|
"use strict";
|
|
5427
|
-
var { EventEmitter:
|
|
5427
|
+
var { EventEmitter: EventEmitter7 } = __require("node:events");
|
|
5428
5428
|
var {
|
|
5429
5429
|
lsCacheSym,
|
|
5430
5430
|
levelValSym,
|
|
@@ -5505,7 +5505,7 @@ var require_proto = __commonJS({
|
|
|
5505
5505
|
[getLevelSym]: getLevel,
|
|
5506
5506
|
[setLevelSym]: setLevel
|
|
5507
5507
|
};
|
|
5508
|
-
Object.setPrototypeOf(prototype,
|
|
5508
|
+
Object.setPrototypeOf(prototype, EventEmitter7.prototype);
|
|
5509
5509
|
module.exports = function() {
|
|
5510
5510
|
return Object.create(prototype);
|
|
5511
5511
|
};
|
|
@@ -5628,23 +5628,23 @@ var require_proto = __commonJS({
|
|
|
5628
5628
|
obj = mixinMergeStrategy(obj, mixin(obj, num, this));
|
|
5629
5629
|
}
|
|
5630
5630
|
const s = this[asJsonSym](obj, msg, num, t);
|
|
5631
|
-
const
|
|
5632
|
-
if (
|
|
5633
|
-
|
|
5634
|
-
|
|
5635
|
-
|
|
5636
|
-
|
|
5637
|
-
|
|
5631
|
+
const stream2 = this[streamSym];
|
|
5632
|
+
if (stream2[needsMetadataGsym] === true) {
|
|
5633
|
+
stream2.lastLevel = num;
|
|
5634
|
+
stream2.lastObj = obj;
|
|
5635
|
+
stream2.lastMsg = msg;
|
|
5636
|
+
stream2.lastTime = t.slice(this[timeSliceIndexSym]);
|
|
5637
|
+
stream2.lastLogger = this;
|
|
5638
5638
|
}
|
|
5639
|
-
|
|
5639
|
+
stream2.write(streamWriteHook ? streamWriteHook(s) : s);
|
|
5640
5640
|
}
|
|
5641
5641
|
function flush(cb) {
|
|
5642
5642
|
if (cb != null && typeof cb !== "function") {
|
|
5643
5643
|
throw Error("callback must be a function");
|
|
5644
5644
|
}
|
|
5645
|
-
const
|
|
5646
|
-
if (typeof
|
|
5647
|
-
|
|
5645
|
+
const stream2 = this[streamSym];
|
|
5646
|
+
if (typeof stream2.flush === "function") {
|
|
5647
|
+
stream2.flush(cb || noop);
|
|
5648
5648
|
} else if (cb) cb();
|
|
5649
5649
|
}
|
|
5650
5650
|
}
|
|
@@ -6287,25 +6287,25 @@ var require_multistream = __commonJS({
|
|
|
6287
6287
|
function write(data) {
|
|
6288
6288
|
let dest;
|
|
6289
6289
|
const level2 = this.lastLevel;
|
|
6290
|
-
const { streams
|
|
6290
|
+
const { streams } = this;
|
|
6291
6291
|
let recordedLevel = 0;
|
|
6292
|
-
let
|
|
6293
|
-
for (let i = initLoopVar(
|
|
6294
|
-
dest =
|
|
6292
|
+
let stream2;
|
|
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;
|
|
6298
6298
|
}
|
|
6299
|
-
|
|
6300
|
-
if (
|
|
6299
|
+
stream2 = dest.stream;
|
|
6300
|
+
if (stream2[metadata]) {
|
|
6301
6301
|
const { lastTime, lastMsg, lastObj, lastLogger } = this;
|
|
6302
|
-
|
|
6303
|
-
|
|
6304
|
-
|
|
6305
|
-
|
|
6306
|
-
|
|
6302
|
+
stream2.lastLevel = level2;
|
|
6303
|
+
stream2.lastTime = lastTime;
|
|
6304
|
+
stream2.lastMsg = lastMsg;
|
|
6305
|
+
stream2.lastObj = lastObj;
|
|
6306
|
+
stream2.lastLogger = lastLogger;
|
|
6307
6307
|
}
|
|
6308
|
-
|
|
6308
|
+
stream2.write(data);
|
|
6309
6309
|
if (opts.dedupe) {
|
|
6310
6310
|
recordedLevel = dest.level;
|
|
6311
6311
|
}
|
|
@@ -6315,16 +6315,16 @@ var require_multistream = __commonJS({
|
|
|
6315
6315
|
}
|
|
6316
6316
|
}
|
|
6317
6317
|
function emit(...args) {
|
|
6318
|
-
for (const { stream } of this.streams) {
|
|
6319
|
-
if (typeof
|
|
6320
|
-
|
|
6318
|
+
for (const { stream: stream2 } of this.streams) {
|
|
6319
|
+
if (typeof stream2.emit === "function") {
|
|
6320
|
+
stream2.emit(...args);
|
|
6321
6321
|
}
|
|
6322
6322
|
}
|
|
6323
6323
|
}
|
|
6324
6324
|
function flushSync() {
|
|
6325
|
-
for (const { stream } of this.streams) {
|
|
6326
|
-
if (typeof
|
|
6327
|
-
|
|
6325
|
+
for (const { stream: stream2 } of this.streams) {
|
|
6326
|
+
if (typeof stream2.flushSync === "function") {
|
|
6327
|
+
stream2.flushSync();
|
|
6328
6328
|
}
|
|
6329
6329
|
}
|
|
6330
6330
|
}
|
|
@@ -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
|
|
6340
|
+
const { streams, streamLevels: streamLevels2 } = this;
|
|
6341
6341
|
let level2;
|
|
6342
6342
|
if (typeof dest.levelVal === "number") {
|
|
6343
6343
|
level2 = dest.levelVal;
|
|
@@ -6354,33 +6354,33 @@ var require_multistream = __commonJS({
|
|
|
6354
6354
|
levelVal: void 0,
|
|
6355
6355
|
id: ++res.lastId
|
|
6356
6356
|
};
|
|
6357
|
-
|
|
6358
|
-
|
|
6359
|
-
this.minLevel =
|
|
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
|
|
6364
|
-
const index =
|
|
6363
|
+
const { streams } = this;
|
|
6364
|
+
const index = streams.findIndex((s) => s.id === id2);
|
|
6365
6365
|
if (index >= 0) {
|
|
6366
|
-
|
|
6367
|
-
|
|
6368
|
-
this.minLevel =
|
|
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
|
}
|
|
6372
6372
|
function end() {
|
|
6373
|
-
for (const { stream } of this.streams) {
|
|
6374
|
-
if (typeof
|
|
6375
|
-
|
|
6373
|
+
for (const { stream: stream2 } of this.streams) {
|
|
6374
|
+
if (typeof stream2.flushSync === "function") {
|
|
6375
|
+
stream2.flushSync();
|
|
6376
6376
|
}
|
|
6377
|
-
|
|
6377
|
+
stream2.end();
|
|
6378
6378
|
}
|
|
6379
6379
|
}
|
|
6380
6380
|
function clone(level2) {
|
|
6381
|
-
const
|
|
6382
|
-
for (let i = 0; i <
|
|
6383
|
-
|
|
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
|
|
6393
|
+
streams,
|
|
6394
6394
|
clone,
|
|
6395
6395
|
emit,
|
|
6396
6396
|
flushSync,
|
|
@@ -6503,7 +6503,7 @@ var require_pino = __commonJS({
|
|
|
6503
6503
|
var serializers = Object.assign(/* @__PURE__ */ Object.create(null), stdSerializers);
|
|
6504
6504
|
function pino2(...args) {
|
|
6505
6505
|
const instance = {};
|
|
6506
|
-
const { opts, stream } = normalize(instance, caller(), ...args);
|
|
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,
|
|
@@ -6566,8 +6566,8 @@ var require_pino = __commonJS({
|
|
|
6566
6566
|
if (msgPrefix && typeof msgPrefix !== "string") throw Error(`Unknown msgPrefix type "${typeof msgPrefix}" - expected "string"`);
|
|
6567
6567
|
assertDefaultLevelFound(level2, customLevels, useOnlyCustomLevels);
|
|
6568
6568
|
const levels = mappings(customLevels, useOnlyCustomLevels);
|
|
6569
|
-
if (typeof
|
|
6570
|
-
|
|
6569
|
+
if (typeof stream2.emit === "function") {
|
|
6570
|
+
stream2.emit("message", { code: "PINO_CONFIG", config: { levels, messageKey, errorKey } });
|
|
6571
6571
|
}
|
|
6572
6572
|
assertLevelComparison(levelComparison);
|
|
6573
6573
|
const levelCompFunc = genLevelComparison(levelComparison);
|
|
@@ -6575,7 +6575,7 @@ var require_pino = __commonJS({
|
|
|
6575
6575
|
levels,
|
|
6576
6576
|
[levelCompSym]: levelCompFunc,
|
|
6577
6577
|
[useOnlyCustomLevelsSym]: useOnlyCustomLevels,
|
|
6578
|
-
[streamSym]:
|
|
6578
|
+
[streamSym]: stream2,
|
|
6579
6579
|
[timeSym]: time2,
|
|
6580
6580
|
[timeSliceIndexSym]: timeSliceIndex,
|
|
6581
6581
|
[stringifySym]: stringify,
|
|
@@ -6738,7 +6738,7 @@ import { EventEmitter } from "events";
|
|
|
6738
6738
|
import fs from "fs";
|
|
6739
6739
|
import { createWriteStream } from "fs";
|
|
6740
6740
|
import { tmpdir as tmpdir4 } from "os";
|
|
6741
|
-
import { join as
|
|
6741
|
+
import { join as join5 } from "path";
|
|
6742
6742
|
|
|
6743
6743
|
// src/core/backends/naudiodon-backend.ts
|
|
6744
6744
|
var UnsupportedError = class extends Error {
|
|
@@ -7389,12 +7389,74 @@ var HowlerBackend = class {
|
|
|
7389
7389
|
}
|
|
7390
7390
|
};
|
|
7391
7391
|
|
|
7392
|
+
// src/utils/logger.ts
|
|
7393
|
+
var import_pino = __toESM(require_pino(), 1);
|
|
7394
|
+
import { Transform } from "stream";
|
|
7395
|
+
import { homedir } from "os";
|
|
7396
|
+
import { join as join4 } from "path";
|
|
7397
|
+
import { existsSync as existsSync4, mkdirSync } from "fs";
|
|
7398
|
+
var logDir = join4(homedir(), ".ocosay");
|
|
7399
|
+
var logFile = join4(logDir, "ocosay.log");
|
|
7400
|
+
if (!existsSync4(logDir)) {
|
|
7401
|
+
try {
|
|
7402
|
+
mkdirSync(logDir, { recursive: true });
|
|
7403
|
+
} catch {
|
|
7404
|
+
}
|
|
7405
|
+
}
|
|
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;
|
|
7429
|
+
try {
|
|
7430
|
+
const fileDest = import_pino.default.destination({ dest: logFile, mkdir: true });
|
|
7431
|
+
fileStream = createFormatStream();
|
|
7432
|
+
fileStream.pipe(fileDest);
|
|
7433
|
+
} catch {
|
|
7434
|
+
}
|
|
7435
|
+
var logger = (0, import_pino.default)(
|
|
7436
|
+
{
|
|
7437
|
+
level,
|
|
7438
|
+
base: { service: "ocosay" },
|
|
7439
|
+
timestamp: import_pino.default.stdTimeFunctions.isoTime,
|
|
7440
|
+
formatters: {
|
|
7441
|
+
level: (label) => ({ level: label })
|
|
7442
|
+
}
|
|
7443
|
+
},
|
|
7444
|
+
import_pino.default.multistream([
|
|
7445
|
+
{ stream: stdoutStream },
|
|
7446
|
+
...fileStream ? [{ stream: fileStream }] : []
|
|
7447
|
+
])
|
|
7448
|
+
);
|
|
7449
|
+
function createModuleLogger(module) {
|
|
7450
|
+
return logger.child({ module });
|
|
7451
|
+
}
|
|
7452
|
+
|
|
7392
7453
|
// src/core/backends/index.ts
|
|
7393
7454
|
function isNaudiodonAvailable() {
|
|
7394
7455
|
try {
|
|
7395
7456
|
__require.resolve("naudiodon");
|
|
7396
7457
|
return true;
|
|
7397
|
-
} catch (
|
|
7458
|
+
} catch (err) {
|
|
7459
|
+
logger.debug({ err }, "naudiodon not available");
|
|
7398
7460
|
return false;
|
|
7399
7461
|
}
|
|
7400
7462
|
}
|
|
@@ -7417,7 +7479,8 @@ function createBackend(type = "auto" /* AUTO */, options = {}) {
|
|
|
7417
7479
|
if (naudiodon) {
|
|
7418
7480
|
return new NaudiodonBackend(options);
|
|
7419
7481
|
}
|
|
7420
|
-
} catch (
|
|
7482
|
+
} catch (err) {
|
|
7483
|
+
logger.warn({ err }, "failed to initialize naudiodon backend");
|
|
7421
7484
|
}
|
|
7422
7485
|
}
|
|
7423
7486
|
switch (platform) {
|
|
@@ -7510,7 +7573,7 @@ var AudioPlayer = class extends EventEmitter {
|
|
|
7510
7573
|
this._playing = true;
|
|
7511
7574
|
this._paused = false;
|
|
7512
7575
|
try {
|
|
7513
|
-
const tempFile =
|
|
7576
|
+
const tempFile = join5(tmpdir4(), `ocosay-${Date.now()}.${format}`);
|
|
7514
7577
|
this.currentFile = tempFile;
|
|
7515
7578
|
if (Buffer.isBuffer(audioData)) {
|
|
7516
7579
|
fs.writeFileSync(tempFile, audioData);
|
|
@@ -7607,52 +7670,81 @@ var AudioPlayer = class extends EventEmitter {
|
|
|
7607
7670
|
}
|
|
7608
7671
|
};
|
|
7609
7672
|
|
|
7610
|
-
// src/
|
|
7611
|
-
var
|
|
7612
|
-
|
|
7613
|
-
|
|
7614
|
-
|
|
7615
|
-
|
|
7616
|
-
|
|
7617
|
-
|
|
7618
|
-
|
|
7619
|
-
|
|
7620
|
-
}
|
|
7621
|
-
|
|
7622
|
-
}
|
|
7623
|
-
|
|
7624
|
-
|
|
7625
|
-
|
|
7626
|
-
|
|
7627
|
-
|
|
7628
|
-
}
|
|
7629
|
-
}
|
|
7630
|
-
var level = process.env.NODE_ENV !== "production" ? "debug" : process.env.OCOSAY_LOG_LEVEL || "info";
|
|
7631
|
-
var logger = (0, import_pino.default)(
|
|
7632
|
-
{
|
|
7633
|
-
level,
|
|
7634
|
-
base: { service: "ocosay" },
|
|
7635
|
-
timestamp: import_pino.default.stdTimeFunctions.isoTime
|
|
7636
|
-
},
|
|
7637
|
-
import_pino.default.multistream(streams)
|
|
7638
|
-
);
|
|
7639
|
-
|
|
7640
|
-
// src/core/speaker.ts
|
|
7641
|
-
function toast(options) {
|
|
7642
|
-
const tui = global.__opencode_tui__;
|
|
7643
|
-
if (tui?.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
|
+
}
|
|
7644
7692
|
try {
|
|
7645
|
-
tui.showToast({
|
|
7646
|
-
|
|
7647
|
-
|
|
7648
|
-
|
|
7649
|
-
|
|
7693
|
+
this.tui.showToast({
|
|
7694
|
+
body: {
|
|
7695
|
+
title,
|
|
7696
|
+
message,
|
|
7697
|
+
variant,
|
|
7698
|
+
duration
|
|
7699
|
+
}
|
|
7650
7700
|
});
|
|
7701
|
+
logger2.debug({ title, variant }, "toast shown");
|
|
7702
|
+
return true;
|
|
7651
7703
|
} catch (err) {
|
|
7652
|
-
|
|
7704
|
+
logger2.warn({ err, title }, "toast call failed, queueing for retry");
|
|
7705
|
+
this.pendingToasts.push(options);
|
|
7706
|
+
this.scheduleRetry();
|
|
7707
|
+
return false;
|
|
7653
7708
|
}
|
|
7654
7709
|
}
|
|
7655
|
-
|
|
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");
|
|
7656
7748
|
var Speaker = class extends EventEmitter2 {
|
|
7657
7749
|
constructor(options = {}) {
|
|
7658
7750
|
super();
|
|
@@ -7662,11 +7754,10 @@ var Speaker = class extends EventEmitter2 {
|
|
|
7662
7754
|
onEnd: () => {
|
|
7663
7755
|
this.isSpeaking = false;
|
|
7664
7756
|
this.emit("end", this.currentText);
|
|
7665
|
-
|
|
7666
|
-
|
|
7667
|
-
|
|
7668
|
-
|
|
7669
|
-
});
|
|
7757
|
+
notificationService.info(
|
|
7758
|
+
"TTS playback success",
|
|
7759
|
+
"Audio generated and playing"
|
|
7760
|
+
);
|
|
7670
7761
|
},
|
|
7671
7762
|
onError: (error) => this.emit("error", error),
|
|
7672
7763
|
onPause: () => {
|
|
@@ -7729,16 +7820,16 @@ var Speaker = class extends EventEmitter2 {
|
|
|
7729
7820
|
});
|
|
7730
7821
|
if (this.player) {
|
|
7731
7822
|
await this.player.play(result.audioData, result.format);
|
|
7732
|
-
|
|
7823
|
+
logger3.info({ textLength: text.length, model: options.model }, "TTS playback completed");
|
|
7733
7824
|
}
|
|
7734
7825
|
} catch (error) {
|
|
7735
7826
|
this.isSpeaking = false;
|
|
7827
|
+
logger3.error({ error }, "speak failed");
|
|
7736
7828
|
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
7737
|
-
|
|
7738
|
-
|
|
7739
|
-
|
|
7740
|
-
|
|
7741
|
-
});
|
|
7829
|
+
notificationService.error(
|
|
7830
|
+
"TTS playback error",
|
|
7831
|
+
errorMessage
|
|
7832
|
+
);
|
|
7742
7833
|
if (error instanceof TTSError) {
|
|
7743
7834
|
this.emit("error", error);
|
|
7744
7835
|
throw error;
|
|
@@ -7801,61 +7892,524 @@ var Speaker = class extends EventEmitter2 {
|
|
|
7801
7892
|
return provider.listVoices();
|
|
7802
7893
|
}
|
|
7803
7894
|
/**
|
|
7804
|
-
* 获取 Provider 能力
|
|
7895
|
+
* 获取 Provider 能力
|
|
7896
|
+
*/
|
|
7897
|
+
getCapabilities(providerName) {
|
|
7898
|
+
const name = providerName || this.options.defaultProvider || "minimax";
|
|
7899
|
+
const provider = getProvider(name);
|
|
7900
|
+
return provider.getCapabilities();
|
|
7901
|
+
}
|
|
7902
|
+
/**
|
|
7903
|
+
* 获取所有已注册的 Provider
|
|
7904
|
+
*/
|
|
7905
|
+
getProviders() {
|
|
7906
|
+
return listProviders();
|
|
7907
|
+
}
|
|
7908
|
+
/**
|
|
7909
|
+
* 是否正在播放
|
|
7910
|
+
*/
|
|
7911
|
+
isPlaying() {
|
|
7912
|
+
return this.isSpeaking && !this.isPaused;
|
|
7913
|
+
}
|
|
7914
|
+
/**
|
|
7915
|
+
* 是否暂停
|
|
7916
|
+
*/
|
|
7917
|
+
isPausedState() {
|
|
7918
|
+
return this.isPaused;
|
|
7919
|
+
}
|
|
7920
|
+
};
|
|
7921
|
+
var defaultSpeaker;
|
|
7922
|
+
function getDefaultSpeaker() {
|
|
7923
|
+
if (!defaultSpeaker) {
|
|
7924
|
+
defaultSpeaker = new Speaker();
|
|
7925
|
+
}
|
|
7926
|
+
return defaultSpeaker;
|
|
7927
|
+
}
|
|
7928
|
+
async function speak(text, options) {
|
|
7929
|
+
const speaker2 = getDefaultSpeaker();
|
|
7930
|
+
return speaker2.speak(text, options);
|
|
7931
|
+
}
|
|
7932
|
+
async function stop() {
|
|
7933
|
+
const speaker2 = getDefaultSpeaker();
|
|
7934
|
+
return speaker2.stop();
|
|
7935
|
+
}
|
|
7936
|
+
function pause() {
|
|
7937
|
+
const speaker2 = getDefaultSpeaker();
|
|
7938
|
+
speaker2.pause();
|
|
7939
|
+
}
|
|
7940
|
+
function resume() {
|
|
7941
|
+
const speaker2 = getDefaultSpeaker();
|
|
7942
|
+
speaker2.resume();
|
|
7943
|
+
}
|
|
7944
|
+
async function listVoices(providerName) {
|
|
7945
|
+
const speaker2 = getDefaultSpeaker();
|
|
7946
|
+
return speaker2.listVoices(providerName);
|
|
7947
|
+
}
|
|
7948
|
+
|
|
7949
|
+
// src/services/speaker-service.ts
|
|
7950
|
+
var SpeakerService = class {
|
|
7951
|
+
constructor(options = {}) {
|
|
7952
|
+
this.options = options;
|
|
7953
|
+
this.speaker = getDefaultSpeaker();
|
|
7954
|
+
}
|
|
7955
|
+
options;
|
|
7956
|
+
speaker;
|
|
7957
|
+
async speak(text, options) {
|
|
7958
|
+
const timestamp = this.getTimestamp();
|
|
7959
|
+
logger.info(`[Ocosay][${timestamp}][INFO][Speaker] \u5BF9\u5E94\u4E8B\u4EF6{\u64AD\u653E\u5F00\u59CB} - \u6587\u672C\u957F\u5EA6: ${text.length}`);
|
|
7960
|
+
return this.speaker.speak(text, options);
|
|
7961
|
+
}
|
|
7962
|
+
pause() {
|
|
7963
|
+
this.speaker.pause();
|
|
7964
|
+
}
|
|
7965
|
+
resume() {
|
|
7966
|
+
this.speaker.resume();
|
|
7967
|
+
}
|
|
7968
|
+
async stop() {
|
|
7969
|
+
return this.speaker.stop();
|
|
7970
|
+
}
|
|
7971
|
+
async listVoices(providerName) {
|
|
7972
|
+
return this.speaker.listVoices(providerName);
|
|
7973
|
+
}
|
|
7974
|
+
getCapabilities(providerName) {
|
|
7975
|
+
return this.speaker.getCapabilities(providerName);
|
|
7976
|
+
}
|
|
7977
|
+
getProviders() {
|
|
7978
|
+
return this.speaker.getProviders();
|
|
7979
|
+
}
|
|
7980
|
+
isPlaying() {
|
|
7981
|
+
return this.speaker.isPlaying();
|
|
7982
|
+
}
|
|
7983
|
+
isPausedState() {
|
|
7984
|
+
return this.speaker.isPausedState();
|
|
7985
|
+
}
|
|
7986
|
+
async destroy() {
|
|
7987
|
+
return this.speaker.destroy();
|
|
7988
|
+
}
|
|
7989
|
+
getTimestamp() {
|
|
7990
|
+
const now = /* @__PURE__ */ new Date();
|
|
7991
|
+
const pad = (n) => n.toString().padStart(2, "0");
|
|
7992
|
+
return `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())} ${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}`;
|
|
7993
|
+
}
|
|
7994
|
+
};
|
|
7995
|
+
var defaultSpeakerService;
|
|
7996
|
+
function getDefaultSpeakerService() {
|
|
7997
|
+
if (!defaultSpeakerService) {
|
|
7998
|
+
defaultSpeakerService = new SpeakerService();
|
|
7999
|
+
}
|
|
8000
|
+
return defaultSpeakerService;
|
|
8001
|
+
}
|
|
8002
|
+
async function speak2(text, options) {
|
|
8003
|
+
if (options) {
|
|
8004
|
+
return speak(text, options);
|
|
8005
|
+
}
|
|
8006
|
+
return speak(text);
|
|
8007
|
+
}
|
|
8008
|
+
async function stop2() {
|
|
8009
|
+
return stop();
|
|
8010
|
+
}
|
|
8011
|
+
function pause2() {
|
|
8012
|
+
pause();
|
|
8013
|
+
}
|
|
8014
|
+
function resume2() {
|
|
8015
|
+
resume();
|
|
8016
|
+
}
|
|
8017
|
+
async function listVoices2(providerName) {
|
|
8018
|
+
return listVoices(providerName);
|
|
8019
|
+
}
|
|
8020
|
+
|
|
8021
|
+
// src/services/streaming-service.ts
|
|
8022
|
+
import { EventEmitter as EventEmitter4 } from "events";
|
|
8023
|
+
|
|
8024
|
+
// src/core/stream-player.ts
|
|
8025
|
+
import { EventEmitter as EventEmitter3 } from "events";
|
|
8026
|
+
var StreamPlayer = class extends EventEmitter3 {
|
|
8027
|
+
backend = null;
|
|
8028
|
+
_bytesWritten = 0;
|
|
8029
|
+
_started = false;
|
|
8030
|
+
_paused = false;
|
|
8031
|
+
_stopped = false;
|
|
8032
|
+
format = "mp3";
|
|
8033
|
+
events;
|
|
8034
|
+
constructor(options = {}) {
|
|
8035
|
+
super();
|
|
8036
|
+
this.format = options.format || "mp3";
|
|
8037
|
+
this.events = options.events;
|
|
8038
|
+
const backendType = options.backendType || "naudiodon" /* NAUDIODON */;
|
|
8039
|
+
this.backend = createBackend(backendType, {
|
|
8040
|
+
format: this.format,
|
|
8041
|
+
events: {
|
|
8042
|
+
onStart: () => {
|
|
8043
|
+
this.events?.onStart?.();
|
|
8044
|
+
this.emit("start");
|
|
8045
|
+
},
|
|
8046
|
+
onEnd: () => {
|
|
8047
|
+
this.events?.onEnd?.();
|
|
8048
|
+
this.emit("end");
|
|
8049
|
+
},
|
|
8050
|
+
onError: (error) => {
|
|
8051
|
+
this.handleError(error);
|
|
8052
|
+
},
|
|
8053
|
+
onPause: () => {
|
|
8054
|
+
this._paused = true;
|
|
8055
|
+
this.events?.onPause?.();
|
|
8056
|
+
this.emit("pause");
|
|
8057
|
+
},
|
|
8058
|
+
onResume: () => {
|
|
8059
|
+
this._paused = false;
|
|
8060
|
+
this.events?.onResume?.();
|
|
8061
|
+
this.emit("resume");
|
|
8062
|
+
},
|
|
8063
|
+
onStop: () => {
|
|
8064
|
+
this.events?.onStop?.();
|
|
8065
|
+
this.emit("stop");
|
|
8066
|
+
},
|
|
8067
|
+
onProgress: (bytes) => {
|
|
8068
|
+
this.events?.onProgress?.(bytes);
|
|
8069
|
+
this.emit("progress", bytes);
|
|
8070
|
+
}
|
|
8071
|
+
}
|
|
8072
|
+
});
|
|
8073
|
+
}
|
|
8074
|
+
/**
|
|
8075
|
+
* 开始播放
|
|
8076
|
+
* 初始化后端,准备接收音频数据
|
|
8077
|
+
*/
|
|
8078
|
+
start() {
|
|
8079
|
+
if (this._started) {
|
|
8080
|
+
return;
|
|
8081
|
+
}
|
|
8082
|
+
if (!this.backend) {
|
|
8083
|
+
this.handleError(new Error("Audio backend not initialized"));
|
|
8084
|
+
return;
|
|
8085
|
+
}
|
|
8086
|
+
this.backend.start("");
|
|
8087
|
+
this._started = true;
|
|
8088
|
+
this._stopped = false;
|
|
8089
|
+
this._paused = false;
|
|
8090
|
+
this._bytesWritten = 0;
|
|
8091
|
+
}
|
|
8092
|
+
/**
|
|
8093
|
+
* 写入音频数据块(边收边播)
|
|
8094
|
+
* 如果尚未 start(),会自动调用
|
|
8095
|
+
*/
|
|
8096
|
+
write(chunk) {
|
|
8097
|
+
if (this._stopped) {
|
|
8098
|
+
return;
|
|
8099
|
+
}
|
|
8100
|
+
if (!this._started) {
|
|
8101
|
+
this.start();
|
|
8102
|
+
}
|
|
8103
|
+
if (this.backend) {
|
|
8104
|
+
this.backend.write(chunk);
|
|
8105
|
+
this._bytesWritten += chunk.length;
|
|
8106
|
+
this.events?.onProgress?.(this._bytesWritten);
|
|
8107
|
+
this.emit("progress", this._bytesWritten);
|
|
8108
|
+
}
|
|
8109
|
+
}
|
|
8110
|
+
/**
|
|
8111
|
+
* 结束写入
|
|
8112
|
+
* 通知后端写入完成,但保持播放直到结束
|
|
8113
|
+
*/
|
|
8114
|
+
end() {
|
|
8115
|
+
if (this.backend) {
|
|
8116
|
+
this.backend.end();
|
|
8117
|
+
}
|
|
8118
|
+
}
|
|
8119
|
+
/**
|
|
8120
|
+
* 停止播放
|
|
8121
|
+
* 立即停止播放并释放资源
|
|
8122
|
+
*/
|
|
8123
|
+
stop() {
|
|
8124
|
+
this._stopped = true;
|
|
8125
|
+
this._started = false;
|
|
8126
|
+
this._paused = false;
|
|
8127
|
+
if (this.backend) {
|
|
8128
|
+
this.backend.stop();
|
|
8129
|
+
}
|
|
8130
|
+
this._bytesWritten = 0;
|
|
8131
|
+
this.events?.onStop?.();
|
|
8132
|
+
this.emit("stop");
|
|
8133
|
+
}
|
|
8134
|
+
/**
|
|
8135
|
+
* 暂停播放
|
|
8136
|
+
*/
|
|
8137
|
+
pause() {
|
|
8138
|
+
if (!this._started || this._paused || this._stopped) {
|
|
8139
|
+
return;
|
|
8140
|
+
}
|
|
8141
|
+
if (this.backend) {
|
|
8142
|
+
this.backend.pause();
|
|
8143
|
+
}
|
|
8144
|
+
}
|
|
8145
|
+
/**
|
|
8146
|
+
* 恢复播放
|
|
8147
|
+
*/
|
|
8148
|
+
resume() {
|
|
8149
|
+
if (!this._paused || this._stopped) {
|
|
8150
|
+
return;
|
|
8151
|
+
}
|
|
8152
|
+
if (this.backend) {
|
|
8153
|
+
this.backend.resume();
|
|
8154
|
+
}
|
|
8155
|
+
}
|
|
8156
|
+
/**
|
|
8157
|
+
* 是否已启动
|
|
8158
|
+
*/
|
|
8159
|
+
isStarted() {
|
|
8160
|
+
return this._started;
|
|
8161
|
+
}
|
|
8162
|
+
/**
|
|
8163
|
+
* 是否暂停
|
|
8164
|
+
*/
|
|
8165
|
+
isPaused() {
|
|
8166
|
+
return this._paused;
|
|
8167
|
+
}
|
|
8168
|
+
/**
|
|
8169
|
+
* 是否已停止
|
|
8170
|
+
*/
|
|
8171
|
+
isStopped() {
|
|
8172
|
+
return this._stopped;
|
|
8173
|
+
}
|
|
8174
|
+
/**
|
|
8175
|
+
* 获取已写入的字节数
|
|
8176
|
+
*/
|
|
8177
|
+
getBytesWritten() {
|
|
8178
|
+
return this._bytesWritten;
|
|
8179
|
+
}
|
|
8180
|
+
/**
|
|
8181
|
+
* 处理错误
|
|
8182
|
+
*/
|
|
8183
|
+
handleError(error) {
|
|
8184
|
+
this.events?.onError?.(error);
|
|
8185
|
+
this.emit("error", error);
|
|
8186
|
+
}
|
|
8187
|
+
};
|
|
8188
|
+
|
|
8189
|
+
// src/services/streaming-service.ts
|
|
8190
|
+
var StreamingService = class extends EventEmitter4 {
|
|
8191
|
+
player = null;
|
|
8192
|
+
providerName;
|
|
8193
|
+
voice;
|
|
8194
|
+
speed;
|
|
8195
|
+
volume;
|
|
8196
|
+
pitch;
|
|
8197
|
+
backendType;
|
|
8198
|
+
_isActive = false;
|
|
8199
|
+
_bytesWritten = 0;
|
|
8200
|
+
constructor(options = {}) {
|
|
8201
|
+
super();
|
|
8202
|
+
this.providerName = options.provider || "minimax";
|
|
8203
|
+
this.voice = options.voice;
|
|
8204
|
+
this.speed = options.speed;
|
|
8205
|
+
this.volume = options.volume;
|
|
8206
|
+
this.pitch = options.pitch;
|
|
8207
|
+
this.backendType = options.backendType || "naudiodon" /* NAUDIODON */;
|
|
8208
|
+
}
|
|
8209
|
+
/**
|
|
8210
|
+
* 获取时间戳
|
|
8211
|
+
*/
|
|
8212
|
+
getTimestamp() {
|
|
8213
|
+
const now = /* @__PURE__ */ new Date();
|
|
8214
|
+
const pad = (n) => n.toString().padStart(2, "0");
|
|
8215
|
+
return `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())} ${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}`;
|
|
8216
|
+
}
|
|
8217
|
+
/**
|
|
8218
|
+
* 初始化播放器
|
|
8219
|
+
*/
|
|
8220
|
+
initPlayer() {
|
|
8221
|
+
if (this.player) {
|
|
8222
|
+
this.player.stop();
|
|
8223
|
+
this.player = null;
|
|
8224
|
+
}
|
|
8225
|
+
const playerOptions = {
|
|
8226
|
+
format: "mp3",
|
|
8227
|
+
backendType: this.backendType,
|
|
8228
|
+
events: {
|
|
8229
|
+
onStart: () => {
|
|
8230
|
+
const timestamp = this.getTimestamp();
|
|
8231
|
+
logger.info(`[Ocosay][${timestamp}][INFO][Streaming] \u5BF9\u5E94\u4E8B\u4EF6{\u6D41\u5F0F\u64AD\u653E\u5F00\u59CB}`);
|
|
8232
|
+
this.emit("start");
|
|
8233
|
+
},
|
|
8234
|
+
onEnd: () => {
|
|
8235
|
+
const timestamp = this.getTimestamp();
|
|
8236
|
+
logger.info(`[Ocosay][${timestamp}][INFO][Streaming] \u5BF9\u5E94\u4E8B\u4EF6{\u6D41\u5F0F\u64AD\u653E\u7ED3\u675F}`);
|
|
8237
|
+
this._isActive = false;
|
|
8238
|
+
this.emit("end");
|
|
8239
|
+
},
|
|
8240
|
+
onError: (error) => {
|
|
8241
|
+
const timestamp = this.getTimestamp();
|
|
8242
|
+
logger.error(`[Ocosay][${timestamp}][ERROR][Streaming] \u5BF9\u5E94\u4E8B\u4EF6{\u6D41\u5F0F\u64AD\u653E\u9519\u8BEF} - ${error.message}`);
|
|
8243
|
+
this._isActive = false;
|
|
8244
|
+
this.emit("error", error);
|
|
8245
|
+
},
|
|
8246
|
+
onProgress: (bytes) => {
|
|
8247
|
+
this._bytesWritten = bytes;
|
|
8248
|
+
this.emit("progress", bytes);
|
|
8249
|
+
},
|
|
8250
|
+
onPause: () => {
|
|
8251
|
+
const timestamp = this.getTimestamp();
|
|
8252
|
+
logger.info(`[Ocosay][${timestamp}][INFO][Streaming] \u5BF9\u5E94\u4E8B\u4EF6{\u6D41\u5F0F\u64AD\u653E\u6682\u505C}`);
|
|
8253
|
+
this.emit("pause");
|
|
8254
|
+
},
|
|
8255
|
+
onResume: () => {
|
|
8256
|
+
const timestamp = this.getTimestamp();
|
|
8257
|
+
logger.info(`[Ocosay][${timestamp}][INFO][Streaming] \u5BF9\u5E94\u4E8B\u4EF6{\u6D41\u5F0F\u64AD\u653E\u6062\u590D}`);
|
|
8258
|
+
this.emit("resume");
|
|
8259
|
+
},
|
|
8260
|
+
onStop: () => {
|
|
8261
|
+
const timestamp = this.getTimestamp();
|
|
8262
|
+
logger.info(`[Ocosay][${timestamp}][INFO][Streaming] \u5BF9\u5E94\u4E8B\u4EF6{\u6D41\u5F0F\u64AD\u653E\u505C\u6B62}`);
|
|
8263
|
+
this._isActive = false;
|
|
8264
|
+
this._bytesWritten = 0;
|
|
8265
|
+
this.emit("stop");
|
|
8266
|
+
}
|
|
8267
|
+
}
|
|
8268
|
+
};
|
|
8269
|
+
this.player = new StreamPlayer(playerOptions);
|
|
8270
|
+
return this.player;
|
|
8271
|
+
}
|
|
8272
|
+
/**
|
|
8273
|
+
* 流式播放文本
|
|
8274
|
+
* 边接收边播放(豆包模式)
|
|
8275
|
+
*/
|
|
8276
|
+
async stream(text) {
|
|
8277
|
+
if (!text || text.trim().length === 0) {
|
|
8278
|
+
const timestamp2 = this.getTimestamp();
|
|
8279
|
+
logger.warn(`[Ocosay][${timestamp2}][WARNING][Streaming] \u5BF9\u5E94\u4E8B\u4EF6{\u7A7A\u6587\u672C\u8DF3\u8FC7}`);
|
|
8280
|
+
return;
|
|
8281
|
+
}
|
|
8282
|
+
const timestamp = this.getTimestamp();
|
|
8283
|
+
logger.info(`[Ocosay][${timestamp}][INFO][Streaming] \u5BF9\u5E94\u4E8B\u4EF6{\u6D41\u5F0F\u64AD\u653E\u5F00\u59CB} - \u6587\u672C\u957F\u5EA6: ${text.length}`);
|
|
8284
|
+
try {
|
|
8285
|
+
const provider = getProvider(this.providerName);
|
|
8286
|
+
if (!provider) {
|
|
8287
|
+
throw new TTSError(
|
|
8288
|
+
`Provider ${this.providerName} not found`,
|
|
8289
|
+
"UNKNOWN" /* UNKNOWN */,
|
|
8290
|
+
this.providerName
|
|
8291
|
+
);
|
|
8292
|
+
}
|
|
8293
|
+
const player = this.initPlayer();
|
|
8294
|
+
player.start();
|
|
8295
|
+
this._isActive = true;
|
|
8296
|
+
this._bytesWritten = 0;
|
|
8297
|
+
const result = await provider.speak(text, {
|
|
8298
|
+
voice: this.voice,
|
|
8299
|
+
model: "stream",
|
|
8300
|
+
speed: this.speed,
|
|
8301
|
+
volume: this.volume,
|
|
8302
|
+
pitch: this.pitch
|
|
8303
|
+
});
|
|
8304
|
+
await this.processAudioResult(result, player);
|
|
8305
|
+
} catch (error) {
|
|
8306
|
+
const ts = this.getTimestamp();
|
|
8307
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
8308
|
+
logger.error(`[Ocosay][${ts}][ERROR][Streaming] \u5BF9\u5E94\u4E8B\u4EF6{\u6D41\u5F0F\u64AD\u653E\u9519\u8BEF} - ${errorMsg}`);
|
|
8309
|
+
this._isActive = false;
|
|
8310
|
+
throw error;
|
|
8311
|
+
}
|
|
8312
|
+
}
|
|
8313
|
+
/**
|
|
8314
|
+
* 处理音频结果
|
|
8315
|
+
*/
|
|
8316
|
+
async processAudioResult(result, player) {
|
|
8317
|
+
if (result.isStream && result.audioData instanceof ReadableStream) {
|
|
8318
|
+
await this.streamAudioChunks(result.audioData, player);
|
|
8319
|
+
} else if (Buffer.isBuffer(result.audioData)) {
|
|
8320
|
+
player.write(result.audioData);
|
|
8321
|
+
player.end();
|
|
8322
|
+
}
|
|
8323
|
+
}
|
|
8324
|
+
/**
|
|
8325
|
+
* 流式处理音频chunk
|
|
8326
|
+
*/
|
|
8327
|
+
async streamAudioChunks(stream2, player) {
|
|
8328
|
+
const reader = stream2.getReader();
|
|
8329
|
+
try {
|
|
8330
|
+
while (true) {
|
|
8331
|
+
const { done, value } = await reader.read();
|
|
8332
|
+
if (done) {
|
|
8333
|
+
break;
|
|
8334
|
+
}
|
|
8335
|
+
if (value) {
|
|
8336
|
+
const chunk = Buffer.isBuffer(value) ? value : Buffer.from(value);
|
|
8337
|
+
player.write(chunk);
|
|
8338
|
+
}
|
|
8339
|
+
}
|
|
8340
|
+
} finally {
|
|
8341
|
+
reader.releaseLock();
|
|
8342
|
+
player.end();
|
|
8343
|
+
}
|
|
8344
|
+
}
|
|
8345
|
+
/**
|
|
8346
|
+
* 停止流式播放
|
|
8347
|
+
*/
|
|
8348
|
+
stop() {
|
|
8349
|
+
if (this.player) {
|
|
8350
|
+
this.player.stop();
|
|
8351
|
+
}
|
|
8352
|
+
this._isActive = false;
|
|
8353
|
+
this._bytesWritten = 0;
|
|
8354
|
+
}
|
|
8355
|
+
/**
|
|
8356
|
+
* 暂停流式播放
|
|
8357
|
+
*/
|
|
8358
|
+
pause() {
|
|
8359
|
+
if (this.player) {
|
|
8360
|
+
this.player.pause();
|
|
8361
|
+
}
|
|
8362
|
+
}
|
|
8363
|
+
/**
|
|
8364
|
+
* 恢复流式播放
|
|
7805
8365
|
*/
|
|
7806
|
-
|
|
7807
|
-
|
|
7808
|
-
|
|
7809
|
-
|
|
8366
|
+
resume() {
|
|
8367
|
+
if (this.player) {
|
|
8368
|
+
this.player.resume();
|
|
8369
|
+
}
|
|
7810
8370
|
}
|
|
7811
8371
|
/**
|
|
7812
|
-
*
|
|
8372
|
+
* 获取流式播放状态
|
|
7813
8373
|
*/
|
|
7814
|
-
|
|
7815
|
-
return
|
|
8374
|
+
getStatus() {
|
|
8375
|
+
return {
|
|
8376
|
+
isActive: this._isActive,
|
|
8377
|
+
bytesWritten: this._bytesWritten,
|
|
8378
|
+
state: this.player?.isStopped() ? "stopped" : this.player?.isPaused() ? "paused" : this._isActive ? "playing" : "idle"
|
|
8379
|
+
};
|
|
7816
8380
|
}
|
|
7817
8381
|
/**
|
|
7818
|
-
*
|
|
8382
|
+
* 是否处于活跃状态
|
|
7819
8383
|
*/
|
|
7820
|
-
|
|
7821
|
-
return this.
|
|
8384
|
+
isActive() {
|
|
8385
|
+
return this._isActive;
|
|
7822
8386
|
}
|
|
7823
8387
|
/**
|
|
7824
|
-
*
|
|
8388
|
+
* 销毁服务
|
|
7825
8389
|
*/
|
|
7826
|
-
|
|
7827
|
-
|
|
8390
|
+
async destroy() {
|
|
8391
|
+
if (this.player) {
|
|
8392
|
+
this.player.stop();
|
|
8393
|
+
this.player = null;
|
|
8394
|
+
}
|
|
8395
|
+
this._isActive = false;
|
|
8396
|
+
this._bytesWritten = 0;
|
|
7828
8397
|
}
|
|
7829
8398
|
};
|
|
7830
|
-
var
|
|
7831
|
-
function
|
|
7832
|
-
if (!
|
|
7833
|
-
|
|
8399
|
+
var defaultStreamingService;
|
|
8400
|
+
function getDefaultStreamingService() {
|
|
8401
|
+
if (!defaultStreamingService) {
|
|
8402
|
+
defaultStreamingService = new StreamingService();
|
|
7834
8403
|
}
|
|
7835
|
-
return
|
|
7836
|
-
}
|
|
7837
|
-
async function speak(text, options) {
|
|
7838
|
-
const speaker2 = getDefaultSpeaker();
|
|
7839
|
-
return speaker2.speak(text, options);
|
|
7840
|
-
}
|
|
7841
|
-
async function stop() {
|
|
7842
|
-
const speaker2 = getDefaultSpeaker();
|
|
7843
|
-
return speaker2.stop();
|
|
7844
|
-
}
|
|
7845
|
-
function pause() {
|
|
7846
|
-
const speaker2 = getDefaultSpeaker();
|
|
7847
|
-
speaker2.pause();
|
|
8404
|
+
return defaultStreamingService;
|
|
7848
8405
|
}
|
|
7849
|
-
function
|
|
7850
|
-
const
|
|
7851
|
-
|
|
7852
|
-
}
|
|
7853
|
-
async function listVoices(providerName) {
|
|
7854
|
-
const speaker2 = getDefaultSpeaker();
|
|
7855
|
-
return speaker2.listVoices(providerName);
|
|
8406
|
+
async function stream(text, options) {
|
|
8407
|
+
const service = options ? new StreamingService(options) : getDefaultStreamingService();
|
|
8408
|
+
return service.stream(text);
|
|
7856
8409
|
}
|
|
7857
8410
|
|
|
7858
8411
|
// src/tools/tts.ts
|
|
8412
|
+
var logger4 = createModuleLogger("TTS");
|
|
7859
8413
|
function extractTextArg(args) {
|
|
7860
8414
|
if (!args || typeof args !== "object") {
|
|
7861
8415
|
return void 0;
|
|
@@ -7868,17 +8422,26 @@ function extractTextArg(args) {
|
|
|
7868
8422
|
const text7 = argObj.text7;
|
|
7869
8423
|
if (text7 != null) {
|
|
7870
8424
|
if (typeof text7 === "string" && text7.trim().length > 0) {
|
|
7871
|
-
|
|
8425
|
+
logger4.warn("received text7 instead of text from OpenCode framework");
|
|
7872
8426
|
return text7.trim();
|
|
7873
8427
|
}
|
|
7874
|
-
if (typeof text7 === "object"
|
|
7875
|
-
|
|
7876
|
-
|
|
7877
|
-
|
|
7878
|
-
|
|
8428
|
+
if (typeof text7 === "object") {
|
|
8429
|
+
if ("split" in text7 && "content" in text7) {
|
|
8430
|
+
const content = text7.content;
|
|
8431
|
+
if (typeof content === "string" && content.trim().length > 0) {
|
|
8432
|
+
logger4.info("text7 split format detected");
|
|
8433
|
+
return content.trim();
|
|
8434
|
+
}
|
|
8435
|
+
}
|
|
8436
|
+
if ("content" in text7) {
|
|
8437
|
+
const content = text7.content;
|
|
8438
|
+
if (typeof content === "string" && content.trim().length > 0) {
|
|
8439
|
+
logger4.info("text7 content format detected");
|
|
8440
|
+
return content.trim();
|
|
8441
|
+
}
|
|
7879
8442
|
}
|
|
7880
8443
|
}
|
|
7881
|
-
|
|
8444
|
+
logger4.warn({ type: typeof text7 }, "text7 is not a valid string or object with content");
|
|
7882
8445
|
return void 0;
|
|
7883
8446
|
}
|
|
7884
8447
|
for (const key of Object.keys(argObj)) {
|
|
@@ -7890,7 +8453,7 @@ function extractTextArg(args) {
|
|
|
7890
8453
|
}
|
|
7891
8454
|
}
|
|
7892
8455
|
if (text !== void 0) {
|
|
7893
|
-
|
|
8456
|
+
logger4.warn({ type: typeof text }, "text arg is not a valid string");
|
|
7894
8457
|
}
|
|
7895
8458
|
return void 0;
|
|
7896
8459
|
}
|
|
@@ -7902,29 +8465,29 @@ async function handleToolCall(toolName, args) {
|
|
|
7902
8465
|
if (!text) {
|
|
7903
8466
|
return { success: false, error: "No valid text found in args" };
|
|
7904
8467
|
}
|
|
7905
|
-
await
|
|
8468
|
+
await speak2(text);
|
|
7906
8469
|
return { success: true, message: "Speech completed" };
|
|
7907
8470
|
}
|
|
7908
8471
|
case "tts_stop":
|
|
7909
|
-
await
|
|
8472
|
+
await stop2();
|
|
7910
8473
|
return { success: true, message: "Stopped" };
|
|
7911
8474
|
case "tts_pause":
|
|
7912
|
-
|
|
8475
|
+
pause2();
|
|
7913
8476
|
return { success: true, message: "Paused" };
|
|
7914
8477
|
case "tts_resume":
|
|
7915
|
-
|
|
8478
|
+
resume2();
|
|
7916
8479
|
return { success: true, message: "Resumed" };
|
|
7917
8480
|
case "tts_list_voices": {
|
|
7918
|
-
const voices = await
|
|
8481
|
+
const voices = await listVoices2(args?.provider);
|
|
7919
8482
|
return { success: true, voices };
|
|
7920
8483
|
}
|
|
7921
8484
|
case "tts_list_providers": {
|
|
7922
|
-
const speaker2 =
|
|
8485
|
+
const speaker2 = getDefaultSpeakerService();
|
|
7923
8486
|
const providers2 = speaker2.getProviders();
|
|
7924
8487
|
return { success: true, providers: providers2 };
|
|
7925
8488
|
}
|
|
7926
8489
|
case "tts_status": {
|
|
7927
|
-
const s =
|
|
8490
|
+
const s = getDefaultSpeakerService();
|
|
7928
8491
|
return {
|
|
7929
8492
|
success: true,
|
|
7930
8493
|
isPlaying: s.isPlaying(),
|
|
@@ -7946,14 +8509,14 @@ async function handleToolCall(toolName, args) {
|
|
|
7946
8509
|
"tts_stream"
|
|
7947
8510
|
);
|
|
7948
8511
|
}
|
|
7949
|
-
const
|
|
7950
|
-
|
|
7951
|
-
if (streamReader2 && synthesizer) {
|
|
7952
|
-
streamReader2.start();
|
|
8512
|
+
const streamingService = getDefaultStreamingService();
|
|
8513
|
+
if (streamingService) {
|
|
7953
8514
|
const textArg = extractTextArg(args);
|
|
7954
8515
|
if (textArg && typeof textArg === "string" && textArg.trim().length > 0) {
|
|
7955
|
-
|
|
7956
|
-
|
|
8516
|
+
logger4.info({ text: textArg.substring(0, 50) + "..." }, "synthesizing text");
|
|
8517
|
+
stream(textArg).catch((error) => {
|
|
8518
|
+
logger4.error({ error }, "stream failed");
|
|
8519
|
+
});
|
|
7957
8520
|
}
|
|
7958
8521
|
return { success: true, message: "Stream speak started" };
|
|
7959
8522
|
}
|
|
@@ -7971,13 +8534,13 @@ async function handleToolCall(toolName, args) {
|
|
|
7971
8534
|
"tts_stream"
|
|
7972
8535
|
);
|
|
7973
8536
|
}
|
|
7974
|
-
const
|
|
7975
|
-
if (
|
|
7976
|
-
|
|
8537
|
+
const streamingService = getDefaultStreamingService();
|
|
8538
|
+
if (streamingService) {
|
|
8539
|
+
streamingService.stop();
|
|
7977
8540
|
return { success: true, message: "Stream stopped" };
|
|
7978
8541
|
}
|
|
7979
8542
|
throw new TTSError(
|
|
7980
|
-
"Stream
|
|
8543
|
+
"Stream service not available",
|
|
7981
8544
|
"UNKNOWN" /* UNKNOWN */,
|
|
7982
8545
|
"tts_stream"
|
|
7983
8546
|
);
|
|
@@ -8105,34 +8668,39 @@ var MiniMaxProvider = class extends BaseTTSProvider {
|
|
|
8105
8668
|
},
|
|
8106
8669
|
responseType: "stream"
|
|
8107
8670
|
});
|
|
8108
|
-
const
|
|
8671
|
+
const stream2 = response.data;
|
|
8109
8672
|
const audioChunks = [];
|
|
8673
|
+
let lineBuffer = "";
|
|
8110
8674
|
return new Promise((resolve, reject) => {
|
|
8111
|
-
|
|
8112
|
-
|
|
8113
|
-
|
|
8114
|
-
|
|
8115
|
-
|
|
8116
|
-
|
|
8117
|
-
|
|
8118
|
-
|
|
8119
|
-
|
|
8120
|
-
|
|
8121
|
-
|
|
8122
|
-
|
|
8123
|
-
|
|
8124
|
-
|
|
8125
|
-
|
|
8126
|
-
|
|
8127
|
-
|
|
8128
|
-
|
|
8675
|
+
stream2.on("data", (chunk) => {
|
|
8676
|
+
lineBuffer += chunk.toString();
|
|
8677
|
+
while (true) {
|
|
8678
|
+
const lineEnd = lineBuffer.indexOf("\n");
|
|
8679
|
+
if (lineEnd === -1) break;
|
|
8680
|
+
const line = lineBuffer.slice(0, lineEnd).trim();
|
|
8681
|
+
lineBuffer = lineBuffer.slice(lineEnd + 1);
|
|
8682
|
+
if (!line || !line.startsWith("data:")) continue;
|
|
8683
|
+
const jsonStr = line.slice(5).trim();
|
|
8684
|
+
if (!jsonStr) continue;
|
|
8685
|
+
try {
|
|
8686
|
+
const data = JSON.parse(jsonStr);
|
|
8687
|
+
if (data.audio) {
|
|
8688
|
+
audioChunks.push(Buffer.from(data.audio, "hex"));
|
|
8689
|
+
}
|
|
8690
|
+
if (data.is_final === true) {
|
|
8691
|
+
const fullAudio = Buffer.concat(audioChunks);
|
|
8692
|
+
resolve({
|
|
8693
|
+
audioData: fullAudio,
|
|
8694
|
+
format: this.audioFormat,
|
|
8695
|
+
isStream: true,
|
|
8696
|
+
duration: this.estimateDuration(fullAudio.length)
|
|
8697
|
+
});
|
|
8129
8698
|
}
|
|
8699
|
+
} catch (e) {
|
|
8130
8700
|
}
|
|
8131
|
-
} catch (e) {
|
|
8132
|
-
audioChunks.push(chunk);
|
|
8133
8701
|
}
|
|
8134
8702
|
});
|
|
8135
|
-
|
|
8703
|
+
stream2.on("error", (err) => {
|
|
8136
8704
|
reject(new TTSError(
|
|
8137
8705
|
"Stream error",
|
|
8138
8706
|
"NETWORK" /* NETWORK */,
|
|
@@ -8140,7 +8708,19 @@ var MiniMaxProvider = class extends BaseTTSProvider {
|
|
|
8140
8708
|
err
|
|
8141
8709
|
));
|
|
8142
8710
|
});
|
|
8143
|
-
|
|
8711
|
+
stream2.on("end", () => {
|
|
8712
|
+
if (lineBuffer.trim() && lineBuffer.startsWith("data:")) {
|
|
8713
|
+
const jsonStr = lineBuffer.slice(5).trim();
|
|
8714
|
+
if (jsonStr) {
|
|
8715
|
+
try {
|
|
8716
|
+
const data = JSON.parse(jsonStr);
|
|
8717
|
+
if (data.audio) {
|
|
8718
|
+
audioChunks.push(Buffer.from(data.audio, "hex"));
|
|
8719
|
+
}
|
|
8720
|
+
} catch (e) {
|
|
8721
|
+
}
|
|
8722
|
+
}
|
|
8723
|
+
}
|
|
8144
8724
|
if (audioChunks.length > 0) {
|
|
8145
8725
|
const fullAudio = Buffer.concat(audioChunks);
|
|
8146
8726
|
resolve({
|
|
@@ -8430,8 +9010,9 @@ var MINIMAX_VOICES = [
|
|
|
8430
9010
|
];
|
|
8431
9011
|
|
|
8432
9012
|
// src/core/stream-reader.ts
|
|
8433
|
-
import { EventEmitter as
|
|
8434
|
-
var
|
|
9013
|
+
import { EventEmitter as EventEmitter5 } from "events";
|
|
9014
|
+
var logger5 = createModuleLogger("StreamReader");
|
|
9015
|
+
var StreamReader = class extends EventEmitter5 {
|
|
8435
9016
|
constructor(bufferSize = 30, bufferTimeout = 2e3) {
|
|
8436
9017
|
super();
|
|
8437
9018
|
this.bufferSize = bufferSize;
|
|
@@ -8457,7 +9038,7 @@ var StreamReader = class extends EventEmitter3 {
|
|
|
8457
9038
|
}
|
|
8458
9039
|
handleDelta(sessionID, messageID, partID, delta) {
|
|
8459
9040
|
if (typeof delta !== "string") {
|
|
8460
|
-
|
|
9041
|
+
logger5.warn({ delta }, "handleDelta received non-string delta, skipping");
|
|
8461
9042
|
return;
|
|
8462
9043
|
}
|
|
8463
9044
|
if (this.state === "idle" /* IDLE */) {
|
|
@@ -8466,11 +9047,11 @@ var StreamReader = class extends EventEmitter3 {
|
|
|
8466
9047
|
this.messageID = messageID;
|
|
8467
9048
|
this.partID = partID;
|
|
8468
9049
|
this.emit("streamStart");
|
|
8469
|
-
|
|
9050
|
+
logger5.debug({ sessionID, messageID, partID }, "Stream started");
|
|
8470
9051
|
}
|
|
8471
9052
|
this.buffer += delta;
|
|
8472
9053
|
this.resetTimeout();
|
|
8473
|
-
|
|
9054
|
+
logger5.debug({ deltaLength: delta.length, bufferLength: this.buffer.length }, "Delta received");
|
|
8474
9055
|
if (this.shouldFlush()) {
|
|
8475
9056
|
this.flushBuffer();
|
|
8476
9057
|
}
|
|
@@ -8595,8 +9176,8 @@ var StreamReader = class extends EventEmitter3 {
|
|
|
8595
9176
|
};
|
|
8596
9177
|
|
|
8597
9178
|
// src/core/streaming-synthesizer.ts
|
|
8598
|
-
import { EventEmitter as
|
|
8599
|
-
var StreamingSynthesizer = class extends
|
|
9179
|
+
import { EventEmitter as EventEmitter6 } from "events";
|
|
9180
|
+
var StreamingSynthesizer = class extends EventEmitter6 {
|
|
8600
9181
|
constructor(options) {
|
|
8601
9182
|
super();
|
|
8602
9183
|
this.options = options;
|
|
@@ -8622,6 +9203,7 @@ var StreamingSynthesizer = class extends EventEmitter4 {
|
|
|
8622
9203
|
await this.processAudioResult(result);
|
|
8623
9204
|
this.emit("done");
|
|
8624
9205
|
} catch (error) {
|
|
9206
|
+
logger.error({ error }, "synthesize failed");
|
|
8625
9207
|
const ttsError = error instanceof TTSError ? error : new TTSError(
|
|
8626
9208
|
error instanceof Error ? error.message : "Synthesis failed",
|
|
8627
9209
|
"UNKNOWN",
|
|
@@ -8644,8 +9226,8 @@ var StreamingSynthesizer = class extends EventEmitter4 {
|
|
|
8644
9226
|
/**
|
|
8645
9227
|
* 处理 ReadableStream,逐chunk emit
|
|
8646
9228
|
*/
|
|
8647
|
-
async processReadableStream(
|
|
8648
|
-
const reader =
|
|
9229
|
+
async processReadableStream(stream2) {
|
|
9230
|
+
const reader = stream2.getReader();
|
|
8649
9231
|
try {
|
|
8650
9232
|
while (true) {
|
|
8651
9233
|
const { done, value } = await reader.read();
|
|
@@ -8684,171 +9266,6 @@ var StreamingSynthesizer = class extends EventEmitter4 {
|
|
|
8684
9266
|
}
|
|
8685
9267
|
};
|
|
8686
9268
|
|
|
8687
|
-
// src/core/stream-player.ts
|
|
8688
|
-
import { EventEmitter as EventEmitter5 } from "events";
|
|
8689
|
-
var StreamPlayer = class extends EventEmitter5 {
|
|
8690
|
-
backend = null;
|
|
8691
|
-
_bytesWritten = 0;
|
|
8692
|
-
_started = false;
|
|
8693
|
-
_paused = false;
|
|
8694
|
-
_stopped = false;
|
|
8695
|
-
format = "mp3";
|
|
8696
|
-
events;
|
|
8697
|
-
constructor(options = {}) {
|
|
8698
|
-
super();
|
|
8699
|
-
this.format = options.format || "mp3";
|
|
8700
|
-
this.events = options.events;
|
|
8701
|
-
const backendType = options.backendType || "naudiodon" /* NAUDIODON */;
|
|
8702
|
-
this.backend = createBackend(backendType, {
|
|
8703
|
-
format: this.format,
|
|
8704
|
-
events: {
|
|
8705
|
-
onStart: () => {
|
|
8706
|
-
this.events?.onStart?.();
|
|
8707
|
-
this.emit("start");
|
|
8708
|
-
},
|
|
8709
|
-
onEnd: () => {
|
|
8710
|
-
this.events?.onEnd?.();
|
|
8711
|
-
this.emit("end");
|
|
8712
|
-
},
|
|
8713
|
-
onError: (error) => {
|
|
8714
|
-
this.handleError(error);
|
|
8715
|
-
},
|
|
8716
|
-
onPause: () => {
|
|
8717
|
-
this._paused = true;
|
|
8718
|
-
this.events?.onPause?.();
|
|
8719
|
-
this.emit("pause");
|
|
8720
|
-
},
|
|
8721
|
-
onResume: () => {
|
|
8722
|
-
this._paused = false;
|
|
8723
|
-
this.events?.onResume?.();
|
|
8724
|
-
this.emit("resume");
|
|
8725
|
-
},
|
|
8726
|
-
onStop: () => {
|
|
8727
|
-
this.events?.onStop?.();
|
|
8728
|
-
this.emit("stop");
|
|
8729
|
-
},
|
|
8730
|
-
onProgress: (bytes) => {
|
|
8731
|
-
this.events?.onProgress?.(bytes);
|
|
8732
|
-
this.emit("progress", bytes);
|
|
8733
|
-
}
|
|
8734
|
-
}
|
|
8735
|
-
});
|
|
8736
|
-
}
|
|
8737
|
-
/**
|
|
8738
|
-
* 开始播放
|
|
8739
|
-
* 初始化后端,准备接收音频数据
|
|
8740
|
-
*/
|
|
8741
|
-
start() {
|
|
8742
|
-
if (this._started) {
|
|
8743
|
-
return;
|
|
8744
|
-
}
|
|
8745
|
-
if (!this.backend) {
|
|
8746
|
-
this.handleError(new Error("Audio backend not initialized"));
|
|
8747
|
-
return;
|
|
8748
|
-
}
|
|
8749
|
-
this.backend.start("");
|
|
8750
|
-
this._started = true;
|
|
8751
|
-
this._stopped = false;
|
|
8752
|
-
this._paused = false;
|
|
8753
|
-
this._bytesWritten = 0;
|
|
8754
|
-
}
|
|
8755
|
-
/**
|
|
8756
|
-
* 写入音频数据块(边收边播)
|
|
8757
|
-
* 如果尚未 start(),会自动调用
|
|
8758
|
-
*/
|
|
8759
|
-
write(chunk) {
|
|
8760
|
-
if (this._stopped) {
|
|
8761
|
-
return;
|
|
8762
|
-
}
|
|
8763
|
-
if (!this._started) {
|
|
8764
|
-
this.start();
|
|
8765
|
-
}
|
|
8766
|
-
if (this.backend) {
|
|
8767
|
-
this.backend.write(chunk);
|
|
8768
|
-
this._bytesWritten += chunk.length;
|
|
8769
|
-
this.events?.onProgress?.(this._bytesWritten);
|
|
8770
|
-
this.emit("progress", this._bytesWritten);
|
|
8771
|
-
}
|
|
8772
|
-
}
|
|
8773
|
-
/**
|
|
8774
|
-
* 结束写入
|
|
8775
|
-
* 通知后端写入完成,但保持播放直到结束
|
|
8776
|
-
*/
|
|
8777
|
-
end() {
|
|
8778
|
-
if (this.backend) {
|
|
8779
|
-
this.backend.end();
|
|
8780
|
-
}
|
|
8781
|
-
}
|
|
8782
|
-
/**
|
|
8783
|
-
* 停止播放
|
|
8784
|
-
* 立即停止播放并释放资源
|
|
8785
|
-
*/
|
|
8786
|
-
stop() {
|
|
8787
|
-
this._stopped = true;
|
|
8788
|
-
this._started = false;
|
|
8789
|
-
this._paused = false;
|
|
8790
|
-
if (this.backend) {
|
|
8791
|
-
this.backend.stop();
|
|
8792
|
-
}
|
|
8793
|
-
this._bytesWritten = 0;
|
|
8794
|
-
this.events?.onStop?.();
|
|
8795
|
-
this.emit("stop");
|
|
8796
|
-
}
|
|
8797
|
-
/**
|
|
8798
|
-
* 暂停播放
|
|
8799
|
-
*/
|
|
8800
|
-
pause() {
|
|
8801
|
-
if (!this._started || this._paused || this._stopped) {
|
|
8802
|
-
return;
|
|
8803
|
-
}
|
|
8804
|
-
if (this.backend) {
|
|
8805
|
-
this.backend.pause();
|
|
8806
|
-
}
|
|
8807
|
-
}
|
|
8808
|
-
/**
|
|
8809
|
-
* 恢复播放
|
|
8810
|
-
*/
|
|
8811
|
-
resume() {
|
|
8812
|
-
if (!this._paused || this._stopped) {
|
|
8813
|
-
return;
|
|
8814
|
-
}
|
|
8815
|
-
if (this.backend) {
|
|
8816
|
-
this.backend.resume();
|
|
8817
|
-
}
|
|
8818
|
-
}
|
|
8819
|
-
/**
|
|
8820
|
-
* 是否已启动
|
|
8821
|
-
*/
|
|
8822
|
-
isStarted() {
|
|
8823
|
-
return this._started;
|
|
8824
|
-
}
|
|
8825
|
-
/**
|
|
8826
|
-
* 是否暂停
|
|
8827
|
-
*/
|
|
8828
|
-
isPaused() {
|
|
8829
|
-
return this._paused;
|
|
8830
|
-
}
|
|
8831
|
-
/**
|
|
8832
|
-
* 是否已停止
|
|
8833
|
-
*/
|
|
8834
|
-
isStopped() {
|
|
8835
|
-
return this._stopped;
|
|
8836
|
-
}
|
|
8837
|
-
/**
|
|
8838
|
-
* 获取已写入的字节数
|
|
8839
|
-
*/
|
|
8840
|
-
getBytesWritten() {
|
|
8841
|
-
return this._bytesWritten;
|
|
8842
|
-
}
|
|
8843
|
-
/**
|
|
8844
|
-
* 处理错误
|
|
8845
|
-
*/
|
|
8846
|
-
handleError(error) {
|
|
8847
|
-
this.events?.onError?.(error);
|
|
8848
|
-
this.emit("error", error);
|
|
8849
|
-
}
|
|
8850
|
-
};
|
|
8851
|
-
|
|
8852
9269
|
// src/index.ts
|
|
8853
9270
|
var speaker;
|
|
8854
9271
|
var streamReader;
|
|
@@ -8982,20 +9399,12 @@ function getStreamStatus() {
|
|
|
8982
9399
|
state: streamReader.getState()
|
|
8983
9400
|
};
|
|
8984
9401
|
}
|
|
8985
|
-
function getStreamReader() {
|
|
8986
|
-
return streamReader;
|
|
8987
|
-
}
|
|
8988
|
-
function getStreamingSynthesizer() {
|
|
8989
|
-
return streamingSynthesizer;
|
|
8990
|
-
}
|
|
8991
|
-
function getStreamPlayer() {
|
|
8992
|
-
return streamPlayer;
|
|
8993
|
-
}
|
|
8994
9402
|
|
|
8995
9403
|
// src/config.ts
|
|
8996
9404
|
import * as fs2 from "fs";
|
|
8997
9405
|
import * as path from "path";
|
|
8998
9406
|
import * as os from "os";
|
|
9407
|
+
var logger6 = createModuleLogger("Config");
|
|
8999
9408
|
var DEFAULT_CONFIG = {
|
|
9000
9409
|
enabled: true,
|
|
9001
9410
|
autoPlay: false,
|
|
@@ -9094,11 +9503,12 @@ function loadOrCreateConfig() {
|
|
|
9094
9503
|
try {
|
|
9095
9504
|
fs2.mkdirSync(configDir, { recursive: true });
|
|
9096
9505
|
} catch (err) {
|
|
9506
|
+
logger6.error({ err }, "failed to create config directory");
|
|
9097
9507
|
throw new Error(`[ocosay] \u65E0\u6CD5\u521B\u5EFA\u914D\u7F6E\u76EE\u5F55 ${configDir}: ${err}`);
|
|
9098
9508
|
}
|
|
9099
9509
|
}
|
|
9100
9510
|
if (!fs2.existsSync(CONFIG_PATH)) {
|
|
9101
|
-
|
|
9511
|
+
logger6.info("config file not found, creating default config");
|
|
9102
9512
|
const defaultConfig = generateDefaultConfig();
|
|
9103
9513
|
const configContent = JSON.stringify(defaultConfig, null, 2);
|
|
9104
9514
|
try {
|
|
@@ -9106,13 +9516,14 @@ function loadOrCreateConfig() {
|
|
|
9106
9516
|
try {
|
|
9107
9517
|
fs2.chmodSync(CONFIG_PATH, 384);
|
|
9108
9518
|
} catch (err) {
|
|
9109
|
-
|
|
9519
|
+
logger6.warn({ err }, "failed to set config file permissions");
|
|
9110
9520
|
}
|
|
9111
9521
|
} catch (err) {
|
|
9522
|
+
logger6.error({ err }, "failed to write config file");
|
|
9112
9523
|
throw new Error(`[ocosay] cannot write config file ${CONFIG_PATH}: ${err}`);
|
|
9113
9524
|
}
|
|
9114
|
-
|
|
9115
|
-
|
|
9525
|
+
logger6.info({ path: CONFIG_PATH }, "config file created");
|
|
9526
|
+
logger6.info("please edit config file to add API Key and Base URL");
|
|
9116
9527
|
return defaultConfig;
|
|
9117
9528
|
}
|
|
9118
9529
|
try {
|
|
@@ -9134,7 +9545,7 @@ function loadOrCreateConfig() {
|
|
|
9134
9545
|
}
|
|
9135
9546
|
};
|
|
9136
9547
|
} catch (error) {
|
|
9137
|
-
|
|
9548
|
+
logger6.error({ error }, "config file read failed, using default config");
|
|
9138
9549
|
return generateDefaultConfig();
|
|
9139
9550
|
}
|
|
9140
9551
|
}
|
|
@@ -9143,6 +9554,7 @@ function loadOrCreateConfig() {
|
|
|
9143
9554
|
import { readFileSync as readFileSync2 } from "fs";
|
|
9144
9555
|
import { fileURLToPath } from "url";
|
|
9145
9556
|
import { dirname as dirname2, join as join7 } from "path";
|
|
9557
|
+
var logger7 = createModuleLogger("Plugin");
|
|
9146
9558
|
var __filename = fileURLToPath(import.meta.url);
|
|
9147
9559
|
var __dirname2 = dirname2(__filename);
|
|
9148
9560
|
var id = "ocosay";
|
|
@@ -9282,30 +9694,26 @@ var server = (async (input, _options) => {
|
|
|
9282
9694
|
});
|
|
9283
9695
|
} catch (err) {
|
|
9284
9696
|
initError = err instanceof Error ? err : new Error(String(err));
|
|
9285
|
-
|
|
9697
|
+
logger7.error({ error: initError }, "initialization failed");
|
|
9286
9698
|
}
|
|
9287
9699
|
const opencodeTui = input.client?.tui;
|
|
9288
9700
|
global.__opencode_tui__ = opencodeTui;
|
|
9289
|
-
|
|
9290
|
-
|
|
9701
|
+
notificationService.setTui(opencodeTui);
|
|
9702
|
+
setTimeout(() => {
|
|
9291
9703
|
if (initError) {
|
|
9292
|
-
|
|
9293
|
-
|
|
9294
|
-
|
|
9295
|
-
|
|
9296
|
-
|
|
9297
|
-
}
|
|
9298
|
-
});
|
|
9704
|
+
notificationService.error(
|
|
9705
|
+
`Ocosay v${pluginVersion} Init Failed`,
|
|
9706
|
+
"Please check your config file",
|
|
9707
|
+
8e3
|
|
9708
|
+
);
|
|
9299
9709
|
} else {
|
|
9300
|
-
|
|
9301
|
-
|
|
9302
|
-
|
|
9303
|
-
|
|
9304
|
-
|
|
9305
|
-
}
|
|
9306
|
-
});
|
|
9710
|
+
notificationService.success(
|
|
9711
|
+
`Ocosay v${pluginVersion} Ready`,
|
|
9712
|
+
`Auto-read: ${config.autoRead ? "ON" : "OFF"}`,
|
|
9713
|
+
5e3
|
|
9714
|
+
);
|
|
9307
9715
|
}
|
|
9308
|
-
},
|
|
9716
|
+
}, 1500);
|
|
9309
9717
|
return {
|
|
9310
9718
|
tool: {
|
|
9311
9719
|
tts_speak: ttsSpeakTool,
|
|
@@ -9338,15 +9746,11 @@ var server = (async (input, _options) => {
|
|
|
9338
9746
|
});
|
|
9339
9747
|
initError = null;
|
|
9340
9748
|
} catch (err) {
|
|
9341
|
-
|
|
9342
|
-
|
|
9343
|
-
|
|
9344
|
-
|
|
9345
|
-
|
|
9346
|
-
variant: "error"
|
|
9347
|
-
}
|
|
9348
|
-
});
|
|
9349
|
-
}
|
|
9749
|
+
notificationService.error(
|
|
9750
|
+
`Ocosay v${pluginVersion} Init Failed`,
|
|
9751
|
+
"Initialization failed, please check config",
|
|
9752
|
+
8e3
|
|
9753
|
+
);
|
|
9350
9754
|
}
|
|
9351
9755
|
}
|
|
9352
9756
|
}
|