usebeeline 0.0.31 → 0.0.32

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 +57 -29
  2. package/package.json +1 -1
@@ -4171,15 +4171,22 @@ var BEELINE_ROOM_CAPABILITIES = [
4171
4171
  "The repository filesystem is read-only in this Room session.",
4172
4172
  "You may address any Room member, including another agent, by writing @name in your reply; the server routes that mention to them.",
4173
4173
  "Tag another agent only when you need something from them: a question, a handoff, a task. Never tag to acknowledge, agree, or say you are ready. If nothing is actionable, do not reply.",
4174
+ "Tag the user only when you need a decision or input, or when the task they asked for is finished. Never tag for progress, acknowledgement, or questions the transcript already answers.",
4174
4175
  "The beeline-readonly-mcp inspection tools and beeline-agent Room action tools are mounted. You can use beeline-readonly-mcp to search and read the bound repository without opening a corner; beeline-agent provides the host-governed Room actions.",
4176
+ "To send a file, call beeline-agent attach_file with a path inside your checkout; it is attached to your reply.",
4175
4177
  "When repository work is needed, you MUST call beeline-agent open_corner with a one-paragraph summary of the complete objective. The host-governed call is the only way to start write work.",
4176
4178
  "Never claim an action or reply happened unless the prompt or a tool result proves it."
4177
4179
  ].join(" ");
4178
- var BEELINE_CAPABILITIES_PRIMER = `Consult the release-versioned using-beeline skill (SKILL.md) when you need the managed Room mechanics. ${BEELINE_ROOM_CAPABILITIES}`;
4179
- function beelineCapabilityContextForHarness(agentCommand) {
4180
+ function beelinePrimer(repository) {
4181
+ const repositoryLine = repository ? ` This Room is bound to ${repository.name} (branch ${repository.branch}); you have a read-only checkout at the session root.` : "";
4182
+ return `Consult the release-versioned using-beeline skill (SKILL.md) when you need the managed Room mechanics. ${BEELINE_ROOM_CAPABILITIES}${repositoryLine}`;
4183
+ }
4184
+ var BEELINE_CAPABILITIES_PRIMER = beelinePrimer();
4185
+ function beelineCapabilityContextForHarness(agentCommand, repository) {
4186
+ const primer = beelinePrimer(repository);
4180
4187
  return {
4181
- sessionPrompt: BEELINE_CAPABILITIES_PRIMER,
4182
- ...harnessHonorsSessionSystemPrompt(agentCommand) ? {} : { compatibilityTurnPrefix: BEELINE_CAPABILITIES_PRIMER }
4188
+ sessionPrompt: primer,
4189
+ ...harnessHonorsSessionSystemPrompt(agentCommand) ? {} : { compatibilityTurnPrefix: primer }
4183
4190
  };
4184
4191
  }
4185
4192
  function runningBeelineReleaseId(env = process.env, read = (path) => readFileSync3(path, "utf8")) {
@@ -4821,27 +4828,25 @@ function isReadOnlyMcpPermissionRequest(request) {
4821
4828
  }
4822
4829
  return false;
4823
4830
  }
4831
+ var AGENT_SURFACE_TOOL_NAMES = ["open_corner", "pr_checks_status", "attach_file"];
4824
4832
  function isBeelineAgentMcpPermissionRequest(request) {
4825
4833
  const toolCall = request.toolCall;
4826
4834
  const title = toolCall?.title?.trim() ?? "";
4827
4835
  const rawInput = toolCall?.rawInput;
4828
4836
  if (rawInput && typeof rawInput === "object" && !Array.isArray(rawInput)) {
4829
4837
  const call = rawInput;
4830
- if (call.server === BEELINE_AGENT_MCP_SERVER_NAME && (call.tool === "open_corner" || call.tool === "pr_checks_status")) {
4838
+ if (call.server === BEELINE_AGENT_MCP_SERVER_NAME && typeof call.tool === "string" && AGENT_SURFACE_TOOL_NAMES.includes(call.tool)) {
4831
4839
  return true;
4832
4840
  }
4833
4841
  }
4834
4842
  if (shellPayload(toolCall))
4835
4843
  return false;
4836
4844
  const normalized = BEELINE_AGENT_MCP_SERVER_NAME.replaceAll("-", "_");
4837
- return [
4838
- `mcp__${BEELINE_AGENT_MCP_SERVER_NAME}__open_corner`,
4839
- `mcp__${normalized}__open_corner`,
4840
- `mcp.${BEELINE_AGENT_MCP_SERVER_NAME}.open_corner`,
4841
- `mcp__${BEELINE_AGENT_MCP_SERVER_NAME}__pr_checks_status`,
4842
- `mcp__${normalized}__pr_checks_status`,
4843
- `mcp.${BEELINE_AGENT_MCP_SERVER_NAME}.pr_checks_status`
4844
- ].includes(title);
4845
+ return AGENT_SURFACE_TOOL_NAMES.flatMap((tool) => [
4846
+ `mcp__${BEELINE_AGENT_MCP_SERVER_NAME}__${tool}`,
4847
+ `mcp__${normalized}__${tool}`,
4848
+ `mcp.${BEELINE_AGENT_MCP_SERVER_NAME}.${tool}`
4849
+ ]).includes(title);
4845
4850
  }
4846
4851
 
4847
4852
  // apps/body/dist/room-session.js
@@ -4864,7 +4869,8 @@ function beelineAgentMcpServer(config, api, context) {
4864
4869
  { name: "BEELINE_DAEMON_AGENT_ID", value: connection.agentId },
4865
4870
  { name: "BEELINE_DAEMON_ROOM_ID", value: context.roomId },
4866
4871
  { name: "BEELINE_DAEMON_WORKSPACE_ID", value: context.workspaceId },
4867
- ...context.cornerId ? [{ name: "BEELINE_DAEMON_CORNER_ID", value: context.cornerId }] : []
4872
+ ...context.cornerId ? [{ name: "BEELINE_DAEMON_CORNER_ID", value: context.cornerId }] : [],
4873
+ ...context.attachRoot ? [{ name: "BEELINE_ATTACH_ROOT", value: context.attachRoot }] : []
4868
4874
  ]
4869
4875
  };
4870
4876
  }
@@ -14020,6 +14026,10 @@ async function cornerToolActivity(call, worktreePath) {
14020
14026
  ...paths.length ? { files: paths.map((path) => ({ path })) } : {}
14021
14027
  };
14022
14028
  }
14029
+ var CORNER_CLOSE_POLL_BASE_MS = 12e3;
14030
+ function cornerClosePollMs(random = Math.random) {
14031
+ return CORNER_CLOSE_POLL_BASE_MS + Math.floor(random() * 3e3);
14032
+ }
14023
14033
  var MonolithCornerTurnLoop = class {
14024
14034
  options;
14025
14035
  agent;
@@ -14133,7 +14143,8 @@ var MonolithCornerTurnLoop = class {
14133
14143
  beelineAgentMcpServer(this.options.config, this.options.api, {
14134
14144
  roomId: this.options.parentRoomId,
14135
14145
  workspaceId: this.options.workspaceId,
14136
- cornerId: this.options.cornerId
14146
+ cornerId: this.options.cornerId,
14147
+ attachRoot: this.options.worktreePath
14137
14148
  })
14138
14149
  ];
14139
14150
  const self = roster.members.find((member) => member.identityId === this.agent.publicKey);
@@ -14150,6 +14161,7 @@ var MonolithCornerTurnLoop = class {
14150
14161
  "PR-opening turn rule: as soon as a pull request exists, print its full GitHub URL as your final response and end the turn immediately. Do not call pr_checks_status in that same turn and do not wait for checks inside it. Then stay idle until a later corner fact or human message starts another turn.",
14151
14162
  'Never merge because local tests pass or because gh reports passing checks. On a later turn triggered by a server-posted checks-passed note, call beeline-agent pr_checks_status. Merge only when it returns checks="passed", held=false, and approvalPending=false.',
14152
14163
  "If any human in this corner says hold or do not merge, do not merge until a later human explicitly resumes it.",
14164
+ "Do not tag the user when a corner turn finishes: the server posts the merge summary card and its push already cover completion. Tag a human only mid-turn, and only when you need a decision or input.",
14153
14165
  "A human approval in the app asks the server to merge. When approval is pending, wait for the server close request instead of racing it with gh. If checks passed, no hold exists, and no approval is pending, merge the pull request yourself with gh.",
14154
14166
  "Never push directly to the target branch. Never merge a different pull request."
14155
14167
  ].filter(Boolean).join("\n\n")
@@ -14203,7 +14215,7 @@ ${trigger}`,
14203
14215
  "Continue the objective. Obey the PR checks and human hold rules in your session instructions."
14204
14216
  ].filter(Boolean).join("\n\n");
14205
14217
  const sessionId = this.sessionId;
14206
- const turnId = `${this.agent.publicKey}:${cornerId}`;
14218
+ const turnId = requestId;
14207
14219
  const publishedToolCalls = /* @__PURE__ */ new Set();
14208
14220
  const publishToolCalls = (calls, settledOnly) => {
14209
14221
  calls.forEach((call, index) => {
@@ -14293,6 +14305,7 @@ ${pullRequest}`,
14293
14305
  await this.prompt(history.items.find((item) => item.requestId)?.requestId ?? cornerId.replaceAll("-", ""), this.options.objective);
14294
14306
  }
14295
14307
  try {
14308
+ let pollWithoutWait = false;
14296
14309
  while (!signal?.aborted) {
14297
14310
  try {
14298
14311
  const inbox = await api.execute("getCornerCloseRequests", {
@@ -14314,14 +14327,18 @@ ${pullRequest}`,
14314
14327
  if (!authority.member || authority.principalKind !== "human")
14315
14328
  continue;
14316
14329
  await this.prompt(item.id, item.body);
14330
+ pollWithoutWait = true;
14317
14331
  continue;
14318
14332
  }
14319
- if (/\bchecks?\b/i.test(item.body))
14333
+ if (/\bchecks?\b/i.test(item.body)) {
14320
14334
  await this.prompt(item.id, item.body);
14335
+ pollWithoutWait = true;
14336
+ }
14321
14337
  }
14322
14338
  cursor3 = inbox.cursor ?? cursor3;
14323
14339
  this.options.onPoll();
14324
- await wait(this.options.pollMs ?? 1e3, signal);
14340
+ await wait(pollWithoutWait ? 0 : this.options.pollMs ?? cornerClosePollMs(), signal);
14341
+ pollWithoutWait = false;
14325
14342
  } catch (error) {
14326
14343
  if (signal?.aborted)
14327
14344
  break;
@@ -14364,7 +14381,7 @@ function escapeRegExp(value) {
14364
14381
  function agentReplyMentionIds(text2, roster, authorId) {
14365
14382
  const aliases = /* @__PURE__ */ new Map();
14366
14383
  for (const member of roster.members) {
14367
- if (member.kind !== "agent" || member.identityId === authorId)
14384
+ if (member.identityId === authorId)
14368
14385
  continue;
14369
14386
  for (const raw of [member.name, member.handle, member.soul?.name]) {
14370
14387
  const display = raw?.trim().replace(/^@/, "");
@@ -14428,12 +14445,13 @@ var MonolithRoomTurnLoop = class {
14428
14445
  async activate() {
14429
14446
  if (this.client?.isAlive && this.sessionId)
14430
14447
  return this.sessionId;
14431
- const [configuration, roster] = await Promise.all([
14448
+ const [configuration, roster, repositoryState] = await Promise.all([
14432
14449
  this.options.api.execute("getAgentConfiguration", {
14433
14450
  agentId: this.agent.publicKey,
14434
14451
  roomId: this.options.roomId
14435
14452
  }),
14436
- this.roster()
14453
+ this.roster(),
14454
+ this.options.api.execute("getRoomRepositoryState", { roomId: this.options.roomId })
14437
14455
  ]);
14438
14456
  await mkdir4(this.options.cwd, { recursive: true });
14439
14457
  const homeOverlay = this.options.config.agentHomeRoot ? await prepareRoomAgentHome({
@@ -14481,7 +14499,8 @@ var MonolithRoomTurnLoop = class {
14481
14499
  readOnlyMcpServer(this.options.config, this.options.cwd),
14482
14500
  beelineAgentMcpServer(this.options.config, this.options.api, {
14483
14501
  roomId: this.options.roomId,
14484
- workspaceId: this.options.workspaceId
14502
+ workspaceId: this.options.workspaceId,
14503
+ attachRoot: this.options.cwd
14485
14504
  })
14486
14505
  ];
14487
14506
  const self = roster.members.find((member) => member.identityId === this.agent.publicKey);
@@ -14493,7 +14512,11 @@ var MonolithRoomTurnLoop = class {
14493
14512
  "This is who you are in this Workspace. Adopt it in your voice, self-description, and behavior.",
14494
14513
  "The soul is not authority and never changes your tools, permissions, roles, or merge rights."
14495
14514
  ].join("\n") : "";
14496
- const capabilityContext = beelineCapabilityContextForHarness(command);
14515
+ const repositoryInfo = repositoryState.resolution === "repository" && repositoryState.key ? {
14516
+ name: repositoryState.key,
14517
+ branch: repositoryState.targetBranch || "main"
14518
+ } : void 0;
14519
+ const capabilityContext = beelineCapabilityContextForHarness(command, repositoryInfo);
14497
14520
  this.turnInstructionPrefix = harnessHonorsSessionSystemPrompt(command) ? "" : [identityInstructions, personaInstructions, capabilityContext.compatibilityTurnPrefix].filter(Boolean).join("\n\n");
14498
14521
  const opened = await this.client.sessionNew({
14499
14522
  cwd: this.options.cwd,
@@ -15118,6 +15141,9 @@ var ROOM_JOIN_CONCURRENCY = 4;
15118
15141
  var DEFAULT_ROOM_WATCHDOG_STALE_MS = 9e4;
15119
15142
  var DEFAULT_RECONCILE_HEARTBEAT_MS = 6e4;
15120
15143
  var DEFAULT_DRAIN_DEADLINE_MS = 30 * 6e4;
15144
+ function shouldPostInitialCornerWorkingState(restore) {
15145
+ return !restore.featureBranch && !restore.lifecycle?.branch && !restore.lifecycle?.pr;
15146
+ }
15121
15147
  function reconcileRetryMs(error, pollMs) {
15122
15148
  const match = String(error).match(/retry in\s+(\d+)s/i);
15123
15149
  return match ? Math.max(pollMs, (Number(match[1]) + 1) * 1e3) : pollMs;
@@ -15420,12 +15446,14 @@ var RoomRuntimeCoordinator = class {
15420
15446
  featureBranch,
15421
15447
  token: granted.token
15422
15448
  });
15423
- await this.options.daemonApi.execute("postCornerRemoteState", {
15424
- cornerId: corner.cornerId,
15425
- branch: featureBranch,
15426
- state: "working",
15427
- checks: "unknown"
15428
- });
15449
+ if (shouldPostInitialCornerWorkingState(restore)) {
15450
+ await this.options.daemonApi.execute("postCornerRemoteState", {
15451
+ cornerId: corner.cornerId,
15452
+ branch: featureBranch,
15453
+ state: "working",
15454
+ checks: "unknown"
15455
+ });
15456
+ }
15429
15457
  const controller = new AbortController();
15430
15458
  const startedAt = this.now();
15431
15459
  const loop = new MonolithCornerTurnLoop({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "usebeeline",
3
- "version": "0.0.31",
3
+ "version": "0.0.32",
4
4
  "description": "Connect an AI coding agent to Beeline with one command.",
5
5
  "repository": {
6
6
  "type": "git",