zooid 0.7.1 → 0.7.3

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/bin.js CHANGED
@@ -5,6 +5,7 @@ import {
5
5
  SpawnRegistry,
6
6
  buildAcpRegistry,
7
7
  createMatrixTransport,
8
+ ensureDefaultChannel,
8
9
  ensureWorkforceSpace,
9
10
  findConfigFile,
10
11
  findHttpTransport,
@@ -14,7 +15,7 @@ import {
14
15
  renderRegistration,
15
16
  startDaemonSocketServer,
16
17
  startWorkforcePublisher
17
- } from "./chunk-SUPTPSN3.js";
18
+ } from "./chunk-3IKBBKGI.js";
18
19
 
19
20
  // src/bin.ts
20
21
  import { resolve as resolve5 } from "path";
@@ -557,12 +558,13 @@ async function startDaemon(opts = {}) {
557
558
  hsToken: matrix.transport.hs_token,
558
559
  adminUserId: opts.adminUserId
559
560
  });
560
- const requestedPort = matrix.transport.port ?? 8080;
561
+ const requestedPort = matrix.transport.port ?? 9e3;
561
562
  server = serve({ fetch: transport.app.fetch, port: requestedPort, hostname: "0.0.0.0" });
562
563
  port = await listenAsync(server);
563
564
  const serverName = matrix.transport.user_namespace.split(":").slice(1).join(":").replace(/\\?\)?$/, "") || new URL(matrix.transport.homeserver).hostname;
564
565
  const asUserId = `@${matrix.transport.sender_localpart}:${serverName}`;
565
566
  const spaceLocalpart = matrix.transport.space ?? "dev";
567
+ const adminUserIds = opts.adminUserId ? [opts.adminUserId] : [];
566
568
  let spaceRoomId;
567
569
  try {
568
570
  spaceRoomId = await ensureWorkforceSpace({
@@ -570,14 +572,27 @@ async function startDaemon(opts = {}) {
570
572
  asUserId,
571
573
  serverName,
572
574
  spaceLocalpart,
573
- preset: "public_chat"
575
+ preset: "public_chat",
576
+ admins: adminUserIds
574
577
  });
575
578
  console.log(`[matrix] ensured workforce space #${spaceLocalpart}:${serverName} \u2192 ${spaceRoomId}`);
576
579
  } catch (err) {
577
580
  console.warn("[matrix] workforce space provisioning failed:", err);
578
581
  }
579
- await transport.bootstrap({ spaceRoomId, asUserId });
582
+ await transport.bootstrap({ spaceRoomId, asUserId, adminUserIds });
580
583
  if (spaceRoomId) {
584
+ try {
585
+ const generalRoomId = await ensureDefaultChannel({
586
+ client,
587
+ asUserId,
588
+ serverName,
589
+ spaceId: spaceRoomId,
590
+ admins: adminUserIds
591
+ });
592
+ console.log(`[matrix] ensured default channel #general:${serverName} \u2192 ${generalRoomId}`);
593
+ } catch (err) {
594
+ console.warn("[matrix] default channel provisioning failed:", err);
595
+ }
581
596
  try {
582
597
  const publisher = await startWorkforcePublisher({
583
598
  client,
@@ -633,6 +648,9 @@ async function startDaemon(opts = {}) {
633
648
 
634
649
  // src/services/tuwunel.ts
635
650
  import { spawn } from "child_process";
651
+ import { execFile as execFile2 } from "child_process";
652
+ import { promisify as promisify2 } from "util";
653
+ var execFileAsync = promisify2(execFile2);
636
654
  var DEFAULT_IMAGE = "ghcr.io/matrix-construct/tuwunel:latest";
637
655
  function buildRunArgs(opts) {
638
656
  const image = opts.image ?? DEFAULT_IMAGE;
@@ -680,6 +698,16 @@ var TuwunelService = class {
680
698
  }
681
699
  async waitHealthy(opts) {
682
700
  const deadline = Date.now() + opts.timeoutMs;
701
+ while (Date.now() < deadline) {
702
+ const state = await this.inspectState().catch(() => null);
703
+ if (state?.status === "running") break;
704
+ if (state?.status === "exited") {
705
+ throw new Error(
706
+ `Tuwunel container exited before serving HTTP (exit=${state.exitCode}${state.error ? `, error=${state.error}` : ""}). Check the engine logs (\`${this.opts.engine} logs ${this.opts.name}\`).`
707
+ );
708
+ }
709
+ await new Promise((resolve6) => setTimeout(resolve6, 500));
710
+ }
683
711
  while (Date.now() < deadline) {
684
712
  try {
685
713
  const r = await fetch(`${opts.url}/_matrix/client/versions`);
@@ -688,10 +716,35 @@ var TuwunelService = class {
688
716
  }
689
717
  await new Promise((resolve6) => setTimeout(resolve6, 500));
690
718
  }
719
+ const finalState = await this.inspectState().catch(() => null);
720
+ const detail = finalState ? ` (container status=${finalState.status}${finalState.exitCode !== void 0 ? `, exit=${finalState.exitCode}` : ""})` : "";
691
721
  throw new Error(
692
- `Tuwunel did not become healthy at ${opts.url} in ${opts.timeoutMs}ms`
722
+ `Tuwunel did not become healthy at ${opts.url} in ${opts.timeoutMs}ms${detail}`
693
723
  );
694
724
  }
725
+ /**
726
+ * Read the engine's view of the container. Returns null if the container
727
+ * isn't known to the engine (e.g. before spawn completed or after `--rm`).
728
+ */
729
+ async inspectState() {
730
+ try {
731
+ const { stdout } = await execFileAsync(this.opts.engine, [
732
+ "inspect",
733
+ this.opts.name,
734
+ "--format",
735
+ "{{.State.Status}}|{{.State.ExitCode}}|{{.State.Error}}"
736
+ ]);
737
+ const [status, exitCodeRaw, error] = stdout.trim().split("|");
738
+ const exitCode = exitCodeRaw && exitCodeRaw !== "<no value>" ? Number(exitCodeRaw) : void 0;
739
+ return {
740
+ status: status ?? "unknown",
741
+ ...Number.isFinite(exitCode) ? { exitCode } : {},
742
+ ...error ? { error } : {}
743
+ };
744
+ } catch {
745
+ return null;
746
+ }
747
+ }
695
748
  };
696
749
  function execEngine(engine, args) {
697
750
  return new Promise((resolve6, reject) => {
@@ -1132,7 +1185,7 @@ async function runDev(flags) {
1132
1185
  title: "Wait for Tuwunel /_matrix/client/versions",
1133
1186
  task: async () => {
1134
1187
  if (!ctx.svc) throw new Error("service not started");
1135
- await ctx.svc.waitHealthy({ url: homeserver, timeoutMs: 6e4 });
1188
+ await ctx.svc.waitHealthy({ url: homeserver, timeoutMs: 18e4 });
1136
1189
  }
1137
1190
  },
1138
1191
  {