@ai-react-markdown/engine 2.9.1 → 2.10.0
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/index.cjs +42 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +68 -36
- package/dist/index.d.ts +68 -36
- package/dist/index.dev.cjs +42 -26
- package/dist/index.dev.cjs.map +1 -1
- package/dist/index.dev.js +42 -26
- package/dist/index.dev.js.map +1 -1
- package/dist/index.js +42 -26
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -1498,22 +1498,29 @@ declare const sanitizeSchema: Schema;
|
|
|
1498
1498
|
* exactly the incremental-parse engine's fast path — the controller sits
|
|
1499
1499
|
* upstream of the renderer and never touches the parse pipeline.
|
|
1500
1500
|
*
|
|
1501
|
-
* Pacing model —
|
|
1502
|
-
*
|
|
1503
|
-
*
|
|
1504
|
-
*
|
|
1505
|
-
*
|
|
1506
|
-
*
|
|
1507
|
-
*
|
|
1508
|
-
*
|
|
1509
|
-
*
|
|
1510
|
-
*
|
|
1511
|
-
*
|
|
1512
|
-
*
|
|
1513
|
-
*
|
|
1501
|
+
* Pacing model — a completion-deadline law over a gap-quantile estimator
|
|
1502
|
+
* (v2.10 redesign; the prior water-level jitter buffer's rationale and the
|
|
1503
|
+
* falsified alternatives live in the archived design plan):
|
|
1504
|
+
* - Every inter-arrival gap enters a small sliding window — there is NO
|
|
1505
|
+
* pause classifier. The target interval Î is a high quantile of that
|
|
1506
|
+
* window: two slow-gap confirmations flip the controller into a slower
|
|
1507
|
+
* mode, while leaving it takes the window turning over ("cautious
|
|
1508
|
+
* fast, aggressive slow").
|
|
1509
|
+
* - Streaming: everything on hand should be on screen by the time the
|
|
1510
|
+
* next lump is expected. The horizon H = clamp(bufferFactor × Î + pad,
|
|
1511
|
+
* 16, maxLagMs) stamps a deadline at the last arrival + H, and
|
|
1512
|
+
* rate = backlog / time-to-deadline — constant within a period, so a
|
|
1513
|
+
* coarse feed reads as an even typewriter, not pour-then-crawl. The
|
|
1514
|
+
* floor is a tiny anti-freeze trickle. `maxLagMs` is the preset's
|
|
1515
|
+
* max-lag promise AND the pause handler: a gap beyond it saturates H
|
|
1516
|
+
* and cannot change any further decision.
|
|
1517
|
+
* - Pre-stats (first lump after construction/snap — no gap sample yet):
|
|
1518
|
+
* the backlog reveals over roughly one correction window.
|
|
1514
1519
|
* - Finished: rate = backlog / time-to-deadline, deadline stamped at
|
|
1515
|
-
* `finish() +
|
|
1516
|
-
*
|
|
1520
|
+
* `finish()` + a rate-continuity window — the tail reveals at most
|
|
1521
|
+
* ~2× the stream's measured throughput, clamped to [drainMs, 3×drainMs]
|
|
1522
|
+
* — so the backlog empties BY the deadline without an end-of-message
|
|
1523
|
+
* pour.
|
|
1517
1524
|
* - A deadline credit accumulator converts elapsed time (injectable
|
|
1518
1525
|
* `now()`) into whole-grapheme reveals per scheduled frame — timers
|
|
1519
1526
|
* carry no state between frames, so throttled/paused schedulers
|
|
@@ -1538,39 +1545,63 @@ declare const sanitizeSchema: Schema;
|
|
|
1538
1545
|
* latency-vs-smoothness axis (the audio-plugin buffer-preset convention —
|
|
1539
1546
|
* perceptual parameters resist meaningful numeric tuning).
|
|
1540
1547
|
*
|
|
1541
|
-
* - `'smooth'` —
|
|
1542
|
-
* between server flushes,
|
|
1543
|
-
* - `'balanced'` (default) — ~1
|
|
1544
|
-
*
|
|
1545
|
-
* - `'responsive'` —
|
|
1546
|
-
* visible
|
|
1548
|
+
* - `'smooth'` — ~1.7 delivery intervals of runway (max lag 3.5s): extra
|
|
1549
|
+
* slack between server flushes, the most delivery coarseness absorbed.
|
|
1550
|
+
* - `'balanced'` (default) — ~1 interval of runway (max lag 2.5s): even
|
|
1551
|
+
* pacing for delivery intervals up to ~2.5s at minimal lag.
|
|
1552
|
+
* - `'responsive'` — ~0.45 of an interval (max lag 0.8s): lowest lag,
|
|
1553
|
+
* accepts visible pauses on coarse or bursty delivery.
|
|
1547
1554
|
*/
|
|
1548
1555
|
type SmoothStreamPacing = 'smooth' | 'balanced' | 'responsive';
|
|
1549
1556
|
/** The numeric parameter bundle a {@link SmoothStreamPacing} preset names. */
|
|
1550
1557
|
interface SmoothStreamPacingParams {
|
|
1551
|
-
/**
|
|
1558
|
+
/**
|
|
1559
|
+
* Horizon multiple — "periods of runway": the reveal deadline sits this
|
|
1560
|
+
* many expected delivery intervals after the last arrival. 1.0 means
|
|
1561
|
+
* everything on hand is on screen just as the next chunk is expected.
|
|
1562
|
+
*/
|
|
1552
1563
|
bufferFactor: number;
|
|
1553
1564
|
/**
|
|
1554
|
-
*
|
|
1555
|
-
*
|
|
1556
|
-
*
|
|
1565
|
+
* Pre-stats reveal window (ms) for the FIRST lump of a stream, before
|
|
1566
|
+
* any inter-arrival sample exists. The streaming path no longer reads
|
|
1567
|
+
* it — the v2.10 deadline law replaced the old feedback term it used to
|
|
1568
|
+
* time-constant.
|
|
1557
1569
|
*/
|
|
1558
1570
|
correctionTauMs: number;
|
|
1559
|
-
/**
|
|
1571
|
+
/**
|
|
1572
|
+
* @deprecated Read by nothing since the v2.10 deadline-law redesign (it
|
|
1573
|
+
* used to be the EMA horizon AND, harmfully, the pause-classifier
|
|
1574
|
+
* threshold — the "1.8s cliff"). Kept in the preset objects so their
|
|
1575
|
+
* exported shape is unchanged; setting it has no effect.
|
|
1576
|
+
*/
|
|
1560
1577
|
emaTauMs: number;
|
|
1578
|
+
/**
|
|
1579
|
+
* The preset's max-lag promise (ms): the reveal DEADLINE never targets
|
|
1580
|
+
* more than this far behind the live source (a throttled scheduler can
|
|
1581
|
+
* transiently exceed it; the next tick self-corrects). It is also the
|
|
1582
|
+
* whole pause story —
|
|
1583
|
+
* a gap longer than `maxLagMs / bufferFactor` saturates the horizon and
|
|
1584
|
+
* cannot change any further decision. Pay-per-use: a fine-grained
|
|
1585
|
+
* stream's horizon tracks its own (small) cadence and never approaches
|
|
1586
|
+
* this cap. Full smoothing of a coarse feed requires
|
|
1587
|
+
* delivery-interval ≤ maxLagMs (bufferFactor ≥ 1 presets); steady mean
|
|
1588
|
+
* lag there is about half the delivery period.
|
|
1589
|
+
*/
|
|
1590
|
+
maxLagMs?: number;
|
|
1561
1591
|
/**
|
|
1562
1592
|
* Anti-freeze floor (grapheme clusters/s). Deliberately tiny — smaller
|
|
1563
|
-
* than any realistic arrival rate —
|
|
1564
|
-
*
|
|
1565
|
-
* freezing visible progress entirely.
|
|
1593
|
+
* than any realistic arrival rate — a last-resort trickle so visible
|
|
1594
|
+
* progress never freezes entirely while anything is pending.
|
|
1566
1595
|
*/
|
|
1567
1596
|
minCharsPerSecond: number;
|
|
1568
1597
|
/**
|
|
1569
|
-
*
|
|
1570
|
-
* deadline is stamped at `finish()
|
|
1571
|
-
*
|
|
1572
|
-
*
|
|
1573
|
-
*
|
|
1598
|
+
* Drain-budget FLOOR after {@link SmoothStreamController.finish}: the
|
|
1599
|
+
* drain deadline is stamped at `finish()` plus a rate-continuity window
|
|
1600
|
+
* — enough time that the tail reveals at ~2× the stream's measured
|
|
1601
|
+
* throughput — clamped to `[drainMs, 3 × drainMs]`. Short backlogs
|
|
1602
|
+
* behave exactly as the pre-v2.10 fixed window did. Consumed when the
|
|
1603
|
+
* deadline is stamped — changing it affects the next drain, not one in
|
|
1604
|
+
* progress.
|
|
1574
1605
|
*/
|
|
1575
1606
|
drainMs: number;
|
|
1576
1607
|
}
|
|
@@ -1609,8 +1640,9 @@ interface SmoothStreamController {
|
|
|
1609
1640
|
update(source: string): void;
|
|
1610
1641
|
/**
|
|
1611
1642
|
* Signals end of stream: confirms the held-back trailing grapheme and
|
|
1612
|
-
* switches the control law to the
|
|
1613
|
-
* a later {@link update} resumes
|
|
1643
|
+
* switches the control law to the rate-continuity drain window (floored
|
|
1644
|
+
* at `drainMs`). Not terminal — a later {@link update} resumes
|
|
1645
|
+
* animation.
|
|
1614
1646
|
*/
|
|
1615
1647
|
finish(): void;
|
|
1616
1648
|
/** Jumps to `source` instantly, no animation, and clears any backlog.
|
package/dist/index.d.ts
CHANGED
|
@@ -1498,22 +1498,29 @@ declare const sanitizeSchema: Schema;
|
|
|
1498
1498
|
* exactly the incremental-parse engine's fast path — the controller sits
|
|
1499
1499
|
* upstream of the renderer and never touches the parse pipeline.
|
|
1500
1500
|
*
|
|
1501
|
-
* Pacing model —
|
|
1502
|
-
*
|
|
1503
|
-
*
|
|
1504
|
-
*
|
|
1505
|
-
*
|
|
1506
|
-
*
|
|
1507
|
-
*
|
|
1508
|
-
*
|
|
1509
|
-
*
|
|
1510
|
-
*
|
|
1511
|
-
*
|
|
1512
|
-
*
|
|
1513
|
-
*
|
|
1501
|
+
* Pacing model — a completion-deadline law over a gap-quantile estimator
|
|
1502
|
+
* (v2.10 redesign; the prior water-level jitter buffer's rationale and the
|
|
1503
|
+
* falsified alternatives live in the archived design plan):
|
|
1504
|
+
* - Every inter-arrival gap enters a small sliding window — there is NO
|
|
1505
|
+
* pause classifier. The target interval Î is a high quantile of that
|
|
1506
|
+
* window: two slow-gap confirmations flip the controller into a slower
|
|
1507
|
+
* mode, while leaving it takes the window turning over ("cautious
|
|
1508
|
+
* fast, aggressive slow").
|
|
1509
|
+
* - Streaming: everything on hand should be on screen by the time the
|
|
1510
|
+
* next lump is expected. The horizon H = clamp(bufferFactor × Î + pad,
|
|
1511
|
+
* 16, maxLagMs) stamps a deadline at the last arrival + H, and
|
|
1512
|
+
* rate = backlog / time-to-deadline — constant within a period, so a
|
|
1513
|
+
* coarse feed reads as an even typewriter, not pour-then-crawl. The
|
|
1514
|
+
* floor is a tiny anti-freeze trickle. `maxLagMs` is the preset's
|
|
1515
|
+
* max-lag promise AND the pause handler: a gap beyond it saturates H
|
|
1516
|
+
* and cannot change any further decision.
|
|
1517
|
+
* - Pre-stats (first lump after construction/snap — no gap sample yet):
|
|
1518
|
+
* the backlog reveals over roughly one correction window.
|
|
1514
1519
|
* - Finished: rate = backlog / time-to-deadline, deadline stamped at
|
|
1515
|
-
* `finish() +
|
|
1516
|
-
*
|
|
1520
|
+
* `finish()` + a rate-continuity window — the tail reveals at most
|
|
1521
|
+
* ~2× the stream's measured throughput, clamped to [drainMs, 3×drainMs]
|
|
1522
|
+
* — so the backlog empties BY the deadline without an end-of-message
|
|
1523
|
+
* pour.
|
|
1517
1524
|
* - A deadline credit accumulator converts elapsed time (injectable
|
|
1518
1525
|
* `now()`) into whole-grapheme reveals per scheduled frame — timers
|
|
1519
1526
|
* carry no state between frames, so throttled/paused schedulers
|
|
@@ -1538,39 +1545,63 @@ declare const sanitizeSchema: Schema;
|
|
|
1538
1545
|
* latency-vs-smoothness axis (the audio-plugin buffer-preset convention —
|
|
1539
1546
|
* perceptual parameters resist meaningful numeric tuning).
|
|
1540
1547
|
*
|
|
1541
|
-
* - `'smooth'` —
|
|
1542
|
-
* between server flushes,
|
|
1543
|
-
* - `'balanced'` (default) — ~1
|
|
1544
|
-
*
|
|
1545
|
-
* - `'responsive'` —
|
|
1546
|
-
* visible
|
|
1548
|
+
* - `'smooth'` — ~1.7 delivery intervals of runway (max lag 3.5s): extra
|
|
1549
|
+
* slack between server flushes, the most delivery coarseness absorbed.
|
|
1550
|
+
* - `'balanced'` (default) — ~1 interval of runway (max lag 2.5s): even
|
|
1551
|
+
* pacing for delivery intervals up to ~2.5s at minimal lag.
|
|
1552
|
+
* - `'responsive'` — ~0.45 of an interval (max lag 0.8s): lowest lag,
|
|
1553
|
+
* accepts visible pauses on coarse or bursty delivery.
|
|
1547
1554
|
*/
|
|
1548
1555
|
type SmoothStreamPacing = 'smooth' | 'balanced' | 'responsive';
|
|
1549
1556
|
/** The numeric parameter bundle a {@link SmoothStreamPacing} preset names. */
|
|
1550
1557
|
interface SmoothStreamPacingParams {
|
|
1551
|
-
/**
|
|
1558
|
+
/**
|
|
1559
|
+
* Horizon multiple — "periods of runway": the reveal deadline sits this
|
|
1560
|
+
* many expected delivery intervals after the last arrival. 1.0 means
|
|
1561
|
+
* everything on hand is on screen just as the next chunk is expected.
|
|
1562
|
+
*/
|
|
1552
1563
|
bufferFactor: number;
|
|
1553
1564
|
/**
|
|
1554
|
-
*
|
|
1555
|
-
*
|
|
1556
|
-
*
|
|
1565
|
+
* Pre-stats reveal window (ms) for the FIRST lump of a stream, before
|
|
1566
|
+
* any inter-arrival sample exists. The streaming path no longer reads
|
|
1567
|
+
* it — the v2.10 deadline law replaced the old feedback term it used to
|
|
1568
|
+
* time-constant.
|
|
1557
1569
|
*/
|
|
1558
1570
|
correctionTauMs: number;
|
|
1559
|
-
/**
|
|
1571
|
+
/**
|
|
1572
|
+
* @deprecated Read by nothing since the v2.10 deadline-law redesign (it
|
|
1573
|
+
* used to be the EMA horizon AND, harmfully, the pause-classifier
|
|
1574
|
+
* threshold — the "1.8s cliff"). Kept in the preset objects so their
|
|
1575
|
+
* exported shape is unchanged; setting it has no effect.
|
|
1576
|
+
*/
|
|
1560
1577
|
emaTauMs: number;
|
|
1578
|
+
/**
|
|
1579
|
+
* The preset's max-lag promise (ms): the reveal DEADLINE never targets
|
|
1580
|
+
* more than this far behind the live source (a throttled scheduler can
|
|
1581
|
+
* transiently exceed it; the next tick self-corrects). It is also the
|
|
1582
|
+
* whole pause story —
|
|
1583
|
+
* a gap longer than `maxLagMs / bufferFactor` saturates the horizon and
|
|
1584
|
+
* cannot change any further decision. Pay-per-use: a fine-grained
|
|
1585
|
+
* stream's horizon tracks its own (small) cadence and never approaches
|
|
1586
|
+
* this cap. Full smoothing of a coarse feed requires
|
|
1587
|
+
* delivery-interval ≤ maxLagMs (bufferFactor ≥ 1 presets); steady mean
|
|
1588
|
+
* lag there is about half the delivery period.
|
|
1589
|
+
*/
|
|
1590
|
+
maxLagMs?: number;
|
|
1561
1591
|
/**
|
|
1562
1592
|
* Anti-freeze floor (grapheme clusters/s). Deliberately tiny — smaller
|
|
1563
|
-
* than any realistic arrival rate —
|
|
1564
|
-
*
|
|
1565
|
-
* freezing visible progress entirely.
|
|
1593
|
+
* than any realistic arrival rate — a last-resort trickle so visible
|
|
1594
|
+
* progress never freezes entirely while anything is pending.
|
|
1566
1595
|
*/
|
|
1567
1596
|
minCharsPerSecond: number;
|
|
1568
1597
|
/**
|
|
1569
|
-
*
|
|
1570
|
-
* deadline is stamped at `finish()
|
|
1571
|
-
*
|
|
1572
|
-
*
|
|
1573
|
-
*
|
|
1598
|
+
* Drain-budget FLOOR after {@link SmoothStreamController.finish}: the
|
|
1599
|
+
* drain deadline is stamped at `finish()` plus a rate-continuity window
|
|
1600
|
+
* — enough time that the tail reveals at ~2× the stream's measured
|
|
1601
|
+
* throughput — clamped to `[drainMs, 3 × drainMs]`. Short backlogs
|
|
1602
|
+
* behave exactly as the pre-v2.10 fixed window did. Consumed when the
|
|
1603
|
+
* deadline is stamped — changing it affects the next drain, not one in
|
|
1604
|
+
* progress.
|
|
1574
1605
|
*/
|
|
1575
1606
|
drainMs: number;
|
|
1576
1607
|
}
|
|
@@ -1609,8 +1640,9 @@ interface SmoothStreamController {
|
|
|
1609
1640
|
update(source: string): void;
|
|
1610
1641
|
/**
|
|
1611
1642
|
* Signals end of stream: confirms the held-back trailing grapheme and
|
|
1612
|
-
* switches the control law to the
|
|
1613
|
-
* a later {@link update} resumes
|
|
1643
|
+
* switches the control law to the rate-continuity drain window (floored
|
|
1644
|
+
* at `drainMs`). Not terminal — a later {@link update} resumes
|
|
1645
|
+
* animation.
|
|
1614
1646
|
*/
|
|
1615
1647
|
finish(): void;
|
|
1616
1648
|
/** Jumps to `source` instantly, no animation, and clears any backlog.
|
package/dist/index.dev.cjs
CHANGED
|
@@ -4443,24 +4443,32 @@ var SMOOTH_STREAM_PACING_PRESETS = Object.freeze({
|
|
|
4443
4443
|
correctionTauMs: 280,
|
|
4444
4444
|
emaTauMs: 2600,
|
|
4445
4445
|
minCharsPerSecond: 4,
|
|
4446
|
-
drainMs: 320
|
|
4446
|
+
drainMs: 320,
|
|
4447
|
+
maxLagMs: 3500
|
|
4447
4448
|
}),
|
|
4448
4449
|
balanced: Object.freeze({
|
|
4449
4450
|
bufferFactor: 1,
|
|
4450
4451
|
correctionTauMs: 180,
|
|
4451
4452
|
emaTauMs: 1800,
|
|
4452
4453
|
minCharsPerSecond: 6,
|
|
4453
|
-
drainMs: 240
|
|
4454
|
+
drainMs: 240,
|
|
4455
|
+
maxLagMs: 2500
|
|
4454
4456
|
}),
|
|
4455
4457
|
responsive: Object.freeze({
|
|
4456
4458
|
bufferFactor: 0.45,
|
|
4457
4459
|
correctionTauMs: 110,
|
|
4458
4460
|
emaTauMs: 1100,
|
|
4459
4461
|
minCharsPerSecond: 10,
|
|
4460
|
-
drainMs: 150
|
|
4462
|
+
drainMs: 150,
|
|
4463
|
+
maxLagMs: 800
|
|
4461
4464
|
})
|
|
4462
4465
|
});
|
|
4463
|
-
var
|
|
4466
|
+
var GAP_WINDOW = 16;
|
|
4467
|
+
var INTERVAL_QUANTILE = 0.9;
|
|
4468
|
+
var HORIZON_PAD_MS = 50;
|
|
4469
|
+
var DEADLINE_FLOOR_MS = 33;
|
|
4470
|
+
var DRAIN_CATCHUP_FACTOR = 2;
|
|
4471
|
+
var DRAIN_MAX_FACTOR = 3;
|
|
4464
4472
|
var defaultNow = typeof performance !== "undefined" && typeof performance.now === "function" ? () => performance.now() : () => Date.now();
|
|
4465
4473
|
var defaultSchedule = (cb) => {
|
|
4466
4474
|
if (typeof requestAnimationFrame === "function") {
|
|
@@ -4511,18 +4519,18 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4511
4519
|
let lastTickAt = 0;
|
|
4512
4520
|
let cancelFrame;
|
|
4513
4521
|
let disposed = false;
|
|
4514
|
-
let
|
|
4515
|
-
let intervalEma;
|
|
4522
|
+
let gapWindow = [];
|
|
4516
4523
|
let lastArrivalAt;
|
|
4517
4524
|
const listeners = /* @__PURE__ */ new Set();
|
|
4518
4525
|
const resolveParams = () => {
|
|
4519
|
-
const preset = SMOOTH_STREAM_PACING_PRESETS[options.pacing]
|
|
4526
|
+
const preset = Object.hasOwn(SMOOTH_STREAM_PACING_PRESETS, options.pacing) ? SMOOTH_STREAM_PACING_PRESETS[options.pacing] : SMOOTH_STREAM_PACING_PRESETS.balanced;
|
|
4520
4527
|
return {
|
|
4521
4528
|
bufferFactor: finiteOr(options.bufferFactor, preset.bufferFactor),
|
|
4522
4529
|
correctionTauMs: finiteOr(options.correctionTauMs, preset.correctionTauMs),
|
|
4523
4530
|
emaTauMs: finiteOr(options.emaTauMs, preset.emaTauMs),
|
|
4524
4531
|
minCharsPerSecond: finiteOr(options.minCharsPerSecond, preset.minCharsPerSecond),
|
|
4525
|
-
drainMs: finiteOr(options.drainMs, preset.drainMs)
|
|
4532
|
+
drainMs: finiteOr(options.drainMs, preset.drainMs),
|
|
4533
|
+
maxLagMs: finiteOr(options.maxLagMs, preset.maxLagMs ?? 2500)
|
|
4526
4534
|
};
|
|
4527
4535
|
};
|
|
4528
4536
|
const recordArrival = (t, added) => {
|
|
@@ -4533,12 +4541,8 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4533
4541
|
}
|
|
4534
4542
|
const gap = Math.max(1, t - lastArrivalAt);
|
|
4535
4543
|
lastArrivalAt = t;
|
|
4536
|
-
|
|
4537
|
-
if (
|
|
4538
|
-
const alpha = 1 - Math.exp(-gap / tau);
|
|
4539
|
-
const instantRate = added * 1e3 / gap;
|
|
4540
|
-
rateEma = (rateEma ?? 0) + alpha * (instantRate - (rateEma ?? 0));
|
|
4541
|
-
intervalEma = (intervalEma ?? 0) + alpha * (gap - (intervalEma ?? 0));
|
|
4544
|
+
gapWindow.push({ gap, added });
|
|
4545
|
+
if (gapWindow.length > GAP_WINDOW) gapWindow.shift();
|
|
4542
4546
|
};
|
|
4543
4547
|
const notify = () => {
|
|
4544
4548
|
visibleCache = source.slice(0, visibleEnd);
|
|
@@ -4564,15 +4568,12 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4564
4568
|
let rate;
|
|
4565
4569
|
if (finished && drainDeadlineAt !== void 0) {
|
|
4566
4570
|
rate = Math.max(params.minCharsPerSecond, pending.length * 1e3 / Math.max(1, drainDeadlineAt - t));
|
|
4567
|
-
} else if (
|
|
4568
|
-
const
|
|
4569
|
-
|
|
4570
|
-
|
|
4571
|
-
);
|
|
4572
|
-
rate = Math.max(
|
|
4573
|
-
params.minCharsPerSecond,
|
|
4574
|
-
rateEma + (pending.length - targetBuffer) * 1e3 / Math.max(1, params.correctionTauMs)
|
|
4575
|
-
);
|
|
4571
|
+
} else if (gapWindow.length > 0 && lastArrivalAt !== void 0) {
|
|
4572
|
+
const gaps = gapWindow.map((s) => s.gap).sort((a, b) => a - b);
|
|
4573
|
+
const intervalQ = gaps[Math.min(gaps.length - 1, Math.floor(gaps.length * INTERVAL_QUANTILE))];
|
|
4574
|
+
const horizon = Math.max(16, Math.min(params.bufferFactor * intervalQ + HORIZON_PAD_MS, params.maxLagMs));
|
|
4575
|
+
const deadline = Math.max(lastArrivalAt + horizon, t + DEADLINE_FLOOR_MS);
|
|
4576
|
+
rate = Math.max(params.minCharsPerSecond, pending.length * 1e3 / Math.max(1, deadline - t));
|
|
4576
4577
|
} else {
|
|
4577
4578
|
rate = Math.max(params.minCharsPerSecond, pending.length * 1e3 / Math.max(1, params.correctionTauMs));
|
|
4578
4579
|
}
|
|
@@ -4618,8 +4619,7 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4618
4619
|
initialized = true;
|
|
4619
4620
|
finished = false;
|
|
4620
4621
|
drainDeadlineAt = void 0;
|
|
4621
|
-
|
|
4622
|
-
intervalEma = void 0;
|
|
4622
|
+
gapWindow = [];
|
|
4623
4623
|
lastArrivalAt = void 0;
|
|
4624
4624
|
source = next;
|
|
4625
4625
|
visibleEnd = next.length;
|
|
@@ -4656,10 +4656,26 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4656
4656
|
if (finished) return;
|
|
4657
4657
|
finished = true;
|
|
4658
4658
|
lastArrivalAt = void 0;
|
|
4659
|
-
drainDeadlineAt = now() + resolveParams().drainMs;
|
|
4660
4659
|
if (tentativeEnd > (pending.length > 0 ? pending[pending.length - 1] : visibleEnd)) {
|
|
4661
4660
|
pending.push(tentativeEnd);
|
|
4662
4661
|
}
|
|
4662
|
+
const params = resolveParams();
|
|
4663
|
+
let drainWin = params.drainMs;
|
|
4664
|
+
let chars = 0;
|
|
4665
|
+
let ms = 0;
|
|
4666
|
+
for (let i = 0; i < gapWindow.length - 1; i += 1) {
|
|
4667
|
+
chars += gapWindow[i].added;
|
|
4668
|
+
ms += gapWindow[i].gap;
|
|
4669
|
+
}
|
|
4670
|
+
const backlog = source.length - visibleEnd;
|
|
4671
|
+
if (chars > 0 && ms > 0 && backlog > 0) {
|
|
4672
|
+
const throughput = chars * 1e3 / ms;
|
|
4673
|
+
drainWin = Math.min(
|
|
4674
|
+
Math.max(backlog * 1e3 / (DRAIN_CATCHUP_FACTOR * throughput), params.drainMs),
|
|
4675
|
+
DRAIN_MAX_FACTOR * params.drainMs
|
|
4676
|
+
);
|
|
4677
|
+
}
|
|
4678
|
+
drainDeadlineAt = now() + drainWin;
|
|
4663
4679
|
seam = source.length;
|
|
4664
4680
|
ensureScheduled();
|
|
4665
4681
|
},
|