@agenticmail/claudecode 0.1.5 → 0.1.6
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-3ULRGCUI.js → chunk-5M43V6CB.js} +75 -8
- package/dist/{chunk-OZPRB336.js → chunk-N43A7EQB.js} +4 -4
- package/dist/{chunk-UZZNLWBR.js → chunk-UC63VEBP.js} +1 -1
- package/dist/{chunk-4JURQ6QD.js → chunk-WP2ELPRM.js} +1 -1
- package/dist/{chunk-5S377IWV.js → chunk-XGBVWZ3M.js} +1 -1
- package/dist/{chunk-W2R3GH54.js → chunk-YWSO3QOQ.js} +19 -6
- package/dist/cli.js +4 -4
- package/dist/dispatcher-bin.js +2 -2
- package/dist/dispatcher.d.ts +18 -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-YWSO3QOQ.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 = 5e3;
|
|
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;
|
|
@@ -94,6 +94,7 @@ async function runWorker(query, persona, userPrompt, agent, mcpServerName, mcpCo
|
|
|
94
94
|
`mcp__${mcpServerName}__list_agents`,
|
|
95
95
|
`mcp__${mcpServerName}__message_agent`,
|
|
96
96
|
`mcp__${mcpServerName}__call_agent`,
|
|
97
|
+
`mcp__${mcpServerName}__wait_for_email`,
|
|
97
98
|
`mcp__${mcpServerName}__check_tasks`,
|
|
98
99
|
`mcp__${mcpServerName}__claim_task`,
|
|
99
100
|
`mcp__${mcpServerName}__submit_result`,
|
|
@@ -143,13 +144,55 @@ function newMailPrompt(agent, event) {
|
|
|
143
144
|
`- Subject: ${subject}`,
|
|
144
145
|
uid ? `- UID: ${uid}` : "",
|
|
145
146
|
``,
|
|
146
|
-
|
|
147
|
-
` - if it's a question or request \u2192 reply with reply_email`,
|
|
148
|
-
` - if it requires research \u2192 use call_agent to ask the right teammate, then reply`,
|
|
149
|
-
` - if it's an FYI \u2192 archive (mark_read) and move on`,
|
|
150
|
-
` - if it's spam-looking \u2192 trust the auto-spam-filter; only intervene if it slipped through`,
|
|
147
|
+
`## Thread-aware coordination protocol`,
|
|
151
148
|
``,
|
|
152
|
-
`
|
|
149
|
+
`You are ${agent.name}. Multiple agents may be CC'd on the same thread \u2014`,
|
|
150
|
+
`that is intentional: a thread is the shared workspace, and turn-taking is`,
|
|
151
|
+
`implicit from context (who was addressed last, whose stage of the workflow`,
|
|
152
|
+
`is next, who was @mentioned). Follow these steps in order:`,
|
|
153
|
+
``,
|
|
154
|
+
`1. **Read this message.** read_email({ uid: ${uid ?? "<uid>"}, _account: "${agent.name}" }).`,
|
|
155
|
+
``,
|
|
156
|
+
`2. **If this is a reply (Subject starts with "Re:" or an In-Reply-To header is present), load the rest of the thread.**`,
|
|
157
|
+
` Use search_emails({ subject: "<core subject without Re:>", _account: "${agent.name}" })`,
|
|
158
|
+
` to surface earlier messages in the thread, then read_email each prior UID.`,
|
|
159
|
+
` You MUST read the full thread before deciding what to do.`,
|
|
160
|
+
``,
|
|
161
|
+
`3. **Identify the participants.** Look at To + CC across the thread. Those`,
|
|
162
|
+
` are your collaborators. Their names map to AgenticMail agents at`,
|
|
163
|
+
` <name>@localhost. They will each be woken on every reply-all the same way you were.`,
|
|
164
|
+
``,
|
|
165
|
+
`4. **Decide: is it MY turn?** Yes if any of:`,
|
|
166
|
+
` - The latest message addresses you by name ("Vesper, please \u2026", "@${agent.name} \u2026").`,
|
|
167
|
+
` - The previous-stage handoff is to your role (e.g. designer \u2192 developer, and you are the developer).`,
|
|
168
|
+
` - You were directly asked a question and nobody has answered yet.`,
|
|
169
|
+
` No if:`,
|
|
170
|
+
` - The current ask is targeted at a teammate (their turn, not yours).`,
|
|
171
|
+
` - You have nothing substantive to add right now.`,
|
|
172
|
+
` When in doubt, stay silent \u2014 over-replying creates noise. Better to let`,
|
|
173
|
+
` the right teammate take the turn than to step on theirs.`,
|
|
174
|
+
``,
|
|
175
|
+
`5. **If it's your turn \u2014 reply-all so the whole thread sees it.**`,
|
|
176
|
+
` reply_email({ uid: ${uid ?? "<uid>"}, replyAll: true, text: "...", _account: "${agent.name}" })`,
|
|
177
|
+
` Sign with your name. Be substantive but concise. If you are handing off`,
|
|
178
|
+
` to the next teammate, name them explicitly in your reply ("Orion \u2014 over to you, please \u2026").`,
|
|
179
|
+
``,
|
|
180
|
+
`6. **If you need additional help from a teammate not yet on the thread,**`,
|
|
181
|
+
` include them by CC'ing in your reply-all \u2014 DO NOT spin up a separate`,
|
|
182
|
+
` call_agent / message_agent side-channel. The thread is the workspace;`,
|
|
183
|
+
` everyone stays in context.`,
|
|
184
|
+
``,
|
|
185
|
+
`7. **If it's NOT your turn,** mark the message read with mark_read and return.`,
|
|
186
|
+
` Do not reply just to acknowledge. Silence IS a valid contribution.`,
|
|
187
|
+
``,
|
|
188
|
+
`When you finish, return a one-line summary of what you did:`,
|
|
189
|
+
` "Contributed: <one-line description>" OR "Stayed silent \u2014 not my turn."`,
|
|
190
|
+
``,
|
|
191
|
+
`## Fallback for non-thread mail`,
|
|
192
|
+
``,
|
|
193
|
+
`If this is a fresh standalone email (not part of a thread, only addressed`,
|
|
194
|
+
`to you), handle it directly: answer the question, do the work, reply.`,
|
|
195
|
+
`Spam: trust the auto-filter unless something obviously slipped through.`
|
|
153
196
|
].filter(Boolean).join("\n");
|
|
154
197
|
}
|
|
155
198
|
function taskPrompt(agent, event) {
|
|
@@ -248,6 +291,29 @@ var Dispatcher = class {
|
|
|
248
291
|
return;
|
|
249
292
|
}
|
|
250
293
|
}
|
|
294
|
+
/**
|
|
295
|
+
* Should the dispatcher own a wake-channel for this account?
|
|
296
|
+
*
|
|
297
|
+
* We skip the bridge agent (default name "claudecode"). The bridge is
|
|
298
|
+
* the host session's own inbox proxy — when mail lands there, the
|
|
299
|
+
* HOST Claude Code session reads it via MCP (`list_inbox` /
|
|
300
|
+
* `wait_for_email` / `read_email`), NOT via a separately-spawned
|
|
301
|
+
* dispatcher worker. Spawning a worker for the bridge would:
|
|
302
|
+
* 1. Compete with the host (two Claude instances trying to "be"
|
|
303
|
+
* Claude Code, both potentially replying autonomously).
|
|
304
|
+
* 2. Waste tokens — the host is already aware via its MCP polling.
|
|
305
|
+
* 3. Send the bridge into an autonomous loop if it ever replies-all
|
|
306
|
+
* (because that mail would wake it again, ad infinitum).
|
|
307
|
+
*
|
|
308
|
+
* Role="bridge" is also skipped for symmetry with selectExposableAgents
|
|
309
|
+
* in install.ts — anything tagged as a bridge is host-managed.
|
|
310
|
+
*/
|
|
311
|
+
shouldWatch(account) {
|
|
312
|
+
const bridgeName = this.cfg.bridgeAgentName.toLowerCase();
|
|
313
|
+
if (account.name.toLowerCase() === bridgeName) return false;
|
|
314
|
+
if (account.role === "bridge") return false;
|
|
315
|
+
return true;
|
|
316
|
+
}
|
|
251
317
|
/** Re-fetch /accounts; open SSE for new ones, close for vanished ones. */
|
|
252
318
|
async syncAccounts() {
|
|
253
319
|
let accounts;
|
|
@@ -257,6 +323,7 @@ var Dispatcher = class {
|
|
|
257
323
|
this.log("warn", `[dispatcher] could not list accounts: ${err.message}`);
|
|
258
324
|
return;
|
|
259
325
|
}
|
|
326
|
+
accounts = accounts.filter((a) => this.shouldWatch(a));
|
|
260
327
|
const liveIds = new Set(accounts.map((a) => a.id));
|
|
261
328
|
for (const [id, ch] of this.channels) {
|
|
262
329
|
if (!liveIds.has(id)) {
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
install
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-WP2ELPRM.js";
|
|
4
4
|
import {
|
|
5
5
|
status
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-UC63VEBP.js";
|
|
7
7
|
import {
|
|
8
8
|
uninstall
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-XGBVWZ3M.js";
|
|
10
10
|
import {
|
|
11
11
|
AgenticMailApiError
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-YWSO3QOQ.js";
|
|
13
13
|
|
|
14
14
|
// src/http-routes.ts
|
|
15
15
|
import { Router } from "express";
|
|
@@ -130,12 +130,16 @@ var ESSENTIAL_TOOL_NAMES = [
|
|
|
130
130
|
"search_emails",
|
|
131
131
|
"list_agents",
|
|
132
132
|
"message_agent",
|
|
133
|
-
// call_agent is the
|
|
134
|
-
//
|
|
135
|
-
//
|
|
136
|
-
// call request_tools just to discover it would be a usability disaster
|
|
137
|
-
// for the most common coordination pattern.
|
|
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.
|
|
138
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",
|
|
139
143
|
"check_tasks",
|
|
140
144
|
// Meta-tools — these unlock the other ~50 tools on demand.
|
|
141
145
|
"request_tools",
|
|
@@ -201,7 +205,16 @@ function renderPersonaBody(input) {
|
|
|
201
205
|
`${tool("whoami")}({ _account: "${agent.name}" })`,
|
|
202
206
|
"```",
|
|
203
207
|
"",
|
|
204
|
-
`**Coordination
|
|
208
|
+
`**Coordination \u2014 the thread is the workspace.** When you wake on new mail and it's part of a thread (Subject starts with "Re:" or an In-Reply-To header is present):`,
|
|
209
|
+
"",
|
|
210
|
+
` 1. Read the new message with \`${tool("read_email")}\`.`,
|
|
211
|
+
` 2. Load the rest of the thread with \`${tool("search_emails")}({ subject: "<core subject>", _account: "${agent.name}" })\` and read each prior message. You MUST have full thread context before acting.`,
|
|
212
|
+
` 3. Look at To + CC across the thread \u2014 those are your teammates. They will each be woken on every reply-all just like you were.`,
|
|
213
|
+
` 4. Decide if it's YOUR turn: are you addressed by name? Is the previous-stage handoff to your role? Is a question pending for you? When in doubt, stay silent \u2014 over-replying creates noise.`,
|
|
214
|
+
` 5. If yes: \`${tool("reply_email")}({ uid, replyAll: true, text: "...", _account: "${agent.name}" })\`. Sign with your name. If you're handing off, name the next teammate explicitly ("Orion \u2014 over to you, please \u2026"). To bring a new teammate in, just add them to CC.`,
|
|
215
|
+
` 6. If no: \`mark_read\` and return. Silence IS a valid contribution.`,
|
|
216
|
+
"",
|
|
217
|
+
`**When to use \`${tool("call_agent")}\` instead:** only when you need ONE structured answer from ONE teammate, inline in your current turn \u2014 e.g. "give me a JSON list of X". For multi-step / multi-agent work, the thread pattern above is the right primitive.`,
|
|
205
218
|
"",
|
|
206
219
|
`On-demand (via invoke) examples \u2014 anything NOT in the pre-loaded list:`,
|
|
207
220
|
"",
|
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-WP2ELPRM.js";
|
|
5
5
|
import {
|
|
6
6
|
status
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-UC63VEBP.js";
|
|
8
8
|
import {
|
|
9
9
|
uninstall
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-XGBVWZ3M.js";
|
|
11
11
|
import "./chunk-US5FT2UB.js";
|
|
12
12
|
import {
|
|
13
13
|
AgenticMailApiError
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-YWSO3QOQ.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
|
@@ -111,6 +111,24 @@ declare class Dispatcher {
|
|
|
111
111
|
stop(): Promise<void>;
|
|
112
112
|
/** Public for tests — directly hand an event to the routing path. */
|
|
113
113
|
handleEvent(account: AgenticMailAccount, event: SSEEvent): Promise<void>;
|
|
114
|
+
/**
|
|
115
|
+
* Should the dispatcher own a wake-channel for this account?
|
|
116
|
+
*
|
|
117
|
+
* We skip the bridge agent (default name "claudecode"). The bridge is
|
|
118
|
+
* the host session's own inbox proxy — when mail lands there, the
|
|
119
|
+
* HOST Claude Code session reads it via MCP (`list_inbox` /
|
|
120
|
+
* `wait_for_email` / `read_email`), NOT via a separately-spawned
|
|
121
|
+
* dispatcher worker. Spawning a worker for the bridge would:
|
|
122
|
+
* 1. Compete with the host (two Claude instances trying to "be"
|
|
123
|
+
* Claude Code, both potentially replying autonomously).
|
|
124
|
+
* 2. Waste tokens — the host is already aware via its MCP polling.
|
|
125
|
+
* 3. Send the bridge into an autonomous loop if it ever replies-all
|
|
126
|
+
* (because that mail would wake it again, ad infinitum).
|
|
127
|
+
*
|
|
128
|
+
* Role="bridge" is also skipped for symmetry with selectExposableAgents
|
|
129
|
+
* in install.ts — anything tagged as a bridge is host-managed.
|
|
130
|
+
*/
|
|
131
|
+
private shouldWatch;
|
|
114
132
|
/** Re-fetch /accounts; open SSE for new ones, close for vanished ones. */
|
|
115
133
|
private syncAccounts;
|
|
116
134
|
/** Watch one account's SSE stream forever; reconnect with backoff on drop. */
|
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-N43A7EQB.js";
|
|
4
|
+
import "./chunk-WP2ELPRM.js";
|
|
5
|
+
import "./chunk-UC63VEBP.js";
|
|
6
|
+
import "./chunk-XGBVWZ3M.js";
|
|
7
7
|
import "./chunk-US5FT2UB.js";
|
|
8
|
-
import "./chunk-
|
|
8
|
+
import "./chunk-YWSO3QOQ.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-5M43V6CB.js";
|
|
5
5
|
import {
|
|
6
6
|
createIntegrationRoutes
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-N43A7EQB.js";
|
|
8
8
|
import {
|
|
9
9
|
install
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-WP2ELPRM.js";
|
|
11
11
|
import {
|
|
12
12
|
status
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-UC63VEBP.js";
|
|
14
14
|
import {
|
|
15
15
|
uninstall
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-XGBVWZ3M.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-YWSO3QOQ.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.6",
|
|
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",
|