@agenticmail/claudecode 0.1.16 → 0.2.0

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.
@@ -102,6 +102,18 @@ interface DispatcherOptions extends ResolveConfigOptions {
102
102
  log?: (level: 'info' | 'warn' | 'error', msg: string) => void;
103
103
  /** Override Date.now() — tests use this to advance the budget clock. */
104
104
  nowMs?: () => number;
105
+ /** Debounce window for wake-coalescing per (agent, thread).
106
+ * Default 30 s — covers a typical "burst of back-to-back
107
+ * replies in 5–15 s" pattern without making single replies
108
+ * feel sluggish. Set to 0 to disable coalescing entirely
109
+ * (one Claude turn per event, pre-0.9.0 behaviour). */
110
+ wakeCoalesceMs?: number;
111
+ /** Override the ThreadCache disk root. Tests use a tmpdir;
112
+ * production runs against ~/.agenticmail/thread-cache/. */
113
+ threadCacheDir?: string;
114
+ /** Override the AgentMemoryStore disk root. Same rationale as
115
+ * threadCacheDir — only tests should set this. */
116
+ agentMemoryDir?: string;
105
117
  }
106
118
  /** Minimal Claude Agent SDK query signature we use. */
107
119
  interface QueryFn {
@@ -152,6 +164,33 @@ declare class Dispatcher {
152
164
  private maxWakesPerThread;
153
165
  private wakeWindowMs;
154
166
  private now;
167
+ /**
168
+ * Layered wake-context system. ThreadCache holds the last K
169
+ * envelopes per thread (built passively on every SSE new-mail
170
+ * event, even when no agent wakes). AgentMemoryStore holds
171
+ * per-(agent, thread) markdown that workers write at end-of-
172
+ * wake via the save_thread_memory MCP tool. Both are read on
173
+ * worker spawn and injected into the wake prompt — see
174
+ * spawnWorker for the rendering.
175
+ */
176
+ private threadCache;
177
+ private agentMemory;
178
+ /**
179
+ * Coalesced wake queue. Keyed by `${accountId}::${threadId}`,
180
+ * each entry holds the pending events + the timer that will
181
+ * fire the spawn. A new event arriving while the entry exists
182
+ * EXTENDS the timer (debounce, not throttle) and appends to
183
+ * the event list. When the timer fires, a single Claude turn
184
+ * sees the union of new messages and replies once.
185
+ *
186
+ * Why debounce + not throttle: bursts of replies from one
187
+ * sender are typically a single logical handoff, not N
188
+ * separate actions. Throttling would still produce a stale
189
+ * wake after the burst settles; debouncing collapses the
190
+ * whole burst into one wake at the trailing edge.
191
+ */
192
+ private wakeCoalesce;
193
+ private wakeCoalesceMs;
155
194
  constructor(opts?: DispatcherOptions);
156
195
  /**
157
196
  * Charge one wake against the (agent, thread) budget. Returns true
@@ -221,6 +260,51 @@ declare class Dispatcher {
221
260
  private runChannel;
222
261
  /** Single SSE attach. Returns when the stream closes for any reason. */
223
262
  private streamOne;
263
+ /**
264
+ * Enqueue (or extend) a wake for `(account, thread)`. First
265
+ * event creates the entry + starts the debounce timer; every
266
+ * subsequent event within the window APPENDS to the event
267
+ * list and EXTENDS the timer to `now + wakeCoalesceMs`.
268
+ *
269
+ * When the timer fires, `fireCoalescedWake` synthesises a
270
+ * single wake prompt covering every event that arrived in
271
+ * the burst and spawns one worker. The wake-budget is
272
+ * charged ONCE for the batch (a burst of 4 replies is one
273
+ * logical handoff, not four).
274
+ *
275
+ * When `wakeCoalesceMs` is 0 (test mode / opt-out), we skip
276
+ * the queue and spawn immediately to keep the pre-0.9.0
277
+ * one-event-per-wake semantics.
278
+ */
279
+ private scheduleCoalescedWake;
280
+ /**
281
+ * Pre-0.9.0 fast path used when coalescing is disabled. Same
282
+ * spawn that scheduleCoalescedWake/fireCoalescedWake would do
283
+ * for a single-event batch.
284
+ */
285
+ private fireWakeImmediately;
286
+ /**
287
+ * Timer callback for the coalesced wake. Builds a single wake
288
+ * prompt that summarises every event in the batch and fires
289
+ * one worker. Wake budget is charged once for the batch.
290
+ */
291
+ private fireCoalescedWake;
292
+ /**
293
+ * Prepend the thread-context block (cache + memory) to the
294
+ * wake prompt for a given account. Returns the prompt
295
+ * unchanged when neither layer has content — the very first
296
+ * wake on a brand-new thread shouldn't show the agent an
297
+ * empty "Thread context" section that screams "you've seen
298
+ * this before" when there's nothing to see.
299
+ *
300
+ * Exposed as a separate method so tests can drive it
301
+ * directly without invoking the SDK.
302
+ */
303
+ composeWakePromptWithContext(account: AgenticMailAccount, ctx: {
304
+ kind: string;
305
+ subject?: string;
306
+ uid?: number;
307
+ }, prompt: string): string;
224
308
  /** Acquire a concurrency slot, run a worker, release the slot. */
225
309
  private spawnWorker;
226
310
  /**
@@ -1,7 +1,13 @@
1
1
  import {
2
2
  Dispatcher
3
- } from "./chunk-RNKJRBEF.js";
3
+ } from "./chunk-UCI2HLHM.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.js CHANGED
@@ -1,7 +1,12 @@
1
1
  import {
2
2
  Dispatcher,
3
3
  loadPersonaForAgent
4
- } from "./chunk-RNKJRBEF.js";
4
+ } from "./chunk-UCI2HLHM.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.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.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
  };
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.16",
3
+ "version": "0.2.0",
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.0",
51
51
  "@anthropic-ai/claude-agent-sdk": "^0.2.140"
52
52
  },
53
53
  "peerDependencies": {