cumora 0.1.47 → 0.1.49
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 +42 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -181,7 +181,11 @@ var ClaudeAdapter = class {
|
|
|
181
181
|
const flags = extraArgs("CUMORA_CLAUDE_ARGS");
|
|
182
182
|
const model = args.model ? ["--model", args.model] : [];
|
|
183
183
|
const argv = flags.length ? [...flags, "-p", args.prompt] : ["-p", args.prompt, ...model, "--output-format", "stream-json", "--verbose", "--dangerously-skip-permissions"];
|
|
184
|
-
const env =
|
|
184
|
+
const env = {
|
|
185
|
+
...args.env,
|
|
186
|
+
MAX_THINKING_TOKENS: args.env.MAX_THINKING_TOKENS ?? "0"
|
|
187
|
+
};
|
|
188
|
+
if (args.fastModel) env.ANTHROPIC_SMALL_FAST_MODEL = args.fastModel;
|
|
185
189
|
return spawnEngine(this.bin, argv, { ...args, env });
|
|
186
190
|
}
|
|
187
191
|
};
|
|
@@ -222,6 +226,7 @@ var DEFAULT_SERVER = process.env.CUMORA_SERVER_URL || "https://api.cumora.ai";
|
|
|
222
226
|
var TOKEN_REFRESH_SKEW_MS = 5 * 60 * 1e3;
|
|
223
227
|
var AGENT_POLL_MS = 6e4;
|
|
224
228
|
var HEARTBEAT_MS = 3e4;
|
|
229
|
+
var INBOX_POLL_MS = 2e4;
|
|
225
230
|
var MAX_VISIBLE_ERROR_CHARS = 900;
|
|
226
231
|
function parseArgs(argv) {
|
|
227
232
|
const out = {};
|
|
@@ -379,14 +384,22 @@ var AgentRunner = class {
|
|
|
379
384
|
pendingRerun = false;
|
|
380
385
|
stopped = false;
|
|
381
386
|
lastWakeConvo = null;
|
|
387
|
+
pollTimer;
|
|
382
388
|
adapter;
|
|
383
389
|
async start() {
|
|
384
390
|
await this.adapter.seedHome(this.home, { id: this.agent.id, name: this.agent.name, role: this.agent.role });
|
|
385
391
|
await writeShim(this.binDir);
|
|
386
392
|
void this.streamLoop();
|
|
393
|
+
this.pollTimer = setInterval(() => {
|
|
394
|
+
if (!this.busy && !this.stopped) void this.runTurn();
|
|
395
|
+
}, INBOX_POLL_MS);
|
|
387
396
|
}
|
|
388
397
|
stop() {
|
|
389
398
|
this.stopped = true;
|
|
399
|
+
if (this.pollTimer) {
|
|
400
|
+
clearInterval(this.pollTimer);
|
|
401
|
+
this.pollTimer = void 0;
|
|
402
|
+
}
|
|
390
403
|
}
|
|
391
404
|
/** Does this runner's live config still match the latest server state? The
|
|
392
405
|
* engine + model + persona are captured at construction (the adapter is
|
|
@@ -473,6 +486,31 @@ ${hint}`,
|
|
|
473
486
|
async inboxTriage(token) {
|
|
474
487
|
return runtimeGet(this.cfg.serverUrl, "/inbox-triage", token);
|
|
475
488
|
}
|
|
489
|
+
/** Snapshot the unread inbox as {conversationId → latest unread message id}.
|
|
490
|
+
* Captured BEFORE the engine runs so we can later ack exactly what THIS
|
|
491
|
+
* turn saw (`ackSeen`) without swallowing messages that arrive mid-turn —
|
|
492
|
+
* those keep a higher id, stay unread, and drive the coalesced rerun. */
|
|
493
|
+
async snapshotUnread(token) {
|
|
494
|
+
const inbox = await runtimeGet(this.cfg.serverUrl, "/inbox", token);
|
|
495
|
+
const seen = /* @__PURE__ */ new Map();
|
|
496
|
+
for (const row of inbox?.rows ?? []) {
|
|
497
|
+
if (typeof row.conversation_id === "string" && row.conversation_id && typeof row.id === "string" && row.id) {
|
|
498
|
+
seen.set(row.conversation_id, row.id);
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
return seen;
|
|
502
|
+
}
|
|
503
|
+
/** Advance this agent's read cursor over the conversations it just saw, so a
|
|
504
|
+
* wake that ends WITHOUT a reply (small-brain said "skip", or the engine
|
|
505
|
+
* read the room and chose silence) does not re-trigger on the same messages
|
|
506
|
+
* every INBOX_POLL_MS. markConversationRead is monotonic, so this never
|
|
507
|
+
* regresses a cursor the engine already advanced further via `cumora reply`. */
|
|
508
|
+
async ackSeen(token, seen) {
|
|
509
|
+
if (seen.size === 0) return;
|
|
510
|
+
await Promise.all([...seen].map(
|
|
511
|
+
([conversationId, upToMessageId]) => runtimeBest(this.cfg.serverUrl, "/conversation/mark-read", token, { conversationId, upToMessageId })
|
|
512
|
+
));
|
|
513
|
+
}
|
|
476
514
|
formatTriageNote(triage) {
|
|
477
515
|
if (!triage) return "";
|
|
478
516
|
const note = typeof triage?.promptNote === "string" ? triage.promptNote.trim() : "";
|
|
@@ -530,10 +568,12 @@ If nothing genuinely needs you, it's fine to do nothing and stop. When finished,
|
|
|
530
568
|
const token = this.token;
|
|
531
569
|
const convo = this.lastWakeConvo;
|
|
532
570
|
this.lastWakeConvo = null;
|
|
571
|
+
const seen = await this.snapshotUnread(token);
|
|
533
572
|
const triage = await this.inboxTriage(token);
|
|
534
573
|
if (triage?.actionable === false) {
|
|
535
574
|
const reason = typeof triage.reason === "string" ? triage.reason : "not relevant";
|
|
536
575
|
console.log(`[computer] ${this.agent.id} skipped by small-brain inbox triage: ${reason}`);
|
|
576
|
+
await this.ackSeen(token, seen);
|
|
537
577
|
await runtimeBest(this.cfg.serverUrl, "/status", token, { status: "avail" });
|
|
538
578
|
continue;
|
|
539
579
|
}
|
|
@@ -602,6 +642,7 @@ If nothing genuinely needs you, it's fine to do nothing and stop. When finished,
|
|
|
602
642
|
error: engineError
|
|
603
643
|
});
|
|
604
644
|
}
|
|
645
|
+
if (!engineError) await this.ackSeen(token, seen);
|
|
605
646
|
await runtimeBest(this.cfg.serverUrl, "/status", token, { status: "avail" });
|
|
606
647
|
} while (this.pendingRerun && !this.stopped);
|
|
607
648
|
} finally {
|