@ai-matrx/summon 0.1.17 → 0.1.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/open.js CHANGED
@@ -1,185 +1,74 @@
1
- // src/core/types.ts
2
- var DEFAULT_INSTANCE_ID = "default";
3
- function instanceKey(overlayId, instanceId = DEFAULT_INSTANCE_ID) {
4
- return `${overlayId}:${instanceId}`;
5
- }
6
- function parseInstanceKey(key) {
7
- const at = key.indexOf(":");
8
- if (at <= 0 || at === key.length - 1) return null;
9
- return { overlayId: key.slice(0, at), instanceId: key.slice(at + 1) };
10
- }
11
- function defaultWindowIdFor(meta) {
12
- return meta.window?.windowId ?? meta.id;
13
- }
14
-
15
- // src/core/ports.ts
16
- var noop = () => {
17
- };
18
- var anonymousIdentity = {
19
- current: () => ({ key: "anonymous", ready: true }),
20
- subscribe: () => noop
21
- };
22
- var locationRouter = {
23
- pathname: () => typeof window === "undefined" ? "/" : window.location.pathname,
24
- search: () => typeof window === "undefined" ? "" : window.location.search,
25
- replaceSearch: (nextSearch) => {
26
- if (typeof window === "undefined") return;
27
- const query = nextSearch && !nextSearch.startsWith("?") ? `?${nextSearch}` : nextSearch;
28
- const url = `${window.location.pathname}${query}${window.location.hash}`;
29
- window.history.replaceState(window.history.state, "", url);
30
- },
31
- subscribe: (listener) => {
32
- if (typeof window === "undefined") return noop;
33
- window.addEventListener("popstate", listener);
34
- return () => window.removeEventListener("popstate", listener);
35
- }
36
- };
37
- var consoleNotify = {
38
- info: (message) => console.info(`[summon] ${message}`),
39
- warn: (message) => console.warn(`[summon] ${message}`),
40
- error: (message) => console.error(`[summon] ${message}`)
41
- };
42
- var consoleErrorSink = {
43
- capture: (error, context) => console.error("[summon]", error, context)
44
- };
45
- var debugOff = { enabled: () => false };
46
- var DEFAULT_PORTS = {
47
- identity: anonymousIdentity,
48
- router: locationRouter,
49
- notify: consoleNotify,
50
- errors: consoleErrorSink,
51
- debug: debugOff,
52
- persistence: null
53
- };
54
- function resolvePorts(overrides) {
55
- return { ...DEFAULT_PORTS, ...overrides };
56
- }
57
-
58
- // src/core/registry.ts
59
- import { globalSlot } from "@ai-matrx/kit/global-slot";
60
- var state = () => globalSlot("ai-matrx.summon.registry", () => ({
61
- byId: /* @__PURE__ */ new Map(),
62
- byLinkKey: /* @__PURE__ */ new Map(),
63
- listeners: /* @__PURE__ */ new Set()
64
- }));
65
- function registerOverlayMeta(definitions) {
66
- const s = state();
67
- for (const def of definitions) {
68
- s.byId.set(def.id, def);
69
- const keys = def.link ? [def.link.key, ...def.link.aliases ?? []] : [];
70
- for (const key of keys) {
71
- const holder = s.byLinkKey.get(key);
72
- if (holder && holder.id !== def.id) {
73
- throw new Error(`[summon] link key "${key}" is claimed by both "${holder.id}" and "${def.id}"`);
74
- }
75
- s.byLinkKey.set(key, def);
76
- }
77
- }
78
- for (const listener of s.listeners) listener();
79
- }
80
- function getOverlayMeta(overlayId) {
81
- return state().byId.get(overlayId);
82
- }
83
- function getOverlayMetaByLinkKey(linkKey) {
84
- return state().byLinkKey.get(linkKey);
85
- }
86
- function allOverlayMeta() {
87
- return [...state().byId.values()];
88
- }
89
- function isRegisteredOverlay(overlayId) {
90
- return state().byId.has(overlayId);
91
- }
92
- function subscribeToOverlayRegistry(listener) {
93
- const s = state();
94
- s.listeners.add(listener);
95
- return () => s.listeners.delete(listener);
96
- }
97
- function resetOverlayRegistry() {
98
- const s = state();
99
- s.byId.clear();
100
- s.byLinkKey.clear();
101
- }
102
-
103
- // src/open/actions.ts
104
- function creator(type, build) {
105
- const create = (...args) => ({ type, payload: build(...args) });
106
- return Object.assign(create, {
107
- type,
108
- toString: () => type,
109
- match: (action) => typeof action === "object" && action !== null && action.type === type
110
- });
111
- }
112
- function isPlainRecord(value) {
113
- return typeof value === "object" && value !== null && !Array.isArray(value);
114
- }
115
- function stripFunctions(overlayId, data) {
116
- if (!isPlainRecord(data)) return data;
117
- const offenders = Object.keys(data).filter((key) => typeof data[key] === "function");
118
- if (offenders.length === 0) return data;
119
- console.error(
120
- `[summon] BUG: function value(s) in openOverlay data for "${overlayId}" (keys: ${offenders.join(", ")}). Functions cannot travel through Redux \u2014 the handler would NEVER fire. Register a handle (@ai-matrx/summon/handles) and pass its id string instead. The offending key(s) were stripped from state.`
121
- );
122
- const cleaned = { ...data };
123
- for (const key of offenders) delete cleaned[key];
124
- return cleaned;
125
- }
126
- function rawOpen(payload) {
127
- const raw = { overlayId: payload.overlayId };
128
- if (payload.instanceId !== void 0) raw.instanceId = payload.instanceId;
129
- if (payload.data !== void 0) raw.data = stripFunctions(payload.overlayId, payload.data);
130
- const defaults = getOverlayMeta(payload.overlayId)?.defaults;
131
- if (isPlainRecord(defaults)) raw.defaults = stripFunctions(payload.overlayId, defaults);
132
- return raw;
133
- }
134
- var O = "overlays/";
135
- var openOverlay = creator(O + "openOverlay", (payload) => rawOpen(payload));
136
- var closeOverlay = creator(
137
- O + "closeOverlay",
138
- (payload) => payload.instanceId === void 0 ? { overlayId: payload.overlayId } : { overlayId: payload.overlayId, instanceId: payload.instanceId }
139
- );
140
- var toggleOverlay = creator(O + "toggleOverlay", (payload) => rawOpen(payload));
141
- var closeAllInstancesOfOverlay = creator(O + "closeAllInstancesOfOverlay", (payload) => ({
142
- overlayId: payload.overlayId
143
- }));
144
- function overlayIdsBoundToPage() {
145
- return allOverlayMeta().filter((meta) => meta.closesOnNavigation === true).map((meta) => meta.id);
146
- }
147
- var closeOverlaysBoundToPage = creator(
148
- O + "closeOverlaysBoundToPage",
149
- (payload) => ({
150
- overlayIds: [...payload?.overlayIds ?? overlayIdsBoundToPage()]
151
- })
152
- );
153
- var closeAllOverlays = creator(O + "closeAllOverlays", () => void 0);
154
- var pruneStaleInstances = creator(O + "pruneStaleInstances", (payload) => payload);
155
- var W = "windowManager/";
156
- var pass = () => (payload) => payload;
157
- var focusWindow = creator(W + "focusWindow", pass());
158
- var restoreWindow = creator(W + "restoreWindow", pass());
159
- var toggleWindowsHidden = creator(W + "toggleWindowsHidden", () => void 0);
160
- var restoreAll = creator(W + "restoreAll", () => void 0);
161
- var minimizeAll = creator(W + "minimizeAll", pass());
162
- var arrangeActiveWindows = creator(W + "arrangeActiveWindows", pass());
163
- var revealWindow = creator(W + "revealWindow", pass());
164
- var updateWindowRect = creator(
165
- W + "updateWindowRect",
166
- pass()
167
- );
168
- var setOverlayStateValue = creator("overlayState/setOverlayStateValue", pass());
169
- var registerSyncEntry = creator("urlSync/registerSyncEntry", pass());
170
- var unregisterSyncEntry = creator("urlSync/unregisterSyncEntry", pass());
171
- var SUMMON_SLICE_KEYS = ["overlays", "windowManager", "urlSync", "overlayState"];
172
- function isSummonAction(action) {
173
- if (typeof action !== "object" || action === null) return false;
174
- const type = action.type;
175
- if (typeof type !== "string") return false;
176
- const slash = type.indexOf("/");
177
- return slash > 0 && SUMMON_SLICE_KEYS.includes(type.slice(0, slash));
178
- }
1
+ import {
2
+ DEFAULT_INSTANCE_ID,
3
+ DEFAULT_PORTS,
4
+ SUMMON_INSTALLED_ACTION,
5
+ SUMMON_SLICE_KEYS,
6
+ allOverlayMeta,
7
+ anonymousIdentity,
8
+ arrangeActiveWindows,
9
+ closeAllInstancesOfOverlay,
10
+ closeAllOverlays,
11
+ closeOverlay,
12
+ closeOverlaysBoundToPage,
13
+ consoleErrorSink,
14
+ consoleNotify,
15
+ createSummonGate,
16
+ debugOff,
17
+ defaultWindowIdFor,
18
+ dropPendingChannelsOf,
19
+ ensureSummonRuntime,
20
+ focusWindow,
21
+ getOverlayMeta,
22
+ getOverlayMetaByLinkKey,
23
+ installSummonCore,
24
+ instanceKey,
25
+ isRegisteredOverlay,
26
+ isSummonAction,
27
+ isSummonInstalled,
28
+ listOpenInstanceKeys,
29
+ locationRouter,
30
+ materializePendingChannels,
31
+ minimizeAll,
32
+ openOverlay,
33
+ openPendingEventChannel,
34
+ overlayIdsBoundToPage,
35
+ parseInstanceKey,
36
+ prefetchSummonRuntime,
37
+ pruneStaleInstances,
38
+ registerOverlayMeta,
39
+ registerSyncEntry,
40
+ resetOverlayRegistry,
41
+ resolvePorts,
42
+ restoreAll,
43
+ restoreWindow,
44
+ revealWindow,
45
+ selectAllMinimized,
46
+ selectAllWindows,
47
+ selectAnyOverlayTouched,
48
+ selectIsOverlayOpen,
49
+ selectOpenInstances,
50
+ selectOverlay,
51
+ selectOverlayData,
52
+ selectWindowsHidden,
53
+ setOverlayStateValue,
54
+ subscribeSummonInstalled,
55
+ subscribeToOverlayRegistry,
56
+ toggleOverlay,
57
+ toggleWindowsHidden,
58
+ unregisterSyncEntry,
59
+ updateWindowRect
60
+ } from "./chunk-server-C4KQZFIN.js";
61
+ import {
62
+ HANDLES_SLOT,
63
+ newHandleId,
64
+ registerHandleEntry,
65
+ removeHandleGroup,
66
+ unregisterHandleEntry
67
+ } from "./chunk-server-H7NUWPEM.js";
179
68
 
180
69
  // src/open/renderAcks.ts
181
- import { globalSlot as globalSlot2 } from "@ai-matrx/kit/global-slot";
182
- var slot = () => globalSlot2("ai-matrx.summon.renderWatchdog", () => ({ renderAcks: /* @__PURE__ */ new Map(), ackWaiters: /* @__PURE__ */ new Map(), watches: /* @__PURE__ */ new Map() }));
70
+ import { globalSlot } from "@ai-matrx/kit/global-slot";
71
+ var slot = () => globalSlot("ai-matrx.summon.renderWatchdog", () => ({ renderAcks: /* @__PURE__ */ new Map(), ackWaiters: /* @__PURE__ */ new Map(), watches: /* @__PURE__ */ new Map() }));
183
72
  function ackOverlaySurfaceRender(overlayId) {
184
73
  const s = slot();
185
74
  s.renderAcks.set(overlayId, { kind: "surface" });
@@ -194,242 +83,10 @@ function clearOverlaySurfaceRender(overlayId) {
194
83
  if (s.renderAcks.get(overlayId)?.kind === "surface") s.renderAcks.delete(overlayId);
195
84
  }
196
85
 
197
- // src/open/selectors.ts
198
- import { globalSlot as globalSlot3 } from "@ai-matrx/kit/global-slot";
199
- var overlaysOf = (state2) => state2.overlays;
200
- var CLOSED = Object.freeze({ isOpen: false, data: null });
201
- var EMPTY = Object.freeze([]);
202
- var selectOverlay = (state2, overlayId, instanceId = DEFAULT_INSTANCE_ID) => overlaysOf(state2)?.overlays[overlayId]?.[instanceId] ?? CLOSED;
203
- var selectIsOverlayOpen = (state2, overlayId, instanceId = DEFAULT_INSTANCE_ID) => selectOverlay(state2, overlayId, instanceId).isOpen;
204
- var selectOverlayData = (state2, overlayId, instanceId = DEFAULT_INSTANCE_ID) => selectOverlay(state2, overlayId, instanceId).data;
205
- var openCache = () => globalSlot3("ai-matrx.summon.openInstances", () => /* @__PURE__ */ new Map());
206
- var selectOpenInstances = (state2, overlayId) => {
207
- const bucket = overlaysOf(state2)?.overlays[overlayId];
208
- const cache = openCache();
209
- const hit = cache.get(overlayId);
210
- if (hit && hit.bucket === bucket) return hit.result;
211
- let result = EMPTY;
212
- if (bucket) {
213
- const open = [];
214
- for (const [instanceId, inst] of Object.entries(bucket)) if (inst.isOpen) open.push({ instanceId, data: inst.data });
215
- if (open.length > 0) result = open;
216
- }
217
- cache.set(overlayId, { bucket, result });
218
- return result;
219
- };
220
- function listOpenInstanceKeys(state2) {
221
- const keys = [];
222
- for (const [overlayId, bucket] of Object.entries(overlaysOf(state2)?.overlays ?? {})) {
223
- for (const [instanceId, inst] of Object.entries(bucket)) if (inst.isOpen) keys.push(`${overlayId}:${instanceId}`);
224
- }
225
- return keys;
226
- }
227
- function selectAnyOverlayTouched(state2) {
228
- for (const _ in overlaysOf(state2)?.overlays ?? {}) return true;
229
- return false;
230
- }
231
- var selectWindowsHidden = (state2) => state2.windowManager?.windowsHidden ?? false;
232
- var EMPTY_WINDOWS = Object.freeze([]);
233
- var lastWindowsMap = null;
234
- var lastWindows = EMPTY_WINDOWS;
235
- function selectAllWindows(state2) {
236
- const map = state2.windowManager?.windows;
237
- if (!map) return EMPTY_WINDOWS;
238
- if (map !== lastWindowsMap) {
239
- lastWindowsMap = map;
240
- lastWindows = Object.values(map).sort((a, b) => b.zIndex - a.zIndex);
241
- }
242
- return lastWindows;
243
- }
244
- function selectAllMinimized(state2) {
245
- const map = state2.windowManager?.windows;
246
- if (!map) return false;
247
- const wins = Object.values(map);
248
- return wins.length > 0 && wins.every((w) => w.state === "minimized");
249
- }
250
-
251
- // src/open/gate.ts
252
- import { globalSlot as globalSlot4 } from "@ai-matrx/kit/global-slot";
253
- var SUMMON_INSTALLED_ACTION = "@@summon/installed";
254
- var slot2 = () => globalSlot4("ai-matrx.summon.gate", () => ({ core: null, loading: null, gates: /* @__PURE__ */ new Set(), listeners: /* @__PURE__ */ new Set() }));
255
- function installSummonCore(core) {
256
- const s = slot2();
257
- if (s.core) return;
258
- s.core = core;
259
- const gates = [...s.gates];
260
- s.gates.clear();
261
- for (const gate of gates) gate.install(core);
262
- for (const listener of [...s.listeners]) listener();
263
- }
264
- function isSummonInstalled() {
265
- return slot2().core !== null;
266
- }
267
- function subscribeSummonInstalled(listener) {
268
- const s = slot2();
269
- s.listeners.add(listener);
270
- return () => s.listeners.delete(listener);
271
- }
272
- function ensureSummonRuntime() {
273
- const s = slot2();
274
- if (s.core) return Promise.resolve();
275
- s.loading ??= import("@ai-matrx/summon").then(
276
- (core) => installSummonCore(core.summonCore),
277
- (error) => {
278
- s.loading = null;
279
- throw error;
280
- }
281
- );
282
- return s.loading;
283
- }
284
- function prefetchSummonRuntime() {
285
- ensureSummonRuntime().catch(() => void 0);
286
- }
287
- function createSummonGate(options = {}) {
288
- let inject = null;
289
- let injected = false;
290
- let api = null;
291
- let next = null;
292
- let chain = null;
293
- const queue = [];
294
- const settle = (core2, live) => {
295
- if (inject && !injected) {
296
- inject(core2.reducers);
297
- injected = true;
298
- }
299
- if (!api || !next || chain) return;
300
- const store = api;
301
- let composed = next;
302
- for (const middleware2 of [...core2.createMiddleware(options.ports)].reverse()) {
303
- composed = middleware2(store)(composed);
304
- }
305
- chain = composed;
306
- const flush = () => {
307
- if (live) store.dispatch({ type: SUMMON_INSTALLED_ACTION });
308
- for (const action of queue.splice(0)) store.dispatch(action);
309
- };
310
- if (live) flush();
311
- else if (queue.length > 0) queueMicrotask(flush);
312
- };
313
- const internals = { install: (core2) => settle(core2, true) };
314
- const core = () => slot2().core;
315
- const middleware = (storeApi) => {
316
- api = storeApi;
317
- return (nextDispatch) => {
318
- next = nextDispatch;
319
- const loaded = core();
320
- if (loaded) settle(loaded, false);
321
- else slot2().gates.add(internals);
322
- return (action) => {
323
- if (chain) return chain(action);
324
- if (!isSummonAction(action)) return nextDispatch(action);
325
- queue.push(action);
326
- void ensureSummonRuntime().catch((error) => {
327
- console.error("[summon] the overlay runtime failed to load; queued requests are kept for the next try", error);
328
- });
329
- return action;
330
- };
331
- };
332
- };
333
- return {
334
- middleware,
335
- attachReducer(fn) {
336
- inject = fn;
337
- const loaded = core();
338
- if (loaded) {
339
- inject(loaded.reducers);
340
- injected = true;
341
- }
342
- }
343
- };
344
- }
345
-
346
- // src/handles/slot.ts
347
- var HANDLES_SLOT = "ai-matrx.summon.handles";
348
-
349
86
  // src/open/peek.ts
350
87
  function peekHandle(id) {
351
- const slot3 = globalThis[Symbol.for(HANDLES_SLOT)];
352
- return slot3?.callbacks.get(id)?.callback;
353
- }
354
-
355
- // src/open/ids.ts
356
- function newHandleId() {
357
- const c = typeof globalThis.crypto === "undefined" ? void 0 : globalThis.crypto;
358
- if (c && typeof c.randomUUID === "function") return c.randomUUID();
359
- const bytes = new Uint8Array(16);
360
- if (c && typeof c.getRandomValues === "function") {
361
- c.getRandomValues(bytes);
362
- } else {
363
- for (let i = 0; i < 16; i += 1) bytes[i] = Math.floor(Math.random() * 256);
364
- }
365
- bytes[6] = (bytes[6] ?? 0) & 15 | 64;
366
- bytes[8] = (bytes[8] ?? 0) & 63 | 128;
367
- const hex2 = Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
368
- return `${hex2.slice(0, 8)}-${hex2.slice(8, 12)}-${hex2.slice(12, 16)}-${hex2.slice(16, 20)}-${hex2.slice(20)}`;
369
- }
370
-
371
- // src/open/handleEntries.ts
372
- import { globalSlot as globalSlot5 } from "@ai-matrx/kit/global-slot";
373
- var handlesState = () => globalSlot5(HANDLES_SLOT, () => ({
374
- callbacks: /* @__PURE__ */ new Map(),
375
- groups: /* @__PURE__ */ new Map(),
376
- owners: /* @__PURE__ */ new Map(),
377
- registryListeners: /* @__PURE__ */ new Set()
378
- }));
379
- function notifyHandlesRegistry() {
380
- for (const listener of [...handlesState().registryListeners]) listener();
381
- }
382
- function deleteHandleEntry(id, notify = true) {
383
- const s = handlesState();
384
- const entry = s.callbacks.get(id);
385
- if (!entry) return;
386
- s.callbacks.delete(id);
387
- if (entry.groupId !== void 0) {
388
- const group = s.groups.get(entry.groupId);
389
- group?.delete(id);
390
- if (group?.size === 0) s.groups.delete(entry.groupId);
391
- }
392
- if (entry.owner !== void 0) {
393
- const owned = s.owners.get(entry.owner);
394
- owned?.delete(id);
395
- if (owned?.size === 0) s.owners.delete(entry.owner);
396
- }
397
- if (notify) notifyHandlesRegistry();
398
- entry.onRemove?.();
399
- }
400
- function registerHandleEntry(slot3, options = {}) {
401
- const s = handlesState();
402
- const id = options.id ?? newHandleId();
403
- if (s.callbacks.has(id)) deleteHandleEntry(id, false);
404
- const entry = { callback: slot3 };
405
- if (options.context !== void 0) entry.context = options.context;
406
- if (options.groupId !== void 0) entry.groupId = options.groupId;
407
- if (options.owner !== void 0) entry.owner = options.owner;
408
- if (options.onRemove !== void 0) entry.onRemove = options.onRemove;
409
- s.callbacks.set(id, entry);
410
- if (options.groupId !== void 0) {
411
- const group = s.groups.get(options.groupId) ?? /* @__PURE__ */ new Set();
412
- group.add(id);
413
- s.groups.set(options.groupId, group);
414
- }
415
- if (options.owner !== void 0) {
416
- const owned = s.owners.get(options.owner) ?? /* @__PURE__ */ new Set();
417
- owned.add(id);
418
- s.owners.set(options.owner, owned);
419
- }
420
- notifyHandlesRegistry();
421
- return id;
422
- }
423
- function unregisterHandleEntry(id) {
424
- deleteHandleEntry(id, true);
425
- }
426
- function removeHandleGroup(groupId) {
427
- const s = handlesState();
428
- const group = s.groups.get(groupId);
429
- if (!group) return;
430
- s.groups.delete(groupId);
431
- for (const id of [...group]) deleteHandleEntry(id, false);
432
- notifyHandlesRegistry();
88
+ const slot2 = globalThis[Symbol.for(HANDLES_SLOT)];
89
+ return slot2?.callbacks.get(id)?.callback;
433
90
  }
434
91
 
435
92
  // src/open/lazyOpener.ts
@@ -471,7 +128,7 @@ function lazyOpener(overlayId, load, options = {}) {
471
128
  if (real) return real(...args);
472
129
  let target = null;
473
130
  let closed = false;
474
- const pending2 = [];
131
+ const pending = [];
475
132
  const standIn = {
476
133
  instanceId: instanceId ?? "",
477
134
  get callbackGroupId() {
@@ -479,7 +136,7 @@ function lazyOpener(overlayId, load, options = {}) {
479
136
  },
480
137
  update(patch) {
481
138
  if (target) target.update?.(patch);
482
- else if (!closed) pending2.push(patch);
139
+ else if (!closed) pending.push(patch);
483
140
  },
484
141
  close() {
485
142
  if (target) target.close?.();
@@ -491,7 +148,7 @@ function lazyOpener(overlayId, load, options = {}) {
491
148
  if (closed) return;
492
149
  const handle = opener(...args);
493
150
  target = handle ?? {};
494
- for (const patch of pending2.splice(0)) target.update?.(patch);
151
+ for (const patch of pending.splice(0)) target.update?.(patch);
495
152
  },
496
153
  (error) => {
497
154
  console.error(`[summon] the "${overlayId}" opener failed to load; nothing opened`, error);
@@ -502,28 +159,6 @@ function lazyOpener(overlayId, load, options = {}) {
502
159
  return lazy;
503
160
  }
504
161
 
505
- // src/open/channels.ts
506
- import { globalSlot as globalSlot6 } from "@ai-matrx/kit/global-slot";
507
- var pending = () => globalSlot6("ai-matrx.summon.pendingChannels", () => /* @__PURE__ */ new Map());
508
- function materializePendingChannels(createEventChannel) {
509
- const map = pending();
510
- for (const [id, entry] of [...map]) {
511
- map.delete(id);
512
- const channel = createEventChannel({ owner: entry.owner, id });
513
- channel.subscribe((message) => entry.getHandlers()?.[message.type]?.(message.payload));
514
- }
515
- }
516
- function openPendingEventChannel(owner, getHandlers) {
517
- const id = `ch-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
518
- pending().set(id, { owner, getHandlers });
519
- void import("@ai-matrx/summon/handles").then(({ createEventChannel }) => materializePendingChannels(createEventChannel));
520
- return id;
521
- }
522
- function dropPendingChannelsOf(owner) {
523
- const map = pending();
524
- for (const [id, entry] of [...map]) if (entry.owner === owner) map.delete(id);
525
- }
526
-
527
162
  // src/open/grammar.ts
528
163
  var hex = (ch) => `%${ch.charCodeAt(0).toString(16).toUpperCase().padStart(2, "0")}`;
529
164
  function encodeLinkId(id) {