@ateam-ai/mcp 0.3.35 → 0.3.37
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/package.json +1 -1
- package/src/api.js +7 -1
- package/src/tools.js +48 -10
package/package.json
CHANGED
package/src/api.js
CHANGED
|
@@ -384,7 +384,13 @@ function formatError(method, path, status, body) {
|
|
|
384
384
|
*/
|
|
385
385
|
async function request(method, path, body, sessionId, opts = {}) {
|
|
386
386
|
const timeoutMs = opts.timeoutMs || REQUEST_TIMEOUT_MS;
|
|
387
|
-
|
|
387
|
+
// Default to 2 retries on transient proxy errors (502/504). Existing
|
|
388
|
+
// gate further down only retries on those status codes — real errors
|
|
389
|
+
// (4xx, 5xx other than 502/504) still fail fast on attempt 0. Bumping
|
|
390
|
+
// the default from 0 → 2 protects every wrapper call against a
|
|
391
|
+
// skill-builder mid-restart 502 (bug #6 in parallel-agent feedback)
|
|
392
|
+
// without callers having to remember to pass retries everywhere.
|
|
393
|
+
const maxRetries = opts.retries ?? 2;
|
|
388
394
|
const baseUrl = getBaseUrl(sessionId);
|
|
389
395
|
|
|
390
396
|
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
package/src/tools.js
CHANGED
|
@@ -54,6 +54,28 @@ async function pollDeployJob(jobId, sid, { label = 'deploy', maxMs = 15 * 60_000
|
|
|
54
54
|
};
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
+
// ─── Dotted-field resolver ─────────────────────────────────────────
|
|
58
|
+
//
|
|
59
|
+
// Given an object and a dotted field name, walk down the path creating
|
|
60
|
+
// missing intermediate objects, and return { parent, leaf } so the caller
|
|
61
|
+
// can mutate parent[leaf] directly. Used by ateam_patch's _push / _delete /
|
|
62
|
+
// _update mutators so they correctly traverse "intents.supported" instead
|
|
63
|
+
// of creating a top-level key with a literal dot in its name. (That bug
|
|
64
|
+
// silently corrupted skill.json with three different copies of the same
|
|
65
|
+
// field — see the bug report from the parallel agent.)
|
|
66
|
+
function _resolveDottedField(obj, dottedPath) {
|
|
67
|
+
const parts = dottedPath.split('.');
|
|
68
|
+
let parent = obj;
|
|
69
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
70
|
+
const k = parts[i];
|
|
71
|
+
if (!parent[k] || typeof parent[k] !== 'object' || Array.isArray(parent[k])) {
|
|
72
|
+
parent[k] = {};
|
|
73
|
+
}
|
|
74
|
+
parent = parent[k];
|
|
75
|
+
}
|
|
76
|
+
return { parent, leaf: parts[parts.length - 1] };
|
|
77
|
+
}
|
|
78
|
+
|
|
57
79
|
// ─── Tool definitions ───────────────────────────────────────────────
|
|
58
80
|
|
|
59
81
|
export const tools = [
|
|
@@ -1897,24 +1919,40 @@ const handlers = {
|
|
|
1897
1919
|
const existing = typeof patched.role.persona === "string" ? patched.role.persona : "";
|
|
1898
1920
|
const sep = (!existing || /\s$/.test(existing)) ? "" : "\n\n";
|
|
1899
1921
|
patched.role.persona = existing + sep + value;
|
|
1900
|
-
} else if (key.endsWith("_push")
|
|
1901
|
-
// Array push: tools_push,
|
|
1922
|
+
} else if (key.endsWith("_push")) {
|
|
1923
|
+
// Array push: tools_push, intents.supported_push, etc.
|
|
1924
|
+
// BUG FIX: previously did `patched[field] = ...` which created a
|
|
1925
|
+
// top-level key with a literal dot (e.g. patched["intents.supported"])
|
|
1926
|
+
// instead of pushing into patched.intents.supported. Traverse the
|
|
1927
|
+
// dotted path correctly. Also enforce array-only values — was silently
|
|
1928
|
+
// falling through to the dot-notation branch when given a single
|
|
1929
|
+
// object, leaving a stray "<field>_push" sibling key behind.
|
|
1930
|
+
if (!Array.isArray(value)) {
|
|
1931
|
+
return { ok: false, phase: "patch", error: `${key} requires an array value (got ${typeof value}). Wrap the item in [] — e.g. {"${key}": [{...}]}.` };
|
|
1932
|
+
}
|
|
1902
1933
|
const field = key.replace(/_push$/, "");
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1934
|
+
const { parent, leaf } = _resolveDottedField(patched, field);
|
|
1935
|
+
parent[leaf] = [...(Array.isArray(parent[leaf]) ? parent[leaf] : []), ...value];
|
|
1936
|
+
} else if (key.endsWith("_delete")) {
|
|
1937
|
+
if (!Array.isArray(value)) {
|
|
1938
|
+
return { ok: false, phase: "patch", error: `${key} requires an array of names/ids (got ${typeof value}). Pass {"${key}": ["name1", "name2"]}.` };
|
|
1939
|
+
}
|
|
1906
1940
|
const field = key.replace(/_delete$/, "");
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1941
|
+
const { parent, leaf } = _resolveDottedField(patched, field);
|
|
1942
|
+
parent[leaf] = (Array.isArray(parent[leaf]) ? parent[leaf] : []).filter(item => !value.includes(item?.name || item?.id || item));
|
|
1943
|
+
} else if (key.endsWith("_update")) {
|
|
1944
|
+
if (!Array.isArray(value)) {
|
|
1945
|
+
return { ok: false, phase: "patch", error: `${key} requires an array of update objects (got ${typeof value}). Pass {"${key}": [{name: "x", description: "..."}]}.` };
|
|
1946
|
+
}
|
|
1910
1947
|
const field = key.replace(/_update$/, "");
|
|
1911
|
-
const
|
|
1948
|
+
const { parent, leaf } = _resolveDottedField(patched, field);
|
|
1949
|
+
const arr = Array.isArray(parent[leaf]) ? parent[leaf] : [];
|
|
1912
1950
|
for (const upd of value) {
|
|
1913
1951
|
const idx = arr.findIndex(item => (item.name || item.id) === (upd.name || upd.id));
|
|
1914
1952
|
if (idx >= 0) arr[idx] = { ...arr[idx], ...upd };
|
|
1915
1953
|
else arr.push(upd);
|
|
1916
1954
|
}
|
|
1917
|
-
|
|
1955
|
+
parent[leaf] = arr;
|
|
1918
1956
|
} else if (key.includes(".")) {
|
|
1919
1957
|
// Dot notation: "role.persona", "intents.thresholds.accept"
|
|
1920
1958
|
const parts = key.split(".");
|