usebeeline 0.0.30 → 0.0.31
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 +83 -15
- package/package.json +1 -1
package/dist/usebeeline.mjs
CHANGED
|
@@ -3193,14 +3193,6 @@ function toolCallEntries(updates) {
|
|
|
3193
3193
|
}
|
|
3194
3194
|
return [...calls.values()];
|
|
3195
3195
|
}
|
|
3196
|
-
function isMutatingPermissionRequest(request) {
|
|
3197
|
-
const tool = request.toolCall;
|
|
3198
|
-
const kind = tool?.kind?.toLowerCase();
|
|
3199
|
-
if (kind && ["edit", "execute", "delete", "move"].includes(kind))
|
|
3200
|
-
return true;
|
|
3201
|
-
const description = [tool?.title, tool?.rawInput].filter((value) => value !== void 0).map((value) => typeof value === "string" ? value : JSON.stringify(value)).join(" ").toLowerCase();
|
|
3202
|
-
return /(^|[^a-z])(str_replace|write|edit|shell|bash|execute|create|delete|remove|move|rename|patch|apply_patch)([^a-z]|$)/.test(description);
|
|
3203
|
-
}
|
|
3204
3196
|
var AcpClient = class extends EventEmitter {
|
|
3205
3197
|
child = null;
|
|
3206
3198
|
buf = "";
|
|
@@ -3227,6 +3219,7 @@ var AcpClient = class extends EventEmitter {
|
|
|
3227
3219
|
inheritProcessEnv;
|
|
3228
3220
|
autoApprove;
|
|
3229
3221
|
permissionHandler;
|
|
3222
|
+
permissionAllowlist;
|
|
3230
3223
|
constructor(opts) {
|
|
3231
3224
|
super();
|
|
3232
3225
|
const command = opts.agentCommand ?? opts.agentBinary;
|
|
@@ -3241,6 +3234,7 @@ var AcpClient = class extends EventEmitter {
|
|
|
3241
3234
|
this.inheritProcessEnv = opts.inheritProcessEnv ?? process.env.BUZZY_BODY_AGENT_ENV_INHERIT === "1";
|
|
3242
3235
|
this.autoApprove = opts.autoApprovePermissions ?? true;
|
|
3243
3236
|
this.permissionHandler = opts.permissionHandler;
|
|
3237
|
+
this.permissionAllowlist = opts.permissionAllowlist;
|
|
3244
3238
|
}
|
|
3245
3239
|
async start(timeoutMs = 6e4) {
|
|
3246
3240
|
if (this.alive)
|
|
@@ -3679,7 +3673,14 @@ var AcpClient = class extends EventEmitter {
|
|
|
3679
3673
|
if (tracked)
|
|
3680
3674
|
p.toolCall = { ...tracked, ...p.toolCall };
|
|
3681
3675
|
let decision = this.autoApprove ? "allow" : "reject";
|
|
3682
|
-
if (this.
|
|
3676
|
+
if (!this.autoApprove && this.permissionAllowlist) {
|
|
3677
|
+
try {
|
|
3678
|
+
decision = this.permissionAllowlist(p) ? "allow" : "reject";
|
|
3679
|
+
} catch (error) {
|
|
3680
|
+
this.emit("permission/error", error);
|
|
3681
|
+
decision = "reject";
|
|
3682
|
+
}
|
|
3683
|
+
} else if (this.permissionHandler) {
|
|
3683
3684
|
try {
|
|
3684
3685
|
decision = await this.permissionHandler(p);
|
|
3685
3686
|
} catch (error) {
|
|
@@ -4170,7 +4171,7 @@ var BEELINE_ROOM_CAPABILITIES = [
|
|
|
4170
4171
|
"The repository filesystem is read-only in this Room session.",
|
|
4171
4172
|
"You may address any Room member, including another agent, by writing @name in your reply; the server routes that mention to them.",
|
|
4172
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.",
|
|
4173
|
-
"The beeline-readonly-mcp inspection tools and beeline-agent Room action tools are mounted
|
|
4174
|
+
"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.",
|
|
4174
4175
|
"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.",
|
|
4175
4176
|
"Never claim an action or reply happened unless the prompt or a tool result proves it."
|
|
4176
4177
|
].join(" ");
|
|
@@ -4781,6 +4782,7 @@ var READ_ONLY_PERMISSION_TITLES = new Set(READ_ONLY_TOOL_NAMES.flatMap((tool) =>
|
|
|
4781
4782
|
`${READ_ONLY_MCP_SERVER_NAME}/${tool}`
|
|
4782
4783
|
]));
|
|
4783
4784
|
var READ_ONLY_TOOL_SET = new Set(READ_ONLY_TOOL_NAMES);
|
|
4785
|
+
var TOOL_NAME_SEPARATORS = ["__", ".", "/", ":", " "];
|
|
4784
4786
|
var READ_ONLY_SERVER_TITLE_PREFIXES = [
|
|
4785
4787
|
`mcp__${READ_ONLY_MCP_SERVER_NAME}__`,
|
|
4786
4788
|
`mcp__${READ_ONLY_MCP_TOOL_SERVER_NAME}__`,
|
|
@@ -4798,6 +4800,27 @@ function shellPayload(toolCall) {
|
|
|
4798
4800
|
const record2 = rawInput;
|
|
4799
4801
|
return typeof record2.command === "string" || typeof record2.cmd === "string";
|
|
4800
4802
|
}
|
|
4803
|
+
function isReadOnlyMcpPermissionRequest(request) {
|
|
4804
|
+
const toolCall = request.toolCall;
|
|
4805
|
+
const title = toolCall?.title?.trim() ?? "";
|
|
4806
|
+
const rawInput = toolCall?.rawInput;
|
|
4807
|
+
const mcpCall = Boolean(rawInput) && typeof rawInput === "object" && !Array.isArray(rawInput) ? rawInput : void 0;
|
|
4808
|
+
if (mcpCall?.server === READ_ONLY_MCP_SERVER_NAME && typeof mcpCall.tool === "string" && READ_ONLY_TOOL_SET.has(mcpCall.tool)) {
|
|
4809
|
+
return true;
|
|
4810
|
+
}
|
|
4811
|
+
if (shellPayload(toolCall))
|
|
4812
|
+
return false;
|
|
4813
|
+
if (READ_ONLY_PERMISSION_TITLES.has(title))
|
|
4814
|
+
return true;
|
|
4815
|
+
if (READ_ONLY_SERVER_TITLE_PREFIXES.some((prefix) => title.startsWith(prefix))) {
|
|
4816
|
+
for (const tool of READ_ONLY_TOOL_NAMES) {
|
|
4817
|
+
if (title === tool || title.endsWith(`(${tool})`) || TOOL_NAME_SEPARATORS.some((separator) => title.endsWith(`${separator}${tool}`))) {
|
|
4818
|
+
return true;
|
|
4819
|
+
}
|
|
4820
|
+
}
|
|
4821
|
+
}
|
|
4822
|
+
return false;
|
|
4823
|
+
}
|
|
4801
4824
|
function isBeelineAgentMcpPermissionRequest(request) {
|
|
4802
4825
|
const toolCall = request.toolCall;
|
|
4803
4826
|
const title = toolCall?.title?.trim() ?? "";
|
|
@@ -14329,6 +14352,9 @@ async function wait(ms, signal) {
|
|
|
14329
14352
|
// apps/body/dist/monolith-room-turn.js
|
|
14330
14353
|
import { mkdir as mkdir4 } from "node:fs/promises";
|
|
14331
14354
|
import { homedir as homedir5 } from "node:os";
|
|
14355
|
+
function isRoomMcpPermissionRequest(request) {
|
|
14356
|
+
return isReadOnlyMcpPermissionRequest(request) || isBeelineAgentMcpPermissionRequest(request);
|
|
14357
|
+
}
|
|
14332
14358
|
function roomPrincipalMayAddressAgent(authority, humanPermitted) {
|
|
14333
14359
|
return authority.member && (authority.principalKind === "agent" || authority.principalKind === "human" && humanPermitted);
|
|
14334
14360
|
}
|
|
@@ -14447,7 +14473,7 @@ var MonolithRoomTurnLoop = class {
|
|
|
14447
14473
|
agentCwd: this.options.cwd,
|
|
14448
14474
|
agentLabel: command,
|
|
14449
14475
|
autoApprovePermissions: false,
|
|
14450
|
-
|
|
14476
|
+
permissionAllowlist: isRoomMcpPermissionRequest
|
|
14451
14477
|
};
|
|
14452
14478
|
this.client = (this.options.createAcpClient ?? ((value) => new AcpClient(value)))(clientOptions);
|
|
14453
14479
|
await this.client.start();
|
|
@@ -15244,7 +15270,7 @@ var RoomRuntimeCoordinator = class {
|
|
|
15244
15270
|
}
|
|
15245
15271
|
await mapWithConcurrency(desiredTopRooms, ROOM_JOIN_CONCURRENCY, async (roomId) => {
|
|
15246
15272
|
if (!this.running.has(roomId))
|
|
15247
|
-
this.startRoom(roomId);
|
|
15273
|
+
await this.startRoom(roomId);
|
|
15248
15274
|
});
|
|
15249
15275
|
await mapWithConcurrency([...desiredCorners.values()], ROOM_JOIN_CONCURRENCY, async (corner) => {
|
|
15250
15276
|
if (!this.running.has(corner.cornerId))
|
|
@@ -15284,10 +15310,9 @@ var RoomRuntimeCoordinator = class {
|
|
|
15284
15310
|
...agentHomeRoot ? { agentHomeRoot } : {}
|
|
15285
15311
|
};
|
|
15286
15312
|
}
|
|
15287
|
-
startRoom(roomId) {
|
|
15313
|
+
async startRoom(roomId) {
|
|
15288
15314
|
const controller = new AbortController();
|
|
15289
|
-
const
|
|
15290
|
-
const cwd = record2?.repo.root ?? this.roomRoot(roomId);
|
|
15315
|
+
const cwd = await this.materializeRoomCheckout(roomId);
|
|
15291
15316
|
const startedAt = this.now();
|
|
15292
15317
|
const loop = new MonolithRoomTurnLoop({
|
|
15293
15318
|
roomId,
|
|
@@ -15324,6 +15349,44 @@ var RoomRuntimeCoordinator = class {
|
|
|
15324
15349
|
});
|
|
15325
15350
|
console.log(`[thin-core] serving monolith Room ${roomId}`);
|
|
15326
15351
|
}
|
|
15352
|
+
/**
|
|
15353
|
+
* A Room is a repository inspection surface, so its session cwd must be the
|
|
15354
|
+
* current server-bound repository rather than a legacy runtime path (or the
|
|
15355
|
+
* otherwise-empty per-Room state directory). The daemon consumes the
|
|
15356
|
+
* short-lived GitHub token itself; it is never included in the Room MCP or
|
|
15357
|
+
* harness environment.
|
|
15358
|
+
*/
|
|
15359
|
+
async materializeRoomCheckout(roomId) {
|
|
15360
|
+
const repository = await this.options.daemonApi.execute("getRoomRepositoryState", { roomId });
|
|
15361
|
+
if (repository.resolution !== "repository" || !repository.remote)
|
|
15362
|
+
return this.roomRoot(roomId);
|
|
15363
|
+
const remote = roomCheckoutRemote(repository.remote);
|
|
15364
|
+
const targetBranch = repository.targetBranch || "main";
|
|
15365
|
+
const checkoutId = createHash("sha256").update(`${remote}\0${targetBranch}`).digest("hex").slice(0, 24);
|
|
15366
|
+
const path = resolve10(this.runtime.supervisorRoot, "beeline", "room-checkouts", checkoutId);
|
|
15367
|
+
await mkdir5(dirname4(path), { recursive: true, mode: 448 });
|
|
15368
|
+
const token = remote.startsWith("https://github.com/") ? await this.options.daemonApi.execute("getRoomGitHubToken", { roomId }) : void 0;
|
|
15369
|
+
const env = token ? githubGitEnv(token.token) : process.env;
|
|
15370
|
+
if (!existsSync4(resolve10(path, ".git"))) {
|
|
15371
|
+
await execFileAsync3("git", ["clone", "--no-checkout", remote, path], {
|
|
15372
|
+
env,
|
|
15373
|
+
maxBuffer: 4 * 1024 * 1024
|
|
15374
|
+
});
|
|
15375
|
+
}
|
|
15376
|
+
await execFileAsync3("git", [
|
|
15377
|
+
"-C",
|
|
15378
|
+
path,
|
|
15379
|
+
"fetch",
|
|
15380
|
+
"--prune",
|
|
15381
|
+
"origin",
|
|
15382
|
+
`+refs/heads/${targetBranch}:refs/remotes/origin/${targetBranch}`
|
|
15383
|
+
], { env, maxBuffer: 4 * 1024 * 1024 });
|
|
15384
|
+
await execFileAsync3("git", ["-C", path, "checkout", "--detach", "--force", `origin/${targetBranch}`], {
|
|
15385
|
+
env,
|
|
15386
|
+
maxBuffer: 4 * 1024 * 1024
|
|
15387
|
+
});
|
|
15388
|
+
return path;
|
|
15389
|
+
}
|
|
15327
15390
|
async startCorner(corner) {
|
|
15328
15391
|
if (this.running.has(corner.cornerId) || this.startingCorners.has(corner.cornerId))
|
|
15329
15392
|
return;
|
|
@@ -15555,6 +15618,11 @@ function githubHttpsRemote(remote) {
|
|
|
15555
15618
|
url.password = "";
|
|
15556
15619
|
return url.toString().replace(/\/$/, "").replace(/\.git$/i, "") + ".git";
|
|
15557
15620
|
}
|
|
15621
|
+
function roomCheckoutRemote(remote) {
|
|
15622
|
+
if (remote.startsWith("file://"))
|
|
15623
|
+
return remote;
|
|
15624
|
+
return githubHttpsRemote(remote);
|
|
15625
|
+
}
|
|
15558
15626
|
function githubGitEnv(token) {
|
|
15559
15627
|
const authorization = Buffer.from(`x-access-token:${token}`).toString("base64");
|
|
15560
15628
|
return {
|