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.
- package/dist/usebeeline.mjs +703 -474
- 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();
|
|
@@ -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
|
|
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
|
}
|
|
@@ -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
|
|
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 =
|
|
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
|
-
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
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, [
|
|
47847
|
-
const requester = requesterAttribution?.handle ?? fallbackPersonName(
|
|
47848
|
-
|
|
47849
|
-
|
|
47850
|
-
|
|
47851
|
-
|
|
47852
|
-
|
|
47853
|
-
|
|
47854
|
-
|
|
47855
|
-
|
|
47856
|
-
|
|
47857
|
-
|
|
47858
|
-
|
|
47859
|
-
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
-
|
|
48823
|
-
|
|
48824
|
-
|
|
48825
|
-
|
|
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
|
-
|
|
48964
|
+
status
|
|
48831
48965
|
});
|
|
48832
|
-
|
|
48833
|
-
|
|
48834
|
-
|
|
48835
|
-
|
|
48836
|
-
|
|
48837
|
-
|
|
48838
|
-
|
|
48839
|
-
|
|
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
|
-
|
|
48842
|
-
limit: 200
|
|
48978
|
+
startAtLatest: true
|
|
48843
48979
|
});
|
|
48844
|
-
|
|
48845
|
-
|
|
48846
|
-
|
|
48847
|
-
|
|
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
|
-
|
|
48989
|
+
...cursor3 ? { after: cursor3 } : {},
|
|
48990
|
+
limit: 200
|
|
48850
48991
|
});
|
|
48851
|
-
|
|
48852
|
-
|
|
48853
|
-
|
|
48854
|
-
|
|
48855
|
-
|
|
48856
|
-
|
|
48857
|
-
|
|
48858
|
-
|
|
48859
|
-
|
|
48860
|
-
|
|
48861
|
-
|
|
48862
|
-
|
|
48863
|
-
|
|
48864
|
-
|
|
48865
|
-
|
|
48866
|
-
|
|
48867
|
-
|
|
48868
|
-
|
|
48869
|
-
|
|
48870
|
-
|
|
48871
|
-
|
|
48872
|
-
|
|
48873
|
-
|
|
48874
|
-
|
|
48875
|
-
|
|
48876
|
-
|
|
48877
|
-
|
|
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
|
|
55715
|
-
|
|
55716
|
-
|
|
55717
|
-
|
|
55718
|
-
|
|
55719
|
-
|
|
55720
|
-
|
|
55721
|
-
|
|
55722
|
-
|
|
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
|
-
|
|
55931
|
+
agentBinary: localConfig.agentBinary,
|
|
55932
|
+
agentKind: selectedAgent.kind,
|
|
55933
|
+
agentCommand: selectedAgent.command,
|
|
55934
|
+
agentArgs: selectedAgent.args,
|
|
55725
55935
|
modelSelection: { model: grant.model },
|
|
55726
|
-
|
|
55727
|
-
|
|
55936
|
+
mcpBinary: localConfig.mcpBinary,
|
|
55937
|
+
agentIdentity,
|
|
55938
|
+
bodyIdentity: identityFromKey(grant.bodySecretKey, DEFAULT_BODY_IDENTITY_NAME),
|
|
55939
|
+
...options.supervisorRoot ? { supervisorRoot: options.supervisorRoot } : {}
|
|
55728
55940
|
});
|
|
55729
|
-
|
|
55730
|
-
|
|
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
|
|
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:
|
|
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
|
|
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
|
-
|
|
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 [
|
|
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
|