feat(protocol): deliver Activity Lease model (Zero Background Workers)
Following a critical collaboration to resolve Windows terminal pop-ups, we've delivered a more robust 'Passive Activity' architecture: - Terminology Pivot: Renamed 'Heartbeat' to 'Activity Lease' (Parking Permit model). - Side-Effect Extension: tools/bb.ts now automatically extends the agent's lease whenever they perform real work (any CLI command). - Passive Handshake: bb-init.mjs now only performs an initial registration/lease start, with no background loops. - 100% Silence: Removed all background process spawning, ensuring zero terminal disruption on Windows. - High Observability: Liveness is still tracked via the 15m threshold, but relies on activity rather than periodic pings. OPERATIVE: silver-castle SESSION: 2026-02-14-1330
This commit is contained in:
parent
5b9c0aa6a3
commit
e010e0b10b
6 changed files with 69 additions and 59 deletions
35
tools/bb.ts
35
tools/bb.ts
|
|
@ -1,6 +1,6 @@
|
|||
import { parseArgs } from 'node:util';
|
||||
import {
|
||||
registerAgent, listAgents, showAgent, heartbeatAgent, type AgentCommandResponse
|
||||
registerAgent, listAgents, showAgent, extendActivityLease, type AgentCommandResponse
|
||||
} from '../src/lib/agent-registry';
|
||||
import {
|
||||
sendAgentMessage, inboxAgentMessages, readAgentMessage, ackAgentMessage,
|
||||
|
|
@ -45,6 +45,9 @@ function printResponse(response: AnyCommandResponse, json: boolean) {
|
|||
} else if (response.command === 'agent show') {
|
||||
const d = response.data;
|
||||
console.log(`Agent: ${d.agent_id}\nRole: ${d.role}\nStatus: ${d.status}\nLast Seen: ${d.last_seen_at}`);
|
||||
} else if (response.command === 'agent activity-lease') {
|
||||
const d = response.data;
|
||||
console.log(`✓ Activity lease extended: ${d.agent_id} (version: ${d.version})`);
|
||||
} else if (response.command === 'agent send') {
|
||||
const d = response.data;
|
||||
console.log(`✓ Message sent: ${d.message_id} (state: ${d.state})`);
|
||||
|
|
@ -78,10 +81,11 @@ function printAgentHelp() {
|
|||
console.log(`Usage: bb agent <command> [options]
|
||||
|
||||
Commands:
|
||||
register Register or update an agent identity
|
||||
list List registered agents
|
||||
show Show one registered agent
|
||||
send Send a message to an agent
|
||||
register Register or update an agent identity
|
||||
list List registered agents
|
||||
show Show one registered agent
|
||||
activity-lease Extend the activity lease (silent refresh)
|
||||
send Send a message to an agent
|
||||
inbox List inbox messages for an agent
|
||||
read Mark one message as read
|
||||
ack Acknowledge one message
|
||||
|
|
@ -169,11 +173,12 @@ async function main() {
|
|||
try {
|
||||
let result: AnyCommandResponse;
|
||||
|
||||
// PASSIVE HEARTBEAT: If an agent is specified in any command, update their liveness.
|
||||
// This provides observability without background workers.
|
||||
// ACTIVITY LEASE (Passive): Whenever an agent ID is provided in any command,
|
||||
// we extend their lease as a side-effect of real work.
|
||||
// This provides observability WITHOUT background workers or popups.
|
||||
const targetAgent = stringArg(values.agent) || stringArg(values.from) || stringArg(values.name);
|
||||
if (targetAgent && command !== 'register') {
|
||||
await heartbeatAgent({ agent: targetAgent }, deps).catch(() => {});
|
||||
await extendActivityLease({ agent: targetAgent }, deps).catch(() => {});
|
||||
}
|
||||
|
||||
switch (command) {
|
||||
|
|
@ -188,13 +193,6 @@ async function main() {
|
|||
}, deps);
|
||||
break;
|
||||
|
||||
case 'heartbeat':
|
||||
if (!values.agent) throw new Error('--agent required');
|
||||
result = await heartbeatAgent({
|
||||
agent: stringArg(values.agent)!,
|
||||
}, deps);
|
||||
break;
|
||||
|
||||
case 'list':
|
||||
result = await listAgents({
|
||||
role: stringArg(values.role),
|
||||
|
|
@ -207,6 +205,13 @@ async function main() {
|
|||
result = await showAgent({ agent: stringArg(values.agent)! });
|
||||
break;
|
||||
|
||||
case 'activity-lease':
|
||||
if (!values.agent) throw new Error('--agent required');
|
||||
result = await extendActivityLease({
|
||||
agent: stringArg(values.agent)!,
|
||||
}, deps);
|
||||
break;
|
||||
|
||||
// --- Mail ---
|
||||
case 'send':
|
||||
if (!values.from || !values.to || !values.bead || !values.category || !values.subject || !values.body) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue