@agenticmail/claudecode 0.1.17 → 0.2.1

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.
@@ -1,4 +1,4 @@
1
- import { R as ResolveConfigOptions, A as AgenticMailAccount } from './config-CjEDSvVy.js';
1
+ import { R as ResolveConfigOptions, A as AgenticMailAccount } from './config-CXW3gXFC.js';
2
2
 
3
3
  /**
4
4
  * AgenticMail → Claude Code event dispatcher.
@@ -68,6 +68,11 @@ interface SSEEvent {
68
68
  * Claude turn. When absent, every CC'd recipient wakes (v0.8.x default).
69
69
  */
70
70
  wakeAllowlist?: string[];
71
+ /** Per-recipient "was I on the To field?" flag emitted by the
72
+ * API in 0.9.1+. Pairs with the recipient's `wake_on_cc`
73
+ * preference: when the agent registered with wake_on_cc:false
74
+ * and `wasOnTo !== true`, the dispatcher drops the wake. */
75
+ wasOnTo?: boolean;
71
76
  [key: string]: unknown;
72
77
  }
73
78
  interface DispatcherOptions extends ResolveConfigOptions {
@@ -102,6 +107,18 @@ interface DispatcherOptions extends ResolveConfigOptions {
102
107
  log?: (level: 'info' | 'warn' | 'error', msg: string) => void;
103
108
  /** Override Date.now() — tests use this to advance the budget clock. */
104
109
  nowMs?: () => number;
110
+ /** Debounce window for wake-coalescing per (agent, thread).
111
+ * Default 30 s — covers a typical "burst of back-to-back
112
+ * replies in 5–15 s" pattern without making single replies
113
+ * feel sluggish. Set to 0 to disable coalescing entirely
114
+ * (one Claude turn per event, pre-0.9.0 behaviour). */
115
+ wakeCoalesceMs?: number;
116
+ /** Override the ThreadCache disk root. Tests use a tmpdir;
117
+ * production runs against ~/.agenticmail/thread-cache/. */
118
+ threadCacheDir?: string;
119
+ /** Override the AgentMemoryStore disk root. Same rationale as
120
+ * threadCacheDir — only tests should set this. */
121
+ agentMemoryDir?: string;
105
122
  }
106
123
  /** Minimal Claude Agent SDK query signature we use. */
107
124
  interface QueryFn {
@@ -152,6 +169,40 @@ declare class Dispatcher {
152
169
  private maxWakesPerThread;
153
170
  private wakeWindowMs;
154
171
  private now;
172
+ /**
173
+ * Layered wake-context system. ThreadCache holds the last K
174
+ * envelopes per thread (built passively on every SSE new-mail
175
+ * event, even when no agent wakes). AgentMemoryStore holds
176
+ * per-(agent, thread) markdown that workers write at end-of-
177
+ * wake via the save_thread_memory MCP tool. Both are read on
178
+ * worker spawn and injected into the wake prompt — see
179
+ * spawnWorker for the rendering.
180
+ */
181
+ private threadCache;
182
+ private agentMemory;
183
+ /**
184
+ * Coalesced wake queue. Keyed by `${accountId}::${threadId}`,
185
+ * each entry holds the pending events + the timer that will
186
+ * fire the spawn. A new event arriving while the entry exists
187
+ * EXTENDS the timer (debounce, not throttle) and appends to
188
+ * the event list. When the timer fires, a single Claude turn
189
+ * sees the union of new messages and replies once.
190
+ *
191
+ * Why debounce + not throttle: bursts of replies from one
192
+ * sender are typically a single logical handoff, not N
193
+ * separate actions. Throttling would still produce a stale
194
+ * wake after the burst settles; debouncing collapses the
195
+ * whole burst into one wake at the trailing edge.
196
+ */
197
+ private wakeCoalesce;
198
+ private wakeCoalesceMs;
199
+ /** Wall-clock timestamp the dispatcher started. Surfaced via
200
+ * process-heartbeat so check_activity can show uptime. */
201
+ private startedAtMs;
202
+ /** Periodic timer that posts a process-heartbeat to the API.
203
+ * Without this, a hung dispatcher looks identical to "no
204
+ * events to wake on" — the host has no liveness signal. */
205
+ private processHeartbeatTimer;
155
206
  constructor(opts?: DispatcherOptions);
156
207
  /**
157
208
  * Charge one wake against the (agent, thread) budget. Returns true
@@ -221,6 +272,51 @@ declare class Dispatcher {
221
272
  private runChannel;
222
273
  /** Single SSE attach. Returns when the stream closes for any reason. */
223
274
  private streamOne;
275
+ /**
276
+ * Enqueue (or extend) a wake for `(account, thread)`. First
277
+ * event creates the entry + starts the debounce timer; every
278
+ * subsequent event within the window APPENDS to the event
279
+ * list and EXTENDS the timer to `now + wakeCoalesceMs`.
280
+ *
281
+ * When the timer fires, `fireCoalescedWake` synthesises a
282
+ * single wake prompt covering every event that arrived in
283
+ * the burst and spawns one worker. The wake-budget is
284
+ * charged ONCE for the batch (a burst of 4 replies is one
285
+ * logical handoff, not four).
286
+ *
287
+ * When `wakeCoalesceMs` is 0 (test mode / opt-out), we skip
288
+ * the queue and spawn immediately to keep the pre-0.9.0
289
+ * one-event-per-wake semantics.
290
+ */
291
+ private scheduleCoalescedWake;
292
+ /**
293
+ * Pre-0.9.0 fast path used when coalescing is disabled. Same
294
+ * spawn that scheduleCoalescedWake/fireCoalescedWake would do
295
+ * for a single-event batch.
296
+ */
297
+ private fireWakeImmediately;
298
+ /**
299
+ * Timer callback for the coalesced wake. Builds a single wake
300
+ * prompt that summarises every event in the batch and fires
301
+ * one worker. Wake budget is charged once for the batch.
302
+ */
303
+ private fireCoalescedWake;
304
+ /**
305
+ * Prepend the thread-context block (cache + memory) to the
306
+ * wake prompt for a given account. Returns the prompt
307
+ * unchanged when neither layer has content — the very first
308
+ * wake on a brand-new thread shouldn't show the agent an
309
+ * empty "Thread context" section that screams "you've seen
310
+ * this before" when there's nothing to see.
311
+ *
312
+ * Exposed as a separate method so tests can drive it
313
+ * directly without invoking the SDK.
314
+ */
315
+ composeWakePromptWithContext(account: AgenticMailAccount, ctx: {
316
+ kind: string;
317
+ subject?: string;
318
+ uid?: number;
319
+ }, prompt: string): string;
224
320
  /** Acquire a concurrency slot, run a worker, release the slot. */
225
321
  private spawnWorker;
226
322
  /**
@@ -232,6 +328,22 @@ declare class Dispatcher {
232
328
  * load-bearing state.
233
329
  */
234
330
  private postActivity;
331
+ /**
332
+ * Post a "skipped wake" notification with the reason the
333
+ * dispatcher decided not to fire a Claude turn. Surfaced in
334
+ * `check_activity` so the host can see the decision instead
335
+ * of just observing silence ("did my mail land? did the
336
+ * dispatcher skip it? is the dispatcher even alive?").
337
+ *
338
+ * Reasons cover every filter that drops a wake:
339
+ * - thread-closed — subject had [FINAL]/[DONE]/[CLOSED]/[WRAP]
340
+ * - allowlist-excluded — sender's `wake` list did not include the agent
341
+ * - wake-on-cc — agent registered wake_on_cc:false and was on Cc
342
+ * - dedup — duplicate UID seen recently
343
+ * - rpc-suppress — RPC-notification mail right after a task event
344
+ * - budget-exhausted — per-(agent, thread) wake budget hit the cap
345
+ */
346
+ private postSkipped;
235
347
  /** Build the env block we pass to the worker's MCP server child process. */
236
348
  private buildMcpEnv;
237
349
  private acquireSlot;
@@ -1,7 +1,13 @@
1
1
  import {
2
2
  Dispatcher
3
- } from "./chunk-SO75WFJB.js";
3
+ } from "./chunk-TWFORAWT.js";
4
+ import "./chunk-DDJNA5HP.js";
5
+ import "./chunk-B276KPVO.js";
6
+ import "./chunk-RB5MGRT3.js";
7
+ import "./chunk-XNNC4MIH.js";
8
+ import "./chunk-BYXBJQAS.js";
4
9
  import "./chunk-SBP7MJP2.js";
10
+ import "./chunk-2ESYSVXG.js";
5
11
  export {
6
12
  Dispatcher
7
13
  };
@@ -0,0 +1,40 @@
1
+ import "./chunk-BYXBJQAS.js";
2
+ import "./chunk-2ESYSVXG.js";
3
+
4
+ // ../core/dist/email-worker-template-BOJPKCVB.js
5
+ var EMAIL_WORKER_SCRIPT = `
6
+ export default {
7
+ async email(message, env, ctx) {
8
+ // Read the raw RFC822 stream into an ArrayBuffer, then base64-encode
9
+ // because the inbound endpoint expects base64 in the rawEmail field.
10
+ const arrayBuf = await new Response(message.raw).arrayBuffer();
11
+ const bytes = new Uint8Array(arrayBuf);
12
+ let binary = '';
13
+ for (let i = 0; i < bytes.length; i++) {
14
+ binary += String.fromCharCode(bytes[i]);
15
+ }
16
+ const rawEmail = btoa(binary);
17
+
18
+ const response = await fetch(env.INBOUND_URL, {
19
+ method: 'POST',
20
+ headers: {
21
+ 'Content-Type': 'application/json',
22
+ 'X-Inbound-Secret': env.INBOUND_SECRET,
23
+ },
24
+ body: JSON.stringify({
25
+ from: message.from,
26
+ to: message.to,
27
+ rawEmail,
28
+ }),
29
+ });
30
+
31
+ if (!response.ok) {
32
+ // Log but don't reject \u2014 rejecting causes bounce-back to sender
33
+ console.error('AgenticMail inbound webhook failed:', response.status, await response.text());
34
+ }
35
+ },
36
+ };
37
+ `;
38
+ export {
39
+ EMAIL_WORKER_SCRIPT
40
+ };
@@ -7,6 +7,7 @@ import "./chunk-DKTAW2N5.js";
7
7
  import "./chunk-O4H76K3B.js";
8
8
  import "./chunk-US5FT2UB.js";
9
9
  import "./chunk-SBP7MJP2.js";
10
+ import "./chunk-2ESYSVXG.js";
10
11
  export {
11
12
  createIntegrationRoutes
12
13
  };
@@ -0,0 +1,6 @@
1
+ import {
2
+ require_imap_flow
3
+ } from "./chunk-DDJNA5HP.js";
4
+ import "./chunk-RB5MGRT3.js";
5
+ import "./chunk-2ESYSVXG.js";
6
+ export default require_imap_flow();
package/dist/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  export { install } from './install.js';
2
2
  export { UninstallOptions, uninstall } from './uninstall.js';
3
3
  export { status } from './status.js';
4
- import { A as AgenticMailAccount } from './config-CjEDSvVy.js';
5
- export { C as ClaudeCodeIntegrationConfig, I as InstallResult, a as InstallStatus, R as ResolveConfigOptions, U as UninstallResult, r as resolveConfig } from './config-CjEDSvVy.js';
4
+ import { A as AgenticMailAccount } from './config-CXW3gXFC.js';
5
+ export { C as ClaudeCodeIntegrationConfig, I as InstallResult, a as InstallStatus, R as ResolveConfigOptions, U as UninstallResult, r as resolveConfig } from './config-CXW3gXFC.js';
6
6
  export { createIntegrationRoutes } from './http-routes.js';
7
7
  export { Dispatcher, DispatcherOptions, QueryFn } from './dispatcher.js';
8
8
  import 'express';
package/dist/index.js CHANGED
@@ -1,7 +1,12 @@
1
1
  import {
2
2
  Dispatcher,
3
3
  loadPersonaForAgent
4
- } from "./chunk-SO75WFJB.js";
4
+ } from "./chunk-TWFORAWT.js";
5
+ import "./chunk-DDJNA5HP.js";
6
+ import "./chunk-B276KPVO.js";
7
+ import "./chunk-RB5MGRT3.js";
8
+ import "./chunk-XNNC4MIH.js";
9
+ import "./chunk-BYXBJQAS.js";
5
10
  import {
6
11
  createIntegrationRoutes
7
12
  } from "./chunk-PTLX7SQV.js";
@@ -28,6 +33,7 @@ import {
28
33
  renderSubagentMarkdown,
29
34
  resolveConfig
30
35
  } from "./chunk-SBP7MJP2.js";
36
+ import "./chunk-2ESYSVXG.js";
31
37
  export {
32
38
  AgenticMailApiError,
33
39
  Dispatcher,
package/dist/install.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { R as ResolveConfigOptions, I as InstallResult, A as AgenticMailAccount, C as ClaudeCodeIntegrationConfig } from './config-CjEDSvVy.js';
1
+ import { R as ResolveConfigOptions, I as InstallResult, A as AgenticMailAccount, C as ClaudeCodeIntegrationConfig } from './config-CXW3gXFC.js';
2
2
 
3
3
  /**
4
4
  * Install AgenticMail into Claude Code.
package/dist/install.js CHANGED
@@ -5,6 +5,7 @@ import {
5
5
  import "./chunk-DKTAW2N5.js";
6
6
  import "./chunk-US5FT2UB.js";
7
7
  import "./chunk-SBP7MJP2.js";
8
+ import "./chunk-2ESYSVXG.js";
8
9
  export {
9
10
  install,
10
11
  selectExposableAgents
@@ -0,0 +1,6 @@
1
+ import {
2
+ require_mailparser
3
+ } from "./chunk-B276KPVO.js";
4
+ import "./chunk-RB5MGRT3.js";
5
+ import "./chunk-2ESYSVXG.js";
6
+ export default require_mailparser();
@@ -0,0 +1,14 @@
1
+ import {
2
+ SPAM_THRESHOLD,
3
+ WARNING_THRESHOLD,
4
+ isInternalEmail,
5
+ scoreEmail
6
+ } from "./chunk-XNNC4MIH.js";
7
+ import "./chunk-BYXBJQAS.js";
8
+ import "./chunk-2ESYSVXG.js";
9
+ export {
10
+ SPAM_THRESHOLD,
11
+ WARNING_THRESHOLD,
12
+ isInternalEmail,
13
+ scoreEmail
14
+ };
package/dist/status.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { R as ResolveConfigOptions, a as InstallStatus } from './config-CjEDSvVy.js';
1
+ import { R as ResolveConfigOptions, a as InstallStatus } from './config-CXW3gXFC.js';
2
2
 
3
3
  /**
4
4
  * Inspect the current install state of @agenticmail/claudecode.
package/dist/status.js CHANGED
@@ -3,6 +3,7 @@ import {
3
3
  } from "./chunk-O4H76K3B.js";
4
4
  import "./chunk-US5FT2UB.js";
5
5
  import "./chunk-SBP7MJP2.js";
6
+ import "./chunk-2ESYSVXG.js";
6
7
  export {
7
8
  status
8
9
  };
@@ -1,4 +1,4 @@
1
- import { R as ResolveConfigOptions, U as UninstallResult } from './config-CjEDSvVy.js';
1
+ import { R as ResolveConfigOptions, U as UninstallResult } from './config-CXW3gXFC.js';
2
2
 
3
3
  /**
4
4
  * Uninstall AgenticMail from Claude Code.
package/dist/uninstall.js CHANGED
@@ -4,6 +4,7 @@ import {
4
4
  import "./chunk-DKTAW2N5.js";
5
5
  import "./chunk-US5FT2UB.js";
6
6
  import "./chunk-SBP7MJP2.js";
7
+ import "./chunk-2ESYSVXG.js";
7
8
  export {
8
9
  uninstall
9
10
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agenticmail/claudecode",
3
- "version": "0.1.17",
3
+ "version": "0.2.1",
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",
@@ -47,7 +47,7 @@
47
47
  "prepublishOnly": "npm run build"
48
48
  },
49
49
  "dependencies": {
50
- "@agenticmail/mcp": "^0.7.0",
50
+ "@agenticmail/mcp": "^0.9.1",
51
51
  "@anthropic-ai/claude-agent-sdk": "^0.2.140"
52
52
  },
53
53
  "peerDependencies": {