usebeeline 0.0.3 → 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.
- package/dist/usebeeline.mjs +538 -490
- package/package.json +1 -1
package/dist/usebeeline.mjs
CHANGED
|
@@ -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();
|
|
@@ -27677,432 +27929,199 @@ async function attachCommunityMemberToChannel(ctx, channelId, memberPubkey, comm
|
|
|
27677
27929
|
}
|
|
27678
27930
|
const membershipSince = now3();
|
|
27679
27931
|
await setMemberRole(ctx, channelId, memberPubkey, "member", {
|
|
27680
|
-
extraTags: [
|
|
27681
|
-
[TAG_COMMUNITY, communityId],
|
|
27682
|
-
["member-invite", memberPubkey]
|
|
27683
|
-
]
|
|
27684
|
-
});
|
|
27685
|
-
await waitUntilMember(ctx, channelId, memberPubkey);
|
|
27686
|
-
return { joined: true, membershipSince };
|
|
27687
|
-
}
|
|
27688
|
-
function inviteExpiry(options, createdAt) {
|
|
27689
|
-
if (options?.expiresAt !== void 0 && options.expiresInSeconds !== void 0) {
|
|
27690
|
-
throw new Error("set either expiresAt or expiresInSeconds, not both");
|
|
27691
|
-
}
|
|
27692
|
-
const expiresAt = options?.expiresAt ?? createdAt + (options?.expiresInSeconds ?? DEFAULT_INVITE_TTL_SECONDS);
|
|
27693
|
-
if (!Number.isSafeInteger(expiresAt) || expiresAt <= createdAt) {
|
|
27694
|
-
throw new Error("invite expiry must be a future Unix timestamp");
|
|
27695
|
-
}
|
|
27696
|
-
return expiresAt;
|
|
27697
|
-
}
|
|
27698
|
-
function parseCommunityInvite(event) {
|
|
27699
|
-
if (event.kind !== KIND_COMMUNITY_INVITE && event.kind !== KIND_STREAM_MESSAGE || !verifyEvent2(event)) {
|
|
27700
|
-
return null;
|
|
27701
|
-
}
|
|
27702
|
-
if (!tagValues(event, "t").includes(TAG_COMMUNITY_INVITE))
|
|
27703
|
-
return null;
|
|
27704
|
-
const tokenHash = tagValue(event, "d");
|
|
27705
|
-
const communityId = tagValue(event, "h");
|
|
27706
|
-
const communityTag = tagValue(event, TAG_COMMUNITY);
|
|
27707
|
-
const expiresRaw = tagValue(event, "expiration");
|
|
27708
|
-
const expiresAt = expiresRaw === void 0 ? NaN : Number(expiresRaw);
|
|
27709
|
-
const revoked = tagValue(event, "revoked") === "true";
|
|
27710
|
-
if (!tokenHash || !/^[0-9a-f]{64}$/.test(tokenHash))
|
|
27711
|
-
return null;
|
|
27712
|
-
if (!communityId || communityTag !== communityId)
|
|
27713
|
-
return null;
|
|
27714
|
-
if (!Number.isSafeInteger(expiresAt) || expiresAt <= event.created_at)
|
|
27715
|
-
return null;
|
|
27716
|
-
return {
|
|
27717
|
-
tokenHash,
|
|
27718
|
-
communityId,
|
|
27719
|
-
expiresAt,
|
|
27720
|
-
mintedBy: event.pubkey,
|
|
27721
|
-
...revoked ? { revoked: true } : {},
|
|
27722
|
-
event
|
|
27723
|
-
};
|
|
27724
|
-
}
|
|
27725
|
-
function latestInviteRecord(events, tokenHash) {
|
|
27726
|
-
const record2 = events.map(parseCommunityInvite).filter((candidate) => candidate?.tokenHash === tokenHash).sort((a2, b) => b.event.created_at - a2.event.created_at || b.event.id.localeCompare(a2.event.id))[0];
|
|
27727
|
-
return record2 && !record2.revoked ? record2 : null;
|
|
27728
|
-
}
|
|
27729
|
-
async function findCommunityInvite(http, tokenHash, readerPubkey) {
|
|
27730
|
-
const current = await queryEvents(http, [
|
|
27731
|
-
{
|
|
27732
|
-
kinds: [KIND_COMMUNITY_INVITE],
|
|
27733
|
-
"#d": [tokenHash],
|
|
27734
|
-
"#t": [TAG_COMMUNITY_INVITE],
|
|
27735
|
-
limit: 20
|
|
27736
|
-
}
|
|
27737
|
-
], readerPubkey);
|
|
27738
|
-
const foundCurrent = latestInviteRecord(current, tokenHash);
|
|
27739
|
-
if (foundCurrent)
|
|
27740
|
-
return foundCurrent;
|
|
27741
|
-
if (current.some((event) => parseCommunityInvite(event)?.revoked))
|
|
27742
|
-
return null;
|
|
27743
|
-
const legacy = await queryEvents(http, [{ kinds: [KIND_STREAM_MESSAGE], "#t": [TAG_COMMUNITY_INVITE], limit: 500 }], readerPubkey);
|
|
27744
|
-
return latestInviteRecord(legacy, tokenHash);
|
|
27745
|
-
}
|
|
27746
|
-
async function listCommunityInvites(ctx, communityId) {
|
|
27747
|
-
const events = await query(ctx, [
|
|
27748
|
-
{
|
|
27749
|
-
kinds: [KIND_COMMUNITY_INVITE],
|
|
27750
|
-
authors: [ctx.identity.publicKey],
|
|
27751
|
-
"#t": [TAG_COMMUNITY_INVITE],
|
|
27752
|
-
limit: 500
|
|
27753
|
-
}
|
|
27754
|
-
]);
|
|
27755
|
-
const latestByToken = /* @__PURE__ */ new Map();
|
|
27756
|
-
for (const event of events) {
|
|
27757
|
-
const record2 = parseCommunityInvite(event);
|
|
27758
|
-
if (!record2 || record2.communityId !== communityId)
|
|
27759
|
-
continue;
|
|
27760
|
-
const current = latestByToken.get(record2.tokenHash);
|
|
27761
|
-
if (!current || record2.event.created_at > current.event.created_at || record2.event.created_at === current.event.created_at && record2.event.id > current.event.id) {
|
|
27762
|
-
latestByToken.set(record2.tokenHash, record2);
|
|
27763
|
-
}
|
|
27764
|
-
}
|
|
27765
|
-
const currentTime = now3();
|
|
27766
|
-
return [...latestByToken.values()].filter((record2) => !record2.revoked && record2.expiresAt > currentTime).sort((a2, b) => b.event.created_at - a2.event.created_at);
|
|
27767
|
-
}
|
|
27768
|
-
async function revokeCommunityInvite(ctx, communityId, tokenHash) {
|
|
27769
|
-
if (!/^[0-9a-f]{64}$/.test(tokenHash))
|
|
27770
|
-
throw new Error("invalid invite");
|
|
27771
|
-
const members = await communityMembers(ctx, communityId);
|
|
27772
|
-
const actor = members.find((member2) => member2.pubkey === ctx.identity.publicKey);
|
|
27773
|
-
if (actor?.role !== "owner" && actor?.role !== "admin") {
|
|
27774
|
-
throw new Error("only a Workspace owner or admin can revoke invites");
|
|
27775
|
-
}
|
|
27776
|
-
const invite = (await listCommunityInvites(ctx, communityId)).find((record2) => record2.tokenHash === tokenHash);
|
|
27777
|
-
if (!invite)
|
|
27778
|
-
throw new Error("invite is no longer active");
|
|
27779
|
-
const createdAt = Math.max(nextCommunityTimestamp(), invite.event.created_at + 1);
|
|
27780
|
-
lastCommunityMutationTimestamp = createdAt;
|
|
27781
|
-
const event = sign3(ctx, KIND_COMMUNITY_INVITE, [
|
|
27782
|
-
["h", communityId],
|
|
27783
|
-
["t", TAG_COMMUNITY_INVITE],
|
|
27784
|
-
["d", tokenHash],
|
|
27785
|
-
[TAG_COMMUNITY, communityId],
|
|
27786
|
-
["expiration", String(Math.max(invite.expiresAt, createdAt + 1))],
|
|
27787
|
-
["role", "member"],
|
|
27788
|
-
["revoked", "true"]
|
|
27789
|
-
], "", createdAt);
|
|
27790
|
-
await publishEvent(ctx.http, event);
|
|
27791
|
-
}
|
|
27792
|
-
async function createInvite(ctx, communityId, options) {
|
|
27793
|
-
const community = await getCommunity(ctx, communityId);
|
|
27794
|
-
if (!community)
|
|
27795
|
-
throw new Error(`community not found: ${communityId}`);
|
|
27796
|
-
const members = await communityMembers(ctx, communityId);
|
|
27797
|
-
if (!members.some((member2) => member2.pubkey === ctx.identity.publicKey)) {
|
|
27798
|
-
throw new Error("only a community member can mint an invite");
|
|
27799
|
-
}
|
|
27800
|
-
const createdAt = now3();
|
|
27801
|
-
const expiresAt = inviteExpiry(options, createdAt);
|
|
27802
|
-
const token2 = randomToken();
|
|
27803
|
-
const tokenHash = inviteTokenHash(token2);
|
|
27804
|
-
const event = sign3(ctx, KIND_COMMUNITY_INVITE, [
|
|
27805
|
-
["h", communityId],
|
|
27806
|
-
["t", TAG_COMMUNITY_INVITE],
|
|
27807
|
-
["d", tokenHash],
|
|
27808
|
-
[TAG_COMMUNITY, communityId],
|
|
27809
|
-
["expiration", String(expiresAt)],
|
|
27810
|
-
["role", "member"]
|
|
27811
|
-
], "", createdAt);
|
|
27812
|
-
await publishEvent(ctx.http, event);
|
|
27813
|
-
return {
|
|
27814
|
-
token: token2,
|
|
27815
|
-
tokenHash,
|
|
27816
|
-
communityId,
|
|
27817
|
-
expiresAt,
|
|
27818
|
-
mintedBy: ctx.identity.publicKey,
|
|
27819
|
-
event
|
|
27820
|
-
};
|
|
27821
|
-
}
|
|
27822
|
-
async function redeemInvite(ctx, token2) {
|
|
27823
|
-
if (!token2 || token2.length > 512)
|
|
27824
|
-
throw new Error("invalid invite token");
|
|
27825
|
-
const tokenHash = inviteTokenHash(token2);
|
|
27826
|
-
const invite = await findCommunityInvite(ctx.http, tokenHash, ctx.identity.publicKey);
|
|
27827
|
-
if (!invite)
|
|
27828
|
-
throw new Error("invalid invite token");
|
|
27829
|
-
const members = await communityMembers(ctx, invite.communityId);
|
|
27830
|
-
if (!members.some((member2) => member2.pubkey === invite.mintedBy)) {
|
|
27831
|
-
throw new Error("invite minter is not a community member");
|
|
27832
|
-
}
|
|
27833
|
-
if ((await getChannelMetadata(ctx, invite.communityId))?.archived) {
|
|
27834
|
-
throw archivedWorkspaceError();
|
|
27835
|
-
}
|
|
27836
|
-
if (members.some((member2) => member2.pubkey === ctx.identity.publicKey)) {
|
|
27837
|
-
await assertCommunityMemberInChannels(ctx, invite.communityId, ctx.identity.publicKey);
|
|
27838
|
-
return {
|
|
27839
|
-
communityId: invite.communityId,
|
|
27840
|
-
mintedBy: invite.mintedBy,
|
|
27841
|
-
expiresAt: invite.expiresAt,
|
|
27842
|
-
joined: false,
|
|
27843
|
-
alreadyMember: true
|
|
27844
|
-
};
|
|
27845
|
-
}
|
|
27846
|
-
if (invite.expiresAt <= now3())
|
|
27847
|
-
throw new Error("invite has expired");
|
|
27848
|
-
try {
|
|
27849
|
-
await setMemberRole(ctx, invite.communityId, ctx.identity.publicKey, "member", {
|
|
27850
|
-
extraTags: [
|
|
27851
|
-
["invite", tokenHash],
|
|
27852
|
-
[TAG_COMMUNITY, invite.communityId]
|
|
27853
|
-
]
|
|
27854
|
-
});
|
|
27855
|
-
} catch (error) {
|
|
27856
|
-
if (isArchivedChannelError(error))
|
|
27857
|
-
throw archivedWorkspaceError();
|
|
27858
|
-
throw error;
|
|
27859
|
-
}
|
|
27860
|
-
await waitUntilMember(ctx, invite.communityId, ctx.identity.publicKey);
|
|
27861
|
-
await assertCommunityMemberInChannels(ctx, invite.communityId, ctx.identity.publicKey);
|
|
27862
|
-
return {
|
|
27863
|
-
communityId: invite.communityId,
|
|
27864
|
-
mintedBy: invite.mintedBy,
|
|
27865
|
-
expiresAt: invite.expiresAt,
|
|
27866
|
-
joined: true,
|
|
27867
|
-
alreadyMember: false
|
|
27868
|
-
};
|
|
27869
|
-
}
|
|
27870
|
-
|
|
27871
|
-
// packages/buzz-client/dist/room-view.js
|
|
27872
|
-
init_dist();
|
|
27873
|
-
|
|
27874
|
-
// packages/api-contract/dist/phone-types.js
|
|
27875
|
-
var ROOM_VIEW_MESSAGE_LIMIT = 30;
|
|
27876
|
-
var ROOM_VIEW_BRIEFING_LIMIT = 10;
|
|
27877
|
-
var ROOM_VIEW_WORKSPACE_LIMIT = 50;
|
|
27878
|
-
var ROOM_VIEW_CHAT_LIMIT = 200;
|
|
27879
|
-
var ROOM_VIEW_MEMBER_LIMIT = 200;
|
|
27880
|
-
var ROOM_VIEW_AGENT_LIMIT = 200;
|
|
27881
|
-
var ROOM_VIEW_REQUEST_TIMEOUT_MS = 8e3;
|
|
27882
|
-
|
|
27883
|
-
// packages/api-contract/dist/phone-guards.js
|
|
27884
|
-
var HEX = /^[0-9a-f]{64}$/;
|
|
27885
|
-
var UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
|
|
27886
|
-
function record(value) {
|
|
27887
|
-
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
27888
|
-
}
|
|
27889
|
-
function integer3(value) {
|
|
27890
|
-
return Number.isSafeInteger(value) && value >= 0;
|
|
27891
|
-
}
|
|
27892
|
-
function optionalString(value) {
|
|
27893
|
-
return value === void 0 || typeof value === "string";
|
|
27894
|
-
}
|
|
27895
|
-
function httpUrl(value) {
|
|
27896
|
-
if (typeof value !== "string")
|
|
27897
|
-
return false;
|
|
27898
|
-
try {
|
|
27899
|
-
const protocol = new URL(value).protocol;
|
|
27900
|
-
return protocol === "http:" || protocol === "https:";
|
|
27901
|
-
} catch {
|
|
27902
|
-
return false;
|
|
27903
|
-
}
|
|
27904
|
-
}
|
|
27905
|
-
function attachment(value) {
|
|
27906
|
-
const item = record(value);
|
|
27907
|
-
return Boolean(item && httpUrl(item.url) && typeof item.name === "string" && item.name.length > 0 && typeof item.mimeType === "string" && /^[^/\s]+\/[^/\s]+$/.test(item.mimeType) && integer3(item.size) && (item.previewUrl === void 0 || httpUrl(item.previewUrl)) && (item.thumbnailUrl === void 0 || httpUrl(item.thumbnailUrl)) && (item.sha256 === void 0 || typeof item.sha256 === "string" && HEX.test(item.sha256)) && (item.width === void 0 || integer3(item.width) && item.width > 0) && (item.height === void 0 || integer3(item.height) && item.height > 0));
|
|
27908
|
-
}
|
|
27909
|
-
function activity(value) {
|
|
27910
|
-
const item = record(value);
|
|
27911
|
-
const rollup = item?.rollup === void 0 ? void 0 : record(item.rollup);
|
|
27912
|
-
const plan = item?.plan === void 0 ? void 0 : record(item.plan);
|
|
27913
|
-
return Boolean(item && (item.kind === "thinking" || item.kind === "tool" || item.kind === "output" || item.kind === "summary") && typeof item.title === "string" && optionalString(item.operation) && optionalString(item.status) && (item.thoughtMs === void 0 || integer3(item.thoughtMs)) && (rollup === void 0 || rollup !== null && Object.values(rollup).every(integer3)) && (item.observed === void 0 || Array.isArray(item.observed) && item.observed.every((candidate) => {
|
|
27914
|
-
const observed = record(candidate);
|
|
27915
|
-
return Boolean(observed && typeof observed.verb === "string" && optionalString(observed.target) && optionalString(observed.result));
|
|
27916
|
-
})) && (item.files === void 0 || Array.isArray(item.files) && item.files.every((candidate) => {
|
|
27917
|
-
const file = record(candidate);
|
|
27918
|
-
return Boolean(file && typeof file.path === "string" && optionalString(file.status));
|
|
27919
|
-
})) && (plan === void 0 || plan !== null && optionalString(plan.objective) && Array.isArray(plan.items) && plan.items.every((candidate) => {
|
|
27920
|
-
const planItem = record(candidate);
|
|
27921
|
-
return Boolean(planItem && typeof planItem.step === "string" && (planItem.status === "pending" || planItem.status === "in_progress" || planItem.status === "completed"));
|
|
27922
|
-
})));
|
|
27923
|
-
}
|
|
27924
|
-
function identity(value) {
|
|
27925
|
-
const item = record(value);
|
|
27926
|
-
return Boolean(item && typeof item.pubkey === "string" && HEX.test(item.pubkey) && (item.kind === "human" || item.kind === "agent") && typeof item.name === "string" && optionalString(item.handle) && optionalString(item.avatar));
|
|
27927
|
-
}
|
|
27928
|
-
function header(value) {
|
|
27929
|
-
const item = record(value);
|
|
27930
|
-
return Boolean(item && typeof item.id === "string" && UUID.test(item.id) && typeof item.workspaceId === "string" && UUID.test(item.workspaceId) && (item.parentId === void 0 || typeof item.parentId === "string" && UUID.test(item.parentId)) && typeof item.name === "string" && optionalString(item.about) && optionalString(item.avatar) && (item.visibility === void 0 || item.visibility === "public" || item.visibility === "invite-only") && typeof item.archived === "boolean" && integer3(item.createdAt) && integer3(item.updatedAt));
|
|
27931
|
-
}
|
|
27932
|
-
function member(value) {
|
|
27933
|
-
const item = record(value);
|
|
27934
|
-
const presence = item?.presence === void 0 ? void 0 : record(item.presence);
|
|
27935
|
-
return Boolean(item && identity(item.identity) && (item.role === "owner" || item.role === "admin" || item.role === "member") && (presence === void 0 || presence && (presence.status === "online" || presence.status === "offline") && integer3(presence.observedAt) && (presence.roomId === void 0 || typeof presence.roomId === "string" && UUID.test(presence.roomId))));
|
|
27936
|
-
}
|
|
27937
|
-
function messageCorner(value) {
|
|
27938
|
-
const item = record(value);
|
|
27939
|
-
return Boolean(item && typeof item.id === "string" && UUID.test(item.id) && (item.status === "open" || item.status === "working" || item.status === "waiting" || item.status === "idle" || item.status === "concluded" || item.status === "closed"));
|
|
27940
|
-
}
|
|
27941
|
-
function messagePermission(value) {
|
|
27942
|
-
const item = record(value);
|
|
27943
|
-
return Boolean(item && typeof item.permissionId === "string" && item.permissionId.length > 0 && typeof item.requestId === "string" && item.requestId.length > 0 && identity(item.agent) && item.agent.kind === "agent" && identity(item.requester) && item.requester.kind === "human" && (item.decider === void 0 || identity(item.decider) && item.decider.kind === "human") && typeof item.tool === "string" && item.tool.length > 0 && optionalString(item.repository) && (item.purpose === void 0 || item.purpose === "squire-spending") && (item.status === "pending" || item.status === "allowed" || item.status === "denied" || item.status === "expired" || item.status === "failed") && (item.cornerId === void 0 || typeof item.cornerId === "string" && UUID.test(item.cornerId)));
|
|
27944
|
-
}
|
|
27945
|
-
function targetBranch(value) {
|
|
27946
|
-
const item = record(value);
|
|
27947
|
-
return Boolean(item && typeof item.proposalId === "string" && item.proposalId.length > 0 && typeof item.from === "string" && typeof item.to === "string" && item.to.length > 0 && optionalString(item.repository) && (item.agent === void 0 || identity(item.agent)) && (item.requester === void 0 || identity(item.requester)));
|
|
27948
|
-
}
|
|
27949
|
-
function githubUrl(value) {
|
|
27950
|
-
if (typeof value !== "string")
|
|
27951
|
-
return false;
|
|
27952
|
-
try {
|
|
27953
|
-
const url = new URL(value);
|
|
27954
|
-
return url.protocol === "https:" && url.hostname === "github.com";
|
|
27955
|
-
} catch {
|
|
27956
|
-
return false;
|
|
27957
|
-
}
|
|
27958
|
-
}
|
|
27959
|
-
function githubEvent(value) {
|
|
27960
|
-
const item = record(value);
|
|
27961
|
-
if (!item || item.type !== "pull-request" && item.type !== "issue" || typeof item.actor !== "string" || typeof item.title !== "string" || !githubUrl(item.url)) {
|
|
27962
|
-
return false;
|
|
27963
|
-
}
|
|
27964
|
-
return item.type === "pull-request" && (item.action === "opened" || item.action === "closed" || item.action === "merged") || item.type === "issue" && (item.action === "opened" || item.action === "closed");
|
|
27965
|
-
}
|
|
27966
|
-
function daemonFact(value) {
|
|
27967
|
-
const item = record(value);
|
|
27968
|
-
const pullRequest = item?.pullRequest === void 0 ? void 0 : record(item.pullRequest);
|
|
27969
|
-
if (!item || item.type !== "corner-complete" && item.type !== "checks-failing" && item.type !== "worktree-cleaned" && item.type !== "corner-open" || typeof item.cornerId !== "string" || !UUID.test(item.cornerId) || typeof item.objective !== "string" || !item.objective.trim() || item.outcome !== void 0 && item.outcome !== "landed" && item.outcome !== "abandoned" || !optionalString(item.name) || item.type === "corner-open" && (typeof item.name !== "string" || !item.name.trim()) || pullRequest !== void 0 && (!pullRequest || pullRequest.number !== void 0 && (!Number.isSafeInteger(pullRequest.number) || Number(pullRequest.number) <= 0) || !optionalString(pullRequest.title) || !githubUrl(pullRequest.url) || !optionalString(pullRequest.targetBranch)) || item.subgoals !== void 0 && (!Array.isArray(item.subgoals) || !item.subgoals.every((subgoal) => {
|
|
27970
|
-
const entry = record(subgoal);
|
|
27971
|
-
return Boolean(entry && typeof entry.step === "string" && entry.step.trim() && (entry.status === "pending" || entry.status === "in_progress" || entry.status === "completed"));
|
|
27972
|
-
}))) {
|
|
27973
|
-
return false;
|
|
27974
|
-
}
|
|
27975
|
-
return item.type !== "corner-complete" || item.outcome === "landed" || item.outcome === "abandoned";
|
|
27976
|
-
}
|
|
27977
|
-
function isRoomViewMessage(value) {
|
|
27978
|
-
const item = record(value);
|
|
27979
|
-
const reference = item?.reference === void 0 ? void 0 : record(item.reference);
|
|
27980
|
-
const reply = item?.reply === void 0 ? void 0 : record(item.reply);
|
|
27981
|
-
return Boolean(item && typeof item.id === "string" && HEX.test(item.id) && typeof item.text === "string" && integer3(item.createdAt) && identity(item.author) && (item.presentation === "message" || item.presentation === "system" || item.presentation === "activity" || item.presentation === "card") && (reference === void 0 || reference && typeof reference.channelId === "string" && UUID.test(reference.channelId) && reference.eventId === item.id && typeof reference.rootId === "string" && HEX.test(reference.rootId)) && (reply === void 0 || reply && typeof reply.channelId === "string" && UUID.test(reply.channelId) && typeof reply.eventId === "string" && HEX.test(reply.eventId) && typeof reply.rootId === "string" && HEX.test(reply.rootId)) && optionalString(item.liveTurnId) && optionalString(item.requestId) && (item.attachments === void 0 || Array.isArray(item.attachments) && item.attachments.every(attachment)) && (item.mentionPubkeys === void 0 || Array.isArray(item.mentionPubkeys) && item.mentionPubkeys.every((pubkey2) => typeof pubkey2 === "string" && HEX.test(pubkey2))) && (item.activity === void 0 || Array.isArray(item.activity) && item.activity.every(activity)) && (item.durableFact === void 0 || item.durableFact === "failure" || item.durableFact === "merge" || item.durableFact === "action") && (item.corner === void 0 || messageCorner(item.corner)) && (item.permission === void 0 || messagePermission(item.permission)) && (item.targetBranch === void 0 || targetBranch(item.targetBranch)) && (item.githubEvent === void 0 || githubEvent(item.githubEvent)) && (item.daemonFact === void 0 || daemonFact(item.daemonFact)));
|
|
27982
|
-
}
|
|
27983
|
-
function scopedMessage(value, roomId) {
|
|
27984
|
-
return typeof roomId === "string" && isRoomViewMessage(value) && (value.reference === void 0 || value.reference.channelId === roomId) && (value.reply === void 0 || value.reply.channelId === roomId);
|
|
27985
|
-
}
|
|
27986
|
-
function watchFilters(value) {
|
|
27987
|
-
return Array.isArray(value) && value.length <= 32 && value.every((candidate) => {
|
|
27988
|
-
const filter = record(candidate);
|
|
27989
|
-
if (!filter)
|
|
27990
|
-
return false;
|
|
27991
|
-
return Object.entries(filter).every(([key, entry]) => {
|
|
27992
|
-
if (key === "kinds")
|
|
27993
|
-
return Array.isArray(entry) && entry.every(integer3);
|
|
27994
|
-
if (key === "authors" || key === "#h" || key === "#d" || key === "#p" || key === "#t") {
|
|
27995
|
-
return Array.isArray(entry) && entry.every((item) => typeof item === "string");
|
|
27996
|
-
}
|
|
27997
|
-
return false;
|
|
27998
|
-
});
|
|
27999
|
-
});
|
|
28000
|
-
}
|
|
28001
|
-
function viewer(value) {
|
|
28002
|
-
const item = record(value);
|
|
28003
|
-
const permissions = record(item?.permissions);
|
|
28004
|
-
return Boolean(item && identity(item.identity) && (item.role === "owner" || item.role === "admin" || item.role === "member") && permissions && typeof permissions.send === "boolean" && typeof permissions.manage === "boolean");
|
|
28005
|
-
}
|
|
28006
|
-
function directMessage(value) {
|
|
28007
|
-
const item = record(value);
|
|
28008
|
-
return Boolean(item && Array.isArray(item.participants) && item.participants.length === 2 && item.participants.every((pubkey2) => typeof pubkey2 === "string" && HEX.test(pubkey2)) && item.participants[0] < item.participants[1]);
|
|
28009
|
-
}
|
|
28010
|
-
function directMessageForViewer(value, viewerValue) {
|
|
28011
|
-
const viewerItem = record(viewerValue);
|
|
28012
|
-
const viewerIdentity = record(viewerItem?.identity);
|
|
28013
|
-
return directMessage(value) && typeof viewerIdentity?.pubkey === "string" && value.participants.includes(viewerIdentity.pubkey);
|
|
28014
|
-
}
|
|
28015
|
-
function agentTurn(value) {
|
|
28016
|
-
const item = record(value);
|
|
28017
|
-
return Boolean(item && typeof item.requestId === "string" && HEX.test(item.requestId) && typeof item.agentPubkey === "string" && HEX.test(item.agentPubkey) && (item.status === "working" || item.status === "complete" || item.status === "failed") && integer3(item.createdAt) && optionalString(item.generationId));
|
|
28018
|
-
}
|
|
28019
|
-
function workspace(value) {
|
|
28020
|
-
const item = record(value);
|
|
28021
|
-
return Boolean(item && typeof item.id === "string" && UUID.test(item.id) && typeof item.name === "string" && optionalString(item.avatar) && (item.visibility === "public" || item.visibility === "invite-only") && (item.role === "owner" || item.role === "admin" || item.role === "member") && integer3(item.updatedAt));
|
|
28022
|
-
}
|
|
28023
|
-
function latest(value) {
|
|
28024
|
-
const item = record(value);
|
|
28025
|
-
return Boolean(item && typeof item.id === "string" && HEX.test(item.id) && typeof item.text === "string" && integer3(item.createdAt) && identity(item.author));
|
|
28026
|
-
}
|
|
28027
|
-
function chat(value) {
|
|
28028
|
-
const item = record(value);
|
|
28029
|
-
return Boolean(item && header(item.room) && (item.latestMessage === void 0 || latest(item.latestMessage)) && integer3(item.memberCount) && integer3(item.cornerCount) && typeof item.unread === "boolean" && optionalString(item.repositoryName) && (item.agentState === void 0 || item.agentState === "needs-you" || item.agentState === "working"));
|
|
28030
|
-
}
|
|
28031
|
-
function corner(value) {
|
|
28032
|
-
const item = record(value);
|
|
28033
|
-
return Boolean(item && header(item.corner) && cornerLifecycle(item.lifecycle) && (item.status === "open" || item.status === "working" || item.status === "waiting" || item.status === "idle" || item.status === "concluded" || item.status === "closed") && (item.statusAt === void 0 || integer3(item.statusAt)) && (item.reason === void 0 || item.reason === "review" || item.reason === "question" || item.reason === "failure") && (item.agent === void 0 || identity(item.agent)) && (item.latestMessage === void 0 || latest(item.latestMessage)));
|
|
28034
|
-
}
|
|
28035
|
-
function cornerLifecycle(value) {
|
|
28036
|
-
const item = record(value);
|
|
28037
|
-
const pr = item?.pr === void 0 ? void 0 : record(item.pr);
|
|
28038
|
-
return Boolean(item && (item.lifecycle === "working" || item.lifecycle === "in-review" || item.lifecycle === "unknown" || item.lifecycle === "done") && (item.checks === "passing" || item.checks === "failing" || item.checks === "pending" || item.checks === "unknown") && optionalString(item.branch) && (item.outcome === void 0 || item.outcome === "landed" || item.outcome === "abandoned") && optionalString(item.reason) && (pr === void 0 || pr && integer3(pr.number) && pr.number > 0 && githubUrl(pr.url) && typeof pr.title === "string" && pr.title.length > 0 && typeof pr.targetBranch === "string" && pr.targetBranch.length > 0 && typeof pr.headSha === "string" && /^[0-9a-f]{40}$/i.test(pr.headSha) && optionalString(pr.mergedAt) && optionalString(pr.mergedBy)));
|
|
28039
|
-
}
|
|
28040
|
-
function repository(value) {
|
|
28041
|
-
const item = record(value);
|
|
28042
|
-
return Boolean(item && typeof item.key === "string" && item.key.length > 0 && typeof item.name === "string" && item.name.length > 0 && typeof item.remote === "string" && item.remote.length > 0 && typeof item.targetBranch === "string" && item.targetBranch.length > 0 && integer3(item.updatedAt) && (item.githubInstallationId === void 0 || integer3(item.githubInstallationId)) && typeof item.githubEventsEnabled === "boolean");
|
|
28043
|
-
}
|
|
28044
|
-
function repositoryResolution(value) {
|
|
28045
|
-
return value === "repository" || value === "none" || value === "unverified";
|
|
28046
|
-
}
|
|
28047
|
-
function modelSelection(value) {
|
|
28048
|
-
const item = record(value);
|
|
28049
|
-
return Boolean(item && optionalString(item.model) && optionalString(item.effort));
|
|
28050
|
-
}
|
|
28051
|
-
function modelOption(value) {
|
|
28052
|
-
const item = record(value);
|
|
28053
|
-
return Boolean(item && typeof item.id === "string" && item.id.length > 0 && typeof item.category === "string" && item.category.length > 0 && optionalString(item.currentValue) && Array.isArray(item.options) && item.options.every((candidate) => {
|
|
28054
|
-
const option = record(candidate);
|
|
28055
|
-
return Boolean(option && typeof option.id === "string" && option.id.length > 0 && optionalString(option.name));
|
|
28056
|
-
}));
|
|
28057
|
-
}
|
|
28058
|
-
function isRoomView(value) {
|
|
28059
|
-
const item = record(value);
|
|
28060
|
-
return Boolean(item && header(item.room) && Array.isArray(item.messages) && item.messages.length <= ROOM_VIEW_MESSAGE_LIMIT && item.messages.every((candidate) => scopedMessage(candidate, record(item.room)?.id)) && Array.isArray(item.latestAgentTurns) && item.latestAgentTurns.length <= ROOM_VIEW_AGENT_LIMIT && item.latestAgentTurns.every(agentTurn) && Array.isArray(item.members) && item.members.length <= ROOM_VIEW_MEMBER_LIMIT && item.members.every(member) && viewer(item.viewer) && (item.directMessage === void 0 || directMessageForViewer(item.directMessage, item.viewer)) && (item.parent === void 0 || header(item.parent)) && (item.briefing === void 0 || Array.isArray(item.briefing) && item.briefing.length <= ROOM_VIEW_BRIEFING_LIMIT && item.briefing.every(isRoomViewMessage)) && (item.cornerPlan === void 0 || activity({ kind: "output", title: "Plan", plan: item.cornerPlan })) && Array.isArray(item.corners) && item.corners.every(corner) && (item.repository === void 0 || repository(item.repository)) && repositoryResolution(item.repositoryResolution) && (item.cornerLifecycle === void 0 || cornerLifecycle(item.cornerLifecycle)) && watchFilters(item.watchFilters));
|
|
28061
|
-
}
|
|
28062
|
-
function isRoomHistoryView(value) {
|
|
28063
|
-
const item = record(value);
|
|
28064
|
-
const before = item?.nextBefore === void 0 ? void 0 : record(item.nextBefore);
|
|
28065
|
-
return Boolean(item && typeof item.roomId === "string" && UUID.test(item.roomId) && Array.isArray(item.messages) && item.messages.length <= ROOM_VIEW_MESSAGE_LIMIT && item.messages.every((candidate) => scopedMessage(candidate, item.roomId)) && (before === void 0 || before && integer3(before.createdAt) && typeof before.id === "string" && HEX.test(before.id)));
|
|
27932
|
+
extraTags: [
|
|
27933
|
+
[TAG_COMMUNITY, communityId],
|
|
27934
|
+
["member-invite", memberPubkey]
|
|
27935
|
+
]
|
|
27936
|
+
});
|
|
27937
|
+
await waitUntilMember(ctx, channelId, memberPubkey);
|
|
27938
|
+
return { joined: true, membershipSince };
|
|
28066
27939
|
}
|
|
28067
|
-
function
|
|
28068
|
-
|
|
28069
|
-
|
|
27940
|
+
function inviteExpiry(options, createdAt) {
|
|
27941
|
+
if (options?.expiresAt !== void 0 && options.expiresInSeconds !== void 0) {
|
|
27942
|
+
throw new Error("set either expiresAt or expiresInSeconds, not both");
|
|
27943
|
+
}
|
|
27944
|
+
const expiresAt = options?.expiresAt ?? createdAt + (options?.expiresInSeconds ?? DEFAULT_INVITE_TTL_SECONDS);
|
|
27945
|
+
if (!Number.isSafeInteger(expiresAt) || expiresAt <= createdAt) {
|
|
27946
|
+
throw new Error("invite expiry must be a future Unix timestamp");
|
|
27947
|
+
}
|
|
27948
|
+
return expiresAt;
|
|
28070
27949
|
}
|
|
28071
|
-
function
|
|
28072
|
-
|
|
28073
|
-
|
|
28074
|
-
|
|
27950
|
+
function parseCommunityInvite(event) {
|
|
27951
|
+
if (event.kind !== KIND_COMMUNITY_INVITE && event.kind !== KIND_STREAM_MESSAGE || !verifyEvent2(event)) {
|
|
27952
|
+
return null;
|
|
27953
|
+
}
|
|
27954
|
+
if (!tagValues(event, "t").includes(TAG_COMMUNITY_INVITE))
|
|
27955
|
+
return null;
|
|
27956
|
+
const tokenHash = tagValue(event, "d");
|
|
27957
|
+
const communityId = tagValue(event, "h");
|
|
27958
|
+
const communityTag = tagValue(event, TAG_COMMUNITY);
|
|
27959
|
+
const expiresRaw = tagValue(event, "expiration");
|
|
27960
|
+
const expiresAt = expiresRaw === void 0 ? NaN : Number(expiresRaw);
|
|
27961
|
+
const revoked = tagValue(event, "revoked") === "true";
|
|
27962
|
+
if (!tokenHash || !/^[0-9a-f]{64}$/.test(tokenHash))
|
|
27963
|
+
return null;
|
|
27964
|
+
if (!communityId || communityTag !== communityId)
|
|
27965
|
+
return null;
|
|
27966
|
+
if (!Number.isSafeInteger(expiresAt) || expiresAt <= event.created_at)
|
|
27967
|
+
return null;
|
|
27968
|
+
return {
|
|
27969
|
+
tokenHash,
|
|
27970
|
+
communityId,
|
|
27971
|
+
expiresAt,
|
|
27972
|
+
mintedBy: event.pubkey,
|
|
27973
|
+
...revoked ? { revoked: true } : {},
|
|
27974
|
+
event
|
|
27975
|
+
};
|
|
28075
27976
|
}
|
|
28076
|
-
function
|
|
28077
|
-
const
|
|
28078
|
-
return
|
|
27977
|
+
function latestInviteRecord(events, tokenHash) {
|
|
27978
|
+
const record2 = events.map(parseCommunityInvite).filter((candidate) => candidate?.tokenHash === tokenHash).sort((a2, b) => b.event.created_at - a2.event.created_at || b.event.id.localeCompare(a2.event.id))[0];
|
|
27979
|
+
return record2 && !record2.revoked ? record2 : null;
|
|
28079
27980
|
}
|
|
28080
|
-
function
|
|
28081
|
-
const
|
|
28082
|
-
|
|
27981
|
+
async function findCommunityInvite(http, tokenHash, readerPubkey) {
|
|
27982
|
+
const current = await queryEvents(http, [
|
|
27983
|
+
{
|
|
27984
|
+
kinds: [KIND_COMMUNITY_INVITE],
|
|
27985
|
+
"#d": [tokenHash],
|
|
27986
|
+
"#t": [TAG_COMMUNITY_INVITE],
|
|
27987
|
+
limit: 20
|
|
27988
|
+
}
|
|
27989
|
+
], readerPubkey);
|
|
27990
|
+
const foundCurrent = latestInviteRecord(current, tokenHash);
|
|
27991
|
+
if (foundCurrent)
|
|
27992
|
+
return foundCurrent;
|
|
27993
|
+
if (current.some((event) => parseCommunityInvite(event)?.revoked))
|
|
27994
|
+
return null;
|
|
27995
|
+
const legacy = await queryEvents(http, [{ kinds: [KIND_STREAM_MESSAGE], "#t": [TAG_COMMUNITY_INVITE], limit: 500 }], readerPubkey);
|
|
27996
|
+
return latestInviteRecord(legacy, tokenHash);
|
|
28083
27997
|
}
|
|
28084
|
-
function
|
|
28085
|
-
const
|
|
28086
|
-
|
|
28087
|
-
|
|
27998
|
+
async function listCommunityInvites(ctx, communityId) {
|
|
27999
|
+
const events = await query(ctx, [
|
|
28000
|
+
{
|
|
28001
|
+
kinds: [KIND_COMMUNITY_INVITE],
|
|
28002
|
+
authors: [ctx.identity.publicKey],
|
|
28003
|
+
"#t": [TAG_COMMUNITY_INVITE],
|
|
28004
|
+
limit: 500
|
|
28005
|
+
}
|
|
28006
|
+
]);
|
|
28007
|
+
const latestByToken = /* @__PURE__ */ new Map();
|
|
28008
|
+
for (const event of events) {
|
|
28009
|
+
const record2 = parseCommunityInvite(event);
|
|
28010
|
+
if (!record2 || record2.communityId !== communityId)
|
|
28011
|
+
continue;
|
|
28012
|
+
const current = latestByToken.get(record2.tokenHash);
|
|
28013
|
+
if (!current || record2.event.created_at > current.event.created_at || record2.event.created_at === current.event.created_at && record2.event.id > current.event.id) {
|
|
28014
|
+
latestByToken.set(record2.tokenHash, record2);
|
|
28015
|
+
}
|
|
28016
|
+
}
|
|
28017
|
+
const currentTime = now3();
|
|
28018
|
+
return [...latestByToken.values()].filter((record2) => !record2.revoked && record2.expiresAt > currentTime).sort((a2, b) => b.event.created_at - a2.event.created_at);
|
|
28088
28019
|
}
|
|
28089
|
-
function
|
|
28090
|
-
|
|
28091
|
-
|
|
28092
|
-
|
|
28093
|
-
|
|
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
|
|
28096
|
-
|
|
28097
|
-
|
|
28098
|
-
|
|
28099
|
-
|
|
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
|
|
28102
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
28557
|
-
if (
|
|
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
|
|
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
|
-
|
|
43668
|
-
const requestLead = String.raw`(?:(?:please|kindly)\s+|(?:can|could|would|will)\s+you\s+|i\s+(?:want|need)\s+you\s+to\s+|i(?:['’]d| would)\s+like\s+you\s+to\s+)?`;
|
|
43669
|
-
const directCornerCommand = new RegExp(String.raw`^${requestLead}(?:open|create|launch|start)\s+(?:up\s+)?(?:a\s+|the\s+)?(?:new\s+)?corner\b`, "i");
|
|
43670
|
-
const startWorkInCornerCommand = new RegExp(String.raw`^${requestLead}start\s+(?:(?:the|this|that)\s+)?(?:work|working)\b.{0,200}\b(?:in|inside|within)\s+(?:a\s+|the\s+)?(?:new\s+)?corner\b`, "i");
|
|
43671
|
-
return directCornerCommand.test(content) || startWorkInCornerCommand.test(content);
|
|
43688
|
+
return isExplicitCornerOpenRequest(event.content);
|
|
43672
43689
|
}
|
|
43673
43690
|
async function createAgentSubchannel(agentIdentity, parentChannelId, name, openingHumanPubkey, communityId, task, extraTags = []) {
|
|
43674
43691
|
if (!openingHumanPubkey || openingHumanPubkey === agentIdentity.publicKey) {
|
|
@@ -47272,6 +47289,18 @@ Deliver artifacts from this corner; there is no branch to land.`;
|
|
|
47272
47289
|
const named = editPolicy === "named-repository" ? namedRepositoryTargetFromRoomRequest(request.content) : void 0;
|
|
47273
47290
|
if (!named) {
|
|
47274
47291
|
console.log(`[body] Room ${tlcChannelId} has no repository target for corner work`);
|
|
47292
|
+
const text2 = "This Room has no repository yet - bind one in Room settings.";
|
|
47293
|
+
if (this.daemonApi) {
|
|
47294
|
+
await this.daemonApi.execute("postRoomMessage", {
|
|
47295
|
+
roomId: tlcChannelId,
|
|
47296
|
+
requestId: request.eventId,
|
|
47297
|
+
text: text2,
|
|
47298
|
+
presentation: "message"
|
|
47299
|
+
});
|
|
47300
|
+
} else {
|
|
47301
|
+
const event = await this.durableState.reserveReply(tlcChannelId, request.eventId, buildAgentMessage(tlcChannelId, this.agentIdentity, text2, request.eventId, [], [["request", request.eventId]], request.replyRootId));
|
|
47302
|
+
await publishEvent2(event, this.agentIdentity);
|
|
47303
|
+
}
|
|
47275
47304
|
return { status: "handled", outcome: { openedCorner: false, producedReply: true } };
|
|
47276
47305
|
}
|
|
47277
47306
|
}
|
|
@@ -48927,72 +48956,88 @@ Deliver artifacts from this corner; there is no branch to land.`;
|
|
|
48927
48956
|
async runMonolithRoomLoop(channelId, boundRepo, editPolicy, opts) {
|
|
48928
48957
|
const api = this.daemonApi;
|
|
48929
48958
|
let cursor3 = await this.durableState.daemonInboxCursor(channelId);
|
|
48930
|
-
|
|
48931
|
-
|
|
48932
|
-
|
|
48933
|
-
|
|
48934
|
-
});
|
|
48935
|
-
if (!cursor3) {
|
|
48936
|
-
const activation = await api.execute("getRoomInbox", {
|
|
48959
|
+
const availableStatus = this.config.modelUnavailable ? "offline" : "online";
|
|
48960
|
+
const postPresence = async (status) => {
|
|
48961
|
+
await api.execute("postAgentPresence", {
|
|
48962
|
+
agentId: this.agentIdentity.publicKey,
|
|
48937
48963
|
roomId: channelId,
|
|
48938
|
-
|
|
48964
|
+
status
|
|
48939
48965
|
});
|
|
48940
|
-
|
|
48941
|
-
|
|
48942
|
-
|
|
48943
|
-
|
|
48944
|
-
|
|
48945
|
-
|
|
48946
|
-
|
|
48947
|
-
|
|
48966
|
+
this.onRoomPresence?.(channelId, status);
|
|
48967
|
+
};
|
|
48968
|
+
await postPresence(availableStatus);
|
|
48969
|
+
let presenceTail = Promise.resolve();
|
|
48970
|
+
const heartbeat = setInterval(() => {
|
|
48971
|
+
presenceTail = presenceTail.then(() => postPresence(availableStatus)).catch((error) => console.error(`[body] monolith Room ${channelId} presence heartbeat failed:`, error));
|
|
48972
|
+
}, AGENT_PRESENCE_HEARTBEAT_MS);
|
|
48973
|
+
heartbeat.unref?.();
|
|
48974
|
+
try {
|
|
48975
|
+
if (!cursor3) {
|
|
48976
|
+
const activation = await api.execute("getRoomInbox", {
|
|
48948
48977
|
roomId: channelId,
|
|
48949
|
-
|
|
48950
|
-
limit: 200
|
|
48978
|
+
startAtLatest: true
|
|
48951
48979
|
});
|
|
48952
|
-
|
|
48953
|
-
|
|
48954
|
-
|
|
48955
|
-
|
|
48980
|
+
if (activation.cursor) {
|
|
48981
|
+
cursor3 = activation.cursor;
|
|
48982
|
+
await this.durableState.setDaemonInboxCursor(channelId, cursor3);
|
|
48983
|
+
}
|
|
48984
|
+
}
|
|
48985
|
+
while (!opts.signal?.aborted && !this.disposed) {
|
|
48986
|
+
try {
|
|
48987
|
+
const inbox = await api.execute("getRoomInbox", {
|
|
48956
48988
|
roomId: channelId,
|
|
48957
|
-
|
|
48989
|
+
...cursor3 ? { after: cursor3 } : {},
|
|
48990
|
+
limit: 200
|
|
48958
48991
|
});
|
|
48959
|
-
|
|
48960
|
-
|
|
48961
|
-
|
|
48962
|
-
|
|
48963
|
-
|
|
48964
|
-
|
|
48965
|
-
|
|
48966
|
-
|
|
48967
|
-
|
|
48968
|
-
|
|
48969
|
-
|
|
48970
|
-
|
|
48971
|
-
|
|
48972
|
-
|
|
48973
|
-
|
|
48974
|
-
|
|
48975
|
-
|
|
48976
|
-
|
|
48977
|
-
|
|
48978
|
-
|
|
48979
|
-
|
|
48980
|
-
|
|
48981
|
-
|
|
48982
|
-
|
|
48983
|
-
|
|
48984
|
-
|
|
48985
|
-
|
|
48992
|
+
for (const item of inbox.items) {
|
|
48993
|
+
if (item.authorId === this.agentIdentity.publicKey || item.type !== "message" || item.mentionIds.length > 0 && !item.mentionIds.includes(this.agentIdentity.publicKey) || this.processedRequestIds.has(item.id))
|
|
48994
|
+
continue;
|
|
48995
|
+
const authority = await api.execute("getRoomAuthority", {
|
|
48996
|
+
roomId: channelId,
|
|
48997
|
+
principalId: item.authorId
|
|
48998
|
+
});
|
|
48999
|
+
if (!authority.member || authority.principalKind !== "human")
|
|
49000
|
+
continue;
|
|
49001
|
+
if (!this.senderAccessAllowed(item.authorId))
|
|
49002
|
+
continue;
|
|
49003
|
+
const attachments = item.attachments.map((attachment2) => ({
|
|
49004
|
+
url: attachment2.url,
|
|
49005
|
+
name: attachment2.name ?? "attachment",
|
|
49006
|
+
mimeType: attachment2.mimeType ?? "application/octet-stream",
|
|
49007
|
+
size: attachment2.size ?? 0,
|
|
49008
|
+
...attachment2.thumbnailUrl ? { thumbnailUrl: attachment2.thumbnailUrl } : {}
|
|
49009
|
+
}));
|
|
49010
|
+
const request = {
|
|
49011
|
+
eventId: item.id,
|
|
49012
|
+
authorPubkey: item.authorId,
|
|
49013
|
+
content: item.body.trim(),
|
|
49014
|
+
attachments,
|
|
49015
|
+
createdAt: item.createdAt,
|
|
49016
|
+
...item.rootMessageId ? { replyRootId: item.rootMessageId } : {}
|
|
49017
|
+
};
|
|
49018
|
+
const workIntent = isExplicitCornerOpenRequest(item.body);
|
|
49019
|
+
const outcome = await this.replyInRoom(channelId, boundRepo, request, workIntent, editPolicy, void 0, workIntent);
|
|
49020
|
+
if (outcome.producedReply)
|
|
49021
|
+
this.processedRequestIds.add(item.id);
|
|
49022
|
+
}
|
|
49023
|
+
if (inbox.cursor) {
|
|
49024
|
+
cursor3 = inbox.cursor;
|
|
49025
|
+
await this.durableState.setDaemonInboxCursor(channelId, cursor3);
|
|
49026
|
+
}
|
|
49027
|
+
this.onRoomPollSuccess?.(channelId);
|
|
49028
|
+
await this.waitForPoll(opts.pollMs ?? 1e3, opts.signal);
|
|
49029
|
+
} catch (error) {
|
|
49030
|
+
if (opts.signal?.aborted || this.disposed)
|
|
49031
|
+
break;
|
|
49032
|
+
this.onRoomPollFailure?.(channelId, 1e3);
|
|
49033
|
+
console.error(`[body] monolith Room ${channelId} poll failed:`, error);
|
|
49034
|
+
await this.waitForPoll(1e3, opts.signal);
|
|
48986
49035
|
}
|
|
48987
|
-
this.onRoomPollSuccess?.(channelId);
|
|
48988
|
-
await this.waitForPoll(opts.pollMs ?? 1e3, opts.signal);
|
|
48989
|
-
} catch (error) {
|
|
48990
|
-
if (opts.signal?.aborted || this.disposed)
|
|
48991
|
-
break;
|
|
48992
|
-
this.onRoomPollFailure?.(channelId, 1e3);
|
|
48993
|
-
console.error(`[body] monolith Room ${channelId} poll failed:`, error);
|
|
48994
|
-
await this.waitForPoll(1e3, opts.signal);
|
|
48995
49036
|
}
|
|
49037
|
+
} finally {
|
|
49038
|
+
clearInterval(heartbeat);
|
|
49039
|
+
await presenceTail;
|
|
49040
|
+
await postPresence("offline").catch((error) => console.error(`[body] monolith Room ${channelId} shutdown presence failed:`, error));
|
|
48996
49041
|
}
|
|
48997
49042
|
}
|
|
48998
49043
|
/** One long-running body loop owns request discovery, steering, and merge closure. */
|
|
@@ -56185,8 +56230,11 @@ async function jsonRequest(url, body, fetchImpl) {
|
|
|
56185
56230
|
return response.json();
|
|
56186
56231
|
}
|
|
56187
56232
|
function requestConnectGrant(baseUrl, pairingCode, selection, fetchImpl) {
|
|
56233
|
+
const normalizedPairingCode = normalizeAgentPairingCode(pairingCode);
|
|
56234
|
+
if (!normalizedPairingCode)
|
|
56235
|
+
throw new Error("invalid pairing code");
|
|
56188
56236
|
return jsonRequest(`${baseUrl}/auth/agent/connect`, {
|
|
56189
|
-
pairing_code:
|
|
56237
|
+
pairing_code: normalizedPairingCode,
|
|
56190
56238
|
harness: selection.harness,
|
|
56191
56239
|
...selection.provider ? { provider: selection.provider } : {},
|
|
56192
56240
|
model: selection.model,
|
|
@@ -56286,7 +56334,7 @@ async function runConnectCommand(code, options = {}) {
|
|
|
56286
56334
|
intro(brass("Beeline connect"));
|
|
56287
56335
|
const pairingCode = code?.trim() || await clackPrompts.text({
|
|
56288
56336
|
message: brass("Pairing code from the app"),
|
|
56289
|
-
validate: (value) => value
|
|
56337
|
+
validate: (value) => normalizeAgentPairingCode(value) ? void 0 : "Enter the pairing code shown in the app"
|
|
56290
56338
|
});
|
|
56291
56339
|
const selection = await collectConnectWizard();
|
|
56292
56340
|
const fetchImpl = options.fetchImpl ?? fetch;
|
|
@@ -57341,7 +57389,7 @@ ${import_picocolors6.default.dim("Usage:")}
|
|
|
57341
57389
|
beeline archive <subchannel-uuid> Archive subchannel
|
|
57342
57390
|
beeline pair <BUZZ-XXXX-XXXX> [options] Pair an agent (optionally to this repo)
|
|
57343
57391
|
and start its durable daemon
|
|
57344
|
-
beeline connect [
|
|
57392
|
+
beeline connect [XXXXXXXX-XXXXXXXX] Install and connect an app-authorized agent
|
|
57345
57393
|
beeline start [agent-pubkey] Start \u2014 or RESTART when already running,
|
|
57346
57394
|
stopping cleanly after in-flight work \u2014
|
|
57347
57395
|
this repo's (or, outside a repo, this
|