usebeeline 0.0.109 → 0.0.110
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 +49 -3
- package/package.json +1 -1
package/dist/usebeeline.mjs
CHANGED
|
@@ -18025,6 +18025,7 @@ var DaemonApiClient = class {
|
|
|
18025
18025
|
liveReconnect;
|
|
18026
18026
|
liveReconnectDelayMs = 1e3;
|
|
18027
18027
|
liveRooms = /* @__PURE__ */ new Map();
|
|
18028
|
+
roomsChangedListener;
|
|
18028
18029
|
constructor(baseUrl, daemonToken, agentId, fetchImpl = fetch, webSocketFactory = (url, protocols) => new wrapper_default(url, protocols)) {
|
|
18029
18030
|
this.baseUrl = baseUrl;
|
|
18030
18031
|
this.daemonToken = daemonToken;
|
|
@@ -18071,6 +18072,12 @@ var DaemonApiClient = class {
|
|
|
18071
18072
|
}
|
|
18072
18073
|
};
|
|
18073
18074
|
}
|
|
18075
|
+
/** Register the one listener invoked when the server reports this agent's
|
|
18076
|
+
* Room/corner memberships changed — the wake that discovers a freshly
|
|
18077
|
+
* created Room without waiting for the reconciliation heartbeat. */
|
|
18078
|
+
setRoomsChangedListener(listener) {
|
|
18079
|
+
this.roomsChangedListener = listener;
|
|
18080
|
+
}
|
|
18074
18081
|
updateLiveCursor(roomId, cursor3) {
|
|
18075
18082
|
const room = this.liveRooms.get(roomId);
|
|
18076
18083
|
if (room && cursor3)
|
|
@@ -18104,6 +18111,7 @@ var DaemonApiClient = class {
|
|
|
18104
18111
|
this.liveReconnectDelayMs = 1e3;
|
|
18105
18112
|
for (const roomId of this.liveRooms.keys())
|
|
18106
18113
|
this.sendLiveSubscription(roomId);
|
|
18114
|
+
this.roomsChangedListener?.();
|
|
18107
18115
|
};
|
|
18108
18116
|
socket.onmessage = (message) => {
|
|
18109
18117
|
let value;
|
|
@@ -18115,6 +18123,10 @@ var DaemonApiClient = class {
|
|
|
18115
18123
|
if (!value || typeof value !== "object")
|
|
18116
18124
|
return;
|
|
18117
18125
|
const event = value;
|
|
18126
|
+
if (event.type === "rooms-changed") {
|
|
18127
|
+
this.roomsChangedListener?.();
|
|
18128
|
+
return;
|
|
18129
|
+
}
|
|
18118
18130
|
if (event.type === "subscribed" && typeof event.roomId === "string") {
|
|
18119
18131
|
const capabilities = event.capabilities;
|
|
18120
18132
|
this.liveRooms.get(event.roomId)?.onState?.(true, {
|
|
@@ -19382,7 +19394,7 @@ var BEELINE_ROOM_CAPABILITIES = [
|
|
|
19382
19394
|
"Files and photos people share are downloaded for you: read them at the local path named in the prompt (photos may also arrive inline); never fetch the reference URL.",
|
|
19383
19395
|
"To create a file (this Room has no other way to write one), call beeline-agent write_scratch_file with a relative path and content - text by default, or base64 for bytes you computed; it returns a path in your writable session home. To send a file, call beeline-agent post_artifact with a path inside your checkout or anywhere in your writable session home (wherever a file you or your harness generated actually landed, including one you just wrote), or with html/bytes content directly; it is uploaded and attached to your reply, and title and mime default from the file when you post by path. write_scratch_file produces the file, not a picture - turning it into a raster image needs a converter, which needs shell, which this Room does not have.",
|
|
19384
19396
|
"To run something later or repeatedly, call beeline-agent create_schedule (interval in minutes or a 5-field cron, optional maxRuns); list_schedules / delete_schedule manage them.",
|
|
19385
|
-
`To react to things that HAPPEN in this Room rather than only to what is said to you, call beeline-agent subscribe_events with the kinds you want (${SERVER_EVENT_KINDS.join(", ")}); each one then wakes you for a turn. It replaces your list, so send every kind you want - list_event_subscriptions shows the current one. You do this yourself: nobody has to configure it for you. grant-decided carries the grant id and status and resumes the turn that asked for the grant.`,
|
|
19397
|
+
`To react to things that HAPPEN in this Room rather than only to what is said to you, call beeline-agent subscribe_events with the kinds you want (${SERVER_EVENT_KINDS.join(", ")}); each one then wakes you for a turn. Subscriptions are per Room and cover every way the event lands: joining a Room you subscribed to wakes you, and so does a person arriving in the Workspace when that arrival projects into this Room - subscribe to joined in an onboarding Room and every newcomer wakes you, exactly like a greeter. It replaces your list, so send every kind you want - list_event_subscriptions shows the current one. You do this yourself: nobody has to configure it for you. grant-decided carries the grant id and status and resumes the turn that asked for the grant.`,
|
|
19386
19398
|
"To state something that happened so the Room and other agents can act on it, call beeline-agent emit_event with your own agent:<slug> kind, one sentence, and optionally the agent members to wake. Chains of events are bounded and a refused emit posts nothing.",
|
|
19387
19399
|
"When repository work is needed, you MUST call beeline-agent open_corner with a name of at most three words - it titles the corner everywhere - and a complete objective of no more than 24 words. The host-governed call is the only way to start write work.",
|
|
19388
19400
|
"Never open a corner from your own reading of a person's ask. For every ask, first reply on one line `Proposed corner: <name> \u2014 <objective>`, using the exact title and objective you would pass to open_corner, then stop and wait. If one message contains several asks, list one numbered `Proposed corner:` line per ask; `go on 1 and 3` opens exactly those objectives and leaves the others proposed. A person's `go`, `yes`, or equivalent opens exactly the proposed corner; if they edit it, their edited text is the objective. Skip this ceremony only when the message itself explicitly commands a corner and states its scope, such as `open a corner and do X` or `go build X in a corner`; open that scope immediately.",
|
|
@@ -24632,6 +24644,25 @@ var DEFAULT_ROOM_WATCHDOG_STALE_MS = 9e4;
|
|
|
24632
24644
|
var DEFAULT_RECONCILE_HEARTBEAT_MS = 6e4;
|
|
24633
24645
|
var DEFAULT_DRAIN_DEADLINE_MS = 30 * 6e4;
|
|
24634
24646
|
var CORNER_BRANCH_DELETE_ATTEMPTS = 3;
|
|
24647
|
+
var DiscoveryWakes = class {
|
|
24648
|
+
arrived = 0;
|
|
24649
|
+
served = 0;
|
|
24650
|
+
/** Called for every agent-directed `rooms-changed` wake. */
|
|
24651
|
+
wake() {
|
|
24652
|
+
this.arrived += 1;
|
|
24653
|
+
}
|
|
24654
|
+
needsFastReconcile() {
|
|
24655
|
+
return this.arrived !== this.served;
|
|
24656
|
+
}
|
|
24657
|
+
/** Snapshot at reconcile entry: the wake count its reads will cover. */
|
|
24658
|
+
beginReconcile() {
|
|
24659
|
+
return this.arrived;
|
|
24660
|
+
}
|
|
24661
|
+
/** Clear only wakes the completed start pass actually served. */
|
|
24662
|
+
completeReconcile(covered) {
|
|
24663
|
+
this.served = Math.max(this.served, covered);
|
|
24664
|
+
}
|
|
24665
|
+
};
|
|
24635
24666
|
function shouldPostInitialCornerWorkingState(restore, isOpener = true) {
|
|
24636
24667
|
return isOpener && !restore.featureBranch && !restore.lifecycle?.branch && !restore.lifecycle?.pr;
|
|
24637
24668
|
}
|
|
@@ -24808,6 +24839,11 @@ var RoomRuntimeCoordinator = class {
|
|
|
24808
24839
|
workspaceRemovalConfirmations = 0;
|
|
24809
24840
|
roomRemovalConfirmations = /* @__PURE__ */ new Map();
|
|
24810
24841
|
confirmationPending = false;
|
|
24842
|
+
/** Agent-directed discovery wakes (#1369), counted instead of flagged: a
|
|
24843
|
+
* wake that arrives while a reconcile is already running must survive its
|
|
24844
|
+
* start-pass clearing, or a corner opened mid-reconcile waits a heartbeat
|
|
24845
|
+
* for a wake the daemon already received. */
|
|
24846
|
+
discoveryWakes = new DiscoveryWakes();
|
|
24811
24847
|
/** One command-grant runner per daemon; Rooms and corners register their checkouts on it. */
|
|
24812
24848
|
grantRunner;
|
|
24813
24849
|
grantRunnerServer;
|
|
@@ -24828,6 +24864,9 @@ var RoomRuntimeCoordinator = class {
|
|
|
24828
24864
|
});
|
|
24829
24865
|
this.grantRunnerServer = new GrantRunnerServer(this.grantRunner);
|
|
24830
24866
|
this.connectorUsage = new ConnectorUsageRecorder();
|
|
24867
|
+
this.options.daemonApi.setRoomsChangedListener?.(() => {
|
|
24868
|
+
this.discoveryWakes.wake();
|
|
24869
|
+
});
|
|
24831
24870
|
this.watchdogStaleMs = options.watchdogStaleMs ?? DEFAULT_ROOM_WATCHDOG_STALE_MS;
|
|
24832
24871
|
this.reconcileHeartbeatMs = options.reconcileHeartbeatMs ?? DEFAULT_RECONCILE_HEARTBEAT_MS;
|
|
24833
24872
|
this.drainDeadlineMs = options.drainDeadlineMs ?? DEFAULT_DRAIN_DEADLINE_MS;
|
|
@@ -24858,7 +24897,7 @@ var RoomRuntimeCoordinator = class {
|
|
|
24858
24897
|
return this.scheduler.snapshot();
|
|
24859
24898
|
}
|
|
24860
24899
|
needsFastReconcile() {
|
|
24861
|
-
return this.confirmationPending;
|
|
24900
|
+
return this.confirmationPending || this.discoveryWakes.needsFastReconcile();
|
|
24862
24901
|
}
|
|
24863
24902
|
reconcileHeartbeatIntervalMs() {
|
|
24864
24903
|
return this.reconcileHeartbeatMs;
|
|
@@ -24894,6 +24933,7 @@ var RoomRuntimeCoordinator = class {
|
|
|
24894
24933
|
}
|
|
24895
24934
|
async reconcile() {
|
|
24896
24935
|
this.confirmationPending = false;
|
|
24936
|
+
const coveredWakes = this.discoveryWakes.beginReconcile();
|
|
24897
24937
|
const bootstrap = await this.options.daemonApi.execute("getDaemonBootstrap", {
|
|
24898
24938
|
agentId: this.agent.publicKey
|
|
24899
24939
|
});
|
|
@@ -24961,8 +25001,13 @@ var RoomRuntimeCoordinator = class {
|
|
|
24961
25001
|
}
|
|
24962
25002
|
}
|
|
24963
25003
|
await mapWithConcurrency(desiredTopRooms, ROOM_JOIN_CONCURRENCY, async (roomId) => {
|
|
24964
|
-
if (
|
|
25004
|
+
if (this.running.has(roomId))
|
|
25005
|
+
return;
|
|
25006
|
+
try {
|
|
24965
25007
|
await this.startRoom(roomId);
|
|
25008
|
+
} catch (error) {
|
|
25009
|
+
console.error(`[thin-core] failed to start Room ${roomId}:`, error);
|
|
25010
|
+
}
|
|
24966
25011
|
});
|
|
24967
25012
|
await mapWithConcurrency([...desiredCorners.values()], ROOM_JOIN_CONCURRENCY, async (corner) => {
|
|
24968
25013
|
if (!this.running.has(corner.cornerId))
|
|
@@ -24970,6 +25015,7 @@ var RoomRuntimeCoordinator = class {
|
|
|
24970
25015
|
});
|
|
24971
25016
|
for (const running of this.running.values())
|
|
24972
25017
|
running.body.requestReconciliation();
|
|
25018
|
+
this.discoveryWakes.completeReconcile(coveredWakes);
|
|
24973
25019
|
return "member";
|
|
24974
25020
|
}
|
|
24975
25021
|
roomRecord(roomId) {
|