mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-12 01:37:06 +02:00
Trois défauts sans rapport entre eux, tous visibles à l'écran. Jauge de contexte bloquée à « 0 / N (0 %) » : le comptage exact vient de usage.prompt_tokens (include_usage), qu'un llama-server récent a cessé de renvoyer. On note désormais si l'usage est arrivé ; sinon la fin de tour publie l'estimation qui pilote déjà la compaction — approximative, mais jamais absente. Et la souscription envoie la valeur courante juste après le rattrapage : une page rechargée affichait zéro sur une discussion pourtant pleine, faute d'événement ctx_used dans la fenêtre rejouée. Espace disque : « il ne reste que 11,9 Go » sur un partage Unraid qui en a des centaines. /mnt/user est servi par shfs, un FUSE qui agrège plusieurs disques — statfs y renvoie l'espace d'un seul, et ce chiffre REFUSAIT l'installation du modèle. Les systèmes de fichiers qui approximent (FUSE, overlay, NFS, CIFS, Ceph, Gluster) sont reconnus par leur magie : leur chiffre reste affiché, précédé d'un « ~ », mais ne bloque plus rien. Panneau Fichiers : le panneau entier défilait, emportant vers le haut l'en-tête, le fil d'Ariane et le pied (occupation disque, bouton .zip) dès qu'il y avait quelques fichiers. Seule la liste défile maintenant ; le pied reste en bas et l'état vide se centre. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
256 lines
7.6 KiB
JavaScript
256 lines
7.6 KiB
JavaScript
/**
|
||
* @import {Encoding, Value} from 'micromark-util-types'
|
||
*/
|
||
|
||
/**
|
||
* @typedef {import('micromark-util-types').Options} Options
|
||
*/
|
||
|
||
/**
|
||
* @callback Callback
|
||
* Function called when write was successful.
|
||
* @returns {undefined}
|
||
* Nothing.
|
||
*
|
||
* @typedef PipeOptions
|
||
* Configuration for piping.
|
||
* @property {boolean | null | undefined} [end]
|
||
* Whether to end the destination stream when the source stream ends.
|
||
*
|
||
* @typedef {Omit<NodeJS.ReadableStream & NodeJS.WritableStream, 'isPaused' | 'pause' | 'read' | 'resume' | 'setEncoding' | 'unpipe' | 'unshift' | 'wrap'>} MinimalDuplex
|
||
* Duplex stream.
|
||
*/
|
||
|
||
import { EventEmitter } from 'node:events';
|
||
import { compile } from './lib/compile.js';
|
||
import { parse } from './lib/parse.js';
|
||
import { postprocess } from './lib/postprocess.js';
|
||
import { preprocess } from './lib/preprocess.js';
|
||
|
||
/**
|
||
* Create a duplex (readable and writable) stream.
|
||
*
|
||
* Some of the work to parse markdown can be done streaming, but in the
|
||
* end buffering is required.
|
||
*
|
||
* micromark does not handle errors for you, so you must handle errors on whatever
|
||
* streams you pipe into it.
|
||
* As markdown does not know errors, `micromark` itself does not emit errors.
|
||
*
|
||
* @param {Options | null | undefined} [options]
|
||
* Configuration (optional).
|
||
* @returns {MinimalDuplex}
|
||
* Duplex stream.
|
||
*/
|
||
export function stream(options) {
|
||
const prep = preprocess();
|
||
const tokenize = parse(options).document().write;
|
||
const comp = compile(options);
|
||
/** @type {boolean} */
|
||
let ended;
|
||
const emitter = /** @type {MinimalDuplex} */new EventEmitter();
|
||
// @ts-expect-error: fine.
|
||
emitter.end = end;
|
||
emitter.pipe = pipe;
|
||
emitter.readable = true;
|
||
emitter.writable = true;
|
||
// @ts-expect-error: fine.
|
||
emitter.write = write;
|
||
return emitter;
|
||
|
||
/**
|
||
* Write a chunk into memory.
|
||
*
|
||
* @overload
|
||
* @param {Value | null | undefined} [chunk]
|
||
* Slice of markdown to parse (`string` or `Uint8Array`).
|
||
* @param {Encoding | null | undefined} [encoding]
|
||
* Character encoding to understand `chunk` as when it’s a `Uint8Array`
|
||
* (`string`, default: `'utf8'`).
|
||
* @param {Callback | null | undefined} [callback]
|
||
* Function called when write was successful.
|
||
* @returns {boolean}
|
||
* Whether write was successful.
|
||
*
|
||
* @overload
|
||
* @param {Value | null | undefined} [chunk]
|
||
* Slice of markdown to parse (`string` or `Uint8Array`).
|
||
* @param {Callback | null | undefined} [callback]
|
||
* Function called when write was successful.
|
||
* @returns {boolean}
|
||
* Whether write was successful.
|
||
*
|
||
* @param {Value | null | undefined} [chunk]
|
||
* Slice of markdown to parse (`string` or `Uint8Array`).
|
||
* @param {Callback | Encoding | null | undefined} [encoding]
|
||
* Character encoding to understand `chunk` as when it’s a `Uint8Array`
|
||
* (`string`, default: `'utf8'`).
|
||
* @param {Callback | null | undefined} [callback]
|
||
* Function called when write was successful.
|
||
* @returns {boolean}
|
||
* Whether write was successful.
|
||
*/
|
||
function write(chunk, encoding, callback) {
|
||
if (typeof encoding === 'function') {
|
||
callback = encoding;
|
||
encoding = undefined;
|
||
}
|
||
if (ended) {
|
||
throw new Error('Did not expect `write` after `end`');
|
||
}
|
||
tokenize(prep(chunk || '', encoding));
|
||
if (callback) {
|
||
callback();
|
||
}
|
||
|
||
// Signal successful write.
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* End the writing.
|
||
*
|
||
* Passes all arguments as a final `write`.
|
||
*
|
||
* @overload
|
||
* @param {Value | null | undefined} [chunk]
|
||
* Slice of markdown to parse (`string` or `Uint8Array`).
|
||
* @param {Encoding | null | undefined} [encoding]
|
||
* Character encoding to understand `chunk` as when it’s a `Uint8Array`
|
||
* (`string`, default: `'utf8'`).
|
||
* @param {Callback | null | undefined} [callback]
|
||
* Function called when write was successful.
|
||
* @returns {boolean}
|
||
* Whether write was successful.
|
||
*
|
||
* @overload
|
||
* @param {Value | null | undefined} [chunk]
|
||
* Slice of markdown to parse (`string` or `Uint8Array`).
|
||
* @param {Callback | null | undefined} [callback]
|
||
* Function called when write was successful.
|
||
* @returns {boolean}
|
||
* Whether write was successful.
|
||
*
|
||
* @overload
|
||
* @param {Callback | null | undefined} [callback]
|
||
* Function called when write was successful.
|
||
* @returns {boolean}
|
||
* Whether write was successful.
|
||
*
|
||
* @param {Callback | Value | null | undefined} [chunk]
|
||
* Slice of markdown to parse (`string` or `Uint8Array`).
|
||
* @param {Callback | Encoding | null | undefined} [encoding]
|
||
* Character encoding to understand `chunk` as when it’s a `Uint8Array`
|
||
* (`string`, default: `'utf8'`).
|
||
* @param {Callback | null | undefined} [callback]
|
||
* Function called when write was successful.
|
||
* @returns {boolean}
|
||
* Whether write was successful.
|
||
*/
|
||
function end(chunk, encoding, callback) {
|
||
if (typeof chunk === 'function') {
|
||
encoding = chunk;
|
||
chunk = undefined;
|
||
}
|
||
if (typeof encoding === 'function') {
|
||
callback = encoding;
|
||
encoding = undefined;
|
||
}
|
||
write(chunk, encoding, callback);
|
||
emitter.emit('data', comp(postprocess(tokenize(prep('', encoding, true)))));
|
||
emitter.emit('end');
|
||
ended = true;
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* Pipe the processor into a writable stream.
|
||
*
|
||
* Basically `Stream#pipe`, but inlined and simplified to keep the bundled
|
||
* size down.
|
||
* See: <https://github.com/nodejs/node/blob/43a5170/lib/internal/streams/legacy.js#L13>.
|
||
*
|
||
* @template {NodeJS.WritableStream} Stream
|
||
* Writable stream.
|
||
* @param {Stream} destination
|
||
* Stream to pipe into.
|
||
* @param {PipeOptions | null | undefined} [options]
|
||
* Configuration.
|
||
* @returns {Stream}
|
||
* Destination stream.
|
||
*/
|
||
function pipe(destination, options) {
|
||
emitter.on('data', ondata);
|
||
emitter.on('error', onerror);
|
||
emitter.on('end', cleanup);
|
||
emitter.on('close', cleanup);
|
||
|
||
// If the `end` option is not supplied, `destination.end()` will be
|
||
// called when the `end` or `close` events are received.
|
||
// @ts-expect-error `_isStdio` is available on `std{err,out}`
|
||
if (!destination._isStdio && (!options || options.end !== false)) {
|
||
emitter.on('end', onend);
|
||
}
|
||
destination.on('error', onerror);
|
||
destination.on('close', cleanup);
|
||
destination.emit('pipe', emitter);
|
||
return destination;
|
||
|
||
/**
|
||
* End destination stream.
|
||
*
|
||
* @returns {undefined}
|
||
* Nothing.
|
||
*/
|
||
function onend() {
|
||
if (destination.end) {
|
||
destination.end();
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Handle data.
|
||
*
|
||
* @param {string} chunk
|
||
* Data.
|
||
* @returns {undefined}
|
||
* Nothing.
|
||
*/
|
||
function ondata(chunk) {
|
||
if (destination.writable) {
|
||
destination.write(chunk);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Clean listeners.
|
||
*
|
||
* @returns {undefined}
|
||
* Nothing.
|
||
*/
|
||
function cleanup() {
|
||
emitter.removeListener('data', ondata);
|
||
emitter.removeListener('end', onend);
|
||
emitter.removeListener('error', onerror);
|
||
emitter.removeListener('end', cleanup);
|
||
emitter.removeListener('close', cleanup);
|
||
destination.removeListener('error', onerror);
|
||
destination.removeListener('close', cleanup);
|
||
}
|
||
|
||
/**
|
||
* Close dangling pipes and handle unheard errors.
|
||
*
|
||
* @param {Error | null | undefined} [error]
|
||
* Error, if any.
|
||
* @returns {undefined}
|
||
* Nothing.
|
||
*/
|
||
function onerror(error) {
|
||
cleanup();
|
||
if (!emitter.listenerCount('error')) {
|
||
throw error; // Unhandled stream error in pipe.
|
||
}
|
||
}
|
||
}
|
||
} |