@lightcone-ai/daemon 0.15.59 → 0.15.60
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/package.json +1 -1
- package/src/agent-manager.js +42 -0
- package/src/connection.js +22 -2
- package/src/index.js +1 -0
package/package.json
CHANGED
package/src/agent-manager.js
CHANGED
|
@@ -179,6 +179,48 @@ export class AgentManager {
|
|
|
179
179
|
return `${workspaceId ?? ''}:${agentId}`;
|
|
180
180
|
}
|
|
181
181
|
|
|
182
|
+
/**
|
|
183
|
+
* Snapshot of agents this daemon process is currently managing. Sent to the
|
|
184
|
+
* server alongside 'ready' so the server can reconcile lifecycle state
|
|
185
|
+
* after a reconnect — agents previously on this machine but absent from
|
|
186
|
+
* the inventory get reset from stale `crashed unreachable` back to a clean
|
|
187
|
+
* `standby reachable available` baseline (machine is healthy, agent will
|
|
188
|
+
* be spawned on demand).
|
|
189
|
+
*
|
|
190
|
+
* Each entry mirrors the daemon-internal agent state machine:
|
|
191
|
+
* - 'starting': spawn in progress (entry exists in this.starting)
|
|
192
|
+
* - 'running': child process is alive (this.agents has it)
|
|
193
|
+
* The server treats whatever is NOT in this list as 'standby' (spawnable
|
|
194
|
+
* but not currently running on this machine).
|
|
195
|
+
*/
|
|
196
|
+
getAgentInventory() {
|
|
197
|
+
const inventory = [];
|
|
198
|
+
for (const key of this.starting) {
|
|
199
|
+
const colonIdx = key.indexOf(':');
|
|
200
|
+
const workspaceId = colonIdx === -1 ? null : (key.slice(0, colonIdx) || null);
|
|
201
|
+
const agentId = colonIdx === -1 ? key : key.slice(colonIdx + 1);
|
|
202
|
+
inventory.push({
|
|
203
|
+
agentId,
|
|
204
|
+
workspaceId,
|
|
205
|
+
runtimeState: 'starting',
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
for (const [key, agent] of this.agents.entries()) {
|
|
209
|
+
const colonIdx = key.indexOf(':');
|
|
210
|
+
const workspaceId = agent.workspaceId
|
|
211
|
+
?? (colonIdx === -1 ? null : (key.slice(0, colonIdx) || null));
|
|
212
|
+
const agentId = agent.agentId
|
|
213
|
+
?? (colonIdx === -1 ? key : key.slice(colonIdx + 1));
|
|
214
|
+
inventory.push({
|
|
215
|
+
agentId,
|
|
216
|
+
workspaceId,
|
|
217
|
+
runtimeState: 'running',
|
|
218
|
+
sessionId: agent.sessionId ?? null,
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
return inventory;
|
|
222
|
+
}
|
|
223
|
+
|
|
182
224
|
handle(msg, connection) {
|
|
183
225
|
switch (msg.type) {
|
|
184
226
|
case 'agent:start': return this._startAgent(msg, connection);
|
package/src/connection.js
CHANGED
|
@@ -45,10 +45,16 @@ function parseOptionalDeviceHints() {
|
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
export class DaemonConnection {
|
|
48
|
-
constructor({ serverUrl, machineApiKey, onMessage }) {
|
|
48
|
+
constructor({ serverUrl, machineApiKey, onMessage, getAgentInventory = null }) {
|
|
49
49
|
this.serverUrl = serverUrl.replace(/^http/, 'ws');
|
|
50
50
|
this.machineApiKey = machineApiKey;
|
|
51
51
|
this.onMessage = onMessage;
|
|
52
|
+
// Optional callback invoked at 'ready' time to snapshot which agents
|
|
53
|
+
// this daemon is currently managing. Server uses this to reconcile
|
|
54
|
+
// stale lifecycle state after reconnects (see src/daemon/index.js
|
|
55
|
+
// 'ready' handler — agents previously on this machine but missing
|
|
56
|
+
// from inventory get reset from stale crashed→standby).
|
|
57
|
+
this.getAgentInventory = typeof getAgentInventory === 'function' ? getAgentInventory : null;
|
|
52
58
|
this.ws = null;
|
|
53
59
|
this.reconnectDelay = RECONNECT_INITIAL;
|
|
54
60
|
this.stopped = false;
|
|
@@ -111,7 +117,20 @@ export class DaemonConnection {
|
|
|
111
117
|
...parseOptionalDeviceHints(),
|
|
112
118
|
};
|
|
113
119
|
|
|
114
|
-
|
|
120
|
+
let agentInventory = [];
|
|
121
|
+
if (this.getAgentInventory) {
|
|
122
|
+
try {
|
|
123
|
+
const snapshot = this.getAgentInventory();
|
|
124
|
+
if (Array.isArray(snapshot)) agentInventory = snapshot;
|
|
125
|
+
} catch (err) {
|
|
126
|
+
console.warn(`[Connection] getAgentInventory failed: ${err?.message ?? err}`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
console.log(
|
|
131
|
+
`[Connection] Ready — host=${hostname} runtimes=[${runtimes.join(',')}] v${DAEMON_VERSION}`
|
|
132
|
+
+ ` inventory=${agentInventory.length}`
|
|
133
|
+
);
|
|
115
134
|
this.send({
|
|
116
135
|
type: 'ready',
|
|
117
136
|
hostname,
|
|
@@ -119,6 +138,7 @@ export class DaemonConnection {
|
|
|
119
138
|
runtimes,
|
|
120
139
|
daemonVersion: DAEMON_VERSION,
|
|
121
140
|
deviceHints,
|
|
141
|
+
agentInventory,
|
|
122
142
|
});
|
|
123
143
|
}
|
|
124
144
|
|
package/src/index.js
CHANGED