agenthub-multiagent-mcp 1.72.0 → 1.74.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.
- package/dist/brain/memvidBrain.d.ts.map +1 -1
- package/dist/brain/memvidBrain.js +22 -3
- package/dist/brain/memvidBrain.js.map +1 -1
- package/dist/brain/nativeShadow.d.ts +22 -0
- package/dist/brain/nativeShadow.d.ts.map +1 -0
- package/dist/brain/nativeShadow.js +56 -0
- package/dist/brain/nativeShadow.js.map +1 -0
- package/dist/brain/nativeShadow.test.d.ts +2 -0
- package/dist/brain/nativeShadow.test.d.ts.map +1 -0
- package/dist/brain/nativeShadow.test.js +54 -0
- package/dist/brain/nativeShadow.test.js.map +1 -0
- package/dist/client.d.ts +7 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +11 -0
- package/dist/client.js.map +1 -1
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -1
- package/dist/npxRetired.d.ts +27 -0
- package/dist/npxRetired.d.ts.map +1 -0
- package/dist/npxRetired.js +74 -0
- package/dist/npxRetired.js.map +1 -0
- package/dist/npxRetired.test.d.ts +2 -0
- package/dist/npxRetired.test.d.ts.map +1 -0
- package/dist/npxRetired.test.js +66 -0
- package/dist/npxRetired.test.js.map +1 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +7 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/zohoSendOutcome.d.ts +13 -0
- package/dist/zohoSendOutcome.d.ts.map +1 -0
- package/dist/zohoSendOutcome.js +37 -0
- package/dist/zohoSendOutcome.js.map +1 -0
- package/dist/zohoSendOutcome.test.d.ts +2 -0
- package/dist/zohoSendOutcome.test.d.ts.map +1 -0
- package/dist/zohoSendOutcome.test.js +58 -0
- package/dist/zohoSendOutcome.test.js.map +1 -0
- package/package.json +1 -1
- package/skills/catalog.json +4 -2
- package/skills/manifest.json +2 -1
- package/skills/skills/zoho-mail/SKILL.md +2 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* True when the call may have been carried out although it did not succeed:
|
|
3
|
+
* the server said so (`zoho_outcome_unknown`), something in front of the server
|
|
4
|
+
* answered instead of AgentHub (a 502/503/504 with no AgentHub error code), or
|
|
5
|
+
* no answer arrived at all (network error, client timeout).
|
|
6
|
+
*
|
|
7
|
+
* AgentHub's own coded errors are definite answers and pass through, including
|
|
8
|
+
* its coded 502s (`reply_recipients_unavailable`, `zoho_error`) and `504
|
|
9
|
+
* zoho_timeout`, which means nothing was saved.
|
|
10
|
+
*/
|
|
11
|
+
export declare function isUnknownSendOutcome(err: unknown): boolean;
|
|
12
|
+
export declare function unknownSendOutcomeError(mailbox: string, mode: "draft" | "send", cause: unknown): Error;
|
|
13
|
+
//# sourceMappingURL=zohoSendOutcome.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zohoSendOutcome.d.ts","sourceRoot":"","sources":["../src/zohoSendOutcome.ts"],"names":[],"mappings":"AAYA;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAQ1D;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,KAAK,CAQtG"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// fix-zoho-send-write-deadline (AGHUB-2108) — a zoho_send_email call whose
|
|
2
|
+
// answer was lost.
|
|
3
|
+
//
|
|
4
|
+
// On 2026-10-30 the server saved a 9-attachment draft and the caller got
|
|
5
|
+
// nginx's 502: the answer was lost, not the work. Reporting that as a plain
|
|
6
|
+
// failure invites a retry, which saves a second draft or, with mode=send, sends
|
|
7
|
+
// the email twice. When the outcome is unknown, say so.
|
|
8
|
+
import { AgentHubApiError } from "./client.js";
|
|
9
|
+
const GATEWAY_STATUSES = new Set([502, 503, 504]);
|
|
10
|
+
/**
|
|
11
|
+
* True when the call may have been carried out although it did not succeed:
|
|
12
|
+
* the server said so (`zoho_outcome_unknown`), something in front of the server
|
|
13
|
+
* answered instead of AgentHub (a 502/503/504 with no AgentHub error code), or
|
|
14
|
+
* no answer arrived at all (network error, client timeout).
|
|
15
|
+
*
|
|
16
|
+
* AgentHub's own coded errors are definite answers and pass through, including
|
|
17
|
+
* its coded 502s (`reply_recipients_unavailable`, `zoho_error`) and `504
|
|
18
|
+
* zoho_timeout`, which means nothing was saved.
|
|
19
|
+
*/
|
|
20
|
+
export function isUnknownSendOutcome(err) {
|
|
21
|
+
if (err instanceof AgentHubApiError) {
|
|
22
|
+
if (err.code === "zoho_outcome_unknown")
|
|
23
|
+
return true;
|
|
24
|
+
return err.code === "" && GATEWAY_STATUSES.has(err.status);
|
|
25
|
+
}
|
|
26
|
+
// Anything else thrown by the request is a transport failure or timeout:
|
|
27
|
+
// the server may have received and run the call.
|
|
28
|
+
return err instanceof Error;
|
|
29
|
+
}
|
|
30
|
+
export function unknownSendOutcomeError(mailbox, mode, cause) {
|
|
31
|
+
const what = mode === "send" ? "the email may have been sent" : "the draft may have been saved";
|
|
32
|
+
const detail = cause instanceof Error ? cause.message : String(cause);
|
|
33
|
+
return new Error(`Outcome unknown: no answer reached this call, so ${what} in ${mailbox}. ` +
|
|
34
|
+
`Check its Drafts and Sent folders (zoho_search on the subject) before retrying; ` +
|
|
35
|
+
`retrying blindly can create a duplicate draft or send the email twice. (${detail})`);
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=zohoSendOutcome.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zohoSendOutcome.js","sourceRoot":"","sources":["../src/zohoSendOutcome.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,mBAAmB;AACnB,EAAE;AACF,yEAAyE;AACzE,4EAA4E;AAC5E,gFAAgF;AAChF,wDAAwD;AAExD,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE/C,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;AAElD;;;;;;;;;GASG;AACH,MAAM,UAAU,oBAAoB,CAAC,GAAY;IAC/C,IAAI,GAAG,YAAY,gBAAgB,EAAE,CAAC;QACpC,IAAI,GAAG,CAAC,IAAI,KAAK,sBAAsB;YAAE,OAAO,IAAI,CAAC;QACrD,OAAO,GAAG,CAAC,IAAI,KAAK,EAAE,IAAI,gBAAgB,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC7D,CAAC;IACD,yEAAyE;IACzE,iDAAiD;IACjD,OAAO,GAAG,YAAY,KAAK,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,OAAe,EAAE,IAAsB,EAAE,KAAc;IAC7F,MAAM,IAAI,GAAG,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,8BAA8B,CAAC,CAAC,CAAC,+BAA+B,CAAC;IAChG,MAAM,MAAM,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACtE,OAAO,IAAI,KAAK,CACd,oDAAoD,IAAI,OAAO,OAAO,IAAI;QACxE,kFAAkF;QAClF,2EAA2E,MAAM,GAAG,CACvF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zohoSendOutcome.test.d.ts","sourceRoot":"","sources":["../src/zohoSendOutcome.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { describe, it, expect, afterEach } from "vitest";
|
|
2
|
+
import { AgentHubApiError, requestTimeoutMs, DEFAULT_TIMEOUT_MS, ZOHO_SEND_TIMEOUT_MS } from "./client.js";
|
|
3
|
+
import { isUnknownSendOutcome, unknownSendOutcomeError } from "./zohoSendOutcome.js";
|
|
4
|
+
// fix-zoho-send-write-deadline (AGHUB-2108). A zoho_send_email call whose
|
|
5
|
+
// answer was lost may have saved the draft or sent the email. Reporting it as a
|
|
6
|
+
// plain failure invites a retry that duplicates it.
|
|
7
|
+
afterEach(() => {
|
|
8
|
+
delete process.env.AGENTHUB_REQUEST_TIMEOUT_MS;
|
|
9
|
+
});
|
|
10
|
+
describe("isUnknownSendOutcome", () => {
|
|
11
|
+
it("treats the proxy's own 502/503/504 (no AgentHub code) as unknown", () => {
|
|
12
|
+
for (const status of [502, 503, 504]) {
|
|
13
|
+
const err = new AgentHubApiError(`HTTP ${status} from POST /zoho/send: non-JSON response: <html>`, status, "");
|
|
14
|
+
expect(isUnknownSendOutcome(err)).toBe(true);
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
it("treats the server's zoho_outcome_unknown as unknown", () => {
|
|
18
|
+
expect(isUnknownSendOutcome(new AgentHubApiError("Zoho did not answer", 504, "zoho_outcome_unknown"))).toBe(true);
|
|
19
|
+
});
|
|
20
|
+
it("treats a network error or client timeout as unknown", () => {
|
|
21
|
+
expect(isUnknownSendOutcome(new TypeError("fetch failed"))).toBe(true);
|
|
22
|
+
expect(isUnknownSendOutcome(new Error("POST /zoho/send timed out after 70000ms"))).toBe(true);
|
|
23
|
+
});
|
|
24
|
+
it("passes AgentHub's coded errors through", () => {
|
|
25
|
+
expect(isUnknownSendOutcome(new AgentHubApiError("x", 502, "reply_recipients_unavailable"))).toBe(false);
|
|
26
|
+
expect(isUnknownSendOutcome(new AgentHubApiError("x", 502, "zoho_error"))).toBe(false);
|
|
27
|
+
expect(isUnknownSendOutcome(new AgentHubApiError("x", 504, "zoho_timeout"))).toBe(false);
|
|
28
|
+
expect(isUnknownSendOutcome(new AgentHubApiError("x", 403, "recipient_not_allowed"))).toBe(false);
|
|
29
|
+
expect(isUnknownSendOutcome(new AgentHubApiError("x", 500, ""))).toBe(false);
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
describe("unknownSendOutcomeError", () => {
|
|
33
|
+
it("says what may have happened and to check before retrying", () => {
|
|
34
|
+
const draft = unknownSendOutcomeError("sumit@contetial.com", "draft", new Error("HTTP 502")).message;
|
|
35
|
+
expect(draft).toMatch(/outcome unknown/i);
|
|
36
|
+
expect(draft).toMatch(/may have been saved/);
|
|
37
|
+
expect(draft).toMatch(/Drafts and Sent/);
|
|
38
|
+
expect(draft).toMatch(/before retrying/);
|
|
39
|
+
expect(draft).toContain("HTTP 502");
|
|
40
|
+
const send = unknownSendOutcomeError("admin@contetial.com", "send", new Error("x")).message;
|
|
41
|
+
expect(send).toMatch(/may have been sent/);
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
describe("zoho send request timeout", () => {
|
|
45
|
+
it("outlasts the server's 55s send budget", () => {
|
|
46
|
+
expect(ZOHO_SEND_TIMEOUT_MS).toBeGreaterThan(55_000);
|
|
47
|
+
expect(requestTimeoutMs("/zoho/send")).toBe(ZOHO_SEND_TIMEOUT_MS);
|
|
48
|
+
});
|
|
49
|
+
it("is not lowered by a smaller general override", () => {
|
|
50
|
+
process.env.AGENTHUB_REQUEST_TIMEOUT_MS = "20000";
|
|
51
|
+
expect(requestTimeoutMs("/zoho/send")).toBe(ZOHO_SEND_TIMEOUT_MS);
|
|
52
|
+
expect(requestTimeoutMs("/messages")).toBe(20_000);
|
|
53
|
+
});
|
|
54
|
+
it("leaves other paths on the default", () => {
|
|
55
|
+
expect(requestTimeoutMs("/zoho/messages")).toBe(DEFAULT_TIMEOUT_MS);
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
//# sourceMappingURL=zohoSendOutcome.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zohoSendOutcome.test.js","sourceRoot":"","sources":["../src/zohoSendOutcome.test.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/skills/catalog.json
CHANGED
|
@@ -92,8 +92,10 @@
|
|
|
92
92
|
"name": "zoho-mail",
|
|
93
93
|
"description": "Read and reply to email in a registered Zoho mailbox: find the message, read its attachments, and save a threaded Reply-All draft with files attached, then verify what was saved. Written after a 2026-10-30 bid draft lost its attachments, cc and thread.",
|
|
94
94
|
"category": "skill",
|
|
95
|
-
"current_hash": "
|
|
96
|
-
"prior_hashes": [
|
|
95
|
+
"current_hash": "972be83d5d7ae1dcb6434ba7802cdee941d4e7bd9c45add0ca16a5a6b533c2c1",
|
|
96
|
+
"prior_hashes": [
|
|
97
|
+
"017cd03e191c847ade9b21fa356faf3bbe96515942f1580360394820dc29af55"
|
|
98
|
+
]
|
|
97
99
|
}
|
|
98
100
|
]
|
|
99
101
|
}
|
package/skills/manifest.json
CHANGED
|
@@ -56,7 +56,8 @@
|
|
|
56
56
|
},
|
|
57
57
|
"skills/zoho-mail/SKILL.md": {
|
|
58
58
|
"hashes": [
|
|
59
|
-
"017cd03e191c847ade9b21fa356faf3bbe96515942f1580360394820dc29af55"
|
|
59
|
+
"017cd03e191c847ade9b21fa356faf3bbe96515942f1580360394820dc29af55",
|
|
60
|
+
"972be83d5d7ae1dcb6434ba7802cdee941d4e7bd9c45add0ca16a5a6b533c2c1"
|
|
60
61
|
]
|
|
61
62
|
}
|
|
62
63
|
}
|
|
@@ -110,5 +110,7 @@ its id; the human deletes it in Zoho web so it is never sent by mistake.
|
|
|
110
110
|
| `502 reply_recipients_unavailable` | Zoho did not return the original's headers for Reply-All | Retry once; otherwise pass `to`/`cc` explicitly from `zoho_read_message` |
|
|
111
111
|
| `422 reply_draft_unsupported` | Zoho did not confirm the reply was saved as a draft | Stop and report; do not retry as `send` |
|
|
112
112
|
| `429 send_cap_exceeded` | Daily send cap reached | Stop; tell your human |
|
|
113
|
+
| `Outcome unknown: …` (also `504 zoho_outcome_unknown`, a bare gateway 502/504, a timeout) | The answer was lost: the draft **may have been saved**, or with `mode=send` the email **may have been sent** | **Do not retry yet.** `zoho_search` the subject in Drafts and Sent; retry only if it is in neither. Report what you found |
|
|
114
|
+
| `504 zoho_timeout` | Zoho did not answer an attachment upload; nothing was saved or sent | Retry once; then send fewer or smaller files |
|
|
113
115
|
|
|
114
116
|
Full reference: `zoho-mail-connector-guide`.
|