@ai-ecoverse/slicc-kernel 1.178.4 → 1.180.0

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.
@@ -7518,7 +7518,7 @@ var init_version = __esm({
7518
7518
  "src/version.ts"() {
7519
7519
  "use strict";
7520
7520
  init_captured_globals();
7521
- KERNEL_VERSION = true ? "1.178.4" : "0.0.0-dev";
7521
+ KERNEL_VERSION = true ? "1.180.0" : "0.0.0-dev";
7522
7522
  OS_RELEASE = "6.0.0-slicc";
7523
7523
  }
7524
7524
  });
@@ -7517,7 +7517,7 @@ var init_version = __esm({
7517
7517
  "src/version.ts"() {
7518
7518
  "use strict";
7519
7519
  init_captured_globals();
7520
- KERNEL_VERSION = true ? "1.178.4" : "0.0.0-dev";
7520
+ KERNEL_VERSION = true ? "1.180.0" : "0.0.0-dev";
7521
7521
  OS_RELEASE = "6.0.0-slicc";
7522
7522
  }
7523
7523
  });
package/dist/node.js CHANGED
@@ -2751,6 +2751,82 @@ var KERNEL_SIGINFO = Object.freeze({
2751
2751
  status: 0
2752
2752
  });
2753
2753
 
2754
+ // src/kernel/trace.ts
2755
+ var TRACE_LIMIT = 4096;
2756
+ var TRACE_LIMIT_MAX = 65536;
2757
+ function traceLimit(value2) {
2758
+ if (value2 === void 0) return TRACE_LIMIT;
2759
+ if (!Number.isInteger(value2) || value2 < 1 || value2 > TRACE_LIMIT_MAX) {
2760
+ throw Object.assign(new Error(`a trace limit is an integer from 1 to ${TRACE_LIMIT_MAX}`), {
2761
+ code: "EINVAL"
2762
+ });
2763
+ }
2764
+ return value2;
2765
+ }
2766
+ var TraceHub = class {
2767
+ subs = /* @__PURE__ */ new Set();
2768
+ seq = 0;
2769
+ get idle() {
2770
+ return this.subs.size === 0;
2771
+ }
2772
+ subscribe(tag, viewer, deliver, limit = TRACE_LIMIT) {
2773
+ const sub = {
2774
+ tag,
2775
+ viewer: copyCred(viewer),
2776
+ limit,
2777
+ queue: [],
2778
+ dropped: 0,
2779
+ waiting: false,
2780
+ scheduled: false,
2781
+ deliver
2782
+ };
2783
+ this.subs.add(sub);
2784
+ return {
2785
+ ack: () => {
2786
+ sub.waiting = false;
2787
+ this.schedule(sub);
2788
+ },
2789
+ close: () => {
2790
+ this.subs.delete(sub);
2791
+ sub.queue = [];
2792
+ }
2793
+ };
2794
+ }
2795
+ wants(tags, cred) {
2796
+ if (!tags?.length || this.subs.size === 0) return false;
2797
+ for (const sub of this.subs) if (this.matches(sub, tags, cred)) return true;
2798
+ return false;
2799
+ }
2800
+ publish(tags, cred, draft) {
2801
+ if (!tags?.length) return;
2802
+ let event;
2803
+ for (const sub of this.subs) {
2804
+ if (!this.matches(sub, tags, cred)) continue;
2805
+ event ??= { ...draft, seq: ++this.seq };
2806
+ if (sub.queue.length >= sub.limit) sub.dropped++;
2807
+ else sub.queue.push(event);
2808
+ this.schedule(sub);
2809
+ }
2810
+ }
2811
+ matches(sub, tags, cred) {
2812
+ return tags.includes(sub.tag) && maySee(sub.viewer, cred);
2813
+ }
2814
+ schedule(sub) {
2815
+ if (sub.scheduled || sub.waiting) return;
2816
+ if (sub.queue.length === 0 && sub.dropped === 0) return;
2817
+ sub.scheduled = true;
2818
+ queueMicrotask(() => {
2819
+ sub.scheduled = false;
2820
+ if (!this.subs.has(sub)) return;
2821
+ const batch = { events: sub.queue, dropped: sub.dropped };
2822
+ sub.queue = [];
2823
+ sub.dropped = 0;
2824
+ sub.waiting = true;
2825
+ sub.deliver(batch);
2826
+ });
2827
+ }
2828
+ };
2829
+
2754
2830
  // src/kernel/net/http1.ts
2755
2831
  var HttpError = class extends Error {
2756
2832
  status;
@@ -3711,7 +3787,7 @@ function satisfies(version, range2) {
3711
3787
  }
3712
3788
 
3713
3789
  // src/version.ts
3714
- var KERNEL_VERSION = true ? "1.178.4" : "0.0.0-dev";
3790
+ var KERNEL_VERSION = true ? "1.180.0" : "0.0.0-dev";
3715
3791
  var OS_RELEASE = "6.0.0-slicc";
3716
3792
  function procVersion() {
3717
3793
  return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
@@ -25973,6 +26049,9 @@ var JobTable = class {
25973
26049
  idOf(pid) {
25974
26050
  return this.members.get(pid)?.shownAs ?? pid;
25975
26051
  }
26052
+ execParentOf(pid) {
26053
+ return this.members.get(pid)?.execParent;
26054
+ }
25976
26055
  byId(id2) {
25977
26056
  for (const member of this.members.values()) if (member.shownAs === id2) return member;
25978
26057
  return this.member(id2);
@@ -32611,6 +32690,11 @@ function usersMode(mode = "off") {
32611
32690
  function tagOption(tag) {
32612
32691
  if (tag !== void 0 && typeof tag !== "string") throw new TypeError("a tag must be a string");
32613
32692
  }
32693
+ function cwdMissingOption(value2) {
32694
+ if (value2 === void 0 || value2 === "create") return "create";
32695
+ if (value2 === "error") return "error";
32696
+ throw new TypeError("cwdMissing must be 'create' or 'error'");
32697
+ }
32614
32698
  function withTag(tags, tag) {
32615
32699
  if (tag === void 0 || tags?.includes(tag)) return tags;
32616
32700
  return [...tags ?? [], tag];
@@ -34175,10 +34259,12 @@ var Launcher = class {
34175
34259
  });
34176
34260
  const fit = await (handle.ready ?? true);
34177
34261
  if (fit) {
34262
+ this.traceAdmitted(handle.pid, true);
34178
34263
  await fds.closeAll();
34179
34264
  return handle;
34180
34265
  }
34181
34266
  await handle.exited;
34267
+ this.traceAdmitted(handle.pid, false);
34182
34268
  await this.memories.refused().catch(async (err) => {
34183
34269
  await fds.closeAll();
34184
34270
  throw err;
@@ -34309,10 +34395,12 @@ var Launcher = class {
34309
34395
  if (req.group === "lead") this.jobs.lead(pid);
34310
34396
  if (req.group === "session") this.jobs.setsid(pid);
34311
34397
  this.described.set(pid, describe(req, terminal?.name ?? null));
34398
+ this.traceStarted(pid, req);
34312
34399
  handle.onState(
34313
34400
  (state) => state === "stopped" ? this.stopped.add(pid) : this.stopped.delete(pid)
34314
34401
  );
34315
- void handle.exited.then(() => {
34402
+ void handle.exited.then((status) => {
34403
+ this.traceEnded(pid, handle, status);
34316
34404
  this.cwds.release(this.cwdSlots.get(pid));
34317
34405
  this.cwdSlots.delete(pid);
34318
34406
  this.cwdPaths.delete(pid);
@@ -34427,6 +34515,71 @@ var Launcher = class {
34427
34515
  imageTimes = /* @__PURE__ */ new Map();
34428
34516
  childTimes = /* @__PURE__ */ new Map();
34429
34517
  stopped = /* @__PURE__ */ new Set();
34518
+ traces = new TraceHub();
34519
+ traceHeld = /* @__PURE__ */ new Map();
34520
+ replacedImages = /* @__PURE__ */ new Set();
34521
+ traceStarted(pid, req) {
34522
+ const replaces = req.exec ? req.ppid : void 0;
34523
+ if (req.quietOom) this.traceHeld.set(pid, { replaces, events: [] });
34524
+ else if (replaces !== void 0) this.replacedImages.add(replaces);
34525
+ this.traceEmit(pid, () => {
34526
+ const { pid: shown2, ppid } = this.identityOf(pid);
34527
+ const described2 = this.described.get(pid);
34528
+ const { argv, started, tty: _tty, exeId: _exeId, ...exe } = described2;
34529
+ return {
34530
+ type: req.fork ? "fork" : "exec",
34531
+ pid: shown2,
34532
+ ppid,
34533
+ pgid: this.jobs.pgidOf(pid),
34534
+ argv: [...argv],
34535
+ ...exe,
34536
+ uid: this.credOf(pid).euid,
34537
+ at: started,
34538
+ ...req.exec ? { replaced: true } : {}
34539
+ };
34540
+ });
34541
+ }
34542
+ traceEnded(pid, handle, status) {
34543
+ if (this.replacedImages.delete(pid)) return;
34544
+ this.traceEmit(pid, () => ({
34545
+ type: "exit",
34546
+ pid: this.jobs.idOf(pid),
34547
+ status,
34548
+ ...signalField(handle.termsig()),
34549
+ ...this.chainTimes(pid),
34550
+ at: Date.now()
34551
+ }));
34552
+ }
34553
+ traceEmit(pid, build) {
34554
+ if (this.traces.idle) return;
34555
+ const tags = this.tagsOf(pid);
34556
+ const cred = this.credOf(pid);
34557
+ if (!this.traces.wants(tags, cred)) return;
34558
+ const held = this.traceHeld.get(pid);
34559
+ if (held) held.events.push({ tags, cred: copyCred(cred), draft: build() });
34560
+ else this.traces.publish(tags, cred, build());
34561
+ }
34562
+ traceAdmitted(pid, fit) {
34563
+ const held = this.traceHeld.get(pid);
34564
+ if (!held) return;
34565
+ this.traceHeld.delete(pid);
34566
+ if (!fit) return;
34567
+ if (held.replaces !== void 0) this.replacedImages.add(held.replaces);
34568
+ for (const { tags, cred, draft } of held.events) this.traces.publish(tags, cred, draft);
34569
+ }
34570
+ chainTimes(pid) {
34571
+ let utime = 0;
34572
+ let stime = 0;
34573
+ let timed2 = false;
34574
+ for (let at = pid; at !== void 0; at = this.jobs.execParentOf(at)) {
34575
+ const t = this.timesAt(at);
34576
+ if (!t) continue;
34577
+ timed2 = true;
34578
+ utime += t.utime;
34579
+ stime += t.stime;
34580
+ }
34581
+ return timed2 ? { utime, stime } : {};
34582
+ }
34430
34583
  stateOf(pid) {
34431
34584
  if (!this.processes.has(pid)) return "Z";
34432
34585
  return this.stopped.has(pid) ? "T" : "S";
@@ -35489,7 +35642,7 @@ var Launcher = class {
35489
35642
  const kept = keepingOpen(fs, nodes, (path) => this.changes.publish(path));
35490
35643
  return this.swaps.wrap(unlinked.wrap(kept));
35491
35644
  }
35492
- async starting(argv, dir, account, tags, base) {
35645
+ async starting(argv, dir, account, tags, base, missing6 = "create") {
35493
35646
  const tag = tags?.[0];
35494
35647
  await this.swaps.settled();
35495
35648
  this.resetCatalogs();
@@ -35498,8 +35651,13 @@ var Launcher = class {
35498
35651
  const cwd = await physicalPathAsync(this.base, start2.startsWith("/") ? start2 : `/${start2}`);
35499
35652
  await this.enterable(this.execGuard(credOf(account), 0, tag), cwd);
35500
35653
  const file = await this.execFile(argv[0] ?? "", cwd, this.execGuard(credOf(account), 0, tag));
35501
- if (!await this.base.exists(cwd))
35654
+ if (!await this.base.exists(cwd)) {
35655
+ if (missing6 === "error")
35656
+ throw Object.assign(new Error(`cannot change to ${cwd}: No such file or directory`), {
35657
+ code: "ENOENT"
35658
+ });
35502
35659
  await this.stackFor(tags, base).fs.mkdir(cwd, { recursive: true });
35660
+ }
35503
35661
  const plan = async () => {
35504
35662
  const found = await this.plan(file, argv, cwd, scope);
35505
35663
  await this.mayExec(credOf(account), { file, cwd, pid: 0, tag }, found);
@@ -35510,6 +35668,7 @@ var Launcher = class {
35510
35668
  }
35511
35669
  async openTerminal(argv, options) {
35512
35670
  const tagged = tagsOption(options);
35671
+ const missing6 = cwdMissingOption(options.cwdMissing);
35513
35672
  const { tags } = tagged;
35514
35673
  const { account, tty: ttyGroup } = await this.terminalAccount(options.user);
35515
35674
  const { cwd, file, planned } = await this.starting(
@@ -35517,7 +35676,8 @@ var Launcher = class {
35517
35676
  options.cwd,
35518
35677
  account,
35519
35678
  tags,
35520
- tagged.tagBase
35679
+ tagged.tagBase,
35680
+ missing6
35521
35681
  );
35522
35682
  if (!planned) throw new Error(`${file}: command not found`);
35523
35683
  let leader = 0;
@@ -35569,6 +35729,7 @@ var Launcher = class {
35569
35729
  }
35570
35730
  async run(argv, options = {}) {
35571
35731
  const tagged = tagsOption(options);
35732
+ const missing6 = cwdMissingOption(options.cwdMissing);
35572
35733
  const { tags } = tagged;
35573
35734
  const account = await this.account(options.user);
35574
35735
  const { cwd, file, planned } = await this.starting(
@@ -35576,7 +35737,8 @@ var Launcher = class {
35576
35737
  options.cwd,
35577
35738
  account,
35578
35739
  tags,
35579
- tagged.tagBase
35740
+ tagged.tagBase,
35741
+ missing6
35580
35742
  );
35581
35743
  const env = this.environment(cwd, options.env, account, options.login);
35582
35744
  const out = [];
@@ -36098,7 +36260,7 @@ function serveTransport(peer, transport, {
36098
36260
  }
36099
36261
 
36100
36262
  // src/client/protocol.ts
36101
- var PROTOCOL = [1, 13];
36263
+ var PROTOCOL = [1, 15];
36102
36264
  var FS_METHODS = [
36103
36265
  "readFile",
36104
36266
  "writeFile",
@@ -36265,9 +36427,21 @@ async function runAs(l, self, requested) {
36265
36427
  function clientCred(self) {
36266
36428
  return self ? credOf(self) : copyCred(ROOT);
36267
36429
  }
36430
+ var MAX_SPAWN_TAGS = 8;
36431
+ function spawnTags(value2) {
36432
+ if (!Array.isArray(value2)) {
36433
+ tagOption(value2);
36434
+ return value2 === void 0 ? [] : [value2];
36435
+ }
36436
+ if (value2.length > MAX_SPAWN_TAGS) {
36437
+ throw new TypeError(`a spawn adds at most ${MAX_SPAWN_TAGS} tags`);
36438
+ }
36439
+ for (const each of value2) tagOption(each ?? 0);
36440
+ return value2;
36441
+ }
36268
36442
  async function runTagged(l, self, options, tag, session = -1) {
36269
- tagOption(options.tag);
36270
- const tags = withTag(withTag(void 0, tag), options.tag);
36443
+ let tags = withTag(void 0, tag);
36444
+ for (const added of spawnTags(options.tag)) tags = withTag(tags, added);
36271
36445
  return {
36272
36446
  user: await runAs(l, self, options.user),
36273
36447
  tag,
@@ -36398,6 +36572,34 @@ async function watchOp(l, req, watches, send2, g) {
36398
36572
  watches.set(req.id, unwatch);
36399
36573
  return { result: req.id };
36400
36574
  }
36575
+ function traceRegistry(send2) {
36576
+ const traces = /* @__PURE__ */ new Map();
36577
+ return {
36578
+ answer(l, self, req) {
36579
+ if (req.op === "untrace") {
36580
+ traces.get(req.trace)?.close();
36581
+ return { result: traces.delete(req.trace) };
36582
+ }
36583
+ if (typeof req.tag !== "string" || req.tag === "") {
36584
+ throw fsError("EINVAL", "trace: a tag is a non-empty string");
36585
+ }
36586
+ const limit = traceLimit(req.limit);
36587
+ const id2 = req.id;
36588
+ const deliver = ({ events, dropped: dropped2 }) => send2({ trace: id2, events, ...dropped2 > 0 ? { dropped: dropped2 } : {} });
36589
+ traces.set(id2, l.traces.subscribe(req.tag, credOf(self), deliver, limit));
36590
+ return { result: id2 };
36591
+ },
36592
+ ack(data) {
36593
+ if (typeof data.traceAck !== "number") return false;
36594
+ traces.get(data.traceAck)?.ack();
36595
+ return true;
36596
+ },
36597
+ close() {
36598
+ for (const trace of traces.values()) trace.close();
36599
+ traces.clear();
36600
+ }
36601
+ };
36602
+ }
36401
36603
  var TRAITS_WATCH = -1;
36402
36604
  function traitsWatch(launcher, transport, send2) {
36403
36605
  return launcher.onTraits(() => send2({ traits: transport.traits }));
@@ -36424,6 +36626,21 @@ function requestBinding(send2, port) {
36424
36626
  close: () => unbind?.()
36425
36627
  };
36426
36628
  }
36629
+ function answered(pending, req, reply, detach) {
36630
+ pending.then(
36631
+ ({ result, signal, transfer }) => {
36632
+ reply(req.id, { result, ...signal ? { signal } : {} }, transfer);
36633
+ if (req.op === "detach") detach(req.kill === true);
36634
+ },
36635
+ (err) => {
36636
+ const code = err?.code;
36637
+ reply(req.id, {
36638
+ error: err instanceof Error ? err.message : String(err),
36639
+ ...typeof code === "string" ? { code } : {}
36640
+ });
36641
+ }
36642
+ );
36643
+ }
36427
36644
  function serveClient(port, host) {
36428
36645
  let state = "new";
36429
36646
  let self;
@@ -36439,6 +36656,7 @@ function serveClient(port, host) {
36439
36656
  };
36440
36657
  const reply = (id2, body, transfer) => send2({ id: id2, ...body }, transfer);
36441
36658
  const hosts = hostRegistries(send2, ended.promise, port);
36659
+ const traces = traceRegistry(send2);
36442
36660
  function detach(kill = false, bye = "the slicc-kernel detached this client") {
36443
36661
  if (state === "closed") return;
36444
36662
  send2({ bye });
@@ -36446,6 +36664,7 @@ function serveClient(port, host) {
36446
36664
  net?.close();
36447
36665
  for (const unwatch of watches.values()) unwatch();
36448
36666
  watches.clear();
36667
+ traces.close();
36449
36668
  hosts.close();
36450
36669
  for (const session of terminals.values()) session.close();
36451
36670
  terminals.clear();
@@ -36553,6 +36772,9 @@ function serveClient(port, host) {
36553
36772
  case "serve-facade":
36554
36773
  case "unserve-facade":
36555
36774
  return { result: hosts.answer(l, req) };
36775
+ case "trace":
36776
+ case "untrace":
36777
+ return traces.answer(l, self, req);
36556
36778
  case "detach":
36557
36779
  return { result: true };
36558
36780
  default:
@@ -36576,20 +36798,9 @@ function serveClient(port, host) {
36576
36798
  net?.answer(data);
36577
36799
  return;
36578
36800
  }
36801
+ if (traces.ack(data)) return;
36579
36802
  const req = data;
36580
- handle(req).then(
36581
- ({ result, signal, transfer }) => {
36582
- reply(req.id, { result, ...signal ? { signal } : {} }, transfer);
36583
- if (req.op === "detach") detach(req.kill === true);
36584
- },
36585
- (err) => {
36586
- const code = err?.code;
36587
- reply(req.id, {
36588
- error: err instanceof Error ? err.message : String(err),
36589
- ...typeof code === "string" ? { code } : {}
36590
- });
36591
- }
36592
- );
36803
+ answered(handle(req), req, reply, detach);
36593
36804
  });
36594
36805
  port.addEventListener("close", () => detach());
36595
36806
  port.start?.();
@@ -37518,6 +37729,7 @@ var Channel = class {
37518
37729
  failure;
37519
37730
  pending = /* @__PURE__ */ new Map();
37520
37731
  watching = /* @__PURE__ */ new Map();
37732
+ tracing = /* @__PURE__ */ new Map();
37521
37733
  cdpHooks = /* @__PURE__ */ new Map();
37522
37734
  cdpOpen = /* @__PURE__ */ new Set();
37523
37735
  facadeHooks = /* @__PURE__ */ new Map();
@@ -37585,6 +37797,10 @@ var Channel = class {
37585
37797
  this.watching.get(data.watch)?.(data.change);
37586
37798
  return;
37587
37799
  }
37800
+ if (data.trace !== void 0 && data.id === void 0) {
37801
+ this.traced(data.trace, data.events ?? [], data.dropped ?? 0);
37802
+ return;
37803
+ }
37588
37804
  if (data.bye !== void 0) {
37589
37805
  this.end(new KernelGoneError(data.bye));
37590
37806
  return;
@@ -37613,6 +37829,23 @@ var Channel = class {
37613
37829
  if (reply.error !== void 0) call.reject(new KernelCallError(reply.error, reply.code));
37614
37830
  else call.resolve(reply.result);
37615
37831
  }
37832
+ traced(trace, events, dropped2) {
37833
+ const listener = this.tracing.get(trace);
37834
+ if (!listener) return;
37835
+ const ack = () => {
37836
+ if (this.tracing.has(trace)) this.post({ traceAck: trace });
37837
+ };
37838
+ let consumed;
37839
+ try {
37840
+ consumed = listener({ events, dropped: dropped2 });
37841
+ } finally {
37842
+ if (typeof consumed?.then === "function") {
37843
+ void Promise.resolve(consumed).then(ack, ack);
37844
+ } else {
37845
+ ack();
37846
+ }
37847
+ }
37848
+ }
37616
37849
  openCdp({ cdpOpen: { registration, ...request }, port }) {
37617
37850
  const hook = registration === void 0 ? void 0 : this.cdpHooks.get(registration);
37618
37851
  if (!hook || this.failure) {
@@ -37675,6 +37908,29 @@ async function serveCdpOn(channel, hook, options) {
37675
37908
  }
37676
37909
  };
37677
37910
  }
37911
+ async function traceOn(channel, tag, onEvents, options) {
37912
+ if (typeof onEvents !== "function") throw new TypeError("trace: onEvents must be a function");
37913
+ await since(channel, 15, "trace", async () => {
37914
+ });
37915
+ const { id: id2, done: done4 } = channel.request({
37916
+ op: "trace",
37917
+ tag,
37918
+ ...options.limit !== void 0 ? { limit: options.limit } : {}
37919
+ });
37920
+ channel.tracing.set(id2, onEvents);
37921
+ try {
37922
+ await done4;
37923
+ } catch (error) {
37924
+ channel.tracing.delete(id2);
37925
+ throw error;
37926
+ }
37927
+ return {
37928
+ close: () => {
37929
+ if (!channel.tracing.delete(id2)) return;
37930
+ void channel.call({ op: "untrace", trace: id2 }).catch(() => void 0);
37931
+ }
37932
+ };
37933
+ }
37678
37934
  async function dialOn(channel, { port, host }) {
37679
37935
  const req = { op: "dial", port, ...host ? { host } : {} };
37680
37936
  return dialStream(await since(channel, 4, "dial", () => channel.call(req)));
@@ -37688,6 +37944,10 @@ async function spawnOn(channel, argv, opts) {
37688
37944
  });
37689
37945
  if (opts.tag !== void 0) await since(channel, 12, "a tag per spawn", async () => {
37690
37946
  });
37947
+ if (Array.isArray(opts.tag)) await since(channel, 15, "several tags per spawn", async () => {
37948
+ });
37949
+ if (opts.cwdMissing === "error") await since(channel, 14, "cwdMissing: 'error'", async () => {
37950
+ });
37691
37951
  const started = Promise.withResolvers();
37692
37952
  let endedBy;
37693
37953
  const options = { ...rest2, ...stdin !== void 0 ? { stdin: bytesOf4(stdin) } : {} };
@@ -37747,6 +38007,12 @@ async function terminalOn(channel, argv, opts) {
37747
38007
  });
37748
38008
  if (opts.tag !== void 0) await since(channel, 12, "a tag per terminal", async () => {
37749
38009
  });
38010
+ if (Array.isArray(opts.tag)) {
38011
+ await since(channel, 15, "several tags per terminal", async () => {
38012
+ });
38013
+ }
38014
+ if (opts.cwdMissing === "error") await since(channel, 14, "cwdMissing: 'error'", async () => {
38015
+ });
37750
38016
  let listener = onData ?? null;
37751
38017
  const backlog = [];
37752
38018
  const started = Promise.withResolvers();
@@ -37904,6 +38170,7 @@ async function attachKernel(port, options = {}) {
37904
38170
  channel.traitsListeners.add(listener);
37905
38171
  return () => channel.traitsListeners.delete(listener);
37906
38172
  },
38173
+ trace: (tag, onEvents, options2 = {}) => traceOn(channel, tag, onEvents, options2),
37907
38174
  async close(o = {}) {
37908
38175
  if (channel.failure) return;
37909
38176
  await channel.call({ op: "detach", ...o.kill ? { kill: true } : {} }).catch(() => void 0);