返回 CodeWhale
skills.mjs
根目录 / crates / tui / extension-host / dist / skills.mjs
1 // generated by crates/tui/extension-host/build.mjs from src/shims/skills.ts; do not edit.
2
3 // node_modules/@deepseek-ai/cosmokit/lib/index.js
4 function isNullable(value) {
5 return value === null || value === void 0;
6 }
7 function defineProperty(object, key, value) {
8 return Object.defineProperty(object, key, {
9 writable: true,
10 value,
11 enumerable: false
12 });
13 }
14 function is(type, value) {
15 if (arguments.length === 1) return (value2) => is(type, value2);
16 return type in globalThis && value instanceof globalThis[type] || Object.prototype.toString.call(value).slice(8, -1) === type;
17 }
18 function isArrayBufferLike(value) {
19 return is("ArrayBuffer", value) || is("SharedArrayBuffer", value);
20 }
21 function isArrayBufferSource(value) {
22 return isArrayBufferLike(value) || ArrayBuffer.isView(value);
23 }
24 var Binary;
25 (function(Binary2) {
26 Binary2.is = isArrayBufferLike;
27 Binary2.isSource = isArrayBufferSource;
28 function fromSource(source) {
29 if (ArrayBuffer.isView(source)) return source.buffer.slice(source.byteOffset, source.byteOffset + source.byteLength);
30 else return source;
31 }
32 Binary2.fromSource = fromSource;
33 function toBase64(source) {
34 source = fromSource(source);
35 if (typeof Buffer !== "undefined") return Buffer.from(source).toString("base64");
36 let binary = "";
37 const bytes = new Uint8Array(source);
38 for (let i = 0; i < bytes.byteLength; i++) binary += String.fromCharCode(bytes[i]);
39 return btoa(binary);
40 }
41 Binary2.toBase64 = toBase64;
42 function fromBase64(source) {
43 if (typeof Buffer !== "undefined") return fromSource(Buffer.from(source, "base64"));
44 return Uint8Array.from(atob(source), (c) => c.charCodeAt(0));
45 }
46 Binary2.fromBase64 = fromBase64;
47 function toHex(source) {
48 source = fromSource(source);
49 if (typeof Buffer !== "undefined") return Buffer.from(source).toString("hex");
50 return Array.from(new Uint8Array(source), (byte) => byte.toString(16).padStart(2, "0")).join("");
51 }
52 Binary2.toHex = toHex;
53 function fromHex(source) {
54 if (typeof Buffer !== "undefined") return fromSource(Buffer.from(source, "hex"));
55 const hex = source.length % 2 === 0 ? source : source.slice(0, source.length - 1);
56 const buffer = [];
57 for (let i = 0; i < hex.length; i += 2) buffer.push(parseInt(`${hex[i]}${hex[i + 1]}`, 16));
58 return Uint8Array.from(buffer).buffer;
59 }
60 Binary2.fromHex = fromHex;
61 })(Binary || (Binary = {}));
62 var base64ToArrayBuffer = Binary.fromBase64;
63 var arrayBufferToBase64 = Binary.toBase64;
64 var hexToArrayBuffer = Binary.fromHex;
65 var arrayBufferToHex = Binary.toHex;
66 function tokenize(source, delimiters, delimiter) {
67 const output = [];
68 let state = 0;
69 for (let i = 0; i < source.length; i++) {
70 const code = source.charCodeAt(i);
71 if (code >= 65 && code <= 90) {
72 if (state === 1) {
73 const next = source.charCodeAt(i + 1);
74 if (next >= 97 && next <= 122) output.push(delimiter);
75 output.push(code + 32);
76 } else {
77 if (state !== 0) output.push(delimiter);
78 output.push(code + 32);
79 }
80 state = 1;
81 } else if (code >= 97 && code <= 122) {
82 output.push(code);
83 state = 2;
84 } else if (delimiters.includes(code)) {
85 if (state !== 0) output.push(delimiter);
86 state = 0;
87 } else output.push(code);
88 }
89 return String.fromCharCode(...output);
90 }
91 function paramCase(source) {
92 return tokenize(source, [45, 95], 45);
93 }
94 var hyphenate = paramCase;
95 var Time;
96 (function(Time2) {
97 Time2.millisecond = 1;
98 Time2.second = 1e3;
99 Time2.minute = Time2.second * 60;
100 Time2.hour = Time2.minute * 60;
101 Time2.day = Time2.hour * 24;
102 Time2.week = Time2.day * 7;
103 let timezoneOffset = (/* @__PURE__ */ new Date()).getTimezoneOffset();
104 function setTimezoneOffset(offset) {
105 timezoneOffset = offset;
106 }
107 Time2.setTimezoneOffset = setTimezoneOffset;
108 function getTimezoneOffset() {
109 return timezoneOffset;
110 }
111 Time2.getTimezoneOffset = getTimezoneOffset;
112 function getDateNumber(date = /* @__PURE__ */ new Date(), offset) {
113 if (typeof date === "number") date = new Date(date);
114 if (offset === void 0) offset = timezoneOffset;
115 return Math.floor((date.valueOf() / Time2.minute - offset) / 1440);
116 }
117 Time2.getDateNumber = getDateNumber;
118 function fromDateNumber(value, offset) {
119 const date = new Date(value * Time2.day);
120 if (offset === void 0) offset = timezoneOffset;
121 return new Date(+date + offset * Time2.minute);
122 }
123 Time2.fromDateNumber = fromDateNumber;
124 const numeric = /\d+(?:\.\d+)?/.source;
125 const timeRegExp = new RegExp(`^${[
126 "w(?:eek(?:s)?)?",
127 "d(?:ay(?:s)?)?",
128 "h(?:our(?:s)?)?",
129 "m(?:in(?:ute)?(?:s)?)?",
130 "s(?:ec(?:ond)?(?:s)?)?"
131 ].map((unit) => `(${numeric}${unit})?`).join("")}$`);
132 function parseTime(source) {
133 const capture = timeRegExp.exec(source);
134 if (!capture) return 0;
135 return (parseFloat(capture[1]) * Time2.week || 0) + (parseFloat(capture[2]) * Time2.day || 0) + (parseFloat(capture[3]) * Time2.hour || 0) + (parseFloat(capture[4]) * Time2.minute || 0) + (parseFloat(capture[5]) * Time2.second || 0);
136 }
137 Time2.parseTime = parseTime;
138 function parseDate(date) {
139 const parsed = parseTime(date);
140 if (parsed) date = Date.now() + parsed;
141 else if (/^\d{1,2}(:\d{1,2}){1,2}$/.test(date)) date = `${(/* @__PURE__ */ new Date()).toLocaleDateString()}-${date}`;
142 else if (/^\d{1,2}-\d{1,2}-\d{1,2}(:\d{1,2}){1,2}$/.test(date)) date = `${(/* @__PURE__ */ new Date()).getFullYear()}-${date}`;
143 return date ? new Date(date) : /* @__PURE__ */ new Date();
144 }
145 Time2.parseDate = parseDate;
146 function format(ms) {
147 const abs = Math.abs(ms);
148 if (abs >= Time2.day - Time2.hour / 2) return Math.round(ms / Time2.day) + "d";
149 else if (abs >= Time2.hour - Time2.minute / 2) return Math.round(ms / Time2.hour) + "h";
150 else if (abs >= Time2.minute - Time2.second / 2) return Math.round(ms / Time2.minute) + "m";
151 else if (abs >= Time2.second) return Math.round(ms / Time2.second) + "s";
152 return ms + "ms";
153 }
154 Time2.format = format;
155 function toDigits(source, length = 2) {
156 return source.toString().padStart(length, "0");
157 }
158 Time2.toDigits = toDigits;
159 function template(template2, time = /* @__PURE__ */ new Date()) {
160 return template2.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));
161 }
162 Time2.template = template;
163 })(Time || (Time = {}));
164
165 // node_modules/@deepseek-ai/cordis/lib/index.js
166 var DisposableList = class {
167 sn = 0;
168 map = /* @__PURE__ */ new Map();
169 weak = /* @__PURE__ */ new WeakMap();
170 get length() {
171 return this.map.size;
172 }
173 push(value) {
174 const sn = ++this.sn;
175 this.map.set(sn, value);
176 this.weak.set(value, sn);
177 return () => this.map.delete(sn);
178 }
179 delete(value) {
180 const sn = this.weak.get(value);
181 if (!sn) return false;
182 return this.map.delete(sn);
183 }
184 clear() {
185 const values = [...this.map.values()];
186 this.map.clear();
187 return values.reverse();
188 }
189 [Symbol.iterator]() {
190 return this.map.values();
191 }
192 [/* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom")]() {
193 return [...this];
194 }
195 };
196 var symbols = {
197 shadow: /* @__PURE__ */ Symbol.for("cordis.shadow"),
198 receiver: /* @__PURE__ */ Symbol.for("cordis.receiver"),
199 original: /* @__PURE__ */ Symbol.for("cordis.original"),
200 metadata: /* @__PURE__ */ Symbol.for("cordis.metadata"),
201 initHooks: /* @__PURE__ */ Symbol.for("cordis.initHooks"),
202 checkProto: /* @__PURE__ */ Symbol.for("cordis.checkProto"),
203 effect: /* @__PURE__ */ Symbol.for("cordis.effect"),
204 filter: /* @__PURE__ */ Symbol.for("cordis.filter"),
205 isolate: /* @__PURE__ */ Symbol.for("cordis.isolate"),
206 intercept: /* @__PURE__ */ Symbol.for("cordis.intercept"),
207 init: /* @__PURE__ */ Symbol.for("cordis.init"),
208 check: /* @__PURE__ */ Symbol.for("cordis.check"),
209 config: /* @__PURE__ */ Symbol.for("cordis.config"),
210 invoke: /* @__PURE__ */ Symbol.for("cordis.invoke"),
211 extend: /* @__PURE__ */ Symbol.for("cordis.extend"),
212 tracker: /* @__PURE__ */ Symbol.for("cordis.tracker"),
213 resolveConfig: /* @__PURE__ */ Symbol.for("cordis.resolveConfig")
214 };
215 var GeneratorFunction = function* () {
216 }.constructor;
217 var AsyncGeneratorFunction = async function* () {
218 }.constructor;
219 function isConstructor(func) {
220 if (!func.prototype) return false;
221 if (func instanceof GeneratorFunction) return false;
222 if (AsyncGeneratorFunction !== Function && func instanceof AsyncGeneratorFunction) return false;
223 return true;
224 }
225 function joinPrototype(proto1, proto2) {
226 if (proto1 === Object.prototype) return proto2;
227 const result = Object.create(joinPrototype(Object.getPrototypeOf(proto1), proto2));
228 for (const key of Reflect.ownKeys(proto1)) Object.defineProperty(result, key, Object.getOwnPropertyDescriptor(proto1, key));
229 return result;
230 }
231 function isObject(value) {
232 return value && (typeof value === "object" || typeof value === "function");
233 }
234 function getPropertyDescriptor(target, prop) {
235 let proto = target;
236 while (proto) {
237 const desc = Reflect.getOwnPropertyDescriptor(proto, prop);
238 if (desc) return desc;
239 proto = Object.getPrototypeOf(proto);
240 }
241 }
242 function getTraceable(ctx, value) {
243 if (!isObject(value)) return value;
244 if (Object.hasOwn(value, symbols.shadow)) return Object.getPrototypeOf(value);
245 const tracker = value[symbols.tracker];
246 if (!tracker) return value;
247 return createTraceable(ctx, value, tracker);
248 }
249 function withProps(target, props) {
250 if (!props) return target;
251 return new Proxy(target, {
252 get: (target2, prop, receiver) => {
253 if (prop in props && prop !== "constructor") return Reflect.get(props, prop, receiver);
254 return Reflect.get(target2, prop, receiver);
255 },
256 set: (target2, prop, value, receiver) => {
257 if (prop in props && prop !== "constructor") return Reflect.set(props, prop, value, receiver);
258 return Reflect.set(target2, prop, value, receiver);
259 }
260 });
261 }
262 function withProp(target, prop, value) {
263 return withProps(target, Object.defineProperty(/* @__PURE__ */ Object.create(null), prop, {
264 value,
265 writable: false
266 }));
267 }
268 function createShadow(ctx, target, property, receiver) {
269 if (!property) return receiver;
270 const origin = Reflect.getOwnPropertyDescriptor(target, property)?.value;
271 if (!origin) return receiver;
272 return withProp(receiver, property, ctx.extend({ [symbols.shadow]: origin }));
273 }
274 function createShadowMethod(ctx, value, outer, shadow) {
275 return new Proxy(value, { apply: (target, thisArg, args) => {
276 if (thisArg === outer) thisArg = shadow;
277 return getTraceable(ctx, Reflect.apply(target, thisArg, args));
278 } });
279 }
280 function createTraceable(ctx, value, tracker) {
281 if (ctx[symbols.shadow] && !tracker.noShadow) ctx = Object.getPrototypeOf(ctx);
282 const proxy = new Proxy(value, {
283 get: (target, prop, receiver) => {
284 if (prop === symbols.original) return target;
285 if (prop === tracker.property) return ctx;
286 if (typeof prop === "symbol") return Reflect.get(target, prop, receiver);
287 if (tracker.associate && ctx.reflect.props[`${tracker.associate}.${prop}`]) return Reflect.get(ctx, `${tracker.associate}.${prop}`, withProp(ctx, symbols.receiver, receiver));
288 let shadow, innerValue;
289 const desc = getPropertyDescriptor(target, prop);
290 if (desc && "value" in desc) innerValue = desc.value;
291 else {
292 shadow = createShadow(ctx, target, tracker.property, receiver);
293 innerValue = Reflect.get(target, prop, shadow);
294 }
295 const innerTracker = innerValue?.[symbols.tracker];
296 if (innerTracker) return createTraceable(ctx, innerValue, innerTracker);
297 else if (!tracker.noShadow && typeof innerValue === "function") {
298 shadow ??= createShadow(ctx, target, tracker.property, receiver);
299 return createShadowMethod(ctx, innerValue, receiver, shadow);
300 } else return innerValue;
301 },
302 set: (target, prop, value2, receiver) => {
303 if (prop === symbols.original) return false;
304 if (prop === tracker.property) return false;
305 if (typeof prop === "symbol") return Reflect.set(target, prop, value2, receiver);
306 if (tracker.associate && ctx.reflect.props[`${tracker.associate}.${prop}`]) return Reflect.set(ctx, `${tracker.associate}.${prop}`, value2, withProp(ctx, symbols.receiver, receiver));
307 const shadow = createShadow(ctx, target, tracker.property, receiver);
308 return Reflect.set(target, prop, value2, shadow);
309 },
310 apply: (target, thisArg, args) => {
311 return applyTraceable(proxy, target, thisArg, args);
312 }
313 });
314 return proxy;
315 }
316 function applyTraceable(proxy, value, thisArg, args) {
317 if (!value[symbols.invoke]) return Reflect.apply(value, thisArg, args);
318 return value[symbols.invoke].apply(proxy, args);
319 }
320 function createCallable(name, proto, tracker) {
321 const self = function(...args) {
322 return applyTraceable(createTraceable(self["ctx"], self, tracker), self, this, args);
323 };
324 defineProperty(self, "name", name);
325 return Object.setPrototypeOf(self, proto);
326 }
327 function handleError(info, reason, getOuterStack) {
328 const innerLines = info.error.stack.split("\n");
329 if (typeof reason?.stack !== "string") {
330 const outerError = new Error(reason);
331 const lines2 = outerError.stack.split("\n");
332 lines2.splice(1, Infinity, ...getOuterStack());
333 outerError.stack = lines2.join("\n");
334 throw outerError;
335 }
336 const lines = reason.stack.split("\n");
337 let index = lines.indexOf(innerLines[2]);
338 if (index === -1) throw reason;
339 index -= info.offset;
340 while (index > 0) {
341 if (!lines[index - 1].endsWith(" (<anonymous>)")) break;
342 index -= 1;
343 }
344 lines.splice(index, Infinity, ...getOuterStack());
345 reason.stack = lines.join("\n");
346 throw reason;
347 }
348 function composeError(callback, getOuterStack = buildOuterStack()) {
349 const info = {
350 offset: 1,
351 error: /* @__PURE__ */ new Error()
352 };
353 try {
354 const result = callback(info);
355 if (isObject(result) && "then" in result) return result.then(void 0, (reason) => handleError(info, reason, getOuterStack));
356 else return result;
357 } catch (reason) {
358 handleError(info, reason, getOuterStack);
359 }
360 }
361 function buildOuterStack(offset = 0) {
362 const outerError = /* @__PURE__ */ new Error();
363 return () => outerError.stack.split("\n").slice(3 + offset);
364 }
365 function isBailed(value) {
366 return value !== null && value !== false && value !== void 0;
367 }
368 var EventsService = class {
369 ctx;
370 _hooks = {};
371 constructor(ctx) {
372 this.ctx = ctx;
373 defineProperty(this, symbols.tracker, {
374 property: "ctx",
375 noShadow: true
376 });
377 this.on("internal/listener", function(name, listener, options) {
378 if (name === "internal/update" && !options.global) return (this.fiber._hooks["internal/update"] ??= new DisposableList())[options.prepend ? "unshift" : "push"](listener);
379 });
380 this.on("internal/update", function(config, noSave, next) {
381 const cbs = [...this._hooks["internal/update"] || []];
382 const _next = () => {
383 return (cbs.shift() ?? next).call(this, config, noSave, _next);
384 };
385 return _next();
386 }, {
387 global: true,
388 prepend: true
389 });
390 }
391 /**
392 * Resolve listeners for one dispatch and apply context filtering.
393 *
394 * @param type — the dispatch mode, reported on `internal/dispatch`.
395 * @param args — the raw dispatch arguments; consumed up to the event name.
396 * @returns the matching listener callbacks, bound to the dispatch `this`.
397 */
398 dispatch(type, args) {
399 const thisArg = typeof args[0] === "object" || typeof args[0] === "function" ? args.shift() : null;
400 const name = args.shift();
401 if (!name.startsWith("internal/")) this.emit("internal/dispatch", type, name, args, thisArg);
402 const filter = thisArg?.[Context.filter];
403 return (this._hooks[name] || []).filter((hook) => hook.global || !filter || filter.call(thisArg, hook.ctx)).map((hook) => hook.callback.bind(thisArg));
404 }
405 /**
406 * Run listeners concurrently and wait for all of them.
407 *
408 * @param args — optional `this`, the event name, then listener arguments.
409 * @returns a promise resolving once every listener has settled.
410 */
411 async parallel(...args) {
412 const errors = (await Promise.allSettled(this.dispatch("emit", args).map(async (cb) => cb(...args)))).filter((result) => result.status === "rejected");
413 if (errors.length) throw new AggregateError(errors.map((error) => error.reason));
414 }
415 /**
416 * Run listeners synchronously without waiting for returned promises.
417 *
418 * @param args — optional `this`, the event name, then listener arguments.
419 */
420 emit(...args) {
421 this.dispatch("emit", args).map((cb) => cb(...args));
422 }
423 /**
424 * Run listeners in order, awaiting each, until one returns a bail value.
425 *
426 * @param args — optional `this`, the event name, then listener arguments.
427 * @returns the first bail value (see {@link isBailed}), if any.
428 */
429 async serial(...args) {
430 for (const cb of this.dispatch("serial", args)) {
431 const result = await cb(...args);
432 if (isBailed(result)) return result;
433 }
434 }
435 /**
436 * Run listeners synchronously until one returns a bail value.
437 *
438 * @param args — optional `this`, the event name, then listener arguments.
439 * @returns the first bail value (see {@link isBailed}), if any.
440 */
441 bail(...args) {
442 for (const cb of this.dispatch("bail", args)) {
443 const result = cb(...args);
444 if (isBailed(result)) return result;
445 }
446 }
447 /**
448 * Compose listeners around the final `next` callback.
449 *
450 * The last dispatch argument is treated as the innermost `next`. Listeners
451 * run outermost-first; a listener that does not call `next()` vetoes the
452 * rest of the chain, including the built-in behavior.
453 *
454 * @param args — optional `this`, the event name, listener arguments, then `next`.
455 * @returns the outermost listener's return value.
456 */
457 waterfall(...args) {
458 const cbs = this.dispatch("waterfall", args);
459 const inner = args.pop();
460 const next = () => {
461 return (cbs.shift() ?? inner)(...args);
462 };
463 args.push(next);
464 return next();
465 }
466 /**
467 * Store a listener record as an effect on the current fiber.
468 *
469 * @param label — effect label shown in fiber diagnostics.
470 * @param hooks — the listener list for one event.
471 * @param callback — the listener to store.
472 * @param options — placement and filtering options.
473 * @returns a disposer that unregisters the listener.
474 */
475 register(label, hooks, callback, options) {
476 const method = options.prepend ? "unshift" : "push";
477 return this.ctx.fiber.effect(() => {
478 hooks[method]({
479 ctx: this.ctx,
480 callback,
481 ...options
482 });
483 return () => this.unregister(hooks, callback);
484 }, label);
485 }
486 /**
487 * Remove a stored listener record.
488 *
489 * @param hooks — the listener list for one event.
490 * @param callback — the listener to remove.
491 * @returns `true` if the listener was found and removed.
492 */
493 unregister(hooks, callback) {
494 const index = hooks.findIndex((hook) => hook.callback === callback);
495 if (index >= 0) {
496 hooks.splice(index, 1);
497 return true;
498 }
499 }
500 /**
501 * Register an event listener owned by the current fiber.
502 *
503 * The listener is removed automatically when the fiber unloads. Throws
504 * `CordisError('INACTIVE_EFFECT')` if the fiber is already disposed.
505 *
506 * @param name — the event name to listen for.
507 * @param listener — called with the dispatch arguments.
508 * @param options — listener options; a boolean is shorthand for `prepend`.
509 * @returns a disposer removing the listener; `true` if it was still registered.
510 */
511 on(name, listener, options) {
512 if (typeof options !== "object") options = { prepend: options };
513 this.ctx.fiber.assertActive();
514 listener = this.ctx.reflect.bind(listener);
515 const result = this.bail(this.ctx, "internal/listener", name, listener, options);
516 if (result) return result;
517 const hooks = this._hooks[name] ||= [];
518 const label = `ctx.on(${typeof name === "string" ? JSON.stringify(name) : name.toString()})`;
519 return this.register(label, hooks, listener, options);
520 }
521 /**
522 * Register an event listener that disposes itself after the first call.
523 *
524 * @param name — the event name to listen for.
525 * @param listener — called at most once with the dispatch arguments.
526 * @param options — listener options; a boolean is shorthand for `prepend`.
527 * @returns a disposer removing the listener; `true` if it was still registered.
528 */
529 once(name, listener, options) {
530 const dispose = this.on(name, function(...args) {
531 dispose();
532 return listener.apply(this, args);
533 }, options);
534 return dispose;
535 }
536 };
537 var defaultFormatters = {
538 s: (value) => String(value),
539 d: (value) => Math.trunc(Number(value)),
540 i: (value) => Math.trunc(Number(value)),
541 f: (value) => Number(value),
542 o: (value) => JSON.stringify(value),
543 O: (value) => JSON.stringify(value),
544 c: () => "",
545 C: (value, exporter, message) => {
546 return Logger.color(exporter, Logger.code(message.name, exporter.colors), value);
547 }
548 };
549 function isAggregateError(error) {
550 return error instanceof Error && Array.isArray(error["errors"]);
551 }
552 var Logger = class {
553 service;
554 static color(exporter, code, value, decoration = "") {
555 if (!exporter.colors) return "" + value;
556 return `\x1B[3${code < 8 ? code : "8;5;" + code}${exporter.colors >= 2 ? decoration : ""}m${value}\x1B[0m`;
557 }
558 static code(name, level) {
559 let hash = 0;
560 for (let i = 0; i < name.length; i++) {
561 hash = (hash << 3) - hash + name.charCodeAt(i) + 13;
562 hash |= 0;
563 }
564 const colors = !level ? [] : level >= 2 ? c256 : c16;
565 return colors[Math.abs(hash) % colors.length];
566 }
567 static format(exporter, message) {
568 const args = message.args.slice();
569 if (args[0] instanceof Error) {
570 args[0] = args[0].stack || args[0].message;
571 args.unshift("%s");
572 } else if (typeof args[0] !== "string") args.unshift("%o");
573 let format = args.shift();
574 format = format.replace(/%([a-zA-Z%])/g, (match, char) => {
575 if (match === "%%") return "%";
576 const formatter = exporter.formatters?.[char] ?? defaultFormatters[char];
577 if (typeof formatter === "function") return formatter(args.shift(), exporter, message);
578 return match;
579 });
580 const oFormatter = exporter.formatters?.o ?? defaultFormatters.o;
581 for (let arg of args) {
582 if (typeof arg === "object" && arg) arg = oFormatter(arg, exporter, message);
583 format += " " + arg;
584 }
585 const { maxLength = 10240 } = exporter;
586 return format.split(/\r?\n/g).map((line) => {
587 return line.slice(0, maxLength) + (line.length > maxLength ? "..." : "");
588 }).join("\n");
589 }
590 constructor(options, service) {
591 this.service = service;
592 Object.assign(this, options);
593 this.error = this._method("error", 0);
594 this.info = this._method("info", 1);
595 this.warn = this._method("warn", 2);
596 this.debug = this._method("debug", 3);
597 }
598 _method(type, level) {
599 return (...args) => {
600 if (args.length === 1 && args[0] instanceof Error) {
601 if (args[0].cause) this[type](args[0].cause);
602 else if (isAggregateError(args[0])) {
603 args[0].errors.forEach((error) => this[type](error));
604 return;
605 }
606 }
607 const sn = ++this.service._snMessage;
608 const ts = Date.now();
609 for (const exporter of this.service.exporters.values()) {
610 if ((exporter.levels?.[this.name] ?? exporter.levels?.default ?? this.level ?? 1) < level) continue;
611 const message = {
612 sn,
613 ts,
614 type,
615 level,
616 name: this.name,
617 ...this.meta,
618 args
619 };
620 exporter.export(message);
621 }
622 };
623 }
624 };
625 var c16 = [
626 6,
627 2,
628 3,
629 4,
630 5,
631 1
632 ];
633 var c256 = [
634 20,
635 21,
636 26,
637 27,
638 32,
639 33,
640 38,
641 39,
642 40,
643 41,
644 42,
645 43,
646 44,
647 45,
648 56,
649 57,
650 62,
651 63,
652 68,
653 69,
654 74,
655 75,
656 76,
657 77,
658 78,
659 79,
660 80,
661 81,
662 92,
663 93,
664 98,
665 99,
666 112,
667 113,
668 129,
669 134,
670 135,
671 148,
672 149,
673 160,
674 161,
675 162,
676 163,
677 164,
678 165,
679 166,
680 167,
681 168,
682 169,
683 170,
684 171,
685 172,
686 173,
687 178,
688 179,
689 184,
690 185,
691 196,
692 197,
693 198,
694 199,
695 200,
696 201,
697 202,
698 203,
699 204,
700 205,
701 206,
702 207,
703 208,
704 209,
705 214,
706 215,
707 220,
708 221
709 ];
710 var LoggerService = class LoggerService2 {
711 bufferSize = 1e3;
712 buffer = [];
713 ctx;
714 _snMessage = 0;
715 _snExporter = 0;
716 exporters = /* @__PURE__ */ new Map();
717 constructor(ctx) {
718 const tracker = {
719 property: "ctx",
720 noShadow: true
721 };
722 const self = createCallable("logger", joinPrototype(Object.getPrototypeOf(this), Function.prototype), tracker);
723 Object.assign(self, this);
724 self.ctx = ctx;
725 defineProperty(self, symbols.tracker, tracker);
726 self.exporter({
727 colors: 3,
728 export: (message) => {
729 self.buffer.push(message);
730 if (self.buffer.length > self.bufferSize) self.buffer = self.buffer.slice(-self.bufferSize);
731 }
732 });
733 return self;
734 }
735 /**
736 * Register an exporter and dispose it with the current fiber.
737 *
738 * @param exporter — the sink that receives structured log messages.
739 * @returns a disposer that removes the exporter.
740 */
741 exporter(exporter) {
742 return this.ctx.effect(() => {
743 const id = ++this._snExporter;
744 this.exporters.set(id, exporter);
745 return () => this.exporters.delete(id);
746 }, "ctx.logger.exporter()");
747 }
748 _resolveConfig() {
749 let intercept = this.ctx[symbols.intercept];
750 const configs = [];
751 while ("logger" in intercept) {
752 if (Object.hasOwn(intercept, "logger")) configs.unshift(intercept["logger"]);
753 intercept = Object.getPrototypeOf(intercept);
754 }
755 return Object.assign({}, ...configs);
756 }
757 [symbols.invoke](name) {
758 const config = this._resolveConfig();
759 const fiber = (this.ctx[symbols.shadow] ?? this.ctx).fiber;
760 name ??= config.name;
761 name ??= hyphenate(fiber.name);
762 return new Logger({
763 name,
764 level: config.level,
765 meta: { fiber: new WeakRef(fiber) }
766 }, this);
767 }
768 static {
769 for (const type of [
770 "error",
771 "info",
772 "warn",
773 "debug"
774 ]) LoggerService2.prototype[type] = function(...args) {
775 return this()[type](...args);
776 };
777 }
778 };
779 function enhanceError(error) {
780 const lines = error.stack.split("\n");
781 lines.splice(0, 2, `Error: ${error.message}`);
782 error.stack = lines.join("\n");
783 return error;
784 }
785 var RESERVED_WORDS = ["prototype", "then"];
786 function isSpecialProperty(prop) {
787 return typeof prop === "symbol" || RESERVED_WORDS.includes(prop) || parseInt(prop).toString() === prop || prop.startsWith("_");
788 }
789 var ReflectService = class {
790 ctx;
791 /** Proxy traps implementing service resolution for every context object. */
792 static handler = {
793 get: (target, prop, ctx) => {
794 if (isSpecialProperty(prop)) return Reflect.get(target, prop, ctx);
795 if (Reflect.has(target, prop)) return getTraceable(ctx, Reflect.get(target, prop, ctx));
796 const error = /* @__PURE__ */ new Error(`cannot get property "${prop}" without inject`);
797 try {
798 const def = target.reflect.props[prop];
799 if (def?.type === "accessor") return def.get.call(ctx, ctx[symbols.receiver], error);
800 if (!ctx.fiber.runtime) return ctx.reflect.get(prop, false);
801 return ctx.events.waterfall("internal/get", ctx, prop, error, () => {
802 const key = target[symbols.isolate][prop];
803 let fiber = (ctx[symbols.shadow] ?? ctx).fiber;
804 while (true) {
805 const impl = fiber.store?.[prop];
806 if (impl) return getTraceable(ctx, impl.value);
807 if (prop in fiber.inject) {
808 error.message = `cannot get required service "${prop}" in inactive context`;
809 throw error;
810 }
811 if (!fiber.runtime) throw error;
812 if (fiber.parent[symbols.isolate][prop] !== key) throw error;
813 fiber = fiber.parent.fiber;
814 }
815 });
816 } catch (e) {
817 throw e === error ? enhanceError(e) : e;
818 }
819 },
820 set: (target, prop, value, ctx) => {
821 if (isSpecialProperty(prop)) return Reflect.set(target, prop, value, ctx);
822 const error = /* @__PURE__ */ new Error(`cannot set property "${prop}" without provide`);
823 const def = target.reflect.props[prop];
824 if (!def) {
825 if (!ctx.fiber.runtime) return Reflect.set(target, prop, value, ctx);
826 throw enhanceError(error);
827 }
828 try {
829 if (def.type === "accessor") {
830 if (!def.set) return false;
831 return def.set.call(ctx, value, ctx[symbols.receiver], error);
832 }
833 return ctx.events.waterfall("internal/set", ctx, prop, value, error, () => {
834 return ctx.reflect.set(prop, value, error);
835 });
836 } catch (e) {
837 throw e === error ? enhanceError(e) : e;
838 }
839 },
840 has: (target, prop) => {
841 if (isSpecialProperty(prop)) return Reflect.has(target, prop);
842 if (Reflect.has(target, prop)) return true;
843 return !!target.reflect.props[prop];
844 }
845 };
846 /** Service implementations, keyed by isolation label. */
847 store = /* @__PURE__ */ Object.create(null);
848 /** Declared context properties (services and accessors), by name. */
849 props = /* @__PURE__ */ Object.create(null);
850 constructor(ctx) {
851 this.ctx = ctx;
852 defineProperty(this, symbols.tracker, {
853 property: "ctx",
854 noShadow: true
855 });
856 this.mixin("reflect", [
857 "get",
858 "set",
859 "provide",
860 "accessor",
861 "mixin"
862 ]);
863 this.mixin("fiber", ["runtime", "effect"]);
864 this.mixin("registry", ["inject", "plugin"]);
865 this.mixin("events", [
866 "on",
867 "once",
868 "parallel",
869 "emit",
870 "serial",
871 "bail",
872 "waterfall"
873 ]);
874 }
875 /**
876 * Read a service from the store without the inject requirement.
877 *
878 * @param name — the service name.
879 * @param strict — when `true`, only return implementations whose providing
880 * fiber is currently active.
881 * @returns the service value, or `undefined` when not (yet) provided.
882 */
883 get(name, strict = true) {
884 return getTraceable(this.ctx, this._getImpl(name, strict)?.value);
885 }
886 _getImpl(name, strict = true) {
887 const key = this.ctx[symbols.isolate][name];
888 const impl = key && this.store[key];
889 if (!impl) return;
890 if (strict && impl.fiber.state !== 2) return;
891 return impl;
892 }
893 /**
894 * Overwrite a provided service's value.
895 *
896 * @param name — the service name.
897 * @param value — the new service value.
898 * @param error — carrier for the caller stack in diagnostics.
899 * @returns `true` on success.
900 * @throws when `name` was never provided, or was provided by another fiber.
901 */
902 set(name, value, error) {
903 const key = this.ctx[symbols.isolate][name];
904 const impl = this.store[key];
905 if (!impl) throw new Error(`cannot set property "${name}" without provide`);
906 if (impl.fiber !== this.ctx.fiber) throw new Error(`cannot set property "${name}" in multiple fibers`);
907 impl.value = value;
908 return true;
909 }
910 /**
911 * Register a service implementation owned by the current fiber.
912 *
913 * See the `ctx.provide()` overload above for the full contract.
914 *
915 * @param name — the service name.
916 * @param value — the service value.
917 * @param check — optional availability predicate for dependents.
918 * @returns a disposer that unregisters the service.
919 */
920 provide(name, value, check) {
921 return this.ctx.fiber.effect(() => {
922 if (!this.props[name]) this.props[name] ??= { type: "service" };
923 else if (this.props[name].type !== "service") throw new Error(`property "${name}" is already declared as ${this.props[name].type}`);
924 this.props[name] = { type: "service" };
925 this.ctx.root[symbols.isolate][name] ??= Symbol(name);
926 const key = this.ctx[symbols.isolate][name];
927 const impl = {
928 name,
929 value,
930 fiber: this.ctx.fiber,
931 check
932 };
933 if (this.store[key]) throw new Error(`service "${name}" has been registered at <${this.store[key].fiber.name}>`);
934 this.store[key] = impl;
935 this.ctx.fiber.store[name] = impl;
936 if (this.ctx.fiber.state === 2) this.notify([name]);
937 return async () => {
938 delete this.store[key];
939 const fibers = this.notify([name]);
940 await Promise.allSettled(fibers.map((fiber) => fiber.await()));
941 delete this.ctx.fiber.store[name];
942 };
943 }, `ctx.provide(${JSON.stringify(name)})`);
944 }
945 /**
946 * Re-evaluate every fiber that requires one of the given services.
947 *
948 * @param names — the service names that changed.
949 * @param filter — restricts notification to matching isolation scopes.
950 * @returns the fibers whose dependency state was refreshed.
951 */
952 notify(names, filter = (ctx, name) => ctx[symbols.isolate][name] === this.ctx[symbols.isolate][name]) {
953 const fibers = [];
954 for (const runtime of this.ctx.registry.values()) for (const fiber of runtime.fibers) {
955 let hasUpdate = false;
956 for (const name of names) {
957 if (!(name in fiber.inject)) continue;
958 if (!filter(fiber.ctx, name)) continue;
959 hasUpdate = true;
960 fiber._checkImpl(name);
961 }
962 if (!hasUpdate) continue;
963 fiber._refresh();
964 fibers.push(fiber);
965 }
966 for (const name of names) {
967 const self = Object.create(this.ctx);
968 self[symbols.filter] = (target) => filter(target, name);
969 this.ctx.events.emit(self, "internal/service", name, this._getImpl(name, false)?.value);
970 }
971 return fibers;
972 }
973 /**
974 * Define a computed context property backed by get/set hooks.
975 *
976 * @param name — the context property name.
977 * @param options — the `get` hook and optional `set` hook.
978 * @returns a disposer that removes the accessor.
979 */
980 accessor(name, options) {
981 return this.ctx.fiber.effect(() => {
982 if (name in this.props) throw new Error(`property "${name}" is already declared as ${this.props[name].type}`);
983 this.props[name] = {
984 type: "accessor",
985 ...options
986 };
987 return () => delete this.props[name];
988 }, `ctx.accessor(${JSON.stringify(name)})`);
989 }
990 /**
991 * Expose selected members of a service directly on `ctx`.
992 *
993 * See the `ctx.mixin()` overload above for the full contract.
994 *
995 * @param source — a context property name or a source object.
996 * @param mixins — keys to forward, or a source-key → ctx-key map.
997 * @returns a disposer that removes all created accessors.
998 */
999 mixin(source, mixins) {
1000 const self = this;
1001 return this.ctx.fiber.effect(function* () {
1002 const entries = Array.isArray(mixins) ? mixins.map((key) => [key, key]) : Object.entries(mixins);
1003 const getTarget = (ctx, error) => {
1004 return ctx[source];
1005 };
1006 for (const [key, value] of entries) yield self.accessor(value, {
1007 get(receiver, error) {
1008 const service = getTarget(this, error);
1009 if (isNullable(service)) return service;
1010 const mixin = receiver ? withProps(receiver, service) : service;
1011 const value2 = Reflect.get(service, key, mixin);
1012 if (typeof value2 !== "function") return value2;
1013 return value2.bind(mixin ?? service);
1014 },
1015 set(value2, receiver, error) {
1016 const service = getTarget(this, error);
1017 const mixin = receiver ? withProps(receiver, service) : service;
1018 return Reflect.set(service, key, value2, mixin);
1019 }
1020 });
1021 }, `ctx.mixin(${JSON.stringify(source)})`);
1022 }
1023 /**
1024 * Attach this context's tracing wrapper to a value.
1025 *
1026 * @param value — the value to wrap.
1027 * @returns the traceable wrapper (or the value itself when not applicable).
1028 */
1029 trace(value) {
1030 return getTraceable(this.ctx, value);
1031 }
1032 /**
1033 * Wrap a callback so calls trace `this` and arguments to this context.
1034 *
1035 * @param callback — the function to wrap.
1036 * @returns a proxy delegating to `callback` with traced values.
1037 */
1038 bind(callback) {
1039 return new Proxy(callback, {
1040 apply: (target, thisArg, args) => {
1041 return Reflect.apply(target, this.trace(thisArg), args.map((arg) => this.trace(arg)));
1042 },
1043 construct: (target, args, newTarget) => {
1044 return Reflect.construct(target, args.map((arg) => this.trace(arg)), newTarget);
1045 }
1046 });
1047 }
1048 };
1049 var kValidationError = /* @__PURE__ */ Symbol.for("ValidationError");
1050 var ValidationError = class extends TypeError {
1051 name = "ValidationError";
1052 /**
1053 * Build the aggregated message from schema issues.
1054 *
1055 * @param issues — the standard-schema issues, one message line each.
1056 */
1057 constructor(issues) {
1058 super(`invalid config:
1059 ` + issues.map((issue) => {
1060 if (issue.path) return ` - ${issue.message} (at ${issue.path.join(".")})`;
1061 else return ` - ${issue.message}`;
1062 }).join("\n"));
1063 }
1064 };
1065 Object.defineProperty(ValidationError.prototype, kValidationError, { value: true });
1066 function resolveConfig(runtime, config) {
1067 if (!runtime.Config) return config;
1068 const result = runtime.Config["~standard"].validate(config);
1069 if ("then" in result) throw new TypeError("Async config validation is not supported");
1070 if (result.issues) throw new ValidationError(result.issues);
1071 else return result.value;
1072 }
1073 var effectInertia = /* @__PURE__ */ new WeakMap();
1074 function runDisposable(dispose) {
1075 const result = dispose();
1076 return effectInertia.get(dispose)?.() ?? result;
1077 }
1078 function emitPluginDisposed(context, fiber) {
1079 const args = ["internal/plugin", fiber];
1080 let callbacks;
1081 try {
1082 callbacks = context.events.dispatch("emit", args);
1083 } catch (error) {
1084 context.logger.error(error);
1085 return;
1086 }
1087 for (const callback of callbacks) try {
1088 const returned = callback(...args);
1089 Promise.resolve(returned).catch((error) => context.logger.error(error));
1090 } catch (error) {
1091 context.logger.error(error);
1092 }
1093 }
1094 var CordisError = class CordisError2 extends Error {
1095 code;
1096 /**
1097 * @param code — the stable error code; also the default message.
1098 * @param message — optional human-readable override.
1099 */
1100 constructor(code, message) {
1101 super(message ?? CordisError2.Code[code]);
1102 this.code = code;
1103 }
1104 };
1105 (function(CordisError3) {
1106 CordisError3.Code = { INACTIVE_EFFECT: "cannot create effect on inactive context" };
1107 })(CordisError || (CordisError = {}));
1108 var INACTIVE = "__INACTIVE__";
1109 var Fiber = class {
1110 parent;
1111 inject;
1112 runtime;
1113 /** Unique id within the registry; 0 for the root fiber, `null` once disposed. */
1114 uid;
1115 /** The context this fiber's plugin runs in (extends the parent context). */
1116 ctx;
1117 /** The validated plugin config (updated by `update()`). */
1118 config;
1119 /** The raw plugin config, re-resolved before each activation. */
1120 _config;
1121 /** Current lifecycle state; transitions emit `internal/status`. */
1122 state = 0;
1123 /** Dispose this fiber: unload the plugin, then settle once cleanup finished. */
1124 dispose;
1125 /** Snapshot of required service implementations while loaded; `undefined` otherwise. */
1126 store;
1127 /** The in-flight load/unload transition, if one is currently running. */
1128 inertia;
1129 _hooks = /* @__PURE__ */ Object.create(null);
1130 _disposables = new DisposableList();
1131 context;
1132 _error;
1133 _runner;
1134 _store = /* @__PURE__ */ Object.create(null);
1135 /**
1136 * Create a fiber. Plugin authors normally obtain fibers from `ctx.plugin()`
1137 * rather than constructing them directly.
1138 *
1139 * @param parent — the context the plugin was loaded from.
1140 * @param config — raw config, validated against the runtime's schema.
1141 * @param inject — resolved dependency map (service name → intercept config).
1142 * @param runtime — the shared plugin runtime, or `null` for the root fiber.
1143 * @param getOuterStack — captures the caller stack for effect diagnostics.
1144 */
1145 constructor(parent, config, inject, runtime, getOuterStack) {
1146 this.parent = parent;
1147 this.inject = inject;
1148 this.runtime = runtime;
1149 this._config = config;
1150 const collect = (dispose) => {
1151 this._disposables.push(dispose);
1152 };
1153 if (runtime) {
1154 this.uid = parent.registry.counter;
1155 this.ctx = this.context = parent.extend({ fiber: this });
1156 const injectEntries = Object.entries(this.inject);
1157 if (injectEntries.length) {
1158 this.ctx[Context.intercept] = Object.create(parent[Context.intercept]);
1159 for (const [name, config2] of injectEntries) {
1160 if (isNullable(config2)) continue;
1161 this.ctx[Context.intercept][name] = config2;
1162 }
1163 }
1164 this._runner = {
1165 epoch: INACTIVE,
1166 getOuterStack,
1167 execute: function() {
1168 if (isConstructor(runtime.callback)) {
1169 const instance = new runtime.callback(this.ctx, this.config);
1170 for (const hook of instance?.[symbols.initHooks] ?? []) hook();
1171 return instance?.[symbols.init]?.();
1172 } else return runtime.callback(this.ctx, this.config);
1173 },
1174 collect
1175 };
1176 this.dispose = parent.fiber.effect(() => {
1177 const remove = runtime.fibers.push(this);
1178 return async () => {
1179 this.uid = null;
1180 emitPluginDisposed(this.context, this);
1181 if (this.ctx.registry.has(runtime.callback)) {
1182 remove();
1183 if (!runtime.fibers.length) this.ctx.registry.delete(runtime.callback);
1184 }
1185 this._setEpoch(INACTIVE);
1186 if (!this.inertia) this._updateState(() => {
1187 this.inertia = this._unload();
1188 return 5;
1189 });
1190 while (this.inertia) await this.inertia;
1191 };
1192 }, "ctx.plugin()");
1193 try {
1194 this.context.emit("internal/plugin", this);
1195 } catch (error) {
1196 Promise.resolve(this.dispose()).catch((reason) => this.ctx.logger.error(reason));
1197 throw error;
1198 }
1199 if (this.uid !== null && parent.fiber.state !== 5) {
1200 for (const name of Object.keys(this.inject)) this._checkImpl(name);
1201 this._refresh();
1202 }
1203 } else {
1204 this.uid = 0;
1205 this.ctx = this.context = parent;
1206 this.state = 2;
1207 this.store = /* @__PURE__ */ Object.create(null);
1208 this._runner = {
1209 epoch: "",
1210 getOuterStack,
1211 execute: () => {
1212 },
1213 collect
1214 };
1215 this.dispose = () => this.restart();
1216 }
1217 }
1218 /** The plugin's display name, inherited from the nearest named ancestor, else `'root'`. */
1219 get name() {
1220 let fiber = this;
1221 do {
1222 if (fiber.runtime?.name) return fiber.runtime.name;
1223 fiber = fiber.parent.fiber;
1224 } while (fiber !== fiber.parent.fiber);
1225 return "root";
1226 }
1227 /**
1228 * Throw if the fiber has already been disposed.
1229 *
1230 * @returns nothing when the fiber is still active.
1231 * @throws {CordisError} `INACTIVE_EFFECT` when the fiber's uid has been cleared.
1232 */
1233 assertActive() {
1234 if (this.uid !== null) return;
1235 throw new CordisError("INACTIVE_EFFECT");
1236 }
1237 _execute(runner) {
1238 const oldEpoch = runner.epoch;
1239 return composeError((info) => {
1240 const safeCollect = (dispose) => {
1241 if (typeof dispose === "function") runner.collect(dispose);
1242 else if (!isNullable(dispose)) throw new TypeError("Invalid effect");
1243 };
1244 const effect = runner.execute.call(this);
1245 if (typeof effect === "function") return runner.collect(effect);
1246 else if (isNullable(effect)) {
1247 } else if (!isObject(effect)) throw new TypeError("Invalid effect");
1248 else if ("then" in effect) return effect.then(safeCollect);
1249 else if (Symbol.iterator in effect) {
1250 info.error = /* @__PURE__ */ new Error();
1251 const iter = effect[Symbol.iterator]();
1252 while (true) {
1253 const result = iter.next();
1254 safeCollect(result.value);
1255 if (result.done) return;
1256 }
1257 } else if (Symbol.asyncIterator in effect) {
1258 const iter = effect[Symbol.asyncIterator]();
1259 return (async () => {
1260 await Promise.resolve();
1261 info.error = /* @__PURE__ */ new Error();
1262 while (true) {
1263 if (runner.epoch !== oldEpoch) return;
1264 const result = await iter.next();
1265 safeCollect(result.value);
1266 if (result.done) return;
1267 }
1268 })();
1269 } else throw new TypeError("Invalid effect");
1270 }, runner.getOuterStack);
1271 }
1272 effect(execute, label = "anonymous") {
1273 this.assertActive();
1274 if (this.state === 5) throw new CordisError("INACTIVE_EFFECT");
1275 const disposables = [];
1276 let disposing = false;
1277 let disposalTask;
1278 const dispose = () => {
1279 if (disposing) return disposalTask;
1280 disposing = true;
1281 let task2;
1282 for (const disposable of disposables.splice(0).reverse()) if (task2) task2 = task2.then(() => runDisposable(disposable));
1283 else {
1284 const result = runDisposable(disposable);
1285 if (isObject(result) && "then" in result) task2 = result;
1286 }
1287 return disposalTask = task2;
1288 };
1289 const meta = {
1290 label,
1291 children: []
1292 };
1293 const runner = {
1294 execute,
1295 epoch: true,
1296 collect: (dispose2) => {
1297 disposables.push(dispose2);
1298 this._disposables.delete(dispose2);
1299 if (dispose2[symbols.effect]) meta.children.push(dispose2[symbols.effect]);
1300 },
1301 getOuterStack: buildOuterStack()
1302 };
1303 let task;
1304 let executing = true;
1305 let resolveSetup;
1306 let rejectSetup;
1307 let setupBarrier;
1308 let setupFailed = false;
1309 let inFlight;
1310 let removeWrapper = () => false;
1311 const waitForSetup = () => {
1312 setupBarrier ??= new Promise((resolve, reject) => {
1313 resolveSetup = resolve;
1314 rejectSetup = reject;
1315 });
1316 return setupBarrier;
1317 };
1318 const disposeAfter = (setup) => {
1319 return Promise.resolve(setup).then(() => dispose(), async (reason) => {
1320 await dispose();
1321 throw reason;
1322 });
1323 };
1324 const finalizeDisposal = (callback) => {
1325 let result;
1326 try {
1327 result = callback();
1328 } catch (error) {
1329 removeWrapper();
1330 throw error;
1331 }
1332 if (isObject(result) && "then" in result) {
1333 const pending = Promise.resolve(result).finally(() => {
1334 removeWrapper();
1335 if (inFlight === pending) inFlight = void 0;
1336 });
1337 return inFlight = pending;
1338 }
1339 removeWrapper();
1340 return result;
1341 };
1342 const wrapper = defineProperty(() => {
1343 if (!runner.epoch) return setupFailed ? inFlight : void 0;
1344 runner.epoch = false;
1345 return finalizeDisposal(() => {
1346 if (executing) return disposeAfter(waitForSetup());
1347 return task ? disposeAfter(task) : dispose();
1348 });
1349 }, symbols.effect, meta);
1350 effectInertia.set(wrapper, () => inFlight);
1351 removeWrapper = this._disposables.push(wrapper);
1352 try {
1353 task = this._execute(runner);
1354 } catch (reason) {
1355 executing = false;
1356 setupFailed = true;
1357 runner.epoch = false;
1358 let cleanup;
1359 try {
1360 cleanup = finalizeDisposal(dispose);
1361 } finally {
1362 rejectSetup?.(reason);
1363 }
1364 if (isObject(cleanup) && "then" in cleanup) cleanup.catch((error) => this.ctx.logger.error(error));
1365 throw reason;
1366 }
1367 executing = false;
1368 if (setupBarrier) Promise.resolve(task).then(resolveSetup, rejectSetup);
1369 task?.catch(() => {
1370 if (!runner.epoch) return dispose();
1371 return finalizeDisposal(dispose);
1372 }).catch((error) => this.ctx.logger.error(error));
1373 const disposeAsync = () => {
1374 if (!runner.epoch) return;
1375 runner.epoch = false;
1376 return finalizeDisposal(dispose);
1377 };
1378 wrapper.then = async (onFulfilled, onRejected) => {
1379 return Promise.resolve(task).then(() => disposeAsync).then(onFulfilled, onRejected);
1380 };
1381 return wrapper;
1382 }
1383 /**
1384 * Return metadata for currently registered effects.
1385 *
1386 * @returns one {@link EffectMeta} tree per labeled live effect.
1387 */
1388 getEffects() {
1389 return [...this._disposables].map((dispose) => dispose[symbols.effect]).filter(Boolean);
1390 }
1391 _getState() {
1392 if (this.uid === null) return 4;
1393 if (this._error) return 3;
1394 if (this._runner.epoch !== INACTIVE) return 2;
1395 return 0;
1396 }
1397 _updateState(callback) {
1398 const oldState = this.state;
1399 this.state = callback() ?? this._getState();
1400 if (oldState === this.state) return;
1401 this.context.emit("internal/status", this, oldState);
1402 if (oldState !== 2 && this.state !== 2) return;
1403 for (const key of Reflect.ownKeys(this.ctx.reflect.store)) {
1404 const impl = this.ctx.reflect.store[key];
1405 if (impl.fiber !== this) continue;
1406 this.ctx.reflect.notify([impl.name]);
1407 }
1408 }
1409 _checkImpl(name) {
1410 const impl = this.ctx.reflect._getImpl(name, true);
1411 if (!impl) return delete this._store[name];
1412 try {
1413 if (impl.check && !impl.check.call(getTraceable(this.ctx, impl.value))) return delete this._store[name];
1414 } catch (error) {
1415 impl.fiber.ctx.logger.error(error);
1416 return delete this._store[name];
1417 }
1418 this._store[name] = impl;
1419 }
1420 _refresh() {
1421 let epoch = false;
1422 epoch = "";
1423 for (const name of Object.keys(this.inject)) {
1424 const impl = this._store[name];
1425 if (!impl) {
1426 epoch = INACTIVE;
1427 break;
1428 }
1429 epoch += ":" + impl.fiber.uid;
1430 }
1431 this._setEpoch(epoch);
1432 }
1433 _setEpoch(epoch) {
1434 const oldEpoch = this._runner.epoch;
1435 if (epoch === oldEpoch) return;
1436 this._runner.epoch = epoch;
1437 if (this.inertia) return;
1438 this._updateState(() => {
1439 if (epoch !== INACTIVE && oldEpoch === INACTIVE) {
1440 this.inertia = this._reload();
1441 return 1;
1442 } else {
1443 this.inertia = this._unload();
1444 return 5;
1445 }
1446 });
1447 }
1448 _resolveConfig(config) {
1449 config = this.context.waterfall(this, "internal/config", config, () => config);
1450 return this.runtime ? resolveConfig(this.runtime, config) : config;
1451 }
1452 async _reload() {
1453 this.store = { ...this._store };
1454 const oldEpoch = this._runner.epoch;
1455 try {
1456 await Promise.resolve();
1457 if (this._runner.epoch === oldEpoch) {
1458 this.config = this._resolveConfig(this._config);
1459 await this._execute(this._runner);
1460 this._error = void 0;
1461 }
1462 } catch (reason) {
1463 this.ctx.logger.error(reason);
1464 this._error = reason;
1465 this._runner.epoch = INACTIVE;
1466 }
1467 this._updateState(() => {
1468 if (this._runner.epoch === oldEpoch) this.inertia = void 0;
1469 else {
1470 this.inertia = this._unload();
1471 return 5;
1472 }
1473 });
1474 }
1475 async _unload() {
1476 await Promise.all(this._disposables.clear().map(async (dispose) => {
1477 try {
1478 await composeError(async (info) => {
1479 await Promise.resolve();
1480 info.error = /* @__PURE__ */ new Error();
1481 await runDisposable(dispose);
1482 }, this._runner.getOuterStack);
1483 } catch (reason) {
1484 this.ctx.logger.error(reason);
1485 }
1486 }));
1487 this.store = void 0;
1488 this._updateState(() => {
1489 if (this._runner.epoch === INACTIVE) this.inertia = void 0;
1490 else {
1491 this.inertia = this._reload();
1492 return 1;
1493 }
1494 });
1495 }
1496 /**
1497 * Wait for current lifecycle work and rethrow startup errors.
1498 *
1499 * @returns this fiber, once it has settled into a stable state.
1500 * @throws the config-validation or plugin-startup error, if any.
1501 */
1502 async await() {
1503 while (this.inertia) await this.inertia;
1504 if (this._error) throw this._error;
1505 return this;
1506 }
1507 /**
1508 * Dispose and immediately reload this plugin with its current config.
1509 *
1510 * @returns a promise resolving once the reload settled.
1511 * @throws {CordisError} `INACTIVE_EFFECT` when the fiber is already disposed.
1512 */
1513 async restart() {
1514 this.assertActive();
1515 this._setEpoch(INACTIVE);
1516 this._refresh();
1517 await this.await();
1518 }
1519 /**
1520 * Validate and apply new config, then restart the plugin.
1521 *
1522 * Runs the `internal/update` waterfall first, so update hooks (and HMR)
1523 * can veto or replace the restart.
1524 *
1525 * @param config — the new raw config; validated before anything restarts.
1526 * @param noSave — hint for persistence hooks not to write the change back.
1527 * @returns nothing; the restart runs behind the `internal/update` waterfall.
1528 * @throws {ValidationError} when the new config fails validation.
1529 */
1530 update(config, noSave = false) {
1531 this.assertActive();
1532 this._config = config;
1533 if (this.state !== 2) {
1534 this._error = void 0;
1535 this._setEpoch(INACTIVE);
1536 this._refresh();
1537 return;
1538 }
1539 config = this._resolveConfig(config);
1540 this.context.waterfall(this, "internal/update", config, noSave, () => {
1541 this.config = config;
1542 this._error = void 0;
1543 return this.restart();
1544 });
1545 }
1546 };
1547 function isApplicable(object) {
1548 return object && typeof object === "object" && typeof object.apply === "function";
1549 }
1550 function Inject(name, config) {
1551 return function(value, decorator) {
1552 if (decorator.kind === "class") {
1553 if (!Object.hasOwn(value, "inject")) {
1554 defineProperty(value, "inject", Object.create(Object.getPrototypeOf(value).inject ?? null));
1555 defineProperty(value.inject, symbols.checkProto, true);
1556 }
1557 value.inject[name] = config;
1558 } else if (decorator.kind === "method") {
1559 const inject = (value[symbols.metadata] ??= {}).inject ??= /* @__PURE__ */ Object.create(null);
1560 inject[name] = config;
1561 decorator.addInitializer(function() {
1562 const property = this[symbols.tracker]?.property;
1563 (this[symbols.initHooks] ??= []).push(() => {
1564 this.ctx.inject(inject, (ctx) => {
1565 return value.call(property ? withProps(this, { [property]: ctx }) : this);
1566 });
1567 });
1568 });
1569 } else throw new Error("@Inject() can only be used on class or class methods");
1570 };
1571 }
1572 (function(Inject2) {
1573 function resolve(inject, result = /* @__PURE__ */ Object.create(null)) {
1574 if (!inject) return result;
1575 if (Array.isArray(inject)) for (const name of inject) result[name] = null;
1576 else if (Reflect.has(inject, symbols.checkProto)) {
1577 Object.assign(result, resolve(Object.getPrototypeOf(inject)));
1578 for (const name of Object.keys(inject)) result[name] = inject[name] ?? null;
1579 } else for (const name of Object.keys(inject)) result[name] = inject[name] ?? null;
1580 return result;
1581 }
1582 Inject2.resolve = resolve;
1583 })(Inject || (Inject = {}));
1584 var RegistryService = class {
1585 ctx;
1586 _counter = 0;
1587 _internal = /* @__PURE__ */ new Map();
1588 constructor(ctx) {
1589 this.ctx = ctx;
1590 defineProperty(this, symbols.tracker, {
1591 property: "ctx",
1592 noShadow: true
1593 });
1594 }
1595 /** Allocate the next fiber uid (increments on every read). */
1596 get counter() {
1597 return ++this._counter;
1598 }
1599 /** Number of registered plugin runtimes. */
1600 get size() {
1601 return this._internal.size;
1602 }
1603 /**
1604 * Resolve a supported plugin shape to its executable callback.
1605 *
1606 * @param plugin — a function, class, or `{ apply }` object plugin.
1607 * @returns the callback identifying the plugin, or `undefined` if invalid.
1608 */
1609 resolve(plugin) {
1610 try {
1611 if (typeof plugin === "function") return plugin;
1612 if (isApplicable(plugin)) return plugin.apply;
1613 } catch {
1614 }
1615 }
1616 /**
1617 * Look up the runtime record for a plugin.
1618 *
1619 * @param plugin — any supported plugin shape.
1620 * @returns the runtime, or `undefined` when the plugin is not registered.
1621 */
1622 get(plugin) {
1623 const key = this.resolve(plugin);
1624 return key && this._internal.get(key);
1625 }
1626 /**
1627 * Check whether a plugin has a registered runtime.
1628 *
1629 * @param plugin — any supported plugin shape.
1630 * @returns `true` when at least one fiber of the plugin exists.
1631 */
1632 has(plugin) {
1633 const key = this.resolve(plugin);
1634 return !!key && this._internal.has(key);
1635 }
1636 /**
1637 * Dispose every running fiber for a plugin and remove its runtime record.
1638 *
1639 * @param plugin — any supported plugin shape.
1640 * @returns the removed runtime, or `undefined` when none was registered.
1641 */
1642 delete(plugin) {
1643 const key = this.resolve(plugin);
1644 const runtime = key && this._internal.get(key);
1645 if (!runtime) return;
1646 this._internal.delete(key);
1647 for (const fiber of runtime.fibers) fiber.dispose();
1648 return runtime;
1649 }
1650 /** Iterate the registered plugin callbacks. */
1651 keys() {
1652 return this._internal.keys();
1653 }
1654 /** Iterate the registered plugin runtimes. */
1655 values() {
1656 return this._internal.values();
1657 }
1658 /** Iterate `[callback, runtime]` pairs. */
1659 entries() {
1660 return this._internal.entries();
1661 }
1662 /**
1663 * Visit every registered runtime.
1664 *
1665 * @param callback — receives each runtime and its identifying callback.
1666 */
1667 forEach(callback) {
1668 return this._internal.forEach(callback);
1669 }
1670 /**
1671 * Start a callback once the requested dependencies are available.
1672 *
1673 * @param inject — required services, as an array or a name → config map.
1674 * @param callback — plugin body called with `(ctx, config)`.
1675 * @returns the fiber; awaiting it settles once loading finished.
1676 */
1677 inject(inject, callback) {
1678 return this.plugin({
1679 inject,
1680 apply: callback,
1681 name: callback.name
1682 });
1683 }
1684 /**
1685 * Start a plugin in the current context and return its fiber.
1686 *
1687 * Creates (or reuses) the plugin's runtime record, then starts a new fiber
1688 * under the current context. Throws if `plugin` is not a supported shape or
1689 * if the current fiber is already disposed.
1690 *
1691 * @param plugin — a function, class, or `{ apply }` object plugin.
1692 * @param config — the plugin config, validated against its `Config` schema.
1693 * @param getOuterStack — captures the caller stack for effect diagnostics.
1694 * @returns the fiber; awaiting it settles once loading finished.
1695 */
1696 plugin(plugin, config, getOuterStack = buildOuterStack()) {
1697 const callback = this.resolve(plugin);
1698 if (!callback) throw new Error('invalid plugin, expect function or object with an "apply" method, received ' + typeof plugin);
1699 this.ctx.fiber.assertActive();
1700 let runtime = this._internal.get(callback);
1701 if (!runtime) {
1702 let name = plugin.name;
1703 if (name === "apply") name = void 0;
1704 runtime = {
1705 name,
1706 callback,
1707 fibers: new DisposableList(),
1708 Config: plugin.Config
1709 };
1710 this._internal.set(callback, runtime);
1711 }
1712 const fiber = new Fiber(this.ctx, config, Inject.resolve(plugin.inject), runtime, getOuterStack);
1713 const wrapped = Object.create(fiber);
1714 wrapped.then = (onFulfilled, onRejected) => {
1715 return fiber.await().then(onFulfilled, onRejected);
1716 };
1717 return wrapped;
1718 }
1719 };
1720 var Context = class Context2 {
1721 /** Symbol key under which a disposer exposes its {@link EffectMeta} diagnostics tree. */
1722 static effect = symbols.effect;
1723 /** Symbol key for a context's listener filter, consulted on every event dispatch. */
1724 static filter = symbols.filter;
1725 /** Symbol key of the isolation map (see the `Context[symbols.isolate]` property). */
1726 static isolate = symbols.isolate;
1727 /** Symbol key of the intercept map (see the `Context[symbols.intercept]` property). */
1728 static intercept = symbols.intercept;
1729 /**
1730 * Returns true for Cordis context proxies and context prototypes.
1731 *
1732 * Works across realms and across multiple copies of cordis, because the
1733 * brand is keyed by a global symbol rather than by `instanceof`.
1734 *
1735 * @param value — the value to test.
1736 * @returns `true` if `value` is a Cordis context, narrowing its type.
1737 */
1738 static is(value) {
1739 return !!value?.[Context2.is];
1740 }
1741 static {
1742 Context2.is[Symbol.toPrimitive] = () => /* @__PURE__ */ Symbol.for("cordis.is");
1743 Context2.prototype[Context2.is] = true;
1744 }
1745 /** Create the root context and install the built-in services. */
1746 constructor() {
1747 this[symbols.isolate] = /* @__PURE__ */ Object.create(null);
1748 this[symbols.intercept] = /* @__PURE__ */ Object.create(null);
1749 const self = new Proxy(this, ReflectService.handler);
1750 this.root = self;
1751 this.baseUrl = void 0;
1752 this.fiber = new Fiber(self, {}, /* @__PURE__ */ Object.create(null), null, () => []);
1753 this.reflect = new ReflectService(self);
1754 this.registry = new RegistryService(self);
1755 this.events = new EventsService(self);
1756 this.logger = new LoggerService(self);
1757 this.fiber._disposables.clear();
1758 return self;
1759 }
1760 [/* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom")]() {
1761 return `Context <${this.fiber.name}>`;
1762 }
1763 /**
1764 * Create a child context with extra metadata on top of the current scope.
1765 *
1766 * The child prototypally inherits every property of this context; own
1767 * properties of `meta` shadow the inherited ones. The parent is not mutated.
1768 *
1769 * @param meta — own properties (including symbol keys) to define on the child.
1770 * @returns a child context inheriting from this one.
1771 */
1772 extend(meta = {}) {
1773 const shadow = Reflect.getOwnPropertyDescriptor(this, symbols.shadow)?.value;
1774 const self = Object.create(getTraceable(this, this));
1775 for (const prop of Reflect.ownKeys(meta)) Object.defineProperty(self, prop, Reflect.getOwnPropertyDescriptor(meta, prop));
1776 if (!shadow) return self;
1777 return Object.assign(Object.create(self), { [symbols.shadow]: shadow });
1778 }
1779 /**
1780 * Create a child context with an independent service scope for `name`.
1781 *
1782 * Below the returned context, reads and writes of the service `name`
1783 * resolve against the new label instead of the parent's, so a different
1784 * implementation can be provided without affecting the parent scope.
1785 * Passing the same `label` to two `isolate()` calls joins their scopes.
1786 *
1787 * @param name — the service name to isolate.
1788 * @param label — scope label to join; defaults to a fresh unique symbol.
1789 * @returns a child context whose `name` service resolves in the new scope.
1790 */
1791 isolate(name, label) {
1792 const shadow = Object.create(this[symbols.isolate]);
1793 shadow[name] = label ?? Symbol(name);
1794 return this.extend({ [symbols.isolate]: shadow });
1795 }
1796 intercept(name, config) {
1797 const intercept = Object.create(this[symbols.intercept]);
1798 intercept[name] = config;
1799 return this.extend({ [symbols.intercept]: intercept });
1800 }
1801 };
1802 var Service = class Service2 {
1803 ctx;
1804 /** Symbol key of an instance method run after construction (class plugins). */
1805 static init = symbols.init;
1806 /** Symbol key of the availability predicate passed to `ctx.provide()`. */
1807 static check = symbols.check;
1808 /** Symbol key of the phantom intercept-config type parameter. */
1809 static config = symbols.config;
1810 /** Symbol key of the call body making a service callable (e.g. `ctx.logger()`). */
1811 static invoke = symbols.invoke;
1812 /** Symbol key of the helper deriving an extended service instance. */
1813 static extend = symbols.extend;
1814 /** Symbol key of the tracker metadata used for context tracing. */
1815 static tracker = symbols.tracker;
1816 /** Symbol key of the intercept-config resolution helper below. */
1817 static resolveConfig = symbols.resolveConfig;
1818 /** The service name this instance is registered under. */
1819 name;
1820 /**
1821 * Register this instance as `name` in the current context.
1822 *
1823 * Calls `ctx.reflect.provide(name, this, this[Service.check])`, so the
1824 * service is unregistered automatically when the owning fiber unloads.
1825 * Services with a `[Service.invoke]` body return a callable instance.
1826 *
1827 * @param ctx — the context to register in (stored as `this.ctx`).
1828 * @param name — the service name; defaults to the static `provide` field.
1829 */
1830 constructor(ctx, name) {
1831 this.ctx = ctx;
1832 name ??= this.constructor["provide"];
1833 let self = this;
1834 const tracker = {
1835 associate: name,
1836 property: "ctx"
1837 };
1838 if (self[symbols.invoke]) self = createCallable(name, joinPrototype(Object.getPrototypeOf(this), Function.prototype), tracker);
1839 self.ctx = ctx;
1840 self.name = name;
1841 defineProperty(self, symbols.tracker, tracker);
1842 self.ctx.reflect.provide(name, self, this[symbols.check]);
1843 return self;
1844 }
1845 [symbols.filter](ctx) {
1846 return ctx[symbols.isolate][this.name] === this.ctx[symbols.isolate][this.name];
1847 }
1848 [symbols.extend](props) {
1849 let self;
1850 if (this[Service2.invoke]) self = createCallable(this.name, this, this[symbols.tracker]);
1851 else self = Object.create(this);
1852 return Object.assign(self, props);
1853 }
1854 /**
1855 * Merge intercept config from ancestors with optional base and head values.
1856 *
1857 * Entries added closer to the root apply first; `base` is prepended and
1858 * `head` appended. Uses `Config.merge` when the service declares one,
1859 * otherwise a shallow `Object.assign`.
1860 *
1861 * @param base — lowest-precedence config merged before all intercepts.
1862 * @param head — highest-precedence config merged after all intercepts.
1863 * @returns the merged config.
1864 */
1865 [symbols.resolveConfig](base, head) {
1866 let intercept = this.ctx[Context.intercept];
1867 const configs = [];
1868 while (this.name in intercept) {
1869 if (Object.hasOwn(intercept, this.name)) configs.unshift(intercept[this.name]);
1870 intercept = Object.getPrototypeOf(intercept);
1871 }
1872 if (base) configs.unshift(base);
1873 if (head) configs.push(head);
1874 if (this["Config"]?.merge) return this["Config"].merge(...configs);
1875 else return Object.assign({}, ...configs);
1876 }
1877 static [Symbol.hasInstance](instance) {
1878 if (!instance) return false;
1879 let constructor = instance.constructor;
1880 while (constructor) {
1881 constructor = constructor.prototype?.constructor;
1882 if (constructor === this) return true;
1883 constructor &&= Object.getPrototypeOf(constructor);
1884 }
1885 return false;
1886 }
1887 };
1888
1889 // src/shims/owned.ts
1890 function describeError(error) {
1891 return error instanceof Error ? `${error.name}: ${error.message}` : String(error);
1892 }
1893 var OwnedRegistrations = class {
1894 /** Admitted entries by core handle. */
1895 byHandle = /* @__PURE__ */ new Map();
1896 rpc;
1897 kind;
1898 /** The owner's own index of this kind, for the leak report at deactivation. */
1899 ownedBy;
1900 warn;
1901 constructor(rpc, kind, ownedBy, warn) {
1902 this.rpc = rpc;
1903 this.kind = kind;
1904 this.ownedBy = ownedBy;
1905 this.warn = warn;
1906 }
1907 /** Called inside the owner's effect; returns the effect's cleanup. */
1908 add(entry, spec) {
1909 const owner = entry.owner;
1910 if (owner.state !== "activating" && owner.state !== "active") throw new Error("registration owner was disposed");
1911 const registration = this.rpc.request("registry/register", { owner: owner.ref, ...owner.scope ? { scope: owner.scope } : {}, kind: this.kind, spec }).then(
1912 (result) => {
1913 if (typeof result?.handle === "number") {
1914 entry.handle = result.handle;
1915 if (entry.disposed || owner.state !== "activating" && owner.state !== "active") {
1916 return this.unregister(entry);
1917 }
1918 this.ownedBy(owner).set(result.handle, entry);
1919 this.byHandle.set(result.handle, entry);
1920 } else {
1921 const reason = typeof result?.refused === "string" ? result.refused : "refused without a reason";
1922 owner.refusals.push(`${this.kind} \`${entry.name}\` refused: ${reason}`);
1923 if (owner.state === "active") this.warn(`${this.kind} \`${entry.name}\` refused: ${reason}`, owner);
1924 }
1925 },
1926 (error) => {
1927 owner.refusals.push(`${this.kind} \`${entry.name}\` registration failed: ${describeError(error)}`);
1928 }
1929 ).finally(() => owner.pendingRegistrations.delete(registration));
1930 owner.pendingRegistrations.add(registration);
1931 return () => {
1932 if (entry.disposed) return;
1933 entry.disposed = true;
1934 if (entry.handle !== void 0) void this.unregister(entry);
1935 };
1936 }
1937 /** Undo exactly this entry. The core revokes first, so a failure here is expected after revocation. */
1938 unregister(entry) {
1939 const handle = entry.handle;
1940 const owner = entry.owner;
1941 this.ownedBy(owner).delete(handle);
1942 this.byHandle.delete(handle);
1943 const cleanup = this.rpc.request("registry/unregister", { owner: owner.ref, handle }).then(() => void 0, () => void 0).finally(() => owner.pendingRegistrations.delete(cleanup));
1944 owner.pendingRegistrations.add(cleanup);
1945 return cleanup;
1946 }
1947 /** Drop the host's index of everything `owner` registered (after its teardown). */
1948 forget(owner) {
1949 for (const entry of this.ownedBy(owner).values()) this.byHandle.delete(entry.handle);
1950 }
1951 };
1952
1953 // src/shims/skills.ts
1954 var MAX_SKILL_ROOTS_PER_OWNER = 8;
1955 var MAX_SKILL_ROOTS_PER_HOST = 64;
1956 function normalizeSkillRoot(value) {
1957 if (typeof value !== "object" || value === null || Array.isArray(value) || Object.keys(value).some((key) => key !== "path")) throw new TypeError("skill root supports only path");
1958 const { path } = value;
1959 if (typeof path !== "string" || !path || Buffer.byteLength(path, "utf8") > 512 || /[\\:\u0000-\u001f\u007f-\u009f]/u.test(path) || path.split("/").some((part) => !part || part === "." || part === "..")) {
1960 throw new TypeError("skill root path must be a bounded bundle-relative path with normal slash-separated components");
1961 }
1962 return Object.freeze({ path });
1963 }
1964 var SkillRoots = class {
1965 registrations;
1966 owners = /* @__PURE__ */ new Map();
1967 count = 0;
1968 constructor(rpc, ownedBy, warn) {
1969 this.registrations = new OwnedRegistrations(rpc, "skill_root", ownedBy, warn);
1970 }
1971 register(owner, definition) {
1972 if (owner.state !== "activating" && owner.state !== "active") throw new Error("skill owner is not live");
1973 const { path } = normalizeSkillRoot(definition);
1974 const roots = this.owners.get(owner) ?? /* @__PURE__ */ new Map();
1975 if (roots.has(path)) throw new Error("skill root is already registered; dispose it before registering it again");
1976 if (roots.size >= MAX_SKILL_ROOTS_PER_OWNER || this.count >= MAX_SKILL_ROOTS_PER_HOST) throw new RangeError("skill root owner or host registration limit reached");
1977 const undo = this.registrations.add({ owner, name: path, disposed: false }, { name: path, description: "" });
1978 const dispose = () => {
1979 if (roots.get(path) !== dispose) return;
1980 roots.delete(path);
1981 this.count--;
1982 if (!roots.size) this.owners.delete(owner);
1983 undo();
1984 };
1985 roots.set(path, dispose);
1986 this.owners.set(owner, roots);
1987 this.count++;
1988 return dispose;
1989 }
1990 forget(owner) {
1991 for (const dispose of [...this.owners.get(owner)?.values() ?? []]) dispose();
1992 this.registrations.forget(owner);
1993 }
1994 };
1995 function defineSkillsService(host) {
1996 class SkillsShim extends Service {
1997 constructor(ctx) {
1998 super(ctx, "skills");
1999 }
2000 registerRoot(definition) {
2001 const ctx = this.ctx;
2002 const owner = host.ownerOf(ctx);
2003 if (!owner) throw new Error("skills.registerRoot called outside an extension owner");
2004 const root = normalizeSkillRoot(definition);
2005 return ctx.effect(() => host.skillRoots.register(owner, root), `skills.registerRoot(${JSON.stringify(root.path)})`);
2006 }
2007 }
2008 Object.freeze(SkillsShim.prototype);
2009 return SkillsShim;
2010 }
2011 export {
2012 MAX_SKILL_ROOTS_PER_HOST,
2013 MAX_SKILL_ROOTS_PER_OWNER,
2014 SkillRoots,
2015 defineSkillsService,
2016 normalizeSkillRoot
2017 };
2018
2018 lines Plain Text