cumora 0.1.42 → 0.1.44
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/cli.js +36 -2
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -292,6 +292,7 @@ var AgentRunner = class {
|
|
|
292
292
|
busy = false;
|
|
293
293
|
pendingRerun = false;
|
|
294
294
|
stopped = false;
|
|
295
|
+
lastWakeConvo = null;
|
|
295
296
|
adapter;
|
|
296
297
|
async start() {
|
|
297
298
|
await this.adapter.seedHome(this.home, { id: this.agent.id, name: this.agent.name, role: this.agent.role });
|
|
@@ -301,6 +302,14 @@ var AgentRunner = class {
|
|
|
301
302
|
stop() {
|
|
302
303
|
this.stopped = true;
|
|
303
304
|
}
|
|
305
|
+
/** Does this runner's live config still match the latest server state? The
|
|
306
|
+
* engine + model + persona are captured at construction (the adapter is
|
|
307
|
+
* fixed, and seedHome runs once in start()), so when any of them changes in
|
|
308
|
+
* Cumora, sync() must tear this runner down and build a fresh one — otherwise
|
|
309
|
+
* e.g. a Claude→Codex switch wouldn't take effect until a daemon restart. */
|
|
310
|
+
configMatches(agent, engine) {
|
|
311
|
+
return this.adapter.id === engine && this.agent.name === agent.name && this.agent.role === agent.role && this.agent.model === agent.model && this.agent.fastModel === agent.fastModel;
|
|
312
|
+
}
|
|
304
313
|
async ensureToken() {
|
|
305
314
|
if (this.token && Date.now() < this.tokenExpiresAt - TOKEN_REFRESH_SKEW_MS) return this.token;
|
|
306
315
|
const minted = await api(
|
|
@@ -348,7 +357,16 @@ If nothing genuinely needs you, it's fine to do nothing and stop. When finished,
|
|
|
348
357
|
this.pendingRerun = false;
|
|
349
358
|
await this.ensureToken();
|
|
350
359
|
const token = this.token;
|
|
360
|
+
const convo = this.lastWakeConvo;
|
|
351
361
|
await runtimeBest(this.cfg.serverUrl, "/status", token, { status: "thinking" });
|
|
362
|
+
let typingTimer;
|
|
363
|
+
if (convo) {
|
|
364
|
+
const ping = () => {
|
|
365
|
+
void runtimeBest(this.cfg.serverUrl, "/typing", token, { conversationId: convo, done: false });
|
|
366
|
+
};
|
|
367
|
+
ping();
|
|
368
|
+
typingTimer = setInterval(ping, 6e3);
|
|
369
|
+
}
|
|
352
370
|
const run = await runtimeBest(this.cfg.serverUrl, "/runs", token, {
|
|
353
371
|
trigger: { source: "byoa", engine: this.adapter.id }
|
|
354
372
|
});
|
|
@@ -368,6 +386,9 @@ If nothing genuinely needs you, it's fine to do nothing and stop. When finished,
|
|
|
368
386
|
} catch (err) {
|
|
369
387
|
console.error(`[computer] ${this.agent.id} engine spawn failed:`, err instanceof Error ? err.message : err);
|
|
370
388
|
exitCode = 1;
|
|
389
|
+
} finally {
|
|
390
|
+
if (typingTimer) clearInterval(typingTimer);
|
|
391
|
+
if (convo) await runtimeBest(this.cfg.serverUrl, "/typing", token, { conversationId: convo, done: true });
|
|
371
392
|
}
|
|
372
393
|
if (run?.runId) {
|
|
373
394
|
await runtimeBest(this.cfg.serverUrl, `/runs/${run.runId}/finish`, token, {
|
|
@@ -397,7 +418,14 @@ If nothing genuinely needs you, it's fine to do nothing and stop. When finished,
|
|
|
397
418
|
void this.runTurn();
|
|
398
419
|
for await (const evt of parseSseStream(res.body)) {
|
|
399
420
|
if (this.stopped) break;
|
|
400
|
-
if (evt.event === "wake")
|
|
421
|
+
if (evt.event === "wake") {
|
|
422
|
+
try {
|
|
423
|
+
const convo = evt.data ? JSON.parse(evt.data).conversationId : null;
|
|
424
|
+
if (convo) this.lastWakeConvo = convo;
|
|
425
|
+
} catch {
|
|
426
|
+
}
|
|
427
|
+
void this.runTurn();
|
|
428
|
+
}
|
|
401
429
|
}
|
|
402
430
|
} catch (err) {
|
|
403
431
|
if (this.stopped) break;
|
|
@@ -435,9 +463,15 @@ async function doRun(serverOverride) {
|
|
|
435
463
|
return;
|
|
436
464
|
}
|
|
437
465
|
for (const agent of agents) {
|
|
438
|
-
if (runners.has(agent.id)) continue;
|
|
439
466
|
const engine = agent.engine && available.includes(agent.engine) ? agent.engine : available[0] ?? null;
|
|
440
467
|
if (!engine) continue;
|
|
468
|
+
const existing = runners.get(agent.id);
|
|
469
|
+
if (existing) {
|
|
470
|
+
if (existing.configMatches(agent, engine)) continue;
|
|
471
|
+
console.log(`[computer] agent ${agent.name} (${agent.id}) config changed \u2192 restarting on ${engine}`);
|
|
472
|
+
existing.stop();
|
|
473
|
+
runners.delete(agent.id);
|
|
474
|
+
}
|
|
441
475
|
const runner = new AgentRunner(cfg, agent, engine);
|
|
442
476
|
runners.set(agent.id, runner);
|
|
443
477
|
console.log(`[computer] hosting agent ${agent.name} (${agent.id}) on ${engine}`);
|