@agenticmail/claudecode 0.2.2 → 0.2.3

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.
@@ -12191,7 +12191,7 @@ function rememberBounded(set, item) {
12191
12191
  for (const x of drop) set.delete(x);
12192
12192
  }
12193
12193
  }
12194
- var DEFAULT_MAX_CONCURRENT = 10;
12194
+ var DEFAULT_MAX_CONCURRENT = 50;
12195
12195
  var DEFAULT_SYNC_INTERVAL_MS = 3e4;
12196
12196
  var DEFAULT_RECONNECT_BASE_MS = 2e3;
12197
12197
  var DEFAULT_RECONNECT_MAX_MS = 6e4;
@@ -13184,6 +13184,7 @@ var Dispatcher = class {
13184
13184
  }
13185
13185
  /** Acquire a concurrency slot, run a worker, release the slot. */
13186
13186
  async spawnWorker(account, prompt, ctx) {
13187
+ const releaseAgentLock = await this.acquireAgentSerial(account.id);
13187
13188
  await this.acquireSlot();
13188
13189
  const workerId = `${account.id}:${ctx.kind}:${ctx.uid ?? ctx.taskId ?? ""}:${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
13189
13190
  let workerResult = null;
@@ -13266,6 +13267,10 @@ var Dispatcher = class {
13266
13267
  } finally {
13267
13268
  clearInterval(heartbeatHandle);
13268
13269
  this.releaseSlot();
13270
+ try {
13271
+ releaseAgentLock();
13272
+ } catch {
13273
+ }
13269
13274
  const ok = workerResult?.ok === true;
13270
13275
  const preview = workerResult?.ok ? workerResult.text : workerResult ? workerResult.error : "worker did not start";
13271
13276
  writeLog(`worker_finished ok=${ok} chars=${preview.length}`);
@@ -13371,6 +13376,41 @@ var Dispatcher = class {
13371
13376
  const next = this.waiters.shift();
13372
13377
  if (next) next();
13373
13378
  }
13379
+ /**
13380
+ * Per-agent serialization. At most ONE worker runs for any
13381
+ * given agent at a time. When a new wake fires for an agent
13382
+ * whose worker is still running, the new wake's spawnWorker
13383
+ * waits on the prior worker's tail before proceeding.
13384
+ *
13385
+ * This is the fix for the "dispatcher crashed when sender
13386
+ * broadcast to a 5-CC thread" failure mode: under the old
13387
+ * design, 5 emails landing for vesper-on-3-different-threads
13388
+ * in the same second spawned 5 simultaneous vesper workers,
13389
+ * each opening its own IMAP connection, each calling the
13390
+ * SDK, racing on the same inbox cache. With this gate they
13391
+ * queue tail-to-head and run sequentially.
13392
+ *
13393
+ * `nextRun` is a chained promise: each new spawn calls
13394
+ * `then()` on the previous tail so the order is preserved.
13395
+ * When the chain resolves to a no-op (empty queue), the
13396
+ * entry is garbage-collected from the map so memory stays
13397
+ * bounded at #active-agents.
13398
+ */
13399
+ agentSerial = /* @__PURE__ */ new Map();
13400
+ async acquireAgentSerial(agentId) {
13401
+ const prev = this.agentSerial.get(agentId);
13402
+ let release;
13403
+ const next = new Promise((resolve) => {
13404
+ release = resolve;
13405
+ });
13406
+ this.agentSerial.set(agentId, prev ? prev.then(() => next).catch(() => next) : next);
13407
+ if (prev) await prev.catch(() => {
13408
+ });
13409
+ return () => {
13410
+ release();
13411
+ if (this.agentSerial.get(agentId) === next) this.agentSerial.delete(agentId);
13412
+ };
13413
+ }
13374
13414
  };
13375
13415
  function sleep(ms) {
13376
13416
  return new Promise((resolve) => setTimeout(resolve, ms));
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  Dispatcher
4
- } from "./chunk-T3J2WZMM.js";
4
+ } from "./chunk-ZBDS3QNR.js";
5
5
  import "./chunk-DDJNA5HP.js";
6
6
  import "./chunk-B276KPVO.js";
7
7
  import "./chunk-RB5MGRT3.js";
@@ -31,7 +31,10 @@ async function main() {
31
31
  process.once("SIGINT", shutdown);
32
32
  process.once("SIGTERM", shutdown);
33
33
  process.on("unhandledRejection", (reason) => {
34
- console.error("[dispatcher-bin] unhandledRejection:", reason);
34
+ console.error("[dispatcher-bin] unhandledRejection (continuing):", reason);
35
+ });
36
+ process.on("uncaughtException", (err) => {
37
+ console.error("[dispatcher-bin] uncaughtException (continuing):", err);
35
38
  });
36
39
  await dispatcher.start();
37
40
  }
@@ -348,6 +348,28 @@ declare class Dispatcher {
348
348
  private buildMcpEnv;
349
349
  private acquireSlot;
350
350
  private releaseSlot;
351
+ /**
352
+ * Per-agent serialization. At most ONE worker runs for any
353
+ * given agent at a time. When a new wake fires for an agent
354
+ * whose worker is still running, the new wake's spawnWorker
355
+ * waits on the prior worker's tail before proceeding.
356
+ *
357
+ * This is the fix for the "dispatcher crashed when sender
358
+ * broadcast to a 5-CC thread" failure mode: under the old
359
+ * design, 5 emails landing for vesper-on-3-different-threads
360
+ * in the same second spawned 5 simultaneous vesper workers,
361
+ * each opening its own IMAP connection, each calling the
362
+ * SDK, racing on the same inbox cache. With this gate they
363
+ * queue tail-to-head and run sequentially.
364
+ *
365
+ * `nextRun` is a chained promise: each new spawn calls
366
+ * `then()` on the previous tail so the order is preserved.
367
+ * When the chain resolves to a no-op (empty queue), the
368
+ * entry is garbage-collected from the map so memory stays
369
+ * bounded at #active-agents.
370
+ */
371
+ private agentSerial;
372
+ private acquireAgentSerial;
351
373
  }
352
374
 
353
375
  export { Dispatcher, type DispatcherOptions, type QueryFn, type WorkerObserver };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  Dispatcher
3
- } from "./chunk-T3J2WZMM.js";
3
+ } from "./chunk-ZBDS3QNR.js";
4
4
  import "./chunk-DDJNA5HP.js";
5
5
  import "./chunk-B276KPVO.js";
6
6
  import "./chunk-RB5MGRT3.js";
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  Dispatcher,
3
3
  loadPersonaForAgent
4
- } from "./chunk-T3J2WZMM.js";
4
+ } from "./chunk-ZBDS3QNR.js";
5
5
  import "./chunk-DDJNA5HP.js";
6
6
  import "./chunk-B276KPVO.js";
7
7
  import "./chunk-RB5MGRT3.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agenticmail/claudecode",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "description": "Claude Code integration for AgenticMail — surfaces every AgenticMail agent as a native Claude Code subagent so any Claude Code session can delegate to them with the Agent tool",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",