@agenticmail/claudecode 0.1.6 → 0.1.8
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.
- package/dist/{chunk-5M43V6CB.js → chunk-5HUEJNT5.js} +150 -23
- package/dist/{chunk-XGBVWZ3M.js → chunk-JVDPUO35.js} +1 -1
- package/dist/{chunk-YWSO3QOQ.js → chunk-M5HV2M67.js} +13 -37
- package/dist/{chunk-WP2ELPRM.js → chunk-V5LH4BNZ.js} +1 -1
- package/dist/{chunk-UC63VEBP.js → chunk-VYBBCFP5.js} +1 -1
- package/dist/{chunk-N43A7EQB.js → chunk-XHDRGX46.js} +4 -4
- package/dist/cli.js +4 -4
- package/dist/dispatcher-bin.js +2 -2
- package/dist/dispatcher.d.ts +22 -0
- package/dist/dispatcher.js +2 -2
- package/dist/http-routes.js +5 -5
- package/dist/index.js +6 -6
- package/dist/install.js +2 -2
- package/dist/status.js +2 -2
- package/dist/uninstall.js +2 -2
- package/package.json +1 -1
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
listAccounts,
|
|
3
3
|
renderPersonaBody,
|
|
4
4
|
resolveConfig
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-M5HV2M67.js";
|
|
6
6
|
|
|
7
7
|
// src/persona-loader.ts
|
|
8
8
|
import { existsSync, readFileSync } from "fs";
|
|
@@ -59,7 +59,7 @@ function rememberBounded(set, item) {
|
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
61
|
var DEFAULT_MAX_CONCURRENT = 10;
|
|
62
|
-
var DEFAULT_SYNC_INTERVAL_MS =
|
|
62
|
+
var DEFAULT_SYNC_INTERVAL_MS = 3e4;
|
|
63
63
|
var DEFAULT_RECONNECT_BASE_MS = 2e3;
|
|
64
64
|
var DEFAULT_RECONNECT_MAX_MS = 6e4;
|
|
65
65
|
var TASK_MAIL_SUPPRESS_WINDOW_MS = 3e4;
|
|
@@ -82,25 +82,25 @@ async function runWorker(query, persona, userPrompt, agent, mcpServerName, mcpCo
|
|
|
82
82
|
env: mcpEnv
|
|
83
83
|
}
|
|
84
84
|
},
|
|
85
|
-
//
|
|
86
|
-
//
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
85
|
+
// No `allowedTools` restriction.
|
|
86
|
+
//
|
|
87
|
+
// Earlier versions of the dispatcher locked workers to MCP-only tools
|
|
88
|
+
// ("you operate an email account, not a developer environment"). That
|
|
89
|
+
// was the wrong design: AgenticMail agents are real Claude Code
|
|
90
|
+
// subagents running under the host's OAuth, and the work humans
|
|
91
|
+
// delegate to them (write code, run tests, do research, edit files)
|
|
92
|
+
// demands the full native toolset (Read, Write, Edit, Bash, Glob,
|
|
93
|
+
// Grep, WebFetch, WebSearch, NotebookEdit, …). Restricting them
|
|
94
|
+
// turned "Zephyr implements the game" into "Zephyr emails source
|
|
95
|
+
// code as plaintext and the human has to copy-paste it" — which
|
|
96
|
+
// defeats the point of having agents in the first place.
|
|
97
|
+
//
|
|
98
|
+
// Omitting allowedTools lets the SDK fall through to its defaults
|
|
99
|
+
// (all built-in tools + every tool exposed by the MCP servers we
|
|
100
|
+
// declare above). Outbound mail is still guarded by AgenticMail's
|
|
101
|
+
// own outbound guard (HIGH-severity sends held for owner approval)
|
|
102
|
+
// and the worker is sandboxed by Claude Code's permission system
|
|
103
|
+
// just like any other subagent.
|
|
104
104
|
permissionMode: "bypassPermissions",
|
|
105
105
|
abortController: abortSignal ? wrapSignal(abortSignal) : void 0
|
|
106
106
|
};
|
|
@@ -172,8 +172,14 @@ function newMailPrompt(agent, event) {
|
|
|
172
172
|
` When in doubt, stay silent \u2014 over-replying creates noise. Better to let`,
|
|
173
173
|
` the right teammate take the turn than to step on theirs.`,
|
|
174
174
|
``,
|
|
175
|
-
`5. **If it's your turn \u2014
|
|
176
|
-
`
|
|
175
|
+
`5. **If it's your turn \u2014 do the actual work, THEN reply-all about it.**`,
|
|
176
|
+
` You have full native tools: Read, Write, Edit, Bash, Glob, Grep, WebFetch,`,
|
|
177
|
+
` WebSearch, NotebookEdit, etc. If the task is "implement X", write the file`,
|
|
178
|
+
` with Write or Edit and verify with Bash \u2014 do NOT paste source code into an`,
|
|
179
|
+
` email body and call it shipped. The thread is for COORDINATION ("done,`,
|
|
180
|
+
` see ./foo.py, runs with \`python3 foo.py\`"); the filesystem is for`,
|
|
181
|
+
` DELIVERABLES. Then:`,
|
|
182
|
+
` reply_email({ uid: ${uid ?? "<uid>"}, replyAll: true, text: "...", _account: "${agent.name}" })`,
|
|
177
183
|
` Sign with your name. Be substantive but concise. If you are handing off`,
|
|
178
184
|
` to the next teammate, name them explicitly in your reply ("Orion \u2014 over to you, please \u2026").`,
|
|
179
185
|
``,
|
|
@@ -229,6 +235,7 @@ var Dispatcher = class {
|
|
|
229
235
|
channels = /* @__PURE__ */ new Map();
|
|
230
236
|
// keyed by account.id
|
|
231
237
|
accountSyncTimer = null;
|
|
238
|
+
systemChannelController = null;
|
|
232
239
|
running = 0;
|
|
233
240
|
waiters = [];
|
|
234
241
|
stopped = false;
|
|
@@ -251,11 +258,19 @@ var Dispatcher = class {
|
|
|
251
258
|
this.accountSyncTimer = setInterval(() => {
|
|
252
259
|
this.syncAccounts().catch((err) => this.log("warn", `[dispatcher] account sync failed: ${err}`));
|
|
253
260
|
}, this.syncIntervalMs);
|
|
261
|
+
void this.runSystemChannel();
|
|
254
262
|
}
|
|
255
263
|
async stop() {
|
|
256
264
|
this.stopped = true;
|
|
257
265
|
if (this.accountSyncTimer) clearInterval(this.accountSyncTimer);
|
|
258
266
|
this.accountSyncTimer = null;
|
|
267
|
+
if (this.systemChannelController) {
|
|
268
|
+
try {
|
|
269
|
+
this.systemChannelController.abort();
|
|
270
|
+
} catch {
|
|
271
|
+
}
|
|
272
|
+
this.systemChannelController = null;
|
|
273
|
+
}
|
|
259
274
|
for (const ch of this.channels.values()) {
|
|
260
275
|
ch.stopping = true;
|
|
261
276
|
ch.controller?.abort();
|
|
@@ -352,6 +367,118 @@ var Dispatcher = class {
|
|
|
352
367
|
void this.runChannel(ch);
|
|
353
368
|
}
|
|
354
369
|
}
|
|
370
|
+
/**
|
|
371
|
+
* Subscribe to the API's master-scoped system events SSE.
|
|
372
|
+
*
|
|
373
|
+
* Pushes from /system/events arrive as JSON-per-frame just like the
|
|
374
|
+
* per-account stream:
|
|
375
|
+
* { type: "connected" }
|
|
376
|
+
* { type: "account_created", account: { id, name, email, apiKey, ... } }
|
|
377
|
+
* { type: "account_deleted", accountId, name }
|
|
378
|
+
*
|
|
379
|
+
* On `account_created` we eagerly open a per-account SSE channel using
|
|
380
|
+
* the apiKey carried in the event payload — no extra round trip, the
|
|
381
|
+
* channel is live within milliseconds of the POST /accounts response.
|
|
382
|
+
*
|
|
383
|
+
* Reconnect with the same exponential backoff scheme as per-account
|
|
384
|
+
* channels. If the API is older and doesn't expose /system/events
|
|
385
|
+
* (404), we log once and stop trying — polling-only fallback still
|
|
386
|
+
* works.
|
|
387
|
+
*/
|
|
388
|
+
async runSystemChannel() {
|
|
389
|
+
let backoff = this.reconnectBaseMs;
|
|
390
|
+
let giveUp = false;
|
|
391
|
+
while (!this.stopped && !giveUp) {
|
|
392
|
+
this.systemChannelController = new AbortController();
|
|
393
|
+
try {
|
|
394
|
+
const url = `${this.cfg.apiUrl.replace(/\/$/, "")}/api/agenticmail/system/events`;
|
|
395
|
+
const res = await this.fetchImpl(url, {
|
|
396
|
+
headers: {
|
|
397
|
+
"Authorization": `Bearer ${this.cfg.masterKey}`,
|
|
398
|
+
"Accept": "text/event-stream"
|
|
399
|
+
},
|
|
400
|
+
signal: this.systemChannelController.signal
|
|
401
|
+
});
|
|
402
|
+
if (res.status === 404) {
|
|
403
|
+
this.log("warn", "[dispatcher] /system/events not available on this API \u2014 falling back to polling-only account discovery (please upgrade @agenticmail/api to >=0.7.3)");
|
|
404
|
+
giveUp = true;
|
|
405
|
+
break;
|
|
406
|
+
}
|
|
407
|
+
if (!res.ok || !res.body) {
|
|
408
|
+
throw new Error(`system/events HTTP ${res.status}`);
|
|
409
|
+
}
|
|
410
|
+
backoff = this.reconnectBaseMs;
|
|
411
|
+
const reader = res.body.getReader();
|
|
412
|
+
const decoder = new TextDecoder();
|
|
413
|
+
let buffer = "";
|
|
414
|
+
while (!this.stopped) {
|
|
415
|
+
const { value, done } = await reader.read();
|
|
416
|
+
if (done) break;
|
|
417
|
+
buffer += decoder.decode(value, { stream: true });
|
|
418
|
+
let boundary;
|
|
419
|
+
while ((boundary = buffer.indexOf("\n\n")) !== -1) {
|
|
420
|
+
const frame = buffer.slice(0, boundary);
|
|
421
|
+
buffer = buffer.slice(boundary + 2);
|
|
422
|
+
for (const line of frame.split("\n")) {
|
|
423
|
+
if (!line.startsWith("data: ")) continue;
|
|
424
|
+
try {
|
|
425
|
+
const event = JSON.parse(line.slice(6));
|
|
426
|
+
this.handleSystemEvent(event);
|
|
427
|
+
} catch {
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
} catch (err) {
|
|
433
|
+
if (this.stopped) break;
|
|
434
|
+
this.log("warn", `[dispatcher] system-events stream error: ${err.message}; reconnecting in ${backoff}ms`);
|
|
435
|
+
}
|
|
436
|
+
if (this.stopped || giveUp) break;
|
|
437
|
+
await sleep(backoff);
|
|
438
|
+
backoff = Math.min(backoff * 2, this.reconnectMaxMs);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
/** Apply an account-lifecycle event from /system/events. */
|
|
442
|
+
handleSystemEvent(event) {
|
|
443
|
+
const type = typeof event.type === "string" ? event.type : "";
|
|
444
|
+
if (type === "account_created" && event.account && typeof event.account === "object") {
|
|
445
|
+
const account = event.account;
|
|
446
|
+
if (!account.id || !account.name || !account.apiKey) {
|
|
447
|
+
this.log("warn", "[dispatcher] account_created event missing required fields; ignoring");
|
|
448
|
+
return;
|
|
449
|
+
}
|
|
450
|
+
if (!this.shouldWatch(account)) {
|
|
451
|
+
this.log("info", `[dispatcher] account_created "${account.name}" \u2014 skipping (bridge/role excluded)`);
|
|
452
|
+
return;
|
|
453
|
+
}
|
|
454
|
+
if (this.channels.has(account.id)) return;
|
|
455
|
+
const ch = {
|
|
456
|
+
account,
|
|
457
|
+
controller: null,
|
|
458
|
+
stopping: false,
|
|
459
|
+
backoffMs: this.reconnectBaseMs,
|
|
460
|
+
seenUids: /* @__PURE__ */ new Set(),
|
|
461
|
+
seenTaskIds: /* @__PURE__ */ new Set(),
|
|
462
|
+
suppressTaskMailUntilMs: 0
|
|
463
|
+
};
|
|
464
|
+
this.channels.set(account.id, ch);
|
|
465
|
+
this.log("info", `[dispatcher] account_created "${account.name}" (${account.email}) \u2014 opening SSE channel immediately`);
|
|
466
|
+
void this.runChannel(ch);
|
|
467
|
+
return;
|
|
468
|
+
}
|
|
469
|
+
if (type === "account_deleted" && typeof event.accountId === "string") {
|
|
470
|
+
const ch = this.channels.get(event.accountId);
|
|
471
|
+
if (!ch) return;
|
|
472
|
+
ch.stopping = true;
|
|
473
|
+
try {
|
|
474
|
+
ch.controller?.abort();
|
|
475
|
+
} catch {
|
|
476
|
+
}
|
|
477
|
+
this.channels.delete(event.accountId);
|
|
478
|
+
this.log("info", `[dispatcher] account_deleted "${ch.account.name}" \u2014 closed SSE channel`);
|
|
479
|
+
return;
|
|
480
|
+
}
|
|
481
|
+
}
|
|
355
482
|
/** Watch one account's SSE stream forever; reconnect with backoff on drop. */
|
|
356
483
|
async runChannel(ch) {
|
|
357
484
|
while (!ch.stopping && !this.stopped) {
|
|
@@ -121,30 +121,6 @@ function resolveConfig(opts = {}) {
|
|
|
121
121
|
}
|
|
122
122
|
|
|
123
123
|
// src/subagent-template.ts
|
|
124
|
-
var ESSENTIAL_TOOL_NAMES = [
|
|
125
|
-
"whoami",
|
|
126
|
-
"list_inbox",
|
|
127
|
-
"read_email",
|
|
128
|
-
"send_email",
|
|
129
|
-
"reply_email",
|
|
130
|
-
"search_emails",
|
|
131
|
-
"list_agents",
|
|
132
|
-
"message_agent",
|
|
133
|
-
// call_agent is the one-shot RPC primitive — sync request, sync answer.
|
|
134
|
-
// For multi-step coordination use the thread pattern (send_email with
|
|
135
|
-
// CC + reply_email with replyAll) instead.
|
|
136
|
-
"call_agent",
|
|
137
|
-
// wait_for_email is the thread-coordination primitive: block until a
|
|
138
|
-
// specific reply lands in your inbox (filter by from / subject /
|
|
139
|
-
// inReplyTo / participants). Essential for delegate-then-wait flows;
|
|
140
|
-
// making subagents discover it via request_tools would be a usability
|
|
141
|
-
// disaster for the most common coordination pattern.
|
|
142
|
-
"wait_for_email",
|
|
143
|
-
"check_tasks",
|
|
144
|
-
// Meta-tools — these unlock the other ~50 tools on demand.
|
|
145
|
-
"request_tools",
|
|
146
|
-
"invoke"
|
|
147
|
-
];
|
|
148
124
|
var MANAGED_BY_MARKER = "@agenticmail/claudecode";
|
|
149
125
|
function yamlQuote(s) {
|
|
150
126
|
const cleaned = s.replace(/[\r\n]+/g, " ").replace(/\s+/g, " ").trim();
|
|
@@ -182,14 +158,15 @@ function renderPersonaBody(input) {
|
|
|
182
158
|
"",
|
|
183
159
|
"## Operating instructions",
|
|
184
160
|
"",
|
|
185
|
-
`You
|
|
161
|
+
`You have access to TWO complementary toolsets:`,
|
|
186
162
|
"",
|
|
187
|
-
|
|
188
|
-
`- \`${tool("invoke")}\` \u2014 Calls any AgenticMail tool by name with structured args. Example: \`${tool("invoke")}({ tool: "manage_signatures", args: { action: "create", name: "default", body: "\u2014\\n${agent.name}" }, _account: "${agent.name}" })\`.`,
|
|
163
|
+
`1. **AgenticMail MCP tools** (\`${tool("*")}\`) \u2014 your mailbox, contacts, tasks, signatures, drafts, SMS, agent coordination. The full ~62-tool surface; the most common ones (\`${tool("list_inbox")}\`, \`${tool("send_email")}\`, \`${tool("reply_email")}\`, \`${tool("search_emails")}\`, \`${tool("call_agent")}\`, \`${tool("wait_for_email")}\`, \u2026) are pre-loaded. Anything else is reachable via the meta-tools \`${tool("request_tools")}\` (discover) + \`${tool("invoke")}\` (call by name).`,
|
|
189
164
|
"",
|
|
190
|
-
|
|
165
|
+
`2. **Native Claude Code tools** \u2014 Read, Write, Edit, Bash, Glob, Grep, WebFetch, WebSearch, NotebookEdit, and friends. The same toolset the host session has. Use them when the work actually involves files, code, the shell, or the web \u2014 DO NOT paste source code into an email when you could write the file yourself and tell the team "shipped to ./void_fall.py, runs with python3 void_fall.py". You are a real agent doing real work, not a paste-buffer.`,
|
|
191
166
|
"",
|
|
192
|
-
|
|
167
|
+
`**On EVERY MCP call you make \u2014 pre-loaded OR via \`invoke\` \u2014 you MUST pass \`_account: "${agent.name}"\`.** This tells the MCP server to authenticate as you, not as the integration's bridge identity. Without it, you'd be reading the bridge's empty inbox instead of your own, sending mail from the wrong address, and bypassing your owner's expectation that the agent named "${agent.name}" did the work. Native tools (Read/Write/Bash/etc.) don't need \`_account\` \u2014 they're not MCP.`,
|
|
168
|
+
"",
|
|
169
|
+
`Common MCP examples:`,
|
|
193
170
|
"",
|
|
194
171
|
"```",
|
|
195
172
|
`${tool("list_inbox")}({ _account: "${agent.name}", limit: 10 })`,
|
|
@@ -230,14 +207,16 @@ function renderPersonaBody(input) {
|
|
|
230
207
|
"",
|
|
231
208
|
"## What you can do",
|
|
232
209
|
"",
|
|
233
|
-
`Anything
|
|
210
|
+
`Anything a real Claude Code agent can do, scoped to your AgenticMail identity. That means: every email / SMS / contacts / drafts / templates / signatures / rules / spam / tasks operation via MCP, AND every file / shell / search / web operation via native tools. If the work involves code \u2014 write the file, run it, debug it, commit it. If the work involves research \u2014 fetch the URLs, read the pages, summarise. Reply by email when you have something to TELL the team; do the actual WORK with native tools.`,
|
|
211
|
+
"",
|
|
212
|
+
`If a specific AgenticMail tool isn't already loaded, call \`${tool("request_tools")}\` to find it, then \`${tool("invoke")}\` to call it. Never ask for permission to use a tool \u2014 just use it.`,
|
|
234
213
|
"",
|
|
235
214
|
"## Hard rules",
|
|
236
215
|
"",
|
|
237
|
-
`- **Always pass \`_account: "${agent.name}"\`** on every \`${tool("*")}\` call
|
|
238
|
-
`- **Do
|
|
216
|
+
`- **Always pass \`_account: "${agent.name}"\`** on every \`${tool("*")}\` MCP call. (Native tools \u2014 Read/Write/Bash/etc. \u2014 don't need it.)`,
|
|
217
|
+
`- **Do real work with the right tool.** If a teammate asks you to implement something, write the file with Write or Edit \u2014 do not paste source code into an email body and call it done. The mail thread is for coordination ("shipped at \`./void_fall.py\`, runs with \`python3 void_fall.py\`, here's a 2-line summary"); the filesystem is for deliverables.`,
|
|
239
218
|
`- **Do not invent email content.** If you didn't read a real message, do not summarise one. If you don't know the answer, check your inbox / contacts / tasks first.`,
|
|
240
|
-
`- **Do not impersonate other agents.** You are ${agent.name}, and only ${agent.name}. If the user asks you to also do something as "writer" or "researcher", suggest that they call those agents directly
|
|
219
|
+
`- **Do not impersonate other agents.** You are ${agent.name}, and only ${agent.name}. If the user asks you to also do something as "writer" or "researcher", suggest that they call those agents directly \u2014 don't pass \`_account: "writer"\` to act as writer; that would falsify the From: header in any outgoing mail.`,
|
|
241
220
|
`- **Respect outbound guard.** If a send is blocked by the AgenticMail outbound guard, tell the user in plain English \u2014 recipient, subject, the specific warnings \u2014 and ask them to approve. Do NOT rewrite the email to evade detection.`,
|
|
242
221
|
"",
|
|
243
222
|
"## Output style",
|
|
@@ -247,15 +226,12 @@ function renderPersonaBody(input) {
|
|
|
247
226
|
].filter((line) => line !== void 0).join("\n");
|
|
248
227
|
}
|
|
249
228
|
function renderSubagentMarkdown(input) {
|
|
250
|
-
const { name, agent
|
|
251
|
-
const tool = (n) => `mcp__${mcpServerName}__${n}`;
|
|
229
|
+
const { name, agent } = input;
|
|
252
230
|
const description = describeAgent(agent);
|
|
253
|
-
const allowedTools = ESSENTIAL_TOOL_NAMES.map((n) => tool(n)).join(", ");
|
|
254
231
|
const frontmatter = [
|
|
255
232
|
"---",
|
|
256
233
|
`name: ${name}`,
|
|
257
234
|
`description: ${yamlQuote(description)}`,
|
|
258
|
-
`tools: ${allowedTools}`,
|
|
259
235
|
`model: inherit`,
|
|
260
236
|
`# managed-by: ${MANAGED_BY_MARKER}`,
|
|
261
237
|
`# agenticmail-agent-id: ${agent.id}`,
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
install
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-V5LH4BNZ.js";
|
|
4
4
|
import {
|
|
5
5
|
status
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-VYBBCFP5.js";
|
|
7
7
|
import {
|
|
8
8
|
uninstall
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-JVDPUO35.js";
|
|
10
10
|
import {
|
|
11
11
|
AgenticMailApiError
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-M5HV2M67.js";
|
|
13
13
|
|
|
14
14
|
// src/http-routes.ts
|
|
15
15
|
import { Router } from "express";
|
package/dist/cli.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
install
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-V5LH4BNZ.js";
|
|
5
5
|
import {
|
|
6
6
|
status
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-VYBBCFP5.js";
|
|
8
8
|
import {
|
|
9
9
|
uninstall
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-JVDPUO35.js";
|
|
11
11
|
import "./chunk-US5FT2UB.js";
|
|
12
12
|
import {
|
|
13
13
|
AgenticMailApiError
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-M5HV2M67.js";
|
|
15
15
|
|
|
16
16
|
// src/cli.ts
|
|
17
17
|
var GREEN = (s) => `\x1B[32m${s}\x1B[0m`;
|
package/dist/dispatcher-bin.js
CHANGED
package/dist/dispatcher.d.ts
CHANGED
|
@@ -103,6 +103,7 @@ declare class Dispatcher {
|
|
|
103
103
|
private log;
|
|
104
104
|
private channels;
|
|
105
105
|
private accountSyncTimer;
|
|
106
|
+
private systemChannelController;
|
|
106
107
|
private running;
|
|
107
108
|
private waiters;
|
|
108
109
|
private stopped;
|
|
@@ -131,6 +132,27 @@ declare class Dispatcher {
|
|
|
131
132
|
private shouldWatch;
|
|
132
133
|
/** Re-fetch /accounts; open SSE for new ones, close for vanished ones. */
|
|
133
134
|
private syncAccounts;
|
|
135
|
+
/**
|
|
136
|
+
* Subscribe to the API's master-scoped system events SSE.
|
|
137
|
+
*
|
|
138
|
+
* Pushes from /system/events arrive as JSON-per-frame just like the
|
|
139
|
+
* per-account stream:
|
|
140
|
+
* { type: "connected" }
|
|
141
|
+
* { type: "account_created", account: { id, name, email, apiKey, ... } }
|
|
142
|
+
* { type: "account_deleted", accountId, name }
|
|
143
|
+
*
|
|
144
|
+
* On `account_created` we eagerly open a per-account SSE channel using
|
|
145
|
+
* the apiKey carried in the event payload — no extra round trip, the
|
|
146
|
+
* channel is live within milliseconds of the POST /accounts response.
|
|
147
|
+
*
|
|
148
|
+
* Reconnect with the same exponential backoff scheme as per-account
|
|
149
|
+
* channels. If the API is older and doesn't expose /system/events
|
|
150
|
+
* (404), we log once and stop trying — polling-only fallback still
|
|
151
|
+
* works.
|
|
152
|
+
*/
|
|
153
|
+
private runSystemChannel;
|
|
154
|
+
/** Apply an account-lifecycle event from /system/events. */
|
|
155
|
+
private handleSystemEvent;
|
|
134
156
|
/** Watch one account's SSE stream forever; reconnect with backoff on drop. */
|
|
135
157
|
private runChannel;
|
|
136
158
|
/** Single SSE attach. Returns when the stream closes for any reason. */
|
package/dist/dispatcher.js
CHANGED
package/dist/http-routes.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createIntegrationRoutes
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import "./chunk-
|
|
5
|
-
import "./chunk-
|
|
6
|
-
import "./chunk-
|
|
3
|
+
} from "./chunk-XHDRGX46.js";
|
|
4
|
+
import "./chunk-V5LH4BNZ.js";
|
|
5
|
+
import "./chunk-VYBBCFP5.js";
|
|
6
|
+
import "./chunk-JVDPUO35.js";
|
|
7
7
|
import "./chunk-US5FT2UB.js";
|
|
8
|
-
import "./chunk-
|
|
8
|
+
import "./chunk-M5HV2M67.js";
|
|
9
9
|
export {
|
|
10
10
|
createIntegrationRoutes
|
|
11
11
|
};
|
package/dist/index.js
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Dispatcher,
|
|
3
3
|
loadPersonaForAgent
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-5HUEJNT5.js";
|
|
5
5
|
import {
|
|
6
6
|
createIntegrationRoutes
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-XHDRGX46.js";
|
|
8
8
|
import {
|
|
9
9
|
install
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-V5LH4BNZ.js";
|
|
11
11
|
import {
|
|
12
12
|
status
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-VYBBCFP5.js";
|
|
14
14
|
import {
|
|
15
15
|
uninstall
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-JVDPUO35.js";
|
|
17
17
|
import "./chunk-US5FT2UB.js";
|
|
18
18
|
import {
|
|
19
19
|
AgenticMailApiError,
|
|
@@ -26,7 +26,7 @@ import {
|
|
|
26
26
|
renderPersonaBody,
|
|
27
27
|
renderSubagentMarkdown,
|
|
28
28
|
resolveConfig
|
|
29
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-M5HV2M67.js";
|
|
30
30
|
export {
|
|
31
31
|
AgenticMailApiError,
|
|
32
32
|
Dispatcher,
|
package/dist/install.js
CHANGED
package/dist/status.js
CHANGED
package/dist/uninstall.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.8",
|
|
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",
|