@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
|
|
113
|
-
const subject = event
|
|
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)
|
|
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})`);
|
package/dist/dispatcher-bin.js
CHANGED
package/dist/dispatcher.d.ts
CHANGED
|
@@ -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;
|
package/dist/dispatcher.js
CHANGED
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agenticmail/claudecode",
|
|
3
|
-
"version": "0.1.
|
|
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",
|