usebeeline 0.0.46 → 0.0.48

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/usebeeline.mjs +93 -13
  2. package/package.json +1 -1
@@ -2952,8 +2952,12 @@ function parseSandboxMaskEnv(env) {
2952
2952
  }
2953
2953
 
2954
2954
  // apps/body/dist/access-policy.js
2955
+ var AGENT_ACCESS_POLICIES = ["everyone", "creator", "allowlist"];
2955
2956
  var DEFAULT_ACCESS_POLICY = "creator";
2956
2957
  var LEGACY_ACCESS_POLICY = "everyone";
2958
+ function isAgentAccessPolicy(value) {
2959
+ return AGENT_ACCESS_POLICIES.includes(value);
2960
+ }
2957
2961
  var ACCESS_REFUSAL_WINDOW_MS = 60 * 60 * 1e3;
2958
2962
  function isSenderPermitted(policy, senderPubkey, ownerPubkey, allowlist = void 0) {
2959
2963
  if (!senderPubkey)
@@ -13059,7 +13063,7 @@ async function stageMonolithAgentRuntime(input) {
13059
13063
  supervisorRoot,
13060
13064
  transport: { kind: "monolith", baseUrl, exchangeToken: input.daemonExchangeToken },
13061
13065
  ...input.llmEnvFile ? { llmEnvFile: input.llmEnvFile } : {},
13062
- accessPolicy: DEFAULT_ACCESS_POLICY,
13066
+ accessPolicy: input.accessPolicy ?? DEFAULT_ACCESS_POLICY,
13063
13067
  agentBinary: input.agentBinary,
13064
13068
  agentKind: input.agentKind,
13065
13069
  agentCommand: input.agentCommand,
@@ -17117,8 +17121,16 @@ async function waitForWake(api, cornerId, signal) {
17117
17121
  try {
17118
17122
  await api.execute("waitForCornerWake", { cornerId });
17119
17123
  } catch {
17124
+ await never(signal);
17120
17125
  }
17121
17126
  }
17127
+ async function never(signal) {
17128
+ if (signal?.aborted)
17129
+ return;
17130
+ await new Promise((resolveNever) => {
17131
+ signal?.addEventListener("abort", () => resolveNever(), { once: true });
17132
+ });
17133
+ }
17122
17134
  async function wait(ms, signal) {
17123
17135
  if (signal?.aborted)
17124
17136
  return;
@@ -17142,6 +17154,24 @@ import { join as join6 } from "node:path";
17142
17154
  var SCHEDULE_SCHEDULER_NAME = "Beeline Scheduler";
17143
17155
  var SCHEDULE_RAN_VERB = "ran a schedule for";
17144
17156
 
17157
+ // packages/api-contract/dist/system-events.js
17158
+ var SERVER_EVENT_KINDS = [
17159
+ "joined",
17160
+ "schedule-ran",
17161
+ "corner-opened",
17162
+ "check-passed",
17163
+ "check-failed",
17164
+ "merged",
17165
+ "grant-decided"
17166
+ ];
17167
+ function isServerEventKind(value) {
17168
+ return SERVER_EVENT_KINDS.includes(value);
17169
+ }
17170
+ var RESUME_KINDS = ["grant-decided"];
17171
+ function isResumeKind(value) {
17172
+ return RESUME_KINDS.includes(value);
17173
+ }
17174
+
17145
17175
  // apps/body/dist/monolith-room-turn.js
17146
17176
  function isRoomMcpPermissionRequest(request, mountedServers = ROOM_MOUNTED_MCP_SERVERS) {
17147
17177
  if (isSquireMcpPermissionRequest(request))
@@ -17152,11 +17182,35 @@ function roomPrincipalMayAddressAgent(authority, humanPermitted) {
17152
17182
  return authority.member && (authority.principalKind === "agent" || authority.principalKind === "human" && humanPermitted);
17153
17183
  }
17154
17184
  function isScheduledPrompt(item, agentId) {
17155
- return item.type === "system" && item.systemEvent?.verb === SCHEDULE_RAN_VERB && item.mentionIds.includes(agentId);
17185
+ if (item.type !== "system" || !item.mentionIds.includes(agentId))
17186
+ return false;
17187
+ if (item.systemEvent?.kind)
17188
+ return item.systemEvent.kind === "schedule-ran";
17189
+ return item.systemEvent?.verb === SCHEDULE_RAN_VERB;
17190
+ }
17191
+ function inboxItemAuthorName(item, agentId, names) {
17192
+ if (isScheduledPrompt(item, agentId))
17193
+ return SCHEDULE_SCHEDULER_NAME;
17194
+ const subject = item.systemEvent?.subject;
17195
+ if (item.type === "system" && subject?.name)
17196
+ return subject.name;
17197
+ return names.get(item.authorId) ?? item.authorId.slice(0, 12);
17156
17198
  }
17157
17199
  function inboxItemPromptBody(item, agentId) {
17158
17200
  return isScheduledPrompt(item, agentId) ? item.systemEvent?.consequence ?? item.body : item.body;
17159
17201
  }
17202
+ function isSubscribedEvent(item, agentId) {
17203
+ const kind = item.systemEvent?.kind;
17204
+ return item.type === "system" && kind !== void 0 && !isResumeKind(kind) && item.mentionIds.includes(agentId);
17205
+ }
17206
+ function inboxItemSkipsSenderPolicy(item, agentId) {
17207
+ if (isGrantDecisionLine(item, agentId))
17208
+ return true;
17209
+ if (item.type !== "system" || !item.mentionIds.includes(agentId))
17210
+ return false;
17211
+ const kind = item.systemEvent?.kind;
17212
+ return kind === void 0 ? isScheduledPrompt(item, agentId) : isServerEventKind(kind);
17213
+ }
17160
17214
  function isGrantDecisionLine(item, agentId) {
17161
17215
  return item.type === "system" && item.mentionIds.includes(agentId) && parseGrantDecisionLine(item.body) !== void 0;
17162
17216
  }
@@ -17165,7 +17219,7 @@ function inboxItemTriggersTurn(item, agentId) {
17165
17219
  return false;
17166
17220
  if (!item.mentionIds.includes(agentId))
17167
17221
  return false;
17168
- return item.type === "message" || isScheduledPrompt(item, agentId) || isGrantDecisionLine(item, agentId);
17222
+ return item.type === "message" || isSubscribedEvent(item, agentId) || isScheduledPrompt(item, agentId) || isGrantDecisionLine(item, agentId);
17169
17223
  }
17170
17224
  function pendingGrantToolCall(call) {
17171
17225
  if (!/(?:^|[._:/-])request_grant$/i.test(call.title ?? ""))
@@ -17657,7 +17711,7 @@ var MonolithRoomTurnLoop = class {
17657
17711
  const buildPrompt = () => [
17658
17712
  this.turnInstructionPrefix,
17659
17713
  WarmTranscript.render(this.warmTranscript.select(this.sessionId, transcriptRows), "Room conversation so far:", "New in the Room since your last turn (the earlier conversation is already in this session):"),
17660
- `Newest message from ${isScheduledPrompt(item, this.agent.publicKey) ? SCHEDULE_SCHEDULER_NAME : names.get(item.authorId) ?? item.authorId.slice(0, 12)}:`,
17714
+ `Newest message from ${inboxItemAuthorName(item, this.agent.publicKey, names)}:`,
17661
17715
  roomMessagePrompt("", inboxItemPromptBody(item, this.agent.publicKey), item.attachments, delivered, this.acceptsImages()),
17662
17716
  grantDecision ? [
17663
17717
  "This is the answer to your grant request; your paused work resumes now.",
@@ -17819,7 +17873,7 @@ var MonolithRoomTurnLoop = class {
17819
17873
  for (const item of inbox.items) {
17820
17874
  if (!inboxItemTriggersTurn(item, this.agent.publicKey))
17821
17875
  continue;
17822
- if (!isScheduledPrompt(item, this.agent.publicKey) && !isGrantDecisionLine(item, this.agent.publicKey)) {
17876
+ if (!inboxItemSkipsSenderPolicy(item, this.agent.publicKey)) {
17823
17877
  const authority = await api.execute("getRoomAuthority", {
17824
17878
  roomId,
17825
17879
  principalId: item.authorId
@@ -19476,6 +19530,7 @@ async function pairDevice(grant, options = {}) {
19476
19530
  agentCommand: selectedAgent.command,
19477
19531
  agentArgs: selectedAgent.args,
19478
19532
  modelSelection: { model: grant.model },
19533
+ ...grant.accessPolicy ? { accessPolicy: grant.accessPolicy } : {},
19479
19534
  mcpBinary: localConfig.mcpBinary,
19480
19535
  agentIdentity,
19481
19536
  bodyIdentity: identityFromKey(grant.bodySecretKey, DEFAULT_BODY_IDENTITY_NAME2),
@@ -19760,7 +19815,12 @@ async function jsonRequest(url, body, fetchImpl) {
19760
19815
  }
19761
19816
  return response.json();
19762
19817
  }
19763
- function requestConnectGrant(baseUrl, pairingCode, selection, fetchImpl) {
19818
+ function parseConnectSubscriptions(value) {
19819
+ return [
19820
+ ...new Set((value ?? "").split(",").map((entry) => entry.trim().toLowerCase()).filter(Boolean))
19821
+ ];
19822
+ }
19823
+ function requestConnectGrant(baseUrl, pairingCode, selection, fetchImpl, eventSubscriptions = []) {
19764
19824
  const normalizedPairingCode = normalizeAgentPairingCode(pairingCode);
19765
19825
  if (!normalizedPairingCode)
19766
19826
  throw new Error("invalid pairing code");
@@ -19770,7 +19830,8 @@ function requestConnectGrant(baseUrl, pairingCode, selection, fetchImpl) {
19770
19830
  harness: selection.harness,
19771
19831
  ...selection.provider ? { provider: selection.provider } : {},
19772
19832
  model: selection.model,
19773
- avatar_seed: avatarSeed
19833
+ avatar_seed: avatarSeed,
19834
+ ...eventSubscriptions.length ? { event_subscriptions: [...eventSubscriptions] } : {}
19774
19835
  }, fetchImpl);
19775
19836
  }
19776
19837
  async function renameConnectedAgent(baseUrl, pairingCode, name, fetchImpl) {
@@ -19877,12 +19938,12 @@ async function runConnectCommand(code, options = {}) {
19877
19938
  }
19878
19939
  const restoreRails = paintWizardBrass();
19879
19940
  try {
19880
- await runConnectWizard(code, options.fetchImpl ?? fetch);
19941
+ await runConnectWizard(code, options.fetchImpl ?? fetch, options.subscribe ?? [], options.accessPolicy);
19881
19942
  } finally {
19882
19943
  restoreRails();
19883
19944
  }
19884
19945
  }
19885
- async function runConnectWizard(code, fetchImpl) {
19946
+ async function runConnectWizard(code, fetchImpl, eventSubscriptions, accessPolicy) {
19886
19947
  intro(brass("Beeline connect"));
19887
19948
  const pairingCode = code?.trim() || await clackPrompts.text({
19888
19949
  message: brass("Pairing code from the app"),
@@ -19890,7 +19951,7 @@ async function runConnectWizard(code, fetchImpl) {
19890
19951
  });
19891
19952
  const selection = await collectConnectWizard(clackPrompts, loadConnectModelCatalog, fileConnectKeyStore, process.env, (input) => verifyProviderKey({ ...input, fetchImpl }));
19892
19953
  const baseUrl = (process.env.BEELINE_AUTH_URL ?? "https://server.usebeeline.app").replace(/\/$/, "");
19893
- const claimed = await brassSpinner("Connecting to your Beeline Workspace\u2026", () => requestConnectGrant(baseUrl, pairingCode, selection, fetchImpl), (connectedGrant) => `Connected to ${connectedGrant.workspace_name}`);
19954
+ const claimed = await brassSpinner("Connecting to your Beeline Workspace\u2026", () => requestConnectGrant(baseUrl, pairingCode, selection, fetchImpl, eventSubscriptions), (connectedGrant) => `Connected to ${connectedGrant.workspace_name}`);
19894
19955
  const grant = { ...claimed, agent_name: await confirmSeededName(baseUrl, pairingCode, claimed, fetchImpl) };
19895
19956
  const installedRelease = await brassSpinner("Installing the Beeline daemon\u2026", () => installCurrentRelease(fetchImpl), (release) => `Installed Beeline helper ${release.version}`);
19896
19957
  const llmEnvFile = await writeProviderEnv(selection, grant.agent_pubkey);
@@ -19907,7 +19968,8 @@ async function runConnectWizard(code, fetchImpl) {
19907
19968
  pairedBy: grant.paired_by,
19908
19969
  monolithBaseUrl: baseUrl,
19909
19970
  daemonExchangeToken: grant.daemon_exchange_token,
19910
- ...llmEnvFile ? { llmEnvFile } : {}
19971
+ ...llmEnvFile ? { llmEnvFile } : {},
19972
+ ...accessPolicy ? { accessPolicy } : {}
19911
19973
  });
19912
19974
  await brassSpinner("Starting your agent\u2026", () => runInstalledFinish(installedRelease.binary, grantPath), () => `Started ${grant.agent_name}`);
19913
19975
  console.log("");
@@ -19947,6 +20009,8 @@ function isDevicePairingGrant(value) {
19947
20009
  if (!value || typeof value !== "object")
19948
20010
  return false;
19949
20011
  const grant = value;
20012
+ if (grant.accessPolicy !== void 0 && !isAgentAccessPolicy(grant.accessPolicy))
20013
+ return false;
19950
20014
  let monolithOrigin = "";
19951
20015
  try {
19952
20016
  monolithOrigin = new URL(grant.monolithBaseUrl ?? "").origin;
@@ -21059,7 +21123,12 @@ function usage(exitCode = 1) {
21059
21123
  ${import_picocolors3.default.bold("Beeline \u2014 thin Room agent.")}
21060
21124
 
21061
21125
  ${import_picocolors3.default.dim("Usage:")}
21062
- beeline connect [XXXXXXXX-XXXXXXXX] Install and connect an app-authorized agent
21126
+ beeline connect [XXXXXXXX-XXXXXXXX] [--subscribe <kinds>] [--access <policy>]
21127
+ Install and connect an app-authorized agent;
21128
+ --subscribe takes a comma-separated list of
21129
+ event kinds it reacts to (e.g. joined);
21130
+ --access is everyone|creator|allowlist
21131
+ (default creator)
21063
21132
  beeline start [agent-pubkey] Start \u2014 or RESTART when already running,
21064
21133
  stopping cleanly after in-flight work \u2014
21065
21134
  this repo's (or, outside a repo, this
@@ -21300,7 +21369,18 @@ async function main() {
21300
21369
  return;
21301
21370
  }
21302
21371
  if (command === "connect") {
21303
- await runConnectCommand(args[1]);
21372
+ const subscribeFlag = args.indexOf("--subscribe");
21373
+ const subscribe = subscribeFlag >= 0 ? parseConnectSubscriptions(args[subscribeFlag + 1]) : [];
21374
+ const accessFlag = args.indexOf("--access");
21375
+ const accessPolicy = accessFlag >= 0 ? args[accessFlag + 1] : void 0;
21376
+ if (accessFlag >= 0 && !isAgentAccessPolicy(accessPolicy)) {
21377
+ throw new Error(`--access must be one of ${AGENT_ACCESS_POLICIES.join(", ")}`);
21378
+ }
21379
+ const code = args[1] && !args[1].startsWith("--") ? args[1] : void 0;
21380
+ await runConnectCommand(code, {
21381
+ ...subscribe.length ? { subscribe } : {},
21382
+ ...isAgentAccessPolicy(accessPolicy) ? { accessPolicy } : {}
21383
+ });
21304
21384
  return;
21305
21385
  }
21306
21386
  if (command === "connect-finish") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "usebeeline",
3
- "version": "0.0.46",
3
+ "version": "0.0.48",
4
4
  "description": "Connect an AI coding agent to Beeline with one command.",
5
5
  "homepage": "https://usebeeline.app",
6
6
  "bugs": {