usebeeline 0.0.2 → 0.0.3

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 +227 -46
  2. package/package.json +1 -1
@@ -47718,6 +47718,13 @@ Deliver artifacts from this corner; there is no branch to land.`;
47718
47718
  }
47719
47719
  /** Human decision path retained for a named repository outside the Room binding. */
47720
47720
  async cornerOpenAudience(roomId, requesterPubkey) {
47721
+ if (this.daemonApi) {
47722
+ const authority = await this.daemonApi.execute("getRoomAuthority", {
47723
+ roomId,
47724
+ principalId: requesterPubkey
47725
+ });
47726
+ return authority.member && authority.principalKind === "human" ? [requesterPubkey] : [];
47727
+ }
47721
47728
  const members = await listMembers(this.agentClientContext(), roomId);
47722
47729
  const candidates = members.filter((member2) => member2.pubkey === requesterPubkey || member2.role === "admin" || member2.role === "owner");
47723
47730
  const checked = await Promise.all(candidates.map(async (member2) => ({
@@ -47756,9 +47763,10 @@ Deliver artifacts from this corner; there is no branch to land.`;
47756
47763
  message: published.message
47757
47764
  };
47758
47765
  }
47759
- const permissionId = randomUUID5();
47766
+ const permissionId = this.daemonApi ? createHash10("sha256").update(`corner-permission\0${input.roomId}\0${input.request.eventId}`).digest("hex") : randomUUID5();
47760
47767
  const repository2 = input.roomRepo ? this.repoId(input.roomRepo) : "repo-less";
47761
- const audience = await this.cornerOpenAudience(input.roomId, input.request.authorPubkey);
47768
+ const principalId = input.request.delegation?.rootHumanPubkey ?? input.request.authorPubkey;
47769
+ const audience = await this.cornerOpenAudience(input.roomId, principalId);
47762
47770
  if (audience.length === 0) {
47763
47771
  throw new AgentToolKnownFailure("approval_audience_unavailable", "No eligible human is available to decide this corner request.", true);
47764
47772
  }
@@ -47766,7 +47774,18 @@ Deliver artifacts from this corner; there is no branch to land.`;
47766
47774
  const requester = requesterAttribution?.handle ?? fallbackPersonName(input.request.authorPubkey);
47767
47775
  const agent = (await this.roomAuthorAttributions(input.roomId, [this.agentIdentity.publicKey])).get(this.agentIdentity.publicKey)?.name ?? fallbackAgentName(this.agentIdentity.publicKey);
47768
47776
  const message2 = `@${requester.replace(/^@/, "")} asked ${agent} to open a corner for: ` + input.objective;
47769
- const card = buildControlMessage("permission-request", input.roomId, this.agentIdentity, message2, [
47777
+ const card = this.daemonApi ? await this.daemonApi.execute("postPermissionRequest", {
47778
+ roomId: input.roomId,
47779
+ principalId,
47780
+ permissionId,
47781
+ requestId: input.request.eventId,
47782
+ scope: {
47783
+ type: "operation.execute",
47784
+ connectorId: input.tool,
47785
+ target: repository2,
47786
+ payloadDigest: createHash10("sha256").update(input.objective).digest("hex")
47787
+ }
47788
+ }) : buildControlMessage("permission-request", input.roomId, this.agentIdentity, message2, [
47770
47789
  ["t", WRITE_PERMISSION_REQUEST_TAG],
47771
47790
  ["permission", permissionId],
47772
47791
  ["request", input.request.eventId],
@@ -47779,7 +47798,8 @@ Deliver artifacts from this corner; there is no branch to land.`;
47779
47798
  ...this.delegatedReplyTags(input.request),
47780
47799
  ...audience.map((pubkey2) => ["p", pubkey2])
47781
47800
  ]);
47782
- await publishEvent2(card, this.agentIdentity);
47801
+ if (!this.daemonApi)
47802
+ await publishEvent2(card, this.agentIdentity);
47783
47803
  void this.finishCornerApproval({ ...input, permissionId, repository: repository2, audience }).catch((error) => console.error("[body] corner approval settlement failed:", error));
47784
47804
  return { request_id: permissionId, event_id: card.id, message: message2 };
47785
47805
  })();
@@ -47792,6 +47812,8 @@ Deliver artifacts from this corner; there is no branch to land.`;
47792
47812
  * the signed pending card already authored for this exact member request.
47793
47813
  */
47794
47814
  async publishedCornerApproval(input) {
47815
+ if (this.daemonApi)
47816
+ return void 0;
47795
47817
  const repository2 = input.roomRepo ? this.repoId(input.roomRepo) : "repo-less";
47796
47818
  const events = await this.agentRelay.queryEvents([
47797
47819
  {
@@ -47811,9 +47833,11 @@ Deliver artifacts from this corner; there is no branch to land.`;
47811
47833
  return { permissionId, eventId: event.id, message: event.content, repository: repository2, audience };
47812
47834
  }
47813
47835
  async finishCornerApproval(input) {
47836
+ const principalId = input.request.delegation?.rootHumanPubkey ?? input.request.authorPubkey;
47814
47837
  let deciderPubkey;
47815
47838
  const decision = await this.waitForWritePermissionDecision(input.roomId, input.permissionId, input.request.eventId, input.repository, 10 * 6e4, {
47816
47839
  allowedResponders: new Set(input.audience),
47840
+ principalId,
47817
47841
  captureDecider: (pubkey2) => {
47818
47842
  deciderPubkey = pubkey2;
47819
47843
  }
@@ -47823,44 +47847,61 @@ Deliver artifacts from this corner; there is no branch to land.`;
47823
47847
  if (decision === "allow") {
47824
47848
  try {
47825
47849
  const info = await this.openSubchannelForRequest(input.roomId, input.roomRepo, input.objective, input.request, { objective: input.objective, suppressOpenCard: true });
47826
- await this.postWritePermissionStatus(input.roomId, input.permissionId, input.request.eventId, input.tool, input.repository, "allowed", `Corner approved by @${deciderHandle.replace(/^@/, "")} \u2014 view \u2192`, info.subchannelId, deciderPubkey, input.request.authorPubkey);
47850
+ 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
47851
  this.startCornerTaskOnce(info, input.objective, cornerOpenTaskPrompt(info.taskDescription, input.objective), {
47828
47852
  requestId: input.request.eventId,
47829
47853
  originalRequestId: input.request.eventId,
47830
47854
  cause: "corner-opening"
47831
47855
  });
47832
47856
  } catch (error) {
47833
- await this.postWritePermissionStatus(input.roomId, input.permissionId, input.request.eventId, input.tool, input.repository, "failed", `Corner approved by @${deciderHandle.replace(/^@/, "")}, but it could not start: ${this.safePermissionFailure(error)}`, void 0, deciderPubkey, input.request.authorPubkey);
47857
+ 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
47858
  }
47835
47859
  return;
47836
47860
  }
47837
- await this.postWritePermissionStatus(input.roomId, input.permissionId, input.request.eventId, input.tool, input.repository, decision === "deny" ? "denied" : "expired", decision === "deny" ? `Corner denied by @${deciderHandle.replace(/^@/, "")}.` : "The corner request expired without a decision.", void 0, deciderPubkey, input.request.authorPubkey);
47861
+ 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
47862
  }
47839
47863
  async requestEditCornerApproval(input) {
47840
47864
  const { tlcChannelId, turn, repository: repository2, tool, objective, namedTarget, pendingMessage } = input;
47841
- const permissionId = randomUUID5();
47842
- const audience = await this.cornerOpenAudience(tlcChannelId, turn.request.authorPubkey);
47865
+ const permissionId = this.daemonApi ? createHash10("sha256").update(`edit-permission\0${tlcChannelId}\0${turn.request.eventId}`).digest("hex") : randomUUID5();
47866
+ const principalId = turn.request.delegation?.rootHumanPubkey ?? turn.request.authorPubkey;
47867
+ const audience = await this.cornerOpenAudience(tlcChannelId, principalId);
47843
47868
  if (audience.length === 0) {
47844
47869
  throw new AgentToolKnownFailure("approval_audience_unavailable", "No eligible human is available to decide this corner request.", true);
47845
47870
  }
47846
- const requesterAttribution = turn.request.delegation ? (await this.roomAuthorAttributions(tlcChannelId, [turn.request.authorPubkey])).get(turn.request.authorPubkey) : turn.request.authorAttribution;
47847
- const requester = requesterAttribution?.handle ?? fallbackPersonName(turn.request.authorPubkey);
47848
- await postControlMessage("permission-request", tlcChannelId, this.agentIdentity, `@${requester.replace(/^@/, "")} asked ${this.agentIdentity.name || "the agent"} to open a corner for: ${objective || pendingMessage}`, [
47849
- ["t", WRITE_PERMISSION_REQUEST_TAG],
47850
- ["permission", permissionId],
47851
- ["request", turn.request.eventId],
47852
- ["requester", turn.request.authorPubkey],
47853
- ["agent", this.agentIdentity.publicKey],
47854
- ...audience.map((pubkey2) => ["p", pubkey2]),
47855
- ["tool", tool],
47856
- ["repo", repository2],
47857
- ["objective", objective],
47858
- ["status", "pending"],
47859
- ...this.delegatedReplyTags(turn.request)
47860
- ]);
47871
+ const requesterAttribution = turn.request.delegation ? (await this.roomAuthorAttributions(tlcChannelId, [principalId])).get(principalId) : turn.request.authorAttribution;
47872
+ const requester = requesterAttribution?.handle ?? fallbackPersonName(principalId);
47873
+ if (this.daemonApi) {
47874
+ await this.daemonApi.execute("postPermissionRequest", {
47875
+ roomId: tlcChannelId,
47876
+ principalId,
47877
+ permissionId,
47878
+ requestId: turn.request.eventId,
47879
+ scope: {
47880
+ type: "operation.execute",
47881
+ connectorId: tool,
47882
+ target: repository2,
47883
+ payloadDigest: createHash10("sha256").update(objective || pendingMessage).digest("hex")
47884
+ }
47885
+ });
47886
+ } else {
47887
+ await postControlMessage("permission-request", tlcChannelId, this.agentIdentity, `@${requester.replace(/^@/, "")} asked ${this.agentIdentity.name || "the agent"} to open a corner for: ${objective || pendingMessage}`, [
47888
+ ["t", WRITE_PERMISSION_REQUEST_TAG],
47889
+ ["permission", permissionId],
47890
+ ["request", turn.request.eventId],
47891
+ ["requester", turn.request.authorPubkey],
47892
+ ["agent", this.agentIdentity.publicKey],
47893
+ ...audience.map((pubkey2) => ["p", pubkey2]),
47894
+ ["tool", tool],
47895
+ ["repo", repository2],
47896
+ ["objective", objective],
47897
+ ["status", "pending"],
47898
+ ...this.delegatedReplyTags(turn.request)
47899
+ ]);
47900
+ }
47861
47901
  let deciderPubkey;
47862
47902
  const decision = await this.waitForWritePermissionDecision(tlcChannelId, permissionId, turn.request.eventId, repository2, 10 * 6e4, {
47863
47903
  allowedResponders: new Set(audience),
47904
+ principalId,
47864
47905
  captureDecider: (pubkey2) => {
47865
47906
  deciderPubkey = pubkey2;
47866
47907
  }
@@ -47876,7 +47917,7 @@ Deliver artifacts from this corner; there is no branch to land.`;
47876
47917
  suppressOpenCard: true
47877
47918
  }) : await this.openSubchannel(tlcChannelId, boundRepo, objective, { ...turn.request, content: objective }, { objective, suppressOpenCard: true });
47878
47919
  turn.transitionedToCorner = true;
47879
- await this.postWritePermissionStatus(tlcChannelId, permissionId, turn.request.eventId, tool, repository2, "allowed", `Corner approved by @${deciderHandle.replace(/^@/, "")} \u2014 view \u2192`, info.subchannelId, deciderPubkey, turn.request.authorPubkey).catch((statusError) => console.error("[body] failed to publish direct corner navigation:", statusError));
47920
+ 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
47921
  this.startCornerTaskOnce(info, objective, cornerOpenTaskPrompt(info.taskDescription, objective), {
47881
47922
  requestId: turn.request.eventId,
47882
47923
  originalRequestId: turn.request.eventId,
@@ -47889,10 +47930,10 @@ Deliver artifacts from this corner; there is no branch to land.`;
47889
47930
  return;
47890
47931
  }
47891
47932
  if (decision === "deny") {
47892
- await this.postWritePermissionStatus(tlcChannelId, permissionId, turn.request.eventId, tool, repository2, "denied", `Corner denied by @${deciderHandle.replace(/^@/, "")}.`, void 0, deciderPubkey, turn.request.authorPubkey);
47933
+ await this.postWritePermissionStatus(tlcChannelId, permissionId, turn.request.eventId, tool, repository2, "denied", `Corner denied by @${deciderHandle.replace(/^@/, "")}.`, void 0, deciderPubkey, principalId);
47893
47934
  return;
47894
47935
  }
47895
- await this.postWritePermissionStatus(tlcChannelId, permissionId, turn.request.eventId, tool, repository2, "expired", `The edit request for ${repository2} expired. The Agent remains read-only.`, void 0, void 0, turn.request.authorPubkey);
47936
+ 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
47937
  }
47897
47938
  permissionToolLabel(permission) {
47898
47939
  const title = permission.toolCall?.title?.trim();
@@ -48203,6 +48244,26 @@ Deliver artifacts from this corner; there is no branch to land.`;
48203
48244
  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
48245
  }
48205
48246
  postWritePermissionStatus(tlcChannelId, permissionId, requestId, tool, repository2, status, message2, subchannelId, deciderPubkey, requesterPubkey) {
48247
+ if (this.daemonApi) {
48248
+ const publishStatus = async () => {
48249
+ if (requesterPubkey && (status === "allowed" || status === "failed" || status === "expired")) {
48250
+ await this.daemonApi.execute("postPermissionExecution", {
48251
+ roomId: tlcChannelId,
48252
+ principalId: requesterPubkey,
48253
+ permissionId,
48254
+ status: status === "allowed" ? "succeeded" : "failed",
48255
+ result: message2
48256
+ });
48257
+ }
48258
+ await this.daemonApi.execute("postRoomMessage", {
48259
+ roomId: tlcChannelId,
48260
+ requestId,
48261
+ text: message2,
48262
+ presentation: "system"
48263
+ });
48264
+ };
48265
+ return publishStatus();
48266
+ }
48206
48267
  return postControlMessage("permission-status", tlcChannelId, this.agentIdentity, message2, [
48207
48268
  ["t", WRITE_PERMISSION_REQUEST_TAG],
48208
48269
  ["permission", permissionId],
@@ -48227,6 +48288,53 @@ Deliver artifacts from this corner; there is no branch to land.`;
48227
48288
  * pending decision until timeout.
48228
48289
  */
48229
48290
  async waitForWritePermissionDecision(tlcChannelId, permissionId, requestId, repository2, timeoutMs = 10 * 6e4, options = {}) {
48291
+ if (this.daemonApi) {
48292
+ if (!options.principalId)
48293
+ throw new Error("monolith permission wait requires a principal");
48294
+ const deadline2 = Date.now() + timeoutMs;
48295
+ return new Promise((resolvePromise, rejectPromise) => {
48296
+ let settled = false;
48297
+ let polling = false;
48298
+ const finish = (result) => {
48299
+ if (settled)
48300
+ return;
48301
+ settled = true;
48302
+ clearTimeout(timer);
48303
+ clearInterval(backstop);
48304
+ resolvePromise(result);
48305
+ };
48306
+ const pollOnce = async () => {
48307
+ if (settled || polling)
48308
+ return;
48309
+ polling = true;
48310
+ try {
48311
+ const authority = await this.daemonApi.execute("getPermissionAuthority", {
48312
+ roomId: tlcChannelId,
48313
+ principalId: options.principalId,
48314
+ permissionId
48315
+ });
48316
+ if (authority.status === "authorized")
48317
+ finish("allow");
48318
+ if (authority.status === "denied")
48319
+ finish("deny");
48320
+ } catch (error) {
48321
+ if (!isTransientPermissionPollError(error)) {
48322
+ settled = true;
48323
+ clearTimeout(timer);
48324
+ clearInterval(backstop);
48325
+ rejectPromise(error);
48326
+ }
48327
+ } finally {
48328
+ polling = false;
48329
+ }
48330
+ };
48331
+ const timer = setTimeout(() => finish("timeout"), Math.max(0, deadline2 - Date.now()));
48332
+ timer.unref?.();
48333
+ const backstop = setInterval(() => void pollOnce(), WRITE_PERMISSION_BACKSTOP_POLL_MS);
48334
+ backstop.unref?.();
48335
+ void pollOnce();
48336
+ });
48337
+ }
48230
48338
  const startedAt = Math.floor(Date.now() / 1e3) - 1;
48231
48339
  const deadline = Date.now() + timeoutMs;
48232
48340
  const matchingDecision = async (event) => {
@@ -51176,6 +51284,55 @@ async function assertRuntimeStorageWritable(supervisorRoot, agentPubkey) {
51176
51284
  await rm7(probe, { force: true }).catch(() => void 0);
51177
51285
  }
51178
51286
  }
51287
+ async function stageMonolithAgentRuntime(input) {
51288
+ const supervisorRoot = input.supervisorRoot ? resolve28(input.supervisorRoot) : defaultSupervisorRoot(input.env);
51289
+ const baseUrl = new URL(input.monolithBaseUrl).origin;
51290
+ if (baseUrl !== input.monolithBaseUrl || !/^https?:$/.test(new URL(baseUrl).protocol)) {
51291
+ throw new Error("monolith base URL must be an HTTP or HTTPS origin");
51292
+ }
51293
+ if (!/^bde_[A-Za-z0-9_-]{43}$/.test(input.daemonExchangeToken)) {
51294
+ throw new Error("daemon exchange token is invalid");
51295
+ }
51296
+ const configPath = resolve28(runtimeDirectory(supervisorRoot, input.agentIdentity.publicKey), "runtime.json");
51297
+ if (await agentRuntimeExists(supervisorRoot, input.agentIdentity.publicKey)) {
51298
+ const existing = await readRuntimeRecord(configPath);
51299
+ const transport = existing.transport;
51300
+ 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);
51301
+ if (!sameRuntime) {
51302
+ throw new Error(`agent identity ${input.agentIdentity.publicKey} already has another runtime`);
51303
+ }
51304
+ return { runtime: existing, configPath };
51305
+ }
51306
+ await assertRuntimeStorageWritable(supervisorRoot, input.agentIdentity.publicKey);
51307
+ const runtime = {
51308
+ version: 2,
51309
+ communityId: input.workspaceId,
51310
+ pairedBy: input.pairedBy,
51311
+ agent: storeIdentity(input.agentIdentity, DEFAULT_AGENT_IDENTITY_NAME),
51312
+ body: storeIdentity(input.bodyIdentity, DEFAULT_BODY_IDENTITY_NAME),
51313
+ rooms: [],
51314
+ supervisorRoot,
51315
+ // Required only by legacy records. Monolith runtimes never construct a
51316
+ // relay client, so retaining the server origin here cannot route traffic.
51317
+ relayBaseUrl: baseUrl,
51318
+ transport: {
51319
+ kind: "monolith",
51320
+ baseUrl,
51321
+ exchangeToken: input.daemonExchangeToken
51322
+ },
51323
+ ...input.llmEnvFile ? { llmEnvFile: input.llmEnvFile } : {},
51324
+ accessPolicy: DEFAULT_ACCESS_POLICY,
51325
+ ...input.modelSelection?.model || input.modelSelection?.effort ? { modelSelection: input.modelSelection } : {},
51326
+ agentKind: input.agentKind,
51327
+ agentCommand: input.agentCommand,
51328
+ agentArgs: [...input.agentArgs ?? []],
51329
+ agentBinary: input.agentBinary,
51330
+ mcpBinary: input.mcpBinary,
51331
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
51332
+ };
51333
+ const writtenPath = await writeRuntimeRecord(runtime);
51334
+ return { runtime, configPath: writtenPath };
51335
+ }
51179
51336
  async function writeRuntimePointer(gitCommonDir, agentPubkey, targetConfigPath) {
51180
51337
  const directory = runtimeDirectory(gitCommonDir, agentPubkey);
51181
51338
  const path = resolve28(directory, "runtime.json");
@@ -55703,33 +55860,49 @@ async function pairOneAgent(input) {
55703
55860
  throw error;
55704
55861
  }
55705
55862
  }
55706
- async function completeDevicePairing(grant) {
55707
- const selectedAgent = await selectPairAgentCommand({
55863
+ async function completeDevicePairing(grant, options = {}) {
55864
+ const selectedAgent = options.selectedAgent ?? await selectPairAgentCommand({
55708
55865
  explicitKind: grant.harness,
55709
55866
  env: process.env,
55710
55867
  cwd: process.cwd(),
55711
55868
  interactive: true,
55712
55869
  confirmInstall: async () => true
55713
55870
  });
55714
- const result = await pairOneAgent({
55715
- code: grant.pairingCode,
55716
- selectedAgent,
55717
- agentIdentity: identityFromKey(grant.agentSecretKey, grant.agentName),
55718
- bodyIdentity: identityFromKey(grant.bodySecretKey, DEFAULT_BODY_IDENTITY_NAME),
55719
- cwd: process.cwd(),
55720
- repo: null,
55721
- progressLabel: "Connecting agent\u2026",
55722
- progressDone: (pid) => `Connected (pid ${pid}).`,
55871
+ const localConfig = options.localConfig ?? loadBodyConfig({
55872
+ workspaceRoot: process.cwd(),
55873
+ ...grant.llmEnvFile ? { llmEnvFile: grant.llmEnvFile } : {},
55874
+ agent: selectedAgent
55875
+ });
55876
+ await (options.validateSelection ?? validateModelSelection)(selectedAgent, localConfig.agentEnv, {
55877
+ model: grant.model
55878
+ });
55879
+ const agentIdentity = identityFromKey(grant.agentSecretKey, grant.agentName);
55880
+ const staged = await stageMonolithAgentRuntime({
55881
+ workspaceId: grant.workspaceId,
55882
+ pairedBy: grant.pairedBy,
55883
+ monolithBaseUrl: grant.monolithBaseUrl,
55884
+ daemonExchangeToken: grant.daemonExchangeToken,
55723
55885
  ...grant.llmEnvFile ? { llmEnvFile: grant.llmEnvFile } : {},
55724
- access: "creator",
55886
+ agentBinary: localConfig.agentBinary,
55887
+ agentKind: selectedAgent.kind,
55888
+ agentCommand: selectedAgent.command,
55889
+ agentArgs: selectedAgent.args,
55725
55890
  modelSelection: { model: grant.model },
55726
- agentProfile: { displayName: grant.agentName, personality: grant.soul },
55727
- interactiveUi: false
55891
+ mcpBinary: localConfig.mcpBinary,
55892
+ agentIdentity,
55893
+ bodyIdentity: identityFromKey(grant.bodySecretKey, DEFAULT_BODY_IDENTITY_NAME),
55894
+ ...options.supervisorRoot ? { supervisorRoot: options.supervisorRoot } : {}
55728
55895
  });
55729
- if (result.pairing.communityId !== grant.workspaceId) {
55730
- throw new Error("approved Workspace did not match the pairing grant");
55896
+ const activated = await activateDaemonTransport(staged.configPath, options.fetchImpl);
55897
+ if (!activated)
55898
+ throw new Error("monolith daemon transport activation failed");
55899
+ let pid;
55900
+ try {
55901
+ pid = await (options.launch ?? (async (configPath, publicKey) => process.platform === "linux" && process.env.BEELINE_SYSTEMD_USER !== "0" ? installAgentService(publicKey) : launchRuntimeDaemon(configPath)))(staged.configPath, agentIdentity.publicKey);
55902
+ } catch (error) {
55903
+ 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
55904
  }
55732
- return result;
55905
+ return { runtime: activated.runtime, configPath: staged.configPath, pid };
55733
55906
  }
55734
55907
  function printPairResult(result) {
55735
55908
  console.log(`[buzz] paired agent ${import_picocolors3.default.bold(result.pairing.agent.displayName)}`);
@@ -56123,7 +56296,6 @@ async function runConnectCommand(code, options = {}) {
56123
56296
  const llmEnvFile = await writeProviderEnv(selection, grant.agent_pubkey);
56124
56297
  const grantPath = resolve37(defaultSupervisorRoot(process.env), "beeline", "connect", `grant-${process.pid}-${Date.now()}.json`);
56125
56298
  await writePrivateJson(grantPath, {
56126
- pairingCode: grant.pairing_code,
56127
56299
  agentSecretKey: grant.agent_secret_key,
56128
56300
  bodySecretKey: grant.body_secret_key,
56129
56301
  agentName: grant.agent_name,
@@ -56132,6 +56304,9 @@ async function runConnectCommand(code, options = {}) {
56132
56304
  soul: grant.soul,
56133
56305
  workspaceId: grant.workspace_id,
56134
56306
  workspaceName: grant.workspace_name,
56307
+ pairedBy: grant.paired_by,
56308
+ monolithBaseUrl: baseUrl,
56309
+ daemonExchangeToken: grant.daemon_exchange_token,
56135
56310
  ...llmEnvFile ? { llmEnvFile } : {}
56136
56311
  });
56137
56312
  await brassSpinner("Starting your agent\u2026", () => runInstalledFinish(installedBinary, grantPath));
@@ -56144,7 +56319,13 @@ function isDevicePairingGrant(value) {
56144
56319
  if (!value || typeof value !== "object")
56145
56320
  return false;
56146
56321
  const grant = value;
56147
- return typeof grant.pairingCode === "string" && typeof grant.agentSecretKey === "string" && /^[0-9a-f]{64}$/.test(grant.agentSecretKey) && typeof grant.bodySecretKey === "string" && /^[0-9a-f]{64}$/.test(grant.bodySecretKey) && typeof grant.agentName === "string" && CONNECT_HARNESSES.includes(grant.harness) && typeof grant.model === "string" && typeof grant.soul === "string" && typeof grant.workspaceId === "string" && typeof grant.workspaceName === "string";
56322
+ let monolithOrigin = "";
56323
+ try {
56324
+ monolithOrigin = new URL(grant.monolithBaseUrl ?? "").origin;
56325
+ } catch {
56326
+ return false;
56327
+ }
56328
+ 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
56329
  }
56149
56330
  async function runConnectFinishCommand(path) {
56150
56331
  if (!path)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "usebeeline",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
4
4
  "description": "Connect an AI coding agent to Beeline with one command.",
5
5
  "repository": {
6
6
  "type": "git",