@ateam-ai/mcp 0.4.93 → 0.4.94
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/tools.js +89 -11
package/package.json
CHANGED
package/src/tools.js
CHANGED
|
@@ -1051,9 +1051,14 @@ export const tools = [
|
|
|
1051
1051
|
name: "ateam_delete_solution",
|
|
1052
1052
|
core: true,
|
|
1053
1053
|
description:
|
|
1054
|
-
"⚠️ IRREVERSIBLE —
|
|
1054
|
+
"⚠️ IRREVERSIBLE — THIS CLEARS THE WHOLE TENANT, not just the named solution. " +
|
|
1055
|
+
"TENANT === SOLUTION, so it wipes EVERY skill and connector in the tenant's Core registry, the solution record, " +
|
|
1056
|
+
"and Builder FS — INCLUDING any orphaned skill that no longer belongs to a solution. The name says 'solution'; the " +
|
|
1057
|
+
"blast radius is the tenant. Read the tenant's skill list first (ateam_get_solution view:'skills' or Core's registry) " +
|
|
1058
|
+
"and know what you are destroying — an orphan from an earlier solution is still in there and still goes. " +
|
|
1055
1059
|
"REQUIRES `confirm:true` AND `confirm_solution_id` echoing the solution id you're destroying (defeats typos and hallucinated ids). " +
|
|
1056
|
-
"RECOVERY:
|
|
1060
|
+
"RECOVERY: only what GitHub holds. `ateam_github_pull` rebuilds from `main` — anything never pushed there is GONE. " +
|
|
1061
|
+
"A skill authored FS-only, or orphaned before its solution was pushed, has no copy anywhere.",
|
|
1057
1062
|
inputSchema: {
|
|
1058
1063
|
type: "object",
|
|
1059
1064
|
properties: {
|
|
@@ -1067,10 +1072,17 @@ export const tools = [
|
|
|
1067
1072
|
},
|
|
1068
1073
|
confirm_solution_id: {
|
|
1069
1074
|
type: "string",
|
|
1070
|
-
description: "
|
|
1075
|
+
description: "Required with force:true. Must exactly equal `solution_id`. This defeats typos and hallucinated ids — you can't wipe a solution you couldn't spell.",
|
|
1076
|
+
},
|
|
1077
|
+
force: {
|
|
1078
|
+
type: "boolean",
|
|
1079
|
+
description:
|
|
1080
|
+
"Omit (DEFAULT) to PREVIEW: returns will_clear — every skill and connector that would be destroyed, with " +
|
|
1081
|
+
"orphan_skills called out separately — and clears NOTHING. Pass true only after reading that list. The " +
|
|
1082
|
+
"preview exists because a description cannot name the orphan you did not know was in the registry.",
|
|
1071
1083
|
},
|
|
1072
1084
|
},
|
|
1073
|
-
required: ["solution_id"
|
|
1085
|
+
required: ["solution_id"],
|
|
1074
1086
|
},
|
|
1075
1087
|
},
|
|
1076
1088
|
{
|
|
@@ -4693,8 +4705,36 @@ export const handlers = {
|
|
|
4693
4705
|
? ` ⚠️ Skill "${skill_id}" is INVALID (${validation.error_count ?? "?"} error(s)) — see validation (non-blocking; build_and_run will refuse until fixed).`
|
|
4694
4706
|
: "";
|
|
4695
4707
|
|
|
4708
|
+
// A PATCH THAT DID NOT REBUILD IS NOT A SUCCESSFUL PATCH.
|
|
4709
|
+
//
|
|
4710
|
+
// This returned ok:true whenever the write landed, even if the redeploy
|
|
4711
|
+
// failed or timed out, on the reasoning that the edit "is not lost". The
|
|
4712
|
+
// edit genuinely is not lost — but ok:true is not where that belongs.
|
|
4713
|
+
//
|
|
4714
|
+
// Changing skill.connectors[] makes the connector-derived half of tools[]
|
|
4715
|
+
// STALE, and only the redeploy rebuilds it. So a green patch with a failed
|
|
4716
|
+
// redeploy hands back exactly the state this whole fix exists to prevent: a
|
|
4717
|
+
// skill whose declarations say one thing and whose generated tools still
|
|
4718
|
+
// say another, reported as done. The caller stops, because it was told it
|
|
4719
|
+
// succeeded.
|
|
4720
|
+
//
|
|
4721
|
+
// ok now reflects the LIFECYCLE — update, rebuild, validate, redeploy —
|
|
4722
|
+
// and `patch_persisted` carries the "nothing was lost" fact as a field,
|
|
4723
|
+
// where a caller can act on it, instead of as a lie in the status.
|
|
4724
|
+
const lifecycleOk = redeployResult === undefined ? true : redeployOk;
|
|
4725
|
+
|
|
4696
4726
|
return {
|
|
4697
|
-
ok:
|
|
4727
|
+
ok: lifecycleOk,
|
|
4728
|
+
...(!lifecycleOk && {
|
|
4729
|
+
patch_persisted: true,
|
|
4730
|
+
phase: "redeploy",
|
|
4731
|
+
error:
|
|
4732
|
+
`The edit was saved to ${store} but the redeploy did not complete, so the skill's ` +
|
|
4733
|
+
`connector-derived tools were NOT rebuilt. Nothing is lost and nothing needs re-patching — ` +
|
|
4734
|
+
`the definition is stored. Finish it with ateam_redeploy(solution_id` +
|
|
4735
|
+
(skill_id ? `, skill_id: "${skill_id}"` : "") + `). Until then Builder and Core disagree ` +
|
|
4736
|
+
`about this skill's tools.`,
|
|
4737
|
+
}),
|
|
4698
4738
|
solution_id,
|
|
4699
4739
|
source: isLocal ? "local" : "github",
|
|
4700
4740
|
...(degradedToLocal && {
|
|
@@ -4729,7 +4769,7 @@ export const handlers = {
|
|
|
4729
4769
|
? (widget_health && !widget_health.ok
|
|
4730
4770
|
? `✅ Patched on ${store} + redeployed. ⚠️ ${widget_health.issues?.length || 0} widget(s) not rendering — see widget_health.`
|
|
4731
4771
|
: `✅ Patched on ${store} + redeployed.`)
|
|
4732
|
-
: `⚠️ Patched on ${store} ✅ but redeploy
|
|
4772
|
+
: `⚠️ Patched on ${store} ✅ but the redeploy did NOT complete, so connector-derived tools were not rebuilt — Builder and Core disagree until you run: ateam_redeploy(solution_id` + (skill_id ? `, skill_id: "${skill_id}"` : '') + ')') + validationStatus,
|
|
4733
4773
|
_next: isLocal
|
|
4734
4774
|
? 'Local edit saved + redeployed. When the tenant connects a GitHub repo, the local state is pushed → GitHub (which then becomes master).'
|
|
4735
4775
|
: 'Create a checkpoint before making more changes: ateam_github_promote(solution_id)',
|
|
@@ -5889,23 +5929,61 @@ export const handlers = {
|
|
|
5889
5929
|
ateam_github_list_versions: async ({ solution_id }, sid) =>
|
|
5890
5930
|
get(`/deploy/solutions/${solution_id}/versions/dev`, sid),
|
|
5891
5931
|
|
|
5892
|
-
|
|
5932
|
+
// SHOW BEFORE YOU DESTROY.
|
|
5933
|
+
//
|
|
5934
|
+
// Without force:true this RETURNS THE INVENTORY — every skill and connector
|
|
5935
|
+
// the clear would take — and touches nothing. Only force:true clears.
|
|
5936
|
+
//
|
|
5937
|
+
// A warning in a description is a claim the caller must take on trust, and it
|
|
5938
|
+
// cannot mention the ORPHAN nobody knew was in the registry. The inventory is
|
|
5939
|
+
// evidence: the caller reads the actual names first. On 2026-09-11 the absence
|
|
5940
|
+
// of that step cost `walk-guide` — destroyed while clearing an unrelated test
|
|
5941
|
+
// fixture, present in no GitHub branch, unrecoverable.
|
|
5942
|
+
//
|
|
5943
|
+
// confirm/confirm_solution_id still guard typos and hallucinated ids. They
|
|
5944
|
+
// answer "did you mean THIS tenant"; force answers "have you read what is in
|
|
5945
|
+
// it". Both are needed, and neither substitutes for the other.
|
|
5946
|
+
ateam_delete_solution: async ({ solution_id, confirm, confirm_solution_id, force }, sid) => {
|
|
5947
|
+
if (confirm_solution_id !== undefined && confirm_solution_id !== solution_id) {
|
|
5948
|
+
return {
|
|
5949
|
+
ok: false,
|
|
5950
|
+
error: `⚠️ REFUSED: confirm_solution_id must exactly equal solution_id. Got confirm_solution_id="${confirm_solution_id}" but solution_id="${solution_id}". This check defeats typos and hallucinated ids — you should not be able to wipe a solution whose id you can't spell correctly.`,
|
|
5951
|
+
expected: solution_id,
|
|
5952
|
+
received: confirm_solution_id,
|
|
5953
|
+
};
|
|
5954
|
+
}
|
|
5955
|
+
|
|
5956
|
+
// Preview: no confirm needed to LOOK, and looking is the default.
|
|
5957
|
+
if (force !== true) {
|
|
5958
|
+
const preview = await del(`/deploy/solutions/${solution_id}`, sid);
|
|
5959
|
+
return {
|
|
5960
|
+
...preview,
|
|
5961
|
+
_next:
|
|
5962
|
+
"Nothing was cleared. Read will_clear above — especially orphan_skills, which belong to no solution and " +
|
|
5963
|
+
"are the ones most likely to be unrecoverable. To proceed: ateam_delete_solution(solution_id, " +
|
|
5964
|
+
`confirm:true, confirm_solution_id:"${solution_id}", force:true)`,
|
|
5965
|
+
};
|
|
5966
|
+
}
|
|
5967
|
+
|
|
5893
5968
|
if (confirm !== true) {
|
|
5894
5969
|
return {
|
|
5895
5970
|
ok: false,
|
|
5896
|
-
error:
|
|
5897
|
-
|
|
5971
|
+
error:
|
|
5972
|
+
"⚠️ REFUSED: force:true also requires confirm:true. THIS CLEARS THE WHOLE TENANT — TENANT === SOLUTION, so " +
|
|
5973
|
+
"every skill and connector in the tenant's Core registry goes, including any ORPHAN that no longer belongs " +
|
|
5974
|
+
"to a solution. Recovery reaches only as far as GitHub: anything never pushed is unrecoverable.",
|
|
5975
|
+
recovery: "ateam_github_pull(solution_id, ref:'main') — restores ONLY what `main` holds",
|
|
5898
5976
|
};
|
|
5899
5977
|
}
|
|
5900
5978
|
if (confirm_solution_id !== solution_id) {
|
|
5901
5979
|
return {
|
|
5902
5980
|
ok: false,
|
|
5903
|
-
error: `⚠️ REFUSED: confirm_solution_id
|
|
5981
|
+
error: `⚠️ REFUSED: force:true requires confirm_solution_id to exactly equal solution_id.`,
|
|
5904
5982
|
expected: solution_id,
|
|
5905
5983
|
received: confirm_solution_id,
|
|
5906
5984
|
};
|
|
5907
5985
|
}
|
|
5908
|
-
return del(`/deploy/solutions/${solution_id}`, sid);
|
|
5986
|
+
return del(`/deploy/solutions/${solution_id}?force=true`, sid);
|
|
5909
5987
|
},
|
|
5910
5988
|
|
|
5911
5989
|
ateam_delete_skill: async ({ solution_id, skill_id, confirm }, sid) => {
|