@agentorg/cli 0.0.3 → 0.0.4

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.
Files changed (153) hide show
  1. package/README.md +14 -10
  2. package/dist/bundled/index.json +4 -4
  3. package/dist/bundled/{sha256-87e121cbe58279f3a633e61c9773b61fc17fd53eac3d7c6f037925cbfd5d5384.agentorg → sha256-01d69bc3888c2a53963f4413d47de909d129ad27c78e9af6d830bb50c3478419.agentorg} +0 -0
  4. package/dist/bundled/{sha256-51ecf151e590f5e57f28229d4cb36e4932a2f1670e50ddf1a3ccf335a1ee146d.agentorg → sha256-84165e3be5c904fc971d983dab31102e07cca725d8629a6fd7d118fa3a0a88b8.agentorg} +0 -0
  5. package/dist/bundled/sha256-ade9132b3f34b4c39db92adeadc7e540dc745e4a81b5b54f5d45bf9ec92bca75.agentorg +0 -0
  6. package/dist/bundled/{sha256-b76ec31282e5b863ee9569dfd9d50b283a21101cbe1b3fac23d1cbcf16b9a408.agentorg → sha256-f4330f5987f37d8cf3aeb44d2f831b573641a87186daa2f811f0c35ba04804f0.agentorg} +0 -0
  7. package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/build.d.ts +2 -2
  8. package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/build.js +14 -4
  9. package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/hub-actor.js +8 -0
  10. package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/index.d.ts +1 -1
  11. package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/index.js +1 -1
  12. package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/router.js +40 -16
  13. package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/state.d.ts +63 -0
  14. package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/state.js +177 -36
  15. package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/storage.d.ts +2 -1
  16. package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/storage.js +3 -2
  17. package/{node_modules → dist/node_modules}/@agentorg/hub/package.json +3 -0
  18. package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/hub.d.ts +43 -3
  19. package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/hub.js +40 -3
  20. package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/index.d.ts +1 -0
  21. package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/index.js +1 -0
  22. package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/installer.d.ts +37 -0
  23. package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/installer.js +34 -3
  24. package/dist/node_modules/@agentorg/interfaces/dist/src/rules.d.ts +35 -0
  25. package/dist/node_modules/@agentorg/interfaces/dist/src/rules.js +37 -0
  26. package/dist/node_modules/@agentorg/kit/dist/src/chat.d.ts +37 -0
  27. package/dist/node_modules/@agentorg/kit/dist/src/chat.js +131 -0
  28. package/dist/node_modules/@agentorg/kit/dist/src/components.d.ts +94 -0
  29. package/dist/node_modules/@agentorg/kit/dist/src/components.js +66 -0
  30. package/dist/node_modules/@agentorg/kit/dist/src/icons.d.ts +17 -0
  31. package/dist/node_modules/@agentorg/kit/dist/src/icons.js +30 -0
  32. package/dist/node_modules/@agentorg/kit/dist/src/index.d.ts +6 -0
  33. package/dist/node_modules/@agentorg/kit/dist/src/index.js +10 -0
  34. package/dist/node_modules/@agentorg/kit/dist/src/markdown.d.ts +9 -0
  35. package/dist/node_modules/@agentorg/kit/dist/src/markdown.js +14 -0
  36. package/dist/node_modules/@agentorg/kit/dist/src/resizable.d.ts +5 -0
  37. package/dist/node_modules/@agentorg/kit/dist/src/resizable.js +8 -0
  38. package/dist/node_modules/@agentorg/kit/dist/src/styles.d.ts +11 -0
  39. package/dist/node_modules/@agentorg/kit/dist/src/styles.js +166 -0
  40. package/dist/node_modules/@agentorg/kit/package.json +44 -0
  41. package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/frame/runtime.js +172 -17
  42. package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/host/runner.js +168 -11
  43. package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/client.d.ts +18 -0
  44. package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/client.js +24 -3
  45. package/dist/node_modules/@agentorg/sdk/dist/src/frame-base.d.ts +8 -0
  46. package/dist/node_modules/@agentorg/sdk/dist/src/frame-base.js +64 -0
  47. package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/frame-entry.js +4 -4
  48. package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/frame-host.d.ts +1 -10
  49. package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/frame-host.js +0 -23
  50. package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/frame-protocol.d.ts +0 -8
  51. package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/frame.d.ts +0 -2
  52. package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/frame.js +0 -8
  53. package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/host.js +5 -0
  54. package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/index.d.ts +1 -1
  55. package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/module-host.d.ts +6 -1
  56. package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/module-host.js +24 -1
  57. package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/module.d.ts +30 -1
  58. package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/package.js +111 -6
  59. package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/runtime.d.ts +22 -1
  60. package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/runtime.js +114 -0
  61. package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/testing.d.ts +14 -2
  62. package/dist/node_modules/@agentorg/sdk/dist/src/testing.js +89 -0
  63. package/{node_modules → dist/node_modules}/@agentorg/shell/dist/app.css +27 -144
  64. package/dist/node_modules/@agentorg/shell/dist/app.js +219 -0
  65. package/{node_modules → dist/node_modules}/@agentorg/shell/package.json +1 -0
  66. package/{node_modules → dist/node_modules}/@agentorg/wire/dist/src/index.d.ts +1 -1
  67. package/{node_modules → dist/node_modules}/@agentorg/wire/dist/src/ops.d.ts +14 -1
  68. package/{node_modules → dist/node_modules}/@agentorg/wire/dist/src/ops.js +22 -2
  69. package/dist/src/cli.js +23 -0
  70. package/dist/src/gateway.js +42 -1
  71. package/dist/src/rules.d.ts +71 -0
  72. package/dist/src/rules.js +157 -0
  73. package/package.json +13 -16
  74. package/dist/bundled/sha256-e4c0e857cea3a721998effe2ca859c4011978b9bc36e63c058bfc17c27a1772e.agentorg +0 -0
  75. package/node_modules/@agentorg/sdk/dist/src/testing.js +0 -51
  76. package/node_modules/@agentorg/shell/dist/app.js +0 -9
  77. /package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/hub-actor.d.ts +0 -0
  78. /package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/logs.d.ts +0 -0
  79. /package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/logs.js +0 -0
  80. /package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/net.d.ts +0 -0
  81. /package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/net.js +0 -0
  82. /package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/processes.d.ts +0 -0
  83. /package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/processes.js +0 -0
  84. /package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/router.d.ts +0 -0
  85. /package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/server.d.ts +0 -0
  86. /package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/server.js +0 -0
  87. /package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/validate-worker.d.ts +0 -0
  88. /package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/validate-worker.js +0 -0
  89. /package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/validate.d.ts +0 -0
  90. /package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/validate.js +0 -0
  91. /package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/account-login.d.ts +0 -0
  92. /package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/account-login.js +0 -0
  93. /package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/chat.d.ts +0 -0
  94. /package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/chat.js +0 -0
  95. /package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/http-egress.d.ts +0 -0
  96. /package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/http-egress.js +0 -0
  97. /package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/kv.d.ts +0 -0
  98. /package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/kv.js +0 -0
  99. /package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/layout.d.ts +0 -0
  100. /package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/layout.js +0 -0
  101. /package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/llm-session.d.ts +0 -0
  102. /package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/llm-session.js +0 -0
  103. /package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/storage-admin.d.ts +0 -0
  104. /package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/storage-admin.js +0 -0
  105. /package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/ui-shell.d.ts +0 -0
  106. /package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/ui-shell.js +0 -0
  107. /package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/ui-view.d.ts +0 -0
  108. /package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/ui-view.js +0 -0
  109. /package/{node_modules → dist/node_modules}/@agentorg/interfaces/package.json +0 -0
  110. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/build.d.ts +0 -0
  111. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/build.js +0 -0
  112. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/canonical.d.ts +0 -0
  113. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/canonical.js +0 -0
  114. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/cli.d.ts +0 -0
  115. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/cli.js +0 -0
  116. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/client-http.d.ts +0 -0
  117. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/client-http.js +0 -0
  118. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/describe.d.ts +0 -0
  119. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/describe.js +0 -0
  120. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/errors.d.ts +0 -0
  121. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/errors.js +0 -0
  122. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/frame-entry.d.ts +0 -0
  123. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/frame-protocol.js +0 -0
  124. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/host-main.d.ts +0 -0
  125. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/host-main.js +0 -0
  126. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/host.d.ts +0 -0
  127. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/index.js +0 -0
  128. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/interface.d.ts +0 -0
  129. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/interface.js +0 -0
  130. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/manifest-api.d.ts +0 -0
  131. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/manifest-api.js +0 -0
  132. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/manifest.d.ts +0 -0
  133. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/manifest.js +0 -0
  134. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/module.js +0 -0
  135. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/package.d.ts +0 -0
  136. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/person-commands.d.ts +0 -0
  137. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/person-commands.js +0 -0
  138. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/tar.d.ts +0 -0
  139. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/tar.js +0 -0
  140. /package/{node_modules → dist/node_modules}/@agentorg/sdk/package.json +0 -0
  141. /package/{node_modules → dist/node_modules}/@agentorg/shell/dist/agent-bindings.js +0 -0
  142. /package/{node_modules → dist/node_modules}/@agentorg/shell/dist/index.html +0 -0
  143. /package/{node_modules → dist/node_modules}/@agentorg/shell/src/agent-bindings.ts +0 -0
  144. /package/{node_modules → dist/node_modules}/@agentorg/wire/dist/src/bytes.d.ts +0 -0
  145. /package/{node_modules → dist/node_modules}/@agentorg/wire/dist/src/bytes.js +0 -0
  146. /package/{node_modules → dist/node_modules}/@agentorg/wire/dist/src/frames.d.ts +0 -0
  147. /package/{node_modules → dist/node_modules}/@agentorg/wire/dist/src/frames.js +0 -0
  148. /package/{node_modules → dist/node_modules}/@agentorg/wire/dist/src/index.js +0 -0
  149. /package/{node_modules → dist/node_modules}/@agentorg/wire/dist/src/transports.d.ts +0 -0
  150. /package/{node_modules → dist/node_modules}/@agentorg/wire/dist/src/transports.js +0 -0
  151. /package/{node_modules → dist/node_modules}/@agentorg/wire/dist/src/yamux.d.ts +0 -0
  152. /package/{node_modules → dist/node_modules}/@agentorg/wire/dist/src/yamux.js +0 -0
  153. /package/{node_modules → dist/node_modules}/@agentorg/wire/package.json +0 -0
@@ -1,9 +1,9 @@
1
1
  // src/errors.ts
2
2
  var BRAND = /* @__PURE__ */ Symbol.for("@agentorg/sdk/error");
3
3
  var isBranded = (value, name) => typeof value === "object" && value !== null && value[BRAND] === name;
4
- var instanceOf = (asked, base, name, value) => (
4
+ var instanceOf = (asked, base2, name, value) => (
5
5
  // The name is given, not read from the class: a bundler may rename a class.
6
- asked === base ? isBranded(value, name) : Function.prototype[Symbol.hasInstance].call(asked, value)
6
+ asked === base2 ? isBranded(value, name) : Function.prototype[Symbol.hasInstance].call(asked, value)
7
7
  );
8
8
  var NotConnected = class _NotConnected extends Error {
9
9
  static [Symbol.hasInstance](value) {
@@ -97,7 +97,7 @@ function createRuntime(definition, options) {
97
97
  if (!state.binding) throw new NotConnected(name);
98
98
  return state.binding.provider;
99
99
  };
100
- const base = {
100
+ const base2 = {
101
101
  get bound() {
102
102
  return state.binding !== void 0;
103
103
  },
@@ -112,7 +112,7 @@ function createRuntime(definition, options) {
112
112
  };
113
113
  switch (iface.kind) {
114
114
  case "rpc":
115
- return Object.assign(base, {
115
+ return Object.assign(base2, {
116
116
  call: Object.fromEntries(
117
117
  Object.entries(iface.methods).map(([method, spec]) => [
118
118
  method,
@@ -140,7 +140,7 @@ function createRuntime(definition, options) {
140
140
  }
141
141
  });
142
142
  case "stream":
143
- return Object.assign(base, {
143
+ return Object.assign(base2, {
144
144
  async open(params) {
145
145
  const target2 = provider();
146
146
  const parsed = check(iface.open, params, `${name} open`);
@@ -150,7 +150,7 @@ function createRuntime(definition, options) {
150
150
  }
151
151
  });
152
152
  case "http":
153
- return Object.assign(base, {
153
+ return Object.assign(base2, {
154
154
  async fetch(request) {
155
155
  const target2 = provider();
156
156
  if (!target2.fetch)
@@ -214,6 +214,102 @@ function createRuntime(definition, options) {
214
214
  throw new Refused("unimplemented", `${name} hasn't been implemented yet.`);
215
215
  return state.impl;
216
216
  };
217
+ const exposed = /* @__PURE__ */ new Map();
218
+ const exposedWatchers = /* @__PURE__ */ new Set();
219
+ const exposedChanged = () => {
220
+ const failed = (error) => options.log.error("An onExposed handler threw.", { error: String(error) });
221
+ for (const fn of [...exposedWatchers])
222
+ try {
223
+ const done = fn();
224
+ if (done instanceof Promise) done.catch(failed);
225
+ } catch (error) {
226
+ failed(error);
227
+ }
228
+ };
229
+ const listenExposed = (slot, state, event) => {
230
+ const entry = state.events.get(event);
231
+ if (state.gone || !entry || entry.stop || !entry.fns.size) return;
232
+ let ended = false;
233
+ let stop;
234
+ stop = state.source.subscribe(
235
+ event,
236
+ (payload) => {
237
+ for (const fn of [...entry.fns])
238
+ try {
239
+ fn(payload);
240
+ } catch (error) {
241
+ options.log.error("An event handler threw.", { slot, event, error: String(error) });
242
+ }
243
+ },
244
+ // Ended by the provider going: the interest stays for when it is usable again.
245
+ () => {
246
+ ended = true;
247
+ if (entry.stop === stop) entry.stop = void 0;
248
+ }
249
+ );
250
+ if (!ended) entry.stop = stop;
251
+ };
252
+ const exposedHandle = (slot, state) => {
253
+ const { described, provider } = state.source;
254
+ return Object.freeze({
255
+ slot,
256
+ described,
257
+ provider: Object.freeze({ actor: provider.actor, export: provider.export }),
258
+ call: Object.freeze(
259
+ Object.fromEntries(
260
+ (described.kind === "rpc" ? Object.keys(described.methods) : []).map((method) => [
261
+ method,
262
+ async (input) => {
263
+ if (state.gone) throw new NotConnected(slot);
264
+ return state.source.call(method, input);
265
+ }
266
+ ])
267
+ )
268
+ ),
269
+ on(event, fn) {
270
+ if (described.kind !== "rpc" || !own(described.events, event))
271
+ throw new TypeError(`${slot} has no event ${event}.`);
272
+ const entry = state.events.get(event) ?? { fns: /* @__PURE__ */ new Set() };
273
+ state.events.set(event, entry);
274
+ entry.fns.add(fn);
275
+ listenExposed(slot, state, event);
276
+ return () => {
277
+ entry.fns.delete(fn);
278
+ if (entry.fns.size) return;
279
+ entry.stop?.();
280
+ entry.stop = void 0;
281
+ };
282
+ }
283
+ });
284
+ };
285
+ const unexpose = (slot) => {
286
+ const state = exposed.get(slot);
287
+ if (!state) return;
288
+ exposed.delete(slot);
289
+ state.gone = true;
290
+ for (const entry of state.events.values()) {
291
+ entry.stop?.();
292
+ entry.stop = void 0;
293
+ }
294
+ exposedChanged();
295
+ };
296
+ const expose = (slot, source) => {
297
+ const here = exposed.get(slot);
298
+ if (here && here.source.described.hash === source.described.hash && here.source.provider.actor === source.provider.actor && here.source.provider.export === source.provider.export) {
299
+ here.source = source;
300
+ for (const [event, entry] of here.events) {
301
+ entry.stop?.();
302
+ entry.stop = void 0;
303
+ listenExposed(slot, here, event);
304
+ }
305
+ return;
306
+ }
307
+ if (here) unexpose(slot);
308
+ const state = { source, gone: false, events: /* @__PURE__ */ new Map() };
309
+ state.handle = exposedHandle(slot, state);
310
+ exposed.set(slot, state);
311
+ exposedChanged();
312
+ };
217
313
  const ctx = {
218
314
  slots: Object.fromEntries(
219
315
  Object.entries(definition.slots).map(([name, iface]) => [name, slotHandle(name, iface)])
@@ -239,7 +335,12 @@ function createRuntime(definition, options) {
239
335
  }
240
336
  ),
241
337
  self: options.self,
242
- log: options.log
338
+ log: options.log,
339
+ exposed: () => Object.freeze([...exposed.values()].map((state) => state.handle)),
340
+ onExposed(fn) {
341
+ exposedWatchers.add(fn);
342
+ return () => void exposedWatchers.delete(fn);
343
+ }
243
344
  };
244
345
  const serving = (exportName) => {
245
346
  const state = target(exportName, "http");
@@ -306,6 +407,8 @@ function createRuntime(definition, options) {
306
407
  if (!state) throw new TypeError(`No slot ${slot}.`);
307
408
  if (state.binding) notify(slot, state.binds);
308
409
  },
410
+ expose,
411
+ unexpose,
309
412
  async call(exportName, method, input, caller) {
310
413
  const state = target(exportName, "rpc");
311
414
  const spec = own(state.iface.methods, method);
@@ -552,13 +655,7 @@ function runFrame(options) {
552
655
  log.error("The frame couldn't handle a message from the shell.", { error: String(error) });
553
656
  }
554
657
  };
555
- let told;
556
658
  return {
557
- size(height) {
558
- if (!mounted || height === told) return;
559
- told = height;
560
- send({ op: "size", height });
561
- },
562
659
  failed(error) {
563
660
  log.error(error instanceof Error ? error.message : String(error), {
564
661
  ...error instanceof Error && error.stack ? { stack: error.stack } : {}
@@ -573,9 +670,71 @@ function runFrame(options) {
573
670
  };
574
671
  }
575
672
 
673
+ // src/frame-base.ts
674
+ var FRAME_BASE = `
675
+ :where(*, *::before, *::after) { box-sizing: border-box; }
676
+ :where(html, body) { height: 100%; margin: 0; background: transparent; }
677
+ :where(body) {
678
+ overflow: auto; scrollbar-width: none;
679
+ color: var(--fg); font: 14px/1.45 var(--font, ui-sans-serif, system-ui, sans-serif);
680
+ -webkit-font-smoothing: antialiased;
681
+ }
682
+ :where(body)::-webkit-scrollbar { display: none; }
683
+ :where(body > :only-child) { min-height: 100%; }
684
+ :where(h1, h2, h3, h4) { margin: 0 0 8px; font-weight: 600; letter-spacing: -0.01em; }
685
+ :where(h1) { font-size: 20px; }
686
+ :where(h2) { font-size: 16px; }
687
+ :where(h3, h4) { font-size: 14px; }
688
+ :where(p) { margin: 0 0 8px; }
689
+ :where(small) { color: var(--muted); font-size: 12.5px; }
690
+ :where(a) { color: inherit; text-underline-offset: 2px; }
691
+ :where(hr) { border: 0; border-top: 1px solid var(--line); margin: 10px 0; }
692
+ :where(ul, ol) { margin: 0 0 10px; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 6px; }
693
+ :where(li) { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-radius: 10px; background: var(--raised); }
694
+ :where(button) {
695
+ height: 34px; padding: 0 12px; border: 0; border-radius: 9px; cursor: pointer;
696
+ background: var(--hover); color: var(--fg); font: inherit; font-weight: 500;
697
+ }
698
+ :where(button:hover) { background: var(--selected); }
699
+ :where(button:disabled) { opacity: 0.5; cursor: default; }
700
+ :where(button[type="submit"], button.primary) { background: var(--accent); color: var(--accent-fg); font-weight: 600; }
701
+ :where(input:not([type]), input[type="text"], input[type="search"], input[type="number"], input[type="url"], input[type="email"], select) {
702
+ height: 34px; padding: 0 10px; border: 0; border-radius: 9px; outline: 0;
703
+ background: var(--raised); color: var(--fg); font: inherit;
704
+ }
705
+ :where(textarea) { padding: 8px 10px; border: 0; border-radius: 9px; outline: 0; resize: none; background: var(--raised); color: var(--fg); font: inherit; }
706
+ :where(input:focus-visible, textarea:focus-visible, select:focus-visible, button:focus-visible) { box-shadow: 0 0 0 1.5px var(--ring); outline: 0; }
707
+ :where(input[type="checkbox"]) {
708
+ appearance: none; width: 16px; height: 16px; margin: 0; flex: none; display: grid; place-items: center;
709
+ border: 1.5px solid var(--faint); border-radius: 5px; cursor: pointer;
710
+ }
711
+ :where(input[type="checkbox"]:checked) { background: var(--ok); border-color: var(--ok); }
712
+ :where(input[type="checkbox"]:checked)::after {
713
+ content: ""; width: 4px; height: 8px; border: solid white; border-width: 0 2px 2px 0;
714
+ transform: translateY(-1px) rotate(45deg);
715
+ }
716
+ :where(li:has(> input[type="checkbox"]:checked) > span) { color: var(--faint); text-decoration: line-through; }
717
+ :where(form) { display: flex; gap: 6px; }
718
+ :where(form > input, form > textarea) { flex: 1; min-width: 0; }
719
+ :where(table) { width: 100%; border-collapse: collapse; font-size: 13px; }
720
+ :where(th) { padding: 0 8px 6px; text-align: left; color: var(--faint); font-weight: 500; font-size: 12px; }
721
+ :where(td) { padding: 7px 8px; border-top: 1px solid var(--line); }
722
+ :where(code, pre) { font: 12.5px/1.5 ui-monospace, SFMono-Regular, Menlo, monospace; }
723
+ :where(code) { padding: 1px 5px; border-radius: 5px; background: var(--raised); }
724
+ :where(pre) { margin: 0 0 10px; padding: 10px 12px; border-radius: 10px; background: var(--raised); overflow: auto; }
725
+ :where(pre code) { padding: 0; background: none; }
726
+ :where(progress) { appearance: none; width: 100%; height: 4px; border: 0; border-radius: 2px; background: var(--raised); }
727
+ :where(progress)::-webkit-progress-bar { background: var(--raised); border-radius: 2px; }
728
+ :where(progress)::-webkit-progress-value { background: var(--ok); border-radius: 2px; }
729
+ :where(progress)::-moz-progress-bar { background: var(--ok); border-radius: 2px; }
730
+ `;
731
+
576
732
  // src/frame-entry.ts
577
733
  var self = globalThis;
578
734
  var frame;
735
+ var base = self.document.createElement("style");
736
+ base.textContent = FRAME_BASE;
737
+ self.document.head.prepend(base);
579
738
  self.addEventListener("message", (event) => {
580
739
  const port = event.ports[0];
581
740
  if (frame || event.source !== self.parent || event.data !== FRAME_HELLO || !port) return;
@@ -589,10 +748,6 @@ self.addEventListener("message", (event) => {
589
748
  if (name.startsWith("--")) self.document.documentElement.style.setProperty(name, value);
590
749
  }
591
750
  });
592
- const body = self.document.body;
593
- new self.ResizeObserver(
594
- () => frame?.size(Math.ceil(body.getBoundingClientRect().height))
595
- ).observe(body);
596
751
  });
597
752
  self.addEventListener("error", (event) => frame?.failed(event.error ?? event.message));
598
753
  self.addEventListener("unhandledrejection", (event) => frame?.failed(event.reason));
@@ -478,10 +478,27 @@ function parseHeader(value) {
478
478
  return { op: "offer", name: text(value, "name"), interface: value.interface };
479
479
  case "withdraw":
480
480
  return { op: "withdraw", name: text(value, "name") };
481
- case "slot":
481
+ case "slot": {
482
482
  if (typeof value.bound !== "boolean")
483
483
  throw new HeaderError("A slot header needs bound.");
484
- return { op: "slot", name: text(value, "name"), bound: value.bound };
484
+ if (!("exposed" in value))
485
+ return { op: "slot", name: text(value, "name"), bound: value.bound };
486
+ const exposed = value.exposed;
487
+ if (!value.bound || !isRecord(exposed) || !isRecord(exposed.interface) || !isRecord(exposed.provider))
488
+ throw new HeaderError("A slot header's exposed is a bound slot's {interface, provider}.");
489
+ return {
490
+ op: "slot",
491
+ name: text(value, "name"),
492
+ bound: true,
493
+ exposed: {
494
+ interface: exposed.interface,
495
+ provider: {
496
+ actor: text(exposed.provider, "actor"),
497
+ export: text(exposed.provider, "export")
498
+ }
499
+ }
500
+ };
501
+ }
485
502
  case "serve": {
486
503
  const kind = value.kind;
487
504
  if (kind !== "call" && kind !== "subscribe" && kind !== "open" && kind !== "http")
@@ -21113,6 +21130,24 @@ var ModuleHost = class {
21113
21130
  );
21114
21131
  this.#resubscribe(slot);
21115
21132
  }
21133
+ /**
21134
+ * A notice for a slot made at run time: bound (or usable again) with its exposure, or gone. Its
21135
+ * name is the Actor's, with no module prefix: every module of the Actor has it.
21136
+ */
21137
+ onExposed(slot, exposure) {
21138
+ if (!this.#channel) return;
21139
+ if (!exposure) {
21140
+ this.runtime.unexpose(slot);
21141
+ return;
21142
+ }
21143
+ const open2 = this.#channel;
21144
+ this.runtime.expose(slot, {
21145
+ described: exposure.interface,
21146
+ provider: exposure.provider,
21147
+ call: (method, value) => open2.call(slot, method, value),
21148
+ subscribe: (event, onEvent, onEnd) => open2.subscribe(slot, event, onEvent, () => onEnd())
21149
+ });
21150
+ }
21116
21151
  /** How this module serves the Hub's streams, by its local export names. */
21117
21152
  serve = {
21118
21153
  call: (serve, value) => this.runtime.call(serve.export, serve.method ?? "", value, serve.caller),
@@ -21153,9 +21188,12 @@ var ModuleHost = class {
21153
21188
  this.#channel = channel2;
21154
21189
  for (const [name, { handle, iface }] of this.#added) this.#offer(channel2, name, iface, handle);
21155
21190
  for (const name of channel2.bound)
21156
- if (name.startsWith(this.#prefix)) this.onSlot(name.slice(this.#prefix.length), true);
21191
+ if (name.startsWith(this.#prefix) && !channel2.exposed.has(name))
21192
+ this.onSlot(name.slice(this.#prefix.length), true);
21193
+ for (const [name, exposure] of channel2.exposed) this.onExposed(name, exposure);
21157
21194
  void channel2.closed.then(() => {
21158
21195
  for (const slot of [...this.#bindings.keys()]) this.onSlot(slot, false);
21196
+ for (const { slot } of this.runtime.ctx.exposed()) this.runtime.unexpose(slot);
21159
21197
  for (const ends of this.#subscribers.values()) for (const end of [...ends]) end();
21160
21198
  });
21161
21199
  }
@@ -21303,6 +21341,102 @@ function createRuntime(definition, options) {
21303
21341
  throw new Refused("unimplemented", `${name} hasn't been implemented yet.`);
21304
21342
  return state.impl;
21305
21343
  };
21344
+ const exposed = /* @__PURE__ */ new Map();
21345
+ const exposedWatchers = /* @__PURE__ */ new Set();
21346
+ const exposedChanged = () => {
21347
+ const failed = (error62) => options.log.error("An onExposed handler threw.", { error: String(error62) });
21348
+ for (const fn of [...exposedWatchers])
21349
+ try {
21350
+ const done = fn();
21351
+ if (done instanceof Promise) done.catch(failed);
21352
+ } catch (error62) {
21353
+ failed(error62);
21354
+ }
21355
+ };
21356
+ const listenExposed = (slot, state, event) => {
21357
+ const entry = state.events.get(event);
21358
+ if (state.gone || !entry || entry.stop || !entry.fns.size) return;
21359
+ let ended = false;
21360
+ let stop;
21361
+ stop = state.source.subscribe(
21362
+ event,
21363
+ (payload) => {
21364
+ for (const fn of [...entry.fns])
21365
+ try {
21366
+ fn(payload);
21367
+ } catch (error62) {
21368
+ options.log.error("An event handler threw.", { slot, event, error: String(error62) });
21369
+ }
21370
+ },
21371
+ // Ended by the provider going: the interest stays for when it is usable again.
21372
+ () => {
21373
+ ended = true;
21374
+ if (entry.stop === stop) entry.stop = void 0;
21375
+ }
21376
+ );
21377
+ if (!ended) entry.stop = stop;
21378
+ };
21379
+ const exposedHandle = (slot, state) => {
21380
+ const { described, provider } = state.source;
21381
+ return Object.freeze({
21382
+ slot,
21383
+ described,
21384
+ provider: Object.freeze({ actor: provider.actor, export: provider.export }),
21385
+ call: Object.freeze(
21386
+ Object.fromEntries(
21387
+ (described.kind === "rpc" ? Object.keys(described.methods) : []).map((method) => [
21388
+ method,
21389
+ async (input3) => {
21390
+ if (state.gone) throw new NotConnected(slot);
21391
+ return state.source.call(method, input3);
21392
+ }
21393
+ ])
21394
+ )
21395
+ ),
21396
+ on(event, fn) {
21397
+ if (described.kind !== "rpc" || !own2(described.events, event))
21398
+ throw new TypeError(`${slot} has no event ${event}.`);
21399
+ const entry = state.events.get(event) ?? { fns: /* @__PURE__ */ new Set() };
21400
+ state.events.set(event, entry);
21401
+ entry.fns.add(fn);
21402
+ listenExposed(slot, state, event);
21403
+ return () => {
21404
+ entry.fns.delete(fn);
21405
+ if (entry.fns.size) return;
21406
+ entry.stop?.();
21407
+ entry.stop = void 0;
21408
+ };
21409
+ }
21410
+ });
21411
+ };
21412
+ const unexpose = (slot) => {
21413
+ const state = exposed.get(slot);
21414
+ if (!state) return;
21415
+ exposed.delete(slot);
21416
+ state.gone = true;
21417
+ for (const entry of state.events.values()) {
21418
+ entry.stop?.();
21419
+ entry.stop = void 0;
21420
+ }
21421
+ exposedChanged();
21422
+ };
21423
+ const expose = (slot, source) => {
21424
+ const here = exposed.get(slot);
21425
+ if (here && here.source.described.hash === source.described.hash && here.source.provider.actor === source.provider.actor && here.source.provider.export === source.provider.export) {
21426
+ here.source = source;
21427
+ for (const [event, entry] of here.events) {
21428
+ entry.stop?.();
21429
+ entry.stop = void 0;
21430
+ listenExposed(slot, here, event);
21431
+ }
21432
+ return;
21433
+ }
21434
+ if (here) unexpose(slot);
21435
+ const state = { source, gone: false, events: /* @__PURE__ */ new Map() };
21436
+ state.handle = exposedHandle(slot, state);
21437
+ exposed.set(slot, state);
21438
+ exposedChanged();
21439
+ };
21306
21440
  const ctx = {
21307
21441
  slots: Object.fromEntries(
21308
21442
  Object.entries(definition.slots).map(([name, iface]) => [name, slotHandle(name, iface)])
@@ -21328,7 +21462,12 @@ function createRuntime(definition, options) {
21328
21462
  }
21329
21463
  ),
21330
21464
  self: options.self,
21331
- log: options.log
21465
+ log: options.log,
21466
+ exposed: () => Object.freeze([...exposed.values()].map((state) => state.handle)),
21467
+ onExposed(fn) {
21468
+ exposedWatchers.add(fn);
21469
+ return () => void exposedWatchers.delete(fn);
21470
+ }
21332
21471
  };
21333
21472
  const serving = (exportName) => {
21334
21473
  const state = target(exportName, "http");
@@ -21395,6 +21534,8 @@ function createRuntime(definition, options) {
21395
21534
  if (!state) throw new TypeError(`No slot ${slot}.`);
21396
21535
  if (state.binding) notify(slot, state.binds);
21397
21536
  },
21537
+ expose,
21538
+ unexpose,
21398
21539
  async call(exportName, method, input3, caller) {
21399
21540
  const state = target(exportName, "rpc");
21400
21541
  const spec = own2(state.iface.methods, method);
@@ -21478,6 +21619,8 @@ var drain = (reader) => void reader.rest().pipeTo(new WritableStream()).catch(()
21478
21619
  async function openChannel(options) {
21479
21620
  let session;
21480
21621
  const bound = /* @__PURE__ */ new Set();
21622
+ const exposed = /* @__PURE__ */ new Map();
21623
+ let ended = false;
21481
21624
  let ready;
21482
21625
  let headers = new Promise((resolve) => {
21483
21626
  ready = resolve;
@@ -21503,12 +21646,17 @@ async function openChannel(options) {
21503
21646
  }
21504
21647
  async function serveStream(header, stream, reader) {
21505
21648
  if (header.op === "slot") {
21649
+ if (ended) return;
21506
21650
  if (header.bound) bound.add(header.name);
21507
21651
  else bound.delete(header.name);
21508
- await stream.writable.close().catch(() => {
21652
+ const wasExposed = exposed.delete(header.name);
21653
+ const exposure = header.exposed;
21654
+ if (exposure) exposed.set(header.name, exposure);
21655
+ void stream.writable.close().catch(() => {
21509
21656
  });
21510
21657
  try {
21511
- options.onSlot?.(header.name, header.bound);
21658
+ if (exposure || wasExposed) options.onExposed?.(header.name, exposure);
21659
+ else options.onSlot?.(header.name, header.bound);
21512
21660
  } catch (error62) {
21513
21661
  options.log?.error("A slot notice's handler threw.", {
21514
21662
  slot: header.name,
@@ -21622,18 +21770,23 @@ async function openChannel(options) {
21622
21770
  });
21623
21771
  return next;
21624
21772
  };
21625
- const closed = session.closed.then(() => bound.clear());
21773
+ const closed = session.closed.then(() => {
21774
+ ended = true;
21775
+ bound.clear();
21776
+ exposed.clear();
21777
+ });
21626
21778
  return {
21627
21779
  actorId: options.actorId,
21628
21780
  bound,
21781
+ exposed,
21629
21782
  async call(slot, method, value) {
21630
21783
  return answered(await exchange({ op: "call", slot, method }, slot, input(value)), slot);
21631
21784
  },
21632
21785
  subscribe(slot, event, onEvent, onEnd) {
21633
- let ended = false;
21786
+ let ended2 = false;
21634
21787
  const end = (error62) => {
21635
- if (ended) return;
21636
- ended = true;
21788
+ if (ended2) return;
21789
+ ended2 = true;
21637
21790
  onEnd?.(error62);
21638
21791
  };
21639
21792
  let stream;
@@ -21662,7 +21815,7 @@ async function openChannel(options) {
21662
21815
  }
21663
21816
  })();
21664
21817
  return () => {
21665
- ended = true;
21818
+ ended2 = true;
21666
21819
  stream.reset();
21667
21820
  };
21668
21821
  },
@@ -21738,6 +21891,10 @@ async function runHost(options) {
21738
21891
  const found = route(name);
21739
21892
  found?.[0].onSlot(found[1], bound);
21740
21893
  },
21894
+ // A slot made at run time is the Actor's: every host module has it.
21895
+ onExposed(name, exposure) {
21896
+ for (const host2 of hosts.values()) host2.onExposed(name, exposure);
21897
+ },
21741
21898
  serve: {
21742
21899
  call: (serve, value) => {
21743
21900
  const [handlers, local] = routed(serve);
@@ -47,14 +47,32 @@ interface ChannelBase {
47
47
  * or, for a slot already bound, when its provider came back.
48
48
  */
49
49
  onSlot?(name: string, bound: boolean): void;
50
+ /**
51
+ * Each notice for a slot made at run time, in the same order: its exposure when bound (or
52
+ * usable again), `undefined` when it is gone. These don't reach `onSlot`.
53
+ */
54
+ onExposed?(name: string, exposure: ChannelExposure | undefined): void;
50
55
  /** Where a notice handler's own failure is reported. */
51
56
  log?: Log;
52
57
  }
58
+ /** A slot made at run time, as the channel keeps it: the export's interface, and whose it is. */
59
+ export interface ChannelExposure {
60
+ interface: DescribedInterface;
61
+ provider: {
62
+ actor: string;
63
+ export: string;
64
+ };
65
+ }
53
66
  /** A channel to the Hub as one Actor, at the wire's level: no local checks, no handles. */
54
67
  export interface Channel {
55
68
  readonly actorId: string;
56
69
  /** The Actor's slots bound now, from hello's snapshot and the Hub's notices; empty once closed. */
57
70
  readonly bound: ReadonlySet<string>;
71
+ /**
72
+ * The slots made for it at run time and bound now, from the notices: hello names them among
73
+ * `bound`, and a notice with each one's exposure follows.
74
+ */
75
+ readonly exposed: ReadonlyMap<string, ChannelExposure>;
58
76
  call(slot: string, method: string, value: unknown): Promise<unknown>;
59
77
  /** Events from a slot's provider until it ends (`onEnd`) or is stopped; returns how to stop. */
60
78
  subscribe(slot: string, event: string, onEvent: (payload: unknown) => void, onEnd?: (error?: Error) => void): () => void;
@@ -48,6 +48,9 @@ const drain = (reader) => void reader
48
48
  export async function openChannel(options) {
49
49
  let session;
50
50
  const bound = new Set();
51
+ const exposed = new Map();
52
+ /** Set as the session ends: a notice read before then but handled after is dropped. */
53
+ let ended = false;
51
54
  // Notices arrive as streams; their headers are read in arrival order, after hello's snapshot.
52
55
  let ready;
53
56
  let headers = new Promise((resolve) => {
@@ -74,13 +77,25 @@ export async function openChannel(options) {
74
77
  }
75
78
  async function serveStream(header, stream, reader) {
76
79
  if (header.op === "slot") {
80
+ if (ended)
81
+ return;
77
82
  if (header.bound)
78
83
  bound.add(header.name);
79
84
  else
80
85
  bound.delete(header.name);
81
- await stream.writable.close().catch(() => { });
86
+ // A slot made at run time is its exposure while bound, and gone when unbound.
87
+ const wasExposed = exposed.delete(header.name);
88
+ const exposure = header.exposed;
89
+ if (exposure)
90
+ exposed.set(header.name, exposure);
91
+ // Told before closing our side, which may wait behind other frames: a channel that ends
92
+ // meanwhile must not hear of a slot after its close has cleared them.
93
+ void stream.writable.close().catch(() => { });
82
94
  try {
83
- options.onSlot?.(header.name, header.bound);
95
+ if (exposure || wasExposed)
96
+ options.onExposed?.(header.name, exposure);
97
+ else
98
+ options.onSlot?.(header.name, header.bound);
84
99
  }
85
100
  catch (error) {
86
101
  options.log?.error("A slot notice's handler threw.", {
@@ -205,10 +220,15 @@ export async function openChannel(options) {
205
220
  changes = next.catch(() => { });
206
221
  return next;
207
222
  };
208
- const closed = session.closed.then(() => bound.clear());
223
+ const closed = session.closed.then(() => {
224
+ ended = true;
225
+ bound.clear();
226
+ exposed.clear();
227
+ });
209
228
  return {
210
229
  actorId: options.actorId,
211
230
  bound,
231
+ exposed,
212
232
  async call(slot, method, value) {
213
233
  return answered(await exchange({ op: "call", slot, method }, slot, input(value)), slot);
214
234
  },
@@ -325,6 +345,7 @@ export async function connect(options) {
325
345
  ? {}
326
346
  : { declares: { slots: describeAll(slots), exports: describeAll(exports) } }),
327
347
  onSlot: (slot, bound) => host.onSlot(slot, bound),
348
+ onExposed: (slot, exposure) => host.onExposed(slot, exposure),
328
349
  serve: host.serve,
329
350
  });
330
351
  host.attach(channel);
@@ -0,0 +1,8 @@
1
+ /**
2
+ * The base stylesheet every view's frame gets first, before the view's own: the document fills the
3
+ * frame on a transparent background, and plain HTML looks like the shell, drawn with the theme's
4
+ * tokens (`--fg`, `--surface`, `--accent`, … as the shell sends them at mount). Every rule is in
5
+ * `:where()`, so it has no specificity: any selector a view writes wins, and a view that wants its
6
+ * own look draws it.
7
+ */
8
+ export declare const FRAME_BASE = "\n:where(*, *::before, *::after) { box-sizing: border-box; }\n:where(html, body) { height: 100%; margin: 0; background: transparent; }\n:where(body) {\n overflow: auto; scrollbar-width: none;\n color: var(--fg); font: 14px/1.45 var(--font, ui-sans-serif, system-ui, sans-serif);\n -webkit-font-smoothing: antialiased;\n}\n:where(body)::-webkit-scrollbar { display: none; }\n:where(body > :only-child) { min-height: 100%; }\n:where(h1, h2, h3, h4) { margin: 0 0 8px; font-weight: 600; letter-spacing: -0.01em; }\n:where(h1) { font-size: 20px; }\n:where(h2) { font-size: 16px; }\n:where(h3, h4) { font-size: 14px; }\n:where(p) { margin: 0 0 8px; }\n:where(small) { color: var(--muted); font-size: 12.5px; }\n:where(a) { color: inherit; text-underline-offset: 2px; }\n:where(hr) { border: 0; border-top: 1px solid var(--line); margin: 10px 0; }\n:where(ul, ol) { margin: 0 0 10px; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 6px; }\n:where(li) { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-radius: 10px; background: var(--raised); }\n:where(button) {\n height: 34px; padding: 0 12px; border: 0; border-radius: 9px; cursor: pointer;\n background: var(--hover); color: var(--fg); font: inherit; font-weight: 500;\n}\n:where(button:hover) { background: var(--selected); }\n:where(button:disabled) { opacity: 0.5; cursor: default; }\n:where(button[type=\"submit\"], button.primary) { background: var(--accent); color: var(--accent-fg); font-weight: 600; }\n:where(input:not([type]), input[type=\"text\"], input[type=\"search\"], input[type=\"number\"], input[type=\"url\"], input[type=\"email\"], select) {\n height: 34px; padding: 0 10px; border: 0; border-radius: 9px; outline: 0;\n background: var(--raised); color: var(--fg); font: inherit;\n}\n:where(textarea) { padding: 8px 10px; border: 0; border-radius: 9px; outline: 0; resize: none; background: var(--raised); color: var(--fg); font: inherit; }\n:where(input:focus-visible, textarea:focus-visible, select:focus-visible, button:focus-visible) { box-shadow: 0 0 0 1.5px var(--ring); outline: 0; }\n:where(input[type=\"checkbox\"]) {\n appearance: none; width: 16px; height: 16px; margin: 0; flex: none; display: grid; place-items: center;\n border: 1.5px solid var(--faint); border-radius: 5px; cursor: pointer;\n}\n:where(input[type=\"checkbox\"]:checked) { background: var(--ok); border-color: var(--ok); }\n:where(input[type=\"checkbox\"]:checked)::after {\n content: \"\"; width: 4px; height: 8px; border: solid white; border-width: 0 2px 2px 0;\n transform: translateY(-1px) rotate(45deg);\n}\n:where(li:has(> input[type=\"checkbox\"]:checked) > span) { color: var(--faint); text-decoration: line-through; }\n:where(form) { display: flex; gap: 6px; }\n:where(form > input, form > textarea) { flex: 1; min-width: 0; }\n:where(table) { width: 100%; border-collapse: collapse; font-size: 13px; }\n:where(th) { padding: 0 8px 6px; text-align: left; color: var(--faint); font-weight: 500; font-size: 12px; }\n:where(td) { padding: 7px 8px; border-top: 1px solid var(--line); }\n:where(code, pre) { font: 12.5px/1.5 ui-monospace, SFMono-Regular, Menlo, monospace; }\n:where(code) { padding: 1px 5px; border-radius: 5px; background: var(--raised); }\n:where(pre) { margin: 0 0 10px; padding: 10px 12px; border-radius: 10px; background: var(--raised); overflow: auto; }\n:where(pre code) { padding: 0; background: none; }\n:where(progress) { appearance: none; width: 100%; height: 4px; border: 0; border-radius: 2px; background: var(--raised); }\n:where(progress)::-webkit-progress-bar { background: var(--raised); border-radius: 2px; }\n:where(progress)::-webkit-progress-value { background: var(--ok); border-radius: 2px; }\n:where(progress)::-moz-progress-bar { background: var(--ok); border-radius: 2px; }\n";