dsh-sidenote 0.4.0 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.js CHANGED
@@ -1,3 +1,3991 @@
1
+ import { createRequire } from "node:module";
2
+ //#region node_modules/.pnpm/@deepseek-ai+cosmokit@1.8.3/node_modules/@deepseek-ai/cosmokit/lib/index.js
3
+ /** Return true when a value is `null` or `undefined`. */
4
+ function isNullable(value) {
5
+ return value === null || value === void 0;
6
+ }
7
+ /** Return true for non-array object values. */
8
+ function isPlainObject(data) {
9
+ return data && typeof data === "object" && !Array.isArray(data);
10
+ }
11
+ /** Filter object entries and return a new object. */
12
+ function filterKeys(object, filter) {
13
+ return Object.fromEntries(Object.entries(object).filter(([key, value]) => filter(key, value)));
14
+ }
15
+ /** Map object values while preserving the original key set. */
16
+ function mapValues(object, transform) {
17
+ return Object.fromEntries(Object.entries(object).map(([key, value]) => [key, transform(value, key)]));
18
+ }
19
+ /** Pick selected keys from an object, optionally including `undefined` values. */
20
+ function pick(source, keys, forced) {
21
+ if (!keys) return { ...source };
22
+ const result = {};
23
+ for (const key of keys) if (forced || source[key] !== void 0) result[key] = source[key];
24
+ return result;
25
+ }
26
+ /** Define a non-enumerable writable property and return the object. */
27
+ function defineProperty(object, key, value) {
28
+ return Object.defineProperty(object, key, {
29
+ writable: true,
30
+ value,
31
+ enumerable: false
32
+ });
33
+ }
34
+ /** Test values using `instanceof` with a `toStringTag` fallback. */
35
+ function is(type, value) {
36
+ if (arguments.length === 1) return (value) => is(type, value);
37
+ return type in globalThis && value instanceof globalThis[type] || Object.prototype.toString.call(value).slice(8, -1) === type;
38
+ }
39
+ function isArrayBufferLike(value) {
40
+ return is("ArrayBuffer", value) || is("SharedArrayBuffer", value);
41
+ }
42
+ function isArrayBufferSource(value) {
43
+ return isArrayBufferLike(value) || ArrayBuffer.isView(value);
44
+ }
45
+ /** Binary source detection and base64/hex conversion helpers. */
46
+ var Binary;
47
+ (function(Binary) {
48
+ Binary.is = isArrayBufferLike;
49
+ Binary.isSource = isArrayBufferSource;
50
+ function fromSource(source) {
51
+ if (ArrayBuffer.isView(source)) return source.buffer.slice(source.byteOffset, source.byteOffset + source.byteLength);
52
+ else return source;
53
+ }
54
+ Binary.fromSource = fromSource;
55
+ function toBase64(source) {
56
+ source = fromSource(source);
57
+ if (typeof Buffer !== "undefined") return Buffer.from(source).toString("base64");
58
+ let binary = "";
59
+ const bytes = new Uint8Array(source);
60
+ for (let i = 0; i < bytes.byteLength; i++) binary += String.fromCharCode(bytes[i]);
61
+ return btoa(binary);
62
+ }
63
+ Binary.toBase64 = toBase64;
64
+ function fromBase64(source) {
65
+ if (typeof Buffer !== "undefined") return fromSource(Buffer.from(source, "base64"));
66
+ return Uint8Array.from(atob(source), (c) => c.charCodeAt(0));
67
+ }
68
+ Binary.fromBase64 = fromBase64;
69
+ function toHex(source) {
70
+ source = fromSource(source);
71
+ if (typeof Buffer !== "undefined") return Buffer.from(source).toString("hex");
72
+ return Array.from(new Uint8Array(source), (byte) => byte.toString(16).padStart(2, "0")).join("");
73
+ }
74
+ Binary.toHex = toHex;
75
+ function fromHex(source) {
76
+ if (typeof Buffer !== "undefined") return fromSource(Buffer.from(source, "hex"));
77
+ const hex = source.length % 2 === 0 ? source : source.slice(0, source.length - 1);
78
+ const buffer = [];
79
+ for (let i = 0; i < hex.length; i += 2) buffer.push(parseInt(`${hex[i]}${hex[i + 1]}`, 16));
80
+ return Uint8Array.from(buffer).buffer;
81
+ }
82
+ Binary.fromHex = fromHex;
83
+ })(Binary || (Binary = {}));
84
+ Binary.fromBase64;
85
+ Binary.toBase64;
86
+ Binary.fromHex;
87
+ Binary.toHex;
88
+ /** Deep-clone common JavaScript values while preserving prototypes and cycles. */
89
+ function clone(source, refs = /* @__PURE__ */ new Map()) {
90
+ if (!source || typeof source !== "object") return source;
91
+ if (is("Date", source)) return new Date(source.valueOf());
92
+ if (is("RegExp", source)) return new RegExp(source.source, source.flags);
93
+ if (isArrayBufferLike(source)) return source.slice(0);
94
+ if (ArrayBuffer.isView(source)) return source.buffer.slice(source.byteOffset, source.byteOffset + source.byteLength);
95
+ const cached = refs.get(source);
96
+ if (cached) return cached;
97
+ if (Array.isArray(source)) {
98
+ const result = [];
99
+ refs.set(source, result);
100
+ source.forEach((value, index) => {
101
+ result[index] = Reflect.apply(clone, null, [value, refs]);
102
+ });
103
+ return result;
104
+ }
105
+ const result = Object.create(Object.getPrototypeOf(source));
106
+ refs.set(source, result);
107
+ for (const key of Reflect.ownKeys(source)) {
108
+ const descriptor = { ...Reflect.getOwnPropertyDescriptor(source, key) };
109
+ if ("value" in descriptor) descriptor.value = Reflect.apply(clone, null, [descriptor.value, refs]);
110
+ Reflect.defineProperty(result, key, descriptor);
111
+ }
112
+ return result;
113
+ }
114
+ /** Deeply compare arrays, dates, regexps, buffers, and plain object fields. */
115
+ function deepEqual(a, b, strict) {
116
+ if (a === b) return true;
117
+ if (!strict && isNullable(a) && isNullable(b)) return true;
118
+ if (typeof a !== typeof b) return false;
119
+ if (typeof a !== "object") return false;
120
+ if (!a || !b) return false;
121
+ function check(test, then) {
122
+ return test(a) ? test(b) ? then(a, b) : false : test(b) ? false : void 0;
123
+ }
124
+ return check(Array.isArray, (a, b) => a.length === b.length && a.every((item, index) => deepEqual(item, b[index]))) ?? check(is("Date"), (a, b) => a.valueOf() === b.valueOf()) ?? check(is("RegExp"), (a, b) => a.source === b.source && a.flags === b.flags) ?? check(isArrayBufferLike, (a, b) => {
125
+ if (a.byteLength !== b.byteLength) return false;
126
+ const viewA = new Uint8Array(a);
127
+ const viewB = new Uint8Array(b);
128
+ for (let i = 0; i < viewA.length; i++) if (viewA[i] !== viewB[i]) return false;
129
+ return true;
130
+ }) ?? Object.keys({
131
+ ...a,
132
+ ...b
133
+ }).every((key) => deepEqual(a[key], b[key], strict));
134
+ }
135
+ function tokenize(source, delimiters, delimiter) {
136
+ const output = [];
137
+ let state = 0;
138
+ for (let i = 0; i < source.length; i++) {
139
+ const code = source.charCodeAt(i);
140
+ if (code >= 65 && code <= 90) {
141
+ if (state === 1) {
142
+ const next = source.charCodeAt(i + 1);
143
+ if (next >= 97 && next <= 122) output.push(delimiter);
144
+ output.push(code + 32);
145
+ } else {
146
+ if (state !== 0) output.push(delimiter);
147
+ output.push(code + 32);
148
+ }
149
+ state = 1;
150
+ } else if (code >= 97 && code <= 122) {
151
+ output.push(code);
152
+ state = 2;
153
+ } else if (delimiters.includes(code)) {
154
+ if (state !== 0) output.push(delimiter);
155
+ state = 0;
156
+ } else output.push(code);
157
+ }
158
+ return String.fromCharCode(...output);
159
+ }
160
+ /** Convert text to dash-delimited parameter case. */
161
+ function paramCase(source) {
162
+ return tokenize(source, [45, 95], 45);
163
+ }
164
+ /** Runtime alias for `paramCase`. */
165
+ const hyphenate = paramCase;
166
+ /** Time constants plus parsing and formatting helpers. */
167
+ var Time;
168
+ (function(Time) {
169
+ Time.millisecond = 1;
170
+ Time.second = 1e3;
171
+ Time.minute = Time.second * 60;
172
+ Time.hour = Time.minute * 60;
173
+ Time.day = Time.hour * 24;
174
+ Time.week = Time.day * 7;
175
+ let timezoneOffset = (/* @__PURE__ */ new Date()).getTimezoneOffset();
176
+ function setTimezoneOffset(offset) {
177
+ timezoneOffset = offset;
178
+ }
179
+ Time.setTimezoneOffset = setTimezoneOffset;
180
+ function getTimezoneOffset() {
181
+ return timezoneOffset;
182
+ }
183
+ Time.getTimezoneOffset = getTimezoneOffset;
184
+ function getDateNumber(date = /* @__PURE__ */ new Date(), offset) {
185
+ if (typeof date === "number") date = new Date(date);
186
+ if (offset === void 0) offset = timezoneOffset;
187
+ return Math.floor((date.valueOf() / Time.minute - offset) / 1440);
188
+ }
189
+ Time.getDateNumber = getDateNumber;
190
+ function fromDateNumber(value, offset) {
191
+ const date = new Date(value * Time.day);
192
+ if (offset === void 0) offset = timezoneOffset;
193
+ return new Date(+date + offset * Time.minute);
194
+ }
195
+ Time.fromDateNumber = fromDateNumber;
196
+ const numeric = /\d+(?:\.\d+)?/.source;
197
+ const timeRegExp = new RegExp(`^${[
198
+ "w(?:eek(?:s)?)?",
199
+ "d(?:ay(?:s)?)?",
200
+ "h(?:our(?:s)?)?",
201
+ "m(?:in(?:ute)?(?:s)?)?",
202
+ "s(?:ec(?:ond)?(?:s)?)?"
203
+ ].map((unit) => `(${numeric}${unit})?`).join("")}$`);
204
+ function parseTime(source) {
205
+ const capture = timeRegExp.exec(source);
206
+ if (!capture) return 0;
207
+ return (parseFloat(capture[1]) * Time.week || 0) + (parseFloat(capture[2]) * Time.day || 0) + (parseFloat(capture[3]) * Time.hour || 0) + (parseFloat(capture[4]) * Time.minute || 0) + (parseFloat(capture[5]) * Time.second || 0);
208
+ }
209
+ Time.parseTime = parseTime;
210
+ function parseDate(date) {
211
+ const parsed = parseTime(date);
212
+ if (parsed) date = Date.now() + parsed;
213
+ else if (/^\d{1,2}(:\d{1,2}){1,2}$/.test(date)) date = `${(/* @__PURE__ */ new Date()).toLocaleDateString()}-${date}`;
214
+ else if (/^\d{1,2}-\d{1,2}-\d{1,2}(:\d{1,2}){1,2}$/.test(date)) date = `${(/* @__PURE__ */ new Date()).getFullYear()}-${date}`;
215
+ return date ? new Date(date) : /* @__PURE__ */ new Date();
216
+ }
217
+ Time.parseDate = parseDate;
218
+ function format(ms) {
219
+ const abs = Math.abs(ms);
220
+ if (abs >= Time.day - Time.hour / 2) return Math.round(ms / Time.day) + "d";
221
+ else if (abs >= Time.hour - Time.minute / 2) return Math.round(ms / Time.hour) + "h";
222
+ else if (abs >= Time.minute - Time.second / 2) return Math.round(ms / Time.minute) + "m";
223
+ else if (abs >= Time.second) return Math.round(ms / Time.second) + "s";
224
+ return ms + "ms";
225
+ }
226
+ Time.format = format;
227
+ function toDigits(source, length = 2) {
228
+ return source.toString().padStart(length, "0");
229
+ }
230
+ Time.toDigits = toDigits;
231
+ function template(template, time = /* @__PURE__ */ new Date()) {
232
+ return template.replace("yyyy", time.getFullYear().toString()).replace("yy", time.getFullYear().toString().slice(2)).replace("MM", toDigits(time.getMonth() + 1)).replace("dd", toDigits(time.getDate())).replace("hh", toDigits(time.getHours())).replace("mm", toDigits(time.getMinutes())).replace("ss", toDigits(time.getSeconds())).replace("SSS", toDigits(time.getMilliseconds(), 3));
233
+ }
234
+ Time.template = template;
235
+ })(Time || (Time = {}));
236
+ //#endregion
237
+ //#region node_modules/.pnpm/@deepseek-ai+cordis@4.0.2/node_modules/@deepseek-ai/cordis/lib/index.js
238
+ /** Ordered collection of disposable values with O(1) deletion by value. */
239
+ var DisposableList = class {
240
+ sn = 0;
241
+ map = /* @__PURE__ */ new Map();
242
+ weak = /* @__PURE__ */ new WeakMap();
243
+ get length() {
244
+ return this.map.size;
245
+ }
246
+ push(value) {
247
+ const sn = ++this.sn;
248
+ this.map.set(sn, value);
249
+ this.weak.set(value, sn);
250
+ return () => this.map.delete(sn);
251
+ }
252
+ delete(value) {
253
+ const sn = this.weak.get(value);
254
+ if (!sn) return false;
255
+ return this.map.delete(sn);
256
+ }
257
+ clear() {
258
+ const values = [...this.map.values()];
259
+ this.map.clear();
260
+ return values.reverse();
261
+ }
262
+ [Symbol.iterator]() {
263
+ return this.map.values();
264
+ }
265
+ [Symbol.for("nodejs.util.inspect.custom")]() {
266
+ return [...this];
267
+ }
268
+ };
269
+ /** Shared symbols used to avoid public property-name collisions. */
270
+ const symbols = {
271
+ shadow: Symbol.for("cordis.shadow"),
272
+ receiver: Symbol.for("cordis.receiver"),
273
+ original: Symbol.for("cordis.original"),
274
+ metadata: Symbol.for("cordis.metadata"),
275
+ initHooks: Symbol.for("cordis.initHooks"),
276
+ checkProto: Symbol.for("cordis.checkProto"),
277
+ effect: Symbol.for("cordis.effect"),
278
+ filter: Symbol.for("cordis.filter"),
279
+ isolate: Symbol.for("cordis.isolate"),
280
+ intercept: Symbol.for("cordis.intercept"),
281
+ init: Symbol.for("cordis.init"),
282
+ check: Symbol.for("cordis.check"),
283
+ config: Symbol.for("cordis.config"),
284
+ invoke: Symbol.for("cordis.invoke"),
285
+ extend: Symbol.for("cordis.extend"),
286
+ tracker: Symbol.for("cordis.tracker"),
287
+ resolveConfig: Symbol.for("cordis.resolveConfig")
288
+ };
289
+ const GeneratorFunction = function* () {}.constructor;
290
+ const AsyncGeneratorFunction = async function* () {}.constructor;
291
+ /** Return true when a plugin callback should be constructed with `new`. */
292
+ function isConstructor(func) {
293
+ if (!func.prototype) return false;
294
+ if (func instanceof GeneratorFunction) return false;
295
+ if (AsyncGeneratorFunction !== Function && func instanceof AsyncGeneratorFunction) return false;
296
+ return true;
297
+ }
298
+ /** Merge two prototype chains while preserving descriptors from `proto1`. */
299
+ function joinPrototype(proto1, proto2) {
300
+ if (proto1 === Object.prototype) return proto2;
301
+ const result = Object.create(joinPrototype(Object.getPrototypeOf(proto1), proto2));
302
+ for (const key of Reflect.ownKeys(proto1)) Object.defineProperty(result, key, Object.getOwnPropertyDescriptor(proto1, key));
303
+ return result;
304
+ }
305
+ /** Return true for non-null objects and functions. */
306
+ function isObject(value) {
307
+ return value && (typeof value === "object" || typeof value === "function");
308
+ }
309
+ /** Find a property descriptor by walking an object's prototype chain. */
310
+ function getPropertyDescriptor(target, prop) {
311
+ let proto = target;
312
+ while (proto) {
313
+ const desc = Reflect.getOwnPropertyDescriptor(proto, prop);
314
+ if (desc) return desc;
315
+ proto = Object.getPrototypeOf(proto);
316
+ }
317
+ }
318
+ /** Wrap services/functions so method calls see the caller's active context. */
319
+ function getTraceable(ctx, value) {
320
+ if (!isObject(value)) return value;
321
+ if (Object.hasOwn(value, symbols.shadow)) return Object.getPrototypeOf(value);
322
+ const tracker = value[symbols.tracker];
323
+ if (!tracker) return value;
324
+ return createTraceable(ctx, value, tracker);
325
+ }
326
+ /** Return a proxy that overlays readonly or writable properties onto a target. */
327
+ function withProps(target, props) {
328
+ if (!props) return target;
329
+ return new Proxy(target, {
330
+ get: (target, prop, receiver) => {
331
+ if (prop in props && prop !== "constructor") return Reflect.get(props, prop, receiver);
332
+ return Reflect.get(target, prop, receiver);
333
+ },
334
+ set: (target, prop, value, receiver) => {
335
+ if (prop in props && prop !== "constructor") return Reflect.set(props, prop, value, receiver);
336
+ return Reflect.set(target, prop, value, receiver);
337
+ }
338
+ });
339
+ }
340
+ function withProp(target, prop, value) {
341
+ return withProps(target, Object.defineProperty(Object.create(null), prop, {
342
+ value,
343
+ writable: false
344
+ }));
345
+ }
346
+ function createShadow(ctx, target, property, receiver) {
347
+ if (!property) return receiver;
348
+ const origin = Reflect.getOwnPropertyDescriptor(target, property)?.value;
349
+ if (!origin) return receiver;
350
+ return withProp(receiver, property, ctx.extend({ [symbols.shadow]: origin }));
351
+ }
352
+ function createShadowMethod(ctx, value, outer, shadow) {
353
+ return new Proxy(value, { apply: (target, thisArg, args) => {
354
+ if (thisArg === outer) thisArg = shadow;
355
+ return getTraceable(ctx, Reflect.apply(target, thisArg, args));
356
+ } });
357
+ }
358
+ function createTraceable(ctx, value, tracker) {
359
+ if (ctx[symbols.shadow] && !tracker.noShadow) ctx = Object.getPrototypeOf(ctx);
360
+ const proxy = new Proxy(value, {
361
+ get: (target, prop, receiver) => {
362
+ if (prop === symbols.original) return target;
363
+ if (prop === tracker.property) return ctx;
364
+ if (typeof prop === "symbol") return Reflect.get(target, prop, receiver);
365
+ if (tracker.associate && ctx.reflect.props[`${tracker.associate}.${prop}`]) return Reflect.get(ctx, `${tracker.associate}.${prop}`, withProp(ctx, symbols.receiver, receiver));
366
+ let shadow, innerValue;
367
+ const desc = getPropertyDescriptor(target, prop);
368
+ if (desc && "value" in desc) innerValue = desc.value;
369
+ else {
370
+ shadow = createShadow(ctx, target, tracker.property, receiver);
371
+ innerValue = Reflect.get(target, prop, shadow);
372
+ }
373
+ const innerTracker = innerValue?.[symbols.tracker];
374
+ if (innerTracker) return createTraceable(ctx, innerValue, innerTracker);
375
+ else if (!tracker.noShadow && typeof innerValue === "function") {
376
+ shadow ??= createShadow(ctx, target, tracker.property, receiver);
377
+ return createShadowMethod(ctx, innerValue, receiver, shadow);
378
+ } else return innerValue;
379
+ },
380
+ set: (target, prop, value, receiver) => {
381
+ if (prop === symbols.original) return false;
382
+ if (prop === tracker.property) return false;
383
+ if (typeof prop === "symbol") return Reflect.set(target, prop, value, receiver);
384
+ if (tracker.associate && ctx.reflect.props[`${tracker.associate}.${prop}`]) return Reflect.set(ctx, `${tracker.associate}.${prop}`, value, withProp(ctx, symbols.receiver, receiver));
385
+ const shadow = createShadow(ctx, target, tracker.property, receiver);
386
+ return Reflect.set(target, prop, value, shadow);
387
+ },
388
+ apply: (target, thisArg, args) => {
389
+ return applyTraceable(proxy, target, thisArg, args);
390
+ }
391
+ });
392
+ return proxy;
393
+ }
394
+ function applyTraceable(proxy, value, thisArg, args) {
395
+ if (!value[symbols.invoke]) return Reflect.apply(value, thisArg, args);
396
+ return value[symbols.invoke].apply(proxy, args);
397
+ }
398
+ /** Create a callable service object that dispatches through `symbols.invoke`. */
399
+ function createCallable(name, proto, tracker) {
400
+ const self = function(...args) {
401
+ return applyTraceable(createTraceable(self["ctx"], self, tracker), self, this, args);
402
+ };
403
+ defineProperty(self, "name", name);
404
+ return Object.setPrototypeOf(self, proto);
405
+ }
406
+ function handleError(info, reason, getOuterStack) {
407
+ const innerLines = info.error.stack.split("\n");
408
+ if (typeof reason?.stack !== "string") {
409
+ const outerError = new Error(reason);
410
+ const lines = outerError.stack.split("\n");
411
+ lines.splice(1, Infinity, ...getOuterStack());
412
+ outerError.stack = lines.join("\n");
413
+ throw outerError;
414
+ }
415
+ const lines = reason.stack.split("\n");
416
+ let index = lines.indexOf(innerLines[2]);
417
+ if (index === -1) throw reason;
418
+ index -= info.offset;
419
+ while (index > 0) {
420
+ if (!lines[index - 1].endsWith(" (<anonymous>)")) break;
421
+ index -= 1;
422
+ }
423
+ lines.splice(index, Infinity, ...getOuterStack());
424
+ reason.stack = lines.join("\n");
425
+ throw reason;
426
+ }
427
+ /** Run a callback and splice outer call-site frames into thrown async errors. */
428
+ function composeError(callback, getOuterStack = buildOuterStack()) {
429
+ const info = {
430
+ offset: 1,
431
+ error: /* @__PURE__ */ new Error()
432
+ };
433
+ try {
434
+ const result = callback(info);
435
+ if (isObject(result) && "then" in result) return result.then(void 0, (reason) => handleError(info, reason, getOuterStack));
436
+ else return result;
437
+ } catch (reason) {
438
+ handleError(info, reason, getOuterStack);
439
+ }
440
+ }
441
+ /** Capture a lazy stack-frame supplier for later error composition. */
442
+ function buildOuterStack(offset = 0) {
443
+ const outerError = /* @__PURE__ */ new Error();
444
+ return () => outerError.stack.split("\n").slice(3 + offset);
445
+ }
446
+ /**
447
+ * Return whether an event result should stop a bail-style dispatch.
448
+ *
449
+ * @param value — a listener's return value.
450
+ * @returns `true` unless `value` is `null`, `false`, or `undefined`.
451
+ */
452
+ function isBailed(value) {
453
+ return value !== null && value !== false && value !== void 0;
454
+ }
455
+ /**
456
+ * Event bus installed as `ctx.events` and mixed into every context.
457
+ *
458
+ * The service supports concurrent, synchronous, serial, bail, and waterfall
459
+ * dispatch and automatically disposes listeners with their owning fiber.
460
+ */
461
+ var EventsService = class {
462
+ ctx;
463
+ _hooks = {};
464
+ constructor(ctx) {
465
+ this.ctx = ctx;
466
+ defineProperty(this, symbols.tracker, {
467
+ property: "ctx",
468
+ noShadow: true
469
+ });
470
+ this.on("internal/listener", function(name, listener, options) {
471
+ if (name === "internal/update" && !options.global) return (this.fiber._hooks["internal/update"] ??= new DisposableList())[options.prepend ? "unshift" : "push"](listener);
472
+ });
473
+ this.on("internal/update", function(config, noSave, next) {
474
+ const cbs = [...this._hooks["internal/update"] || []];
475
+ const _next = () => {
476
+ return (cbs.shift() ?? next).call(this, config, noSave, _next);
477
+ };
478
+ return _next();
479
+ }, {
480
+ global: true,
481
+ prepend: true
482
+ });
483
+ }
484
+ /**
485
+ * Resolve listeners for one dispatch and apply context filtering.
486
+ *
487
+ * @param type — the dispatch mode, reported on `internal/dispatch`.
488
+ * @param args — the raw dispatch arguments; consumed up to the event name.
489
+ * @returns the matching listener callbacks, bound to the dispatch `this`.
490
+ */
491
+ dispatch(type, args) {
492
+ const thisArg = typeof args[0] === "object" || typeof args[0] === "function" ? args.shift() : null;
493
+ const name = args.shift();
494
+ if (!name.startsWith("internal/")) this.emit("internal/dispatch", type, name, args, thisArg);
495
+ const filter = thisArg?.[Context.filter];
496
+ return (this._hooks[name] || []).filter((hook) => hook.global || !filter || filter.call(thisArg, hook.ctx)).map((hook) => hook.callback.bind(thisArg));
497
+ }
498
+ /**
499
+ * Run listeners concurrently and wait for all of them.
500
+ *
501
+ * @param args — optional `this`, the event name, then listener arguments.
502
+ * @returns a promise resolving once every listener has settled.
503
+ */
504
+ async parallel(...args) {
505
+ const errors = (await Promise.allSettled(this.dispatch("emit", args).map(async (cb) => cb(...args)))).filter((result) => result.status === "rejected");
506
+ if (errors.length) throw new AggregateError(errors.map((error) => error.reason));
507
+ }
508
+ /**
509
+ * Run listeners synchronously without waiting for returned promises.
510
+ *
511
+ * @param args — optional `this`, the event name, then listener arguments.
512
+ */
513
+ emit(...args) {
514
+ this.dispatch("emit", args).map((cb) => cb(...args));
515
+ }
516
+ /**
517
+ * Run listeners in order, awaiting each, until one returns a bail value.
518
+ *
519
+ * @param args — optional `this`, the event name, then listener arguments.
520
+ * @returns the first bail value (see {@link isBailed}), if any.
521
+ */
522
+ async serial(...args) {
523
+ for (const cb of this.dispatch("serial", args)) {
524
+ const result = await cb(...args);
525
+ if (isBailed(result)) return result;
526
+ }
527
+ }
528
+ /**
529
+ * Run listeners synchronously until one returns a bail value.
530
+ *
531
+ * @param args — optional `this`, the event name, then listener arguments.
532
+ * @returns the first bail value (see {@link isBailed}), if any.
533
+ */
534
+ bail(...args) {
535
+ for (const cb of this.dispatch("bail", args)) {
536
+ const result = cb(...args);
537
+ if (isBailed(result)) return result;
538
+ }
539
+ }
540
+ /**
541
+ * Compose listeners around the final `next` callback.
542
+ *
543
+ * The last dispatch argument is treated as the innermost `next`. Listeners
544
+ * run outermost-first; a listener that does not call `next()` vetoes the
545
+ * rest of the chain, including the built-in behavior.
546
+ *
547
+ * @param args — optional `this`, the event name, listener arguments, then `next`.
548
+ * @returns the outermost listener's return value.
549
+ */
550
+ waterfall(...args) {
551
+ const cbs = this.dispatch("waterfall", args);
552
+ const inner = args.pop();
553
+ const next = () => {
554
+ return (cbs.shift() ?? inner)(...args);
555
+ };
556
+ args.push(next);
557
+ return next();
558
+ }
559
+ /**
560
+ * Store a listener record as an effect on the current fiber.
561
+ *
562
+ * @param label — effect label shown in fiber diagnostics.
563
+ * @param hooks — the listener list for one event.
564
+ * @param callback — the listener to store.
565
+ * @param options — placement and filtering options.
566
+ * @returns a disposer that unregisters the listener.
567
+ */
568
+ register(label, hooks, callback, options) {
569
+ const method = options.prepend ? "unshift" : "push";
570
+ return this.ctx.fiber.effect(() => {
571
+ hooks[method]({
572
+ ctx: this.ctx,
573
+ callback,
574
+ ...options
575
+ });
576
+ return () => this.unregister(hooks, callback);
577
+ }, label);
578
+ }
579
+ /**
580
+ * Remove a stored listener record.
581
+ *
582
+ * @param hooks — the listener list for one event.
583
+ * @param callback — the listener to remove.
584
+ * @returns `true` if the listener was found and removed.
585
+ */
586
+ unregister(hooks, callback) {
587
+ const index = hooks.findIndex((hook) => hook.callback === callback);
588
+ if (index >= 0) {
589
+ hooks.splice(index, 1);
590
+ return true;
591
+ }
592
+ }
593
+ /**
594
+ * Register an event listener owned by the current fiber.
595
+ *
596
+ * The listener is removed automatically when the fiber unloads. Throws
597
+ * `CordisError('INACTIVE_EFFECT')` if the fiber is already disposed.
598
+ *
599
+ * @param name — the event name to listen for.
600
+ * @param listener — called with the dispatch arguments.
601
+ * @param options — listener options; a boolean is shorthand for `prepend`.
602
+ * @returns a disposer removing the listener; `true` if it was still registered.
603
+ */
604
+ on(name, listener, options) {
605
+ if (typeof options !== "object") options = { prepend: options };
606
+ this.ctx.fiber.assertActive();
607
+ listener = this.ctx.reflect.bind(listener);
608
+ const result = this.bail(this.ctx, "internal/listener", name, listener, options);
609
+ if (result) return result;
610
+ const hooks = this._hooks[name] ||= [];
611
+ const label = `ctx.on(${typeof name === "string" ? JSON.stringify(name) : name.toString()})`;
612
+ return this.register(label, hooks, listener, options);
613
+ }
614
+ /**
615
+ * Register an event listener that disposes itself after the first call.
616
+ *
617
+ * @param name — the event name to listen for.
618
+ * @param listener — called at most once with the dispatch arguments.
619
+ * @param options — listener options; a boolean is shorthand for `prepend`.
620
+ * @returns a disposer removing the listener; `true` if it was still registered.
621
+ */
622
+ once(name, listener, options) {
623
+ const dispose = this.on(name, function(...args) {
624
+ dispose();
625
+ return listener.apply(this, args);
626
+ }, options);
627
+ return dispose;
628
+ }
629
+ };
630
+ /** Built-in placeholder formatters used by `Logger.format()`. */
631
+ const defaultFormatters = {
632
+ s: (value) => String(value),
633
+ d: (value) => Math.trunc(Number(value)),
634
+ i: (value) => Math.trunc(Number(value)),
635
+ f: (value) => Number(value),
636
+ o: (value) => JSON.stringify(value),
637
+ O: (value) => JSON.stringify(value),
638
+ c: () => "",
639
+ C: (value, exporter, message) => {
640
+ return Logger.color(exporter, Logger.code(message.name, exporter.colors), value);
641
+ }
642
+ };
643
+ function isAggregateError(error) {
644
+ return error instanceof Error && Array.isArray(error["errors"]);
645
+ }
646
+ /** Logger facade for one named subsystem. */
647
+ var Logger = class {
648
+ service;
649
+ static color(exporter, code, value, decoration = "") {
650
+ if (!exporter.colors) return "" + value;
651
+ return `\u001b[3${code < 8 ? code : "8;5;" + code}${exporter.colors >= 2 ? decoration : ""}m${value}\u001b[0m`;
652
+ }
653
+ static code(name, level) {
654
+ let hash = 0;
655
+ for (let i = 0; i < name.length; i++) {
656
+ hash = (hash << 3) - hash + name.charCodeAt(i) + 13;
657
+ hash |= 0;
658
+ }
659
+ const colors = !level ? [] : level >= 2 ? c256 : c16;
660
+ return colors[Math.abs(hash) % colors.length];
661
+ }
662
+ static format(exporter, message) {
663
+ const args = message.args.slice();
664
+ if (args[0] instanceof Error) {
665
+ args[0] = args[0].stack || args[0].message;
666
+ args.unshift("%s");
667
+ } else if (typeof args[0] !== "string") args.unshift("%o");
668
+ let format = args.shift();
669
+ format = format.replace(/%([a-zA-Z%])/g, (match, char) => {
670
+ if (match === "%%") return "%";
671
+ const formatter = exporter.formatters?.[char] ?? defaultFormatters[char];
672
+ if (typeof formatter === "function") return formatter(args.shift(), exporter, message);
673
+ return match;
674
+ });
675
+ const oFormatter = exporter.formatters?.o ?? defaultFormatters.o;
676
+ for (let arg of args) {
677
+ if (typeof arg === "object" && arg) arg = oFormatter(arg, exporter, message);
678
+ format += " " + arg;
679
+ }
680
+ const { maxLength = 10240 } = exporter;
681
+ return format.split(/\r?\n/g).map((line) => {
682
+ return line.slice(0, maxLength) + (line.length > maxLength ? "..." : "");
683
+ }).join("\n");
684
+ }
685
+ constructor(options, service) {
686
+ this.service = service;
687
+ Object.assign(this, options);
688
+ this.error = this._method("error", 0);
689
+ this.info = this._method("info", 1);
690
+ this.warn = this._method("warn", 2);
691
+ this.debug = this._method("debug", 3);
692
+ }
693
+ _method(type, level) {
694
+ return (...args) => {
695
+ if (args.length === 1 && args[0] instanceof Error) {
696
+ if (args[0].cause) this[type](args[0].cause);
697
+ else if (isAggregateError(args[0])) {
698
+ args[0].errors.forEach((error) => this[type](error));
699
+ return;
700
+ }
701
+ }
702
+ const sn = ++this.service._snMessage;
703
+ const ts = Date.now();
704
+ for (const exporter of this.service.exporters.values()) {
705
+ if ((exporter.levels?.[this.name] ?? exporter.levels?.default ?? this.level ?? 1) < level) continue;
706
+ const message = {
707
+ sn,
708
+ ts,
709
+ type,
710
+ level,
711
+ name: this.name,
712
+ ...this.meta,
713
+ args
714
+ };
715
+ exporter.export(message);
716
+ }
717
+ };
718
+ }
719
+ };
720
+ /** ANSI 16-color palette indexes used for logger name coloring. */
721
+ const c16 = [
722
+ 6,
723
+ 2,
724
+ 3,
725
+ 4,
726
+ 5,
727
+ 1
728
+ ];
729
+ /** ANSI 256-color palette indexes used for logger name coloring. */
730
+ const c256 = [
731
+ 20,
732
+ 21,
733
+ 26,
734
+ 27,
735
+ 32,
736
+ 33,
737
+ 38,
738
+ 39,
739
+ 40,
740
+ 41,
741
+ 42,
742
+ 43,
743
+ 44,
744
+ 45,
745
+ 56,
746
+ 57,
747
+ 62,
748
+ 63,
749
+ 68,
750
+ 69,
751
+ 74,
752
+ 75,
753
+ 76,
754
+ 77,
755
+ 78,
756
+ 79,
757
+ 80,
758
+ 81,
759
+ 92,
760
+ 93,
761
+ 98,
762
+ 99,
763
+ 112,
764
+ 113,
765
+ 129,
766
+ 134,
767
+ 135,
768
+ 148,
769
+ 149,
770
+ 160,
771
+ 161,
772
+ 162,
773
+ 163,
774
+ 164,
775
+ 165,
776
+ 166,
777
+ 167,
778
+ 168,
779
+ 169,
780
+ 170,
781
+ 171,
782
+ 172,
783
+ 173,
784
+ 178,
785
+ 179,
786
+ 184,
787
+ 185,
788
+ 196,
789
+ 197,
790
+ 198,
791
+ 199,
792
+ 200,
793
+ 201,
794
+ 202,
795
+ 203,
796
+ 204,
797
+ 205,
798
+ 206,
799
+ 207,
800
+ 208,
801
+ 209,
802
+ 214,
803
+ 215,
804
+ 220,
805
+ 221
806
+ ];
807
+ /**
808
+ * Built-in logging service.
809
+ *
810
+ * Call `ctx.logger()` to create a named logger, or call `ctx.logger.info()`
811
+ * directly to log with the current fiber-derived name.
812
+ */
813
+ var LoggerService = class LoggerService {
814
+ bufferSize = 1e3;
815
+ buffer = [];
816
+ ctx;
817
+ _snMessage = 0;
818
+ _snExporter = 0;
819
+ exporters = /* @__PURE__ */ new Map();
820
+ constructor(ctx) {
821
+ const tracker = {
822
+ property: "ctx",
823
+ noShadow: true
824
+ };
825
+ const self = createCallable("logger", joinPrototype(Object.getPrototypeOf(this), Function.prototype), tracker);
826
+ Object.assign(self, this);
827
+ self.ctx = ctx;
828
+ defineProperty(self, symbols.tracker, tracker);
829
+ self.exporter({
830
+ colors: 3,
831
+ export: (message) => {
832
+ self.buffer.push(message);
833
+ if (self.buffer.length > self.bufferSize) self.buffer = self.buffer.slice(-self.bufferSize);
834
+ }
835
+ });
836
+ return self;
837
+ }
838
+ /**
839
+ * Register an exporter and dispose it with the current fiber.
840
+ *
841
+ * @param exporter — the sink that receives structured log messages.
842
+ * @returns a disposer that removes the exporter.
843
+ */
844
+ exporter(exporter) {
845
+ return this.ctx.effect(() => {
846
+ this.exporters.set(++this._snExporter, exporter);
847
+ return () => this.exporters.delete(this._snExporter);
848
+ }, "ctx.logger.exporter()");
849
+ }
850
+ _resolveConfig() {
851
+ let intercept = this.ctx[symbols.intercept];
852
+ const configs = [];
853
+ while ("logger" in intercept) {
854
+ if (Object.hasOwn(intercept, "logger")) configs.unshift(intercept["logger"]);
855
+ intercept = Object.getPrototypeOf(intercept);
856
+ }
857
+ return Object.assign({}, ...configs);
858
+ }
859
+ [symbols.invoke](name) {
860
+ const config = this._resolveConfig();
861
+ const fiber = (this.ctx[symbols.shadow] ?? this.ctx).fiber;
862
+ name ??= config.name;
863
+ name ??= hyphenate(fiber.name);
864
+ return new Logger({
865
+ name,
866
+ level: config.level,
867
+ meta: { fiber: new WeakRef(fiber) }
868
+ }, this);
869
+ }
870
+ static {
871
+ for (const type of [
872
+ "error",
873
+ "info",
874
+ "warn",
875
+ "debug"
876
+ ]) LoggerService.prototype[type] = function(...args) {
877
+ return this()[type](...args);
878
+ };
879
+ }
880
+ };
881
+ function enhanceError(error) {
882
+ const lines = error.stack.split("\n");
883
+ lines.splice(0, 2, `Error: ${error.message}`);
884
+ error.stack = lines.join("\n");
885
+ return error;
886
+ }
887
+ const RESERVED_WORDS = ["prototype", "then"];
888
+ function isSpecialProperty(prop) {
889
+ return typeof prop === "symbol" || RESERVED_WORDS.includes(prop) || parseInt(prop).toString() === prop || prop.startsWith("_");
890
+ }
891
+ /**
892
+ * Reflection and service-resolution layer installed as `ctx.reflect`.
893
+ *
894
+ * This service powers the context proxy, service registration, accessors, and
895
+ * the mixins that expose core service methods directly on `ctx`.
896
+ */
897
+ var ReflectService = class {
898
+ ctx;
899
+ /** Proxy traps implementing service resolution for every context object. */
900
+ static handler = {
901
+ get: (target, prop, ctx) => {
902
+ if (isSpecialProperty(prop)) return Reflect.get(target, prop, ctx);
903
+ if (Reflect.has(target, prop)) return getTraceable(ctx, Reflect.get(target, prop, ctx));
904
+ const error = /* @__PURE__ */ new Error(`cannot get property "${prop}" without inject`);
905
+ try {
906
+ const def = target.reflect.props[prop];
907
+ if (def?.type === "accessor") return def.get.call(ctx, ctx[symbols.receiver], error);
908
+ if (!ctx.fiber.runtime) return ctx.reflect.get(prop, false);
909
+ return ctx.events.waterfall("internal/get", ctx, prop, error, () => {
910
+ const key = target[symbols.isolate][prop];
911
+ let fiber = (ctx[symbols.shadow] ?? ctx).fiber;
912
+ while (true) {
913
+ const impl = fiber.store?.[prop];
914
+ if (impl) return getTraceable(ctx, impl.value);
915
+ if (prop in fiber.inject) {
916
+ error.message = `cannot get required service "${prop}" in inactive context`;
917
+ throw error;
918
+ }
919
+ if (!fiber.runtime) throw error;
920
+ if (fiber.parent[symbols.isolate][prop] !== key) throw error;
921
+ fiber = fiber.parent.fiber;
922
+ }
923
+ });
924
+ } catch (e) {
925
+ throw e === error ? enhanceError(e) : e;
926
+ }
927
+ },
928
+ set: (target, prop, value, ctx) => {
929
+ if (isSpecialProperty(prop)) return Reflect.set(target, prop, value, ctx);
930
+ const error = /* @__PURE__ */ new Error(`cannot set property "${prop}" without provide`);
931
+ const def = target.reflect.props[prop];
932
+ if (!def) {
933
+ if (!ctx.fiber.runtime) return Reflect.set(target, prop, value, ctx);
934
+ throw enhanceError(error);
935
+ }
936
+ try {
937
+ if (def.type === "accessor") {
938
+ if (!def.set) return false;
939
+ return def.set.call(ctx, value, ctx[symbols.receiver], error);
940
+ }
941
+ return ctx.events.waterfall("internal/set", ctx, prop, value, error, () => {
942
+ return ctx.reflect.set(prop, value, error);
943
+ });
944
+ } catch (e) {
945
+ throw e === error ? enhanceError(e) : e;
946
+ }
947
+ },
948
+ has: (target, prop) => {
949
+ if (isSpecialProperty(prop)) return Reflect.has(target, prop);
950
+ if (Reflect.has(target, prop)) return true;
951
+ return !!target.reflect.props[prop];
952
+ }
953
+ };
954
+ /** Service implementations, keyed by isolation label. */
955
+ store = Object.create(null);
956
+ /** Declared context properties (services and accessors), by name. */
957
+ props = Object.create(null);
958
+ constructor(ctx) {
959
+ this.ctx = ctx;
960
+ defineProperty(this, symbols.tracker, {
961
+ property: "ctx",
962
+ noShadow: true
963
+ });
964
+ this.mixin("reflect", [
965
+ "get",
966
+ "set",
967
+ "provide",
968
+ "accessor",
969
+ "mixin"
970
+ ]);
971
+ this.mixin("fiber", ["runtime", "effect"]);
972
+ this.mixin("registry", ["inject", "plugin"]);
973
+ this.mixin("events", [
974
+ "on",
975
+ "once",
976
+ "parallel",
977
+ "emit",
978
+ "serial",
979
+ "bail",
980
+ "waterfall"
981
+ ]);
982
+ }
983
+ /**
984
+ * Read a service from the store without the inject requirement.
985
+ *
986
+ * @param name — the service name.
987
+ * @param strict — when `true`, only return implementations whose providing
988
+ * fiber is currently active.
989
+ * @returns the service value, or `undefined` when not (yet) provided.
990
+ */
991
+ get(name, strict = true) {
992
+ return getTraceable(this.ctx, this._getImpl(name, strict)?.value);
993
+ }
994
+ _getImpl(name, strict = true) {
995
+ const key = this.ctx[symbols.isolate][name];
996
+ const impl = key && this.store[key];
997
+ if (!impl) return;
998
+ if (strict && impl.fiber.state !== 2) return;
999
+ return impl;
1000
+ }
1001
+ /**
1002
+ * Overwrite a provided service's value.
1003
+ *
1004
+ * @param name — the service name.
1005
+ * @param value — the new service value.
1006
+ * @param error — carrier for the caller stack in diagnostics.
1007
+ * @returns `true` on success.
1008
+ * @throws when `name` was never provided, or was provided by another fiber.
1009
+ */
1010
+ set(name, value, error) {
1011
+ const key = this.ctx[symbols.isolate][name];
1012
+ const impl = this.store[key];
1013
+ if (!impl) throw new Error(`cannot set property "${name}" without provide`);
1014
+ if (impl.fiber !== this.ctx.fiber) throw new Error(`cannot set property "${name}" in multiple fibers`);
1015
+ impl.value = value;
1016
+ return true;
1017
+ }
1018
+ /**
1019
+ * Register a service implementation owned by the current fiber.
1020
+ *
1021
+ * See the `ctx.provide()` overload above for the full contract.
1022
+ *
1023
+ * @param name — the service name.
1024
+ * @param value — the service value.
1025
+ * @param check — optional availability predicate for dependents.
1026
+ * @returns a disposer that unregisters the service.
1027
+ */
1028
+ provide(name, value, check) {
1029
+ return this.ctx.fiber.effect(() => {
1030
+ if (!this.props[name]) this.props[name] ??= { type: "service" };
1031
+ else if (this.props[name].type !== "service") throw new Error(`property "${name}" is already declared as ${this.props[name].type}`);
1032
+ this.props[name] = { type: "service" };
1033
+ this.ctx.root[symbols.isolate][name] ??= Symbol(name);
1034
+ const key = this.ctx[symbols.isolate][name];
1035
+ const impl = {
1036
+ name,
1037
+ value,
1038
+ fiber: this.ctx.fiber,
1039
+ check
1040
+ };
1041
+ if (this.store[key]) throw new Error(`service "${name}" has been registered at <${this.store[key].fiber.name}>`);
1042
+ this.store[key] = impl;
1043
+ this.ctx.fiber.store[name] = impl;
1044
+ if (this.ctx.fiber.state === 2) this.notify([name]);
1045
+ return async () => {
1046
+ delete this.store[key];
1047
+ const fibers = this.notify([name]);
1048
+ await Promise.allSettled(fibers.map((fiber) => fiber.await()));
1049
+ delete this.ctx.fiber.store[name];
1050
+ };
1051
+ }, `ctx.provide(${JSON.stringify(name)})`);
1052
+ }
1053
+ /**
1054
+ * Re-evaluate every fiber that requires one of the given services.
1055
+ *
1056
+ * @param names — the service names that changed.
1057
+ * @param filter — restricts notification to matching isolation scopes.
1058
+ * @returns the fibers whose dependency state was refreshed.
1059
+ */
1060
+ notify(names, filter = (ctx, name) => ctx[symbols.isolate][name] === this.ctx[symbols.isolate][name]) {
1061
+ const fibers = [];
1062
+ for (const runtime of this.ctx.registry.values()) for (const fiber of runtime.fibers) {
1063
+ let hasUpdate = false;
1064
+ for (const name of names) {
1065
+ if (!(name in fiber.inject)) continue;
1066
+ if (!filter(fiber.ctx, name)) continue;
1067
+ hasUpdate = true;
1068
+ fiber._checkImpl(name);
1069
+ }
1070
+ if (!hasUpdate) continue;
1071
+ fiber._refresh();
1072
+ fibers.push(fiber);
1073
+ }
1074
+ for (const name of names) {
1075
+ const self = Object.create(this.ctx);
1076
+ self[symbols.filter] = (target) => filter(target, name);
1077
+ this.ctx.events.emit(self, "internal/service", name, this._getImpl(name, false)?.value);
1078
+ }
1079
+ return fibers;
1080
+ }
1081
+ /**
1082
+ * Define a computed context property backed by get/set hooks.
1083
+ *
1084
+ * @param name — the context property name.
1085
+ * @param options — the `get` hook and optional `set` hook.
1086
+ * @returns a disposer that removes the accessor.
1087
+ */
1088
+ accessor(name, options) {
1089
+ return this.ctx.fiber.effect(() => {
1090
+ if (name in this.props) throw new Error(`property "${name}" is already declared as ${this.props[name].type}`);
1091
+ this.props[name] = {
1092
+ type: "accessor",
1093
+ ...options
1094
+ };
1095
+ return () => delete this.props[name];
1096
+ }, `ctx.accessor(${JSON.stringify(name)})`);
1097
+ }
1098
+ /**
1099
+ * Expose selected members of a service directly on `ctx`.
1100
+ *
1101
+ * See the `ctx.mixin()` overload above for the full contract.
1102
+ *
1103
+ * @param source — a context property name or a source object.
1104
+ * @param mixins — keys to forward, or a source-key → ctx-key map.
1105
+ * @returns a disposer that removes all created accessors.
1106
+ */
1107
+ mixin(source, mixins) {
1108
+ const self = this;
1109
+ return this.ctx.fiber.effect(function* () {
1110
+ const entries = Array.isArray(mixins) ? mixins.map((key) => [key, key]) : Object.entries(mixins);
1111
+ const getTarget = (ctx, error) => {
1112
+ return ctx[source];
1113
+ };
1114
+ for (const [key, value] of entries) yield self.accessor(value, {
1115
+ get(receiver, error) {
1116
+ const service = getTarget(this, error);
1117
+ if (isNullable(service)) return service;
1118
+ const mixin = receiver ? withProps(receiver, service) : service;
1119
+ const value = Reflect.get(service, key, mixin);
1120
+ if (typeof value !== "function") return value;
1121
+ return value.bind(mixin ?? service);
1122
+ },
1123
+ set(value, receiver, error) {
1124
+ const service = getTarget(this, error);
1125
+ const mixin = receiver ? withProps(receiver, service) : service;
1126
+ return Reflect.set(service, key, value, mixin);
1127
+ }
1128
+ });
1129
+ }, `ctx.mixin(${JSON.stringify(source)})`);
1130
+ }
1131
+ /**
1132
+ * Attach this context's tracing wrapper to a value.
1133
+ *
1134
+ * @param value — the value to wrap.
1135
+ * @returns the traceable wrapper (or the value itself when not applicable).
1136
+ */
1137
+ trace(value) {
1138
+ return getTraceable(this.ctx, value);
1139
+ }
1140
+ /**
1141
+ * Wrap a callback so calls trace `this` and arguments to this context.
1142
+ *
1143
+ * @param callback — the function to wrap.
1144
+ * @returns a proxy delegating to `callback` with traced values.
1145
+ */
1146
+ bind(callback) {
1147
+ return new Proxy(callback, {
1148
+ apply: (target, thisArg, args) => {
1149
+ return Reflect.apply(target, this.trace(thisArg), args.map((arg) => this.trace(arg)));
1150
+ },
1151
+ construct: (target, args, newTarget) => {
1152
+ return Reflect.construct(target, args.map((arg) => this.trace(arg)), newTarget);
1153
+ }
1154
+ });
1155
+ }
1156
+ };
1157
+ const kValidationError$1 = Symbol.for("ValidationError");
1158
+ /** Error raised when plugin configuration fails standard-schema validation. */
1159
+ var ValidationError$1 = class extends TypeError {
1160
+ name = "ValidationError";
1161
+ /**
1162
+ * Build the aggregated message from schema issues.
1163
+ *
1164
+ * @param issues — the standard-schema issues, one message line each.
1165
+ */
1166
+ constructor(issues) {
1167
+ super(`invalid config:\n` + issues.map((issue) => {
1168
+ if (issue.path) return ` - ${issue.message} (at ${issue.path.join(".")})`;
1169
+ else return ` - ${issue.message}`;
1170
+ }).join("\n"));
1171
+ }
1172
+ };
1173
+ Object.defineProperty(ValidationError$1.prototype, kValidationError$1, { value: true });
1174
+ /**
1175
+ * Validate and normalize config for a plugin runtime before it starts.
1176
+ *
1177
+ * @param runtime — the plugin runtime whose `Config` schema to apply.
1178
+ * @param config — the raw user config.
1179
+ * @returns the validated config, or `config` unchanged if the runtime has no schema.
1180
+ * @throws {ValidationError} when validation reports issues.
1181
+ */
1182
+ function resolveConfig(runtime, config) {
1183
+ if (!runtime.Config) return config;
1184
+ const result = runtime.Config["~standard"].validate(config);
1185
+ if ("then" in result) throw new TypeError("Async config validation is not supported");
1186
+ if (result.issues) throw new ValidationError$1(result.issues);
1187
+ else return result.value;
1188
+ }
1189
+ const effectInertia = /* @__PURE__ */ new WeakMap();
1190
+ function runDisposable(dispose) {
1191
+ const result = dispose();
1192
+ return effectInertia.get(dispose)?.() ?? result;
1193
+ }
1194
+ /** Notify plugin teardown without allowing one observer to break ownership cleanup. */
1195
+ function emitPluginDisposed(context, fiber) {
1196
+ const args = ["internal/plugin", fiber];
1197
+ let callbacks;
1198
+ try {
1199
+ callbacks = context.events.dispatch("emit", args);
1200
+ } catch (error) {
1201
+ context.logger.error(error);
1202
+ return;
1203
+ }
1204
+ for (const callback of callbacks) try {
1205
+ const returned = callback(...args);
1206
+ Promise.resolve(returned).catch((error) => context.logger.error(error));
1207
+ } catch (error) {
1208
+ context.logger.error(error);
1209
+ }
1210
+ }
1211
+ /** Framework error with a stable machine-readable code. */
1212
+ var CordisError = class CordisError extends Error {
1213
+ code;
1214
+ /**
1215
+ * @param code — the stable error code; also the default message.
1216
+ * @param message — optional human-readable override.
1217
+ */
1218
+ constructor(code, message) {
1219
+ super(message ?? CordisError.Code[code]);
1220
+ this.code = code;
1221
+ }
1222
+ };
1223
+ /** Cordis error code definitions. */
1224
+ (function(CordisError) {
1225
+ CordisError.Code = { INACTIVE_EFFECT: "cannot create effect on inactive context" };
1226
+ })(CordisError || (CordisError = {}));
1227
+ const INACTIVE = "__INACTIVE__";
1228
+ /**
1229
+ * Runtime instance of one plugin application.
1230
+ *
1231
+ * A fiber tracks dependency state, validated config, lifecycle effects, and
1232
+ * cleanup for the plugin context returned by `ctx.plugin()`.
1233
+ */
1234
+ var Fiber = class {
1235
+ parent;
1236
+ inject;
1237
+ runtime;
1238
+ /** Unique id within the registry; 0 for the root fiber, `null` once disposed. */
1239
+ uid;
1240
+ /** The context this fiber's plugin runs in (extends the parent context). */
1241
+ ctx;
1242
+ /** The validated plugin config (updated by `update()`). */
1243
+ config;
1244
+ /** The raw plugin config, re-resolved before each activation. */
1245
+ _config;
1246
+ /** Current lifecycle state; transitions emit `internal/status`. */
1247
+ state = 0;
1248
+ /** Dispose this fiber: unload the plugin, then settle once cleanup finished. */
1249
+ dispose;
1250
+ /** Snapshot of required service implementations while loaded; `undefined` otherwise. */
1251
+ store;
1252
+ /** The in-flight load/unload transition, if one is currently running. */
1253
+ inertia;
1254
+ _hooks = Object.create(null);
1255
+ _disposables = new DisposableList();
1256
+ context;
1257
+ _error;
1258
+ _runner;
1259
+ _store = Object.create(null);
1260
+ /**
1261
+ * Create a fiber. Plugin authors normally obtain fibers from `ctx.plugin()`
1262
+ * rather than constructing them directly.
1263
+ *
1264
+ * @param parent — the context the plugin was loaded from.
1265
+ * @param config — raw config, validated against the runtime's schema.
1266
+ * @param inject — resolved dependency map (service name → intercept config).
1267
+ * @param runtime — the shared plugin runtime, or `null` for the root fiber.
1268
+ * @param getOuterStack — captures the caller stack for effect diagnostics.
1269
+ */
1270
+ constructor(parent, config, inject, runtime, getOuterStack) {
1271
+ this.parent = parent;
1272
+ this.inject = inject;
1273
+ this.runtime = runtime;
1274
+ this._config = config;
1275
+ const collect = (dispose) => {
1276
+ this._disposables.push(dispose);
1277
+ };
1278
+ if (runtime) {
1279
+ this.uid = parent.registry.counter;
1280
+ this.ctx = this.context = parent.extend({ fiber: this });
1281
+ const injectEntries = Object.entries(this.inject);
1282
+ if (injectEntries.length) {
1283
+ this.ctx[Context.intercept] = Object.create(parent[Context.intercept]);
1284
+ for (const [name, config] of injectEntries) {
1285
+ if (isNullable(config)) continue;
1286
+ this.ctx[Context.intercept][name] = config;
1287
+ }
1288
+ }
1289
+ this._runner = {
1290
+ epoch: INACTIVE,
1291
+ getOuterStack,
1292
+ execute: function() {
1293
+ if (isConstructor(runtime.callback)) {
1294
+ const instance = new runtime.callback(this.ctx, this.config);
1295
+ for (const hook of instance?.[symbols.initHooks] ?? []) hook();
1296
+ return instance?.[symbols.init]?.();
1297
+ } else return runtime.callback(this.ctx, this.config);
1298
+ },
1299
+ collect
1300
+ };
1301
+ this.dispose = parent.fiber.effect(() => {
1302
+ const remove = runtime.fibers.push(this);
1303
+ return async () => {
1304
+ this.uid = null;
1305
+ emitPluginDisposed(this.context, this);
1306
+ if (this.ctx.registry.has(runtime.callback)) {
1307
+ remove();
1308
+ if (!runtime.fibers.length) this.ctx.registry.delete(runtime.callback);
1309
+ }
1310
+ this._setEpoch(INACTIVE);
1311
+ if (!this.inertia) this._updateState(() => {
1312
+ this.inertia = this._unload();
1313
+ return 5;
1314
+ });
1315
+ while (this.inertia) await this.inertia;
1316
+ };
1317
+ }, "ctx.plugin()");
1318
+ try {
1319
+ this.context.emit("internal/plugin", this);
1320
+ } catch (error) {
1321
+ Promise.resolve(this.dispose()).catch((reason) => this.ctx.logger.error(reason));
1322
+ throw error;
1323
+ }
1324
+ if (this.uid !== null && parent.fiber.state !== 5) {
1325
+ for (const name of Object.keys(this.inject)) this._checkImpl(name);
1326
+ this._refresh();
1327
+ }
1328
+ } else {
1329
+ this.uid = 0;
1330
+ this.ctx = this.context = parent;
1331
+ this.state = 2;
1332
+ this.store = Object.create(null);
1333
+ this._runner = {
1334
+ epoch: "",
1335
+ getOuterStack,
1336
+ execute: () => {},
1337
+ collect
1338
+ };
1339
+ this.dispose = () => this.restart();
1340
+ }
1341
+ }
1342
+ /** The plugin's display name, inherited from the nearest named ancestor, else `'root'`. */
1343
+ get name() {
1344
+ let fiber = this;
1345
+ do {
1346
+ if (fiber.runtime?.name) return fiber.runtime.name;
1347
+ fiber = fiber.parent.fiber;
1348
+ } while (fiber !== fiber.parent.fiber);
1349
+ return "root";
1350
+ }
1351
+ /**
1352
+ * Throw if the fiber has already been disposed.
1353
+ *
1354
+ * @returns nothing when the fiber is still active.
1355
+ * @throws {CordisError} `INACTIVE_EFFECT` when the fiber's uid has been cleared.
1356
+ */
1357
+ assertActive() {
1358
+ if (this.uid !== null) return;
1359
+ throw new CordisError("INACTIVE_EFFECT");
1360
+ }
1361
+ _execute(runner) {
1362
+ const oldEpoch = runner.epoch;
1363
+ return composeError((info) => {
1364
+ const safeCollect = (dispose) => {
1365
+ if (typeof dispose === "function") runner.collect(dispose);
1366
+ else if (!isNullable(dispose)) throw new TypeError("Invalid effect");
1367
+ };
1368
+ const effect = runner.execute.call(this);
1369
+ if (typeof effect === "function") return runner.collect(effect);
1370
+ else if (isNullable(effect)) {} else if (!isObject(effect)) throw new TypeError("Invalid effect");
1371
+ else if ("then" in effect) return effect.then(safeCollect);
1372
+ else if (Symbol.iterator in effect) {
1373
+ info.error = /* @__PURE__ */ new Error();
1374
+ const iter = effect[Symbol.iterator]();
1375
+ while (true) {
1376
+ const result = iter.next();
1377
+ safeCollect(result.value);
1378
+ if (result.done) return;
1379
+ }
1380
+ } else if (Symbol.asyncIterator in effect) {
1381
+ const iter = effect[Symbol.asyncIterator]();
1382
+ return (async () => {
1383
+ await Promise.resolve();
1384
+ info.error = /* @__PURE__ */ new Error();
1385
+ while (true) {
1386
+ if (runner.epoch !== oldEpoch) return;
1387
+ const result = await iter.next();
1388
+ safeCollect(result.value);
1389
+ if (result.done) return;
1390
+ }
1391
+ })();
1392
+ } else throw new TypeError("Invalid effect");
1393
+ }, runner.getOuterStack);
1394
+ }
1395
+ effect(execute, label = "anonymous") {
1396
+ this.assertActive();
1397
+ if (this.state === 5) throw new CordisError("INACTIVE_EFFECT");
1398
+ const disposables = [];
1399
+ let disposing = false;
1400
+ let disposalTask;
1401
+ const dispose = () => {
1402
+ if (disposing) return disposalTask;
1403
+ disposing = true;
1404
+ let task;
1405
+ for (const disposable of disposables.splice(0).reverse()) if (task) task = task.then(() => runDisposable(disposable));
1406
+ else {
1407
+ const result = runDisposable(disposable);
1408
+ if (isObject(result) && "then" in result) task = result;
1409
+ }
1410
+ return disposalTask = task;
1411
+ };
1412
+ const meta = {
1413
+ label,
1414
+ children: []
1415
+ };
1416
+ const runner = {
1417
+ execute,
1418
+ epoch: true,
1419
+ collect: (dispose) => {
1420
+ disposables.push(dispose);
1421
+ this._disposables.delete(dispose);
1422
+ if (dispose[symbols.effect]) meta.children.push(dispose[symbols.effect]);
1423
+ },
1424
+ getOuterStack: buildOuterStack()
1425
+ };
1426
+ let task;
1427
+ let executing = true;
1428
+ let resolveSetup;
1429
+ let rejectSetup;
1430
+ let setupBarrier;
1431
+ let setupFailed = false;
1432
+ let inFlight;
1433
+ let removeWrapper = () => false;
1434
+ const waitForSetup = () => {
1435
+ setupBarrier ??= new Promise((resolve, reject) => {
1436
+ resolveSetup = resolve;
1437
+ rejectSetup = reject;
1438
+ });
1439
+ return setupBarrier;
1440
+ };
1441
+ const disposeAfter = (setup) => {
1442
+ return Promise.resolve(setup).then(() => dispose(), async (reason) => {
1443
+ await dispose();
1444
+ throw reason;
1445
+ });
1446
+ };
1447
+ const finalizeDisposal = (callback) => {
1448
+ let result;
1449
+ try {
1450
+ result = callback();
1451
+ } catch (error) {
1452
+ removeWrapper();
1453
+ throw error;
1454
+ }
1455
+ if (isObject(result) && "then" in result) {
1456
+ const pending = Promise.resolve(result).finally(() => {
1457
+ removeWrapper();
1458
+ if (inFlight === pending) inFlight = void 0;
1459
+ });
1460
+ return inFlight = pending;
1461
+ }
1462
+ removeWrapper();
1463
+ return result;
1464
+ };
1465
+ const wrapper = defineProperty(() => {
1466
+ if (!runner.epoch) return setupFailed ? inFlight : void 0;
1467
+ runner.epoch = false;
1468
+ return finalizeDisposal(() => {
1469
+ if (executing) return disposeAfter(waitForSetup());
1470
+ return task ? disposeAfter(task) : dispose();
1471
+ });
1472
+ }, symbols.effect, meta);
1473
+ effectInertia.set(wrapper, () => inFlight);
1474
+ removeWrapper = this._disposables.push(wrapper);
1475
+ try {
1476
+ task = this._execute(runner);
1477
+ } catch (reason) {
1478
+ executing = false;
1479
+ setupFailed = true;
1480
+ runner.epoch = false;
1481
+ let cleanup;
1482
+ try {
1483
+ cleanup = finalizeDisposal(dispose);
1484
+ } finally {
1485
+ rejectSetup?.(reason);
1486
+ }
1487
+ if (isObject(cleanup) && "then" in cleanup) cleanup.catch((error) => this.ctx.logger.error(error));
1488
+ throw reason;
1489
+ }
1490
+ executing = false;
1491
+ if (setupBarrier) Promise.resolve(task).then(resolveSetup, rejectSetup);
1492
+ task?.catch(() => {
1493
+ if (!runner.epoch) return dispose();
1494
+ return finalizeDisposal(dispose);
1495
+ }).catch((error) => this.ctx.logger.error(error));
1496
+ const disposeAsync = () => {
1497
+ if (!runner.epoch) return;
1498
+ runner.epoch = false;
1499
+ return finalizeDisposal(dispose);
1500
+ };
1501
+ wrapper.then = async (onFulfilled, onRejected) => {
1502
+ return Promise.resolve(task).then(() => disposeAsync).then(onFulfilled, onRejected);
1503
+ };
1504
+ return wrapper;
1505
+ }
1506
+ /**
1507
+ * Return metadata for currently registered effects.
1508
+ *
1509
+ * @returns one {@link EffectMeta} tree per labeled live effect.
1510
+ */
1511
+ getEffects() {
1512
+ return [...this._disposables].map((dispose) => dispose[symbols.effect]).filter(Boolean);
1513
+ }
1514
+ _getState() {
1515
+ if (this.uid === null) return 4;
1516
+ if (this._error) return 3;
1517
+ if (this._runner.epoch !== INACTIVE) return 2;
1518
+ return 0;
1519
+ }
1520
+ _updateState(callback) {
1521
+ const oldState = this.state;
1522
+ this.state = callback() ?? this._getState();
1523
+ if (oldState === this.state) return;
1524
+ this.context.emit("internal/status", this, oldState);
1525
+ if (oldState !== 2 && this.state !== 2) return;
1526
+ for (const key of Reflect.ownKeys(this.ctx.reflect.store)) {
1527
+ const impl = this.ctx.reflect.store[key];
1528
+ if (impl.fiber !== this) continue;
1529
+ this.ctx.reflect.notify([impl.name]);
1530
+ }
1531
+ }
1532
+ _checkImpl(name) {
1533
+ const impl = this.ctx.reflect._getImpl(name, true);
1534
+ if (!impl) return delete this._store[name];
1535
+ try {
1536
+ if (impl.check && !impl.check.call(getTraceable(this.ctx, impl.value))) return delete this._store[name];
1537
+ } catch (error) {
1538
+ impl.fiber.ctx.logger.error(error);
1539
+ return delete this._store[name];
1540
+ }
1541
+ this._store[name] = impl;
1542
+ }
1543
+ _refresh() {
1544
+ let epoch = false;
1545
+ epoch = "";
1546
+ for (const name of Object.keys(this.inject)) {
1547
+ const impl = this._store[name];
1548
+ if (!impl) {
1549
+ epoch = INACTIVE;
1550
+ break;
1551
+ }
1552
+ epoch += ":" + impl.fiber.uid;
1553
+ }
1554
+ this._setEpoch(epoch);
1555
+ }
1556
+ _setEpoch(epoch) {
1557
+ const oldEpoch = this._runner.epoch;
1558
+ if (epoch === oldEpoch) return;
1559
+ this._runner.epoch = epoch;
1560
+ if (this.inertia) return;
1561
+ this._updateState(() => {
1562
+ if (epoch !== INACTIVE && oldEpoch === INACTIVE) {
1563
+ this.inertia = this._reload();
1564
+ return 1;
1565
+ } else {
1566
+ this.inertia = this._unload();
1567
+ return 5;
1568
+ }
1569
+ });
1570
+ }
1571
+ _resolveConfig(config) {
1572
+ config = this.context.waterfall(this, "internal/config", config, () => config);
1573
+ return this.runtime ? resolveConfig(this.runtime, config) : config;
1574
+ }
1575
+ async _reload() {
1576
+ this.store = { ...this._store };
1577
+ const oldEpoch = this._runner.epoch;
1578
+ try {
1579
+ await Promise.resolve();
1580
+ if (this._runner.epoch === oldEpoch) {
1581
+ this.config = this._resolveConfig(this._config);
1582
+ await this._execute(this._runner);
1583
+ this._error = void 0;
1584
+ }
1585
+ } catch (reason) {
1586
+ this.ctx.logger.error(reason);
1587
+ this._error = reason;
1588
+ this._runner.epoch = INACTIVE;
1589
+ }
1590
+ this._updateState(() => {
1591
+ if (this._runner.epoch === oldEpoch) this.inertia = void 0;
1592
+ else {
1593
+ this.inertia = this._unload();
1594
+ return 5;
1595
+ }
1596
+ });
1597
+ }
1598
+ async _unload() {
1599
+ await Promise.all(this._disposables.clear().map(async (dispose) => {
1600
+ try {
1601
+ await composeError(async (info) => {
1602
+ await Promise.resolve();
1603
+ info.error = /* @__PURE__ */ new Error();
1604
+ await runDisposable(dispose);
1605
+ }, this._runner.getOuterStack);
1606
+ } catch (reason) {
1607
+ this.ctx.logger.error(reason);
1608
+ }
1609
+ }));
1610
+ this.store = void 0;
1611
+ this._updateState(() => {
1612
+ if (this._runner.epoch === INACTIVE) this.inertia = void 0;
1613
+ else {
1614
+ this.inertia = this._reload();
1615
+ return 1;
1616
+ }
1617
+ });
1618
+ }
1619
+ /**
1620
+ * Wait for current lifecycle work and rethrow startup errors.
1621
+ *
1622
+ * @returns this fiber, once it has settled into a stable state.
1623
+ * @throws the config-validation or plugin-startup error, if any.
1624
+ */
1625
+ async await() {
1626
+ while (this.inertia) await this.inertia;
1627
+ if (this._error) throw this._error;
1628
+ return this;
1629
+ }
1630
+ /**
1631
+ * Dispose and immediately reload this plugin with its current config.
1632
+ *
1633
+ * @returns a promise resolving once the reload settled.
1634
+ * @throws {CordisError} `INACTIVE_EFFECT` when the fiber is already disposed.
1635
+ */
1636
+ async restart() {
1637
+ this.assertActive();
1638
+ this._setEpoch(INACTIVE);
1639
+ this._refresh();
1640
+ await this.await();
1641
+ }
1642
+ /**
1643
+ * Validate and apply new config, then restart the plugin.
1644
+ *
1645
+ * Runs the `internal/update` waterfall first, so update hooks (and HMR)
1646
+ * can veto or replace the restart.
1647
+ *
1648
+ * @param config — the new raw config; validated before anything restarts.
1649
+ * @param noSave — hint for persistence hooks not to write the change back.
1650
+ * @returns the update waterfall result; the default restart returns a promise.
1651
+ * @throws when validation, an update listener, or the restarted plugin fails.
1652
+ */
1653
+ update(config, noSave = false) {
1654
+ this.assertActive();
1655
+ this._config = config;
1656
+ if (this.state !== 2) {
1657
+ this._error = void 0;
1658
+ this._setEpoch(INACTIVE);
1659
+ this._refresh();
1660
+ return;
1661
+ }
1662
+ config = this._resolveConfig(config);
1663
+ return this.context.waterfall(this, "internal/update", config, noSave, () => {
1664
+ this.config = config;
1665
+ this._error = void 0;
1666
+ return this.restart();
1667
+ });
1668
+ }
1669
+ };
1670
+ function isApplicable(object) {
1671
+ return object && typeof object === "object" && typeof object.apply === "function";
1672
+ }
1673
+ /**
1674
+ * Decorator for declaring service dependencies on classes or class methods.
1675
+ *
1676
+ * On classes it contributes to the plugin's static `inject` map. On methods it
1677
+ * delays the method call until the declared services are available.
1678
+ */
1679
+ /**
1680
+ * @param name — the required service name.
1681
+ * @param config — optional intercept config applied for that service.
1682
+ * @returns the class or method decorator.
1683
+ */
1684
+ function Inject(name, config) {
1685
+ return function(value, decorator) {
1686
+ if (decorator.kind === "class") {
1687
+ if (!Object.hasOwn(value, "inject")) {
1688
+ defineProperty(value, "inject", Object.create(Object.getPrototypeOf(value).inject ?? null));
1689
+ defineProperty(value.inject, symbols.checkProto, true);
1690
+ }
1691
+ value.inject[name] = config;
1692
+ } else if (decorator.kind === "method") {
1693
+ const inject = (value[symbols.metadata] ??= {}).inject ??= Object.create(null);
1694
+ inject[name] = config;
1695
+ decorator.addInitializer(function() {
1696
+ const property = this[symbols.tracker]?.property;
1697
+ (this[symbols.initHooks] ??= []).push(() => {
1698
+ this.ctx.inject(inject, (ctx) => {
1699
+ return value.call(property ? withProps(this, { [property]: ctx }) : this);
1700
+ });
1701
+ });
1702
+ });
1703
+ } else throw new Error("@Inject() can only be used on class or class methods");
1704
+ };
1705
+ }
1706
+ /** Utilities for normalizing plugin dependency declarations. */
1707
+ (function(Inject) {
1708
+ /**
1709
+ * Convert array/object/class-inherited inject metadata into a plain map.
1710
+ *
1711
+ * @param inject — the declaration to normalize; `null`/`undefined` add nothing.
1712
+ * @param result — the map to fill (service name → intercept config or `null`).
1713
+ * @returns `result`.
1714
+ */
1715
+ function resolve(inject, result = Object.create(null)) {
1716
+ if (!inject) return result;
1717
+ if (Array.isArray(inject)) for (const name of inject) result[name] = null;
1718
+ else if (Reflect.has(inject, symbols.checkProto)) {
1719
+ Object.assign(result, resolve(Object.getPrototypeOf(inject)));
1720
+ for (const name of Object.keys(inject)) result[name] = inject[name] ?? null;
1721
+ } else for (const name of Object.keys(inject)) result[name] = inject[name] ?? null;
1722
+ return result;
1723
+ }
1724
+ Inject.resolve = resolve;
1725
+ })(Inject || (Inject = {}));
1726
+ /**
1727
+ * Plugin registry installed as `ctx.registry` and mixed into every context.
1728
+ *
1729
+ * It normalizes plugin shapes, tracks plugin runtimes, starts fibers, and
1730
+ * exposes map-like inspection over active plugin callbacks.
1731
+ */
1732
+ var RegistryService = class {
1733
+ ctx;
1734
+ _counter = 0;
1735
+ _internal = /* @__PURE__ */ new Map();
1736
+ constructor(ctx) {
1737
+ this.ctx = ctx;
1738
+ defineProperty(this, symbols.tracker, {
1739
+ property: "ctx",
1740
+ noShadow: true
1741
+ });
1742
+ }
1743
+ /** Allocate the next fiber uid (increments on every read). */
1744
+ get counter() {
1745
+ return ++this._counter;
1746
+ }
1747
+ /** Number of registered plugin runtimes. */
1748
+ get size() {
1749
+ return this._internal.size;
1750
+ }
1751
+ /**
1752
+ * Resolve a supported plugin shape to its executable callback.
1753
+ *
1754
+ * @param plugin — a function, class, or `{ apply }` object plugin.
1755
+ * @returns the callback identifying the plugin, or `undefined` if invalid.
1756
+ */
1757
+ resolve(plugin) {
1758
+ try {
1759
+ if (typeof plugin === "function") return plugin;
1760
+ if (isApplicable(plugin)) return plugin.apply;
1761
+ } catch {}
1762
+ }
1763
+ /**
1764
+ * Look up the runtime record for a plugin.
1765
+ *
1766
+ * @param plugin — any supported plugin shape.
1767
+ * @returns the runtime, or `undefined` when the plugin is not registered.
1768
+ */
1769
+ get(plugin) {
1770
+ const key = this.resolve(plugin);
1771
+ return key && this._internal.get(key);
1772
+ }
1773
+ /**
1774
+ * Check whether a plugin has a registered runtime.
1775
+ *
1776
+ * @param plugin — any supported plugin shape.
1777
+ * @returns `true` when at least one fiber of the plugin exists.
1778
+ */
1779
+ has(plugin) {
1780
+ const key = this.resolve(plugin);
1781
+ return !!key && this._internal.has(key);
1782
+ }
1783
+ /**
1784
+ * Dispose every running fiber for a plugin and remove its runtime record.
1785
+ *
1786
+ * @param plugin — any supported plugin shape.
1787
+ * @returns the removed runtime, or `undefined` when none was registered.
1788
+ */
1789
+ delete(plugin) {
1790
+ const key = this.resolve(plugin);
1791
+ const runtime = key && this._internal.get(key);
1792
+ if (!runtime) return;
1793
+ this._internal.delete(key);
1794
+ for (const fiber of runtime.fibers) fiber.dispose();
1795
+ return runtime;
1796
+ }
1797
+ /** Iterate the registered plugin callbacks. */
1798
+ keys() {
1799
+ return this._internal.keys();
1800
+ }
1801
+ /** Iterate the registered plugin runtimes. */
1802
+ values() {
1803
+ return this._internal.values();
1804
+ }
1805
+ /** Iterate `[callback, runtime]` pairs. */
1806
+ entries() {
1807
+ return this._internal.entries();
1808
+ }
1809
+ /**
1810
+ * Visit every registered runtime.
1811
+ *
1812
+ * @param callback — receives each runtime and its identifying callback.
1813
+ */
1814
+ forEach(callback) {
1815
+ return this._internal.forEach(callback);
1816
+ }
1817
+ /**
1818
+ * Start a callback once the requested dependencies are available.
1819
+ *
1820
+ * @param inject — required services, as an array or a name → config map.
1821
+ * @param callback — plugin body called with `(ctx, config)`.
1822
+ * @returns the fiber; awaiting it settles once loading finished.
1823
+ */
1824
+ inject(inject, callback) {
1825
+ return this.plugin({
1826
+ inject,
1827
+ apply: callback,
1828
+ name: callback.name
1829
+ });
1830
+ }
1831
+ /**
1832
+ * Start a plugin in the current context and return its fiber.
1833
+ *
1834
+ * Creates (or reuses) the plugin's runtime record, then starts a new fiber
1835
+ * under the current context. Throws if `plugin` is not a supported shape or
1836
+ * if the current fiber is already disposed.
1837
+ *
1838
+ * @param plugin — a function, class, or `{ apply }` object plugin.
1839
+ * @param config — the plugin config, validated against its `Config` schema.
1840
+ * @param getOuterStack — captures the caller stack for effect diagnostics.
1841
+ * @returns the fiber; awaiting it settles once loading finished.
1842
+ */
1843
+ plugin(plugin, config, getOuterStack = buildOuterStack()) {
1844
+ const callback = this.resolve(plugin);
1845
+ if (!callback) throw new Error("invalid plugin, expect function or object with an \"apply\" method, received " + typeof plugin);
1846
+ this.ctx.fiber.assertActive();
1847
+ let runtime = this._internal.get(callback);
1848
+ if (!runtime) {
1849
+ let name = plugin.name;
1850
+ if (name === "apply") name = void 0;
1851
+ runtime = {
1852
+ name,
1853
+ callback,
1854
+ fibers: new DisposableList(),
1855
+ Config: plugin.Config
1856
+ };
1857
+ this._internal.set(callback, runtime);
1858
+ }
1859
+ const fiber = new Fiber(this.ctx, config, Inject.resolve(plugin.inject), runtime, getOuterStack);
1860
+ const wrapped = Object.create(fiber);
1861
+ wrapped.then = (onFulfilled, onRejected) => {
1862
+ return fiber.await().then(onFulfilled, onRejected);
1863
+ };
1864
+ return wrapped;
1865
+ }
1866
+ };
1867
+ /**
1868
+ * Root and child dependency containers for Cordis plugins.
1869
+ *
1870
+ * A context is a proxy: normal property reads go through the service resolver,
1871
+ * while `extend()`, `isolate()`, and `intercept()` create scoped child
1872
+ * contexts without mutating their parent.
1873
+ */
1874
+ var Context = class Context {
1875
+ /** Symbol key under which a disposer exposes its {@link EffectMeta} diagnostics tree. */
1876
+ static effect = symbols.effect;
1877
+ /** Symbol key for a context's listener filter, consulted on every event dispatch. */
1878
+ static filter = symbols.filter;
1879
+ /** Symbol key of the isolation map (see the `Context[symbols.isolate]` property). */
1880
+ static isolate = symbols.isolate;
1881
+ /** Symbol key of the intercept map (see the `Context[symbols.intercept]` property). */
1882
+ static intercept = symbols.intercept;
1883
+ /**
1884
+ * Returns true for Cordis context proxies and context prototypes.
1885
+ *
1886
+ * Works across realms and across multiple copies of cordis, because the
1887
+ * brand is keyed by a global symbol rather than by `instanceof`.
1888
+ *
1889
+ * @param value — the value to test.
1890
+ * @returns `true` if `value` is a Cordis context, narrowing its type.
1891
+ */
1892
+ static is(value) {
1893
+ return !!value?.[Context.is];
1894
+ }
1895
+ static {
1896
+ Context.is[Symbol.toPrimitive] = () => Symbol.for("cordis.is");
1897
+ Context.prototype[Context.is] = true;
1898
+ }
1899
+ /** Create the root context and install the built-in services. */
1900
+ constructor() {
1901
+ this[symbols.isolate] = Object.create(null);
1902
+ this[symbols.intercept] = Object.create(null);
1903
+ const self = new Proxy(this, ReflectService.handler);
1904
+ this.root = self;
1905
+ this.baseUrl = void 0;
1906
+ this.fiber = new Fiber(self, {}, Object.create(null), null, () => []);
1907
+ this.reflect = new ReflectService(self);
1908
+ this.registry = new RegistryService(self);
1909
+ this.events = new EventsService(self);
1910
+ this.logger = new LoggerService(self);
1911
+ this.fiber._disposables.clear();
1912
+ return self;
1913
+ }
1914
+ [Symbol.for("nodejs.util.inspect.custom")]() {
1915
+ return `Context <${this.fiber.name}>`;
1916
+ }
1917
+ /**
1918
+ * Create a child context with extra metadata on top of the current scope.
1919
+ *
1920
+ * The child prototypally inherits every property of this context; own
1921
+ * properties of `meta` shadow the inherited ones. The parent is not mutated.
1922
+ *
1923
+ * @param meta — own properties (including symbol keys) to define on the child.
1924
+ * @returns a child context inheriting from this one.
1925
+ */
1926
+ extend(meta = {}) {
1927
+ const shadow = Reflect.getOwnPropertyDescriptor(this, symbols.shadow)?.value;
1928
+ const self = Object.create(getTraceable(this, this));
1929
+ for (const prop of Reflect.ownKeys(meta)) Object.defineProperty(self, prop, Reflect.getOwnPropertyDescriptor(meta, prop));
1930
+ if (!shadow) return self;
1931
+ return Object.assign(Object.create(self), { [symbols.shadow]: shadow });
1932
+ }
1933
+ /**
1934
+ * Create a child context with an independent service scope for `name`.
1935
+ *
1936
+ * Below the returned context, reads and writes of the service `name`
1937
+ * resolve against the new label instead of the parent's, so a different
1938
+ * implementation can be provided without affecting the parent scope.
1939
+ * Passing the same `label` to two `isolate()` calls joins their scopes.
1940
+ *
1941
+ * @param name — the service name to isolate.
1942
+ * @param label — scope label to join; defaults to a fresh unique symbol.
1943
+ * @returns a child context whose `name` service resolves in the new scope.
1944
+ */
1945
+ isolate(name, label) {
1946
+ const shadow = Object.create(this[symbols.isolate]);
1947
+ shadow[name] = label ?? Symbol(name);
1948
+ return this.extend({ [symbols.isolate]: shadow });
1949
+ }
1950
+ intercept(name, config) {
1951
+ const intercept = Object.create(this[symbols.intercept]);
1952
+ intercept[name] = config;
1953
+ return this.extend({ [symbols.intercept]: intercept });
1954
+ }
1955
+ };
1956
+ /**
1957
+ * Base class for services that expose a named API on `ctx`.
1958
+ *
1959
+ * Subclasses call `super(ctx, name)` from their constructor. The service is
1960
+ * registered immediately and is automatically removed with the owning fiber.
1961
+ */
1962
+ var Service = class Service {
1963
+ ctx;
1964
+ /** Symbol key of an instance method run after construction (class plugins). */
1965
+ static init = symbols.init;
1966
+ /** Symbol key of the availability predicate passed to `ctx.provide()`. */
1967
+ static check = symbols.check;
1968
+ /** Symbol key of the phantom intercept-config type parameter. */
1969
+ static config = symbols.config;
1970
+ /** Symbol key of the call body making a service callable (e.g. `ctx.logger()`). */
1971
+ static invoke = symbols.invoke;
1972
+ /** Symbol key of the helper deriving an extended service instance. */
1973
+ static extend = symbols.extend;
1974
+ /** Symbol key of the tracker metadata used for context tracing. */
1975
+ static tracker = symbols.tracker;
1976
+ /** Symbol key of the intercept-config resolution helper below. */
1977
+ static resolveConfig = symbols.resolveConfig;
1978
+ /** The service name this instance is registered under. */
1979
+ name;
1980
+ /**
1981
+ * Register this instance as `name` in the current context.
1982
+ *
1983
+ * Calls `ctx.reflect.provide(name, this, this[Service.check])`, so the
1984
+ * service is unregistered automatically when the owning fiber unloads.
1985
+ * Services with a `[Service.invoke]` body return a callable instance.
1986
+ *
1987
+ * @param ctx — the context to register in (stored as `this.ctx`).
1988
+ * @param name — the service name; defaults to the static `provide` field.
1989
+ */
1990
+ constructor(ctx, name) {
1991
+ this.ctx = ctx;
1992
+ name ??= this.constructor["provide"];
1993
+ let self = this;
1994
+ const tracker = {
1995
+ associate: name,
1996
+ property: "ctx"
1997
+ };
1998
+ if (self[symbols.invoke]) self = createCallable(name, joinPrototype(Object.getPrototypeOf(this), Function.prototype), tracker);
1999
+ self.ctx = ctx;
2000
+ self.name = name;
2001
+ defineProperty(self, symbols.tracker, tracker);
2002
+ self.ctx.reflect.provide(name, self, this[symbols.check]);
2003
+ return self;
2004
+ }
2005
+ [symbols.filter](ctx) {
2006
+ return ctx[symbols.isolate][this.name] === this.ctx[symbols.isolate][this.name];
2007
+ }
2008
+ [symbols.extend](props) {
2009
+ let self;
2010
+ if (this[Service.invoke]) self = createCallable(this.name, this, this[symbols.tracker]);
2011
+ else self = Object.create(this);
2012
+ return Object.assign(self, props);
2013
+ }
2014
+ /**
2015
+ * Merge intercept config from ancestors with optional base and head values.
2016
+ *
2017
+ * Entries added closer to the root apply first; `base` is prepended and
2018
+ * `head` appended. Uses `Config.merge` when the service declares one,
2019
+ * otherwise a shallow `Object.assign`.
2020
+ *
2021
+ * @param base — lowest-precedence config merged before all intercepts.
2022
+ * @param head — highest-precedence config merged after all intercepts.
2023
+ * @returns the merged config.
2024
+ */
2025
+ [symbols.resolveConfig](base, head) {
2026
+ let intercept = this.ctx[Context.intercept];
2027
+ const configs = [];
2028
+ while (this.name in intercept) {
2029
+ if (Object.hasOwn(intercept, this.name)) configs.unshift(intercept[this.name]);
2030
+ intercept = Object.getPrototypeOf(intercept);
2031
+ }
2032
+ if (base) configs.unshift(base);
2033
+ if (head) configs.push(head);
2034
+ if (this["Config"]?.merge) return this["Config"].merge(...configs);
2035
+ else return Object.assign({}, ...configs);
2036
+ }
2037
+ static [Symbol.hasInstance](instance) {
2038
+ if (!instance) return false;
2039
+ let constructor = instance.constructor;
2040
+ while (constructor) {
2041
+ constructor = constructor.prototype?.constructor;
2042
+ if (constructor === this) return true;
2043
+ constructor &&= Object.getPrototypeOf(constructor);
2044
+ }
2045
+ return false;
2046
+ }
2047
+ };
2048
+ //#endregion
2049
+ //#region node_modules/.pnpm/@deepseek-ai+dsh-typert-protocol@0.1.5-rc.2_@deepseek-ai+cordis@4.0.2/node_modules/@deepseek-ai/dsh-typert-protocol/lib/index.js
2050
+ /** The one Remote failure class shared by owners, the Gateway, and consumers. */
2051
+ /**
2052
+ * One Remote call failure: a real Error carrying its stable code and typed
2053
+ * details. Owners throw it at the failure point; the Host Gateway encodes it
2054
+ * onto the wire unchanged; the Client face rebuilds an instance for the
2055
+ * `RemoteResult` error branch, so `throw result.error` keeps throw semantics.
2056
+ * Discrimination is always by `code`, never by instanceof.
2057
+ */
2058
+ var RemoteError = class extends Error {
2059
+ code;
2060
+ details;
2061
+ /** Structural marker: cross-realm/bundle identification never uses instanceof. */
2062
+ isDSHRemoteError = true;
2063
+ /**
2064
+ * @param code - stable failure code declared in {@link RemoteErrorDetailsMap}.
2065
+ * @param message - human diagnostic carried across the wire.
2066
+ * @param details - structured payload typed by the code.
2067
+ * @param options - standard Error options (`cause` survives in-process only).
2068
+ */
2069
+ constructor(code, message, details, options) {
2070
+ super(message, options);
2071
+ this.code = code;
2072
+ this.details = details;
2073
+ this.name = "RemoteError";
2074
+ }
2075
+ };
2076
+ /**
2077
+ * Remote decorators and explicit Gateway bindings backed by versioned
2078
+ * descriptors carried on decorated class prototypes. Strict reflection
2079
+ * remains a Typert compiler responsibility.
2080
+ * @module @deepseek-ai/dsh-typert-protocol
2081
+ */
2082
+ const TYPERT_REMOTE_SEGMENT_PATTERN = /^[A-Za-z0-9_$.-]+$/;
2083
+ /**
2084
+ * Test one generated Remote name against the Connection endpoint grammar.
2085
+ * @param value - namespace, method, lookup, or Context segment.
2086
+ * @returns whether the value can cross the shared RPC carrier unchanged.
2087
+ */
2088
+ function isTypertRemoteSegment(value) {
2089
+ return value !== "." && value !== ".." && TYPERT_REMOTE_SEGMENT_PATTERN.test(value);
2090
+ }
2091
+ const REMOTE_METHOD_DESCRIPTOR = "@deepseek-ai/dsh-typert-protocol/remote-methods";
2092
+ /**
2093
+ * Bind one visible Service field to a Cordis key and Remote namespace.
2094
+ * @param service - owning Service instance, normally `this`.
2095
+ * @param serviceKey - exact Cordis service key.
2096
+ * @param options - optional distinct wire namespace.
2097
+ * @returns a frozen, inspectable binding with no compiler-injected metadata.
2098
+ */
2099
+ function bindTypertRemote(service, serviceKey, options = {}) {
2100
+ validateName("service key", serviceKey);
2101
+ const namespace = options.namespace ?? serviceKey;
2102
+ validateName("namespace", namespace);
2103
+ return Object.freeze({
2104
+ service,
2105
+ serviceKey,
2106
+ namespace
2107
+ });
2108
+ }
2109
+ /** Cordis Service base that exposes its registered name through Typert Gateway. */
2110
+ var TypertRemoteService = class extends Service {
2111
+ /** Visible binding consumed by the Gateway's source-mode discovery. */
2112
+ typertRemote;
2113
+ /**
2114
+ * Register the Service and bind the same key to Typert Gateway.
2115
+ * @param ctx - owning Cordis Context.
2116
+ * @param serviceKey - exact Cordis service key and default wire namespace.
2117
+ * @param options - optional distinct wire namespace.
2118
+ */
2119
+ constructor(ctx, serviceKey, options = {}) {
2120
+ super(ctx, serviceKey);
2121
+ this.typertRemote = bindTypertRemote(this, this.name, options);
2122
+ }
2123
+ };
2124
+ function Remote(methodExportOrOptions, context) {
2125
+ if (typeof methodExportOrOptions === "string") {
2126
+ validateName("Remote export name", methodExportOrOptions);
2127
+ return remoteDecorator({ kind: "direct" }, void 0, methodExportOrOptions);
2128
+ }
2129
+ if (typeof methodExportOrOptions === "object") {
2130
+ if (remoteOptionMode(methodExportOrOptions) !== "stream" || Reflect.ownKeys(methodExportOrOptions).length !== 1) throw new TypeError("typert-protocol: Remote options must contain exactly mode: \"stream\"");
2131
+ return remoteDecorator({ kind: "direct" }, "stream");
2132
+ }
2133
+ if (context === void 0) throw new TypeError("typert-protocol: Remote decorator context is missing");
2134
+ addMarkerInitializer(context, { kind: "direct" });
2135
+ }
2136
+ function remoteOptionMode(options) {
2137
+ return Reflect.get(options, "mode");
2138
+ }
2139
+ function remoteDecorator(invocation, mode, exportName) {
2140
+ return function(_method, context) {
2141
+ addMarkerInitializer(context, invocation, mode, exportName);
2142
+ };
2143
+ }
2144
+ function readRemoteMethodDescriptor(prototype) {
2145
+ const property = Object.getOwnPropertyDescriptor(prototype, REMOTE_METHOD_DESCRIPTOR);
2146
+ if (property === void 0) return void 0;
2147
+ const descriptor = property.value;
2148
+ if (descriptor === null || typeof descriptor !== "object") throw new TypeError("typert-protocol: Remote method descriptor must be an object");
2149
+ const version = Reflect.get(descriptor, "version");
2150
+ if (version !== 1) throw new TypeError(`typert-protocol: unsupported Remote method descriptor version ${String(version)}`);
2151
+ const methods = Reflect.get(descriptor, "methods");
2152
+ if (!Array.isArray(methods)) throw new TypeError("typert-protocol: Remote method descriptor methods must be an array");
2153
+ return descriptor;
2154
+ }
2155
+ function addMarkerInitializer(context, invocation, mode, exportName) {
2156
+ if (context.private || context.static || typeof context.name !== "string") throw new TypeError("typert-protocol: Remote decorators require a public instance method with a string name");
2157
+ const method = context.name;
2158
+ context.addInitializer(function() {
2159
+ const prototype = Object.getPrototypeOf(this);
2160
+ if (prototype === null) throw new TypeError(`typert-protocol: cannot mark Remote method "${method}" on an object without a prototype`);
2161
+ mark(prototype, method, invocation, mode, exportName);
2162
+ });
2163
+ }
2164
+ function mark(prototype, method, invocation, mode, exportName) {
2165
+ const descriptor = readRemoteMethodDescriptor(prototype);
2166
+ const marker = Object.freeze({
2167
+ method,
2168
+ ...exportName === void 0 || exportName === method ? {} : { exportName },
2169
+ ...mode === void 0 ? {} : { mode },
2170
+ invocation: Object.freeze(invocation)
2171
+ });
2172
+ const current = descriptor?.methods.find((candidate) => candidate.method === method);
2173
+ if (current !== void 0) {
2174
+ if (current.exportName === marker.exportName && current.mode === marker.mode && sameInvocation(current.invocation, invocation)) return;
2175
+ throw new Error(`typert-protocol: Remote method "${method}" has conflicting invocation markers`);
2176
+ }
2177
+ Object.defineProperty(prototype, REMOTE_METHOD_DESCRIPTOR, {
2178
+ configurable: true,
2179
+ value: Object.freeze({
2180
+ version: 1,
2181
+ methods: Object.freeze([...descriptor?.methods ?? [], marker])
2182
+ })
2183
+ });
2184
+ }
2185
+ function sameInvocation(left, right) {
2186
+ if (left.kind === "direct") return right.kind === "direct";
2187
+ if (right.kind === "direct") return false;
2188
+ return left.context === right.context;
2189
+ }
2190
+ function validateName(subject, value) {
2191
+ if (!isTypertRemoteSegment(value)) throw new TypeError(`typert-protocol: ${subject} must contain only RPC endpoint segment characters`);
2192
+ }
2193
+ //#endregion
2194
+ //#region node_modules/.pnpm/@deepseek-ai+dsh-util-values@0.1.5-rc.2_@deepseek-ai+cordis@4.0.2/node_modules/@deepseek-ai/dsh-util-values/lib/index.js
2195
+ /**
2196
+ * Deep-freeze an object graph in place while leaving live AbortSignal objects mutable.
2197
+ * @param value - value to freeze.
2198
+ * @returns the same value after every reachable enumerable child is frozen.
2199
+ */
2200
+ function deepFreeze(value) {
2201
+ const seen = /* @__PURE__ */ new WeakSet();
2202
+ const pending = [{
2203
+ kind: "visit",
2204
+ node: value
2205
+ }];
2206
+ while (pending.length > 0) {
2207
+ const task = pending.pop();
2208
+ /* v8 ignore next -- the loop condition guarantees one pending task. */
2209
+ if (task === void 0) continue;
2210
+ if (task.kind === "property") {
2211
+ pending.push({
2212
+ kind: "visit",
2213
+ node: task.source[task.key]
2214
+ });
2215
+ continue;
2216
+ }
2217
+ const node = task.node;
2218
+ if (node === null || typeof node !== "object") continue;
2219
+ if (node instanceof AbortSignal) continue;
2220
+ if (seen.has(node)) continue;
2221
+ seen.add(node);
2222
+ Object.freeze(node);
2223
+ const keys = Object.keys(node);
2224
+ for (let index = keys.length - 1; index >= 0; index--) {
2225
+ const key = keys[index];
2226
+ /* v8 ignore next -- the loop is bounded by the captured key count. */
2227
+ if (key === void 0) continue;
2228
+ pending.push({
2229
+ kind: "property",
2230
+ source: node,
2231
+ key
2232
+ });
2233
+ }
2234
+ }
2235
+ return value;
2236
+ }
2237
+ //#endregion
2238
+ //#region node_modules/.pnpm/@deepseek-ai+dsh-util-crypto@0.1.5-rc.2_@deepseek-ai+cordis@4.0.2/node_modules/@deepseek-ai/dsh-util-crypto/lib/index.js
2239
+ /**
2240
+ * Random v4 UUID, minted from `crypto.getRandomValues`.
2241
+ * @returns the UUID string.
2242
+ */
2243
+ function randomUUID() {
2244
+ const bytes = globalThis.crypto.getRandomValues(/* @__PURE__ */ new Uint8Array(16));
2245
+ const hex = Array.from(bytes, (byte, index) => {
2246
+ return (index === 6 ? byte & 15 | 64 : index === 8 ? byte & 63 | 128 : byte).toString(16).padStart(2, "0");
2247
+ }).join("");
2248
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
2249
+ }
2250
+ //#endregion
2251
+ //#region node_modules/.pnpm/@deepseek-ai+dsh-brand@0.1.5-rc.2_@deepseek-ai+cordis@4.0.2/node_modules/@deepseek-ai/dsh-brand/lib/index.js
2252
+ /**
2253
+ * Duplicate-install-safe nominal primitive helpers.
2254
+ *
2255
+ * A brand makes structurally identical strings or numbers non-interchangeable
2256
+ * at the type level: a `SessionId` cannot be passed where a `ToolCallId` is
2257
+ * expected, and an event sequence cannot be passed as a log offset. Comparison,
2258
+ * logging, and serialization retain the underlying primitive behavior.
2259
+ *
2260
+ * This package owns no concrete domain value and keeps no runtime identity or mutable
2261
+ * state, so independently installed copies produce interchangeable values.
2262
+ *
2263
+ * @module @deepseek-ai/dsh-brand
2264
+ */
2265
+ /**
2266
+ * Apply a compile-time string brand without changing the value.
2267
+ * @param value - string admitted by the domain that owns the target brand.
2268
+ * @returns the same string with the requested compile-time brand.
2269
+ */
2270
+ function brandString(value) {
2271
+ return value;
2272
+ }
2273
+ //#endregion
2274
+ //#region node_modules/.pnpm/@deepseek-ai+schemastery@3.18.2/node_modules/@deepseek-ai/schemastery/lib/index.mjs
2275
+ const kSchema = Symbol.for("schemastery");
2276
+ const kValidationError = Symbol.for("ValidationError");
2277
+ globalThis.__schemastery_index__ ??= 0;
2278
+ globalThis.__schemastery_refs__ = void 0;
2279
+ var ValidationError = class extends TypeError {
2280
+ options;
2281
+ name = "ValidationError";
2282
+ constructor(message, options) {
2283
+ let prefix = "$";
2284
+ for (const segment of options.path || []) if (typeof segment === "string") prefix += "." + segment;
2285
+ else if (typeof segment === "number") prefix += "[" + segment + "]";
2286
+ else if (typeof segment === "symbol") prefix += `[Symbol(${segment.toString()})]`;
2287
+ if (prefix.startsWith(".")) prefix = prefix.slice(1);
2288
+ super((prefix === "$" ? "" : `${prefix} `) + message);
2289
+ this.options = options;
2290
+ }
2291
+ static is(error) {
2292
+ return !!error?.[kValidationError];
2293
+ }
2294
+ };
2295
+ Object.defineProperty(ValidationError.prototype, kValidationError, { value: true });
2296
+ const Schema = function(options) {
2297
+ const schema = function(data, options = {}) {
2298
+ return Schema.resolve(data, schema, options)[0];
2299
+ };
2300
+ if (options.refs) {
2301
+ const refs = mapValues(options.refs, (options) => new Schema(options));
2302
+ const getRef = (uid) => refs[uid];
2303
+ for (const key in refs) {
2304
+ const options = refs[key];
2305
+ options.sKey = getRef(options.sKey);
2306
+ options.inner = getRef(options.inner);
2307
+ options.list = options.list && options.list.map(getRef);
2308
+ options.dict = options.dict && mapValues(options.dict, getRef);
2309
+ }
2310
+ return refs[options.uid];
2311
+ }
2312
+ Object.assign(schema, options);
2313
+ if (typeof schema.callback === "string") try {
2314
+ schema.callback = new Function("return " + schema.callback)();
2315
+ } catch {}
2316
+ Object.defineProperty(schema, "uid", { value: globalThis.__schemastery_index__++ });
2317
+ Object.setPrototypeOf(schema, Schema.prototype);
2318
+ schema.meta ||= {};
2319
+ schema.toString = schema.toString.bind(schema);
2320
+ return schema;
2321
+ };
2322
+ Schema.prototype = Object.create(Function.prototype);
2323
+ Schema.prototype[kSchema] = true;
2324
+ Object.defineProperty(Schema.prototype, "~standard", { get() {
2325
+ return {
2326
+ version: 1,
2327
+ vendor: "schemastery",
2328
+ validate: (value) => {
2329
+ try {
2330
+ return { value: Schema.resolve(value, this, {})[0] };
2331
+ } catch (error) {
2332
+ if (ValidationError.is(error)) return { issues: [{
2333
+ message: error.message,
2334
+ path: error.options.path
2335
+ }] };
2336
+ throw error;
2337
+ }
2338
+ }
2339
+ };
2340
+ } });
2341
+ Schema.ValidationError = ValidationError;
2342
+ Schema.prototype.toJSON = function toJSON() {
2343
+ if (globalThis.__schemastery_refs__) {
2344
+ globalThis.__schemastery_refs__[this.uid] ??= JSON.parse(JSON.stringify({ ...this }));
2345
+ return this.uid;
2346
+ }
2347
+ globalThis.__schemastery_refs__ = { [this.uid]: { ...this } };
2348
+ globalThis.__schemastery_refs__[this.uid] = JSON.parse(JSON.stringify({ ...this }));
2349
+ const result = {
2350
+ uid: this.uid,
2351
+ refs: globalThis.__schemastery_refs__
2352
+ };
2353
+ globalThis.__schemastery_refs__ = void 0;
2354
+ return result;
2355
+ };
2356
+ Schema.prototype.set = function set(key, value) {
2357
+ this.dict[key] = value;
2358
+ return this;
2359
+ };
2360
+ Schema.prototype.push = function push(value) {
2361
+ this.list.push(value);
2362
+ return this;
2363
+ };
2364
+ function mergeDesc(original, messages) {
2365
+ const result = typeof original === "string" ? { "": original } : { ...original };
2366
+ for (const locale in messages) {
2367
+ const value = messages[locale];
2368
+ if (value?.$description || value?.$desc) result[locale] = value.$description || value.$desc;
2369
+ else if (typeof value === "string") result[locale] = value;
2370
+ }
2371
+ return result;
2372
+ }
2373
+ function getInner(value) {
2374
+ return value?.$value ?? value?.$inner;
2375
+ }
2376
+ function extractKeys(data) {
2377
+ return filterKeys(data ?? {}, (key) => !key.startsWith("$"));
2378
+ }
2379
+ Schema.prototype.i18n = function i18n(messages) {
2380
+ const schema = Schema(this);
2381
+ const desc = mergeDesc(schema.meta.description, messages);
2382
+ if (Object.keys(desc).length) schema.meta.description = desc;
2383
+ if (schema.dict) schema.dict = mapValues(schema.dict, (inner, key) => {
2384
+ return inner.i18n(mapValues(messages, (data) => getInner(data)?.[key] ?? data?.[key]));
2385
+ });
2386
+ if (schema.list) schema.list = schema.list.map((inner, index) => {
2387
+ return inner.i18n(mapValues(messages, (data = {}) => {
2388
+ if (Array.isArray(getInner(data))) return getInner(data)[index];
2389
+ if (Array.isArray(data)) return data[index];
2390
+ return extractKeys(data);
2391
+ }));
2392
+ });
2393
+ if (schema.inner) schema.inner = schema.inner.i18n(mapValues(messages, (data) => {
2394
+ if (getInner(data)) return getInner(data);
2395
+ return extractKeys(data);
2396
+ }));
2397
+ if (schema.sKey) schema.sKey = schema.sKey.i18n(mapValues(messages, (data) => data?.$key));
2398
+ return schema;
2399
+ };
2400
+ Schema.prototype.extra = function extra(key, value) {
2401
+ const schema = Schema(this);
2402
+ schema.meta = {
2403
+ ...schema.meta,
2404
+ [key]: value
2405
+ };
2406
+ return schema;
2407
+ };
2408
+ for (const key of [
2409
+ "required",
2410
+ "disabled",
2411
+ "collapse",
2412
+ "hidden",
2413
+ "loose"
2414
+ ]) Object.assign(Schema.prototype, { [key](value = true) {
2415
+ const schema = Schema(this);
2416
+ schema.meta = {
2417
+ ...schema.meta,
2418
+ [key]: value
2419
+ };
2420
+ return schema;
2421
+ } });
2422
+ Schema.prototype.deprecated = function deprecated() {
2423
+ const schema = Schema(this);
2424
+ schema.meta.badges ||= [];
2425
+ schema.meta.badges.push({
2426
+ text: "deprecated",
2427
+ type: "danger"
2428
+ });
2429
+ return schema;
2430
+ };
2431
+ Schema.prototype.experimental = function experimental() {
2432
+ const schema = Schema(this);
2433
+ schema.meta.badges ||= [];
2434
+ schema.meta.badges.push({
2435
+ text: "experimental",
2436
+ type: "warning"
2437
+ });
2438
+ return schema;
2439
+ };
2440
+ Schema.prototype.pattern = function pattern(regexp) {
2441
+ const schema = Schema(this);
2442
+ const pattern = pick(regexp, ["source", "flags"]);
2443
+ schema.meta = {
2444
+ ...schema.meta,
2445
+ pattern
2446
+ };
2447
+ return schema;
2448
+ };
2449
+ Schema.prototype.simplify = function simplify(value) {
2450
+ if (deepEqual(value, this.meta.default, this.type === "dict")) return null;
2451
+ if (isNullable(value)) return value;
2452
+ if (this.type === "object" || this.type === "dict") {
2453
+ const result = {};
2454
+ for (const key in value) {
2455
+ const item = (this.type === "object" ? this.dict[key] : this.inner)?.simplify(value[key]);
2456
+ if (this.type === "dict" || !isNullable(item)) result[key] = item;
2457
+ }
2458
+ if (deepEqual(result, this.meta.default, this.type === "dict")) return null;
2459
+ return result;
2460
+ } else if (this.type === "array" || this.type === "tuple") {
2461
+ const result = [];
2462
+ value.forEach((value, index) => {
2463
+ const schema = this.type === "array" ? this.inner : this.list[index];
2464
+ const item = schema ? schema.simplify(value) : value;
2465
+ result.push(item);
2466
+ });
2467
+ return result;
2468
+ } else if (this.type === "intersect") {
2469
+ const result = {};
2470
+ for (const item of this.list) Object.assign(result, item.simplify(value));
2471
+ return result;
2472
+ } else if (this.type === "union") for (const schema of this.list) try {
2473
+ Schema.resolve(value, schema, {});
2474
+ return schema.simplify(value);
2475
+ } catch {}
2476
+ return value;
2477
+ };
2478
+ Schema.prototype.toString = function toString(inline) {
2479
+ return formatters[this.type]?.(this, inline) ?? `Schema<${this.type}>`;
2480
+ };
2481
+ Schema.prototype.role = function role(role, extra) {
2482
+ const schema = Schema(this);
2483
+ schema.meta = {
2484
+ ...schema.meta,
2485
+ role,
2486
+ extra
2487
+ };
2488
+ return schema;
2489
+ };
2490
+ for (const key of [
2491
+ "default",
2492
+ "link",
2493
+ "comment",
2494
+ "description",
2495
+ "max",
2496
+ "min",
2497
+ "step"
2498
+ ]) Object.assign(Schema.prototype, { [key](value) {
2499
+ const schema = Schema(this);
2500
+ schema.meta = {
2501
+ ...schema.meta,
2502
+ [key]: value
2503
+ };
2504
+ return schema;
2505
+ } });
2506
+ const resolvers = {};
2507
+ Schema.extend = function extend(type, resolve) {
2508
+ resolvers[type] = resolve;
2509
+ };
2510
+ Schema.resolve = function resolve(data, schema, options = {}, strict = false) {
2511
+ if (!schema) return [data];
2512
+ if (options.ignore?.(data, schema)) return [data];
2513
+ if (isNullable(data) && schema.type !== "lazy") {
2514
+ if (schema.meta.required) throw new ValidationError(`missing required value`, options);
2515
+ let current = schema;
2516
+ let fallback = schema.meta.default;
2517
+ while (current?.type === "intersect" && isNullable(fallback)) {
2518
+ current = current.list[0];
2519
+ fallback = current?.meta.default;
2520
+ }
2521
+ if (isNullable(fallback)) return [data];
2522
+ data = clone(fallback);
2523
+ }
2524
+ const callback = resolvers[schema.type];
2525
+ if (!callback) throw new ValidationError(`unsupported type "${schema.type}"`, options);
2526
+ try {
2527
+ return callback(data, schema, options, strict);
2528
+ } catch (error) {
2529
+ if (!schema.meta.loose) throw error;
2530
+ return [schema.meta.default];
2531
+ }
2532
+ };
2533
+ Schema.from = function from(source) {
2534
+ if (isNullable(source)) return Schema.any();
2535
+ else if ([
2536
+ "string",
2537
+ "number",
2538
+ "boolean"
2539
+ ].includes(typeof source)) return Schema.const(source).required();
2540
+ else if (source[kSchema]) return source;
2541
+ else if (typeof source === "function") switch (source) {
2542
+ case String: return Schema.string().required();
2543
+ case Number: return Schema.number().required();
2544
+ case Boolean: return Schema.boolean().required();
2545
+ case Function: return Schema.function().required();
2546
+ default: return Schema.is(source).required();
2547
+ }
2548
+ else throw new TypeError(`cannot infer schema from ${source}`);
2549
+ };
2550
+ Schema.lazy = function lazy(builder) {
2551
+ const toJSON = () => {
2552
+ if (!schema.inner[kSchema]) {
2553
+ schema.inner = schema.builder();
2554
+ schema.inner.meta = {
2555
+ ...schema.meta,
2556
+ ...schema.inner.meta
2557
+ };
2558
+ }
2559
+ return schema.inner.toJSON();
2560
+ };
2561
+ const schema = new Schema({
2562
+ type: "lazy",
2563
+ builder,
2564
+ inner: { toJSON }
2565
+ });
2566
+ return schema;
2567
+ };
2568
+ Schema.natural = function natural() {
2569
+ return Schema.number().step(1).min(0);
2570
+ };
2571
+ Schema.percent = function percent() {
2572
+ return Schema.number().step(.01).min(0).max(1).role("slider");
2573
+ };
2574
+ Schema.date = function date() {
2575
+ return Schema.union([Schema.is(Date), Schema.transform(Schema.string().role("datetime"), (value, options) => {
2576
+ const date = new Date(value);
2577
+ if (isNaN(+date)) throw new ValidationError(`invalid date "${value}"`, options);
2578
+ return date;
2579
+ }, true)]);
2580
+ };
2581
+ Schema.regExp = function regExp(flag = "") {
2582
+ return Schema.union([Schema.is(RegExp), Schema.transform(Schema.string().role("regexp", { flag }), (value, options) => {
2583
+ try {
2584
+ return new RegExp(value, flag);
2585
+ } catch (e) {
2586
+ throw new ValidationError(e.message, options);
2587
+ }
2588
+ }, true)]);
2589
+ };
2590
+ Schema.arrayBuffer = function arrayBuffer(encoding) {
2591
+ return Schema.union([
2592
+ Schema.is(ArrayBuffer),
2593
+ Schema.is(SharedArrayBuffer),
2594
+ Schema.transform(Schema.any(), (value, options) => {
2595
+ if (Binary.isSource(value)) return Binary.fromSource(value);
2596
+ throw new ValidationError(`expected ArrayBufferSource but got ${value}`, options);
2597
+ }, true),
2598
+ ...encoding ? [Schema.transform(Schema.string(), (value, options) => {
2599
+ try {
2600
+ return encoding === "base64" ? Binary.fromBase64(value) : Binary.fromHex(value);
2601
+ } catch (e) {
2602
+ throw new ValidationError(e.message, options);
2603
+ }
2604
+ }, true)] : []
2605
+ ]);
2606
+ };
2607
+ Schema.extend("lazy", (data, schema, options, strict) => {
2608
+ if (!schema.inner[kSchema]) {
2609
+ schema.inner = schema.builder();
2610
+ schema.inner.meta = {
2611
+ ...schema.meta,
2612
+ ...schema.inner.meta
2613
+ };
2614
+ }
2615
+ return Schema.resolve(data, schema.inner, options, strict);
2616
+ });
2617
+ Schema.extend("any", (data) => {
2618
+ return [data];
2619
+ });
2620
+ Schema.extend("never", (data, _, options) => {
2621
+ throw new ValidationError(`expected nullable but got ${data}`, options);
2622
+ });
2623
+ Schema.extend("const", (data, { value }, options) => {
2624
+ if (deepEqual(data, value)) return [value];
2625
+ throw new ValidationError(`expected ${value} but got ${data}`, options);
2626
+ });
2627
+ function checkWithinRange(data, meta, description, options, skipMin = false) {
2628
+ const { max = Infinity, min = -Infinity } = meta;
2629
+ if (data > max) throw new ValidationError(`expected ${description} <= ${max} but got ${data}`, options);
2630
+ if (data < min && !skipMin) throw new ValidationError(`expected ${description} >= ${min} but got ${data}`, options);
2631
+ }
2632
+ Schema.extend("string", (data, { meta }, options) => {
2633
+ if (typeof data !== "string") throw new ValidationError(`expected string but got ${data}`, options);
2634
+ if (meta.pattern) {
2635
+ const regexp = new RegExp(meta.pattern.source, meta.pattern.flags);
2636
+ if (!regexp.test(data)) throw new ValidationError(`expect string to match regexp ${regexp}`, options);
2637
+ }
2638
+ checkWithinRange(data.length, meta, "string length", options);
2639
+ return [data];
2640
+ });
2641
+ function decimalShift(data, digits) {
2642
+ const str = data.toString();
2643
+ if (str.includes("e")) return data * Math.pow(10, digits);
2644
+ const index = str.indexOf(".");
2645
+ if (index === -1) return data * Math.pow(10, digits);
2646
+ const frac = str.slice(index + 1);
2647
+ const integer = str.slice(0, index);
2648
+ if (frac.length <= digits) return +(integer + frac.padEnd(digits, "0"));
2649
+ return +(integer + frac.slice(0, digits) + "." + frac.slice(digits));
2650
+ }
2651
+ function isMultipleOf(data, min, step) {
2652
+ step = Math.abs(step);
2653
+ if (!/^\d+\.\d+$/.test(step.toString())) return (data - min) % step === 0;
2654
+ const index = step.toString().indexOf(".");
2655
+ const digits = step.toString().slice(index + 1).length;
2656
+ return Math.abs(decimalShift(data, digits) - decimalShift(min, digits)) % decimalShift(step, digits) === 0;
2657
+ }
2658
+ Schema.extend("number", (data, { meta }, options) => {
2659
+ if (typeof data !== "number") throw new ValidationError(`expected number but got ${data}`, options);
2660
+ checkWithinRange(data, meta, "number", options);
2661
+ const { step } = meta;
2662
+ if (step && !isMultipleOf(data, meta.min ?? 0, step)) throw new ValidationError(`expected number multiple of ${step} but got ${data}`, options);
2663
+ return [data];
2664
+ });
2665
+ Schema.extend("boolean", (data, _, options) => {
2666
+ if (typeof data === "boolean") return [data];
2667
+ throw new ValidationError(`expected boolean but got ${data}`, options);
2668
+ });
2669
+ Schema.extend("bitset", (data, { bits, meta }, options) => {
2670
+ let value = 0, keys = [];
2671
+ if (typeof data === "number") {
2672
+ value = data;
2673
+ for (const key in bits) if (data & bits[key]) keys.push(key);
2674
+ } else if (Array.isArray(data)) {
2675
+ keys = data;
2676
+ for (const key of keys) {
2677
+ if (typeof key !== "string") throw new ValidationError(`expected string but got ${key}`, options);
2678
+ if (key in bits) value |= bits[key];
2679
+ }
2680
+ } else throw new ValidationError(`expected number or array but got ${data}`, options);
2681
+ if (value === meta.default) return [value];
2682
+ return [value, keys];
2683
+ });
2684
+ Schema.extend("function", (data, _, options) => {
2685
+ if (typeof data === "function") return [data];
2686
+ throw new ValidationError(`expected function but got ${data}`, options);
2687
+ });
2688
+ Schema.extend("is", (data, { constructor }, options) => {
2689
+ if (typeof constructor === "function") {
2690
+ if (data instanceof constructor) return [data];
2691
+ throw new ValidationError(`expected ${constructor.name} but got ${data}`, options);
2692
+ } else {
2693
+ if (isNullable(data)) throw new ValidationError(`expected ${constructor} but got ${data}`, options);
2694
+ let prototype = Object.getPrototypeOf(data);
2695
+ while (prototype) {
2696
+ if (prototype.constructor?.name === constructor) return [data];
2697
+ prototype = Object.getPrototypeOf(prototype);
2698
+ }
2699
+ throw new ValidationError(`expected ${constructor} but got ${data}`, options);
2700
+ }
2701
+ });
2702
+ function property(data, key, schema, options) {
2703
+ try {
2704
+ const [value, adapted] = Schema.resolve(data[key], schema, {
2705
+ ...options,
2706
+ path: [...options.path || [], key]
2707
+ });
2708
+ if (adapted !== void 0) data[key] = adapted;
2709
+ return value;
2710
+ } catch (e) {
2711
+ if (!options?.autofix) throw e;
2712
+ delete data[key];
2713
+ return schema.meta.default;
2714
+ }
2715
+ }
2716
+ Schema.extend("array", (data, { inner, meta }, options) => {
2717
+ if (!Array.isArray(data)) throw new ValidationError(`expected array but got ${data}`, options);
2718
+ checkWithinRange(data.length, meta, "array length", options, !isNullable(inner.meta.default));
2719
+ return [data.map((_, index) => property(data, index, inner, options))];
2720
+ });
2721
+ Schema.extend("dict", (data, { inner, sKey }, options, strict) => {
2722
+ if (!isPlainObject(data)) throw new ValidationError(`expected object but got ${data}`, options);
2723
+ const result = {};
2724
+ for (const key in data) {
2725
+ let rKey;
2726
+ try {
2727
+ rKey = Schema.resolve(key, sKey, options)[0];
2728
+ } catch (error) {
2729
+ if (strict) continue;
2730
+ throw error;
2731
+ }
2732
+ result[rKey] = property(data, key, inner, options);
2733
+ data[rKey] = data[key];
2734
+ if (key !== rKey) delete data[key];
2735
+ }
2736
+ return [result];
2737
+ });
2738
+ Schema.extend("tuple", (data, { list }, options, strict) => {
2739
+ if (!Array.isArray(data)) throw new ValidationError(`expected array but got ${data}`, options);
2740
+ const result = list.map((inner, index) => property(data, index, inner, options));
2741
+ if (strict) return [result];
2742
+ result.push(...data.slice(list.length));
2743
+ return [result];
2744
+ });
2745
+ function merge(result, data) {
2746
+ for (const key in data) {
2747
+ if (key in result) continue;
2748
+ result[key] = data[key];
2749
+ }
2750
+ }
2751
+ Schema.extend("object", (data, { dict }, options, strict) => {
2752
+ if (!isPlainObject(data)) throw new ValidationError(`expected object but got ${data}`, options);
2753
+ const result = {};
2754
+ for (const key in dict) {
2755
+ const value = property(data, key, dict[key], options);
2756
+ if (!isNullable(value) || key in data) result[key] = value;
2757
+ }
2758
+ if (!strict) merge(result, data);
2759
+ return [result];
2760
+ });
2761
+ Schema.extend("union", (data, { list, toString }, options, strict) => {
2762
+ const messages = [];
2763
+ for (const inner of list) try {
2764
+ return Schema.resolve(data, inner, options, strict);
2765
+ } catch (error) {
2766
+ messages.push(error);
2767
+ }
2768
+ throw new ValidationError(`expected ${toString()} but got ${JSON.stringify(data)}`, options);
2769
+ });
2770
+ Schema.extend("intersect", (data, { list, toString }, options, strict) => {
2771
+ if (!list.length) return [data];
2772
+ let result;
2773
+ for (const inner of list) {
2774
+ const value = Schema.resolve(data, inner, options, true)[0];
2775
+ if (isNullable(value)) continue;
2776
+ if (isNullable(result)) result = value;
2777
+ else if (typeof result !== typeof value) throw new ValidationError(`expected ${toString()} but got ${JSON.stringify(data)}`, options);
2778
+ else if (typeof value === "object") merge(result ??= {}, value);
2779
+ else if (result !== value) throw new ValidationError(`expected ${toString()} but got ${JSON.stringify(data)}`, options);
2780
+ }
2781
+ if (!strict && isPlainObject(data)) merge(result, data);
2782
+ return [result];
2783
+ });
2784
+ Schema.extend("transform", (data, { inner, callback, preserve }, options) => {
2785
+ const [result, adapted = data] = Schema.resolve(data, inner, options, true);
2786
+ if (preserve) return [callback(result)];
2787
+ else return [callback(result), callback(adapted)];
2788
+ });
2789
+ const formatters = {};
2790
+ function defineMethod(name, keys, format) {
2791
+ formatters[name] = format;
2792
+ Object.assign(Schema, { [name](...args) {
2793
+ const schema = new Schema({ type: name });
2794
+ keys.forEach((key, index) => {
2795
+ switch (key) {
2796
+ case "sKey":
2797
+ schema.sKey = args[index] ?? Schema.string();
2798
+ break;
2799
+ case "inner":
2800
+ schema.inner = Schema.from(args[index]);
2801
+ break;
2802
+ case "list":
2803
+ schema.list = args[index].map(Schema.from);
2804
+ break;
2805
+ case "dict":
2806
+ schema.dict = mapValues(args[index], Schema.from);
2807
+ break;
2808
+ case "bits":
2809
+ schema.bits = {};
2810
+ for (const key in args[index]) {
2811
+ if (typeof args[index][key] !== "number") continue;
2812
+ schema.bits[key] = args[index][key];
2813
+ }
2814
+ break;
2815
+ case "callback": {
2816
+ const callback = schema.callback = args[index];
2817
+ callback["toJSON"] ||= () => callback.toString();
2818
+ break;
2819
+ }
2820
+ case "constructor": {
2821
+ const constructor = schema.constructor = args[index];
2822
+ if (typeof constructor === "function") constructor["toJSON"] ||= () => constructor["name"];
2823
+ break;
2824
+ }
2825
+ default: schema[key] = args[index];
2826
+ }
2827
+ });
2828
+ if (name === "object" || name === "dict") schema.meta.default = {};
2829
+ else if (name === "array" || name === "tuple") schema.meta.default = [];
2830
+ else if (name === "bitset") schema.meta.default = 0;
2831
+ return schema;
2832
+ } });
2833
+ }
2834
+ defineMethod("is", ["constructor"], ({ constructor }) => {
2835
+ if (typeof constructor === "function") return constructor.name;
2836
+ else return constructor;
2837
+ });
2838
+ defineMethod("any", [], () => "any");
2839
+ defineMethod("never", [], () => "never");
2840
+ defineMethod("const", ["value"], ({ value }) => typeof value === "string" ? JSON.stringify(value) : value);
2841
+ defineMethod("string", [], () => "string");
2842
+ defineMethod("number", [], () => "number");
2843
+ defineMethod("boolean", [], () => "boolean");
2844
+ defineMethod("bitset", ["bits"], () => "bitset");
2845
+ defineMethod("function", [], () => "function");
2846
+ defineMethod("array", ["inner"], ({ inner }) => `${inner.toString(true)}[]`);
2847
+ defineMethod("dict", ["inner", "sKey"], ({ inner, sKey }) => `{ [key: ${sKey.toString()}]: ${inner.toString()} }`);
2848
+ defineMethod("tuple", ["list"], ({ list }) => `[${list.map((inner) => inner.toString()).join(", ")}]`);
2849
+ defineMethod("object", ["dict"], ({ dict }) => {
2850
+ if (Object.keys(dict).length === 0) return "{}";
2851
+ return `{ ${Object.entries(dict).map(([key, inner]) => {
2852
+ return `${key}${inner.meta.required ? "" : "?"}: ${inner.toString()}`;
2853
+ }).join(", ")} }`;
2854
+ });
2855
+ defineMethod("union", ["list"], ({ list }, inline) => {
2856
+ const result = list.map(({ toString: format }) => format()).join(" | ");
2857
+ return inline ? `(${result})` : result;
2858
+ });
2859
+ defineMethod("intersect", ["list"], ({ list }) => {
2860
+ return `${list.map((inner) => inner.toString(true)).join(" & ")}`;
2861
+ });
2862
+ defineMethod("transform", [
2863
+ "inner",
2864
+ "callback",
2865
+ "preserve"
2866
+ ], ({ inner }, isInner) => inner.toString(isInner));
2867
+ //#endregion
2868
+ //#region node_modules/.pnpm/@deepseek-ai+dsh-timeout@0.1.5-rc.2_@deepseek-ai+cordis@4.0.2/node_modules/@deepseek-ai/dsh-timeout/lib/index.js
2869
+ /** Largest delay Node schedules without clamping it to one millisecond. */
2870
+ const MAX_TIMER_DELAY_MS = 2147483647;
2871
+ //#endregion
2872
+ //#region node_modules/.pnpm/@deepseek-ai+dsh-llm@0.1.5-rc.2_@deepseek-ai+cordis@4.0.2/node_modules/@deepseek-ai/dsh-llm/lib/index.js
2873
+ /**
2874
+ * Detach and deep-freeze a message whose identity already exists.
2875
+ * @param message - complete message, including its stable identity.
2876
+ * @returns an immutable snapshot that preserves the identity.
2877
+ */
2878
+ function freezeMessage(message) {
2879
+ return deepFreeze(structuredClone(message));
2880
+ }
2881
+ /**
2882
+ * Create one identified message and freeze it before publication.
2883
+ * @param input - complete role, content, and source for a new message.
2884
+ * @returns an immutable message with a fresh stable identity.
2885
+ */
2886
+ function createMessage(input) {
2887
+ return freezeMessage({
2888
+ ...input,
2889
+ id: brandString(randomUUID())
2890
+ });
2891
+ }
2892
+ /**
2893
+ * Create one identified user-role message and freeze it before publication.
2894
+ * @param input - complete content and source for a new user message.
2895
+ * @returns an immutable user message with a fresh stable identity.
2896
+ */
2897
+ function createUserMessage(input) {
2898
+ return createMessage({
2899
+ ...input,
2900
+ role: "user"
2901
+ });
2902
+ }
2903
+ /**
2904
+ * Harness error base with a stable machine-routable code and chained cause.
2905
+ * Package errors extend it so tool results and replay can retain failure class.
2906
+ * @module @deepseek-ai/dsh-llm/error
2907
+ */
2908
+ /**
2909
+ * Base class for all harness errors. Carries a `code` (stable, programmatic —
2910
+ * e.g. `NO_ADAPTER`, `INVALID_ARGS`, `INVARIANT`) distinct from the
2911
+ * human-readable `message`, and supports `cause` chaining via the standard
2912
+ * `ErrorOptions`. `name` defaults to the subclass constructor name.
2913
+ */
2914
+ var HarnessError = class extends Error {
2915
+ /** Stable machine-routable failure class (e.g. `RATE_LIMIT`); route on this, never by parsing `message`. */
2916
+ code;
2917
+ constructor(message, code, options) {
2918
+ super(message, options);
2919
+ this.code = code;
2920
+ this.name = new.target.name;
2921
+ }
2922
+ };
2923
+ /**
2924
+ * Canonical provider-neutral code for a response that completed normally but
2925
+ * carried no content blocks at all. Providers occasionally emit a degenerate
2926
+ * completion (a terminal stop with zero output); adapters classify it as this
2927
+ * failure instead of yielding an empty assistant message, because an empty
2928
+ * message silently ends the turn with nothing for the user or the loop to act
2929
+ * on. The attempt produced nothing durable, so retry policy treats it as safe
2930
+ * to repeat.
2931
+ */
2932
+ const EMPTY_RESPONSE_CODE = "EMPTY_RESPONSE";
2933
+ new RegExp(String.raw`(?:^|[^a-z0-9])context[\s_-](?:length|window)[\s_-]` + String.raw`(?:exceed(?:ed|s)?|overflow(?:ed)?|limit[\s_-]exceeded)(?:$|[^a-z0-9])`, "i");
2934
+ new RegExp(String.raw`\b(?:request|prompt|input|messages?)\s+(?:is\s+|are\s+)?` + String.raw`too\s+(?:large|long)\s+for\s+(?:(?:this|the)\s+)?` + String.raw`(?:model(?:'s)?\s+)?context(?:\s+window)?\b`, "i");
2935
+ new RegExp(String.raw`\b(?:input|prompt|request|messages?)\b.{0,40}` + String.raw`\b(?:exceed(?:s|ed)?|overflows?|is\s+larger\s+than)\b.{0,40}` + String.raw`\b(?:the\s+)?(?:model(?:'s)?\s+)?context(?:\s+(?:length|window))?\b`, "i");
2936
+ /**
2937
+ * Provider-owned request-retry policy configuration and resolution.
2938
+ *
2939
+ * Adapters expose one resolved policy per registered provider route; the
2940
+ * optional dsh-llm-retry plugin executes it on the agent's failed-step extension point.
2941
+ *
2942
+ * @module @deepseek-ai/dsh-llm/retry-policy
2943
+ */
2944
+ const DEFAULT_MAX_RETRIES = 5;
2945
+ const DEFAULT_INITIAL_DELAY_MS = 500;
2946
+ const DEFAULT_MAX_DELAY_MS = 1e4;
2947
+ const DEFAULT_JITTER_RATIO = .1;
2948
+ const DEFAULT_RETRYABLE_CODES = Object.freeze([
2949
+ EMPTY_RESPONSE_CODE,
2950
+ "RATE_LIMIT",
2951
+ "SERVER",
2952
+ "TIMEOUT",
2953
+ "TRANSPORT"
2954
+ ]);
2955
+ const backoffSchema = Schema.object({
2956
+ initialDelayMs: Schema.number().max(MAX_TIMER_DELAY_MS).default(DEFAULT_INITIAL_DELAY_MS),
2957
+ maxDelayMs: Schema.number().max(MAX_TIMER_DELAY_MS).default(DEFAULT_MAX_DELAY_MS),
2958
+ jitterRatio: Schema.number().min(0).max(1).default(DEFAULT_JITTER_RATIO)
2959
+ });
2960
+ const normalPolicySchema = Schema.object({
2961
+ mode: Schema.const("normal").required(),
2962
+ maxRetries: Schema.number().step(1).min(0).max(Number.MAX_SAFE_INTEGER).default(DEFAULT_MAX_RETRIES),
2963
+ retryableCodes: Schema.array(Schema.string()).default([...DEFAULT_RETRYABLE_CODES]),
2964
+ backoff: backoffSchema
2965
+ });
2966
+ const alwaysPolicySchema = Schema.object({
2967
+ mode: Schema.const("always").required(),
2968
+ backoff: backoffSchema
2969
+ });
2970
+ Schema.union([normalPolicySchema, alwaysPolicySchema]);
2971
+ const NORMAL_POLICY_KEYS = /* @__PURE__ */ new Set([
2972
+ "mode",
2973
+ "maxRetries",
2974
+ "retryableCodes",
2975
+ "backoff"
2976
+ ]);
2977
+ const ALWAYS_POLICY_KEYS = /* @__PURE__ */ new Set([
2978
+ "mode",
2979
+ "maxRetries",
2980
+ "retryableCodes",
2981
+ "backoff"
2982
+ ]);
2983
+ const BACKOFF_KEYS = /* @__PURE__ */ new Set([
2984
+ "initialDelayMs",
2985
+ "maxDelayMs",
2986
+ "jitterRatio"
2987
+ ]);
2988
+ function validateKeys(value, allowed, path) {
2989
+ for (const key of Object.keys(value)) if (!allowed.has(key)) throw new Error(`${path}: unknown key "${key}"`);
2990
+ }
2991
+ function resolveBackoff(config, path) {
2992
+ if (config !== void 0) validateKeys(config, BACKOFF_KEYS, path);
2993
+ const initialDelayMs = config?.initialDelayMs ?? DEFAULT_INITIAL_DELAY_MS;
2994
+ const maxDelayMs = config?.maxDelayMs ?? DEFAULT_MAX_DELAY_MS;
2995
+ const jitterRatio = config?.jitterRatio ?? DEFAULT_JITTER_RATIO;
2996
+ if (!Number.isFinite(initialDelayMs) || initialDelayMs <= 0 || initialDelayMs > 2147483647) throw new Error(`${path}.initialDelayMs must be a positive finite number no greater than ${MAX_TIMER_DELAY_MS}`);
2997
+ if (!Number.isFinite(maxDelayMs) || maxDelayMs <= 0 || maxDelayMs > 2147483647) throw new Error(`${path}.maxDelayMs must be a positive finite number no greater than ${MAX_TIMER_DELAY_MS}`);
2998
+ if (initialDelayMs > maxDelayMs) throw new Error(`${path}.initialDelayMs must be less than or equal to maxDelayMs`);
2999
+ if (!Number.isFinite(jitterRatio) || jitterRatio < 0 || jitterRatio > 1) throw new Error(`${path}.jitterRatio must be between 0 and 1`);
3000
+ return Object.freeze({
3001
+ initialDelayMs,
3002
+ maxDelayMs,
3003
+ jitterRatio
3004
+ });
3005
+ }
3006
+ /**
3007
+ * Validate, default, and detach one provider-owned retry policy.
3008
+ * @param config - optional provider configuration; omission selects normal defaults.
3009
+ * @param path - diagnostic path naming the provider config that owns the value.
3010
+ * @returns an immutable policy safe to capture in provider registration state.
3011
+ */
3012
+ function resolveRetryPolicy(config, path) {
3013
+ if (config === void 0) return Object.freeze({
3014
+ mode: "normal",
3015
+ maxRetries: DEFAULT_MAX_RETRIES,
3016
+ retryableCodes: DEFAULT_RETRYABLE_CODES,
3017
+ ...resolveBackoff(void 0, `${path}.backoff`)
3018
+ });
3019
+ switch (config.mode) {
3020
+ case "normal": {
3021
+ validateKeys(config, NORMAL_POLICY_KEYS, path);
3022
+ const maxRetries = config.maxRetries ?? DEFAULT_MAX_RETRIES;
3023
+ const retryableCodes = config.retryableCodes ?? [...DEFAULT_RETRYABLE_CODES];
3024
+ if (!Number.isSafeInteger(maxRetries) || maxRetries < 0) throw new Error(`${path}.maxRetries must be a non-negative safe integer`);
3025
+ if (retryableCodes.length === 0) throw new Error(`${path}.retryableCodes must not be empty`);
3026
+ if (retryableCodes.some((code) => typeof code !== "string" || code.length === 0)) throw new Error(`${path}.retryableCodes must contain only non-empty strings`);
3027
+ if (new Set(retryableCodes).size !== retryableCodes.length) throw new Error(`${path}.retryableCodes must not contain duplicates`);
3028
+ return Object.freeze({
3029
+ mode: "normal",
3030
+ maxRetries,
3031
+ retryableCodes: Object.freeze([...retryableCodes]),
3032
+ ...resolveBackoff(config.backoff, `${path}.backoff`)
3033
+ });
3034
+ }
3035
+ case "always":
3036
+ validateKeys(config, ALWAYS_POLICY_KEYS, path);
3037
+ return Object.freeze({
3038
+ mode: "always",
3039
+ ...resolveBackoff(config.backoff, `${path}.backoff`)
3040
+ });
3041
+ default: throw new Error(`${path}.mode must be "normal" or "always"`);
3042
+ }
3043
+ }
3044
+ /**
3045
+ * Field-wise equality over {@link LlmCallConfig} — the comparison a caller
3046
+ * runs to decide whether a proposed configuration is a real change (worth a
3047
+ * logged header snapshot) or the held one restated.
3048
+ * @param a - one configuration.
3049
+ * @param b - the other.
3050
+ * @returns whether every field (including the `stop` list, element-wise) matches.
3051
+ */
3052
+ function callConfigEquals(a, b) {
3053
+ if (a.provider !== b.provider || a.model !== b.model || a.reasoningEffort !== b.reasoningEffort || a.temperature !== b.temperature || a.maxTokens !== b.maxTokens) return false;
3054
+ if (a.stop === void 0 || b.stop === void 0) return a.stop === b.stop;
3055
+ return a.stop.length === b.stop.length && a.stop.every((s, i) => s === b.stop?.[i]);
3056
+ }
3057
+ /**
3058
+ * Normalization for values thrown by a final LLM adapter boundary.
3059
+ *
3060
+ * @module @deepseek-ai/dsh-llm/adapter-failure
3061
+ */
3062
+ /**
3063
+ * Detach serializable provider facts from a value thrown by an adapter.
3064
+ * @param value - arbitrary value thrown during adapter dispatch or iteration.
3065
+ * @returns immutable provider-neutral facts suitable for a terminal finish chunk.
3066
+ * @internal
3067
+ */
3068
+ function normalizeLlmFailure(value) {
3069
+ const error = value instanceof Error ? value : new HarnessError(thrownMessage(value), "UNKNOWN", { cause: value });
3070
+ const carried = ownFailureSnapshot(error);
3071
+ if (carried !== void 0 && carried.code === ownErrorCode(error)) return carried;
3072
+ return Object.freeze({
3073
+ message: errorMessage(error),
3074
+ code: harnessErrorCode(error)
3075
+ });
3076
+ }
3077
+ /** Render a non-Error throw without letting hostile coercion escape normalization. */
3078
+ function thrownMessage(value) {
3079
+ try {
3080
+ const message = String(value);
3081
+ return message.length > 0 ? message : "LLM adapter failed";
3082
+ } catch (_hostileThrownValue) {
3083
+ return "LLM adapter failed";
3084
+ }
3085
+ }
3086
+ /** Read a foreign error's own data-backed `code` without invoking accessors. */
3087
+ function ownErrorCode(error) {
3088
+ try {
3089
+ const descriptor = Object.getOwnPropertyDescriptor(error, "code");
3090
+ return descriptor !== void 0 && "value" in descriptor ? descriptor.value : void 0;
3091
+ } catch (_sdkPropertyTrap) {
3092
+ return;
3093
+ }
3094
+ }
3095
+ /** Snapshot an own data property without invoking an SDK-defined accessor. */
3096
+ function ownFailureSnapshot(error) {
3097
+ try {
3098
+ const descriptor = Object.getOwnPropertyDescriptor(error, "failure");
3099
+ return descriptor !== void 0 && "value" in descriptor ? failureSnapshot(descriptor.value) : void 0;
3100
+ } catch (_sdkPropertyTrap) {
3101
+ return;
3102
+ }
3103
+ }
3104
+ /** Validate and detach an arbitrary serializable failure payload. */
3105
+ function failureSnapshot(value) {
3106
+ if (typeof value !== "object" || value === null) return void 0;
3107
+ try {
3108
+ const candidate = value;
3109
+ const message = candidate.message;
3110
+ const code = candidate.code;
3111
+ const status = candidate.status;
3112
+ const providerRetryAfterMs = candidate.providerRetryAfterMs;
3113
+ const requestId = candidate.requestId;
3114
+ if (typeof message !== "string" || message.length === 0 || typeof code !== "string" || code.length === 0 || status !== void 0 && (!Number.isInteger(status) || status < 100 || status > 599) || providerRetryAfterMs !== void 0 && (!Number.isFinite(providerRetryAfterMs) || providerRetryAfterMs <= 0) || requestId !== void 0 && (typeof requestId !== "string" || requestId.length === 0)) return void 0;
3115
+ return Object.freeze({
3116
+ message,
3117
+ code,
3118
+ ...status === void 0 ? {} : { status },
3119
+ ...providerRetryAfterMs === void 0 ? {} : { providerRetryAfterMs },
3120
+ ...requestId === void 0 ? {} : { requestId }
3121
+ });
3122
+ } catch (_sdkFailureGetter) {
3123
+ return;
3124
+ }
3125
+ }
3126
+ /** Read an SDK error message without letting an accessor replace the primary failure. */
3127
+ function errorMessage(error) {
3128
+ try {
3129
+ const message = error.message;
3130
+ if (typeof message === "string" && message.length > 0) return message;
3131
+ } catch (_sdkMessageGetter) {}
3132
+ return "LLM adapter failed";
3133
+ }
3134
+ /** Trust only Harness-owned codes; third-party SDK codes are not our taxonomy. */
3135
+ function harnessErrorCode(error) {
3136
+ return error instanceof HarnessError ? error.code : "UNKNOWN";
3137
+ }
3138
+ function quoted(value) {
3139
+ return JSON.stringify(value);
3140
+ }
3141
+ /**
3142
+ * Stable text shown to a model that cannot accept one durable image reference.
3143
+ * @param ref - durable normalized attachment omitted from the request.
3144
+ * @returns deterministic text-only placeholder.
3145
+ */
3146
+ function textOnlyImageText(ref) {
3147
+ return `[image omitted because this model accepts text only; attachment sha256:${String(ref.attachmentId).slice(7, 15)}]`;
3148
+ }
3149
+ /**
3150
+ * True when typed model content contains an image block, walking nested
3151
+ * tool-result content. This is the one recursive image walk shared by every
3152
+ * image policy (capability gating, text-only serialization, compaction
3153
+ * survey), so a consumer cannot silently diverge on nesting depth.
3154
+ * @param content - typed model content blocks.
3155
+ * @returns whether any nested block is an image.
3156
+ */
3157
+ function contentHasImage(content) {
3158
+ return content.some((block) => block.type === "image" || block.type === "tool-result" && contentHasImage(block.content));
3159
+ }
3160
+ /**
3161
+ * True when typed model content contains a file block, walking nested
3162
+ * tool-result content on the same recursion every file policy shares.
3163
+ * Reads current content on every call without retaining scan results.
3164
+ * @param content - typed model content blocks.
3165
+ * @returns whether any nested block is a file.
3166
+ */
3167
+ function contentHasFile(content) {
3168
+ for (const block of content) if (block.type === "file" || block.type === "tool-result" && contentHasFile(block.content)) return true;
3169
+ return false;
3170
+ }
3171
+ /**
3172
+ * Stable model-facing handle for one durable file reference: the address of
3173
+ * the verbatim stored copy and the instruction to read it on demand. This is
3174
+ * the only representation a provider ever receives for a file.
3175
+ * @param ref - durable verbatim file reference.
3176
+ * @param readonlyPath - execution-world path of the stored copy, when resolvable.
3177
+ * @returns deterministic handle text naming the file, its size, and its address.
3178
+ */
3179
+ function fileHandleText(ref, readonlyPath) {
3180
+ const digest = String(ref.attachmentId).slice(7, 15);
3181
+ const identity = `File ${quoted(ref.name)} (${ref.bytes} bytes, sha256:${digest})`;
3182
+ if (readonlyPath === void 0) return `[${identity} was uploaded, but the current execution environment cannot access a readable path. Report that limitation if its contents are needed; do not claim to have read it.]`;
3183
+ return `[${identity}: verbatim read-only copy saved at ${quoted(readonlyPath)}. Read that path with your file tools when its contents are needed; copy it to a writable location before modifying it. When delegating file work, include this saved path in the delegation prompt; only subagents sharing this execution environment can read it.]`;
3184
+ }
3185
+ /** Replace every file occurrence, including nested tool results, with handle text. */
3186
+ function replaceFilesWithHandles(blocks, resolvePath) {
3187
+ let next;
3188
+ for (const [index, block] of blocks.entries()) {
3189
+ if (block.type === "file") {
3190
+ next ??= blocks.slice(0, index);
3191
+ next.push({
3192
+ type: "text",
3193
+ text: fileHandleText(block.attachment, resolvePath(block.attachment))
3194
+ });
3195
+ continue;
3196
+ }
3197
+ if (block.type === "tool-result") {
3198
+ const content = replaceFilesWithHandles(block.content, resolvePath);
3199
+ if (content !== block.content) {
3200
+ next ??= blocks.slice(0, index);
3201
+ next.push({
3202
+ ...block,
3203
+ content
3204
+ });
3205
+ continue;
3206
+ }
3207
+ }
3208
+ next?.push(block);
3209
+ }
3210
+ return next ?? blocks;
3211
+ }
3212
+ /**
3213
+ * Project durable file history into deterministic handle text for every model
3214
+ * route. Unlike images, no provider receives file blocks natively, so this
3215
+ * projection is unconditional in request assembly.
3216
+ * @param messages - complete request history.
3217
+ * @param resolvePath - resolve one reference's current execution-world read path.
3218
+ * @returns the original list without files, otherwise shallow message copies with handle text.
3219
+ */
3220
+ function projectFilesToText(messages, resolvePath) {
3221
+ if (!messages.some((message) => contentHasFile(message.content))) return messages;
3222
+ return messages.map((message) => {
3223
+ const content = replaceFilesWithHandles(message.content, resolvePath);
3224
+ return content === message.content ? message : {
3225
+ ...message,
3226
+ content
3227
+ };
3228
+ });
3229
+ }
3230
+ /** Replace every image occurrence, including nested tool results, for a text-only model. */
3231
+ function replaceImagesForTextModel(blocks) {
3232
+ let next;
3233
+ for (const [index, block] of blocks.entries()) {
3234
+ if (block.type === "image") {
3235
+ next ??= blocks.slice(0, index);
3236
+ next.push({
3237
+ type: "text",
3238
+ text: textOnlyImageText(block.attachment)
3239
+ });
3240
+ continue;
3241
+ }
3242
+ if (block.type === "tool-result") {
3243
+ const content = replaceImagesForTextModel(block.content);
3244
+ if (content !== block.content) {
3245
+ next ??= blocks.slice(0, index);
3246
+ next.push({
3247
+ ...block,
3248
+ content
3249
+ });
3250
+ continue;
3251
+ }
3252
+ }
3253
+ next?.push(block);
3254
+ }
3255
+ return next ?? blocks;
3256
+ }
3257
+ /**
3258
+ * Project durable image history into deterministic text for an exact text-only model.
3259
+ * @param messages - complete request history.
3260
+ * @returns the original list without images, otherwise shallow message copies with stable placeholders.
3261
+ */
3262
+ function projectImagesForTextModel(messages) {
3263
+ if (!messages.some((message) => contentHasImage(message.content))) return messages;
3264
+ return messages.map((message) => {
3265
+ const content = replaceImagesForTextModel(message.content);
3266
+ return content === message.content ? message : {
3267
+ ...message,
3268
+ content
3269
+ };
3270
+ });
3271
+ }
3272
+ /**
3273
+ * Centralize the non-secret product identity every provider request sends as `User-Agent`, keeping
3274
+ * adapters from drifting. See
3275
+ * `.agents/notes/implemented/architecture/2026-06-21-mandatory-app-attribution-headers.md`.
3276
+ *
3277
+ * App-attribution vocabulary for provider requests.
3278
+ * @module @deepseek-ai/dsh-llm/attribution
3279
+ */
3280
+ const { version } = createRequire(import.meta.url)("../package.json");
3281
+ /**
3282
+ * LLM service: adapter registry with a waterfall-interceptable streaming call
3283
+ * API. Exports the `LlmRuntime` default, the abstract `LlmAdapter` for
3284
+ * provider backends, and `BlockAssembler` for chunk assembly.
3285
+ *
3286
+ * @module @deepseek-ai/dsh-llm
3287
+ */
3288
+ var __runInitializers = function(thisArg, initializers, value) {
3289
+ var useValue = arguments.length > 2;
3290
+ for (var i = 0; i < initializers.length; i++) value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
3291
+ return useValue ? value : void 0;
3292
+ };
3293
+ var __esDecorate = function(ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
3294
+ function accept(f) {
3295
+ if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected");
3296
+ return f;
3297
+ }
3298
+ var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
3299
+ var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
3300
+ var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
3301
+ var _, done = false;
3302
+ for (var i = decorators.length - 1; i >= 0; i--) {
3303
+ var context = {};
3304
+ for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
3305
+ for (var p in contextIn.access) context.access[p] = contextIn.access[p];
3306
+ context.addInitializer = function(f) {
3307
+ if (done) throw new TypeError("Cannot add initializers after decoration has completed");
3308
+ extraInitializers.push(accept(f || null));
3309
+ };
3310
+ var result = (0, decorators[i])(kind === "accessor" ? {
3311
+ get: descriptor.get,
3312
+ set: descriptor.set
3313
+ } : descriptor[key], context);
3314
+ if (kind === "accessor") {
3315
+ if (result === void 0) continue;
3316
+ if (result === null || typeof result !== "object") throw new TypeError("Object expected");
3317
+ if (_ = accept(result.get)) descriptor.get = _;
3318
+ if (_ = accept(result.set)) descriptor.set = _;
3319
+ if (_ = accept(result.init)) initializers.unshift(_);
3320
+ } else if (_ = accept(result)) if (kind === "field") initializers.unshift(_);
3321
+ else descriptor[key] = _;
3322
+ }
3323
+ if (target) Object.defineProperty(target, contextIn.name, descriptor);
3324
+ done = true;
3325
+ };
3326
+ /**
3327
+ * Typed error for LLM-related failures. Extends {@link HarnessError}, so the
3328
+ * `code` string (e.g. `AUTH`, `RATE_LIMIT`, `NO_ADAPTER`) is shared taxonomy.
3329
+ */
3330
+ var LlmError = class extends HarnessError {
3331
+ /** Serializable facts retained beside this live Error. */
3332
+ failure;
3333
+ /**
3334
+ * @param message - non-empty human-readable failure summary.
3335
+ * @param code - non-empty stable provider-neutral machine code.
3336
+ * @param options - optional cause and validated serializable provider facts.
3337
+ */
3338
+ constructor(message, code, options) {
3339
+ if (typeof message !== "string" || message.length === 0) throw new Error("LlmError message must be a non-empty string");
3340
+ if (typeof code !== "string" || code.length === 0) throw new Error("LlmError code must be a non-empty string");
3341
+ if (options?.status !== void 0 && (!Number.isInteger(options.status) || options.status < 100 || options.status > 599)) throw new Error("LlmError status must be an integer from 100 through 599");
3342
+ if (options?.providerRetryAfterMs !== void 0 && (!Number.isFinite(options.providerRetryAfterMs) || options.providerRetryAfterMs <= 0)) throw new Error("LlmError providerRetryAfterMs must be a positive finite number");
3343
+ if (options?.requestId !== void 0 && (typeof options.requestId !== "string" || options.requestId.length === 0)) throw new Error("LlmError requestId must be a non-empty string");
3344
+ super(message, code, options);
3345
+ this.name = "LlmError";
3346
+ this.failure = Object.freeze({
3347
+ message,
3348
+ code,
3349
+ ...options?.status === void 0 ? {} : { status: options.status },
3350
+ ...options?.providerRetryAfterMs === void 0 ? {} : { providerRetryAfterMs: options.providerRetryAfterMs },
3351
+ ...options?.requestId === void 0 ? {} : { requestId: options.requestId }
3352
+ });
3353
+ }
3354
+ };
3355
+ (() => {
3356
+ let _classSuper = TypertRemoteService;
3357
+ let _instanceExtraInitializers = [];
3358
+ let _listProviders_decorators;
3359
+ let _listConfigurableProviders_decorators;
3360
+ let _remoteDiscoverModels_decorators;
3361
+ return class LlmRuntime extends _classSuper {
3362
+ static {
3363
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
3364
+ _listProviders_decorators = [Remote];
3365
+ _listConfigurableProviders_decorators = [Remote];
3366
+ _remoteDiscoverModels_decorators = [Remote("discoverModels")];
3367
+ __esDecorate(this, null, _listProviders_decorators, {
3368
+ kind: "method",
3369
+ name: "listProviders",
3370
+ static: false,
3371
+ private: false,
3372
+ access: {
3373
+ has: (obj) => "listProviders" in obj,
3374
+ get: (obj) => obj.listProviders
3375
+ },
3376
+ metadata: _metadata
3377
+ }, null, _instanceExtraInitializers);
3378
+ __esDecorate(this, null, _listConfigurableProviders_decorators, {
3379
+ kind: "method",
3380
+ name: "listConfigurableProviders",
3381
+ static: false,
3382
+ private: false,
3383
+ access: {
3384
+ has: (obj) => "listConfigurableProviders" in obj,
3385
+ get: (obj) => obj.listConfigurableProviders
3386
+ },
3387
+ metadata: _metadata
3388
+ }, null, _instanceExtraInitializers);
3389
+ __esDecorate(this, null, _remoteDiscoverModels_decorators, {
3390
+ kind: "method",
3391
+ name: "remoteDiscoverModels",
3392
+ static: false,
3393
+ private: false,
3394
+ access: {
3395
+ has: (obj) => "remoteDiscoverModels" in obj,
3396
+ get: (obj) => obj.remoteDiscoverModels
3397
+ },
3398
+ metadata: _metadata
3399
+ }, null, _instanceExtraInitializers);
3400
+ if (_metadata) Object.defineProperty(this, Symbol.metadata, {
3401
+ enumerable: true,
3402
+ configurable: true,
3403
+ writable: true,
3404
+ value: _metadata
3405
+ });
3406
+ }
3407
+ adapters = (__runInitializers(this, _instanceExtraInitializers), /* @__PURE__ */ new Map());
3408
+ directory = /* @__PURE__ */ new Map();
3409
+ discoveries = /* @__PURE__ */ new Map();
3410
+ constructor(ctx) {
3411
+ super(ctx, "llm");
3412
+ }
3413
+ /** Notify topology observers without letting one broken listener veto the commit. */
3414
+ emitAdaptersUpdated() {
3415
+ let invariantFailure;
3416
+ for (const listener of this.ctx.events.dispatch("emit", ["llm/adapters-updated"])) try {
3417
+ const returned = listener();
3418
+ if (returned != null && typeof returned.then === "function") Promise.resolve(returned).then(void 0, (error) => {
3419
+ this.warnAdaptersListenerFailure(error);
3420
+ });
3421
+ } catch (error) {
3422
+ if (error?.code === "INVARIANT") {
3423
+ invariantFailure ??= error;
3424
+ continue;
3425
+ }
3426
+ this.warnAdaptersListenerFailure(error);
3427
+ }
3428
+ if (invariantFailure !== void 0) throw invariantFailure;
3429
+ }
3430
+ /** Contained-listener diagnostic shared by the sync and async failure paths. */
3431
+ warnAdaptersListenerFailure(error) {
3432
+ this.ctx.logger.warn("llm: an llm/adapters-updated listener failed");
3433
+ this.ctx.logger.warn(error);
3434
+ }
3435
+ /**
3436
+ * Register an adapter for the given provider routes. Throws `LlmError` with code
3437
+ * `DUPLICATE_ADAPTER` if any provider already has an adapter (all-or-nothing).
3438
+ * Disposed with the fiber.
3439
+ * @param providers - every provider route this adapter should serve.
3440
+ * @param adapter - the adapter that streams calls for those providers.
3441
+ * @returns the disposer, carrying {@link AdapterRegistrationHandle.replace}.
3442
+ */
3443
+ registerAdapter(providers, adapter) {
3444
+ const owned = /* @__PURE__ */ new Set();
3445
+ let released = false;
3446
+ const dispose = this.ctx.effect(function* () {
3447
+ if (providers.length === 0) throw new LlmError("an adapter must register at least one provider", "INVALID_ADAPTER");
3448
+ this.commitRoutes(owned, this.prepareRoutes(providers, adapter, owned));
3449
+ yield () => {
3450
+ released = true;
3451
+ for (const provider of owned) this.adapters.delete(provider);
3452
+ owned.clear();
3453
+ this.emitAdaptersUpdated();
3454
+ };
3455
+ }.bind(this), "llm.registerAdapter()");
3456
+ const handle = (() => void dispose());
3457
+ handle.replace = (next) => {
3458
+ if (released) throw new LlmError("a disposed adapter registration cannot replace its routes", "REGISTRATION_DISPOSED");
3459
+ this.commitRoutes(owned, this.prepareRoutes(next, adapter, owned));
3460
+ };
3461
+ return handle;
3462
+ }
3463
+ /**
3464
+ * Validate one candidate route set for `adapter`, treating routes this
3465
+ * registration already holds as available. Nothing is mutated: a rejected
3466
+ * candidate leaves the registry exactly as it was.
3467
+ */
3468
+ prepareRoutes(providers, adapter, owned) {
3469
+ const unique = /* @__PURE__ */ new Set();
3470
+ const registrations = [];
3471
+ for (const provider of providers) {
3472
+ if (provider.length === 0) throw new LlmError("adapter provider names must be non-empty", "INVALID_ADAPTER");
3473
+ if (unique.has(provider) || this.adapters.has(provider) && !owned.has(provider)) throw new LlmError(`an adapter for provider "${provider}" is already registered`, "DUPLICATE_ADAPTER");
3474
+ const info = adapter.providerInfo(provider);
3475
+ if (typeof info.id !== "string" || info.id !== provider || typeof info.name !== "string" || info.name.length === 0) throw new LlmError(`adapter metadata for provider "${provider}" must preserve its id and have a non-empty name`, "INVALID_ADAPTER");
3476
+ unique.add(provider);
3477
+ const retryPolicy = adapter.providerRetryPolicy(provider) ?? resolveRetryPolicy(void 0, `llm: provider "${provider}" retryPolicy`);
3478
+ registrations.push({
3479
+ adapter,
3480
+ provider: {
3481
+ id: info.id,
3482
+ name: info.name
3483
+ },
3484
+ retryPolicy
3485
+ });
3486
+ }
3487
+ return registrations;
3488
+ }
3489
+ /**
3490
+ * Swap this registration's routes for the prepared ones in one synchronous
3491
+ * section, so no observer can see the registry between the release and the
3492
+ * re-registration. The route set's one mutation point is also where
3493
+ * `llm/adapters-updated` is published, so a `replace` announces itself
3494
+ * exactly like a first registration.
3495
+ */
3496
+ commitRoutes(owned, registrations) {
3497
+ for (const provider of owned) this.adapters.delete(provider);
3498
+ owned.clear();
3499
+ for (const registration of registrations) {
3500
+ this.adapters.set(registration.provider.id, registration);
3501
+ owned.add(registration.provider.id);
3502
+ }
3503
+ this.emitAdaptersUpdated();
3504
+ }
3505
+ /**
3506
+ * Describe provider routes with a registered adapter.
3507
+ * @returns detached provider metadata in registration order.
3508
+ */
3509
+ listProviders() {
3510
+ return [...this.adapters.values()].map(({ provider }) => ({ ...provider }));
3511
+ }
3512
+ /**
3513
+ * Declare provider routes an adapter plugin can activate through
3514
+ * configuration. Registration is all-or-nothing: an empty list, invalid
3515
+ * entry, or a provider already declared by any registration throws
3516
+ * `LlmError` without registering the rest. Disposed with the fiber.
3517
+ * @param entries - every configurable provider this plugin owns.
3518
+ * @returns a handle that withdraws all of them, and can atomically replace them.
3519
+ */
3520
+ registerConfigurableProviders(entries) {
3521
+ let held = [];
3522
+ let disposed = false;
3523
+ /**
3524
+ * Validate a candidate set in full against everything this registration
3525
+ * does not already hold, then publish it. Nothing is written until the
3526
+ * whole set passes, so a refused candidate leaves the current entries in
3527
+ * place — the property that makes `replace` a swap rather than a
3528
+ * delete-then-add that can strand the directory empty.
3529
+ */
3530
+ const commit = (candidates) => {
3531
+ const detached = [];
3532
+ const own = new Set(held.map((entry) => entry.provider));
3533
+ for (const entry of candidates) {
3534
+ if (entry.provider.length === 0 || entry.displayName.length === 0 || entry.settingsNs.length === 0) throw new LlmError("configurable providers need a non-empty provider, displayName, and settingsNs", "INVALID_DIRECTORY");
3535
+ if (entry.settingsPath.some((segment) => segment.length === 0)) throw new LlmError(`configurable provider "${entry.provider}" has an empty settingsPath segment`, "INVALID_DIRECTORY");
3536
+ if (this.directory.has(entry.provider) && !own.has(entry.provider) || detached.some((seen) => seen.provider === entry.provider)) throw new LlmError(`configurable provider "${entry.provider}" is already declared`, "DUPLICATE_DIRECTORY");
3537
+ detached.push({
3538
+ ...entry,
3539
+ settingsPath: [...entry.settingsPath]
3540
+ });
3541
+ }
3542
+ for (const entry of held) this.directory.delete(entry.provider);
3543
+ for (const entry of detached) this.directory.set(entry.provider, entry);
3544
+ held = detached;
3545
+ this.emitAdaptersUpdated();
3546
+ };
3547
+ const dispose = this.ctx.effect(function* () {
3548
+ if (entries.length === 0) throw new LlmError("a configurable-provider registration must declare at least one provider", "INVALID_DIRECTORY");
3549
+ commit(entries);
3550
+ yield () => {
3551
+ disposed = true;
3552
+ for (const entry of held) this.directory.delete(entry.provider);
3553
+ held = [];
3554
+ this.emitAdaptersUpdated();
3555
+ };
3556
+ }.bind(this), "llm.registerConfigurableProviders()");
3557
+ const handle = (() => void dispose());
3558
+ handle.replace = (next) => {
3559
+ if (disposed) throw new LlmError("this configurable-provider registration was disposed", "REGISTRATION_DISPOSED");
3560
+ commit(next);
3561
+ };
3562
+ return handle;
3563
+ }
3564
+ /**
3565
+ * List every declared configurable provider, registered or dormant.
3566
+ * @returns detached directory entries in declaration order.
3567
+ */
3568
+ listConfigurableProviders() {
3569
+ return [...this.directory.values()].map((entry) => ({
3570
+ ...entry,
3571
+ settingsPath: [...entry.settingsPath]
3572
+ }));
3573
+ }
3574
+ /**
3575
+ * Offer to interrogate provider endpoints on behalf of the settings
3576
+ * namespace this plugin owns. The namespace is the key because that is what
3577
+ * a configuration surface already holds from the configurable-provider
3578
+ * directory, and because a provider being *added* has no route to name yet.
3579
+ * Disposed with the fiber.
3580
+ * @param settingsNs - the namespace whose profiles this discovery serves.
3581
+ * @param discover - interrogates one endpoint and must honor the supplied signal.
3582
+ * @returns the disposer that withdraws the offer.
3583
+ */
3584
+ registerModelDiscovery(settingsNs, discover) {
3585
+ const dispose = this.ctx.effect(function* () {
3586
+ if (settingsNs.length === 0) throw new LlmError("model discovery needs a non-empty settings namespace", "INVALID_DISCOVERY");
3587
+ if (this.discoveries.has(settingsNs)) throw new LlmError(`model discovery for "${settingsNs}" is already registered`, "DUPLICATE_DISCOVERY");
3588
+ this.discoveries.set(settingsNs, discover);
3589
+ yield () => {
3590
+ this.discoveries.delete(settingsNs);
3591
+ };
3592
+ }.bind(this), "llm.registerModelDiscovery()");
3593
+ return () => void dispose();
3594
+ }
3595
+ /**
3596
+ * Interrogate one provider endpoint for the models it advertises. The
3597
+ * request describes a draft, not a stored route, so nothing here reads or
3598
+ * writes settings or credentials — the caller owns both, and the reply is
3599
+ * candidate metadata a surface may offer for adoption.
3600
+ * @param settingsNs - namespace whose registered discovery serves this draft.
3601
+ * @param request - the endpoint, protocol, and one-shot credential to use.
3602
+ * @param signal - caller cancellation.
3603
+ * @returns the advertised models, deduplicated in endpoint order.
3604
+ */
3605
+ async discoverModels(settingsNs, request, signal) {
3606
+ const discover = this.discoveries.get(settingsNs);
3607
+ if (discover === void 0) throw new LlmError(`no model discovery is registered for "${settingsNs}"`, "NO_DISCOVERY");
3608
+ if ((request.provider ?? "").length === 0 && (request.baseURL ?? "").length === 0) throw new LlmError("model discovery needs a provider route or a baseURL", "INVALID_DISCOVERY");
3609
+ const discovered = signal === void 0 ? await discover(request) : await discover(request, signal);
3610
+ const seen = /* @__PURE__ */ new Set();
3611
+ const models = [];
3612
+ for (const model of discovered) {
3613
+ if (typeof model.id !== "string" || model.id.length === 0 || seen.has(model.id)) continue;
3614
+ seen.add(model.id);
3615
+ models.push({
3616
+ id: model.id,
3617
+ ...model.name === void 0 ? {} : { name: model.name },
3618
+ ...model.contextWindow === void 0 ? {} : { contextWindow: model.contextWindow },
3619
+ ...model.maxTokens === void 0 ? {} : { maxTokens: model.maxTokens }
3620
+ });
3621
+ }
3622
+ return models;
3623
+ }
3624
+ /**
3625
+ * Remote adapter for one draft provider interrogation.
3626
+ * @param settingsNs - namespace whose registered discovery serves this draft.
3627
+ * @param request - endpoint, protocol, and one-shot credential to use.
3628
+ * @param signal - caller cancellation supplied by the Remote carrier.
3629
+ * @returns advertised models in endpoint order.
3630
+ * @throws RemoteError with `llm/model-discovery-rejected` when discovery refuses or fails.
3631
+ */
3632
+ async remoteDiscoverModels(settingsNs, request, signal) {
3633
+ try {
3634
+ return await this.discoverModels(settingsNs, request, signal);
3635
+ } catch (error) {
3636
+ throw new RemoteError("llm/model-discovery-rejected", error instanceof Error ? error.message : String(error), {
3637
+ settingsNs,
3638
+ ...request.baseURL === void 0 ? {} : { baseURL: request.baseURL }
3639
+ }, { cause: error });
3640
+ }
3641
+ }
3642
+ /**
3643
+ * Resolve the retry policy captured when one provider route was registered.
3644
+ * @param provider - registered provider route to inspect.
3645
+ * @returns the provider-owned policy, with normal defaults already resolved.
3646
+ */
3647
+ providerRetryPolicy(provider) {
3648
+ return this.registration(provider).retryPolicy;
3649
+ }
3650
+ /**
3651
+ * Resolve provider-side request-image pricing for one exact route, or
3652
+ * `undefined` when the provider is unregistered or declares none. Unknown
3653
+ * providers degrade to `undefined` rather than throwing because callers
3654
+ * price durable history whose route may no longer be mounted.
3655
+ * @param provider - provider route named by a request header.
3656
+ * @param model - exact model id named by the same header.
3657
+ * @returns the owning adapter's image pricing for the route, when declared.
3658
+ */
3659
+ imageRequestPricing(provider, model) {
3660
+ return this.adapters.get(provider)?.adapter.imageRequestPricing(provider, model);
3661
+ }
3662
+ /**
3663
+ * Resolve the exact text one durable file occurrence contributes to every
3664
+ * provider request in the current execution environment.
3665
+ * @param ref - durable verbatim file reference from model history.
3666
+ * @returns the same deterministic handle text used at adapter dispatch.
3667
+ */
3668
+ fileRequestText(ref) {
3669
+ return fileHandleText(ref, this.fileReadPath(ref));
3670
+ }
3671
+ /** Detach typed adapter-owned modality metadata. */
3672
+ detachedModalities(modalities) {
3673
+ return modalities === void 0 ? void 0 : [...modalities];
3674
+ }
3675
+ /**
3676
+ * Discover models advertised by one registered provider. Catalog membership
3677
+ * is advisory and never changes routing or request validation.
3678
+ * @param provider - registered provider route to inspect.
3679
+ * @returns detached model metadata in adapter-preferred order.
3680
+ */
3681
+ async listModels(provider) {
3682
+ const models = await this.registration(provider).adapter.listModels(provider);
3683
+ const seen = /* @__PURE__ */ new Set();
3684
+ return models.map((model) => {
3685
+ if (typeof model.provider !== "string" || model.provider !== provider || typeof model.id !== "string" || model.id.length === 0 || typeof model.name !== "string" || model.name.length === 0 || model.description !== void 0 && typeof model.description !== "string" || seen.has(model.id)) throw new LlmError(`adapter returned invalid or duplicate model metadata for provider "${provider}"`, "INVALID_CATALOG");
3686
+ seen.add(model.id);
3687
+ const inputModalities = this.detachedModalities(model.inputModalities);
3688
+ return {
3689
+ provider: model.provider,
3690
+ id: model.id,
3691
+ name: model.name,
3692
+ ...model.description === void 0 ? {} : { description: model.description },
3693
+ ...inputModalities === void 0 ? {} : { inputModalities }
3694
+ };
3695
+ });
3696
+ }
3697
+ /**
3698
+ * Resolve and validate all metadata from the adapter that owns one exact
3699
+ * route. The result is detached from adapter-owned objects; catalog
3700
+ * membership remains advisory and does not control request routing.
3701
+ * @param provider - registered provider route to inspect.
3702
+ * @param model - exact model id passed to the adapter.
3703
+ * @param signal - optional cancellation for adapter-owned asynchronous lookup.
3704
+ * @returns exact model identity plus available context and reasoning metadata.
3705
+ */
3706
+ async resolveModelInfo(provider, model, signal) {
3707
+ return this.resolveModelInfoFor(this.registration(provider), model, signal);
3708
+ }
3709
+ async resolveModelInfoFor(registration, model, signal) {
3710
+ const resolved = await registration.adapter.resolveModel(registration.provider.id, model, signal);
3711
+ return this.normalizeModelInfo(registration, model, resolved);
3712
+ }
3713
+ /** Validate and detach one adapter-returned exact model result. */
3714
+ normalizeModelInfo(registration, model, resolved) {
3715
+ const provider = registration.provider.id;
3716
+ if (typeof resolved.provider !== "string" || resolved.provider !== provider || typeof resolved.id !== "string" || resolved.id !== model || typeof resolved.name !== "string" || resolved.name.length === 0 || resolved.description !== void 0 && typeof resolved.description !== "string") throw new LlmError(`adapter returned invalid exact model metadata for provider "${provider}" model "${model}"`, "INVALID_MODEL_INFO");
3717
+ const context = resolved.context;
3718
+ if (context !== void 0 && (!Number.isInteger(context.contextWindow) || context.contextWindow <= 0)) throw new LlmError(`adapter returned invalid context metadata for provider "${provider}" model "${model}"`, "INVALID_MODEL_CONTEXT");
3719
+ const inputModalities = this.detachedModalities(resolved.inputModalities);
3720
+ const systemPromptUpdate = resolved.systemPromptUpdate;
3721
+ if (systemPromptUpdate !== void 0 && systemPromptUpdate !== "in-history") throw new LlmError(`adapter returned invalid system prompt update mode for provider "${provider}" model "${model}"`, "INVALID_MODEL_INFO");
3722
+ const defaultMaxTokens = resolved.defaultMaxTokens;
3723
+ if (defaultMaxTokens !== void 0 && (!Number.isSafeInteger(defaultMaxTokens) || defaultMaxTokens <= 0)) throw new LlmError(`adapter returned invalid default maxTokens for provider "${provider}" model "${model}"`, "INVALID_MODEL_MAX_TOKENS");
3724
+ const info = {
3725
+ provider,
3726
+ id: model,
3727
+ name: resolved.name,
3728
+ ...resolved.description === void 0 ? {} : { description: resolved.description },
3729
+ ...inputModalities === void 0 ? {} : { inputModalities },
3730
+ ...context === void 0 ? {} : { context: { contextWindow: context.contextWindow } },
3731
+ ...defaultMaxTokens === void 0 ? {} : { defaultMaxTokens },
3732
+ ...resolved.systemPromptUpdate === void 0 ? {} : { systemPromptUpdate: resolved.systemPromptUpdate }
3733
+ };
3734
+ const reasoning = resolved.reasoning;
3735
+ if (reasoning === void 0) return info;
3736
+ if (reasoning.efforts.length === 0) throw new LlmError(`adapter returned invalid reasoning metadata for provider "${provider}" model "${model}"`, "INVALID_MODEL_REASONING");
3737
+ const seen = /* @__PURE__ */ new Set();
3738
+ const efforts = reasoning.efforts.map((effort) => {
3739
+ if (typeof effort.id !== "string" || effort.id.length === 0 || typeof effort.name !== "string" || effort.name.length === 0 || effort.description !== void 0 && typeof effort.description !== "string" || seen.has(effort.id)) throw new LlmError(`adapter returned invalid or duplicate reasoning effort metadata for provider "${provider}" model "${model}"`, "INVALID_MODEL_REASONING");
3740
+ seen.add(effort.id);
3741
+ return {
3742
+ id: effort.id,
3743
+ name: effort.name,
3744
+ ...effort.description === void 0 ? {} : { description: effort.description }
3745
+ };
3746
+ });
3747
+ if (reasoning.defaultEffort !== void 0 && !seen.has(reasoning.defaultEffort)) throw new LlmError(`adapter returned an unknown default reasoning effort for provider "${provider}" model "${model}"`, "INVALID_MODEL_REASONING");
3748
+ return {
3749
+ ...info,
3750
+ reasoning: {
3751
+ efforts,
3752
+ ...reasoning.defaultEffort === void 0 ? {} : { defaultEffort: reasoning.defaultEffort }
3753
+ }
3754
+ };
3755
+ }
3756
+ /**
3757
+ * Validate a conversation call config against its exact model capability and
3758
+ * materialize adapter-configured defaults. Unsupported explicit efforts
3759
+ * reject before provider I/O; no clamping or aliasing is performed. This
3760
+ * standalone query does not bind a later dispatch; use {@link prepareCall}
3761
+ * when logging and streaming must share one adapter registration.
3762
+ * @param config - provider/model route and optional request controls.
3763
+ * @param signal - optional cancellation for adapter-owned capability lookup.
3764
+ * @returns a detached config only when a default must be materialized.
3765
+ */
3766
+ async resolveCallConfig(config, signal) {
3767
+ return (await this.resolveCallFor(this.registration(config.provider), config, signal)).config;
3768
+ }
3769
+ async resolveCallFor(registration, config, signal) {
3770
+ const info = await this.resolveModelInfoFor(registration, config.model, signal);
3771
+ return this.resolveCallWithInfo(config, info);
3772
+ }
3773
+ /** Validate request controls against one already-bound exact model result. */
3774
+ resolveCallWithInfo(config, info) {
3775
+ const defaulted = config.maxTokens === void 0 && info.defaultMaxTokens !== void 0 ? {
3776
+ ...config,
3777
+ maxTokens: info.defaultMaxTokens
3778
+ } : config;
3779
+ const reasoning = info.reasoning;
3780
+ const requested = defaulted.reasoningEffort;
3781
+ let resolvedConfig = defaulted;
3782
+ if (reasoning === void 0) {
3783
+ if (requested !== void 0) throw new LlmError(`provider "${config.provider}" model "${config.model}" does not support reasoning effort "${requested}"`, "UNSUPPORTED_REASONING_EFFORT");
3784
+ } else {
3785
+ const effective = requested ?? reasoning.defaultEffort;
3786
+ if (effective !== void 0) {
3787
+ if (!reasoning.efforts.some((effort) => effort.id === effective)) throw new LlmError(`provider "${config.provider}" model "${config.model}" does not support reasoning effort "${effective}"`, "UNSUPPORTED_REASONING_EFFORT");
3788
+ if (requested !== effective) resolvedConfig = {
3789
+ ...defaulted,
3790
+ reasoningEffort: effective
3791
+ };
3792
+ }
3793
+ }
3794
+ return {
3795
+ config: resolvedConfig,
3796
+ ...info.context === void 0 ? {} : { context: info.context },
3797
+ modelInfo: info
3798
+ };
3799
+ }
3800
+ /**
3801
+ * Resolve one call under its current adapter registration. The returned
3802
+ * one-shot handle keeps that registration across header logging and dispatch,
3803
+ * so HMR cannot combine one adapter's capability result with another adapter.
3804
+ * @param config - provider/model route and optional request controls.
3805
+ * @param signal - optional cancellation for adapter-owned capability lookup.
3806
+ * @returns a prepared config and its registration-bound stream entry point.
3807
+ */
3808
+ async prepareCall(config, signal) {
3809
+ const registration = this.registration(config.provider);
3810
+ const adapterCall = await registration.adapter.prepareCall(config.provider, config.model, signal);
3811
+ const modelInfo = this.normalizeModelInfo(registration, config.model, adapterCall.model);
3812
+ const resolved = this.resolveCallWithInfo(config, modelInfo);
3813
+ const resolvedConfig = deepFreeze(structuredClone(resolved.config));
3814
+ const context = resolved.context === void 0 ? void 0 : deepFreeze(structuredClone(resolved.context));
3815
+ const adapterDefaults = deepFreeze({
3816
+ ...config.reasoningEffort === void 0 && resolvedConfig.reasoningEffort !== void 0 ? { reasoningEffort: true } : {},
3817
+ ...config.maxTokens === void 0 && resolvedConfig.maxTokens !== void 0 ? { maxTokens: true } : {}
3818
+ });
3819
+ let dispatched = false;
3820
+ return Object.freeze({
3821
+ config: resolvedConfig,
3822
+ retryPolicy: registration.retryPolicy,
3823
+ adapterDefaults,
3824
+ ...context === void 0 ? {} : { context },
3825
+ ...modelInfo.inputModalities === void 0 ? {} : { inputModalities: Object.freeze([...modelInfo.inputModalities]) },
3826
+ ...modelInfo.systemPromptUpdate === void 0 ? {} : { systemPromptUpdate: modelInfo.systemPromptUpdate },
3827
+ stream: (options) => {
3828
+ if (dispatched) throw new LlmError("a prepared LLM call can only be dispatched once", "INVALID_PREPARED_CALL");
3829
+ if (!callConfigEquals(options, resolvedConfig)) throw new LlmError("prepared LLM call config changed before adapter dispatch", "INVALID_PREPARED_CALL");
3830
+ dispatched = true;
3831
+ return this.streamWithRegistration(options, {
3832
+ registration,
3833
+ config: resolvedConfig,
3834
+ modelInfo,
3835
+ dispatch: (options) => adapterCall.stream(options)
3836
+ });
3837
+ }
3838
+ });
3839
+ }
3840
+ registration(provider) {
3841
+ const registration = this.adapters.get(provider);
3842
+ if (!registration) throw new LlmError(`no adapter registered for provider "${provider}"`, "NO_ADAPTER");
3843
+ return registration;
3844
+ }
3845
+ /** Remove replay state whose historical route is owned by another adapter. */
3846
+ forAdapter(options, adapter) {
3847
+ const messages = options.messages.map((message) => {
3848
+ const source = message.source;
3849
+ if (message.role !== "assistant" || source.kind !== "model" || source.replayState === void 0) return message;
3850
+ if (this.adapters.get(source.provider)?.adapter === adapter) return message;
3851
+ return freezeMessage({
3852
+ ...message,
3853
+ source: {
3854
+ kind: "model",
3855
+ provider: source.provider,
3856
+ model: source.model
3857
+ }
3858
+ });
3859
+ });
3860
+ if (messages.every((message, index) => message === options.messages[index])) return options;
3861
+ const filtered = {
3862
+ ...options,
3863
+ messages
3864
+ };
3865
+ return Object.isFrozen(options) ? deepFreeze(filtered) : filtered;
3866
+ }
3867
+ /**
3868
+ * Resolve the current execution-world read path of one durable file
3869
+ * reference through the mounted attachment and filesystem providers.
3870
+ */
3871
+ fileReadPath(ref) {
3872
+ let hostPath;
3873
+ try {
3874
+ hostPath = this.ctx.get("attachments")?.fileHostPath(ref);
3875
+ } catch {
3876
+ return;
3877
+ }
3878
+ if (hostPath === void 0) return void 0;
3879
+ return this.ctx.get("fs")?.processPathFromHostPath(hostPath);
3880
+ }
3881
+ /**
3882
+ * Final adapter boundary. Adapter selection, dispatch, iterator construction,
3883
+ * and iteration failures become one terminal failure chunk. Middleware and
3884
+ * downstream consumer failures remain thrown plugin or consumer errors.
3885
+ */
3886
+ async *adapterStream(options, prepared) {
3887
+ let iterator;
3888
+ try {
3889
+ const registration = prepared?.registration ?? this.registration(options.provider);
3890
+ const adapter = registration.adapter;
3891
+ let modelInfo;
3892
+ let resolvedConfig;
3893
+ let dispatch;
3894
+ if (prepared === void 0) {
3895
+ const adapterCall = await adapter.prepareCall(options.provider, options.model, options.signal);
3896
+ modelInfo = this.normalizeModelInfo(registration, options.model, adapterCall.model);
3897
+ resolvedConfig = this.resolveCallWithInfo(options, modelInfo).config;
3898
+ dispatch = (options) => adapterCall.stream(options);
3899
+ } else {
3900
+ modelInfo = prepared.modelInfo;
3901
+ resolvedConfig = prepared.config;
3902
+ dispatch = prepared.dispatch;
3903
+ }
3904
+ if (prepared !== void 0 && !callConfigEquals(options, resolvedConfig)) throw new LlmError("prepared LLM call config changed before adapter dispatch", "INVALID_PREPARED_CALL");
3905
+ const resolvedOptions = callConfigEquals(options, resolvedConfig) ? options : Object.isFrozen(options) ? deepFreeze({
3906
+ ...options,
3907
+ ...resolvedConfig
3908
+ }) : {
3909
+ ...options,
3910
+ ...resolvedConfig
3911
+ };
3912
+ let projectedMessages = resolvedOptions.messages;
3913
+ if (projectedMessages.some((message) => contentHasFile(message.content))) projectedMessages = projectFilesToText(projectedMessages, (ref) => this.fileReadPath(ref));
3914
+ if (modelInfo.inputModalities !== void 0 && !modelInfo.inputModalities.includes("image") && projectedMessages.some((message) => contentHasImage(message.content))) projectedMessages = projectImagesForTextModel(projectedMessages);
3915
+ const projectedOptions = projectedMessages === resolvedOptions.messages ? resolvedOptions : Object.isFrozen(resolvedOptions) ? deepFreeze({
3916
+ ...resolvedOptions,
3917
+ messages: projectedMessages
3918
+ }) : {
3919
+ ...resolvedOptions,
3920
+ messages: projectedMessages
3921
+ };
3922
+ iterator = dispatch(this.forAdapter(projectedOptions, adapter))[Symbol.asyncIterator]();
3923
+ } catch (error) {
3924
+ yield adapterFailureChunk(error, options.signal);
3925
+ return;
3926
+ }
3927
+ let completed = false;
3928
+ try {
3929
+ while (true) {
3930
+ let item;
3931
+ try {
3932
+ const next = await iterator.next();
3933
+ item = next.done ? { done: true } : {
3934
+ done: false,
3935
+ value: next.value
3936
+ };
3937
+ } catch (error) {
3938
+ completed = true;
3939
+ yield adapterFailureChunk(error, options.signal);
3940
+ return;
3941
+ }
3942
+ if (item.done) {
3943
+ completed = true;
3944
+ return;
3945
+ }
3946
+ yield item.value;
3947
+ }
3948
+ } finally {
3949
+ if (!completed) {
3950
+ const close = iterator.return?.bind(iterator);
3951
+ if (close) await close();
3952
+ }
3953
+ }
3954
+ }
3955
+ /**
3956
+ * Stream one model call as raw chunks (token-level deltas). Replay state is
3957
+ * retained only when the same adapter instance owns its historical provider
3958
+ * and the target provider. Final adapter selection remains fixed through
3959
+ * asynchronous exact-model resolution and dispatch. Adapter selection,
3960
+ * dispatch, and iteration failures become terminal `error` or `aborted`
3961
+ * finish chunks; middleware, nested-call, cleanup, and consumer failures
3962
+ * remain thrown.
3963
+ * @param options - the full request; `options.provider` selects the adapter.
3964
+ * @returns the chunk stream, possibly wrapped by `llm/stream` listeners.
3965
+ */
3966
+ stream(options) {
3967
+ return this.streamWithRegistration(options);
3968
+ }
3969
+ streamWithRegistration(options, prepared) {
3970
+ return this.ctx.waterfall(this, "llm/stream", options, () => this.adapterStream(options, prepared));
3971
+ }
3972
+ };
3973
+ })();
3974
+ /** Convert one adapter throw into the stream protocol's terminal outcome. */
3975
+ function adapterFailureChunk(error, signal) {
3976
+ const failure = normalizeLlmFailure(error);
3977
+ return {
3978
+ type: "finish",
3979
+ reason: signal?.aborted || failure.code === "ABORTED" ? {
3980
+ kind: "aborted",
3981
+ failure
3982
+ } : {
3983
+ kind: "error",
3984
+ failure
3985
+ }
3986
+ };
3987
+ }
3988
+ //#endregion
1
3989
  //#region src/trust-fence.ts
2
3990
  function header(headers, name) {
3
3991
  const value = headers[name];
@@ -53,16 +4041,6 @@ function isTrustedApiRequest(request, trustedHosts) {
53
4041
  }
54
4042
  //#endregion
55
4043
  //#region src/index.ts
56
- let createUserMessageCached;
57
- async function loadCreateUserMessage() {
58
- if (createUserMessageCached !== void 0) return createUserMessageCached;
59
- try {
60
- createUserMessageCached = (await import("./lib-DHFe7-hr.js")).createUserMessage;
61
- } catch {
62
- createUserMessageCached = null;
63
- }
64
- return createUserMessageCached;
65
- }
66
4044
  /** Plugin identity for cordis.yml rows. */
67
4045
  const name = "dsh-sidenote";
68
4046
  const MAX_BODY_BYTES = 65536;
@@ -131,14 +4109,6 @@ function makeReflowHandler(ctx) {
131
4109
  });
132
4110
  return;
133
4111
  }
134
- const createUserMessage = await loadCreateUserMessage();
135
- if (createUserMessage === null) {
136
- writeJson(res, 200, {
137
- ok: false,
138
- error: "dsh-llm-unavailable"
139
- });
140
- return;
141
- }
142
4112
  for (const item of valid) {
143
4113
  const sideTitle = typeof item.sideTitle === "string" ? item.sideTitle : "";
144
4114
  const summary = (sideTitle === "" ? "侧边聊天的结论回流" : `来自「${sideTitle}」的结论回流`).slice(0, 120);