@ateam-ai/mcp 0.3.13 → 0.3.15

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/tools.js +69 -37
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ateam-ai/mcp",
3
- "version": "0.3.13",
3
+ "version": "0.3.15",
4
4
  "mcpName": "io.github.ariekogan/ateam-mcp",
5
5
  "description": "A-Team MCP Server — build, validate, and deploy multi-agent solutions from any AI environment",
6
6
  "type": "module",
package/src/tools.js CHANGED
@@ -1659,29 +1659,77 @@ const handlers = {
1659
1659
  ateam_patch: async ({ solution_id, target, skill_id, updates, test_message }, sid) => {
1660
1660
  const phases = [];
1661
1661
 
1662
- // Phase 1: Apply PATCH
1663
- let patchResult;
1662
+ // GitHub-first patch: read from GitHub → apply patch → write back → redeploy
1663
+ // This ensures GitHub stays the single source of truth.
1664
+
1665
+ // Phase 1: Read current state from GitHub
1666
+ let current;
1667
+ const filePath = target === "skill" && skill_id
1668
+ ? `skills/${skill_id}/skill.json`
1669
+ : `solution.json`;
1664
1670
  try {
1665
- if (target === "skill") {
1666
- patchResult = await patch(`/deploy/solutions/${solution_id}/skills/${skill_id}`, { updates }, sid);
1667
- } else {
1668
- patchResult = await patch(`/deploy/solutions/${solution_id}`, { state_update: updates }, sid);
1671
+ const readResult = await get(`/deploy/solutions/${solution_id}/github/read?path=${encodeURIComponent(filePath)}`, sid);
1672
+ current = JSON.parse(readResult.content);
1673
+ } catch (err) {
1674
+ return { ok: false, phase: "read", error: `Failed to read ${filePath} from GitHub: ${err.message}` };
1675
+ }
1676
+
1677
+ // Phase 2: Apply patch in memory
1678
+ let patched = { ...current };
1679
+ try {
1680
+ for (const [key, value] of Object.entries(updates || {})) {
1681
+ if (key.endsWith("_push") && Array.isArray(value)) {
1682
+ // Array push: tools_push, intents_push, etc.
1683
+ const field = key.replace(/_push$/, "");
1684
+ patched[field] = [...(patched[field] || []), ...value];
1685
+ } else if (key.endsWith("_delete") && Array.isArray(value)) {
1686
+ // Array delete by name
1687
+ const field = key.replace(/_delete$/, "");
1688
+ patched[field] = (patched[field] || []).filter(item => !value.includes(item.name || item.id || item));
1689
+ } else if (key.endsWith("_update") && Array.isArray(value)) {
1690
+ // Array update by name/id
1691
+ const field = key.replace(/_update$/, "");
1692
+ const arr = patched[field] || [];
1693
+ for (const upd of value) {
1694
+ const idx = arr.findIndex(item => (item.name || item.id) === (upd.name || upd.id));
1695
+ if (idx >= 0) arr[idx] = { ...arr[idx], ...upd };
1696
+ else arr.push(upd);
1697
+ }
1698
+ patched[field] = arr;
1699
+ } else if (key.includes(".")) {
1700
+ // Dot notation: "role.persona", "intents.thresholds.accept"
1701
+ const parts = key.split(".");
1702
+ let obj = patched;
1703
+ for (let i = 0; i < parts.length - 1; i++) {
1704
+ if (!obj[parts[i]] || typeof obj[parts[i]] !== "object") obj[parts[i]] = {};
1705
+ obj = obj[parts[i]];
1706
+ }
1707
+ obj[parts[parts.length - 1]] = value;
1708
+ } else {
1709
+ // Direct field replacement
1710
+ patched[key] = value;
1711
+ }
1669
1712
  }
1670
- phases.push({ phase: "update", status: "done" });
1713
+ phases.push({ phase: "patch", status: "done" });
1671
1714
  } catch (err) {
1672
- const notFound = /not found|404|ENOENT/i.test(err.message);
1673
- return {
1674
- ok: false,
1675
- phase: "update",
1676
- error: err.message,
1677
- message: "Patch failed. Check your updates payload format.",
1678
- ...(notFound && {
1679
- hint: "Skill not found in Builder storage. Use ateam_github_patch to edit the skill JSON directly on GitHub (path: skills/<skill-id>/skill.json), then ateam_redeploy(solution_id, skill_id) to deploy the updated skill.",
1680
- }),
1681
- };
1715
+ return { ok: false, phase: "patch", error: `Failed to apply patch: ${err.message}` };
1716
+ }
1717
+
1718
+ // Phase 3: Write patched version back to GitHub
1719
+ try {
1720
+ const patchKeys = Object.keys(updates || {});
1721
+ const message = `Patch: ${target}${skill_id ? ` ${skill_id}` : ""} — ${patchKeys.join(", ")}`;
1722
+ await post(`/deploy/solutions/${solution_id}/github/patch`, {
1723
+ path: filePath,
1724
+ content: JSON.stringify(patched, null, 2),
1725
+ message,
1726
+ }, sid, { timeoutMs: 30_000 });
1727
+ phases.push({ phase: "github_write", status: "done" });
1728
+ } catch (err) {
1729
+ return { ok: false, phase: "github_write", error: `Patch applied but failed to write to GitHub: ${err.message}`, phases };
1682
1730
  }
1683
1731
 
1684
- // Phase 2: Redeploy
1732
+ // Phase 4: Redeploy from GitHub
1685
1733
  let redeployResult;
1686
1734
  try {
1687
1735
  if (target === "skill" && skill_id) {
@@ -1695,9 +1743,8 @@ const handlers = {
1695
1743
  ok: false,
1696
1744
  phase: "redeploy",
1697
1745
  phases,
1698
- patch: patchResult,
1699
1746
  error: err.message,
1700
- message: "Update succeeded but redeploy failed. Try ateam_redeploy manually.",
1747
+ message: "Patch saved to GitHub but redeploy failed. Try ateam_redeploy manually.",
1701
1748
  };
1702
1749
  }
1703
1750
 
@@ -1720,30 +1767,15 @@ const handlers = {
1720
1767
  }
1721
1768
 
1722
1769
  // Phase 4: Auto-push to main branch (non-blocking)
1723
- let github_result;
1724
- try {
1725
- github_result = await post(
1726
- `/deploy/solutions/${solution_id}/github/push`,
1727
- { push_to_github: true, message: `Patch: ${target}${skill_id ? ` ${skill_id}` : ''} — ${Object.keys(updates || {}).join(', ')}` },
1728
- sid,
1729
- { timeoutMs: 60_000 },
1730
- );
1731
- phases.push({ phase: 'github', status: github_result.skipped ? 'skipped' : 'done' });
1732
- } catch (err) {
1733
- github_result = { error: err.message };
1734
- phases.push({ phase: 'github', status: 'error', error: err.message });
1735
- }
1736
-
1737
1770
  return {
1738
1771
  ok: true,
1739
1772
  solution_id,
1740
1773
  branch: 'main',
1741
1774
  phases,
1742
- patch: patchResult,
1775
+ patched: patched,
1743
1776
  redeploy: redeployResult,
1744
1777
  ...(test_result && { test_result }),
1745
- ...(github_result && !github_result.error && !github_result.skipped && { github: github_result }),
1746
- _status: '✅ Patched + redeployed + pushed to main.',
1778
+ _status: '✅ Patched on GitHub + redeployed.',
1747
1779
  _next: 'Create a checkpoint before making more changes: ateam_github_promote(solution_id)',
1748
1780
  };
1749
1781
  },