@agenticmail/claudecode 0.1.0 → 0.1.2

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.
@@ -36,6 +36,20 @@ function loadPersonaForAgent(opts) {
36
36
  }
37
37
 
38
38
  // src/dispatcher.ts
39
+ function extractSubject(event) {
40
+ if (typeof event.subject === "string") return event.subject;
41
+ if (event.message && typeof event.message.subject === "string") return event.message.subject;
42
+ return void 0;
43
+ }
44
+ function extractFrom(event) {
45
+ if (typeof event.from === "string") return event.from;
46
+ if (event.message && Array.isArray(event.message.from)) {
47
+ const first = event.message.from[0];
48
+ if (first?.address) return first.address;
49
+ if (first?.name) return first.name;
50
+ }
51
+ return void 0;
52
+ }
39
53
  var SEEN_CAP = 1024;
40
54
  function rememberBounded(set, item) {
41
55
  set.add(item);
@@ -48,6 +62,16 @@ var DEFAULT_MAX_CONCURRENT = 10;
48
62
  var DEFAULT_SYNC_INTERVAL_MS = 6e4;
49
63
  var DEFAULT_RECONNECT_BASE_MS = 2e3;
50
64
  var DEFAULT_RECONNECT_MAX_MS = 6e4;
65
+ var TASK_MAIL_SUPPRESS_WINDOW_MS = 3e4;
66
+ var TASK_NOTIFICATION_SUBJECT_PREFIXES = ["[RPC]", "[Task]", "[Async-RPC]"];
67
+ function isTaskNotificationSubject(subject) {
68
+ if (!subject) return false;
69
+ const head = subject.trimStart();
70
+ for (const prefix of TASK_NOTIFICATION_SUBJECT_PREFIXES) {
71
+ if (head.toLowerCase().startsWith(prefix.toLowerCase())) return true;
72
+ }
73
+ return false;
74
+ }
51
75
  async function runWorker(query, persona, userPrompt, agent, mcpServerName, mcpCommand, mcpArgs, mcpEnv, log, abortSignal) {
52
76
  const opts = {
53
77
  systemPrompt: persona,
@@ -109,8 +133,8 @@ function wrapSignal(signal) {
109
133
  return c;
110
134
  }
111
135
  function newMailPrompt(agent, event) {
112
- const from = event.from ?? "unknown sender";
113
- const subject = event.subject ?? "(no subject)";
136
+ const from = extractFrom(event) ?? "unknown sender";
137
+ const subject = extractSubject(event) ?? "(no subject)";
114
138
  const uid = event.uid;
115
139
  return [
116
140
  `You have new mail.`,
@@ -202,6 +226,12 @@ var Dispatcher = class {
202
226
  if (event.type === "new" && typeof event.uid === "number") {
203
227
  const ch = this.channels.get(account.id);
204
228
  if (ch?.seenUids.has(event.uid)) return;
229
+ const subject = extractSubject(event);
230
+ if (ch && Date.now() < ch.suppressTaskMailUntilMs && isTaskNotificationSubject(subject)) {
231
+ this.log("info", `[dispatcher] suppressed task-notification mail wake for "${account.name}" (uid=${event.uid}, subject="${subject}") \u2014 task event already dispatched`);
232
+ rememberBounded(ch.seenUids, event.uid);
233
+ return;
234
+ }
205
235
  if (ch) rememberBounded(ch.seenUids, event.uid);
206
236
  await this.spawnWorker(account, newMailPrompt(account, event), { kind: "new-mail", uid: event.uid });
207
237
  return;
@@ -210,7 +240,10 @@ var Dispatcher = class {
210
240
  if (typeof event.assignee === "string" && event.assignee.toLowerCase() !== account.name.toLowerCase()) return;
211
241
  const ch = this.channels.get(account.id);
212
242
  if (ch?.seenTaskIds.has(event.taskId)) return;
213
- if (ch) rememberBounded(ch.seenTaskIds, event.taskId);
243
+ if (ch) {
244
+ rememberBounded(ch.seenTaskIds, event.taskId);
245
+ ch.suppressTaskMailUntilMs = Date.now() + TASK_MAIL_SUPPRESS_WINDOW_MS;
246
+ }
214
247
  await this.spawnWorker(account, taskPrompt(account, event), { kind: "task", taskId: event.taskId });
215
248
  return;
216
249
  }
@@ -244,7 +277,8 @@ var Dispatcher = class {
244
277
  stopping: false,
245
278
  backoffMs: this.reconnectBaseMs,
246
279
  seenUids: /* @__PURE__ */ new Set(),
247
- seenTaskIds: /* @__PURE__ */ new Set()
280
+ seenTaskIds: /* @__PURE__ */ new Set(),
281
+ suppressTaskMailUntilMs: 0
248
282
  };
249
283
  this.channels.set(account.id, ch);
250
284
  this.log("info", `[dispatcher] opening SSE for "${account.name}" (${account.email})`);
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  Dispatcher
4
- } from "./chunk-563BZ447.js";
4
+ } from "./chunk-VICS7KZZ.js";
5
5
  import "./chunk-XAW5NUNU.js";
6
6
 
7
7
  // src/dispatcher-bin.ts
@@ -45,7 +45,19 @@ interface SSEEvent {
45
45
  type?: string;
46
46
  uid?: number;
47
47
  from?: string;
48
+ /**
49
+ * Subject MAY appear at top-level on some code paths AND nested under
50
+ * `message.subject` on others (the master API enriches new-mail events
51
+ * with the full IMAP envelope, which lands under `message`). Always use
52
+ * `extractSubject(event)` rather than reading either path directly.
53
+ */
48
54
  subject?: string;
55
+ message?: {
56
+ subject?: string;
57
+ from?: unknown;
58
+ to?: unknown;
59
+ messageId?: string;
60
+ };
49
61
  taskId?: string;
50
62
  taskType?: string;
51
63
  task?: string;
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  Dispatcher
3
- } from "./chunk-563BZ447.js";
3
+ } from "./chunk-VICS7KZZ.js";
4
4
  import "./chunk-XAW5NUNU.js";
5
5
  export {
6
6
  Dispatcher
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  Dispatcher,
3
3
  loadPersonaForAgent
4
- } from "./chunk-563BZ447.js";
4
+ } from "./chunk-VICS7KZZ.js";
5
5
  import {
6
6
  createIntegrationRoutes
7
7
  } from "./chunk-UPA2YLSM.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agenticmail/claudecode",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
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",