usebeeline 0.0.3 → 0.0.5

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 (2) hide show
  1. package/dist/usebeeline.mjs +545 -494
  2. package/package.json +1 -1
@@ -25286,6 +25286,258 @@ function parseScheduledTurnReceipt(event) {
25286
25286
  // packages/buzz-client/dist/agent.js
25287
25287
  init_dist();
25288
25288
 
25289
+ // packages/api-contract/dist/phone-types.js
25290
+ var ROOM_VIEW_MESSAGE_LIMIT = 30;
25291
+ var ROOM_VIEW_BRIEFING_LIMIT = 10;
25292
+ var ROOM_VIEW_WORKSPACE_LIMIT = 50;
25293
+ var ROOM_VIEW_CHAT_LIMIT = 200;
25294
+ var ROOM_VIEW_MEMBER_LIMIT = 200;
25295
+ var ROOM_VIEW_AGENT_LIMIT = 200;
25296
+ var ROOM_VIEW_REQUEST_TIMEOUT_MS = 8e3;
25297
+
25298
+ // packages/api-contract/dist/phone-guards.js
25299
+ var HEX = /^[0-9a-f]{64}$/;
25300
+ var UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
25301
+ function record(value) {
25302
+ return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
25303
+ }
25304
+ function integer3(value) {
25305
+ return Number.isSafeInteger(value) && value >= 0;
25306
+ }
25307
+ function optionalString(value) {
25308
+ return value === void 0 || typeof value === "string";
25309
+ }
25310
+ function httpUrl(value) {
25311
+ if (typeof value !== "string")
25312
+ return false;
25313
+ try {
25314
+ const protocol = new URL(value).protocol;
25315
+ return protocol === "http:" || protocol === "https:";
25316
+ } catch {
25317
+ return false;
25318
+ }
25319
+ }
25320
+ function attachment(value) {
25321
+ const item = record(value);
25322
+ return Boolean(item && httpUrl(item.url) && typeof item.name === "string" && item.name.length > 0 && typeof item.mimeType === "string" && /^[^/\s]+\/[^/\s]+$/.test(item.mimeType) && integer3(item.size) && (item.previewUrl === void 0 || httpUrl(item.previewUrl)) && (item.thumbnailUrl === void 0 || httpUrl(item.thumbnailUrl)) && (item.sha256 === void 0 || typeof item.sha256 === "string" && HEX.test(item.sha256)) && (item.width === void 0 || integer3(item.width) && item.width > 0) && (item.height === void 0 || integer3(item.height) && item.height > 0));
25323
+ }
25324
+ function activity(value) {
25325
+ const item = record(value);
25326
+ const rollup = item?.rollup === void 0 ? void 0 : record(item.rollup);
25327
+ const plan = item?.plan === void 0 ? void 0 : record(item.plan);
25328
+ return Boolean(item && (item.kind === "thinking" || item.kind === "tool" || item.kind === "output" || item.kind === "summary") && typeof item.title === "string" && optionalString(item.operation) && optionalString(item.status) && (item.thoughtMs === void 0 || integer3(item.thoughtMs)) && (rollup === void 0 || rollup !== null && Object.values(rollup).every(integer3)) && (item.observed === void 0 || Array.isArray(item.observed) && item.observed.every((candidate) => {
25329
+ const observed = record(candidate);
25330
+ return Boolean(observed && typeof observed.verb === "string" && optionalString(observed.target) && optionalString(observed.result));
25331
+ })) && (item.files === void 0 || Array.isArray(item.files) && item.files.every((candidate) => {
25332
+ const file = record(candidate);
25333
+ return Boolean(file && typeof file.path === "string" && optionalString(file.status));
25334
+ })) && (plan === void 0 || plan !== null && optionalString(plan.objective) && Array.isArray(plan.items) && plan.items.every((candidate) => {
25335
+ const planItem = record(candidate);
25336
+ return Boolean(planItem && typeof planItem.step === "string" && (planItem.status === "pending" || planItem.status === "in_progress" || planItem.status === "completed"));
25337
+ })));
25338
+ }
25339
+ function identity(value) {
25340
+ const item = record(value);
25341
+ return Boolean(item && typeof item.pubkey === "string" && HEX.test(item.pubkey) && (item.kind === "human" || item.kind === "agent") && typeof item.name === "string" && optionalString(item.handle) && optionalString(item.avatar));
25342
+ }
25343
+ function header(value) {
25344
+ const item = record(value);
25345
+ return Boolean(item && typeof item.id === "string" && UUID.test(item.id) && typeof item.workspaceId === "string" && UUID.test(item.workspaceId) && (item.parentId === void 0 || typeof item.parentId === "string" && UUID.test(item.parentId)) && typeof item.name === "string" && optionalString(item.about) && optionalString(item.avatar) && (item.visibility === void 0 || item.visibility === "public" || item.visibility === "invite-only") && typeof item.archived === "boolean" && integer3(item.createdAt) && integer3(item.updatedAt));
25346
+ }
25347
+ function member(value) {
25348
+ const item = record(value);
25349
+ const presence = item?.presence === void 0 ? void 0 : record(item.presence);
25350
+ return Boolean(item && identity(item.identity) && (item.role === "owner" || item.role === "admin" || item.role === "member") && (presence === void 0 || presence && (presence.status === "online" || presence.status === "offline") && integer3(presence.observedAt) && (presence.roomId === void 0 || typeof presence.roomId === "string" && UUID.test(presence.roomId))));
25351
+ }
25352
+ function messageCorner(value) {
25353
+ const item = record(value);
25354
+ return Boolean(item && typeof item.id === "string" && UUID.test(item.id) && (item.status === "open" || item.status === "working" || item.status === "waiting" || item.status === "idle" || item.status === "concluded" || item.status === "closed"));
25355
+ }
25356
+ function messagePermission(value) {
25357
+ const item = record(value);
25358
+ return Boolean(item && typeof item.permissionId === "string" && item.permissionId.length > 0 && typeof item.requestId === "string" && item.requestId.length > 0 && identity(item.agent) && item.agent.kind === "agent" && identity(item.requester) && item.requester.kind === "human" && (item.decider === void 0 || identity(item.decider) && item.decider.kind === "human") && typeof item.tool === "string" && item.tool.length > 0 && optionalString(item.repository) && (item.purpose === void 0 || item.purpose === "squire-spending") && (item.status === "pending" || item.status === "allowed" || item.status === "denied" || item.status === "expired" || item.status === "failed") && (item.cornerId === void 0 || typeof item.cornerId === "string" && UUID.test(item.cornerId)));
25359
+ }
25360
+ function targetBranch(value) {
25361
+ const item = record(value);
25362
+ return Boolean(item && typeof item.proposalId === "string" && item.proposalId.length > 0 && typeof item.from === "string" && typeof item.to === "string" && item.to.length > 0 && optionalString(item.repository) && (item.agent === void 0 || identity(item.agent)) && (item.requester === void 0 || identity(item.requester)));
25363
+ }
25364
+ function githubUrl(value) {
25365
+ if (typeof value !== "string")
25366
+ return false;
25367
+ try {
25368
+ const url = new URL(value);
25369
+ return url.protocol === "https:" && url.hostname === "github.com";
25370
+ } catch {
25371
+ return false;
25372
+ }
25373
+ }
25374
+ function githubEvent(value) {
25375
+ const item = record(value);
25376
+ if (!item || item.type !== "pull-request" && item.type !== "issue" || typeof item.actor !== "string" || typeof item.title !== "string" || !githubUrl(item.url)) {
25377
+ return false;
25378
+ }
25379
+ return item.type === "pull-request" && (item.action === "opened" || item.action === "closed" || item.action === "merged") || item.type === "issue" && (item.action === "opened" || item.action === "closed");
25380
+ }
25381
+ function daemonFact(value) {
25382
+ const item = record(value);
25383
+ const pullRequest = item?.pullRequest === void 0 ? void 0 : record(item.pullRequest);
25384
+ if (!item || item.type !== "corner-complete" && item.type !== "checks-failing" && item.type !== "worktree-cleaned" && item.type !== "corner-open" || typeof item.cornerId !== "string" || !UUID.test(item.cornerId) || typeof item.objective !== "string" || !item.objective.trim() || item.outcome !== void 0 && item.outcome !== "landed" && item.outcome !== "abandoned" || !optionalString(item.name) || item.type === "corner-open" && (typeof item.name !== "string" || !item.name.trim()) || pullRequest !== void 0 && (!pullRequest || pullRequest.number !== void 0 && (!Number.isSafeInteger(pullRequest.number) || Number(pullRequest.number) <= 0) || !optionalString(pullRequest.title) || !githubUrl(pullRequest.url) || !optionalString(pullRequest.targetBranch)) || item.subgoals !== void 0 && (!Array.isArray(item.subgoals) || !item.subgoals.every((subgoal) => {
25385
+ const entry = record(subgoal);
25386
+ return Boolean(entry && typeof entry.step === "string" && entry.step.trim() && (entry.status === "pending" || entry.status === "in_progress" || entry.status === "completed"));
25387
+ }))) {
25388
+ return false;
25389
+ }
25390
+ return item.type !== "corner-complete" || item.outcome === "landed" || item.outcome === "abandoned";
25391
+ }
25392
+ function isRoomViewMessage(value) {
25393
+ const item = record(value);
25394
+ const reference = item?.reference === void 0 ? void 0 : record(item.reference);
25395
+ const reply = item?.reply === void 0 ? void 0 : record(item.reply);
25396
+ return Boolean(item && typeof item.id === "string" && HEX.test(item.id) && typeof item.text === "string" && integer3(item.createdAt) && identity(item.author) && (item.presentation === "message" || item.presentation === "system" || item.presentation === "activity" || item.presentation === "card") && (reference === void 0 || reference && typeof reference.channelId === "string" && UUID.test(reference.channelId) && reference.eventId === item.id && typeof reference.rootId === "string" && HEX.test(reference.rootId)) && (reply === void 0 || reply && typeof reply.channelId === "string" && UUID.test(reply.channelId) && typeof reply.eventId === "string" && HEX.test(reply.eventId) && typeof reply.rootId === "string" && HEX.test(reply.rootId)) && optionalString(item.liveTurnId) && optionalString(item.requestId) && (item.attachments === void 0 || Array.isArray(item.attachments) && item.attachments.every(attachment)) && (item.mentionPubkeys === void 0 || Array.isArray(item.mentionPubkeys) && item.mentionPubkeys.every((pubkey2) => typeof pubkey2 === "string" && HEX.test(pubkey2))) && (item.activity === void 0 || Array.isArray(item.activity) && item.activity.every(activity)) && (item.durableFact === void 0 || item.durableFact === "failure" || item.durableFact === "merge" || item.durableFact === "action") && (item.corner === void 0 || messageCorner(item.corner)) && (item.permission === void 0 || messagePermission(item.permission)) && (item.targetBranch === void 0 || targetBranch(item.targetBranch)) && (item.githubEvent === void 0 || githubEvent(item.githubEvent)) && (item.daemonFact === void 0 || daemonFact(item.daemonFact)));
25397
+ }
25398
+ function scopedMessage(value, roomId) {
25399
+ return typeof roomId === "string" && isRoomViewMessage(value) && (value.reference === void 0 || value.reference.channelId === roomId) && (value.reply === void 0 || value.reply.channelId === roomId);
25400
+ }
25401
+ function watchFilters(value) {
25402
+ return Array.isArray(value) && value.length <= 32 && value.every((candidate) => {
25403
+ const filter = record(candidate);
25404
+ if (!filter)
25405
+ return false;
25406
+ return Object.entries(filter).every(([key, entry]) => {
25407
+ if (key === "kinds")
25408
+ return Array.isArray(entry) && entry.every(integer3);
25409
+ if (key === "authors" || key === "#h" || key === "#d" || key === "#p" || key === "#t") {
25410
+ return Array.isArray(entry) && entry.every((item) => typeof item === "string");
25411
+ }
25412
+ return false;
25413
+ });
25414
+ });
25415
+ }
25416
+ function viewer(value) {
25417
+ const item = record(value);
25418
+ const permissions = record(item?.permissions);
25419
+ return Boolean(item && identity(item.identity) && (item.role === "owner" || item.role === "admin" || item.role === "member") && permissions && typeof permissions.send === "boolean" && typeof permissions.manage === "boolean");
25420
+ }
25421
+ function directMessage(value) {
25422
+ const item = record(value);
25423
+ return Boolean(item && Array.isArray(item.participants) && item.participants.length === 2 && item.participants.every((pubkey2) => typeof pubkey2 === "string" && HEX.test(pubkey2)) && item.participants[0] < item.participants[1]);
25424
+ }
25425
+ function directMessageForViewer(value, viewerValue) {
25426
+ const viewerItem = record(viewerValue);
25427
+ const viewerIdentity = record(viewerItem?.identity);
25428
+ return directMessage(value) && typeof viewerIdentity?.pubkey === "string" && value.participants.includes(viewerIdentity.pubkey);
25429
+ }
25430
+ function agentTurn(value) {
25431
+ const item = record(value);
25432
+ return Boolean(item && typeof item.requestId === "string" && HEX.test(item.requestId) && typeof item.agentPubkey === "string" && HEX.test(item.agentPubkey) && (item.status === "working" || item.status === "complete" || item.status === "failed") && integer3(item.createdAt) && optionalString(item.generationId));
25433
+ }
25434
+ function workspace(value) {
25435
+ const item = record(value);
25436
+ return Boolean(item && typeof item.id === "string" && UUID.test(item.id) && typeof item.name === "string" && optionalString(item.avatar) && (item.visibility === "public" || item.visibility === "invite-only") && (item.role === "owner" || item.role === "admin" || item.role === "member") && integer3(item.updatedAt));
25437
+ }
25438
+ function latest(value) {
25439
+ const item = record(value);
25440
+ return Boolean(item && typeof item.id === "string" && HEX.test(item.id) && typeof item.text === "string" && integer3(item.createdAt) && identity(item.author));
25441
+ }
25442
+ function chat(value) {
25443
+ const item = record(value);
25444
+ return Boolean(item && header(item.room) && (item.latestMessage === void 0 || latest(item.latestMessage)) && integer3(item.memberCount) && integer3(item.cornerCount) && typeof item.unread === "boolean" && optionalString(item.repositoryName) && (item.agentState === void 0 || item.agentState === "needs-you" || item.agentState === "working"));
25445
+ }
25446
+ function corner(value) {
25447
+ const item = record(value);
25448
+ return Boolean(item && header(item.corner) && cornerLifecycle(item.lifecycle) && (item.status === "open" || item.status === "working" || item.status === "waiting" || item.status === "idle" || item.status === "concluded" || item.status === "closed") && (item.statusAt === void 0 || integer3(item.statusAt)) && (item.reason === void 0 || item.reason === "review" || item.reason === "question" || item.reason === "failure") && (item.agent === void 0 || identity(item.agent)) && (item.latestMessage === void 0 || latest(item.latestMessage)));
25449
+ }
25450
+ function cornerLifecycle(value) {
25451
+ const item = record(value);
25452
+ const pr = item?.pr === void 0 ? void 0 : record(item.pr);
25453
+ return Boolean(item && (item.lifecycle === "working" || item.lifecycle === "in-review" || item.lifecycle === "unknown" || item.lifecycle === "done") && (item.checks === "passing" || item.checks === "failing" || item.checks === "pending" || item.checks === "unknown") && optionalString(item.branch) && (item.outcome === void 0 || item.outcome === "landed" || item.outcome === "abandoned") && optionalString(item.reason) && (pr === void 0 || pr && integer3(pr.number) && pr.number > 0 && githubUrl(pr.url) && typeof pr.title === "string" && pr.title.length > 0 && typeof pr.targetBranch === "string" && pr.targetBranch.length > 0 && typeof pr.headSha === "string" && /^[0-9a-f]{40}$/i.test(pr.headSha) && optionalString(pr.mergedAt) && optionalString(pr.mergedBy)));
25454
+ }
25455
+ function repository(value) {
25456
+ const item = record(value);
25457
+ return Boolean(item && typeof item.key === "string" && item.key.length > 0 && typeof item.name === "string" && item.name.length > 0 && typeof item.remote === "string" && item.remote.length > 0 && typeof item.targetBranch === "string" && item.targetBranch.length > 0 && integer3(item.updatedAt) && (item.githubInstallationId === void 0 || integer3(item.githubInstallationId)) && typeof item.githubEventsEnabled === "boolean");
25458
+ }
25459
+ function repositoryResolution(value) {
25460
+ return value === "repository" || value === "none" || value === "unverified";
25461
+ }
25462
+ function modelSelection(value) {
25463
+ const item = record(value);
25464
+ return Boolean(item && optionalString(item.model) && optionalString(item.effort));
25465
+ }
25466
+ function modelOption(value) {
25467
+ const item = record(value);
25468
+ return Boolean(item && typeof item.id === "string" && item.id.length > 0 && typeof item.category === "string" && item.category.length > 0 && optionalString(item.currentValue) && Array.isArray(item.options) && item.options.every((candidate) => {
25469
+ const option = record(candidate);
25470
+ return Boolean(option && typeof option.id === "string" && option.id.length > 0 && optionalString(option.name));
25471
+ }));
25472
+ }
25473
+ function isRoomView(value) {
25474
+ const item = record(value);
25475
+ return Boolean(item && header(item.room) && Array.isArray(item.messages) && item.messages.length <= ROOM_VIEW_MESSAGE_LIMIT && item.messages.every((candidate) => scopedMessage(candidate, record(item.room)?.id)) && Array.isArray(item.latestAgentTurns) && item.latestAgentTurns.length <= ROOM_VIEW_AGENT_LIMIT && item.latestAgentTurns.every(agentTurn) && Array.isArray(item.members) && item.members.length <= ROOM_VIEW_MEMBER_LIMIT && item.members.every(member) && viewer(item.viewer) && (item.directMessage === void 0 || directMessageForViewer(item.directMessage, item.viewer)) && (item.parent === void 0 || header(item.parent)) && (item.briefing === void 0 || Array.isArray(item.briefing) && item.briefing.length <= ROOM_VIEW_BRIEFING_LIMIT && item.briefing.every(isRoomViewMessage)) && (item.cornerPlan === void 0 || activity({ kind: "output", title: "Plan", plan: item.cornerPlan })) && Array.isArray(item.corners) && item.corners.every(corner) && (item.repository === void 0 || repository(item.repository)) && repositoryResolution(item.repositoryResolution) && (item.cornerLifecycle === void 0 || cornerLifecycle(item.cornerLifecycle)) && watchFilters(item.watchFilters));
25476
+ }
25477
+ function isRoomHistoryView(value) {
25478
+ const item = record(value);
25479
+ const before = item?.nextBefore === void 0 ? void 0 : record(item.nextBefore);
25480
+ return Boolean(item && typeof item.roomId === "string" && UUID.test(item.roomId) && Array.isArray(item.messages) && item.messages.length <= ROOM_VIEW_MESSAGE_LIMIT && item.messages.every((candidate) => scopedMessage(candidate, item.roomId)) && (before === void 0 || before && integer3(before.createdAt) && typeof before.id === "string" && HEX.test(before.id)));
25481
+ }
25482
+ function isWorkspaceListView(value) {
25483
+ const item = record(value);
25484
+ return Boolean(item && Array.isArray(item.workspaces) && item.workspaces.length <= ROOM_VIEW_WORKSPACE_LIMIT && item.workspaces.every(workspace) && typeof item.truncated === "boolean" && identity(item.viewer) && watchFilters(item.watchFilters));
25485
+ }
25486
+ function isWorkspaceView(value) {
25487
+ const item = record(value);
25488
+ const managerSettings = item?.managerSettings === void 0 ? void 0 : record(item.managerSettings);
25489
+ return Boolean(item && workspace(item.workspace) && integer3(record(item.workspace)?.createdAt) && optionalString(record(item.workspace)?.about) && (managerSettings === void 0 || managerSettings && (managerSettings.visibility === "public" || managerSettings.visibility === "invite-only")) && Array.isArray(item.members) && item.members.length <= ROOM_VIEW_MEMBER_LIMIT && item.members.every(member) && Array.isArray(item.agents) && item.agents.length <= ROOM_VIEW_AGENT_LIMIT && item.agents.every(member) && typeof item.membersTruncated === "boolean" && typeof item.agentsTruncated === "boolean" && viewer(item.viewer) && watchFilters(item.watchFilters));
25490
+ }
25491
+ function isChatListView(value) {
25492
+ const item = record(value);
25493
+ return Boolean(item && workspace(item.workspace) && Array.isArray(item.chats) && item.chats.length <= ROOM_VIEW_CHAT_LIMIT && item.chats.every(chat) && typeof item.truncated === "boolean" && identity(item.viewer) && watchFilters(item.watchFilters));
25494
+ }
25495
+ function isCornerListView(value) {
25496
+ const item = record(value);
25497
+ return Boolean(item && header(item.room) && Array.isArray(item.corners) && item.corners.every(corner) && viewer(item.viewer) && watchFilters(item.watchFilters));
25498
+ }
25499
+ function isAgentDetailView(value) {
25500
+ const item = record(value);
25501
+ const soul = item?.soul === void 0 ? void 0 : record(item.soul);
25502
+ return Boolean(item && typeof item.workspaceId === "string" && UUID.test(item.workspaceId) && member(item.agent) && item.agent.identity.kind === "agent" && Array.isArray(item.catalog) && item.catalog.length <= 100 && item.catalog.every(modelOption) && (soul === void 0 || soul !== null && typeof soul.name === "string" && soul.name.length > 0 && typeof soul.instructions === "string" && soul.instructions.length > 0 && typeof soul.avatarSeed === "string" && soul.avatarSeed.length > 0 && (soul.avatar === void 0 || httpUrl(soul.avatar))) && (item.runtimeSelection === void 0 || modelSelection(item.runtimeSelection)) && (item.selected === void 0 || modelSelection(item.selected)) && watchFilters(item.watchFilters));
25503
+ }
25504
+ function isInviteView(value) {
25505
+ const item = record(value);
25506
+ if (!item || typeof item.name !== "string" || !integer3(item.expiresAt) || !optionalString(item.avatar))
25507
+ return false;
25508
+ return Object.keys(item).every((key) => key === "name" || key === "avatar" || key === "expiresAt");
25509
+ }
25510
+ function isAgentPairingClaimWireView(value) {
25511
+ if (!value || typeof value !== "object")
25512
+ return false;
25513
+ const candidate = value;
25514
+ return typeof candidate.workspaceId === "string" && UUID.test(candidate.workspaceId) && typeof candidate.pairedBy === "string" && HEX.test(candidate.pairedBy) && typeof candidate.joined === "boolean" && (candidate.attachedRoomIds === void 0 || Array.isArray(candidate.attachedRoomIds) && candidate.attachedRoomIds.every((roomId) => typeof roomId === "string" && UUID.test(roomId)));
25515
+ }
25516
+ function isAgentPairingAbandonView(value) {
25517
+ return Boolean(value) && typeof value === "object" && typeof value.abandoned === "boolean";
25518
+ }
25519
+
25520
+ // packages/api-contract/dist/agent-pairing-code.js
25521
+ var AGENT_PAIRING_CODE_ENTROPY_BYTES = 8;
25522
+ var CURRENT_AGENT_PAIRING_CODE = /^[0-9A-F]{8}-[0-9A-F]{8}$/;
25523
+ var LEGACY_AGENT_PAIRING_CODE = /^BUZZ-(?:[0-9A-F]{8}-[0-9A-F]{8}|[A-HJ-NP-Z2-9]{4}-[A-HJ-NP-Z2-9]{4})$/;
25524
+ function normalizeAgentPairingCode(value) {
25525
+ if (typeof value !== "string")
25526
+ return void 0;
25527
+ const normalized = value.trim().toUpperCase();
25528
+ return isAgentPairingCode(normalized) ? normalized : void 0;
25529
+ }
25530
+ function isAgentPairingCode(value) {
25531
+ return typeof value === "string" && (CURRENT_AGENT_PAIRING_CODE.test(value) || LEGACY_AGENT_PAIRING_CODE.test(value));
25532
+ }
25533
+ function createAgentPairingCode(entropy) {
25534
+ if (entropy.length !== AGENT_PAIRING_CODE_ENTROPY_BYTES) {
25535
+ throw new Error(`pairing code entropy must be ${AGENT_PAIRING_CODE_ENTROPY_BYTES} bytes`);
25536
+ }
25537
+ const encoded = Array.from(entropy, (byte) => byte.toString(16).padStart(2, "0")).join("").toUpperCase();
25538
+ return `${encoded.slice(0, 8)}-${encoded.slice(8)}`;
25539
+ }
25540
+
25289
25541
  // packages/buzz-client/dist/community.js
25290
25542
  init_utils();
25291
25543
  init_sha2();
@@ -27679,430 +27931,197 @@ async function attachCommunityMemberToChannel(ctx, channelId, memberPubkey, comm
27679
27931
  await setMemberRole(ctx, channelId, memberPubkey, "member", {
27680
27932
  extraTags: [
27681
27933
  [TAG_COMMUNITY, communityId],
27682
- ["member-invite", memberPubkey]
27683
- ]
27684
- });
27685
- await waitUntilMember(ctx, channelId, memberPubkey);
27686
- return { joined: true, membershipSince };
27687
- }
27688
- function inviteExpiry(options, createdAt) {
27689
- if (options?.expiresAt !== void 0 && options.expiresInSeconds !== void 0) {
27690
- throw new Error("set either expiresAt or expiresInSeconds, not both");
27691
- }
27692
- const expiresAt = options?.expiresAt ?? createdAt + (options?.expiresInSeconds ?? DEFAULT_INVITE_TTL_SECONDS);
27693
- if (!Number.isSafeInteger(expiresAt) || expiresAt <= createdAt) {
27694
- throw new Error("invite expiry must be a future Unix timestamp");
27695
- }
27696
- return expiresAt;
27697
- }
27698
- function parseCommunityInvite(event) {
27699
- if (event.kind !== KIND_COMMUNITY_INVITE && event.kind !== KIND_STREAM_MESSAGE || !verifyEvent2(event)) {
27700
- return null;
27701
- }
27702
- if (!tagValues(event, "t").includes(TAG_COMMUNITY_INVITE))
27703
- return null;
27704
- const tokenHash = tagValue(event, "d");
27705
- const communityId = tagValue(event, "h");
27706
- const communityTag = tagValue(event, TAG_COMMUNITY);
27707
- const expiresRaw = tagValue(event, "expiration");
27708
- const expiresAt = expiresRaw === void 0 ? NaN : Number(expiresRaw);
27709
- const revoked = tagValue(event, "revoked") === "true";
27710
- if (!tokenHash || !/^[0-9a-f]{64}$/.test(tokenHash))
27711
- return null;
27712
- if (!communityId || communityTag !== communityId)
27713
- return null;
27714
- if (!Number.isSafeInteger(expiresAt) || expiresAt <= event.created_at)
27715
- return null;
27716
- return {
27717
- tokenHash,
27718
- communityId,
27719
- expiresAt,
27720
- mintedBy: event.pubkey,
27721
- ...revoked ? { revoked: true } : {},
27722
- event
27723
- };
27724
- }
27725
- function latestInviteRecord(events, tokenHash) {
27726
- const record2 = events.map(parseCommunityInvite).filter((candidate) => candidate?.tokenHash === tokenHash).sort((a2, b) => b.event.created_at - a2.event.created_at || b.event.id.localeCompare(a2.event.id))[0];
27727
- return record2 && !record2.revoked ? record2 : null;
27728
- }
27729
- async function findCommunityInvite(http, tokenHash, readerPubkey) {
27730
- const current = await queryEvents(http, [
27731
- {
27732
- kinds: [KIND_COMMUNITY_INVITE],
27733
- "#d": [tokenHash],
27734
- "#t": [TAG_COMMUNITY_INVITE],
27735
- limit: 20
27736
- }
27737
- ], readerPubkey);
27738
- const foundCurrent = latestInviteRecord(current, tokenHash);
27739
- if (foundCurrent)
27740
- return foundCurrent;
27741
- if (current.some((event) => parseCommunityInvite(event)?.revoked))
27742
- return null;
27743
- const legacy = await queryEvents(http, [{ kinds: [KIND_STREAM_MESSAGE], "#t": [TAG_COMMUNITY_INVITE], limit: 500 }], readerPubkey);
27744
- return latestInviteRecord(legacy, tokenHash);
27745
- }
27746
- async function listCommunityInvites(ctx, communityId) {
27747
- const events = await query(ctx, [
27748
- {
27749
- kinds: [KIND_COMMUNITY_INVITE],
27750
- authors: [ctx.identity.publicKey],
27751
- "#t": [TAG_COMMUNITY_INVITE],
27752
- limit: 500
27753
- }
27754
- ]);
27755
- const latestByToken = /* @__PURE__ */ new Map();
27756
- for (const event of events) {
27757
- const record2 = parseCommunityInvite(event);
27758
- if (!record2 || record2.communityId !== communityId)
27759
- continue;
27760
- const current = latestByToken.get(record2.tokenHash);
27761
- if (!current || record2.event.created_at > current.event.created_at || record2.event.created_at === current.event.created_at && record2.event.id > current.event.id) {
27762
- latestByToken.set(record2.tokenHash, record2);
27763
- }
27764
- }
27765
- const currentTime = now3();
27766
- return [...latestByToken.values()].filter((record2) => !record2.revoked && record2.expiresAt > currentTime).sort((a2, b) => b.event.created_at - a2.event.created_at);
27767
- }
27768
- async function revokeCommunityInvite(ctx, communityId, tokenHash) {
27769
- if (!/^[0-9a-f]{64}$/.test(tokenHash))
27770
- throw new Error("invalid invite");
27771
- const members = await communityMembers(ctx, communityId);
27772
- const actor = members.find((member2) => member2.pubkey === ctx.identity.publicKey);
27773
- if (actor?.role !== "owner" && actor?.role !== "admin") {
27774
- throw new Error("only a Workspace owner or admin can revoke invites");
27775
- }
27776
- const invite = (await listCommunityInvites(ctx, communityId)).find((record2) => record2.tokenHash === tokenHash);
27777
- if (!invite)
27778
- throw new Error("invite is no longer active");
27779
- const createdAt = Math.max(nextCommunityTimestamp(), invite.event.created_at + 1);
27780
- lastCommunityMutationTimestamp = createdAt;
27781
- const event = sign3(ctx, KIND_COMMUNITY_INVITE, [
27782
- ["h", communityId],
27783
- ["t", TAG_COMMUNITY_INVITE],
27784
- ["d", tokenHash],
27785
- [TAG_COMMUNITY, communityId],
27786
- ["expiration", String(Math.max(invite.expiresAt, createdAt + 1))],
27787
- ["role", "member"],
27788
- ["revoked", "true"]
27789
- ], "", createdAt);
27790
- await publishEvent(ctx.http, event);
27791
- }
27792
- async function createInvite(ctx, communityId, options) {
27793
- const community = await getCommunity(ctx, communityId);
27794
- if (!community)
27795
- throw new Error(`community not found: ${communityId}`);
27796
- const members = await communityMembers(ctx, communityId);
27797
- if (!members.some((member2) => member2.pubkey === ctx.identity.publicKey)) {
27798
- throw new Error("only a community member can mint an invite");
27799
- }
27800
- const createdAt = now3();
27801
- const expiresAt = inviteExpiry(options, createdAt);
27802
- const token2 = randomToken();
27803
- const tokenHash = inviteTokenHash(token2);
27804
- const event = sign3(ctx, KIND_COMMUNITY_INVITE, [
27805
- ["h", communityId],
27806
- ["t", TAG_COMMUNITY_INVITE],
27807
- ["d", tokenHash],
27808
- [TAG_COMMUNITY, communityId],
27809
- ["expiration", String(expiresAt)],
27810
- ["role", "member"]
27811
- ], "", createdAt);
27812
- await publishEvent(ctx.http, event);
27813
- return {
27814
- token: token2,
27815
- tokenHash,
27816
- communityId,
27817
- expiresAt,
27818
- mintedBy: ctx.identity.publicKey,
27819
- event
27820
- };
27821
- }
27822
- async function redeemInvite(ctx, token2) {
27823
- if (!token2 || token2.length > 512)
27824
- throw new Error("invalid invite token");
27825
- const tokenHash = inviteTokenHash(token2);
27826
- const invite = await findCommunityInvite(ctx.http, tokenHash, ctx.identity.publicKey);
27827
- if (!invite)
27828
- throw new Error("invalid invite token");
27829
- const members = await communityMembers(ctx, invite.communityId);
27830
- if (!members.some((member2) => member2.pubkey === invite.mintedBy)) {
27831
- throw new Error("invite minter is not a community member");
27832
- }
27833
- if ((await getChannelMetadata(ctx, invite.communityId))?.archived) {
27834
- throw archivedWorkspaceError();
27835
- }
27836
- if (members.some((member2) => member2.pubkey === ctx.identity.publicKey)) {
27837
- await assertCommunityMemberInChannels(ctx, invite.communityId, ctx.identity.publicKey);
27838
- return {
27839
- communityId: invite.communityId,
27840
- mintedBy: invite.mintedBy,
27841
- expiresAt: invite.expiresAt,
27842
- joined: false,
27843
- alreadyMember: true
27844
- };
27845
- }
27846
- if (invite.expiresAt <= now3())
27847
- throw new Error("invite has expired");
27848
- try {
27849
- await setMemberRole(ctx, invite.communityId, ctx.identity.publicKey, "member", {
27850
- extraTags: [
27851
- ["invite", tokenHash],
27852
- [TAG_COMMUNITY, invite.communityId]
27853
- ]
27854
- });
27855
- } catch (error) {
27856
- if (isArchivedChannelError(error))
27857
- throw archivedWorkspaceError();
27858
- throw error;
27859
- }
27860
- await waitUntilMember(ctx, invite.communityId, ctx.identity.publicKey);
27861
- await assertCommunityMemberInChannels(ctx, invite.communityId, ctx.identity.publicKey);
27862
- return {
27863
- communityId: invite.communityId,
27864
- mintedBy: invite.mintedBy,
27865
- expiresAt: invite.expiresAt,
27866
- joined: true,
27867
- alreadyMember: false
27868
- };
27869
- }
27870
-
27871
- // packages/buzz-client/dist/room-view.js
27872
- init_dist();
27873
-
27874
- // packages/api-contract/dist/phone-types.js
27875
- var ROOM_VIEW_MESSAGE_LIMIT = 30;
27876
- var ROOM_VIEW_BRIEFING_LIMIT = 10;
27877
- var ROOM_VIEW_WORKSPACE_LIMIT = 50;
27878
- var ROOM_VIEW_CHAT_LIMIT = 200;
27879
- var ROOM_VIEW_MEMBER_LIMIT = 200;
27880
- var ROOM_VIEW_AGENT_LIMIT = 200;
27881
- var ROOM_VIEW_REQUEST_TIMEOUT_MS = 8e3;
27882
-
27883
- // packages/api-contract/dist/phone-guards.js
27884
- var HEX = /^[0-9a-f]{64}$/;
27885
- var UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
27886
- function record(value) {
27887
- return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
27888
- }
27889
- function integer3(value) {
27890
- return Number.isSafeInteger(value) && value >= 0;
27891
- }
27892
- function optionalString(value) {
27893
- return value === void 0 || typeof value === "string";
27894
- }
27895
- function httpUrl(value) {
27896
- if (typeof value !== "string")
27897
- return false;
27898
- try {
27899
- const protocol = new URL(value).protocol;
27900
- return protocol === "http:" || protocol === "https:";
27901
- } catch {
27902
- return false;
27903
- }
27904
- }
27905
- function attachment(value) {
27906
- const item = record(value);
27907
- return Boolean(item && httpUrl(item.url) && typeof item.name === "string" && item.name.length > 0 && typeof item.mimeType === "string" && /^[^/\s]+\/[^/\s]+$/.test(item.mimeType) && integer3(item.size) && (item.previewUrl === void 0 || httpUrl(item.previewUrl)) && (item.thumbnailUrl === void 0 || httpUrl(item.thumbnailUrl)) && (item.sha256 === void 0 || typeof item.sha256 === "string" && HEX.test(item.sha256)) && (item.width === void 0 || integer3(item.width) && item.width > 0) && (item.height === void 0 || integer3(item.height) && item.height > 0));
27908
- }
27909
- function activity(value) {
27910
- const item = record(value);
27911
- const rollup = item?.rollup === void 0 ? void 0 : record(item.rollup);
27912
- const plan = item?.plan === void 0 ? void 0 : record(item.plan);
27913
- return Boolean(item && (item.kind === "thinking" || item.kind === "tool" || item.kind === "output" || item.kind === "summary") && typeof item.title === "string" && optionalString(item.operation) && optionalString(item.status) && (item.thoughtMs === void 0 || integer3(item.thoughtMs)) && (rollup === void 0 || rollup !== null && Object.values(rollup).every(integer3)) && (item.observed === void 0 || Array.isArray(item.observed) && item.observed.every((candidate) => {
27914
- const observed = record(candidate);
27915
- return Boolean(observed && typeof observed.verb === "string" && optionalString(observed.target) && optionalString(observed.result));
27916
- })) && (item.files === void 0 || Array.isArray(item.files) && item.files.every((candidate) => {
27917
- const file = record(candidate);
27918
- return Boolean(file && typeof file.path === "string" && optionalString(file.status));
27919
- })) && (plan === void 0 || plan !== null && optionalString(plan.objective) && Array.isArray(plan.items) && plan.items.every((candidate) => {
27920
- const planItem = record(candidate);
27921
- return Boolean(planItem && typeof planItem.step === "string" && (planItem.status === "pending" || planItem.status === "in_progress" || planItem.status === "completed"));
27922
- })));
27923
- }
27924
- function identity(value) {
27925
- const item = record(value);
27926
- return Boolean(item && typeof item.pubkey === "string" && HEX.test(item.pubkey) && (item.kind === "human" || item.kind === "agent") && typeof item.name === "string" && optionalString(item.handle) && optionalString(item.avatar));
27927
- }
27928
- function header(value) {
27929
- const item = record(value);
27930
- return Boolean(item && typeof item.id === "string" && UUID.test(item.id) && typeof item.workspaceId === "string" && UUID.test(item.workspaceId) && (item.parentId === void 0 || typeof item.parentId === "string" && UUID.test(item.parentId)) && typeof item.name === "string" && optionalString(item.about) && optionalString(item.avatar) && (item.visibility === void 0 || item.visibility === "public" || item.visibility === "invite-only") && typeof item.archived === "boolean" && integer3(item.createdAt) && integer3(item.updatedAt));
27931
- }
27932
- function member(value) {
27933
- const item = record(value);
27934
- const presence = item?.presence === void 0 ? void 0 : record(item.presence);
27935
- return Boolean(item && identity(item.identity) && (item.role === "owner" || item.role === "admin" || item.role === "member") && (presence === void 0 || presence && (presence.status === "online" || presence.status === "offline") && integer3(presence.observedAt) && (presence.roomId === void 0 || typeof presence.roomId === "string" && UUID.test(presence.roomId))));
27936
- }
27937
- function messageCorner(value) {
27938
- const item = record(value);
27939
- return Boolean(item && typeof item.id === "string" && UUID.test(item.id) && (item.status === "open" || item.status === "working" || item.status === "waiting" || item.status === "idle" || item.status === "concluded" || item.status === "closed"));
27940
- }
27941
- function messagePermission(value) {
27942
- const item = record(value);
27943
- return Boolean(item && typeof item.permissionId === "string" && item.permissionId.length > 0 && typeof item.requestId === "string" && item.requestId.length > 0 && identity(item.agent) && item.agent.kind === "agent" && identity(item.requester) && item.requester.kind === "human" && (item.decider === void 0 || identity(item.decider) && item.decider.kind === "human") && typeof item.tool === "string" && item.tool.length > 0 && optionalString(item.repository) && (item.purpose === void 0 || item.purpose === "squire-spending") && (item.status === "pending" || item.status === "allowed" || item.status === "denied" || item.status === "expired" || item.status === "failed") && (item.cornerId === void 0 || typeof item.cornerId === "string" && UUID.test(item.cornerId)));
27944
- }
27945
- function targetBranch(value) {
27946
- const item = record(value);
27947
- return Boolean(item && typeof item.proposalId === "string" && item.proposalId.length > 0 && typeof item.from === "string" && typeof item.to === "string" && item.to.length > 0 && optionalString(item.repository) && (item.agent === void 0 || identity(item.agent)) && (item.requester === void 0 || identity(item.requester)));
27948
- }
27949
- function githubUrl(value) {
27950
- if (typeof value !== "string")
27951
- return false;
27952
- try {
27953
- const url = new URL(value);
27954
- return url.protocol === "https:" && url.hostname === "github.com";
27955
- } catch {
27956
- return false;
27957
- }
27958
- }
27959
- function githubEvent(value) {
27960
- const item = record(value);
27961
- if (!item || item.type !== "pull-request" && item.type !== "issue" || typeof item.actor !== "string" || typeof item.title !== "string" || !githubUrl(item.url)) {
27962
- return false;
27963
- }
27964
- return item.type === "pull-request" && (item.action === "opened" || item.action === "closed" || item.action === "merged") || item.type === "issue" && (item.action === "opened" || item.action === "closed");
27965
- }
27966
- function daemonFact(value) {
27967
- const item = record(value);
27968
- const pullRequest = item?.pullRequest === void 0 ? void 0 : record(item.pullRequest);
27969
- if (!item || item.type !== "corner-complete" && item.type !== "checks-failing" && item.type !== "worktree-cleaned" && item.type !== "corner-open" || typeof item.cornerId !== "string" || !UUID.test(item.cornerId) || typeof item.objective !== "string" || !item.objective.trim() || item.outcome !== void 0 && item.outcome !== "landed" && item.outcome !== "abandoned" || !optionalString(item.name) || item.type === "corner-open" && (typeof item.name !== "string" || !item.name.trim()) || pullRequest !== void 0 && (!pullRequest || pullRequest.number !== void 0 && (!Number.isSafeInteger(pullRequest.number) || Number(pullRequest.number) <= 0) || !optionalString(pullRequest.title) || !githubUrl(pullRequest.url) || !optionalString(pullRequest.targetBranch)) || item.subgoals !== void 0 && (!Array.isArray(item.subgoals) || !item.subgoals.every((subgoal) => {
27970
- const entry = record(subgoal);
27971
- return Boolean(entry && typeof entry.step === "string" && entry.step.trim() && (entry.status === "pending" || entry.status === "in_progress" || entry.status === "completed"));
27972
- }))) {
27973
- return false;
27974
- }
27975
- return item.type !== "corner-complete" || item.outcome === "landed" || item.outcome === "abandoned";
27976
- }
27977
- function isRoomViewMessage(value) {
27978
- const item = record(value);
27979
- const reference = item?.reference === void 0 ? void 0 : record(item.reference);
27980
- const reply = item?.reply === void 0 ? void 0 : record(item.reply);
27981
- return Boolean(item && typeof item.id === "string" && HEX.test(item.id) && typeof item.text === "string" && integer3(item.createdAt) && identity(item.author) && (item.presentation === "message" || item.presentation === "system" || item.presentation === "activity" || item.presentation === "card") && (reference === void 0 || reference && typeof reference.channelId === "string" && UUID.test(reference.channelId) && reference.eventId === item.id && typeof reference.rootId === "string" && HEX.test(reference.rootId)) && (reply === void 0 || reply && typeof reply.channelId === "string" && UUID.test(reply.channelId) && typeof reply.eventId === "string" && HEX.test(reply.eventId) && typeof reply.rootId === "string" && HEX.test(reply.rootId)) && optionalString(item.liveTurnId) && optionalString(item.requestId) && (item.attachments === void 0 || Array.isArray(item.attachments) && item.attachments.every(attachment)) && (item.mentionPubkeys === void 0 || Array.isArray(item.mentionPubkeys) && item.mentionPubkeys.every((pubkey2) => typeof pubkey2 === "string" && HEX.test(pubkey2))) && (item.activity === void 0 || Array.isArray(item.activity) && item.activity.every(activity)) && (item.durableFact === void 0 || item.durableFact === "failure" || item.durableFact === "merge" || item.durableFact === "action") && (item.corner === void 0 || messageCorner(item.corner)) && (item.permission === void 0 || messagePermission(item.permission)) && (item.targetBranch === void 0 || targetBranch(item.targetBranch)) && (item.githubEvent === void 0 || githubEvent(item.githubEvent)) && (item.daemonFact === void 0 || daemonFact(item.daemonFact)));
27982
- }
27983
- function scopedMessage(value, roomId) {
27984
- return typeof roomId === "string" && isRoomViewMessage(value) && (value.reference === void 0 || value.reference.channelId === roomId) && (value.reply === void 0 || value.reply.channelId === roomId);
27985
- }
27986
- function watchFilters(value) {
27987
- return Array.isArray(value) && value.length <= 32 && value.every((candidate) => {
27988
- const filter = record(candidate);
27989
- if (!filter)
27990
- return false;
27991
- return Object.entries(filter).every(([key, entry]) => {
27992
- if (key === "kinds")
27993
- return Array.isArray(entry) && entry.every(integer3);
27994
- if (key === "authors" || key === "#h" || key === "#d" || key === "#p" || key === "#t") {
27995
- return Array.isArray(entry) && entry.every((item) => typeof item === "string");
27996
- }
27997
- return false;
27998
- });
27999
- });
28000
- }
28001
- function viewer(value) {
28002
- const item = record(value);
28003
- const permissions = record(item?.permissions);
28004
- return Boolean(item && identity(item.identity) && (item.role === "owner" || item.role === "admin" || item.role === "member") && permissions && typeof permissions.send === "boolean" && typeof permissions.manage === "boolean");
28005
- }
28006
- function directMessage(value) {
28007
- const item = record(value);
28008
- return Boolean(item && Array.isArray(item.participants) && item.participants.length === 2 && item.participants.every((pubkey2) => typeof pubkey2 === "string" && HEX.test(pubkey2)) && item.participants[0] < item.participants[1]);
28009
- }
28010
- function directMessageForViewer(value, viewerValue) {
28011
- const viewerItem = record(viewerValue);
28012
- const viewerIdentity = record(viewerItem?.identity);
28013
- return directMessage(value) && typeof viewerIdentity?.pubkey === "string" && value.participants.includes(viewerIdentity.pubkey);
28014
- }
28015
- function agentTurn(value) {
28016
- const item = record(value);
28017
- return Boolean(item && typeof item.requestId === "string" && HEX.test(item.requestId) && typeof item.agentPubkey === "string" && HEX.test(item.agentPubkey) && (item.status === "working" || item.status === "complete" || item.status === "failed") && integer3(item.createdAt) && optionalString(item.generationId));
28018
- }
28019
- function workspace(value) {
28020
- const item = record(value);
28021
- return Boolean(item && typeof item.id === "string" && UUID.test(item.id) && typeof item.name === "string" && optionalString(item.avatar) && (item.visibility === "public" || item.visibility === "invite-only") && (item.role === "owner" || item.role === "admin" || item.role === "member") && integer3(item.updatedAt));
28022
- }
28023
- function latest(value) {
28024
- const item = record(value);
28025
- return Boolean(item && typeof item.id === "string" && HEX.test(item.id) && typeof item.text === "string" && integer3(item.createdAt) && identity(item.author));
28026
- }
28027
- function chat(value) {
28028
- const item = record(value);
28029
- return Boolean(item && header(item.room) && (item.latestMessage === void 0 || latest(item.latestMessage)) && integer3(item.memberCount) && integer3(item.cornerCount) && typeof item.unread === "boolean" && optionalString(item.repositoryName) && (item.agentState === void 0 || item.agentState === "needs-you" || item.agentState === "working"));
28030
- }
28031
- function corner(value) {
28032
- const item = record(value);
28033
- return Boolean(item && header(item.corner) && cornerLifecycle(item.lifecycle) && (item.status === "open" || item.status === "working" || item.status === "waiting" || item.status === "idle" || item.status === "concluded" || item.status === "closed") && (item.statusAt === void 0 || integer3(item.statusAt)) && (item.reason === void 0 || item.reason === "review" || item.reason === "question" || item.reason === "failure") && (item.agent === void 0 || identity(item.agent)) && (item.latestMessage === void 0 || latest(item.latestMessage)));
28034
- }
28035
- function cornerLifecycle(value) {
28036
- const item = record(value);
28037
- const pr = item?.pr === void 0 ? void 0 : record(item.pr);
28038
- return Boolean(item && (item.lifecycle === "working" || item.lifecycle === "in-review" || item.lifecycle === "unknown" || item.lifecycle === "done") && (item.checks === "passing" || item.checks === "failing" || item.checks === "pending" || item.checks === "unknown") && optionalString(item.branch) && (item.outcome === void 0 || item.outcome === "landed" || item.outcome === "abandoned") && optionalString(item.reason) && (pr === void 0 || pr && integer3(pr.number) && pr.number > 0 && githubUrl(pr.url) && typeof pr.title === "string" && pr.title.length > 0 && typeof pr.targetBranch === "string" && pr.targetBranch.length > 0 && typeof pr.headSha === "string" && /^[0-9a-f]{40}$/i.test(pr.headSha) && optionalString(pr.mergedAt) && optionalString(pr.mergedBy)));
28039
- }
28040
- function repository(value) {
28041
- const item = record(value);
28042
- return Boolean(item && typeof item.key === "string" && item.key.length > 0 && typeof item.name === "string" && item.name.length > 0 && typeof item.remote === "string" && item.remote.length > 0 && typeof item.targetBranch === "string" && item.targetBranch.length > 0 && integer3(item.updatedAt) && (item.githubInstallationId === void 0 || integer3(item.githubInstallationId)) && typeof item.githubEventsEnabled === "boolean");
28043
- }
28044
- function repositoryResolution(value) {
28045
- return value === "repository" || value === "none" || value === "unverified";
28046
- }
28047
- function modelSelection(value) {
28048
- const item = record(value);
28049
- return Boolean(item && optionalString(item.model) && optionalString(item.effort));
28050
- }
28051
- function modelOption(value) {
28052
- const item = record(value);
28053
- return Boolean(item && typeof item.id === "string" && item.id.length > 0 && typeof item.category === "string" && item.category.length > 0 && optionalString(item.currentValue) && Array.isArray(item.options) && item.options.every((candidate) => {
28054
- const option = record(candidate);
28055
- return Boolean(option && typeof option.id === "string" && option.id.length > 0 && optionalString(option.name));
28056
- }));
28057
- }
28058
- function isRoomView(value) {
28059
- const item = record(value);
28060
- return Boolean(item && header(item.room) && Array.isArray(item.messages) && item.messages.length <= ROOM_VIEW_MESSAGE_LIMIT && item.messages.every((candidate) => scopedMessage(candidate, record(item.room)?.id)) && Array.isArray(item.latestAgentTurns) && item.latestAgentTurns.length <= ROOM_VIEW_AGENT_LIMIT && item.latestAgentTurns.every(agentTurn) && Array.isArray(item.members) && item.members.length <= ROOM_VIEW_MEMBER_LIMIT && item.members.every(member) && viewer(item.viewer) && (item.directMessage === void 0 || directMessageForViewer(item.directMessage, item.viewer)) && (item.parent === void 0 || header(item.parent)) && (item.briefing === void 0 || Array.isArray(item.briefing) && item.briefing.length <= ROOM_VIEW_BRIEFING_LIMIT && item.briefing.every(isRoomViewMessage)) && (item.cornerPlan === void 0 || activity({ kind: "output", title: "Plan", plan: item.cornerPlan })) && Array.isArray(item.corners) && item.corners.every(corner) && (item.repository === void 0 || repository(item.repository)) && repositoryResolution(item.repositoryResolution) && (item.cornerLifecycle === void 0 || cornerLifecycle(item.cornerLifecycle)) && watchFilters(item.watchFilters));
28061
- }
28062
- function isRoomHistoryView(value) {
28063
- const item = record(value);
28064
- const before = item?.nextBefore === void 0 ? void 0 : record(item.nextBefore);
28065
- return Boolean(item && typeof item.roomId === "string" && UUID.test(item.roomId) && Array.isArray(item.messages) && item.messages.length <= ROOM_VIEW_MESSAGE_LIMIT && item.messages.every((candidate) => scopedMessage(candidate, item.roomId)) && (before === void 0 || before && integer3(before.createdAt) && typeof before.id === "string" && HEX.test(before.id)));
27934
+ ["member-invite", memberPubkey]
27935
+ ]
27936
+ });
27937
+ await waitUntilMember(ctx, channelId, memberPubkey);
27938
+ return { joined: true, membershipSince };
28066
27939
  }
28067
- function isWorkspaceListView(value) {
28068
- const item = record(value);
28069
- return Boolean(item && Array.isArray(item.workspaces) && item.workspaces.length <= ROOM_VIEW_WORKSPACE_LIMIT && item.workspaces.every(workspace) && typeof item.truncated === "boolean" && identity(item.viewer) && watchFilters(item.watchFilters));
27940
+ function inviteExpiry(options, createdAt) {
27941
+ if (options?.expiresAt !== void 0 && options.expiresInSeconds !== void 0) {
27942
+ throw new Error("set either expiresAt or expiresInSeconds, not both");
27943
+ }
27944
+ const expiresAt = options?.expiresAt ?? createdAt + (options?.expiresInSeconds ?? DEFAULT_INVITE_TTL_SECONDS);
27945
+ if (!Number.isSafeInteger(expiresAt) || expiresAt <= createdAt) {
27946
+ throw new Error("invite expiry must be a future Unix timestamp");
27947
+ }
27948
+ return expiresAt;
28070
27949
  }
28071
- function isWorkspaceView(value) {
28072
- const item = record(value);
28073
- const managerSettings = item?.managerSettings === void 0 ? void 0 : record(item.managerSettings);
28074
- return Boolean(item && workspace(item.workspace) && integer3(record(item.workspace)?.createdAt) && optionalString(record(item.workspace)?.about) && (managerSettings === void 0 || managerSettings && (managerSettings.visibility === "public" || managerSettings.visibility === "invite-only")) && Array.isArray(item.members) && item.members.length <= ROOM_VIEW_MEMBER_LIMIT && item.members.every(member) && Array.isArray(item.agents) && item.agents.length <= ROOM_VIEW_AGENT_LIMIT && item.agents.every(member) && typeof item.membersTruncated === "boolean" && typeof item.agentsTruncated === "boolean" && viewer(item.viewer) && watchFilters(item.watchFilters));
27950
+ function parseCommunityInvite(event) {
27951
+ if (event.kind !== KIND_COMMUNITY_INVITE && event.kind !== KIND_STREAM_MESSAGE || !verifyEvent2(event)) {
27952
+ return null;
27953
+ }
27954
+ if (!tagValues(event, "t").includes(TAG_COMMUNITY_INVITE))
27955
+ return null;
27956
+ const tokenHash = tagValue(event, "d");
27957
+ const communityId = tagValue(event, "h");
27958
+ const communityTag = tagValue(event, TAG_COMMUNITY);
27959
+ const expiresRaw = tagValue(event, "expiration");
27960
+ const expiresAt = expiresRaw === void 0 ? NaN : Number(expiresRaw);
27961
+ const revoked = tagValue(event, "revoked") === "true";
27962
+ if (!tokenHash || !/^[0-9a-f]{64}$/.test(tokenHash))
27963
+ return null;
27964
+ if (!communityId || communityTag !== communityId)
27965
+ return null;
27966
+ if (!Number.isSafeInteger(expiresAt) || expiresAt <= event.created_at)
27967
+ return null;
27968
+ return {
27969
+ tokenHash,
27970
+ communityId,
27971
+ expiresAt,
27972
+ mintedBy: event.pubkey,
27973
+ ...revoked ? { revoked: true } : {},
27974
+ event
27975
+ };
28075
27976
  }
28076
- function isChatListView(value) {
28077
- const item = record(value);
28078
- return Boolean(item && workspace(item.workspace) && Array.isArray(item.chats) && item.chats.length <= ROOM_VIEW_CHAT_LIMIT && item.chats.every(chat) && typeof item.truncated === "boolean" && identity(item.viewer) && watchFilters(item.watchFilters));
27977
+ function latestInviteRecord(events, tokenHash) {
27978
+ const record2 = events.map(parseCommunityInvite).filter((candidate) => candidate?.tokenHash === tokenHash).sort((a2, b) => b.event.created_at - a2.event.created_at || b.event.id.localeCompare(a2.event.id))[0];
27979
+ return record2 && !record2.revoked ? record2 : null;
28079
27980
  }
28080
- function isCornerListView(value) {
28081
- const item = record(value);
28082
- return Boolean(item && header(item.room) && Array.isArray(item.corners) && item.corners.every(corner) && viewer(item.viewer) && watchFilters(item.watchFilters));
27981
+ async function findCommunityInvite(http, tokenHash, readerPubkey) {
27982
+ const current = await queryEvents(http, [
27983
+ {
27984
+ kinds: [KIND_COMMUNITY_INVITE],
27985
+ "#d": [tokenHash],
27986
+ "#t": [TAG_COMMUNITY_INVITE],
27987
+ limit: 20
27988
+ }
27989
+ ], readerPubkey);
27990
+ const foundCurrent = latestInviteRecord(current, tokenHash);
27991
+ if (foundCurrent)
27992
+ return foundCurrent;
27993
+ if (current.some((event) => parseCommunityInvite(event)?.revoked))
27994
+ return null;
27995
+ const legacy = await queryEvents(http, [{ kinds: [KIND_STREAM_MESSAGE], "#t": [TAG_COMMUNITY_INVITE], limit: 500 }], readerPubkey);
27996
+ return latestInviteRecord(legacy, tokenHash);
28083
27997
  }
28084
- function isAgentDetailView(value) {
28085
- const item = record(value);
28086
- const soul = item?.soul === void 0 ? void 0 : record(item.soul);
28087
- return Boolean(item && typeof item.workspaceId === "string" && UUID.test(item.workspaceId) && member(item.agent) && item.agent.identity.kind === "agent" && Array.isArray(item.catalog) && item.catalog.length <= 100 && item.catalog.every(modelOption) && (soul === void 0 || soul !== null && typeof soul.name === "string" && soul.name.length > 0 && typeof soul.instructions === "string" && soul.instructions.length > 0 && typeof soul.avatarSeed === "string" && soul.avatarSeed.length > 0 && (soul.avatar === void 0 || httpUrl(soul.avatar))) && (item.runtimeSelection === void 0 || modelSelection(item.runtimeSelection)) && (item.selected === void 0 || modelSelection(item.selected)) && watchFilters(item.watchFilters));
27998
+ async function listCommunityInvites(ctx, communityId) {
27999
+ const events = await query(ctx, [
28000
+ {
28001
+ kinds: [KIND_COMMUNITY_INVITE],
28002
+ authors: [ctx.identity.publicKey],
28003
+ "#t": [TAG_COMMUNITY_INVITE],
28004
+ limit: 500
28005
+ }
28006
+ ]);
28007
+ const latestByToken = /* @__PURE__ */ new Map();
28008
+ for (const event of events) {
28009
+ const record2 = parseCommunityInvite(event);
28010
+ if (!record2 || record2.communityId !== communityId)
28011
+ continue;
28012
+ const current = latestByToken.get(record2.tokenHash);
28013
+ if (!current || record2.event.created_at > current.event.created_at || record2.event.created_at === current.event.created_at && record2.event.id > current.event.id) {
28014
+ latestByToken.set(record2.tokenHash, record2);
28015
+ }
28016
+ }
28017
+ const currentTime = now3();
28018
+ return [...latestByToken.values()].filter((record2) => !record2.revoked && record2.expiresAt > currentTime).sort((a2, b) => b.event.created_at - a2.event.created_at);
28088
28019
  }
28089
- function isInviteView(value) {
28090
- const item = record(value);
28091
- if (!item || typeof item.name !== "string" || !integer3(item.expiresAt) || !optionalString(item.avatar))
28092
- return false;
28093
- return Object.keys(item).every((key) => key === "name" || key === "avatar" || key === "expiresAt");
28020
+ async function revokeCommunityInvite(ctx, communityId, tokenHash) {
28021
+ if (!/^[0-9a-f]{64}$/.test(tokenHash))
28022
+ throw new Error("invalid invite");
28023
+ const members = await communityMembers(ctx, communityId);
28024
+ const actor = members.find((member2) => member2.pubkey === ctx.identity.publicKey);
28025
+ if (actor?.role !== "owner" && actor?.role !== "admin") {
28026
+ throw new Error("only a Workspace owner or admin can revoke invites");
28027
+ }
28028
+ const invite = (await listCommunityInvites(ctx, communityId)).find((record2) => record2.tokenHash === tokenHash);
28029
+ if (!invite)
28030
+ throw new Error("invite is no longer active");
28031
+ const createdAt = Math.max(nextCommunityTimestamp(), invite.event.created_at + 1);
28032
+ lastCommunityMutationTimestamp = createdAt;
28033
+ const event = sign3(ctx, KIND_COMMUNITY_INVITE, [
28034
+ ["h", communityId],
28035
+ ["t", TAG_COMMUNITY_INVITE],
28036
+ ["d", tokenHash],
28037
+ [TAG_COMMUNITY, communityId],
28038
+ ["expiration", String(Math.max(invite.expiresAt, createdAt + 1))],
28039
+ ["role", "member"],
28040
+ ["revoked", "true"]
28041
+ ], "", createdAt);
28042
+ await publishEvent(ctx.http, event);
28094
28043
  }
28095
- function isAgentPairingClaimWireView(value) {
28096
- if (!value || typeof value !== "object")
28097
- return false;
28098
- const candidate = value;
28099
- return typeof candidate.workspaceId === "string" && UUID.test(candidate.workspaceId) && typeof candidate.pairedBy === "string" && HEX.test(candidate.pairedBy) && typeof candidate.joined === "boolean" && (candidate.attachedRoomIds === void 0 || Array.isArray(candidate.attachedRoomIds) && candidate.attachedRoomIds.every((roomId) => typeof roomId === "string" && UUID.test(roomId)));
28044
+ async function createInvite(ctx, communityId, options) {
28045
+ const community = await getCommunity(ctx, communityId);
28046
+ if (!community)
28047
+ throw new Error(`community not found: ${communityId}`);
28048
+ const members = await communityMembers(ctx, communityId);
28049
+ if (!members.some((member2) => member2.pubkey === ctx.identity.publicKey)) {
28050
+ throw new Error("only a community member can mint an invite");
28051
+ }
28052
+ const createdAt = now3();
28053
+ const expiresAt = inviteExpiry(options, createdAt);
28054
+ const token2 = randomToken();
28055
+ const tokenHash = inviteTokenHash(token2);
28056
+ const event = sign3(ctx, KIND_COMMUNITY_INVITE, [
28057
+ ["h", communityId],
28058
+ ["t", TAG_COMMUNITY_INVITE],
28059
+ ["d", tokenHash],
28060
+ [TAG_COMMUNITY, communityId],
28061
+ ["expiration", String(expiresAt)],
28062
+ ["role", "member"]
28063
+ ], "", createdAt);
28064
+ await publishEvent(ctx.http, event);
28065
+ return {
28066
+ token: token2,
28067
+ tokenHash,
28068
+ communityId,
28069
+ expiresAt,
28070
+ mintedBy: ctx.identity.publicKey,
28071
+ event
28072
+ };
28100
28073
  }
28101
- function isAgentPairingAbandonView(value) {
28102
- return Boolean(value) && typeof value === "object" && typeof value.abandoned === "boolean";
28074
+ async function redeemInvite(ctx, token2) {
28075
+ if (!token2 || token2.length > 512)
28076
+ throw new Error("invalid invite token");
28077
+ const tokenHash = inviteTokenHash(token2);
28078
+ const invite = await findCommunityInvite(ctx.http, tokenHash, ctx.identity.publicKey);
28079
+ if (!invite)
28080
+ throw new Error("invalid invite token");
28081
+ const members = await communityMembers(ctx, invite.communityId);
28082
+ if (!members.some((member2) => member2.pubkey === invite.mintedBy)) {
28083
+ throw new Error("invite minter is not a community member");
28084
+ }
28085
+ if ((await getChannelMetadata(ctx, invite.communityId))?.archived) {
28086
+ throw archivedWorkspaceError();
28087
+ }
28088
+ if (members.some((member2) => member2.pubkey === ctx.identity.publicKey)) {
28089
+ await assertCommunityMemberInChannels(ctx, invite.communityId, ctx.identity.publicKey);
28090
+ return {
28091
+ communityId: invite.communityId,
28092
+ mintedBy: invite.mintedBy,
28093
+ expiresAt: invite.expiresAt,
28094
+ joined: false,
28095
+ alreadyMember: true
28096
+ };
28097
+ }
28098
+ if (invite.expiresAt <= now3())
28099
+ throw new Error("invite has expired");
28100
+ try {
28101
+ await setMemberRole(ctx, invite.communityId, ctx.identity.publicKey, "member", {
28102
+ extraTags: [
28103
+ ["invite", tokenHash],
28104
+ [TAG_COMMUNITY, invite.communityId]
28105
+ ]
28106
+ });
28107
+ } catch (error) {
28108
+ if (isArchivedChannelError(error))
28109
+ throw archivedWorkspaceError();
28110
+ throw error;
28111
+ }
28112
+ await waitUntilMember(ctx, invite.communityId, ctx.identity.publicKey);
28113
+ await assertCommunityMemberInChannels(ctx, invite.communityId, ctx.identity.publicKey);
28114
+ return {
28115
+ communityId: invite.communityId,
28116
+ mintedBy: invite.mintedBy,
28117
+ expiresAt: invite.expiresAt,
28118
+ joined: true,
28119
+ alreadyMember: false
28120
+ };
28103
28121
  }
28104
28122
 
28105
28123
  // packages/buzz-client/dist/room-view.js
28124
+ init_dist();
28106
28125
  var AGENT_PAIRING_ROOM_ROLLBACK_CAPABILITY = "pairing-room-rollback";
28107
28126
  var RoomViewHttpError = class extends Error {
28108
28127
  status;
@@ -28354,7 +28373,6 @@ function personHandle(name, pubkey2) {
28354
28373
 
28355
28374
  // packages/buzz-client/dist/agent.js
28356
28375
  var DEFAULT_PAIRING_TTL_SECONDS = 10 * 60;
28357
- var PAIRING_ALPHABET = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
28358
28376
  var KIND_NOSTR_PROFILE = 0;
28359
28377
  var lastSoulTimestamp = 0;
28360
28378
  function now4() {
@@ -28370,10 +28388,7 @@ function optionalHttpUrl(value) {
28370
28388
  function randomPairingCode() {
28371
28389
  const bytes = new Uint8Array(8);
28372
28390
  globalThis.crypto.getRandomValues(bytes);
28373
- let value = "";
28374
- for (const byte of bytes)
28375
- value += PAIRING_ALPHABET[byte % PAIRING_ALPHABET.length];
28376
- return `BUZZ-${value.slice(0, 4)}-${value.slice(4)}`;
28391
+ return createAgentPairingCode(bytes);
28377
28392
  }
28378
28393
  function pairingExpiry(expiresInSeconds, createdAt) {
28379
28394
  if (!Number.isSafeInteger(expiresInSeconds) || expiresInSeconds < 60 || expiresInSeconds > 3600) {
@@ -28488,7 +28503,7 @@ async function createAgentRecord(ctx, communityId, options = {}, pairingHash) {
28488
28503
  await publishEvent(ctx.http, event);
28489
28504
  return parseAgent(event);
28490
28505
  }
28491
- async function createAgentPairingCode(ctx, communityId, expiresInSeconds = DEFAULT_PAIRING_TTL_SECONDS) {
28506
+ async function createAgentPairingCode2(ctx, communityId, expiresInSeconds = DEFAULT_PAIRING_TTL_SECONDS) {
28492
28507
  const community = await getCommunity(ctx, communityId);
28493
28508
  if (!community)
28494
28509
  throw new Error(`community not found: ${communityId}`);
@@ -28553,8 +28568,8 @@ async function matchingAgentPairingRedemptions(ctx, tokenHash) {
28553
28568
  return events.filter((event) => tagValue(event, "pairing") === tokenHash);
28554
28569
  }
28555
28570
  async function redeemAgentPairingCode(ctx, rawCode, options = {}) {
28556
- const code = rawCode.trim().toUpperCase();
28557
- if (!/^BUZZ-[A-HJ-NP-Z2-9]{4}-[A-HJ-NP-Z2-9]{4}$/.test(code)) {
28571
+ const code = normalizeAgentPairingCode(rawCode);
28572
+ if (!code) {
28558
28573
  throw new Error("invalid agent pairing code");
28559
28574
  }
28560
28575
  const tokenHash = inviteTokenHash(code);
@@ -30659,7 +30674,7 @@ var BuzzClient = class {
30659
30674
  return attachAgentToChannel(this.ctx, channelId, agentPubkey, communityId);
30660
30675
  }
30661
30676
  createAgentPairingCode(communityId, expiresInSeconds) {
30662
- return createAgentPairingCode(this.ctx, communityId, expiresInSeconds);
30677
+ return createAgentPairingCode2(this.ctx, communityId, expiresInSeconds);
30663
30678
  }
30664
30679
  redeemAgentPairingCode(code, options) {
30665
30680
  return redeemAgentPairingCode(this.ctx, code, options);
@@ -43531,6 +43546,12 @@ function isRepositoryMutationRequest(content) {
43531
43546
  }
43532
43547
  return new RegExp(String.raw`^${REQUEST_LEAD}(?:open|create|launch|start)\s+(?:up\s+)?(?:a\s+|the\s+)?(?:new\s+)?(?:edit\s+)?corner\b`, "i").test(normalized);
43533
43548
  }
43549
+ function isExplicitCornerOpenRequest(content) {
43550
+ const normalized = normalizeRoomRequest(content);
43551
+ const directCornerCommand = new RegExp(String.raw`^${REQUEST_LEAD}(?:open|create|launch|start)\s+(?:up\s+)?(?:a\s+|the\s+)?(?:new\s+)?corner\b`, "i");
43552
+ const startWorkInCornerCommand = new RegExp(String.raw`^${REQUEST_LEAD}start\s+(?:(?:the|this|that)\s+)?(?:work|working)\b.{0,200}\b(?:in|inside|within)\s+(?:a\s+|the\s+)?(?:new\s+)?corner\b`, "i");
43553
+ return directCornerCommand.test(normalized) || startWorkInCornerCommand.test(normalized);
43554
+ }
43534
43555
  function isNonRetryableRelayError(error) {
43535
43556
  const failure = asRelayPublishError(error);
43536
43557
  return !failure.retryable && (failure.status !== void 0 || failure.kind === "CLIENT_VALIDATION" || failure.kind === "NEGATIVE_ACK");
@@ -43664,11 +43685,7 @@ function isChannelAddressedMessage(event, agentPubkey, roomParticipants = [], in
43664
43685
  function isChannelWorkIntent(event, agentPubkey, roomParticipants = [], indexedMessages = []) {
43665
43686
  if (!isChannelAddressedMessage(event, agentPubkey, roomParticipants, indexedMessages))
43666
43687
  return false;
43667
- const content = event.content.normalize("NFKC").replace(/\s+/g, " ").trim().replace(/^@[\p{L}\p{N}_-]+[,:]?\s+/u, "");
43668
- const requestLead = String.raw`(?:(?:please|kindly)\s+|(?:can|could|would|will)\s+you\s+|i\s+(?:want|need)\s+you\s+to\s+|i(?:['’]d| would)\s+like\s+you\s+to\s+)?`;
43669
- const directCornerCommand = new RegExp(String.raw`^${requestLead}(?:open|create|launch|start)\s+(?:up\s+)?(?:a\s+|the\s+)?(?:new\s+)?corner\b`, "i");
43670
- const startWorkInCornerCommand = new RegExp(String.raw`^${requestLead}start\s+(?:(?:the|this|that)\s+)?(?:work|working)\b.{0,200}\b(?:in|inside|within)\s+(?:a\s+|the\s+)?(?:new\s+)?corner\b`, "i");
43671
- return directCornerCommand.test(content) || startWorkInCornerCommand.test(content);
43688
+ return isExplicitCornerOpenRequest(event.content);
43672
43689
  }
43673
43690
  async function createAgentSubchannel(agentIdentity, parentChannelId, name, openingHumanPubkey, communityId, task, extraTags = []) {
43674
43691
  if (!openingHumanPubkey || openingHumanPubkey === agentIdentity.publicKey) {
@@ -47272,6 +47289,18 @@ Deliver artifacts from this corner; there is no branch to land.`;
47272
47289
  const named = editPolicy === "named-repository" ? namedRepositoryTargetFromRoomRequest(request.content) : void 0;
47273
47290
  if (!named) {
47274
47291
  console.log(`[body] Room ${tlcChannelId} has no repository target for corner work`);
47292
+ const text2 = "This Room has no repository yet - bind one in Room settings.";
47293
+ if (this.daemonApi) {
47294
+ await this.daemonApi.execute("postRoomMessage", {
47295
+ roomId: tlcChannelId,
47296
+ requestId: request.eventId,
47297
+ text: text2,
47298
+ presentation: "message"
47299
+ });
47300
+ } else {
47301
+ const event = await this.durableState.reserveReply(tlcChannelId, request.eventId, buildAgentMessage(tlcChannelId, this.agentIdentity, text2, request.eventId, [], [["request", request.eventId]], request.replyRootId));
47302
+ await publishEvent2(event, this.agentIdentity);
47303
+ }
47275
47304
  return { status: "handled", outcome: { openedCorner: false, producedReply: true } };
47276
47305
  }
47277
47306
  }
@@ -48927,72 +48956,88 @@ Deliver artifacts from this corner; there is no branch to land.`;
48927
48956
  async runMonolithRoomLoop(channelId, boundRepo, editPolicy, opts) {
48928
48957
  const api = this.daemonApi;
48929
48958
  let cursor3 = await this.durableState.daemonInboxCursor(channelId);
48930
- await api.execute("postAgentPresence", {
48931
- agentId: this.agentIdentity.publicKey,
48932
- roomId: channelId,
48933
- status: this.config.modelUnavailable ? "offline" : "online"
48934
- });
48935
- if (!cursor3) {
48936
- const activation = await api.execute("getRoomInbox", {
48959
+ const availableStatus = this.config.modelUnavailable ? "offline" : "online";
48960
+ const postPresence = async (status) => {
48961
+ await api.execute("postAgentPresence", {
48962
+ agentId: this.agentIdentity.publicKey,
48937
48963
  roomId: channelId,
48938
- startAtLatest: true
48964
+ status
48939
48965
  });
48940
- if (activation.cursor) {
48941
- cursor3 = activation.cursor;
48942
- await this.durableState.setDaemonInboxCursor(channelId, cursor3);
48943
- }
48944
- }
48945
- while (!opts.signal?.aborted && !this.disposed) {
48946
- try {
48947
- const inbox = await api.execute("getRoomInbox", {
48966
+ this.onRoomPresence?.(channelId, status);
48967
+ };
48968
+ await postPresence(availableStatus);
48969
+ let presenceTail = Promise.resolve();
48970
+ const heartbeat = setInterval(() => {
48971
+ presenceTail = presenceTail.then(() => postPresence(availableStatus)).catch((error) => console.error(`[body] monolith Room ${channelId} presence heartbeat failed:`, error));
48972
+ }, AGENT_PRESENCE_HEARTBEAT_MS);
48973
+ heartbeat.unref?.();
48974
+ try {
48975
+ if (!cursor3) {
48976
+ const activation = await api.execute("getRoomInbox", {
48948
48977
  roomId: channelId,
48949
- ...cursor3 ? { after: cursor3 } : {},
48950
- limit: 200
48978
+ startAtLatest: true
48951
48979
  });
48952
- for (const item of inbox.items) {
48953
- if (item.authorId === this.agentIdentity.publicKey || item.type !== "message" || item.mentionIds.length > 0 && !item.mentionIds.includes(this.agentIdentity.publicKey) || this.processedRequestIds.has(item.id))
48954
- continue;
48955
- const authority = await api.execute("getRoomAuthority", {
48980
+ if (activation.cursor) {
48981
+ cursor3 = activation.cursor;
48982
+ await this.durableState.setDaemonInboxCursor(channelId, cursor3);
48983
+ }
48984
+ }
48985
+ while (!opts.signal?.aborted && !this.disposed) {
48986
+ try {
48987
+ const inbox = await api.execute("getRoomInbox", {
48956
48988
  roomId: channelId,
48957
- principalId: item.authorId
48989
+ ...cursor3 ? { after: cursor3 } : {},
48990
+ limit: 200
48958
48991
  });
48959
- if (!authority.member || authority.principalKind !== "human")
48960
- continue;
48961
- if (!this.senderAccessAllowed(item.authorId))
48962
- continue;
48963
- const attachments = item.attachments.map((attachment2) => ({
48964
- url: attachment2.url,
48965
- name: attachment2.name ?? "attachment",
48966
- mimeType: attachment2.mimeType ?? "application/octet-stream",
48967
- size: attachment2.size ?? 0,
48968
- ...attachment2.thumbnailUrl ? { thumbnailUrl: attachment2.thumbnailUrl } : {}
48969
- }));
48970
- const request = {
48971
- eventId: item.id,
48972
- authorPubkey: item.authorId,
48973
- content: item.body.trim(),
48974
- attachments,
48975
- createdAt: item.createdAt,
48976
- ...item.rootMessageId ? { replyRootId: item.rootMessageId } : {}
48977
- };
48978
- const workIntent = !isReadOnlyInformationRequest(item.body);
48979
- const outcome = await this.replyInRoom(channelId, boundRepo, request, editPolicy === "repository" && workIntent, editPolicy, void 0, workIntent);
48980
- if (outcome.producedReply)
48981
- this.processedRequestIds.add(item.id);
48982
- }
48983
- if (inbox.cursor) {
48984
- cursor3 = inbox.cursor;
48985
- await this.durableState.setDaemonInboxCursor(channelId, cursor3);
48992
+ for (const item of inbox.items) {
48993
+ if (item.authorId === this.agentIdentity.publicKey || item.type !== "message" || item.mentionIds.length > 0 && !item.mentionIds.includes(this.agentIdentity.publicKey) || this.processedRequestIds.has(item.id))
48994
+ continue;
48995
+ const authority = await api.execute("getRoomAuthority", {
48996
+ roomId: channelId,
48997
+ principalId: item.authorId
48998
+ });
48999
+ if (!authority.member || authority.principalKind !== "human")
49000
+ continue;
49001
+ if (!this.senderAccessAllowed(item.authorId))
49002
+ continue;
49003
+ const attachments = item.attachments.map((attachment2) => ({
49004
+ url: attachment2.url,
49005
+ name: attachment2.name ?? "attachment",
49006
+ mimeType: attachment2.mimeType ?? "application/octet-stream",
49007
+ size: attachment2.size ?? 0,
49008
+ ...attachment2.thumbnailUrl ? { thumbnailUrl: attachment2.thumbnailUrl } : {}
49009
+ }));
49010
+ const request = {
49011
+ eventId: item.id,
49012
+ authorPubkey: item.authorId,
49013
+ content: item.body.trim(),
49014
+ attachments,
49015
+ createdAt: item.createdAt,
49016
+ ...item.rootMessageId ? { replyRootId: item.rootMessageId } : {}
49017
+ };
49018
+ const workIntent = isExplicitCornerOpenRequest(item.body);
49019
+ const outcome = await this.replyInRoom(channelId, boundRepo, request, workIntent, editPolicy, void 0, workIntent);
49020
+ if (outcome.producedReply)
49021
+ this.processedRequestIds.add(item.id);
49022
+ }
49023
+ if (inbox.cursor) {
49024
+ cursor3 = inbox.cursor;
49025
+ await this.durableState.setDaemonInboxCursor(channelId, cursor3);
49026
+ }
49027
+ this.onRoomPollSuccess?.(channelId);
49028
+ await this.waitForPoll(opts.pollMs ?? 1e3, opts.signal);
49029
+ } catch (error) {
49030
+ if (opts.signal?.aborted || this.disposed)
49031
+ break;
49032
+ this.onRoomPollFailure?.(channelId, 1e3);
49033
+ console.error(`[body] monolith Room ${channelId} poll failed:`, error);
49034
+ await this.waitForPoll(1e3, opts.signal);
48986
49035
  }
48987
- this.onRoomPollSuccess?.(channelId);
48988
- await this.waitForPoll(opts.pollMs ?? 1e3, opts.signal);
48989
- } catch (error) {
48990
- if (opts.signal?.aborted || this.disposed)
48991
- break;
48992
- this.onRoomPollFailure?.(channelId, 1e3);
48993
- console.error(`[body] monolith Room ${channelId} poll failed:`, error);
48994
- await this.waitForPoll(1e3, opts.signal);
48995
49036
  }
49037
+ } finally {
49038
+ clearInterval(heartbeat);
49039
+ await presenceTail;
49040
+ await postPresence("offline").catch((error) => console.error(`[body] monolith Room ${channelId} shutdown presence failed:`, error));
48996
49041
  }
48997
49042
  }
48998
49043
  /** One long-running body loop owns request discovery, steering, and merge closure. */
@@ -56185,8 +56230,11 @@ async function jsonRequest(url, body, fetchImpl) {
56185
56230
  return response.json();
56186
56231
  }
56187
56232
  function requestConnectGrant(baseUrl, pairingCode, selection, fetchImpl) {
56233
+ const normalizedPairingCode = normalizeAgentPairingCode(pairingCode);
56234
+ if (!normalizedPairingCode)
56235
+ throw new Error("invalid pairing code");
56188
56236
  return jsonRequest(`${baseUrl}/auth/agent/connect`, {
56189
- pairing_code: pairingCode.trim().toUpperCase(),
56237
+ pairing_code: normalizedPairingCode,
56190
56238
  harness: selection.harness,
56191
56239
  ...selection.provider ? { provider: selection.provider } : {},
56192
56240
  model: selection.model,
@@ -56207,7 +56255,10 @@ async function installCurrentRelease(fetchImpl) {
56207
56255
  }
56208
56256
  });
56209
56257
  await activateRelease(layout, releaseId);
56210
- return resolve37(layout.binDir, "beeline");
56258
+ return {
56259
+ binary: resolve37(layout.binDir, "beeline"),
56260
+ version: published.version ?? releaseId
56261
+ };
56211
56262
  }
56212
56263
  function providerEnvironment(selection) {
56213
56264
  if (!selection.provider || !selection.apiKey)
@@ -56267,12 +56318,12 @@ async function runInstalledFinish(binary, grantPath) {
56267
56318
  });
56268
56319
  });
56269
56320
  }
56270
- async function brassSpinner(message2, action) {
56321
+ async function brassSpinner(message2, action, completion) {
56271
56322
  const spinner2 = spinner({ output: clackPromptOutput() });
56272
56323
  spinner2.start(brass(message2));
56273
56324
  try {
56274
56325
  const result = await action();
56275
- spinner2.stop(brass("Done"));
56326
+ spinner2.stop(brass(completion(result)));
56276
56327
  return result;
56277
56328
  } catch (error) {
56278
56329
  spinner2.stop("Failed");
@@ -56286,13 +56337,13 @@ async function runConnectCommand(code, options = {}) {
56286
56337
  intro(brass("Beeline connect"));
56287
56338
  const pairingCode = code?.trim() || await clackPrompts.text({
56288
56339
  message: brass("Pairing code from the app"),
56289
- validate: (value) => value.trim() ? void 0 : "Pairing code is required"
56340
+ validate: (value) => normalizeAgentPairingCode(value) ? void 0 : "Enter the pairing code shown in the app"
56290
56341
  });
56291
56342
  const selection = await collectConnectWizard();
56292
56343
  const fetchImpl = options.fetchImpl ?? fetch;
56293
56344
  const baseUrl = (process.env.BEELINE_AUTH_URL ?? "https://server.usebeeline.app").replace(/\/$/, "");
56294
- const grant = await brassSpinner("Connecting to your Beeline Workspace\u2026", () => requestConnectGrant(baseUrl, pairingCode, selection, fetchImpl));
56295
- const installedBinary = await brassSpinner("Installing the Beeline daemon\u2026", () => installCurrentRelease(fetchImpl));
56345
+ const grant = await brassSpinner("Connecting to your Beeline Workspace\u2026", () => requestConnectGrant(baseUrl, pairingCode, selection, fetchImpl), (connectedGrant) => `Connected to ${connectedGrant.workspace_name}`);
56346
+ const installedRelease = await brassSpinner("Installing the Beeline daemon\u2026", () => installCurrentRelease(fetchImpl), (release) => `Installed Beeline helper ${release.version}`);
56296
56347
  const llmEnvFile = await writeProviderEnv(selection, grant.agent_pubkey);
56297
56348
  const grantPath = resolve37(defaultSupervisorRoot(process.env), "beeline", "connect", `grant-${process.pid}-${Date.now()}.json`);
56298
56349
  await writePrivateJson(grantPath, {
@@ -56309,7 +56360,7 @@ async function runConnectCommand(code, options = {}) {
56309
56360
  daemonExchangeToken: grant.daemon_exchange_token,
56310
56361
  ...llmEnvFile ? { llmEnvFile } : {}
56311
56362
  });
56312
- await brassSpinner("Starting your agent\u2026", () => runInstalledFinish(installedBinary, grantPath));
56363
+ await brassSpinner("Starting your agent\u2026", () => runInstalledFinish(installedRelease.binary, grantPath), () => `Started ${grant.agent_name}`);
56313
56364
  console.log("");
56314
56365
  console.log(`${brass("Agent")} ${grant.agent_name}`);
56315
56366
  console.log(`${brass("Workspace")} ${grant.workspace_name}`);
@@ -57341,7 +57392,7 @@ ${import_picocolors6.default.dim("Usage:")}
57341
57392
  beeline archive <subchannel-uuid> Archive subchannel
57342
57393
  beeline pair <BUZZ-XXXX-XXXX> [options] Pair an agent (optionally to this repo)
57343
57394
  and start its durable daemon
57344
- beeline connect [BUZZ-XXXX-XXXX] Install and connect an app-authorized agent
57395
+ beeline connect [XXXXXXXX-XXXXXXXX] Install and connect an app-authorized agent
57345
57396
  beeline start [agent-pubkey] Start \u2014 or RESTART when already running,
57346
57397
  stopping cleanly after in-flight work \u2014
57347
57398
  this repo's (or, outside a repo, this
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "usebeeline",
3
- "version": "0.0.3",
3
+ "version": "0.0.5",
4
4
  "description": "Connect an AI coding agent to Beeline with one command.",
5
5
  "repository": {
6
6
  "type": "git",