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 +59 -6
- package/dist/bin.js.map +1 -1
- package/dist/{chunk-SUPTPSN3.js → chunk-3IKBBKGI.js} +178 -24
- package/dist/chunk-3IKBBKGI.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/web/assets/{index-Cz5fEZBc.js → index-BqOX0Pv4.js} +85 -75
- package/dist/web/assets/index-C-ZtBp7U.css +1 -0
- package/dist/web/assets/{index-CqfWXqvO.js → index-Dc8BJYf_.js} +1 -1
- package/dist/web/assets/{reaction-picker-emoji-cME0vOsX.js → reaction-picker-emoji-xD2HkULN.js} +1 -1
- package/dist/web/index.html +2 -2
- package/package.json +8 -8
- package/src/build-registry.context.test.ts +1 -1
- package/src/build-registry.zod043.test.ts +1 -1
- package/src/build-registry.zod044.test.ts +2 -2
- package/src/commands/dev.ts +5 -1
- package/src/daemon/start-daemon.ts +17 -2
- package/src/services/tuwunel.ts +68 -1
- package/dist/chunk-SUPTPSN3.js.map +0 -1
- package/dist/web/assets/index-C2MAIew3.css +0 -1
|
@@ -24181,6 +24181,39 @@ function parseTransport(name, raw, processEnv) {
|
|
|
24181
24181
|
}
|
|
24182
24182
|
return { type: "http", port };
|
|
24183
24183
|
}
|
|
24184
|
+
function parseRoomBinding(path, raw, serverName) {
|
|
24185
|
+
function normalizeAlias(alias) {
|
|
24186
|
+
if (alias.length === 0) {
|
|
24187
|
+
throw new Error(`${path}: must be a non-empty alias`);
|
|
24188
|
+
}
|
|
24189
|
+
if (!MATRIX_ROOM_IDENT_RE.test(alias)) {
|
|
24190
|
+
throw new Error(
|
|
24191
|
+
`${path}: must start with '#' or '!' (got ${JSON.stringify(alias)})`
|
|
24192
|
+
);
|
|
24193
|
+
}
|
|
24194
|
+
return alias.includes(":") ? alias : `${alias}:${serverName}`;
|
|
24195
|
+
}
|
|
24196
|
+
if (typeof raw === "string") {
|
|
24197
|
+
return { alias: normalizeAlias(raw) };
|
|
24198
|
+
}
|
|
24199
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
24200
|
+
throw new Error(`${path}: must be a string or { alias, power_level } object`);
|
|
24201
|
+
}
|
|
24202
|
+
const r = raw;
|
|
24203
|
+
if (typeof r.alias !== "string" || r.alias.length === 0) {
|
|
24204
|
+
throw new Error(`${path}.alias: must be a non-empty string`);
|
|
24205
|
+
}
|
|
24206
|
+
const out = { alias: normalizeAlias(r.alias) };
|
|
24207
|
+
if (r.power_level !== void 0) {
|
|
24208
|
+
if (typeof r.power_level !== "number" || !Number.isInteger(r.power_level)) {
|
|
24209
|
+
throw new Error(
|
|
24210
|
+
`${path}.power_level: must be an integer (got ${JSON.stringify(r.power_level)})`
|
|
24211
|
+
);
|
|
24212
|
+
}
|
|
24213
|
+
out.powerLevel = r.power_level;
|
|
24214
|
+
}
|
|
24215
|
+
return out;
|
|
24216
|
+
}
|
|
24184
24217
|
function parseTransportBinding(name, entry, transports) {
|
|
24185
24218
|
const present = TRANSPORT_KINDS.filter(
|
|
24186
24219
|
(k) => entry[k] !== void 0 && entry[k] !== null
|
|
@@ -24250,16 +24283,8 @@ function parseTransportBinding(name, entry, transports) {
|
|
|
24250
24283
|
throw new Error(`agents.${name}.matrix.rooms is required and must be a non-empty array`);
|
|
24251
24284
|
}
|
|
24252
24285
|
const rooms = [];
|
|
24253
|
-
for (
|
|
24254
|
-
|
|
24255
|
-
throw new Error(`agents.${name}.matrix.rooms[] must be a non-empty string`);
|
|
24256
|
-
}
|
|
24257
|
-
if (!MATRIX_ROOM_IDENT_RE.test(r)) {
|
|
24258
|
-
throw new Error(
|
|
24259
|
-
`agents.${name}.matrix.rooms[] must start with '#' or '!' (got ${JSON.stringify(r)})`
|
|
24260
|
-
);
|
|
24261
|
-
}
|
|
24262
|
-
rooms.push(r.includes(":") ? r : `${r}:${serverName}`);
|
|
24286
|
+
for (let i = 0; i < block.rooms.length; i++) {
|
|
24287
|
+
rooms.push(parseRoomBinding(`agents.${name}.matrix.rooms[${i}]`, block.rooms[i], serverName));
|
|
24263
24288
|
}
|
|
24264
24289
|
let displayName;
|
|
24265
24290
|
if (block.display_name !== void 0) {
|
|
@@ -24785,6 +24810,22 @@ var MatrixClient = class {
|
|
|
24785
24810
|
preset: opts.preset ?? "public_chat"
|
|
24786
24811
|
};
|
|
24787
24812
|
if (opts.name !== void 0) body.name = opts.name;
|
|
24813
|
+
if (opts.roomVersion !== void 0) body.room_version = opts.roomVersion;
|
|
24814
|
+
if (opts.restrictedToSpaceId !== void 0) {
|
|
24815
|
+
body.initial_state = [
|
|
24816
|
+
{
|
|
24817
|
+
type: "m.room.join_rules",
|
|
24818
|
+
state_key: "",
|
|
24819
|
+
content: {
|
|
24820
|
+
join_rule: "restricted",
|
|
24821
|
+
allow: [{ type: "m.room_membership", room_id: opts.restrictedToSpaceId }]
|
|
24822
|
+
}
|
|
24823
|
+
}
|
|
24824
|
+
];
|
|
24825
|
+
}
|
|
24826
|
+
if (opts.userPowerLevels && Object.keys(opts.userPowerLevels).length > 0) {
|
|
24827
|
+
body.power_level_content_override = { users: opts.userPowerLevels };
|
|
24828
|
+
}
|
|
24788
24829
|
const r = await this.fetch(
|
|
24789
24830
|
`${this.homeserver}/_matrix/client/v3/createRoom?user_id=${encodeURIComponent(opts.senderUserId)}`,
|
|
24790
24831
|
{
|
|
@@ -24830,6 +24871,31 @@ var MatrixClient = class {
|
|
|
24830
24871
|
if (!r.ok) throw new Error(`sendStateEvent ${opts.eventType} failed: ${r.status}`);
|
|
24831
24872
|
return await r.json();
|
|
24832
24873
|
}
|
|
24874
|
+
/**
|
|
24875
|
+
* Invite a user to a room. Sent as the inviter (`asUserId`) — that user
|
|
24876
|
+
* needs invite power in the room. Tolerates the "already in room /
|
|
24877
|
+
* already invited" responses idempotently so bootstrap can run on a
|
|
24878
|
+
* fresh AND a populated homeserver without branching.
|
|
24879
|
+
*/
|
|
24880
|
+
async invite(opts) {
|
|
24881
|
+
const url2 = `${this.homeserver}/_matrix/client/v3/rooms/${encodeURIComponent(opts.roomId)}/invite?user_id=${encodeURIComponent(opts.asUserId)}`;
|
|
24882
|
+
const r = await this.fetch(url2, {
|
|
24883
|
+
method: "POST",
|
|
24884
|
+
headers: {
|
|
24885
|
+
Authorization: `Bearer ${this.asToken}`,
|
|
24886
|
+
"content-type": "application/json"
|
|
24887
|
+
},
|
|
24888
|
+
body: JSON.stringify({ user_id: opts.targetUserId })
|
|
24889
|
+
});
|
|
24890
|
+
if (r.ok) return;
|
|
24891
|
+
if (r.status === 403) {
|
|
24892
|
+
const body = await r.text();
|
|
24893
|
+
const idempotent = /already (in the room|invited|a member|joined)/i.test(body) || /user that is joined/i.test(body);
|
|
24894
|
+
if (idempotent) return;
|
|
24895
|
+
throw new Error(`invite(${opts.targetUserId}) failed: 403 ${body}`);
|
|
24896
|
+
}
|
|
24897
|
+
throw new Error(`invite(${opts.targetUserId}) failed: ${r.status}`);
|
|
24898
|
+
}
|
|
24833
24899
|
async joinRoom(roomIdOrAlias, asUserId) {
|
|
24834
24900
|
const url2 = `${this.homeserver}/_matrix/client/v3/join/${encodeURIComponent(roomIdOrAlias)}?user_id=${encodeURIComponent(asUserId)}`;
|
|
24835
24901
|
const r = await this.fetch(url2, {
|
|
@@ -25158,7 +25224,7 @@ function route(event, agents, threadStates) {
|
|
|
25158
25224
|
const threadState = threadRoot ? threadStates?.get(threadRoot) : void 0;
|
|
25159
25225
|
for (const a of agents) {
|
|
25160
25226
|
if (event.sender === a.userId) continue;
|
|
25161
|
-
if (!a.rooms.
|
|
25227
|
+
if (!a.rooms.some((r) => r.alias === event.room_id)) continue;
|
|
25162
25228
|
if (a.trigger === "any") {
|
|
25163
25229
|
matches.push(a);
|
|
25164
25230
|
continue;
|
|
@@ -25185,15 +25251,50 @@ async function ensureWorkforceSpace(opts) {
|
|
|
25185
25251
|
const existing = await opts.client.resolveAlias(alias);
|
|
25186
25252
|
if (existing) return existing;
|
|
25187
25253
|
const display = opts.spaceLocalpart.charAt(0).toUpperCase() + opts.spaceLocalpart.slice(1);
|
|
25188
|
-
|
|
25254
|
+
const body = {
|
|
25255
|
+
room_alias_name: opts.spaceLocalpart,
|
|
25256
|
+
name: display,
|
|
25257
|
+
preset: opts.preset,
|
|
25258
|
+
creation_content: { type: "m.space" },
|
|
25259
|
+
// A workspace is joined by invitation, not self-service. Pin the space's
|
|
25260
|
+
// join rule to invite regardless of preset so it can't be walked into
|
|
25261
|
+
// (which would otherwise satisfy every restricted child room's allow).
|
|
25262
|
+
initial_state: [{ type: "m.room.join_rules", state_key: "", content: { join_rule: "invite" } }]
|
|
25263
|
+
};
|
|
25264
|
+
if (opts.admins && opts.admins.length > 0) {
|
|
25265
|
+
body.invite = opts.admins;
|
|
25266
|
+
const users = { [opts.asUserId]: 100 };
|
|
25267
|
+
for (const a of opts.admins) users[a] = 100;
|
|
25268
|
+
body.power_level_content_override = { users };
|
|
25269
|
+
}
|
|
25270
|
+
return opts.client.createRoomRaw({ asUserId: opts.asUserId, body });
|
|
25271
|
+
}
|
|
25272
|
+
async function ensureDefaultChannel(opts) {
|
|
25273
|
+
const localpart2 = opts.channelLocalpart ?? "general";
|
|
25274
|
+
const alias = `#${localpart2}:${opts.serverName}`;
|
|
25275
|
+
const existing = await opts.client.resolveAlias(alias);
|
|
25276
|
+
if (existing) return existing;
|
|
25277
|
+
let userPowerLevels;
|
|
25278
|
+
if (opts.admins && opts.admins.length > 0) {
|
|
25279
|
+
userPowerLevels = { [opts.asUserId]: 100 };
|
|
25280
|
+
for (const a of opts.admins) userPowerLevels[a] = 100;
|
|
25281
|
+
}
|
|
25282
|
+
const roomId = await opts.client.createRoom({
|
|
25283
|
+
roomAliasName: localpart2,
|
|
25284
|
+
invite: [],
|
|
25285
|
+
senderUserId: opts.asUserId,
|
|
25286
|
+
name: localpart2.charAt(0).toUpperCase() + localpart2.slice(1),
|
|
25287
|
+
restrictedToSpaceId: opts.spaceId,
|
|
25288
|
+
...userPowerLevels ? { userPowerLevels } : {}
|
|
25289
|
+
});
|
|
25290
|
+
await opts.client.sendStateEvent({
|
|
25291
|
+
roomId: opts.spaceId,
|
|
25189
25292
|
asUserId: opts.asUserId,
|
|
25190
|
-
|
|
25191
|
-
|
|
25192
|
-
|
|
25193
|
-
preset: opts.preset,
|
|
25194
|
-
creation_content: { type: "m.space" }
|
|
25195
|
-
}
|
|
25293
|
+
eventType: "m.space.child",
|
|
25294
|
+
stateKey: roomId,
|
|
25295
|
+
content: { via: [opts.serverName] }
|
|
25196
25296
|
});
|
|
25297
|
+
return roomId;
|
|
25197
25298
|
}
|
|
25198
25299
|
function serverNameFromMxid(mxid) {
|
|
25199
25300
|
const colon = mxid.indexOf(":");
|
|
@@ -25224,8 +25325,23 @@ var BotPool = class {
|
|
|
25224
25325
|
} catch (err) {
|
|
25225
25326
|
console.warn(`[matrix] setDisplayName(${a.userId}) failed: ${err.message}`);
|
|
25226
25327
|
}
|
|
25328
|
+
if (opts.spaceRoomId && opts.asUserId) {
|
|
25329
|
+
try {
|
|
25330
|
+
await this.client.invite({
|
|
25331
|
+
roomId: opts.spaceRoomId,
|
|
25332
|
+
asUserId: opts.asUserId,
|
|
25333
|
+
targetUserId: a.userId
|
|
25334
|
+
});
|
|
25335
|
+
await this.client.joinRoom(opts.spaceRoomId, a.userId);
|
|
25336
|
+
} catch (err) {
|
|
25337
|
+
console.warn(
|
|
25338
|
+
`[matrix] space membership for ${a.userId} failed: ${err.message}`
|
|
25339
|
+
);
|
|
25340
|
+
}
|
|
25341
|
+
}
|
|
25227
25342
|
for (let i = 0; i < a.rooms.length; i++) {
|
|
25228
|
-
const
|
|
25343
|
+
const binding = a.rooms[i];
|
|
25344
|
+
const room = binding.alias;
|
|
25229
25345
|
try {
|
|
25230
25346
|
let resolved = room;
|
|
25231
25347
|
if (room.startsWith("#")) {
|
|
@@ -25240,17 +25356,25 @@ var BotPool = class {
|
|
|
25240
25356
|
const colon = room.indexOf(":");
|
|
25241
25357
|
const aliasLocalpart = colon > 1 ? room.slice(1, colon) : room.slice(1);
|
|
25242
25358
|
const sender = opts.adminUserId ?? a.userId;
|
|
25359
|
+
const userPowerLevels = buildUserPowerLevels(
|
|
25360
|
+
opts.asUserId,
|
|
25361
|
+
opts.adminUserIds,
|
|
25362
|
+
this.agents,
|
|
25363
|
+
room
|
|
25364
|
+
);
|
|
25243
25365
|
resolved = await this.client.createRoom({
|
|
25244
25366
|
roomAliasName: aliasLocalpart,
|
|
25245
25367
|
invite: opts.adminUserId ? [opts.adminUserId] : [],
|
|
25246
25368
|
senderUserId: sender,
|
|
25247
|
-
name: aliasLocalpart
|
|
25369
|
+
name: aliasLocalpart,
|
|
25370
|
+
...opts.spaceRoomId ? { restrictedToSpaceId: opts.spaceRoomId } : {},
|
|
25371
|
+
...userPowerLevels ? { userPowerLevels } : {}
|
|
25248
25372
|
});
|
|
25249
25373
|
}
|
|
25250
25374
|
aliasToId.set(room, resolved);
|
|
25251
25375
|
}
|
|
25252
25376
|
}
|
|
25253
|
-
|
|
25377
|
+
binding.alias = resolved;
|
|
25254
25378
|
await this.client.joinRoom(resolved, a.userId);
|
|
25255
25379
|
if (opts.spaceRoomId && opts.asUserId && !attachedToSpace.has(resolved)) {
|
|
25256
25380
|
attachedToSpace.add(resolved);
|
|
@@ -25289,6 +25413,18 @@ function localpart(userId) {
|
|
|
25289
25413
|
if (!m) throw new Error(`bad user id: ${userId}`);
|
|
25290
25414
|
return m[1];
|
|
25291
25415
|
}
|
|
25416
|
+
function buildUserPowerLevels(asUserId, admins, agents, roomAlias) {
|
|
25417
|
+
const users = {};
|
|
25418
|
+
if (asUserId) users[asUserId] = 100;
|
|
25419
|
+
if (admins) for (const a of admins) users[a] = 100;
|
|
25420
|
+
for (const a of agents) {
|
|
25421
|
+
for (const r of a.rooms) {
|
|
25422
|
+
if (r.alias !== roomAlias) continue;
|
|
25423
|
+
if (r.powerLevel !== void 0) users[a.userId] = r.powerLevel;
|
|
25424
|
+
}
|
|
25425
|
+
}
|
|
25426
|
+
return Object.keys(users).length > 0 ? users : void 0;
|
|
25427
|
+
}
|
|
25292
25428
|
|
|
25293
25429
|
// ../transport-matrix/src/transport.ts
|
|
25294
25430
|
import { Hono } from "hono";
|
|
@@ -25439,12 +25575,17 @@ function toMatrixHtml(markdown) {
|
|
|
25439
25575
|
// ../transport-matrix/src/transport.ts
|
|
25440
25576
|
var STARTUP_GRACE_MS = 5e3;
|
|
25441
25577
|
var SEEN_EVENT_CAP = 5e3;
|
|
25578
|
+
var DRAIN_QUIET_MS = 300;
|
|
25579
|
+
var DRAIN_MAX_MS = 3e4;
|
|
25580
|
+
var delay = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
25442
25581
|
function inboundThreadRoot2(evt) {
|
|
25443
25582
|
const r = evt.content?.["m.relates_to"];
|
|
25444
25583
|
return r?.rel_type === "m.thread" && r.event_id ? r.event_id : void 0;
|
|
25445
25584
|
}
|
|
25446
25585
|
function createMatrixTransport(opts) {
|
|
25447
25586
|
const { agents, approvals, client, bindings, hsToken, adminUserId } = opts;
|
|
25587
|
+
const drainQuietMs = opts.drainQuietMs ?? DRAIN_QUIET_MS;
|
|
25588
|
+
const drainMaxMs = opts.drainMaxMs ?? DRAIN_MAX_MS;
|
|
25448
25589
|
const pool = new BotPool(client, bindings);
|
|
25449
25590
|
const sessions = /* @__PURE__ */ new Map();
|
|
25450
25591
|
const buffers = /* @__PURE__ */ new Map();
|
|
@@ -25726,6 +25867,14 @@ function createMatrixTransport(opts) {
|
|
|
25726
25867
|
channelId: evt.room_id,
|
|
25727
25868
|
content: [{ type: "text", text: promptText }]
|
|
25728
25869
|
});
|
|
25870
|
+
const drainStart = Date.now();
|
|
25871
|
+
let drained = buffers.get(sessionId) ?? "";
|
|
25872
|
+
while (drainQuietMs > 0 && Date.now() - drainStart < drainMaxMs) {
|
|
25873
|
+
await delay(drainQuietMs);
|
|
25874
|
+
const next = buffers.get(sessionId) ?? "";
|
|
25875
|
+
if (next === drained && next.length > 0) break;
|
|
25876
|
+
drained = next;
|
|
25877
|
+
}
|
|
25729
25878
|
const text = buffers.get(sessionId) ?? "";
|
|
25730
25879
|
if (text.length > 0) {
|
|
25731
25880
|
const html = toMatrixHtml(text);
|
|
@@ -25777,7 +25926,7 @@ function createMatrixTransport(opts) {
|
|
|
25777
25926
|
}
|
|
25778
25927
|
async function rebuildThreadState(client, roomId, rootEventId, bindings) {
|
|
25779
25928
|
const state = { participants: [], rootMentions: [] };
|
|
25780
|
-
const asUser = (bindings.find((b) => b.rooms.
|
|
25929
|
+
const asUser = (bindings.find((b) => b.rooms.some((r) => r.alias === roomId)) ?? bindings[0])?.userId;
|
|
25781
25930
|
if (!asUser) return state;
|
|
25782
25931
|
const root = await client.fetchEvent(roomId, rootEventId, asUser);
|
|
25783
25932
|
if (root) {
|
|
@@ -25832,7 +25981,11 @@ function truncate(s, n) {
|
|
|
25832
25981
|
function buildWorkforceRoster(agents) {
|
|
25833
25982
|
return {
|
|
25834
25983
|
version: 1,
|
|
25835
|
-
agents: agents.map((a) => ({
|
|
25984
|
+
agents: agents.map((a) => ({
|
|
25985
|
+
user_id: a.userId,
|
|
25986
|
+
name: a.name,
|
|
25987
|
+
rooms: a.rooms.map((r) => r.alias)
|
|
25988
|
+
}))
|
|
25836
25989
|
};
|
|
25837
25990
|
}
|
|
25838
25991
|
async function publishWorkforce(opts) {
|
|
@@ -31425,10 +31578,11 @@ export {
|
|
|
31425
31578
|
MatrixClient,
|
|
31426
31579
|
renderRegistration,
|
|
31427
31580
|
ensureWorkforceSpace,
|
|
31581
|
+
ensureDefaultChannel,
|
|
31428
31582
|
createMatrixTransport,
|
|
31429
31583
|
startWorkforcePublisher,
|
|
31430
31584
|
SpawnRegistry,
|
|
31431
31585
|
startDaemonSocketServer,
|
|
31432
31586
|
buildAcpRegistry
|
|
31433
31587
|
};
|
|
31434
|
-
//# sourceMappingURL=chunk-
|
|
31588
|
+
//# sourceMappingURL=chunk-3IKBBKGI.js.map
|