usebeeline 0.0.2 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/usebeeline.mjs +703 -474
  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();
@@ -27744,365 +27996,132 @@ async function findCommunityInvite(http, tokenHash, readerPubkey) {
27744
27996
  return latestInviteRecord(legacy, tokenHash);
27745
27997
  }
27746
27998
  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)));
28066
- }
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));
28070
- }
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));
28075
- }
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));
28079
- }
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));
28083
- }
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));
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
  }
@@ -47718,6 +47747,13 @@ Deliver artifacts from this corner; there is no branch to land.`;
47718
47747
  }
47719
47748
  /** Human decision path retained for a named repository outside the Room binding. */
47720
47749
  async cornerOpenAudience(roomId, requesterPubkey) {
47750
+ if (this.daemonApi) {
47751
+ const authority = await this.daemonApi.execute("getRoomAuthority", {
47752
+ roomId,
47753
+ principalId: requesterPubkey
47754
+ });
47755
+ return authority.member && authority.principalKind === "human" ? [requesterPubkey] : [];
47756
+ }
47721
47757
  const members = await listMembers(this.agentClientContext(), roomId);
47722
47758
  const candidates = members.filter((member2) => member2.pubkey === requesterPubkey || member2.role === "admin" || member2.role === "owner");
47723
47759
  const checked = await Promise.all(candidates.map(async (member2) => ({
@@ -47756,9 +47792,10 @@ Deliver artifacts from this corner; there is no branch to land.`;
47756
47792
  message: published.message
47757
47793
  };
47758
47794
  }
47759
- const permissionId = randomUUID5();
47795
+ const permissionId = this.daemonApi ? createHash10("sha256").update(`corner-permission\0${input.roomId}\0${input.request.eventId}`).digest("hex") : randomUUID5();
47760
47796
  const repository2 = input.roomRepo ? this.repoId(input.roomRepo) : "repo-less";
47761
- const audience = await this.cornerOpenAudience(input.roomId, input.request.authorPubkey);
47797
+ const principalId = input.request.delegation?.rootHumanPubkey ?? input.request.authorPubkey;
47798
+ const audience = await this.cornerOpenAudience(input.roomId, principalId);
47762
47799
  if (audience.length === 0) {
47763
47800
  throw new AgentToolKnownFailure("approval_audience_unavailable", "No eligible human is available to decide this corner request.", true);
47764
47801
  }
@@ -47766,7 +47803,18 @@ Deliver artifacts from this corner; there is no branch to land.`;
47766
47803
  const requester = requesterAttribution?.handle ?? fallbackPersonName(input.request.authorPubkey);
47767
47804
  const agent = (await this.roomAuthorAttributions(input.roomId, [this.agentIdentity.publicKey])).get(this.agentIdentity.publicKey)?.name ?? fallbackAgentName(this.agentIdentity.publicKey);
47768
47805
  const message2 = `@${requester.replace(/^@/, "")} asked ${agent} to open a corner for: ` + input.objective;
47769
- const card = buildControlMessage("permission-request", input.roomId, this.agentIdentity, message2, [
47806
+ const card = this.daemonApi ? await this.daemonApi.execute("postPermissionRequest", {
47807
+ roomId: input.roomId,
47808
+ principalId,
47809
+ permissionId,
47810
+ requestId: input.request.eventId,
47811
+ scope: {
47812
+ type: "operation.execute",
47813
+ connectorId: input.tool,
47814
+ target: repository2,
47815
+ payloadDigest: createHash10("sha256").update(input.objective).digest("hex")
47816
+ }
47817
+ }) : buildControlMessage("permission-request", input.roomId, this.agentIdentity, message2, [
47770
47818
  ["t", WRITE_PERMISSION_REQUEST_TAG],
47771
47819
  ["permission", permissionId],
47772
47820
  ["request", input.request.eventId],
@@ -47779,7 +47827,8 @@ Deliver artifacts from this corner; there is no branch to land.`;
47779
47827
  ...this.delegatedReplyTags(input.request),
47780
47828
  ...audience.map((pubkey2) => ["p", pubkey2])
47781
47829
  ]);
47782
- await publishEvent2(card, this.agentIdentity);
47830
+ if (!this.daemonApi)
47831
+ await publishEvent2(card, this.agentIdentity);
47783
47832
  void this.finishCornerApproval({ ...input, permissionId, repository: repository2, audience }).catch((error) => console.error("[body] corner approval settlement failed:", error));
47784
47833
  return { request_id: permissionId, event_id: card.id, message: message2 };
47785
47834
  })();
@@ -47792,6 +47841,8 @@ Deliver artifacts from this corner; there is no branch to land.`;
47792
47841
  * the signed pending card already authored for this exact member request.
47793
47842
  */
47794
47843
  async publishedCornerApproval(input) {
47844
+ if (this.daemonApi)
47845
+ return void 0;
47795
47846
  const repository2 = input.roomRepo ? this.repoId(input.roomRepo) : "repo-less";
47796
47847
  const events = await this.agentRelay.queryEvents([
47797
47848
  {
@@ -47811,9 +47862,11 @@ Deliver artifacts from this corner; there is no branch to land.`;
47811
47862
  return { permissionId, eventId: event.id, message: event.content, repository: repository2, audience };
47812
47863
  }
47813
47864
  async finishCornerApproval(input) {
47865
+ const principalId = input.request.delegation?.rootHumanPubkey ?? input.request.authorPubkey;
47814
47866
  let deciderPubkey;
47815
47867
  const decision = await this.waitForWritePermissionDecision(input.roomId, input.permissionId, input.request.eventId, input.repository, 10 * 6e4, {
47816
47868
  allowedResponders: new Set(input.audience),
47869
+ principalId,
47817
47870
  captureDecider: (pubkey2) => {
47818
47871
  deciderPubkey = pubkey2;
47819
47872
  }
@@ -47823,44 +47876,61 @@ Deliver artifacts from this corner; there is no branch to land.`;
47823
47876
  if (decision === "allow") {
47824
47877
  try {
47825
47878
  const info = await this.openSubchannelForRequest(input.roomId, input.roomRepo, input.objective, input.request, { objective: input.objective, suppressOpenCard: true });
47826
- await this.postWritePermissionStatus(input.roomId, input.permissionId, input.request.eventId, input.tool, input.repository, "allowed", `Corner approved by @${deciderHandle.replace(/^@/, "")} \u2014 view \u2192`, info.subchannelId, deciderPubkey, input.request.authorPubkey);
47879
+ await this.postWritePermissionStatus(input.roomId, input.permissionId, input.request.eventId, input.tool, input.repository, "allowed", `Corner approved by @${deciderHandle.replace(/^@/, "")} \u2014 view \u2192`, info.subchannelId, deciderPubkey, principalId);
47827
47880
  this.startCornerTaskOnce(info, input.objective, cornerOpenTaskPrompt(info.taskDescription, input.objective), {
47828
47881
  requestId: input.request.eventId,
47829
47882
  originalRequestId: input.request.eventId,
47830
47883
  cause: "corner-opening"
47831
47884
  });
47832
47885
  } catch (error) {
47833
- await this.postWritePermissionStatus(input.roomId, input.permissionId, input.request.eventId, input.tool, input.repository, "failed", `Corner approved by @${deciderHandle.replace(/^@/, "")}, but it could not start: ${this.safePermissionFailure(error)}`, void 0, deciderPubkey, input.request.authorPubkey);
47886
+ await this.postWritePermissionStatus(input.roomId, input.permissionId, input.request.eventId, input.tool, input.repository, "failed", `Corner approved by @${deciderHandle.replace(/^@/, "")}, but it could not start: ${this.safePermissionFailure(error)}`, void 0, deciderPubkey, principalId);
47834
47887
  }
47835
47888
  return;
47836
47889
  }
47837
- await this.postWritePermissionStatus(input.roomId, input.permissionId, input.request.eventId, input.tool, input.repository, decision === "deny" ? "denied" : "expired", decision === "deny" ? `Corner denied by @${deciderHandle.replace(/^@/, "")}.` : "The corner request expired without a decision.", void 0, deciderPubkey, input.request.authorPubkey);
47890
+ await this.postWritePermissionStatus(input.roomId, input.permissionId, input.request.eventId, input.tool, input.repository, decision === "deny" ? "denied" : "expired", decision === "deny" ? `Corner denied by @${deciderHandle.replace(/^@/, "")}.` : "The corner request expired without a decision.", void 0, deciderPubkey, principalId);
47838
47891
  }
47839
47892
  async requestEditCornerApproval(input) {
47840
47893
  const { tlcChannelId, turn, repository: repository2, tool, objective, namedTarget, pendingMessage } = input;
47841
- const permissionId = randomUUID5();
47842
- const audience = await this.cornerOpenAudience(tlcChannelId, turn.request.authorPubkey);
47894
+ const permissionId = this.daemonApi ? createHash10("sha256").update(`edit-permission\0${tlcChannelId}\0${turn.request.eventId}`).digest("hex") : randomUUID5();
47895
+ const principalId = turn.request.delegation?.rootHumanPubkey ?? turn.request.authorPubkey;
47896
+ const audience = await this.cornerOpenAudience(tlcChannelId, principalId);
47843
47897
  if (audience.length === 0) {
47844
47898
  throw new AgentToolKnownFailure("approval_audience_unavailable", "No eligible human is available to decide this corner request.", true);
47845
47899
  }
47846
- const requesterAttribution = turn.request.delegation ? (await this.roomAuthorAttributions(tlcChannelId, [turn.request.authorPubkey])).get(turn.request.authorPubkey) : turn.request.authorAttribution;
47847
- const requester = requesterAttribution?.handle ?? fallbackPersonName(turn.request.authorPubkey);
47848
- await postControlMessage("permission-request", tlcChannelId, this.agentIdentity, `@${requester.replace(/^@/, "")} asked ${this.agentIdentity.name || "the agent"} to open a corner for: ${objective || pendingMessage}`, [
47849
- ["t", WRITE_PERMISSION_REQUEST_TAG],
47850
- ["permission", permissionId],
47851
- ["request", turn.request.eventId],
47852
- ["requester", turn.request.authorPubkey],
47853
- ["agent", this.agentIdentity.publicKey],
47854
- ...audience.map((pubkey2) => ["p", pubkey2]),
47855
- ["tool", tool],
47856
- ["repo", repository2],
47857
- ["objective", objective],
47858
- ["status", "pending"],
47859
- ...this.delegatedReplyTags(turn.request)
47860
- ]);
47900
+ const requesterAttribution = turn.request.delegation ? (await this.roomAuthorAttributions(tlcChannelId, [principalId])).get(principalId) : turn.request.authorAttribution;
47901
+ const requester = requesterAttribution?.handle ?? fallbackPersonName(principalId);
47902
+ if (this.daemonApi) {
47903
+ await this.daemonApi.execute("postPermissionRequest", {
47904
+ roomId: tlcChannelId,
47905
+ principalId,
47906
+ permissionId,
47907
+ requestId: turn.request.eventId,
47908
+ scope: {
47909
+ type: "operation.execute",
47910
+ connectorId: tool,
47911
+ target: repository2,
47912
+ payloadDigest: createHash10("sha256").update(objective || pendingMessage).digest("hex")
47913
+ }
47914
+ });
47915
+ } else {
47916
+ await postControlMessage("permission-request", tlcChannelId, this.agentIdentity, `@${requester.replace(/^@/, "")} asked ${this.agentIdentity.name || "the agent"} to open a corner for: ${objective || pendingMessage}`, [
47917
+ ["t", WRITE_PERMISSION_REQUEST_TAG],
47918
+ ["permission", permissionId],
47919
+ ["request", turn.request.eventId],
47920
+ ["requester", turn.request.authorPubkey],
47921
+ ["agent", this.agentIdentity.publicKey],
47922
+ ...audience.map((pubkey2) => ["p", pubkey2]),
47923
+ ["tool", tool],
47924
+ ["repo", repository2],
47925
+ ["objective", objective],
47926
+ ["status", "pending"],
47927
+ ...this.delegatedReplyTags(turn.request)
47928
+ ]);
47929
+ }
47861
47930
  let deciderPubkey;
47862
47931
  const decision = await this.waitForWritePermissionDecision(tlcChannelId, permissionId, turn.request.eventId, repository2, 10 * 6e4, {
47863
47932
  allowedResponders: new Set(audience),
47933
+ principalId,
47864
47934
  captureDecider: (pubkey2) => {
47865
47935
  deciderPubkey = pubkey2;
47866
47936
  }
@@ -47876,7 +47946,7 @@ Deliver artifacts from this corner; there is no branch to land.`;
47876
47946
  suppressOpenCard: true
47877
47947
  }) : await this.openSubchannel(tlcChannelId, boundRepo, objective, { ...turn.request, content: objective }, { objective, suppressOpenCard: true });
47878
47948
  turn.transitionedToCorner = true;
47879
- await this.postWritePermissionStatus(tlcChannelId, permissionId, turn.request.eventId, tool, repository2, "allowed", `Corner approved by @${deciderHandle.replace(/^@/, "")} \u2014 view \u2192`, info.subchannelId, deciderPubkey, turn.request.authorPubkey).catch((statusError) => console.error("[body] failed to publish direct corner navigation:", statusError));
47949
+ await this.postWritePermissionStatus(tlcChannelId, permissionId, turn.request.eventId, tool, repository2, "allowed", `Corner approved by @${deciderHandle.replace(/^@/, "")} \u2014 view \u2192`, info.subchannelId, deciderPubkey, principalId).catch((statusError) => console.error("[body] failed to publish direct corner navigation:", statusError));
47880
47950
  this.startCornerTaskOnce(info, objective, cornerOpenTaskPrompt(info.taskDescription, objective), {
47881
47951
  requestId: turn.request.eventId,
47882
47952
  originalRequestId: turn.request.eventId,
@@ -47889,10 +47959,10 @@ Deliver artifacts from this corner; there is no branch to land.`;
47889
47959
  return;
47890
47960
  }
47891
47961
  if (decision === "deny") {
47892
- await this.postWritePermissionStatus(tlcChannelId, permissionId, turn.request.eventId, tool, repository2, "denied", `Corner denied by @${deciderHandle.replace(/^@/, "")}.`, void 0, deciderPubkey, turn.request.authorPubkey);
47962
+ await this.postWritePermissionStatus(tlcChannelId, permissionId, turn.request.eventId, tool, repository2, "denied", `Corner denied by @${deciderHandle.replace(/^@/, "")}.`, void 0, deciderPubkey, principalId);
47893
47963
  return;
47894
47964
  }
47895
- await this.postWritePermissionStatus(tlcChannelId, permissionId, turn.request.eventId, tool, repository2, "expired", `The edit request for ${repository2} expired. The Agent remains read-only.`, void 0, void 0, turn.request.authorPubkey);
47965
+ await this.postWritePermissionStatus(tlcChannelId, permissionId, turn.request.eventId, tool, repository2, "expired", `The edit request for ${repository2} expired. The Agent remains read-only.`, void 0, void 0, principalId);
47896
47966
  }
47897
47967
  permissionToolLabel(permission) {
47898
47968
  const title = permission.toolCall?.title?.trim();
@@ -48203,6 +48273,26 @@ Deliver artifacts from this corner; there is no branch to land.`;
48203
48273
  return summarizeGitFailure(raw).replace(/https?:\/\/\S+/gi, "the configured remote").replace(/(?:[A-Za-z0-9._~+/=-]+):(?:[A-Za-z0-9._~+/=-]+)@/g, "[credentials]@").replace(/\s+/g, " ").trim().slice(0, 240) || "the repository could not be cloned or accessed";
48204
48274
  }
48205
48275
  postWritePermissionStatus(tlcChannelId, permissionId, requestId, tool, repository2, status, message2, subchannelId, deciderPubkey, requesterPubkey) {
48276
+ if (this.daemonApi) {
48277
+ const publishStatus = async () => {
48278
+ if (requesterPubkey && (status === "allowed" || status === "failed" || status === "expired")) {
48279
+ await this.daemonApi.execute("postPermissionExecution", {
48280
+ roomId: tlcChannelId,
48281
+ principalId: requesterPubkey,
48282
+ permissionId,
48283
+ status: status === "allowed" ? "succeeded" : "failed",
48284
+ result: message2
48285
+ });
48286
+ }
48287
+ await this.daemonApi.execute("postRoomMessage", {
48288
+ roomId: tlcChannelId,
48289
+ requestId,
48290
+ text: message2,
48291
+ presentation: "system"
48292
+ });
48293
+ };
48294
+ return publishStatus();
48295
+ }
48206
48296
  return postControlMessage("permission-status", tlcChannelId, this.agentIdentity, message2, [
48207
48297
  ["t", WRITE_PERMISSION_REQUEST_TAG],
48208
48298
  ["permission", permissionId],
@@ -48227,6 +48317,53 @@ Deliver artifacts from this corner; there is no branch to land.`;
48227
48317
  * pending decision until timeout.
48228
48318
  */
48229
48319
  async waitForWritePermissionDecision(tlcChannelId, permissionId, requestId, repository2, timeoutMs = 10 * 6e4, options = {}) {
48320
+ if (this.daemonApi) {
48321
+ if (!options.principalId)
48322
+ throw new Error("monolith permission wait requires a principal");
48323
+ const deadline2 = Date.now() + timeoutMs;
48324
+ return new Promise((resolvePromise, rejectPromise) => {
48325
+ let settled = false;
48326
+ let polling = false;
48327
+ const finish = (result) => {
48328
+ if (settled)
48329
+ return;
48330
+ settled = true;
48331
+ clearTimeout(timer);
48332
+ clearInterval(backstop);
48333
+ resolvePromise(result);
48334
+ };
48335
+ const pollOnce = async () => {
48336
+ if (settled || polling)
48337
+ return;
48338
+ polling = true;
48339
+ try {
48340
+ const authority = await this.daemonApi.execute("getPermissionAuthority", {
48341
+ roomId: tlcChannelId,
48342
+ principalId: options.principalId,
48343
+ permissionId
48344
+ });
48345
+ if (authority.status === "authorized")
48346
+ finish("allow");
48347
+ if (authority.status === "denied")
48348
+ finish("deny");
48349
+ } catch (error) {
48350
+ if (!isTransientPermissionPollError(error)) {
48351
+ settled = true;
48352
+ clearTimeout(timer);
48353
+ clearInterval(backstop);
48354
+ rejectPromise(error);
48355
+ }
48356
+ } finally {
48357
+ polling = false;
48358
+ }
48359
+ };
48360
+ const timer = setTimeout(() => finish("timeout"), Math.max(0, deadline2 - Date.now()));
48361
+ timer.unref?.();
48362
+ const backstop = setInterval(() => void pollOnce(), WRITE_PERMISSION_BACKSTOP_POLL_MS);
48363
+ backstop.unref?.();
48364
+ void pollOnce();
48365
+ });
48366
+ }
48230
48367
  const startedAt = Math.floor(Date.now() / 1e3) - 1;
48231
48368
  const deadline = Date.now() + timeoutMs;
48232
48369
  const matchingDecision = async (event) => {
@@ -48819,72 +48956,88 @@ Deliver artifacts from this corner; there is no branch to land.`;
48819
48956
  async runMonolithRoomLoop(channelId, boundRepo, editPolicy, opts) {
48820
48957
  const api = this.daemonApi;
48821
48958
  let cursor3 = await this.durableState.daemonInboxCursor(channelId);
48822
- await api.execute("postAgentPresence", {
48823
- agentId: this.agentIdentity.publicKey,
48824
- roomId: channelId,
48825
- status: this.config.modelUnavailable ? "offline" : "online"
48826
- });
48827
- if (!cursor3) {
48828
- 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,
48829
48963
  roomId: channelId,
48830
- startAtLatest: true
48964
+ status
48831
48965
  });
48832
- if (activation.cursor) {
48833
- cursor3 = activation.cursor;
48834
- await this.durableState.setDaemonInboxCursor(channelId, cursor3);
48835
- }
48836
- }
48837
- while (!opts.signal?.aborted && !this.disposed) {
48838
- try {
48839
- 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", {
48840
48977
  roomId: channelId,
48841
- ...cursor3 ? { after: cursor3 } : {},
48842
- limit: 200
48978
+ startAtLatest: true
48843
48979
  });
48844
- for (const item of inbox.items) {
48845
- if (item.authorId === this.agentIdentity.publicKey || item.type !== "message" || item.mentionIds.length > 0 && !item.mentionIds.includes(this.agentIdentity.publicKey) || this.processedRequestIds.has(item.id))
48846
- continue;
48847
- 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", {
48848
48988
  roomId: channelId,
48849
- principalId: item.authorId
48989
+ ...cursor3 ? { after: cursor3 } : {},
48990
+ limit: 200
48850
48991
  });
48851
- if (!authority.member || authority.principalKind !== "human")
48852
- continue;
48853
- if (!this.senderAccessAllowed(item.authorId))
48854
- continue;
48855
- const attachments = item.attachments.map((attachment2) => ({
48856
- url: attachment2.url,
48857
- name: attachment2.name ?? "attachment",
48858
- mimeType: attachment2.mimeType ?? "application/octet-stream",
48859
- size: attachment2.size ?? 0,
48860
- ...attachment2.thumbnailUrl ? { thumbnailUrl: attachment2.thumbnailUrl } : {}
48861
- }));
48862
- const request = {
48863
- eventId: item.id,
48864
- authorPubkey: item.authorId,
48865
- content: item.body.trim(),
48866
- attachments,
48867
- createdAt: item.createdAt,
48868
- ...item.rootMessageId ? { replyRootId: item.rootMessageId } : {}
48869
- };
48870
- const workIntent = !isReadOnlyInformationRequest(item.body);
48871
- const outcome = await this.replyInRoom(channelId, boundRepo, request, editPolicy === "repository" && workIntent, editPolicy, void 0, workIntent);
48872
- if (outcome.producedReply)
48873
- this.processedRequestIds.add(item.id);
48874
- }
48875
- if (inbox.cursor) {
48876
- cursor3 = inbox.cursor;
48877
- 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);
48878
49035
  }
48879
- this.onRoomPollSuccess?.(channelId);
48880
- await this.waitForPoll(opts.pollMs ?? 1e3, opts.signal);
48881
- } catch (error) {
48882
- if (opts.signal?.aborted || this.disposed)
48883
- break;
48884
- this.onRoomPollFailure?.(channelId, 1e3);
48885
- console.error(`[body] monolith Room ${channelId} poll failed:`, error);
48886
- await this.waitForPoll(1e3, opts.signal);
48887
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));
48888
49041
  }
48889
49042
  }
48890
49043
  /** One long-running body loop owns request discovery, steering, and merge closure. */
@@ -51176,6 +51329,55 @@ async function assertRuntimeStorageWritable(supervisorRoot, agentPubkey) {
51176
51329
  await rm7(probe, { force: true }).catch(() => void 0);
51177
51330
  }
51178
51331
  }
51332
+ async function stageMonolithAgentRuntime(input) {
51333
+ const supervisorRoot = input.supervisorRoot ? resolve28(input.supervisorRoot) : defaultSupervisorRoot(input.env);
51334
+ const baseUrl = new URL(input.monolithBaseUrl).origin;
51335
+ if (baseUrl !== input.monolithBaseUrl || !/^https?:$/.test(new URL(baseUrl).protocol)) {
51336
+ throw new Error("monolith base URL must be an HTTP or HTTPS origin");
51337
+ }
51338
+ if (!/^bde_[A-Za-z0-9_-]{43}$/.test(input.daemonExchangeToken)) {
51339
+ throw new Error("daemon exchange token is invalid");
51340
+ }
51341
+ const configPath = resolve28(runtimeDirectory(supervisorRoot, input.agentIdentity.publicKey), "runtime.json");
51342
+ if (await agentRuntimeExists(supervisorRoot, input.agentIdentity.publicKey)) {
51343
+ const existing = await readRuntimeRecord(configPath);
51344
+ const transport = existing.transport;
51345
+ const sameRuntime = existing.communityId === input.workspaceId && existing.pairedBy === input.pairedBy && existing.agent.publicKey === input.agentIdentity.publicKey && existing.agent.secretKeyHex === Buffer.from(input.agentIdentity.secretKey).toString("hex") && existing.body.publicKey === input.bodyIdentity.publicKey && transport?.kind === "monolith" && transport.baseUrl === baseUrl && ("daemonToken" in transport || transport.exchangeToken === input.daemonExchangeToken);
51346
+ if (!sameRuntime) {
51347
+ throw new Error(`agent identity ${input.agentIdentity.publicKey} already has another runtime`);
51348
+ }
51349
+ return { runtime: existing, configPath };
51350
+ }
51351
+ await assertRuntimeStorageWritable(supervisorRoot, input.agentIdentity.publicKey);
51352
+ const runtime = {
51353
+ version: 2,
51354
+ communityId: input.workspaceId,
51355
+ pairedBy: input.pairedBy,
51356
+ agent: storeIdentity(input.agentIdentity, DEFAULT_AGENT_IDENTITY_NAME),
51357
+ body: storeIdentity(input.bodyIdentity, DEFAULT_BODY_IDENTITY_NAME),
51358
+ rooms: [],
51359
+ supervisorRoot,
51360
+ // Required only by legacy records. Monolith runtimes never construct a
51361
+ // relay client, so retaining the server origin here cannot route traffic.
51362
+ relayBaseUrl: baseUrl,
51363
+ transport: {
51364
+ kind: "monolith",
51365
+ baseUrl,
51366
+ exchangeToken: input.daemonExchangeToken
51367
+ },
51368
+ ...input.llmEnvFile ? { llmEnvFile: input.llmEnvFile } : {},
51369
+ accessPolicy: DEFAULT_ACCESS_POLICY,
51370
+ ...input.modelSelection?.model || input.modelSelection?.effort ? { modelSelection: input.modelSelection } : {},
51371
+ agentKind: input.agentKind,
51372
+ agentCommand: input.agentCommand,
51373
+ agentArgs: [...input.agentArgs ?? []],
51374
+ agentBinary: input.agentBinary,
51375
+ mcpBinary: input.mcpBinary,
51376
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
51377
+ };
51378
+ const writtenPath = await writeRuntimeRecord(runtime);
51379
+ return { runtime, configPath: writtenPath };
51380
+ }
51179
51381
  async function writeRuntimePointer(gitCommonDir, agentPubkey, targetConfigPath) {
51180
51382
  const directory = runtimeDirectory(gitCommonDir, agentPubkey);
51181
51383
  const path = resolve28(directory, "runtime.json");
@@ -55703,33 +55905,49 @@ async function pairOneAgent(input) {
55703
55905
  throw error;
55704
55906
  }
55705
55907
  }
55706
- async function completeDevicePairing(grant) {
55707
- const selectedAgent = await selectPairAgentCommand({
55908
+ async function completeDevicePairing(grant, options = {}) {
55909
+ const selectedAgent = options.selectedAgent ?? await selectPairAgentCommand({
55708
55910
  explicitKind: grant.harness,
55709
55911
  env: process.env,
55710
55912
  cwd: process.cwd(),
55711
55913
  interactive: true,
55712
55914
  confirmInstall: async () => true
55713
55915
  });
55714
- const result = await pairOneAgent({
55715
- code: grant.pairingCode,
55716
- selectedAgent,
55717
- agentIdentity: identityFromKey(grant.agentSecretKey, grant.agentName),
55718
- bodyIdentity: identityFromKey(grant.bodySecretKey, DEFAULT_BODY_IDENTITY_NAME),
55719
- cwd: process.cwd(),
55720
- repo: null,
55721
- progressLabel: "Connecting agent\u2026",
55722
- progressDone: (pid) => `Connected (pid ${pid}).`,
55916
+ const localConfig = options.localConfig ?? loadBodyConfig({
55917
+ workspaceRoot: process.cwd(),
55918
+ ...grant.llmEnvFile ? { llmEnvFile: grant.llmEnvFile } : {},
55919
+ agent: selectedAgent
55920
+ });
55921
+ await (options.validateSelection ?? validateModelSelection)(selectedAgent, localConfig.agentEnv, {
55922
+ model: grant.model
55923
+ });
55924
+ const agentIdentity = identityFromKey(grant.agentSecretKey, grant.agentName);
55925
+ const staged = await stageMonolithAgentRuntime({
55926
+ workspaceId: grant.workspaceId,
55927
+ pairedBy: grant.pairedBy,
55928
+ monolithBaseUrl: grant.monolithBaseUrl,
55929
+ daemonExchangeToken: grant.daemonExchangeToken,
55723
55930
  ...grant.llmEnvFile ? { llmEnvFile: grant.llmEnvFile } : {},
55724
- access: "creator",
55931
+ agentBinary: localConfig.agentBinary,
55932
+ agentKind: selectedAgent.kind,
55933
+ agentCommand: selectedAgent.command,
55934
+ agentArgs: selectedAgent.args,
55725
55935
  modelSelection: { model: grant.model },
55726
- agentProfile: { displayName: grant.agentName, personality: grant.soul },
55727
- interactiveUi: false
55936
+ mcpBinary: localConfig.mcpBinary,
55937
+ agentIdentity,
55938
+ bodyIdentity: identityFromKey(grant.bodySecretKey, DEFAULT_BODY_IDENTITY_NAME),
55939
+ ...options.supervisorRoot ? { supervisorRoot: options.supervisorRoot } : {}
55728
55940
  });
55729
- if (result.pairing.communityId !== grant.workspaceId) {
55730
- throw new Error("approved Workspace did not match the pairing grant");
55941
+ const activated = await activateDaemonTransport(staged.configPath, options.fetchImpl);
55942
+ if (!activated)
55943
+ throw new Error("monolith daemon transport activation failed");
55944
+ let pid;
55945
+ try {
55946
+ pid = await (options.launch ?? (async (configPath, publicKey) => process.platform === "linux" && process.env.BEELINE_SYSTEMD_USER !== "0" ? installAgentService(publicKey) : launchRuntimeDaemon(configPath)))(staged.configPath, agentIdentity.publicKey);
55947
+ } catch (error) {
55948
+ throw new Error(`agent ${agentIdentity.publicKey} is connected, but its daemon did not start: ${error instanceof Error ? error.message : String(error)}. Run \`beeline start --agent ${agentIdentity.publicKey}\`.`, { cause: error });
55731
55949
  }
55732
- return result;
55950
+ return { runtime: activated.runtime, configPath: staged.configPath, pid };
55733
55951
  }
55734
55952
  function printPairResult(result) {
55735
55953
  console.log(`[buzz] paired agent ${import_picocolors3.default.bold(result.pairing.agent.displayName)}`);
@@ -56012,8 +56230,11 @@ async function jsonRequest(url, body, fetchImpl) {
56012
56230
  return response.json();
56013
56231
  }
56014
56232
  function requestConnectGrant(baseUrl, pairingCode, selection, fetchImpl) {
56233
+ const normalizedPairingCode = normalizeAgentPairingCode(pairingCode);
56234
+ if (!normalizedPairingCode)
56235
+ throw new Error("invalid pairing code");
56015
56236
  return jsonRequest(`${baseUrl}/auth/agent/connect`, {
56016
- pairing_code: pairingCode.trim().toUpperCase(),
56237
+ pairing_code: normalizedPairingCode,
56017
56238
  harness: selection.harness,
56018
56239
  ...selection.provider ? { provider: selection.provider } : {},
56019
56240
  model: selection.model,
@@ -56113,7 +56334,7 @@ async function runConnectCommand(code, options = {}) {
56113
56334
  intro(brass("Beeline connect"));
56114
56335
  const pairingCode = code?.trim() || await clackPrompts.text({
56115
56336
  message: brass("Pairing code from the app"),
56116
- validate: (value) => value.trim() ? void 0 : "Pairing code is required"
56337
+ validate: (value) => normalizeAgentPairingCode(value) ? void 0 : "Enter the pairing code shown in the app"
56117
56338
  });
56118
56339
  const selection = await collectConnectWizard();
56119
56340
  const fetchImpl = options.fetchImpl ?? fetch;
@@ -56123,7 +56344,6 @@ async function runConnectCommand(code, options = {}) {
56123
56344
  const llmEnvFile = await writeProviderEnv(selection, grant.agent_pubkey);
56124
56345
  const grantPath = resolve37(defaultSupervisorRoot(process.env), "beeline", "connect", `grant-${process.pid}-${Date.now()}.json`);
56125
56346
  await writePrivateJson(grantPath, {
56126
- pairingCode: grant.pairing_code,
56127
56347
  agentSecretKey: grant.agent_secret_key,
56128
56348
  bodySecretKey: grant.body_secret_key,
56129
56349
  agentName: grant.agent_name,
@@ -56132,6 +56352,9 @@ async function runConnectCommand(code, options = {}) {
56132
56352
  soul: grant.soul,
56133
56353
  workspaceId: grant.workspace_id,
56134
56354
  workspaceName: grant.workspace_name,
56355
+ pairedBy: grant.paired_by,
56356
+ monolithBaseUrl: baseUrl,
56357
+ daemonExchangeToken: grant.daemon_exchange_token,
56135
56358
  ...llmEnvFile ? { llmEnvFile } : {}
56136
56359
  });
56137
56360
  await brassSpinner("Starting your agent\u2026", () => runInstalledFinish(installedBinary, grantPath));
@@ -56144,7 +56367,13 @@ function isDevicePairingGrant(value) {
56144
56367
  if (!value || typeof value !== "object")
56145
56368
  return false;
56146
56369
  const grant = value;
56147
- return typeof grant.pairingCode === "string" && typeof grant.agentSecretKey === "string" && /^[0-9a-f]{64}$/.test(grant.agentSecretKey) && typeof grant.bodySecretKey === "string" && /^[0-9a-f]{64}$/.test(grant.bodySecretKey) && typeof grant.agentName === "string" && CONNECT_HARNESSES.includes(grant.harness) && typeof grant.model === "string" && typeof grant.soul === "string" && typeof grant.workspaceId === "string" && typeof grant.workspaceName === "string";
56370
+ let monolithOrigin = "";
56371
+ try {
56372
+ monolithOrigin = new URL(grant.monolithBaseUrl ?? "").origin;
56373
+ } catch {
56374
+ return false;
56375
+ }
56376
+ return typeof grant.agentSecretKey === "string" && /^[0-9a-f]{64}$/.test(grant.agentSecretKey) && typeof grant.bodySecretKey === "string" && /^[0-9a-f]{64}$/.test(grant.bodySecretKey) && typeof grant.agentName === "string" && CONNECT_HARNESSES.includes(grant.harness) && typeof grant.model === "string" && typeof grant.soul === "string" && typeof grant.workspaceId === "string" && typeof grant.workspaceName === "string" && typeof grant.pairedBy === "string" && /^[0-9a-f]{64}$/.test(grant.pairedBy) && typeof grant.monolithBaseUrl === "string" && grant.monolithBaseUrl === monolithOrigin && /^https?:$/.test(new URL(monolithOrigin).protocol) && typeof grant.daemonExchangeToken === "string" && /^bde_[A-Za-z0-9_-]{43}$/.test(grant.daemonExchangeToken);
56148
56377
  }
56149
56378
  async function runConnectFinishCommand(path) {
56150
56379
  if (!path)
@@ -57160,7 +57389,7 @@ ${import_picocolors6.default.dim("Usage:")}
57160
57389
  beeline archive <subchannel-uuid> Archive subchannel
57161
57390
  beeline pair <BUZZ-XXXX-XXXX> [options] Pair an agent (optionally to this repo)
57162
57391
  and start its durable daemon
57163
- beeline connect [BUZZ-XXXX-XXXX] Install and connect an app-authorized agent
57392
+ beeline connect [XXXXXXXX-XXXXXXXX] Install and connect an app-authorized agent
57164
57393
  beeline start [agent-pubkey] Start \u2014 or RESTART when already running,
57165
57394
  stopping cleanly after in-flight work \u2014
57166
57395
  this repo's (or, outside a repo, this